ctamixer.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  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. #include "ctamixer.h"
  15. #include "cthardware.h"
  16. #include <linux/slab.h>
  17. #define AMIXER_RESOURCE_NUM 256
  18. #define SUM_RESOURCE_NUM 256
  19. #define AMIXER_Y_IMMEDIATE 1
  20. #define BLANK_SLOT 4094
  21. static void amixer_master(struct rsc *rsc)
  22. {
  23. rsc->conj = 0;
  24. rsc->idx = container_of(rsc, struct amixer, rsc)->idx[0];
  25. }
  26. static void amixer_next_conj(struct rsc *rsc)
  27. {
  28. rsc->conj++;
  29. }
  30. static int amixer_index(const struct rsc *rsc)
  31. {
  32. return container_of(rsc, struct amixer, rsc)->idx[rsc->conj];
  33. }
  34. static int amixer_output_slot(const struct rsc *rsc)
  35. {
  36. return (amixer_index(rsc) << 4) + 0x4;
  37. }
  38. static const struct rsc_ops amixer_basic_rsc_ops = {
  39. .master = amixer_master,
  40. .next_conj = amixer_next_conj,
  41. .index = amixer_index,
  42. .output_slot = amixer_output_slot,
  43. };
  44. static int amixer_set_input(struct amixer *amixer, struct rsc *rsc)
  45. {
  46. struct hw *hw;
  47. hw = amixer->rsc.hw;
  48. hw->amixer_set_mode(amixer->rsc.ctrl_blk, AMIXER_Y_IMMEDIATE);
  49. amixer->input = rsc;
  50. if (!rsc)
  51. hw->amixer_set_x(amixer->rsc.ctrl_blk, BLANK_SLOT);
  52. else
  53. hw->amixer_set_x(amixer->rsc.ctrl_blk,
  54. rsc->ops->output_slot(rsc));
  55. return 0;
  56. }
  57. /* y is a 14-bit immediate constant */
  58. static int amixer_set_y(struct amixer *amixer, unsigned int y)
  59. {
  60. struct hw *hw;
  61. hw = amixer->rsc.hw;
  62. hw->amixer_set_y(amixer->rsc.ctrl_blk, y);
  63. return 0;
  64. }
  65. static int amixer_set_invalid_squash(struct amixer *amixer, unsigned int iv)
  66. {
  67. struct hw *hw;
  68. hw = amixer->rsc.hw;
  69. hw->amixer_set_iv(amixer->rsc.ctrl_blk, iv);
  70. return 0;
  71. }
  72. static int amixer_set_sum(struct amixer *amixer, struct sum *sum)
  73. {
  74. struct hw *hw;
  75. hw = amixer->rsc.hw;
  76. amixer->sum = sum;
  77. if (!sum) {
  78. hw->amixer_set_se(amixer->rsc.ctrl_blk, 0);
  79. } else {
  80. hw->amixer_set_se(amixer->rsc.ctrl_blk, 1);
  81. hw->amixer_set_sadr(amixer->rsc.ctrl_blk,
  82. sum->rsc.ops->index(&sum->rsc));
  83. }
  84. return 0;
  85. }
  86. static int amixer_commit_write(struct amixer *amixer)
  87. {
  88. struct hw *hw;
  89. unsigned int index;
  90. int i;
  91. struct rsc *input;
  92. struct sum *sum;
  93. hw = amixer->rsc.hw;
  94. input = amixer->input;
  95. sum = amixer->sum;
  96. /* Program master and conjugate resources */
  97. amixer->rsc.ops->master(&amixer->rsc);
  98. if (input)
  99. input->ops->master(input);
  100. if (sum)
  101. sum->rsc.ops->master(&sum->rsc);
  102. for (i = 0; i < amixer->rsc.msr; i++) {
  103. hw->amixer_set_dirty_all(amixer->rsc.ctrl_blk);
  104. if (input) {
  105. hw->amixer_set_x(amixer->rsc.ctrl_blk,
  106. input->ops->output_slot(input));
  107. input->ops->next_conj(input);
  108. }
  109. if (sum) {
  110. hw->amixer_set_sadr(amixer->rsc.ctrl_blk,
  111. sum->rsc.ops->index(&sum->rsc));
  112. sum->rsc.ops->next_conj(&sum->rsc);
  113. }
  114. index = amixer->rsc.ops->output_slot(&amixer->rsc);
  115. hw->amixer_commit_write(hw, index, amixer->rsc.ctrl_blk);
  116. amixer->rsc.ops->next_conj(&amixer->rsc);
  117. }
  118. amixer->rsc.ops->master(&amixer->rsc);
  119. if (input)
  120. input->ops->master(input);
  121. if (sum)
  122. sum->rsc.ops->master(&sum->rsc);
  123. return 0;
  124. }
  125. static int amixer_commit_raw_write(struct amixer *amixer)
  126. {
  127. struct hw *hw;
  128. unsigned int index;
  129. hw = amixer->rsc.hw;
  130. index = amixer->rsc.ops->output_slot(&amixer->rsc);
  131. hw->amixer_commit_write(hw, index, amixer->rsc.ctrl_blk);
  132. return 0;
  133. }
  134. static int amixer_get_y(struct amixer *amixer)
  135. {
  136. struct hw *hw;
  137. hw = amixer->rsc.hw;
  138. return hw->amixer_get_y(amixer->rsc.ctrl_blk);
  139. }
  140. static int amixer_setup(struct amixer *amixer, struct rsc *input,
  141. unsigned int scale, struct sum *sum)
  142. {
  143. amixer_set_input(amixer, input);
  144. amixer_set_y(amixer, scale);
  145. amixer_set_sum(amixer, sum);
  146. amixer_commit_write(amixer);
  147. return 0;
  148. }
  149. static const struct amixer_rsc_ops amixer_ops = {
  150. .set_input = amixer_set_input,
  151. .set_invalid_squash = amixer_set_invalid_squash,
  152. .set_scale = amixer_set_y,
  153. .set_sum = amixer_set_sum,
  154. .commit_write = amixer_commit_write,
  155. .commit_raw_write = amixer_commit_raw_write,
  156. .setup = amixer_setup,
  157. .get_scale = amixer_get_y,
  158. };
  159. static int amixer_rsc_init(struct amixer *amixer,
  160. const struct amixer_desc *desc,
  161. struct amixer_mgr *mgr)
  162. {
  163. int err;
  164. err = rsc_init(&amixer->rsc, amixer->idx[0],
  165. AMIXER, desc->msr, mgr->mgr.hw);
  166. if (err)
  167. return err;
  168. /* Set amixer specific operations */
  169. amixer->rsc.ops = &amixer_basic_rsc_ops;
  170. amixer->ops = &amixer_ops;
  171. amixer->input = NULL;
  172. amixer->sum = NULL;
  173. amixer_setup(amixer, NULL, 0, NULL);
  174. return 0;
  175. }
  176. static int amixer_rsc_uninit(struct amixer *amixer)
  177. {
  178. amixer_setup(amixer, NULL, 0, NULL);
  179. rsc_uninit(&amixer->rsc);
  180. amixer->ops = NULL;
  181. amixer->input = NULL;
  182. amixer->sum = NULL;
  183. return 0;
  184. }
  185. static int get_amixer_rsc(struct amixer_mgr *mgr,
  186. const struct amixer_desc *desc,
  187. struct amixer **ramixer)
  188. {
  189. int err, i;
  190. unsigned int idx;
  191. struct amixer *amixer;
  192. unsigned long flags;
  193. *ramixer = NULL;
  194. /* Allocate mem for amixer resource */
  195. amixer = kzalloc(sizeof(*amixer), GFP_KERNEL);
  196. if (!amixer)
  197. return -ENOMEM;
  198. /* Check whether there are sufficient
  199. * amixer resources to meet request. */
  200. err = 0;
  201. spin_lock_irqsave(&mgr->mgr_lock, flags);
  202. for (i = 0; i < desc->msr; i++) {
  203. err = mgr_get_resource(&mgr->mgr, 1, &idx);
  204. if (err)
  205. break;
  206. amixer->idx[i] = idx;
  207. }
  208. spin_unlock_irqrestore(&mgr->mgr_lock, flags);
  209. if (err) {
  210. dev_err(mgr->card->dev,
  211. "Can't meet AMIXER resource request!\n");
  212. goto error;
  213. }
  214. err = amixer_rsc_init(amixer, desc, mgr);
  215. if (err)
  216. goto error;
  217. *ramixer = amixer;
  218. return 0;
  219. error:
  220. spin_lock_irqsave(&mgr->mgr_lock, flags);
  221. for (i--; i >= 0; i--)
  222. mgr_put_resource(&mgr->mgr, 1, amixer->idx[i]);
  223. spin_unlock_irqrestore(&mgr->mgr_lock, flags);
  224. kfree(amixer);
  225. return err;
  226. }
  227. static int put_amixer_rsc(struct amixer_mgr *mgr, struct amixer *amixer)
  228. {
  229. unsigned long flags;
  230. int i;
  231. spin_lock_irqsave(&mgr->mgr_lock, flags);
  232. for (i = 0; i < amixer->rsc.msr; i++)
  233. mgr_put_resource(&mgr->mgr, 1, amixer->idx[i]);
  234. spin_unlock_irqrestore(&mgr->mgr_lock, flags);
  235. amixer_rsc_uninit(amixer);
  236. kfree(amixer);
  237. return 0;
  238. }
  239. int amixer_mgr_create(struct hw *hw, struct amixer_mgr **ramixer_mgr)
  240. {
  241. int err;
  242. struct amixer_mgr *amixer_mgr;
  243. *ramixer_mgr = NULL;
  244. amixer_mgr = kzalloc(sizeof(*amixer_mgr), GFP_KERNEL);
  245. if (!amixer_mgr)
  246. return -ENOMEM;
  247. err = rsc_mgr_init(&amixer_mgr->mgr, AMIXER, AMIXER_RESOURCE_NUM, hw);
  248. if (err)
  249. goto error;
  250. spin_lock_init(&amixer_mgr->mgr_lock);
  251. amixer_mgr->get_amixer = get_amixer_rsc;
  252. amixer_mgr->put_amixer = put_amixer_rsc;
  253. amixer_mgr->card = hw->card;
  254. *ramixer_mgr = amixer_mgr;
  255. return 0;
  256. error:
  257. kfree(amixer_mgr);
  258. return err;
  259. }
  260. int amixer_mgr_destroy(struct amixer_mgr *amixer_mgr)
  261. {
  262. rsc_mgr_uninit(&amixer_mgr->mgr);
  263. kfree(amixer_mgr);
  264. return 0;
  265. }
  266. /* SUM resource management */
  267. static void sum_master(struct rsc *rsc)
  268. {
  269. rsc->conj = 0;
  270. rsc->idx = container_of(rsc, struct sum, rsc)->idx[0];
  271. }
  272. static void sum_next_conj(struct rsc *rsc)
  273. {
  274. rsc->conj++;
  275. }
  276. static int sum_index(const struct rsc *rsc)
  277. {
  278. return container_of(rsc, struct sum, rsc)->idx[rsc->conj];
  279. }
  280. static int sum_output_slot(const struct rsc *rsc)
  281. {
  282. return (sum_index(rsc) << 4) + 0xc;
  283. }
  284. static const struct rsc_ops sum_basic_rsc_ops = {
  285. .master = sum_master,
  286. .next_conj = sum_next_conj,
  287. .index = sum_index,
  288. .output_slot = sum_output_slot,
  289. };
  290. static int sum_rsc_init(struct sum *sum,
  291. const struct sum_desc *desc,
  292. struct sum_mgr *mgr)
  293. {
  294. int err;
  295. err = rsc_init(&sum->rsc, sum->idx[0], SUM, desc->msr, mgr->mgr.hw);
  296. if (err)
  297. return err;
  298. sum->rsc.ops = &sum_basic_rsc_ops;
  299. return 0;
  300. }
  301. static int sum_rsc_uninit(struct sum *sum)
  302. {
  303. rsc_uninit(&sum->rsc);
  304. return 0;
  305. }
  306. static int get_sum_rsc(struct sum_mgr *mgr,
  307. const struct sum_desc *desc,
  308. struct sum **rsum)
  309. {
  310. int err, i;
  311. unsigned int idx;
  312. struct sum *sum;
  313. unsigned long flags;
  314. *rsum = NULL;
  315. /* Allocate mem for sum resource */
  316. sum = kzalloc(sizeof(*sum), GFP_KERNEL);
  317. if (!sum)
  318. return -ENOMEM;
  319. /* Check whether there are sufficient sum resources to meet request. */
  320. err = 0;
  321. spin_lock_irqsave(&mgr->mgr_lock, flags);
  322. for (i = 0; i < desc->msr; i++) {
  323. err = mgr_get_resource(&mgr->mgr, 1, &idx);
  324. if (err)
  325. break;
  326. sum->idx[i] = idx;
  327. }
  328. spin_unlock_irqrestore(&mgr->mgr_lock, flags);
  329. if (err) {
  330. dev_err(mgr->card->dev,
  331. "Can't meet SUM resource request!\n");
  332. goto error;
  333. }
  334. err = sum_rsc_init(sum, desc, mgr);
  335. if (err)
  336. goto error;
  337. *rsum = sum;
  338. return 0;
  339. error:
  340. spin_lock_irqsave(&mgr->mgr_lock, flags);
  341. for (i--; i >= 0; i--)
  342. mgr_put_resource(&mgr->mgr, 1, sum->idx[i]);
  343. spin_unlock_irqrestore(&mgr->mgr_lock, flags);
  344. kfree(sum);
  345. return err;
  346. }
  347. static int put_sum_rsc(struct sum_mgr *mgr, struct sum *sum)
  348. {
  349. unsigned long flags;
  350. int i;
  351. spin_lock_irqsave(&mgr->mgr_lock, flags);
  352. for (i = 0; i < sum->rsc.msr; i++)
  353. mgr_put_resource(&mgr->mgr, 1, sum->idx[i]);
  354. spin_unlock_irqrestore(&mgr->mgr_lock, flags);
  355. sum_rsc_uninit(sum);
  356. kfree(sum);
  357. return 0;
  358. }
  359. int sum_mgr_create(struct hw *hw, struct sum_mgr **rsum_mgr)
  360. {
  361. int err;
  362. struct sum_mgr *sum_mgr;
  363. *rsum_mgr = NULL;
  364. sum_mgr = kzalloc(sizeof(*sum_mgr), GFP_KERNEL);
  365. if (!sum_mgr)
  366. return -ENOMEM;
  367. err = rsc_mgr_init(&sum_mgr->mgr, SUM, SUM_RESOURCE_NUM, hw);
  368. if (err)
  369. goto error;
  370. spin_lock_init(&sum_mgr->mgr_lock);
  371. sum_mgr->get_sum = get_sum_rsc;
  372. sum_mgr->put_sum = put_sum_rsc;
  373. sum_mgr->card = hw->card;
  374. *rsum_mgr = sum_mgr;
  375. return 0;
  376. error:
  377. kfree(sum_mgr);
  378. return err;
  379. }
  380. int sum_mgr_destroy(struct sum_mgr *sum_mgr)
  381. {
  382. rsc_mgr_uninit(&sum_mgr->mgr);
  383. kfree(sum_mgr);
  384. return 0;
  385. }