ctresource.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  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 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 rsc_init(struct rsc *rsc, u32 idx, enum RSCTYP type, u32 msr, void *hw)
  114. {
  115. int err = 0;
  116. rsc->idx = idx;
  117. rsc->conj = idx;
  118. rsc->type = type;
  119. rsc->msr = msr;
  120. rsc->hw = hw;
  121. rsc->ops = &rsc_generic_ops;
  122. if (!hw) {
  123. rsc->ctrl_blk = NULL;
  124. return 0;
  125. }
  126. switch (type) {
  127. case SRC:
  128. err = ((struct hw *)hw)->src_rsc_get_ctrl_blk(&rsc->ctrl_blk);
  129. break;
  130. case AMIXER:
  131. err = ((struct hw *)hw)->
  132. amixer_rsc_get_ctrl_blk(&rsc->ctrl_blk);
  133. break;
  134. case SRCIMP:
  135. case SUM:
  136. case DAIO:
  137. break;
  138. default:
  139. printk(KERN_ERR
  140. "ctxfi: Invalid resource type value %d!\n", type);
  141. return -EINVAL;
  142. }
  143. if (err) {
  144. printk(KERN_ERR
  145. "ctxfi: 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. ((struct hw *)rsc->hw)->
  156. src_rsc_put_ctrl_blk(rsc->ctrl_blk);
  157. break;
  158. case AMIXER:
  159. ((struct hw *)rsc->hw)->
  160. amixer_rsc_put_ctrl_blk(rsc->ctrl_blk);
  161. break;
  162. case SUM:
  163. case DAIO:
  164. break;
  165. default:
  166. printk(KERN_ERR "ctxfi: "
  167. "Invalid resource type value %d!\n", rsc->type);
  168. break;
  169. }
  170. rsc->hw = rsc->ctrl_blk = NULL;
  171. }
  172. rsc->idx = rsc->conj = 0;
  173. rsc->type = NUM_RSCTYP;
  174. rsc->msr = 0;
  175. return 0;
  176. }
  177. int rsc_mgr_init(struct rsc_mgr *mgr, enum RSCTYP type,
  178. unsigned int amount, void *hw_obj)
  179. {
  180. int err = 0;
  181. struct hw *hw = hw_obj;
  182. mgr->type = NUM_RSCTYP;
  183. mgr->rscs = kzalloc(((amount + 8 - 1) / 8), GFP_KERNEL);
  184. if (!mgr->rscs)
  185. return -ENOMEM;
  186. switch (type) {
  187. case SRC:
  188. err = hw->src_mgr_get_ctrl_blk(&mgr->ctrl_blk);
  189. break;
  190. case SRCIMP:
  191. err = hw->srcimp_mgr_get_ctrl_blk(&mgr->ctrl_blk);
  192. break;
  193. case AMIXER:
  194. err = hw->amixer_mgr_get_ctrl_blk(&mgr->ctrl_blk);
  195. break;
  196. case DAIO:
  197. err = hw->daio_mgr_get_ctrl_blk(hw, &mgr->ctrl_blk);
  198. break;
  199. case SUM:
  200. break;
  201. default:
  202. printk(KERN_ERR
  203. "ctxfi: Invalid resource type value %d!\n", type);
  204. err = -EINVAL;
  205. goto error;
  206. }
  207. if (err) {
  208. printk(KERN_ERR
  209. "ctxfi: Failed to get manager control block!\n");
  210. goto error;
  211. }
  212. mgr->type = type;
  213. mgr->avail = mgr->amount = amount;
  214. mgr->hw = hw;
  215. return 0;
  216. error:
  217. kfree(mgr->rscs);
  218. return err;
  219. }
  220. int rsc_mgr_uninit(struct rsc_mgr *mgr)
  221. {
  222. if (NULL != mgr->rscs) {
  223. kfree(mgr->rscs);
  224. mgr->rscs = NULL;
  225. }
  226. if ((NULL != mgr->hw) && (NULL != mgr->ctrl_blk)) {
  227. switch (mgr->type) {
  228. case SRC:
  229. ((struct hw *)mgr->hw)->
  230. src_mgr_put_ctrl_blk(mgr->ctrl_blk);
  231. break;
  232. case SRCIMP:
  233. ((struct hw *)mgr->hw)->
  234. srcimp_mgr_put_ctrl_blk(mgr->ctrl_blk);
  235. break;
  236. case AMIXER:
  237. ((struct hw *)mgr->hw)->
  238. amixer_mgr_put_ctrl_blk(mgr->ctrl_blk);
  239. break;
  240. case DAIO:
  241. ((struct hw *)mgr->hw)->
  242. daio_mgr_put_ctrl_blk(mgr->ctrl_blk);
  243. break;
  244. case SUM:
  245. break;
  246. default:
  247. printk(KERN_ERR "ctxfi: "
  248. "Invalid resource type value %d!\n", mgr->type);
  249. break;
  250. }
  251. mgr->hw = mgr->ctrl_blk = NULL;
  252. }
  253. mgr->type = NUM_RSCTYP;
  254. mgr->avail = mgr->amount = 0;
  255. return 0;
  256. }