2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
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.
11 * This file contains the implementation of the Audio Mixer
12 * resource management object.
20 #include "cthardware.h"
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
)
33 return rsc
->idx
= container_of(rsc
, struct amixer
, rsc
)->idx
[0];
36 static int amixer_next_conj(struct rsc
*rsc
)
39 return container_of(rsc
, struct amixer
, rsc
)->idx
[rsc
->conj
];
42 static int amixer_index(const struct rsc
*rsc
)
44 return container_of(rsc
, struct amixer
, rsc
)->idx
[rsc
->conj
];
47 static int amixer_output_slot(const struct rsc
*rsc
)
49 return (amixer_index(rsc
) << 4) + 0x4;
52 static const 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
)
64 hw
->amixer_set_mode(amixer
->rsc
.ctrl_blk
, AMIXER_Y_IMMEDIATE
);
67 hw
->amixer_set_x(amixer
->rsc
.ctrl_blk
, BLANK_SLOT
);
69 hw
->amixer_set_x(amixer
->rsc
.ctrl_blk
,
70 rsc
->ops
->output_slot(rsc
));
75 /* y is a 14-bit immediate constant */
76 static int amixer_set_y(struct amixer
*amixer
, unsigned int y
)
81 hw
->amixer_set_y(amixer
->rsc
.ctrl_blk
, y
);
86 static int amixer_set_invalid_squash(struct amixer
*amixer
, unsigned int iv
)
91 hw
->amixer_set_iv(amixer
->rsc
.ctrl_blk
, iv
);
96 static int amixer_set_sum(struct amixer
*amixer
, struct sum
*sum
)
103 hw
->amixer_set_se(amixer
->rsc
.ctrl_blk
, 0);
105 hw
->amixer_set_se(amixer
->rsc
.ctrl_blk
, 1);
106 hw
->amixer_set_sadr(amixer
->rsc
.ctrl_blk
,
107 sum
->rsc
.ops
->index(&sum
->rsc
));
113 static int amixer_commit_write(struct amixer
*amixer
)
122 input
= amixer
->input
;
125 /* Program master and conjugate resources */
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
++) {
134 hw
->amixer_set_dirty_all(amixer
->rsc
.ctrl_blk
);
136 hw
->amixer_set_x(amixer
->rsc
.ctrl_blk
,
137 input
->ops
->output_slot(input
));
138 input
->ops
->next_conj(input
);
141 hw
->amixer_set_sadr(amixer
->rsc
.ctrl_blk
,
142 sum
->rsc
.ops
->index(&sum
->rsc
));
143 sum
->rsc
.ops
->next_conj(&sum
->rsc
);
145 index
= amixer
->rsc
.ops
->output_slot(&amixer
->rsc
);
146 hw
->amixer_commit_write(hw
, index
, amixer
->rsc
.ctrl_blk
);
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
);
166 hw
->amixer_commit_write(hw
, index
, amixer
->rsc
.ctrl_blk
);
171 static int amixer_get_y(struct amixer
*amixer
)
176 return hw
->amixer_get_y(amixer
->rsc
.ctrl_blk
);
179 static int amixer_setup(struct amixer
*amixer
, struct rsc
*input
,
180 unsigned int scale
, struct sum
*sum
)
182 amixer_set_input(amixer
, input
);
183 amixer_set_y(amixer
, scale
);
184 amixer_set_sum(amixer
, sum
);
185 amixer_commit_write(amixer
);
189 static const struct amixer_rsc_ops amixer_ops
= {
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
,
201 const struct amixer_desc
*desc
,
202 struct amixer_mgr
*mgr
)
206 err
= rsc_init(&amixer
->rsc
, amixer
->idx
[0],
207 AMIXER
, desc
->msr
, mgr
->mgr
.hw
);
211 /* Set amixer specific operations */
212 amixer
->rsc
.ops
= &amixer_basic_rsc_ops
;
213 amixer
->ops
= &amixer_ops
;
214 amixer
->input
= NULL
;
217 amixer_setup(amixer
, NULL
, 0, NULL
);
222 static int amixer_rsc_uninit(struct amixer
*amixer
)
224 amixer_setup(amixer
, NULL
, 0, NULL
);
225 rsc_uninit(&amixer
->rsc
);
227 amixer
->input
= NULL
;
232 static int get_amixer_rsc(struct amixer_mgr
*mgr
,
233 const struct amixer_desc
*desc
,
234 struct amixer
**ramixer
)
238 struct amixer
*amixer
;
243 /* Allocate mem for amixer resource */
244 amixer
= kzalloc(sizeof(*amixer
), GFP_KERNEL
);
248 /* Check whether there are sufficient
249 * amixer resources to meet request. */
251 spin_lock_irqsave(&mgr
->mgr_lock
, flags
);
252 for (i
= 0; i
< desc
->msr
; i
++) {
253 err
= mgr_get_resource(&mgr
->mgr
, 1, &idx
);
257 amixer
->idx
[i
] = idx
;
259 spin_unlock_irqrestore(&mgr
->mgr_lock
, flags
);
261 dev_err(mgr
->card
->dev
,
262 "Can't meet AMIXER resource request!\n");
266 err
= amixer_rsc_init(amixer
, desc
, mgr
);
275 spin_lock_irqsave(&mgr
->mgr_lock
, flags
);
276 for (i
--; i
>= 0; i
--)
277 mgr_put_resource(&mgr
->mgr
, 1, amixer
->idx
[i
]);
279 spin_unlock_irqrestore(&mgr
->mgr_lock
, flags
);
284 static int put_amixer_rsc(struct amixer_mgr
*mgr
, struct amixer
*amixer
)
289 spin_lock_irqsave(&mgr
->mgr_lock
, flags
);
290 for (i
= 0; i
< amixer
->rsc
.msr
; i
++)
291 mgr_put_resource(&mgr
->mgr
, 1, amixer
->idx
[i
]);
293 spin_unlock_irqrestore(&mgr
->mgr_lock
, flags
);
294 amixer_rsc_uninit(amixer
);
300 int amixer_mgr_create(struct hw
*hw
, struct amixer_mgr
**ramixer_mgr
)
303 struct amixer_mgr
*amixer_mgr
;
306 amixer_mgr
= kzalloc(sizeof(*amixer_mgr
), GFP_KERNEL
);
310 err
= rsc_mgr_init(&amixer_mgr
->mgr
, AMIXER
, AMIXER_RESOURCE_NUM
, hw
);
314 spin_lock_init(&amixer_mgr
->mgr_lock
);
316 amixer_mgr
->get_amixer
= get_amixer_rsc
;
317 amixer_mgr
->put_amixer
= put_amixer_rsc
;
318 amixer_mgr
->card
= hw
->card
;
320 *ramixer_mgr
= amixer_mgr
;
329 int amixer_mgr_destroy(struct amixer_mgr
*amixer_mgr
)
331 rsc_mgr_uninit(&amixer_mgr
->mgr
);
336 /* SUM resource management */
338 static int sum_master(struct rsc
*rsc
)
341 return rsc
->idx
= container_of(rsc
, struct sum
, rsc
)->idx
[0];
344 static int sum_next_conj(struct rsc
*rsc
)
347 return container_of(rsc
, struct sum
, rsc
)->idx
[rsc
->conj
];
350 static int sum_index(const struct rsc
*rsc
)
352 return container_of(rsc
, struct sum
, rsc
)->idx
[rsc
->conj
];
355 static int sum_output_slot(const struct rsc
*rsc
)
357 return (sum_index(rsc
) << 4) + 0xc;
360 static const struct rsc_ops sum_basic_rsc_ops
= {
361 .master
= sum_master
,
362 .next_conj
= sum_next_conj
,
364 .output_slot
= sum_output_slot
,
367 static int sum_rsc_init(struct sum
*sum
,
368 const struct sum_desc
*desc
,
373 err
= rsc_init(&sum
->rsc
, sum
->idx
[0], SUM
, desc
->msr
, mgr
->mgr
.hw
);
377 sum
->rsc
.ops
= &sum_basic_rsc_ops
;
382 static int sum_rsc_uninit(struct sum
*sum
)
384 rsc_uninit(&sum
->rsc
);
388 static int get_sum_rsc(struct sum_mgr
*mgr
,
389 const struct sum_desc
*desc
,
399 /* Allocate mem for sum resource */
400 sum
= kzalloc(sizeof(*sum
), GFP_KERNEL
);
404 /* Check whether there are sufficient sum resources to meet request. */
406 spin_lock_irqsave(&mgr
->mgr_lock
, flags
);
407 for (i
= 0; i
< desc
->msr
; i
++) {
408 err
= mgr_get_resource(&mgr
->mgr
, 1, &idx
);
414 spin_unlock_irqrestore(&mgr
->mgr_lock
, flags
);
416 dev_err(mgr
->card
->dev
,
417 "Can't meet SUM resource request!\n");
421 err
= sum_rsc_init(sum
, desc
, mgr
);
430 spin_lock_irqsave(&mgr
->mgr_lock
, flags
);
431 for (i
--; i
>= 0; i
--)
432 mgr_put_resource(&mgr
->mgr
, 1, sum
->idx
[i
]);
434 spin_unlock_irqrestore(&mgr
->mgr_lock
, flags
);
439 static int put_sum_rsc(struct sum_mgr
*mgr
, struct sum
*sum
)
444 spin_lock_irqsave(&mgr
->mgr_lock
, flags
);
445 for (i
= 0; i
< sum
->rsc
.msr
; i
++)
446 mgr_put_resource(&mgr
->mgr
, 1, sum
->idx
[i
]);
448 spin_unlock_irqrestore(&mgr
->mgr_lock
, flags
);
455 int sum_mgr_create(struct hw
*hw
, struct sum_mgr
**rsum_mgr
)
458 struct sum_mgr
*sum_mgr
;
461 sum_mgr
= kzalloc(sizeof(*sum_mgr
), GFP_KERNEL
);
465 err
= rsc_mgr_init(&sum_mgr
->mgr
, SUM
, SUM_RESOURCE_NUM
, hw
);
469 spin_lock_init(&sum_mgr
->mgr_lock
);
471 sum_mgr
->get_sum
= get_sum_rsc
;
472 sum_mgr
->put_sum
= put_sum_rsc
;
473 sum_mgr
->card
= hw
->card
;
484 int sum_mgr_destroy(struct sum_mgr
*sum_mgr
)
486 rsc_mgr_uninit(&sum_mgr
->mgr
);