This source file includes following definitions.
- lola_init_pin
- lola_init_pins
- lola_free_mixer
- lola_init_mixer_widget
- lola_mixer_set_src_gain
- lola_mixer_set_src_gains
- lola_mixer_set_mapping_gain
- lola_mixer_set_dest_gains
- lola_setup_all_analog_gains
- lola_save_mixer
- lola_restore_mixer
- set_analog_volume
- lola_set_src_config
- init_mixer_values
- lola_analog_vol_info
- lola_analog_vol_get
- lola_analog_vol_put
- lola_analog_vol_tlv
- create_analog_mixer
- lola_input_src_info
- lola_input_src_get
- lola_input_src_put
- create_input_src_mixer
- lola_src_gain_info
- lola_src_gain_get
- lola_src_gain_put
- create_src_gain_mixer
- lola_dest_gain_info
- lola_dest_gain_get
- lola_dest_gain_put
- create_dest_gain_mixer
- lola_create_mixer
1
2
3
4
5
6
7
8 #include <linux/kernel.h>
9 #include <linux/init.h>
10 #include <linux/vmalloc.h>
11 #include <linux/io.h>
12 #include <sound/core.h>
13 #include <sound/control.h>
14 #include <sound/pcm.h>
15 #include <sound/tlv.h>
16 #include "lola.h"
17
18 static int lola_init_pin(struct lola *chip, struct lola_pin *pin,
19 int dir, int nid)
20 {
21 unsigned int val;
22 int err;
23
24 pin->nid = nid;
25 err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val);
26 if (err < 0) {
27 dev_err(chip->card->dev, "Can't read wcaps for 0x%x\n", nid);
28 return err;
29 }
30 val &= 0x00f00fff;
31 if (val == 0x00400200)
32 pin->is_analog = false;
33 else if (val == 0x0040000a && dir == CAPT)
34 pin->is_analog = true;
35 else if (val == 0x0040000c && dir == PLAY)
36 pin->is_analog = true;
37 else {
38 dev_err(chip->card->dev, "Invalid wcaps 0x%x for 0x%x\n", val, nid);
39 return -EINVAL;
40 }
41
42
43
44 if (!pin->is_analog)
45 return 0;
46
47 if (dir == PLAY)
48 err = lola_read_param(chip, nid, LOLA_PAR_AMP_OUT_CAP, &val);
49 else
50 err = lola_read_param(chip, nid, LOLA_PAR_AMP_IN_CAP, &val);
51 if (err < 0) {
52 dev_err(chip->card->dev, "Can't read AMP-caps for 0x%x\n", nid);
53 return err;
54 }
55
56 pin->amp_mute = LOLA_AMP_MUTE_CAPABLE(val);
57 pin->amp_step_size = LOLA_AMP_STEP_SIZE(val);
58 pin->amp_num_steps = LOLA_AMP_NUM_STEPS(val);
59 if (pin->amp_num_steps) {
60
61 pin->amp_num_steps++;
62 pin->amp_step_size++;
63 }
64 pin->amp_offset = LOLA_AMP_OFFSET(val);
65
66 err = lola_codec_read(chip, nid, LOLA_VERB_GET_MAX_LEVEL, 0, 0, &val,
67 NULL);
68 if (err < 0) {
69 dev_err(chip->card->dev, "Can't get MAX_LEVEL 0x%x\n", nid);
70 return err;
71 }
72 pin->max_level = val & 0x3ff;
73
74 pin->config_default_reg = 0;
75 pin->fixed_gain_list_len = 0;
76 pin->cur_gain_step = 0;
77
78 return 0;
79 }
80
81 int lola_init_pins(struct lola *chip, int dir, int *nidp)
82 {
83 int i, err, nid;
84 nid = *nidp;
85 for (i = 0; i < chip->pin[dir].num_pins; i++, nid++) {
86 err = lola_init_pin(chip, &chip->pin[dir].pins[i], dir, nid);
87 if (err < 0)
88 return err;
89 if (chip->pin[dir].pins[i].is_analog)
90 chip->pin[dir].num_analog_pins++;
91 }
92 *nidp = nid;
93 return 0;
94 }
95
96 void lola_free_mixer(struct lola *chip)
97 {
98 vfree(chip->mixer.array_saved);
99 }
100
101 int lola_init_mixer_widget(struct lola *chip, int nid)
102 {
103 unsigned int val;
104 int err;
105
106 err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val);
107 if (err < 0) {
108 dev_err(chip->card->dev, "Can't read wcaps for 0x%x\n", nid);
109 return err;
110 }
111
112 if ((val & 0xfff00000) != 0x02f00000) {
113 dev_dbg(chip->card->dev, "No valid mixer widget\n");
114 return 0;
115 }
116
117 chip->mixer.nid = nid;
118 chip->mixer.caps = val;
119 chip->mixer.array = (struct lola_mixer_array __iomem *)
120 (chip->bar[BAR1].remap_addr + LOLA_BAR1_SOURCE_GAIN_ENABLE);
121
122
123 chip->mixer.array_saved = vmalloc(sizeof(struct lola_mixer_array));
124
125
126 chip->mixer.src_stream_outs = chip->pcm[PLAY].num_streams;
127 chip->mixer.src_phys_ins = chip->pin[CAPT].num_pins;
128
129
130 chip->mixer.dest_stream_ins = chip->pcm[CAPT].num_streams;
131 chip->mixer.dest_phys_outs = chip->pin[PLAY].num_pins;
132
133
134
135
136 chip->mixer.src_stream_out_ofs = chip->mixer.src_phys_ins +
137 LOLA_MIXER_SRC_INPUT_PLAY_SEPARATION(val);
138 chip->mixer.dest_phys_out_ofs = chip->mixer.dest_stream_ins +
139 LOLA_MIXER_DEST_REC_OUTPUT_SEPARATION(val);
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189 if (chip->mixer.src_stream_out_ofs > MAX_AUDIO_INOUT_COUNT ||
190 chip->mixer.dest_phys_out_ofs > MAX_STREAM_IN_COUNT) {
191 dev_err(chip->card->dev, "Invalid mixer widget size\n");
192 return -EINVAL;
193 }
194
195 chip->mixer.src_mask = ((1U << chip->mixer.src_phys_ins) - 1) |
196 (((1U << chip->mixer.src_stream_outs) - 1)
197 << chip->mixer.src_stream_out_ofs);
198 chip->mixer.dest_mask = ((1U << chip->mixer.dest_stream_ins) - 1) |
199 (((1U << chip->mixer.dest_phys_outs) - 1)
200 << chip->mixer.dest_phys_out_ofs);
201
202 dev_dbg(chip->card->dev, "Mixer src_mask=%x, dest_mask=%x\n",
203 chip->mixer.src_mask, chip->mixer.dest_mask);
204
205 return 0;
206 }
207
208 static int lola_mixer_set_src_gain(struct lola *chip, unsigned int id,
209 unsigned short gain, bool on)
210 {
211 unsigned int oldval, val;
212
213 if (!(chip->mixer.src_mask & (1 << id)))
214 return -EINVAL;
215 oldval = val = readl(&chip->mixer.array->src_gain_enable);
216 if (on)
217 val |= (1 << id);
218 else
219 val &= ~(1 << id);
220
221 if ((val == oldval) &&
222 (gain == readw(&chip->mixer.array->src_gain[id])))
223 return 0;
224
225 dev_dbg(chip->card->dev,
226 "lola_mixer_set_src_gain (id=%d, gain=%d) enable=%x\n",
227 id, gain, val);
228 writew(gain, &chip->mixer.array->src_gain[id]);
229 writel(val, &chip->mixer.array->src_gain_enable);
230 lola_codec_flush(chip);
231
232 return lola_codec_write(chip, chip->mixer.nid,
233 LOLA_VERB_SET_SOURCE_GAIN, id, 0);
234 }
235
236 #if 0
237 static int lola_mixer_set_src_gains(struct lola *chip, unsigned int mask,
238 unsigned short *gains)
239 {
240 int i;
241
242 if ((chip->mixer.src_mask & mask) != mask)
243 return -EINVAL;
244 for (i = 0; i < LOLA_MIXER_DIM; i++) {
245 if (mask & (1 << i)) {
246 writew(*gains, &chip->mixer.array->src_gain[i]);
247 gains++;
248 }
249 }
250 writel(mask, &chip->mixer.array->src_gain_enable);
251 lola_codec_flush(chip);
252 if (chip->mixer.caps & LOLA_PEAK_METER_CAN_AGC_MASK) {
253
254 return lola_codec_write(chip, chip->mixer.nid,
255 LOLA_VERB_SET_SOURCE_GAIN, 0x80, 0);
256 }
257
258 for (i = 0; i < LOLA_MIXER_DIM; i++) {
259 if (mask & (1 << i)) {
260 lola_codec_write(chip, chip->mixer.nid,
261 LOLA_VERB_SET_SOURCE_GAIN, i, 0);
262 }
263 }
264 return 0;
265 }
266 #endif
267
268 static int lola_mixer_set_mapping_gain(struct lola *chip,
269 unsigned int src, unsigned int dest,
270 unsigned short gain, bool on)
271 {
272 unsigned int val;
273
274 if (!(chip->mixer.src_mask & (1 << src)) ||
275 !(chip->mixer.dest_mask & (1 << dest)))
276 return -EINVAL;
277 if (on)
278 writew(gain, &chip->mixer.array->dest_mix_gain[dest][src]);
279 val = readl(&chip->mixer.array->dest_mix_gain_enable[dest]);
280 if (on)
281 val |= (1 << src);
282 else
283 val &= ~(1 << src);
284 writel(val, &chip->mixer.array->dest_mix_gain_enable[dest]);
285 lola_codec_flush(chip);
286 return lola_codec_write(chip, chip->mixer.nid, LOLA_VERB_SET_MIX_GAIN,
287 src, dest);
288 }
289
290 #if 0
291 static int lola_mixer_set_dest_gains(struct lola *chip, unsigned int id,
292 unsigned int mask, unsigned short *gains)
293 {
294 int i;
295
296 if (!(chip->mixer.dest_mask & (1 << id)) ||
297 (chip->mixer.src_mask & mask) != mask)
298 return -EINVAL;
299 for (i = 0; i < LOLA_MIXER_DIM; i++) {
300 if (mask & (1 << i)) {
301 writew(*gains, &chip->mixer.array->dest_mix_gain[id][i]);
302 gains++;
303 }
304 }
305 writel(mask, &chip->mixer.array->dest_mix_gain_enable[id]);
306 lola_codec_flush(chip);
307
308 return lola_codec_write(chip, chip->mixer.nid,
309 LOLA_VERB_SET_DESTINATION_GAIN, id, 0);
310 }
311 #endif
312
313
314
315
316 static int set_analog_volume(struct lola *chip, int dir,
317 unsigned int idx, unsigned int val,
318 bool external_call);
319
320 int lola_setup_all_analog_gains(struct lola *chip, int dir, bool mute)
321 {
322 struct lola_pin *pin;
323 int idx, max_idx;
324
325 pin = chip->pin[dir].pins;
326 max_idx = chip->pin[dir].num_pins;
327 for (idx = 0; idx < max_idx; idx++) {
328 if (pin[idx].is_analog) {
329 unsigned int val = mute ? 0 : pin[idx].cur_gain_step;
330
331 set_analog_volume(chip, dir, idx, val, false);
332 }
333 }
334 return lola_codec_flush(chip);
335 }
336
337 void lola_save_mixer(struct lola *chip)
338 {
339
340 if (chip->mixer.array_saved) {
341
342 memcpy_fromio(chip->mixer.array_saved, chip->mixer.array,
343 sizeof(*chip->mixer.array));
344 }
345 lola_setup_all_analog_gains(chip, PLAY, true);
346 }
347
348 void lola_restore_mixer(struct lola *chip)
349 {
350 int i;
351
352
353 if (chip->mixer.array_saved) {
354
355 memcpy_toio(chip->mixer.array, chip->mixer.array_saved,
356 sizeof(*chip->mixer.array));
357
358
359
360 for (i = 0; i < chip->mixer.src_phys_ins; i++)
361 lola_codec_write(chip, chip->mixer.nid,
362 LOLA_VERB_SET_SOURCE_GAIN,
363 i, 0);
364 for (i = 0; i < chip->mixer.src_stream_outs; i++)
365 lola_codec_write(chip, chip->mixer.nid,
366 LOLA_VERB_SET_SOURCE_GAIN,
367 chip->mixer.src_stream_out_ofs + i, 0);
368 for (i = 0; i < chip->mixer.dest_stream_ins; i++)
369 lola_codec_write(chip, chip->mixer.nid,
370 LOLA_VERB_SET_DESTINATION_GAIN,
371 i, 0);
372 for (i = 0; i < chip->mixer.dest_phys_outs; i++)
373 lola_codec_write(chip, chip->mixer.nid,
374 LOLA_VERB_SET_DESTINATION_GAIN,
375 chip->mixer.dest_phys_out_ofs + i, 0);
376 lola_codec_flush(chip);
377 }
378 }
379
380
381
382
383 static int set_analog_volume(struct lola *chip, int dir,
384 unsigned int idx, unsigned int val,
385 bool external_call)
386 {
387 struct lola_pin *pin;
388 int err;
389
390 if (idx >= chip->pin[dir].num_pins)
391 return -EINVAL;
392 pin = &chip->pin[dir].pins[idx];
393 if (!pin->is_analog || pin->amp_num_steps <= val)
394 return -EINVAL;
395 if (external_call && pin->cur_gain_step == val)
396 return 0;
397 if (external_call)
398 lola_codec_flush(chip);
399 dev_dbg(chip->card->dev,
400 "set_analog_volume (dir=%d idx=%d, volume=%d)\n",
401 dir, idx, val);
402 err = lola_codec_write(chip, pin->nid,
403 LOLA_VERB_SET_AMP_GAIN_MUTE, val, 0);
404 if (err < 0)
405 return err;
406 if (external_call)
407 pin->cur_gain_step = val;
408 return 0;
409 }
410
411 int lola_set_src_config(struct lola *chip, unsigned int src_mask, bool update)
412 {
413 int ret = 0;
414 int success = 0;
415 int n, err;
416
417
418 if ((chip->input_src_caps_mask & src_mask) != src_mask)
419 return -EINVAL;
420
421 for (n = 0; n < chip->pin[CAPT].num_pins; n += 2) {
422 unsigned int mask = 3U << n;
423 unsigned int new_src, src_state;
424 if (!(chip->input_src_caps_mask & mask))
425 continue;
426
427 new_src = (src_mask & mask) != 0;
428 if (update) {
429 src_state = (chip->input_src_mask & mask) != 0;
430 if (src_state == new_src)
431 continue;
432 }
433 err = lola_codec_write(chip, chip->pcm[CAPT].streams[n].nid,
434 LOLA_VERB_SET_SRC, new_src, 0);
435 if (!err)
436 success++;
437 else
438 ret = err;
439 }
440 if (success)
441 ret = lola_codec_flush(chip);
442 if (!ret)
443 chip->input_src_mask = src_mask;
444 return ret;
445 }
446
447
448
449 static int init_mixer_values(struct lola *chip)
450 {
451 int i;
452
453
454 lola_set_src_config(chip, (1 << chip->pin[CAPT].num_pins) - 1, false);
455
456
457 memset_io(chip->mixer.array, 0, sizeof(*chip->mixer.array));
458
459 for (i = 0; i < chip->mixer.dest_stream_ins; i++)
460 lola_codec_write(chip, chip->mixer.nid,
461 LOLA_VERB_SET_DESTINATION_GAIN,
462 i, 0);
463
464 for (i = 0; i < chip->mixer.dest_phys_outs; i++)
465 lola_codec_write(chip, chip->mixer.nid,
466 LOLA_VERB_SET_DESTINATION_GAIN,
467 chip->mixer.dest_phys_out_ofs + i, 0);
468
469
470 for (i = 0; i < chip->mixer.src_phys_ins; i++)
471 lola_mixer_set_src_gain(chip, i, 336, true);
472
473
474 for (i = 0; i < chip->mixer.src_stream_outs; i++)
475 lola_mixer_set_src_gain(chip,
476 i + chip->mixer.src_stream_out_ofs,
477 336, true);
478
479 for (i = 0; i < chip->mixer.dest_stream_ins; i++) {
480 int src = i % chip->mixer.src_phys_ins;
481 lola_mixer_set_mapping_gain(chip, src, i, 336, true);
482 }
483
484
485
486
487 for (i = 0; i < chip->mixer.src_stream_outs; i++) {
488 int src = chip->mixer.src_stream_out_ofs + i;
489 int dst = chip->mixer.dest_phys_out_ofs +
490 i % chip->mixer.dest_phys_outs;
491 lola_mixer_set_mapping_gain(chip, src, dst, 336, true);
492 }
493 return 0;
494 }
495
496
497
498
499 static int lola_analog_vol_info(struct snd_kcontrol *kcontrol,
500 struct snd_ctl_elem_info *uinfo)
501 {
502 struct lola *chip = snd_kcontrol_chip(kcontrol);
503 int dir = kcontrol->private_value;
504
505 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
506 uinfo->count = chip->pin[dir].num_pins;
507 uinfo->value.integer.min = 0;
508 uinfo->value.integer.max = chip->pin[dir].pins[0].amp_num_steps;
509 return 0;
510 }
511
512 static int lola_analog_vol_get(struct snd_kcontrol *kcontrol,
513 struct snd_ctl_elem_value *ucontrol)
514 {
515 struct lola *chip = snd_kcontrol_chip(kcontrol);
516 int dir = kcontrol->private_value;
517 int i;
518
519 for (i = 0; i < chip->pin[dir].num_pins; i++)
520 ucontrol->value.integer.value[i] =
521 chip->pin[dir].pins[i].cur_gain_step;
522 return 0;
523 }
524
525 static int lola_analog_vol_put(struct snd_kcontrol *kcontrol,
526 struct snd_ctl_elem_value *ucontrol)
527 {
528 struct lola *chip = snd_kcontrol_chip(kcontrol);
529 int dir = kcontrol->private_value;
530 int i, err;
531
532 for (i = 0; i < chip->pin[dir].num_pins; i++) {
533 err = set_analog_volume(chip, dir, i,
534 ucontrol->value.integer.value[i],
535 true);
536 if (err < 0)
537 return err;
538 }
539 return 0;
540 }
541
542 static int lola_analog_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
543 unsigned int size, unsigned int __user *tlv)
544 {
545 struct lola *chip = snd_kcontrol_chip(kcontrol);
546 int dir = kcontrol->private_value;
547 unsigned int val1, val2;
548 struct lola_pin *pin;
549
550 if (size < 4 * sizeof(unsigned int))
551 return -ENOMEM;
552 pin = &chip->pin[dir].pins[0];
553
554 val2 = pin->amp_step_size * 25;
555 val1 = -1 * (int)pin->amp_offset * (int)val2;
556 #ifdef TLV_DB_SCALE_MUTE
557 val2 |= TLV_DB_SCALE_MUTE;
558 #endif
559 if (put_user(SNDRV_CTL_TLVT_DB_SCALE, tlv))
560 return -EFAULT;
561 if (put_user(2 * sizeof(unsigned int), tlv + 1))
562 return -EFAULT;
563 if (put_user(val1, tlv + 2))
564 return -EFAULT;
565 if (put_user(val2, tlv + 3))
566 return -EFAULT;
567 return 0;
568 }
569
570 static struct snd_kcontrol_new lola_analog_mixer = {
571 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
572 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
573 SNDRV_CTL_ELEM_ACCESS_TLV_READ |
574 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK),
575 .info = lola_analog_vol_info,
576 .get = lola_analog_vol_get,
577 .put = lola_analog_vol_put,
578 .tlv.c = lola_analog_vol_tlv,
579 };
580
581 static int create_analog_mixer(struct lola *chip, int dir, char *name)
582 {
583 if (!chip->pin[dir].num_pins)
584 return 0;
585
586 if (chip->pin[dir].num_pins != chip->pin[dir].num_analog_pins)
587 return 0;
588 lola_analog_mixer.name = name;
589 lola_analog_mixer.private_value = dir;
590 return snd_ctl_add(chip->card,
591 snd_ctl_new1(&lola_analog_mixer, chip));
592 }
593
594
595
596
597 static int lola_input_src_info(struct snd_kcontrol *kcontrol,
598 struct snd_ctl_elem_info *uinfo)
599 {
600 struct lola *chip = snd_kcontrol_chip(kcontrol);
601
602 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
603 uinfo->count = chip->pin[CAPT].num_pins;
604 uinfo->value.integer.min = 0;
605 uinfo->value.integer.max = 1;
606 return 0;
607 }
608
609 static int lola_input_src_get(struct snd_kcontrol *kcontrol,
610 struct snd_ctl_elem_value *ucontrol)
611 {
612 struct lola *chip = snd_kcontrol_chip(kcontrol);
613 int i;
614
615 for (i = 0; i < chip->pin[CAPT].num_pins; i++)
616 ucontrol->value.integer.value[i] =
617 !!(chip->input_src_mask & (1 << i));
618 return 0;
619 }
620
621 static int lola_input_src_put(struct snd_kcontrol *kcontrol,
622 struct snd_ctl_elem_value *ucontrol)
623 {
624 struct lola *chip = snd_kcontrol_chip(kcontrol);
625 int i;
626 unsigned int mask;
627
628 mask = 0;
629 for (i = 0; i < chip->pin[CAPT].num_pins; i++)
630 if (ucontrol->value.integer.value[i])
631 mask |= 1 << i;
632 return lola_set_src_config(chip, mask, true);
633 }
634
635 static const struct snd_kcontrol_new lola_input_src_mixer = {
636 .name = "Digital SRC Capture Switch",
637 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
638 .info = lola_input_src_info,
639 .get = lola_input_src_get,
640 .put = lola_input_src_put,
641 };
642
643
644
645
646
647 static int create_input_src_mixer(struct lola *chip)
648 {
649 if (!chip->input_src_caps_mask)
650 return 0;
651
652 return snd_ctl_add(chip->card,
653 snd_ctl_new1(&lola_input_src_mixer, chip));
654 }
655
656
657
658
659 static int lola_src_gain_info(struct snd_kcontrol *kcontrol,
660 struct snd_ctl_elem_info *uinfo)
661 {
662 unsigned int count = (kcontrol->private_value >> 8) & 0xff;
663
664 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
665 uinfo->count = count;
666 uinfo->value.integer.min = 0;
667 uinfo->value.integer.max = 409;
668 return 0;
669 }
670
671 static int lola_src_gain_get(struct snd_kcontrol *kcontrol,
672 struct snd_ctl_elem_value *ucontrol)
673 {
674 struct lola *chip = snd_kcontrol_chip(kcontrol);
675 unsigned int ofs = kcontrol->private_value & 0xff;
676 unsigned int count = (kcontrol->private_value >> 8) & 0xff;
677 unsigned int mask, i;
678
679 mask = readl(&chip->mixer.array->src_gain_enable);
680 for (i = 0; i < count; i++) {
681 unsigned int idx = ofs + i;
682 unsigned short val;
683 if (!(chip->mixer.src_mask & (1 << idx)))
684 return -EINVAL;
685 if (mask & (1 << idx))
686 val = readw(&chip->mixer.array->src_gain[idx]) + 1;
687 else
688 val = 0;
689 ucontrol->value.integer.value[i] = val;
690 }
691 return 0;
692 }
693
694 static int lola_src_gain_put(struct snd_kcontrol *kcontrol,
695 struct snd_ctl_elem_value *ucontrol)
696 {
697 struct lola *chip = snd_kcontrol_chip(kcontrol);
698 unsigned int ofs = kcontrol->private_value & 0xff;
699 unsigned int count = (kcontrol->private_value >> 8) & 0xff;
700 int i, err;
701
702 for (i = 0; i < count; i++) {
703 unsigned int idx = ofs + i;
704 unsigned short val = ucontrol->value.integer.value[i];
705 if (val)
706 val--;
707 err = lola_mixer_set_src_gain(chip, idx, val, !!val);
708 if (err < 0)
709 return err;
710 }
711 return 0;
712 }
713
714
715 static const DECLARE_TLV_DB_SCALE(lola_src_gain_tlv, -8425, 25, 1);
716
717 static struct snd_kcontrol_new lola_src_gain_mixer = {
718 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
719 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
720 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
721 .info = lola_src_gain_info,
722 .get = lola_src_gain_get,
723 .put = lola_src_gain_put,
724 .tlv.p = lola_src_gain_tlv,
725 };
726
727 static int create_src_gain_mixer(struct lola *chip,
728 int num, int ofs, char *name)
729 {
730 lola_src_gain_mixer.name = name;
731 lola_src_gain_mixer.private_value = ofs + (num << 8);
732 return snd_ctl_add(chip->card,
733 snd_ctl_new1(&lola_src_gain_mixer, chip));
734 }
735
736 #if 0
737
738
739
740 static int lola_dest_gain_info(struct snd_kcontrol *kcontrol,
741 struct snd_ctl_elem_info *uinfo)
742 {
743 unsigned int src_num = (kcontrol->private_value >> 8) & 0xff;
744
745 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
746 uinfo->count = src_num;
747 uinfo->value.integer.min = 0;
748 uinfo->value.integer.max = 433;
749 return 0;
750 }
751
752 static int lola_dest_gain_get(struct snd_kcontrol *kcontrol,
753 struct snd_ctl_elem_value *ucontrol)
754 {
755 struct lola *chip = snd_kcontrol_chip(kcontrol);
756 unsigned int src_ofs = kcontrol->private_value & 0xff;
757 unsigned int src_num = (kcontrol->private_value >> 8) & 0xff;
758 unsigned int dst_ofs = (kcontrol->private_value >> 16) & 0xff;
759 unsigned int dst, mask, i;
760
761 dst = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + dst_ofs;
762 mask = readl(&chip->mixer.array->dest_mix_gain_enable[dst]);
763 for (i = 0; i < src_num; i++) {
764 unsigned int src = src_ofs + i;
765 unsigned short val;
766 if (!(chip->mixer.src_mask & (1 << src)))
767 return -EINVAL;
768 if (mask & (1 << dst))
769 val = readw(&chip->mixer.array->dest_mix_gain[dst][src]) + 1;
770 else
771 val = 0;
772 ucontrol->value.integer.value[i] = val;
773 }
774 return 0;
775 }
776
777 static int lola_dest_gain_put(struct snd_kcontrol *kcontrol,
778 struct snd_ctl_elem_value *ucontrol)
779 {
780 struct lola *chip = snd_kcontrol_chip(kcontrol);
781 unsigned int src_ofs = kcontrol->private_value & 0xff;
782 unsigned int src_num = (kcontrol->private_value >> 8) & 0xff;
783 unsigned int dst_ofs = (kcontrol->private_value >> 16) & 0xff;
784 unsigned int dst, mask;
785 unsigned short gains[MAX_STREAM_COUNT];
786 int i, num;
787
788 mask = 0;
789 num = 0;
790 for (i = 0; i < src_num; i++) {
791 unsigned short val = ucontrol->value.integer.value[i];
792 if (val) {
793 gains[num++] = val - 1;
794 mask |= 1 << i;
795 }
796 }
797 mask <<= src_ofs;
798 dst = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + dst_ofs;
799 return lola_mixer_set_dest_gains(chip, dst, mask, gains);
800 }
801
802 static const DECLARE_TLV_DB_SCALE(lola_dest_gain_tlv, -8425, 25, 1);
803
804 static struct snd_kcontrol_new lola_dest_gain_mixer = {
805 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
806 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
807 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
808 .info = lola_dest_gain_info,
809 .get = lola_dest_gain_get,
810 .put = lola_dest_gain_put,
811 .tlv.p = lola_dest_gain_tlv,
812 };
813
814 static int create_dest_gain_mixer(struct lola *chip,
815 int src_num, int src_ofs,
816 int num, int ofs, char *name)
817 {
818 lola_dest_gain_mixer.count = num;
819 lola_dest_gain_mixer.name = name;
820 lola_dest_gain_mixer.private_value =
821 src_ofs + (src_num << 8) + (ofs << 16) + (num << 24);
822 return snd_ctl_add(chip->card,
823 snd_ctl_new1(&lola_dest_gain_mixer, chip));
824 }
825 #endif
826
827
828
829 int lola_create_mixer(struct lola *chip)
830 {
831 int err;
832
833 err = create_analog_mixer(chip, PLAY, "Analog Playback Volume");
834 if (err < 0)
835 return err;
836 err = create_analog_mixer(chip, CAPT, "Analog Capture Volume");
837 if (err < 0)
838 return err;
839 err = create_input_src_mixer(chip);
840 if (err < 0)
841 return err;
842 err = create_src_gain_mixer(chip, chip->mixer.src_phys_ins, 0,
843 "Digital Capture Volume");
844 if (err < 0)
845 return err;
846 err = create_src_gain_mixer(chip, chip->mixer.src_stream_outs,
847 chip->mixer.src_stream_out_ofs,
848 "Digital Playback Volume");
849 if (err < 0)
850 return err;
851 #if 0
852
853 err = create_dest_gain_mixer(chip,
854 chip->mixer.src_phys_ins, 0,
855 chip->mixer.dest_stream_ins, 0,
856 "Line Capture Volume");
857 if (err < 0)
858 return err;
859 err = create_dest_gain_mixer(chip,
860 chip->mixer.src_stream_outs,
861 chip->mixer.src_stream_out_ofs,
862 chip->mixer.dest_stream_ins, 0,
863 "Stream-Loopback Capture Volume");
864 if (err < 0)
865 return err;
866 err = create_dest_gain_mixer(chip,
867 chip->mixer.src_phys_ins, 0,
868 chip->mixer.dest_phys_outs,
869 chip->mixer.dest_phys_out_ofs,
870 "Line-Loopback Playback Volume");
871 if (err < 0)
872 return err;
873 err = create_dest_gain_mixer(chip,
874 chip->mixer.src_stream_outs,
875 chip->mixer.src_stream_out_ofs,
876 chip->mixer.dest_phys_outs,
877 chip->mixer.dest_phys_out_ofs,
878 "Stream Playback Volume");
879 if (err < 0)
880 return err;
881 #endif
882 return init_mixer_values(chip);
883 }