21 #include <linux/slab.h>
23 #define AMIXER_RESOURCE_NUM 256
24 #define SUM_RESOURCE_NUM 256
26 #define AMIXER_Y_IMMEDIATE 1
28 #define BLANK_SLOT 4094
30 static int amixer_master(
struct rsc *
rsc)
36 static int amixer_next_conj(
struct rsc *
rsc)
42 static int amixer_index(
const struct rsc *
rsc)
47 static int amixer_output_slot(
const struct rsc *
rsc)
49 return (amixer_index(rsc) << 4) + 0x4;
52 static struct rsc_ops amixer_basic_rsc_ops = {
53 .master = amixer_master,
54 .next_conj = amixer_next_conj,
55 .index = amixer_index,
56 .output_slot = amixer_output_slot,
59 static int amixer_set_input(
struct amixer *
amixer,
struct rsc *rsc)
70 rsc->
ops->output_slot(rsc));
76 static int amixer_set_y(
struct amixer *amixer,
unsigned int y)
86 static int amixer_set_invalid_squash(
struct amixer *amixer,
unsigned int iv)
96 static int amixer_set_sum(
struct amixer *amixer,
struct sum *
sum)
107 sum->
rsc.ops->index(&sum->
rsc));
122 input = amixer->
input;
126 amixer->
rsc.ops->master(&amixer->
rsc);
128 input->
ops->master(input);
131 sum->
rsc.ops->master(&sum->
rsc);
133 for (i = 0; i < amixer->
rsc.msr; i++) {
137 input->
ops->output_slot(input));
138 input->
ops->next_conj(input);
142 sum->
rsc.ops->index(&sum->
rsc));
143 sum->
rsc.ops->next_conj(&sum->
rsc);
145 index = amixer->
rsc.ops->output_slot(&amixer->
rsc);
147 amixer->
rsc.ops->next_conj(&amixer->
rsc);
149 amixer->
rsc.ops->master(&amixer->
rsc);
151 input->
ops->master(input);
154 sum->
rsc.ops->master(&sum->
rsc);
159 static int amixer_commit_raw_write(
struct amixer *amixer)
165 index = amixer->
rsc.ops->output_slot(&amixer->
rsc);
179 static int amixer_setup(
struct amixer *amixer,
struct rsc *input,
180 unsigned int scale,
struct sum *sum)
182 amixer_set_input(amixer, input);
184 amixer_set_sum(amixer, sum);
190 .set_input = amixer_set_input,
191 .set_invalid_squash = amixer_set_invalid_squash,
192 .set_scale = amixer_set_y,
193 .set_sum = amixer_set_sum,
194 .commit_write = amixer_commit_write,
195 .commit_raw_write = amixer_commit_raw_write,
196 .setup = amixer_setup,
197 .get_scale = amixer_get_y,
200 static int amixer_rsc_init(
struct amixer *amixer,
212 amixer->
rsc.ops = &amixer_basic_rsc_ops;
213 amixer->
ops = &amixer_ops;
217 amixer_setup(amixer,
NULL, 0,
NULL);
222 static int amixer_rsc_uninit(
struct amixer *amixer)
224 amixer_setup(amixer,
NULL, 0,
NULL);
232 static int get_amixer_rsc(
struct amixer_mgr *mgr,
234 struct amixer **ramixer)
238 struct amixer *amixer;
244 amixer = kzalloc(
sizeof(*amixer),
GFP_KERNEL);
252 for (i = 0; i < desc->
msr; i++) {
259 spin_unlock_irqrestore(&mgr->
mgr_lock, flags);
265 err = amixer_rsc_init(amixer, desc, mgr);
275 for (i--; i >= 0; i--)
278 spin_unlock_irqrestore(&mgr->
mgr_lock, flags);
283 static int put_amixer_rsc(
struct amixer_mgr *mgr,
struct amixer *amixer)
289 for (i = 0; i < amixer->
rsc.msr; i++)
292 spin_unlock_irqrestore(&mgr->
mgr_lock, flags);
293 amixer_rsc_uninit(amixer);
305 amixer_mgr = kzalloc(
sizeof(*amixer_mgr),
GFP_KERNEL);
318 *ramixer_mgr = amixer_mgr;
336 static int sum_master(
struct rsc *rsc)
342 static int sum_next_conj(
struct rsc *rsc)
348 static int sum_index(
const struct rsc *rsc)
353 static int sum_output_slot(
const struct rsc *rsc)
355 return (sum_index(rsc) << 4) + 0xc;
358 static struct rsc_ops sum_basic_rsc_ops = {
359 .master = sum_master,
360 .next_conj = sum_next_conj,
362 .output_slot = sum_output_slot,
365 static int sum_rsc_init(
struct sum *sum,
375 sum->
rsc.ops = &sum_basic_rsc_ops;
380 static int sum_rsc_uninit(
struct sum *sum)
386 static int get_sum_rsc(
struct sum_mgr *mgr,
405 for (i = 0; i < desc->
msr; i++) {
412 spin_unlock_irqrestore(&mgr->
mgr_lock, flags);
418 err = sum_rsc_init(sum, desc, mgr);
428 for (i--; i >= 0; i--)
431 spin_unlock_irqrestore(&mgr->
mgr_lock, flags);
436 static int put_sum_rsc(
struct sum_mgr *mgr,
struct sum *sum)
442 for (i = 0; i < sum->
rsc.msr; i++)
445 spin_unlock_irqrestore(&mgr->
mgr_lock, flags);
458 sum_mgr = kzalloc(
sizeof(*sum_mgr),
GFP_KERNEL);
468 sum_mgr->
get_sum = get_sum_rsc;
469 sum_mgr->
put_sum = put_sum_rsc;