ctresource.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
  4. *
  5. * @File ctresource.c
  6. *
  7. * @Brief
  8. * This file contains the implementation of some generic helper functions.
  9. *
  10. * @Author Liu Chun
  11. * @Date May 15 2008
  12. */
  13. #include "ctresource.h"
  14. #include "cthardware.h"
  15. #include <linux/err.h>
  16. #include <linux/slab.h>
  17. #define AUDIO_SLOT_BLOCK_NUM 256
  18. /* Resource allocation based on bit-map management mechanism */
  19. static int
  20. get_resource(u8 *rscs, unsigned int amount,
  21. unsigned int multi, unsigned int *ridx)
  22. {
  23. int i, j, k, n;
  24. /* Check whether there are sufficient resources to meet request. */
  25. for (i = 0, n = multi; i < amount; i++) {
  26. j = i / 8;
  27. k = i % 8;
  28. if (rscs[j] & ((u8)1 << k)) {
  29. n = multi;
  30. continue;
  31. }
  32. if (!(--n))
  33. break; /* found sufficient contiguous resources */
  34. }
  35. if (i >= amount) {
  36. /* Can not find sufficient contiguous resources */
  37. return -ENOENT;
  38. }
  39. /* Mark the contiguous bits in resource bit-map as used */
  40. for (n = multi; n > 0; n--) {
  41. j = i / 8;
  42. k = i % 8;
  43. rscs[j] |= ((u8)1 << k);
  44. i--;
  45. }
  46. *ridx = i + 1;
  47. return 0;
  48. }
  49. static int put_resource(u8 *rscs, unsigned int multi, unsigned int idx)
  50. {
  51. unsigned int i, j, k, n;
  52. /* Mark the contiguous bits in resource bit-map as used */
  53. for (n = multi, i = idx; n > 0; n--) {
  54. j = i / 8;
  55. k = i % 8;
  56. rscs[j] &= ~((u8)1 << k);
  57. i++;
  58. }
  59. return 0;
  60. }
  61. int mgr_get_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int *ridx)
  62. {
  63. int err;
  64. if (n > mgr->avail)
  65. return -ENOENT;
  66. err = get_resource(mgr->rscs, mgr->amount, n, ridx);
  67. if (!err)
  68. mgr->avail -= n;
  69. return err;
  70. }
  71. int mgr_put_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int idx)
  72. {
  73. put_resource(mgr->rscs, n, idx);
  74. mgr->avail += n;
  75. return 0;
  76. }
  77. static const unsigned char offset_in_audio_slot_block[NUM_RSCTYP] = {
  78. /* SRC channel is at Audio Ring slot 1 every 16 slots. */
  79. [SRC] = 0x1,
  80. [AMIXER] = 0x4,
  81. [SUM] = 0xc,
  82. };
  83. static int rsc_index(const struct rsc *rsc)
  84. {
  85. return rsc->conj;
  86. }
  87. static int audio_ring_slot(const struct rsc *rsc)
  88. {
  89. return (rsc->conj << 4) + offset_in_audio_slot_block[rsc->type];
  90. }
  91. static void rsc_next_conj(struct rsc *rsc)
  92. {
  93. unsigned int i;
  94. for (i = 0; (i < 8) && (!(rsc->msr & (0x1 << i))); )
  95. i++;
  96. rsc->conj += (AUDIO_SLOT_BLOCK_NUM >> i);
  97. }
  98. static void rsc_master(struct rsc *rsc)
  99. {
  100. rsc->conj = rsc->idx;
  101. }
  102. static const struct rsc_ops rsc_generic_ops = {
  103. .index = rsc_index,
  104. .output_slot = audio_ring_slot,
  105. .master = rsc_master,
  106. .next_conj = rsc_next_conj,
  107. };
  108. int
  109. rsc_init(struct rsc *rsc, u32 idx, enum RSCTYP type, u32 msr, struct hw *hw)
  110. {
  111. int err = 0;
  112. rsc->idx = idx;
  113. rsc->conj = idx;
  114. rsc->type = type;
  115. rsc->msr = msr;
  116. rsc->hw = hw;
  117. rsc->ops = &rsc_generic_ops;
  118. if (!hw) {
  119. rsc->ctrl_blk = NULL;
  120. return 0;
  121. }
  122. switch (type) {
  123. case SRC:
  124. err = hw->src_rsc_get_ctrl_blk(&rsc->ctrl_blk);
  125. break;
  126. case AMIXER:
  127. err = hw->amixer_rsc_get_ctrl_blk(&rsc->ctrl_blk);
  128. break;
  129. case SRCIMP:
  130. case SUM:
  131. case DAIO:
  132. break;
  133. default:
  134. dev_err(((struct hw *)hw)->card->dev,
  135. "Invalid resource type value %d!\n", type);
  136. return -EINVAL;
  137. }
  138. if (err) {
  139. dev_err(((struct hw *)hw)->card->dev,
  140. "Failed to get resource control block!\n");
  141. return err;
  142. }
  143. return 0;
  144. }
  145. int rsc_uninit(struct rsc *rsc)
  146. {
  147. if ((NULL != rsc->hw) && (NULL != rsc->ctrl_blk)) {
  148. switch (rsc->type) {
  149. case SRC:
  150. rsc->hw->src_rsc_put_ctrl_blk(rsc->ctrl_blk);
  151. break;
  152. case AMIXER:
  153. rsc->hw->amixer_rsc_put_ctrl_blk(rsc->ctrl_blk);
  154. break;
  155. case SUM:
  156. case DAIO:
  157. break;
  158. default:
  159. dev_err(((struct hw *)rsc->hw)->card->dev,
  160. "Invalid resource type value %d!\n",
  161. rsc->type);
  162. break;
  163. }
  164. rsc->hw = rsc->ctrl_blk = NULL;
  165. }
  166. rsc->idx = rsc->conj = 0;
  167. rsc->type = NUM_RSCTYP;
  168. rsc->msr = 0;
  169. return 0;
  170. }
  171. int rsc_mgr_init(struct rsc_mgr *mgr, enum RSCTYP type,
  172. unsigned int amount, struct hw *hw)
  173. {
  174. int err = 0;
  175. mgr->type = NUM_RSCTYP;
  176. mgr->rscs = kzalloc(DIV_ROUND_UP(amount, 8), GFP_KERNEL);
  177. if (!mgr->rscs)
  178. return -ENOMEM;
  179. switch (type) {
  180. case SRC:
  181. err = hw->src_mgr_get_ctrl_blk(&mgr->ctrl_blk);
  182. break;
  183. case SRCIMP:
  184. err = hw->srcimp_mgr_get_ctrl_blk(&mgr->ctrl_blk);
  185. break;
  186. case AMIXER:
  187. err = hw->amixer_mgr_get_ctrl_blk(&mgr->ctrl_blk);
  188. break;
  189. case DAIO:
  190. err = hw->daio_mgr_get_ctrl_blk(hw, &mgr->ctrl_blk);
  191. break;
  192. case SUM:
  193. break;
  194. default:
  195. dev_err(hw->card->dev,
  196. "Invalid resource type value %d!\n", type);
  197. err = -EINVAL;
  198. goto error;
  199. }
  200. if (err) {
  201. dev_err(hw->card->dev,
  202. "Failed to get manager control block!\n");
  203. goto error;
  204. }
  205. mgr->type = type;
  206. mgr->avail = mgr->amount = amount;
  207. mgr->hw = hw;
  208. return 0;
  209. error:
  210. kfree(mgr->rscs);
  211. return err;
  212. }
  213. int rsc_mgr_uninit(struct rsc_mgr *mgr)
  214. {
  215. kfree(mgr->rscs);
  216. mgr->rscs = NULL;
  217. if ((NULL != mgr->hw) && (NULL != mgr->ctrl_blk)) {
  218. switch (mgr->type) {
  219. case SRC:
  220. mgr->hw->src_mgr_put_ctrl_blk(mgr->ctrl_blk);
  221. break;
  222. case SRCIMP:
  223. mgr->hw->srcimp_mgr_put_ctrl_blk(mgr->ctrl_blk);
  224. break;
  225. case AMIXER:
  226. mgr->hw->amixer_mgr_put_ctrl_blk(mgr->ctrl_blk);
  227. break;
  228. case DAIO:
  229. mgr->hw->daio_mgr_put_ctrl_blk(mgr->ctrl_blk);
  230. break;
  231. case SUM:
  232. break;
  233. default:
  234. dev_err(((struct hw *)mgr->hw)->card->dev,
  235. "Invalid resource type value %d!\n",
  236. mgr->type);
  237. break;
  238. }
  239. mgr->hw = mgr->ctrl_blk = NULL;
  240. }
  241. mgr->type = NUM_RSCTYP;
  242. mgr->avail = mgr->amount = 0;
  243. return 0;
  244. }