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