Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ctresource.c
Go to the documentation of this file.
1 
18 #include "ctresource.h"
19 #include "cthardware.h"
20 #include <linux/err.h>
21 #include <linux/slab.h>
22 
23 #define AUDIO_SLOT_BLOCK_NUM 256
24 
25 /* Resource allocation based on bit-map management mechanism */
26 static int
27 get_resource(u8 *rscs, unsigned int amount,
28  unsigned int multi, unsigned int *ridx)
29 {
30  int i, j, k, n;
31 
32  /* Check whether there are sufficient resources to meet request. */
33  for (i = 0, n = multi; i < amount; i++) {
34  j = i / 8;
35  k = i % 8;
36  if (rscs[j] & ((u8)1 << k)) {
37  n = multi;
38  continue;
39  }
40  if (!(--n))
41  break; /* found sufficient contiguous resources */
42  }
43 
44  if (i >= amount) {
45  /* Can not find sufficient contiguous resources */
46  return -ENOENT;
47  }
48 
49  /* Mark the contiguous bits in resource bit-map as used */
50  for (n = multi; n > 0; n--) {
51  j = i / 8;
52  k = i % 8;
53  rscs[j] |= ((u8)1 << k);
54  i--;
55  }
56 
57  *ridx = i + 1;
58 
59  return 0;
60 }
61 
62 static int put_resource(u8 *rscs, unsigned int multi, unsigned int idx)
63 {
64  unsigned int i, j, k, n;
65 
66  /* Mark the contiguous bits in resource bit-map as used */
67  for (n = multi, i = idx; n > 0; n--) {
68  j = i / 8;
69  k = i % 8;
70  rscs[j] &= ~((u8)1 << k);
71  i++;
72  }
73 
74  return 0;
75 }
76 
77 int mgr_get_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int *ridx)
78 {
79  int err;
80 
81  if (n > mgr->avail)
82  return -ENOENT;
83 
84  err = get_resource(mgr->rscs, mgr->amount, n, ridx);
85  if (!err)
86  mgr->avail -= n;
87 
88  return err;
89 }
90 
91 int mgr_put_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int idx)
92 {
93  put_resource(mgr->rscs, n, idx);
94  mgr->avail += n;
95 
96  return 0;
97 }
98 
99 static unsigned char offset_in_audio_slot_block[NUM_RSCTYP] = {
100  /* SRC channel is at Audio Ring slot 1 every 16 slots. */
101  [SRC] = 0x1,
102  [AMIXER] = 0x4,
103  [SUM] = 0xc,
104 };
105 
106 static int rsc_index(const struct rsc *rsc)
107 {
108  return rsc->conj;
109 }
110 
111 static int audio_ring_slot(const struct rsc *rsc)
112 {
113  return (rsc->conj << 4) + offset_in_audio_slot_block[rsc->type];
114 }
115 
116 static int rsc_next_conj(struct rsc *rsc)
117 {
118  unsigned int i;
119  for (i = 0; (i < 8) && (!(rsc->msr & (0x1 << i))); )
120  i++;
121  rsc->conj += (AUDIO_SLOT_BLOCK_NUM >> i);
122  return rsc->conj;
123 }
124 
125 static int rsc_master(struct rsc *rsc)
126 {
127  return rsc->conj = rsc->idx;
128 }
129 
130 static struct rsc_ops rsc_generic_ops = {
131  .index = rsc_index,
132  .output_slot = audio_ring_slot,
133  .master = rsc_master,
134  .next_conj = rsc_next_conj,
135 };
136 
137 int rsc_init(struct rsc *rsc, u32 idx, enum RSCTYP type, u32 msr, void *hw)
138 {
139  int err = 0;
140 
141  rsc->idx = idx;
142  rsc->conj = idx;
143  rsc->type = type;
144  rsc->msr = msr;
145  rsc->hw = hw;
146  rsc->ops = &rsc_generic_ops;
147  if (!hw) {
148  rsc->ctrl_blk = NULL;
149  return 0;
150  }
151 
152  switch (type) {
153  case SRC:
154  err = ((struct hw *)hw)->src_rsc_get_ctrl_blk(&rsc->ctrl_blk);
155  break;
156  case AMIXER:
157  err = ((struct hw *)hw)->
159  break;
160  case SRCIMP:
161  case SUM:
162  case DAIO:
163  break;
164  default:
166  "ctxfi: Invalid resource type value %d!\n", type);
167  return -EINVAL;
168  }
169 
170  if (err) {
172  "ctxfi: Failed to get resource control block!\n");
173  return err;
174  }
175 
176  return 0;
177 }
178 
179 int rsc_uninit(struct rsc *rsc)
180 {
181  if ((NULL != rsc->hw) && (NULL != rsc->ctrl_blk)) {
182  switch (rsc->type) {
183  case SRC:
184  ((struct hw *)rsc->hw)->
186  break;
187  case AMIXER:
188  ((struct hw *)rsc->hw)->
190  break;
191  case SUM:
192  case DAIO:
193  break;
194  default:
195  printk(KERN_ERR "ctxfi: "
196  "Invalid resource type value %d!\n", rsc->type);
197  break;
198  }
199 
200  rsc->hw = rsc->ctrl_blk = NULL;
201  }
202 
203  rsc->idx = rsc->conj = 0;
204  rsc->type = NUM_RSCTYP;
205  rsc->msr = 0;
206 
207  return 0;
208 }
209 
210 int rsc_mgr_init(struct rsc_mgr *mgr, enum RSCTYP type,
211  unsigned int amount, void *hw_obj)
212 {
213  int err = 0;
214  struct hw *hw = hw_obj;
215 
216  mgr->type = NUM_RSCTYP;
217 
218  mgr->rscs = kzalloc(((amount + 8 - 1) / 8), GFP_KERNEL);
219  if (!mgr->rscs)
220  return -ENOMEM;
221 
222  switch (type) {
223  case SRC:
224  err = hw->src_mgr_get_ctrl_blk(&mgr->ctrl_blk);
225  break;
226  case SRCIMP:
227  err = hw->srcimp_mgr_get_ctrl_blk(&mgr->ctrl_blk);
228  break;
229  case AMIXER:
230  err = hw->amixer_mgr_get_ctrl_blk(&mgr->ctrl_blk);
231  break;
232  case DAIO:
233  err = hw->daio_mgr_get_ctrl_blk(hw, &mgr->ctrl_blk);
234  break;
235  case SUM:
236  break;
237  default:
239  "ctxfi: Invalid resource type value %d!\n", type);
240  err = -EINVAL;
241  goto error;
242  }
243 
244  if (err) {
246  "ctxfi: Failed to get manager control block!\n");
247  goto error;
248  }
249 
250  mgr->type = type;
251  mgr->avail = mgr->amount = amount;
252  mgr->hw = hw;
253 
254  return 0;
255 
256 error:
257  kfree(mgr->rscs);
258  return err;
259 }
260 
261 int rsc_mgr_uninit(struct rsc_mgr *mgr)
262 {
263  if (NULL != mgr->rscs) {
264  kfree(mgr->rscs);
265  mgr->rscs = NULL;
266  }
267 
268  if ((NULL != mgr->hw) && (NULL != mgr->ctrl_blk)) {
269  switch (mgr->type) {
270  case SRC:
271  ((struct hw *)mgr->hw)->
273  break;
274  case SRCIMP:
275  ((struct hw *)mgr->hw)->
277  break;
278  case AMIXER:
279  ((struct hw *)mgr->hw)->
281  break;
282  case DAIO:
283  ((struct hw *)mgr->hw)->
285  break;
286  case SUM:
287  break;
288  default:
289  printk(KERN_ERR "ctxfi: "
290  "Invalid resource type value %d!\n", mgr->type);
291  break;
292  }
293 
294  mgr->hw = mgr->ctrl_blk = NULL;
295  }
296 
297  mgr->type = NUM_RSCTYP;
298  mgr->avail = mgr->amount = 0;
299 
300  return 0;
301 }