ctresource.c 5.5 KB

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