Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.13 486 lines 9.9 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. 4 * 5 * @File ctamixer.c 6 * 7 * @Brief 8 * This file contains the implementation of the Audio Mixer 9 * resource management object. 10 * 11 * @Author Liu Chun 12 * @Date May 21 2008 13 */ 14 15#include "ctamixer.h" 16#include "cthardware.h" 17#include <linux/slab.h> 18 19#define AMIXER_RESOURCE_NUM 256 20#define SUM_RESOURCE_NUM 256 21 22#define AMIXER_Y_IMMEDIATE 1 23 24#define BLANK_SLOT 4094 25 26static int amixer_master(struct rsc *rsc) 27{ 28 rsc->conj = 0; 29 return rsc->idx = container_of(rsc, struct amixer, rsc)->idx[0]; 30} 31 32static int amixer_next_conj(struct rsc *rsc) 33{ 34 rsc->conj++; 35 return container_of(rsc, struct amixer, rsc)->idx[rsc->conj]; 36} 37 38static int amixer_index(const struct rsc *rsc) 39{ 40 return container_of(rsc, struct amixer, rsc)->idx[rsc->conj]; 41} 42 43static int amixer_output_slot(const struct rsc *rsc) 44{ 45 return (amixer_index(rsc) << 4) + 0x4; 46} 47 48static const struct rsc_ops amixer_basic_rsc_ops = { 49 .master = amixer_master, 50 .next_conj = amixer_next_conj, 51 .index = amixer_index, 52 .output_slot = amixer_output_slot, 53}; 54 55static int amixer_set_input(struct amixer *amixer, struct rsc *rsc) 56{ 57 struct hw *hw; 58 59 hw = amixer->rsc.hw; 60 hw->amixer_set_mode(amixer->rsc.ctrl_blk, AMIXER_Y_IMMEDIATE); 61 amixer->input = rsc; 62 if (!rsc) 63 hw->amixer_set_x(amixer->rsc.ctrl_blk, BLANK_SLOT); 64 else 65 hw->amixer_set_x(amixer->rsc.ctrl_blk, 66 rsc->ops->output_slot(rsc)); 67 68 return 0; 69} 70 71/* y is a 14-bit immediate constant */ 72static int amixer_set_y(struct amixer *amixer, unsigned int y) 73{ 74 struct hw *hw; 75 76 hw = amixer->rsc.hw; 77 hw->amixer_set_y(amixer->rsc.ctrl_blk, y); 78 79 return 0; 80} 81 82static int amixer_set_invalid_squash(struct amixer *amixer, unsigned int iv) 83{ 84 struct hw *hw; 85 86 hw = amixer->rsc.hw; 87 hw->amixer_set_iv(amixer->rsc.ctrl_blk, iv); 88 89 return 0; 90} 91 92static int amixer_set_sum(struct amixer *amixer, struct sum *sum) 93{ 94 struct hw *hw; 95 96 hw = amixer->rsc.hw; 97 amixer->sum = sum; 98 if (!sum) { 99 hw->amixer_set_se(amixer->rsc.ctrl_blk, 0); 100 } else { 101 hw->amixer_set_se(amixer->rsc.ctrl_blk, 1); 102 hw->amixer_set_sadr(amixer->rsc.ctrl_blk, 103 sum->rsc.ops->index(&sum->rsc)); 104 } 105 106 return 0; 107} 108 109static int amixer_commit_write(struct amixer *amixer) 110{ 111 struct hw *hw; 112 unsigned int index; 113 int i; 114 struct rsc *input; 115 struct sum *sum; 116 117 hw = amixer->rsc.hw; 118 input = amixer->input; 119 sum = amixer->sum; 120 121 /* Program master and conjugate resources */ 122 amixer->rsc.ops->master(&amixer->rsc); 123 if (input) 124 input->ops->master(input); 125 126 if (sum) 127 sum->rsc.ops->master(&sum->rsc); 128 129 for (i = 0; i < amixer->rsc.msr; i++) { 130 hw->amixer_set_dirty_all(amixer->rsc.ctrl_blk); 131 if (input) { 132 hw->amixer_set_x(amixer->rsc.ctrl_blk, 133 input->ops->output_slot(input)); 134 input->ops->next_conj(input); 135 } 136 if (sum) { 137 hw->amixer_set_sadr(amixer->rsc.ctrl_blk, 138 sum->rsc.ops->index(&sum->rsc)); 139 sum->rsc.ops->next_conj(&sum->rsc); 140 } 141 index = amixer->rsc.ops->output_slot(&amixer->rsc); 142 hw->amixer_commit_write(hw, index, amixer->rsc.ctrl_blk); 143 amixer->rsc.ops->next_conj(&amixer->rsc); 144 } 145 amixer->rsc.ops->master(&amixer->rsc); 146 if (input) 147 input->ops->master(input); 148 149 if (sum) 150 sum->rsc.ops->master(&sum->rsc); 151 152 return 0; 153} 154 155static int amixer_commit_raw_write(struct amixer *amixer) 156{ 157 struct hw *hw; 158 unsigned int index; 159 160 hw = amixer->rsc.hw; 161 index = amixer->rsc.ops->output_slot(&amixer->rsc); 162 hw->amixer_commit_write(hw, index, amixer->rsc.ctrl_blk); 163 164 return 0; 165} 166 167static int amixer_get_y(struct amixer *amixer) 168{ 169 struct hw *hw; 170 171 hw = amixer->rsc.hw; 172 return hw->amixer_get_y(amixer->rsc.ctrl_blk); 173} 174 175static int amixer_setup(struct amixer *amixer, struct rsc *input, 176 unsigned int scale, struct sum *sum) 177{ 178 amixer_set_input(amixer, input); 179 amixer_set_y(amixer, scale); 180 amixer_set_sum(amixer, sum); 181 amixer_commit_write(amixer); 182 return 0; 183} 184 185static const struct amixer_rsc_ops amixer_ops = { 186 .set_input = amixer_set_input, 187 .set_invalid_squash = amixer_set_invalid_squash, 188 .set_scale = amixer_set_y, 189 .set_sum = amixer_set_sum, 190 .commit_write = amixer_commit_write, 191 .commit_raw_write = amixer_commit_raw_write, 192 .setup = amixer_setup, 193 .get_scale = amixer_get_y, 194}; 195 196static int amixer_rsc_init(struct amixer *amixer, 197 const struct amixer_desc *desc, 198 struct amixer_mgr *mgr) 199{ 200 int err; 201 202 err = rsc_init(&amixer->rsc, amixer->idx[0], 203 AMIXER, desc->msr, mgr->mgr.hw); 204 if (err) 205 return err; 206 207 /* Set amixer specific operations */ 208 amixer->rsc.ops = &amixer_basic_rsc_ops; 209 amixer->ops = &amixer_ops; 210 amixer->input = NULL; 211 amixer->sum = NULL; 212 213 amixer_setup(amixer, NULL, 0, NULL); 214 215 return 0; 216} 217 218static int amixer_rsc_uninit(struct amixer *amixer) 219{ 220 amixer_setup(amixer, NULL, 0, NULL); 221 rsc_uninit(&amixer->rsc); 222 amixer->ops = NULL; 223 amixer->input = NULL; 224 amixer->sum = NULL; 225 return 0; 226} 227 228static int get_amixer_rsc(struct amixer_mgr *mgr, 229 const struct amixer_desc *desc, 230 struct amixer **ramixer) 231{ 232 int err, i; 233 unsigned int idx; 234 struct amixer *amixer; 235 unsigned long flags; 236 237 *ramixer = NULL; 238 239 /* Allocate mem for amixer resource */ 240 amixer = kzalloc(sizeof(*amixer), GFP_KERNEL); 241 if (!amixer) 242 return -ENOMEM; 243 244 /* Check whether there are sufficient 245 * amixer resources to meet request. */ 246 err = 0; 247 spin_lock_irqsave(&mgr->mgr_lock, flags); 248 for (i = 0; i < desc->msr; i++) { 249 err = mgr_get_resource(&mgr->mgr, 1, &idx); 250 if (err) 251 break; 252 253 amixer->idx[i] = idx; 254 } 255 spin_unlock_irqrestore(&mgr->mgr_lock, flags); 256 if (err) { 257 dev_err(mgr->card->dev, 258 "Can't meet AMIXER resource request!\n"); 259 goto error; 260 } 261 262 err = amixer_rsc_init(amixer, desc, mgr); 263 if (err) 264 goto error; 265 266 *ramixer = amixer; 267 268 return 0; 269 270error: 271 spin_lock_irqsave(&mgr->mgr_lock, flags); 272 for (i--; i >= 0; i--) 273 mgr_put_resource(&mgr->mgr, 1, amixer->idx[i]); 274 275 spin_unlock_irqrestore(&mgr->mgr_lock, flags); 276 kfree(amixer); 277 return err; 278} 279 280static int put_amixer_rsc(struct amixer_mgr *mgr, struct amixer *amixer) 281{ 282 unsigned long flags; 283 int i; 284 285 spin_lock_irqsave(&mgr->mgr_lock, flags); 286 for (i = 0; i < amixer->rsc.msr; i++) 287 mgr_put_resource(&mgr->mgr, 1, amixer->idx[i]); 288 289 spin_unlock_irqrestore(&mgr->mgr_lock, flags); 290 amixer_rsc_uninit(amixer); 291 kfree(amixer); 292 293 return 0; 294} 295 296int amixer_mgr_create(struct hw *hw, struct amixer_mgr **ramixer_mgr) 297{ 298 int err; 299 struct amixer_mgr *amixer_mgr; 300 301 *ramixer_mgr = NULL; 302 amixer_mgr = kzalloc(sizeof(*amixer_mgr), GFP_KERNEL); 303 if (!amixer_mgr) 304 return -ENOMEM; 305 306 err = rsc_mgr_init(&amixer_mgr->mgr, AMIXER, AMIXER_RESOURCE_NUM, hw); 307 if (err) 308 goto error; 309 310 spin_lock_init(&amixer_mgr->mgr_lock); 311 312 amixer_mgr->get_amixer = get_amixer_rsc; 313 amixer_mgr->put_amixer = put_amixer_rsc; 314 amixer_mgr->card = hw->card; 315 316 *ramixer_mgr = amixer_mgr; 317 318 return 0; 319 320error: 321 kfree(amixer_mgr); 322 return err; 323} 324 325int amixer_mgr_destroy(struct amixer_mgr *amixer_mgr) 326{ 327 rsc_mgr_uninit(&amixer_mgr->mgr); 328 kfree(amixer_mgr); 329 return 0; 330} 331 332/* SUM resource management */ 333 334static int sum_master(struct rsc *rsc) 335{ 336 rsc->conj = 0; 337 return rsc->idx = container_of(rsc, struct sum, rsc)->idx[0]; 338} 339 340static int sum_next_conj(struct rsc *rsc) 341{ 342 rsc->conj++; 343 return container_of(rsc, struct sum, rsc)->idx[rsc->conj]; 344} 345 346static int sum_index(const struct rsc *rsc) 347{ 348 return container_of(rsc, struct sum, rsc)->idx[rsc->conj]; 349} 350 351static int sum_output_slot(const struct rsc *rsc) 352{ 353 return (sum_index(rsc) << 4) + 0xc; 354} 355 356static const struct rsc_ops sum_basic_rsc_ops = { 357 .master = sum_master, 358 .next_conj = sum_next_conj, 359 .index = sum_index, 360 .output_slot = sum_output_slot, 361}; 362 363static int sum_rsc_init(struct sum *sum, 364 const struct sum_desc *desc, 365 struct sum_mgr *mgr) 366{ 367 int err; 368 369 err = rsc_init(&sum->rsc, sum->idx[0], SUM, desc->msr, mgr->mgr.hw); 370 if (err) 371 return err; 372 373 sum->rsc.ops = &sum_basic_rsc_ops; 374 375 return 0; 376} 377 378static int sum_rsc_uninit(struct sum *sum) 379{ 380 rsc_uninit(&sum->rsc); 381 return 0; 382} 383 384static int get_sum_rsc(struct sum_mgr *mgr, 385 const struct sum_desc *desc, 386 struct sum **rsum) 387{ 388 int err, i; 389 unsigned int idx; 390 struct sum *sum; 391 unsigned long flags; 392 393 *rsum = NULL; 394 395 /* Allocate mem for sum resource */ 396 sum = kzalloc(sizeof(*sum), GFP_KERNEL); 397 if (!sum) 398 return -ENOMEM; 399 400 /* Check whether there are sufficient sum resources to meet request. */ 401 err = 0; 402 spin_lock_irqsave(&mgr->mgr_lock, flags); 403 for (i = 0; i < desc->msr; i++) { 404 err = mgr_get_resource(&mgr->mgr, 1, &idx); 405 if (err) 406 break; 407 408 sum->idx[i] = idx; 409 } 410 spin_unlock_irqrestore(&mgr->mgr_lock, flags); 411 if (err) { 412 dev_err(mgr->card->dev, 413 "Can't meet SUM resource request!\n"); 414 goto error; 415 } 416 417 err = sum_rsc_init(sum, desc, mgr); 418 if (err) 419 goto error; 420 421 *rsum = sum; 422 423 return 0; 424 425error: 426 spin_lock_irqsave(&mgr->mgr_lock, flags); 427 for (i--; i >= 0; i--) 428 mgr_put_resource(&mgr->mgr, 1, sum->idx[i]); 429 430 spin_unlock_irqrestore(&mgr->mgr_lock, flags); 431 kfree(sum); 432 return err; 433} 434 435static int put_sum_rsc(struct sum_mgr *mgr, struct sum *sum) 436{ 437 unsigned long flags; 438 int i; 439 440 spin_lock_irqsave(&mgr->mgr_lock, flags); 441 for (i = 0; i < sum->rsc.msr; i++) 442 mgr_put_resource(&mgr->mgr, 1, sum->idx[i]); 443 444 spin_unlock_irqrestore(&mgr->mgr_lock, flags); 445 sum_rsc_uninit(sum); 446 kfree(sum); 447 448 return 0; 449} 450 451int sum_mgr_create(struct hw *hw, struct sum_mgr **rsum_mgr) 452{ 453 int err; 454 struct sum_mgr *sum_mgr; 455 456 *rsum_mgr = NULL; 457 sum_mgr = kzalloc(sizeof(*sum_mgr), GFP_KERNEL); 458 if (!sum_mgr) 459 return -ENOMEM; 460 461 err = rsc_mgr_init(&sum_mgr->mgr, SUM, SUM_RESOURCE_NUM, hw); 462 if (err) 463 goto error; 464 465 spin_lock_init(&sum_mgr->mgr_lock); 466 467 sum_mgr->get_sum = get_sum_rsc; 468 sum_mgr->put_sum = put_sum_rsc; 469 sum_mgr->card = hw->card; 470 471 *rsum_mgr = sum_mgr; 472 473 return 0; 474 475error: 476 kfree(sum_mgr); 477 return err; 478} 479 480int sum_mgr_destroy(struct sum_mgr *sum_mgr) 481{ 482 rsc_mgr_uninit(&sum_mgr->mgr); 483 kfree(sum_mgr); 484 return 0; 485} 486