2 * Support for Digigram Lola PCI-e boards
4 * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc., 59
18 * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 #include <linux/kernel.h>
22 #include <linux/init.h>
23 #include <linux/vmalloc.h>
25 #include <sound/core.h>
26 #include <sound/control.h>
27 #include <sound/pcm.h>
28 #include <sound/tlv.h>
31 static int __devinit
lola_init_pin(struct lola
*chip
, struct lola_pin
*pin
,
38 err
= lola_read_param(chip
, nid
, LOLA_PAR_AUDIO_WIDGET_CAP
, &val
);
40 printk(KERN_ERR SFX
"Can't read wcaps for 0x%x\n", nid
);
43 val
&= 0x00f00fff; /* test TYPE and bits 0..11 */
44 if (val
== 0x00400200) /* Type = 4, Digital = 1 */
45 pin
->is_analog
= false;
46 else if (val
== 0x0040000a && dir
== CAPT
) /* Dig=0, InAmp/ovrd */
47 pin
->is_analog
= true;
48 else if (val
== 0x0040000c && dir
== PLAY
) /* Dig=0, OutAmp/ovrd */
49 pin
->is_analog
= true;
51 printk(KERN_ERR SFX
"Invalid wcaps 0x%x for 0x%x\n", val
, nid
);
55 /* analog parameters only following, so continue in case of Digital pin
61 err
= lola_read_param(chip
, nid
, LOLA_PAR_AMP_OUT_CAP
, &val
);
63 err
= lola_read_param(chip
, nid
, LOLA_PAR_AMP_IN_CAP
, &val
);
65 printk(KERN_ERR SFX
"Can't read AMP-caps for 0x%x\n", nid
);
69 pin
->amp_mute
= LOLA_AMP_MUTE_CAPABLE(val
);
70 pin
->amp_step_size
= LOLA_AMP_STEP_SIZE(val
);
71 pin
->amp_num_steps
= LOLA_AMP_NUM_STEPS(val
);
72 if (pin
->amp_num_steps
) {
73 /* zero as mute state */
77 pin
->amp_offset
= LOLA_AMP_OFFSET(val
);
79 err
= lola_codec_read(chip
, nid
, LOLA_VERB_GET_MAX_LEVEL
, 0, 0, &val
,
82 printk(KERN_ERR SFX
"Can't get MAX_LEVEL 0x%x\n", nid
);
85 pin
->max_level
= val
& 0x3ff; /* 10 bits */
87 pin
->config_default_reg
= 0;
88 pin
->fixed_gain_list_len
= 0;
89 pin
->cur_gain_step
= 0;
94 int __devinit
lola_init_pins(struct lola
*chip
, int dir
, int *nidp
)
98 for (i
= 0; i
< chip
->pin
[dir
].num_pins
; i
++, nid
++) {
99 err
= lola_init_pin(chip
, &chip
->pin
[dir
].pins
[i
], dir
, nid
);
102 if (chip
->pin
[dir
].pins
[i
].is_analog
)
103 chip
->pin
[dir
].num_analog_pins
++;
109 void lola_free_mixer(struct lola
*chip
)
111 if (chip
->mixer
.array_saved
)
112 vfree(chip
->mixer
.array_saved
);
115 int __devinit
lola_init_mixer_widget(struct lola
*chip
, int nid
)
120 err
= lola_read_param(chip
, nid
, LOLA_PAR_AUDIO_WIDGET_CAP
, &val
);
122 printk(KERN_ERR SFX
"Can't read wcaps for 0x%x\n", nid
);
126 if ((val
& 0xfff00000) != 0x02f00000) { /* test SubType and Type */
127 snd_printdd("No valid mixer widget\n");
131 chip
->mixer
.nid
= nid
;
132 chip
->mixer
.caps
= val
;
133 chip
->mixer
.array
= (struct lola_mixer_array __iomem
*)
134 (chip
->bar
[BAR1
].remap_addr
+ LOLA_BAR1_SOURCE_GAIN_ENABLE
);
136 /* reserve memory to copy mixer data for sleep mode transitions */
137 chip
->mixer
.array_saved
= vmalloc(sizeof(struct lola_mixer_array
));
139 /* mixer matrix sources are physical input data and play streams */
140 chip
->mixer
.src_stream_outs
= chip
->pcm
[PLAY
].num_streams
;
141 chip
->mixer
.src_phys_ins
= chip
->pin
[CAPT
].num_pins
;
143 /* mixer matrix destinations are record streams and physical output */
144 chip
->mixer
.dest_stream_ins
= chip
->pcm
[CAPT
].num_streams
;
145 chip
->mixer
.dest_phys_outs
= chip
->pin
[PLAY
].num_pins
;
147 /* mixer matrix can have unused areas between PhysIn and
148 * Play or Record and PhysOut zones
150 chip
->mixer
.src_stream_out_ofs
= chip
->mixer
.src_phys_ins
+
151 LOLA_MIXER_SRC_INPUT_PLAY_SEPARATION(val
);
152 chip
->mixer
.dest_phys_out_ofs
= chip
->mixer
.dest_stream_ins
+
153 LOLA_MIXER_DEST_REC_OUTPUT_SEPATATION(val
);
155 /* example : MixerMatrix of LoLa881
156 * 0-------8------16-------8------16
158 * | INPUT | | INPUT | |
159 * | -> |unused | -> |unused |
160 * | RECORD| | OUTPUT| |
162 * 8--------------------------------
165 * |unused |unused |unused |unused |
168 * 16-------------------------------
170 * | PLAY | | PLAY | |
171 * | -> |unused | -> |unused |
172 * | RECORD| | OUTPUT| |
174 * 8--------------------------------
177 * |unused |unused |unused |unused |
180 * 16-------------------------------
182 if (chip
->mixer
.src_stream_out_ofs
> MAX_AUDIO_INOUT_COUNT
||
183 chip
->mixer
.dest_phys_out_ofs
> MAX_STREAM_IN_COUNT
) {
184 printk(KERN_ERR SFX
"Invalid mixer widget size\n");
188 chip
->mixer
.src_mask
= ((1U << chip
->mixer
.src_phys_ins
) - 1) |
189 (((1U << chip
->mixer
.src_stream_outs
) - 1)
190 << chip
->mixer
.src_stream_out_ofs
);
191 chip
->mixer
.dest_mask
= ((1U << chip
->mixer
.dest_stream_ins
) - 1) |
192 (((1U << chip
->mixer
.dest_phys_outs
) - 1)
193 << chip
->mixer
.dest_phys_out_ofs
);
198 static int lola_mixer_set_src_gain(struct lola
*chip
, unsigned int id
,
199 unsigned short gain
, bool on
)
201 unsigned int oldval
, val
;
203 if (!(chip
->mixer
.src_mask
& (1 << id
)))
205 writew(gain
, &chip
->mixer
.array
->src_gain
[id
]);
206 oldval
= val
= readl(&chip
->mixer
.array
->src_gain_enable
);
211 writel(val
, &chip
->mixer
.array
->src_gain_enable
);
212 lola_codec_flush(chip
);
213 /* inform micro-controller about the new source gain */
214 return lola_codec_write(chip
, chip
->mixer
.nid
,
215 LOLA_VERB_SET_SOURCE_GAIN
, id
, 0);
219 static int lola_mixer_set_src_gains(struct lola
*chip
, unsigned int mask
,
220 unsigned short *gains
)
224 if ((chip
->mixer
.src_mask
& mask
) != mask
)
226 for (i
= 0; i
< LOLA_MIXER_DIM
; i
++) {
227 if (mask
& (1 << i
)) {
228 writew(*gains
, &chip
->mixer
.array
->src_gain
[i
]);
232 writel(mask
, &chip
->mixer
.array
->src_gain_enable
);
233 lola_codec_flush(chip
);
234 if (chip
->mixer
.caps
& LOLA_PEAK_METER_CAN_AGC_MASK
) {
235 /* update for all srcs at once */
236 return lola_codec_write(chip
, chip
->mixer
.nid
,
237 LOLA_VERB_SET_SOURCE_GAIN
, 0x80, 0);
239 /* update manually */
240 for (i
= 0; i
< LOLA_MIXER_DIM
; i
++) {
241 if (mask
& (1 << i
)) {
242 lola_codec_write(chip
, chip
->mixer
.nid
,
243 LOLA_VERB_SET_SOURCE_GAIN
, i
, 0);
248 #endif /* not used */
250 static int lola_mixer_set_mapping_gain(struct lola
*chip
,
251 unsigned int src
, unsigned int dest
,
252 unsigned short gain
, bool on
)
256 if (!(chip
->mixer
.src_mask
& (1 << src
)) ||
257 !(chip
->mixer
.dest_mask
& (1 << dest
)))
260 writew(gain
, &chip
->mixer
.array
->dest_mix_gain
[dest
][src
]);
261 val
= readl(&chip
->mixer
.array
->dest_mix_gain_enable
[dest
]);
266 writel(val
, &chip
->mixer
.array
->dest_mix_gain_enable
[dest
]);
267 lola_codec_flush(chip
);
268 return lola_codec_write(chip
, chip
->mixer
.nid
, LOLA_VERB_SET_MIX_GAIN
,
272 static int lola_mixer_set_dest_gains(struct lola
*chip
, unsigned int id
,
273 unsigned int mask
, unsigned short *gains
)
277 if (!(chip
->mixer
.dest_mask
& (1 << id
)) ||
278 (chip
->mixer
.src_mask
& mask
) != mask
)
280 for (i
= 0; i
< LOLA_MIXER_DIM
; i
++) {
281 if (mask
& (1 << i
)) {
282 writew(*gains
, &chip
->mixer
.array
->dest_mix_gain
[id
][i
]);
286 writel(mask
, &chip
->mixer
.array
->dest_mix_gain_enable
[id
]);
287 lola_codec_flush(chip
);
288 /* update for all dests at once */
289 return lola_codec_write(chip
, chip
->mixer
.nid
,
290 LOLA_VERB_SET_DESTINATION_GAIN
, id
, 0);
296 static int set_analog_volume(struct lola
*chip
, int dir
,
297 unsigned int idx
, unsigned int val
,
300 int lola_setup_all_analog_gains(struct lola
*chip
, int dir
, bool mute
)
302 struct lola_pin
*pin
;
305 pin
= chip
->pin
[dir
].pins
;
306 max_idx
= chip
->pin
[dir
].num_pins
;
307 for (idx
= 0; idx
< max_idx
; idx
++) {
308 if (pin
[idx
].is_analog
) {
309 unsigned int val
= mute
? 0 : pin
[idx
].cur_gain_step
;
310 /* set volume and do not save the value */
311 set_analog_volume(chip
, dir
, idx
, val
, false);
314 return lola_codec_flush(chip
);
317 void lola_save_mixer(struct lola
*chip
)
319 /* mute analog output */
320 if (chip
->mixer
.array_saved
) {
321 /* store contents of mixer array */
322 memcpy_fromio(chip
->mixer
.array_saved
, chip
->mixer
.array
,
323 sizeof(*chip
->mixer
.array
));
325 lola_setup_all_analog_gains(chip
, PLAY
, true); /* output mute */
328 void lola_restore_mixer(struct lola
*chip
)
332 /*lola_reset_setups(chip);*/
333 if (chip
->mixer
.array_saved
) {
334 /* restore contents of mixer array */
335 memcpy_toio(chip
->mixer
.array
, chip
->mixer
.array_saved
,
336 sizeof(*chip
->mixer
.array
));
337 /* inform micro-controller about all restored values
338 * and ignore return values
340 for (i
= 0; i
< chip
->mixer
.src_phys_ins
; i
++)
341 lola_codec_write(chip
, chip
->mixer
.nid
,
342 LOLA_VERB_SET_SOURCE_GAIN
,
344 for (i
= 0; i
< chip
->mixer
.src_stream_outs
; i
++)
345 lola_codec_write(chip
, chip
->mixer
.nid
,
346 LOLA_VERB_SET_SOURCE_GAIN
,
347 chip
->mixer
.src_stream_out_ofs
+ i
, 0);
348 for (i
= 0; i
< chip
->mixer
.dest_stream_ins
; i
++)
349 lola_codec_write(chip
, chip
->mixer
.nid
,
350 LOLA_VERB_SET_DESTINATION_GAIN
,
352 for (i
= 0; i
< chip
->mixer
.dest_phys_outs
; i
++)
353 lola_codec_write(chip
, chip
->mixer
.nid
,
354 LOLA_VERB_SET_DESTINATION_GAIN
,
355 chip
->mixer
.dest_phys_out_ofs
+ i
, 0);
356 lola_codec_flush(chip
);
363 static int set_analog_volume(struct lola
*chip
, int dir
,
364 unsigned int idx
, unsigned int val
,
367 struct lola_pin
*pin
;
370 if (idx
>= chip
->pin
[dir
].num_pins
)
372 pin
= &chip
->pin
[dir
].pins
[idx
];
373 if (!pin
->is_analog
|| pin
->amp_num_steps
<= val
)
375 if (external_call
&& pin
->cur_gain_step
== val
)
378 lola_codec_flush(chip
);
379 err
= lola_codec_write(chip
, pin
->nid
,
380 LOLA_VERB_SET_AMP_GAIN_MUTE
, val
, 0);
384 pin
->cur_gain_step
= val
;
388 int lola_set_src_config(struct lola
*chip
, unsigned int src_mask
, bool update
)
394 /* SRC can be activated and the dwInputSRCMask is valid? */
395 if ((chip
->input_src_caps_mask
& src_mask
) != src_mask
)
397 /* handle all even Inputs - SRC is a stereo setting !!! */
398 for (n
= 0; n
< chip
->pin
[CAPT
].num_pins
; n
+= 2) {
399 unsigned int mask
= 3U << n
; /* handle the stereo case */
400 unsigned int new_src
, src_state
;
401 if (!(chip
->input_src_caps_mask
& mask
))
403 /* if one IO needs SRC, both stereo IO will get SRC */
404 new_src
= (src_mask
& mask
) != 0;
406 src_state
= (chip
->input_src_mask
& mask
) != 0;
407 if (src_state
== new_src
)
408 continue; /* nothing to change for this IO */
410 err
= lola_codec_write(chip
, chip
->pcm
[CAPT
].streams
[n
].nid
,
411 LOLA_VERB_SET_SRC
, new_src
, 0);
418 ret
= lola_codec_flush(chip
);
420 chip
->input_src_mask
= src_mask
;
426 static int init_mixer_values(struct lola
*chip
)
431 lola_set_src_config(chip
, (1 << chip
->pin
[CAPT
].num_pins
) - 1, false);
433 /* clear all matrix */
434 memset_io(chip
->mixer
.array
, 0, sizeof(*chip
->mixer
.array
));
435 /* set src gain to 0dB */
436 for (i
= 0; i
< chip
->mixer
.src_phys_ins
; i
++)
437 lola_mixer_set_src_gain(chip
, i
, 336, true); /* 0dB */
438 for (i
= 0; i
< chip
->mixer
.src_stream_outs
; i
++)
439 lola_mixer_set_src_gain(chip
,
440 i
+ chip
->mixer
.src_stream_out_ofs
,
441 336, true); /* 0dB */
442 /* set 1:1 dest gain */
443 for (i
= 0; i
< chip
->mixer
.dest_stream_ins
; i
++) {
444 int src
= i
% chip
->mixer
.src_phys_ins
;
445 lola_mixer_set_mapping_gain(chip
, src
, i
, 336, true);
447 for (i
= 0; i
< chip
->mixer
.src_stream_outs
; i
++) {
448 int src
= chip
->mixer
.src_stream_out_ofs
+ i
;
449 int dst
= chip
->mixer
.dest_phys_out_ofs
+
450 i
% chip
->mixer
.dest_phys_outs
;
451 lola_mixer_set_mapping_gain(chip
, src
, dst
, 336, true);
457 * analog mixer control element
459 static int lola_analog_vol_info(struct snd_kcontrol
*kcontrol
,
460 struct snd_ctl_elem_info
*uinfo
)
462 struct lola
*chip
= snd_kcontrol_chip(kcontrol
);
463 int dir
= kcontrol
->private_value
;
465 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
466 uinfo
->count
= chip
->pin
[dir
].num_pins
;
467 uinfo
->value
.integer
.min
= 0;
468 uinfo
->value
.integer
.max
= chip
->pin
[dir
].pins
[0].amp_num_steps
;
472 static int lola_analog_vol_get(struct snd_kcontrol
*kcontrol
,
473 struct snd_ctl_elem_value
*ucontrol
)
475 struct lola
*chip
= snd_kcontrol_chip(kcontrol
);
476 int dir
= kcontrol
->private_value
;
479 for (i
= 0; i
< chip
->pin
[dir
].num_pins
; i
++)
480 ucontrol
->value
.integer
.value
[i
] =
481 chip
->pin
[dir
].pins
[i
].cur_gain_step
;
485 static int lola_analog_vol_put(struct snd_kcontrol
*kcontrol
,
486 struct snd_ctl_elem_value
*ucontrol
)
488 struct lola
*chip
= snd_kcontrol_chip(kcontrol
);
489 int dir
= kcontrol
->private_value
;
492 for (i
= 0; i
< chip
->pin
[dir
].num_pins
; i
++) {
493 err
= set_analog_volume(chip
, dir
, i
,
494 ucontrol
->value
.integer
.value
[i
],
502 static int lola_analog_vol_tlv(struct snd_kcontrol
*kcontrol
, int op_flag
,
503 unsigned int size
, unsigned int __user
*tlv
)
505 struct lola
*chip
= snd_kcontrol_chip(kcontrol
);
506 int dir
= kcontrol
->private_value
;
507 unsigned int val1
, val2
;
508 struct lola_pin
*pin
;
510 if (size
< 4 * sizeof(unsigned int))
512 pin
= &chip
->pin
[dir
].pins
[0];
514 val2
= pin
->amp_step_size
* 25;
515 val1
= -1 * (int)pin
->amp_offset
* (int)val2
;
516 #ifdef TLV_DB_SCALE_MUTE
517 val2
|= TLV_DB_SCALE_MUTE
;
519 if (put_user(SNDRV_CTL_TLVT_DB_SCALE
, tlv
))
521 if (put_user(2 * sizeof(unsigned int), tlv
+ 1))
523 if (put_user(val1
, tlv
+ 2))
525 if (put_user(val2
, tlv
+ 3))
530 static struct snd_kcontrol_new lola_analog_mixer __devinitdata
= {
531 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
532 .access
= (SNDRV_CTL_ELEM_ACCESS_READWRITE
|
533 SNDRV_CTL_ELEM_ACCESS_TLV_READ
|
534 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK
),
535 .info
= lola_analog_vol_info
,
536 .get
= lola_analog_vol_get
,
537 .put
= lola_analog_vol_put
,
538 .tlv
.c
= lola_analog_vol_tlv
,
541 static int __devinit
create_analog_mixer(struct lola
*chip
, int dir
, char *name
)
543 if (!chip
->pin
[dir
].num_pins
)
545 /* no analog volumes on digital only adapters */
546 if (chip
->pin
[dir
].num_pins
!= chip
->pin
[dir
].num_analog_pins
)
548 lola_analog_mixer
.name
= name
;
549 lola_analog_mixer
.private_value
= dir
;
550 return snd_ctl_add(chip
->card
,
551 snd_ctl_new1(&lola_analog_mixer
, chip
));
555 * Hardware sample rate converter on digital input
557 static int lola_input_src_info(struct snd_kcontrol
*kcontrol
,
558 struct snd_ctl_elem_info
*uinfo
)
560 struct lola
*chip
= snd_kcontrol_chip(kcontrol
);
562 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_BOOLEAN
;
563 uinfo
->count
= chip
->pin
[CAPT
].num_pins
;
564 uinfo
->value
.integer
.min
= 0;
565 uinfo
->value
.integer
.max
= 1;
569 static int lola_input_src_get(struct snd_kcontrol
*kcontrol
,
570 struct snd_ctl_elem_value
*ucontrol
)
572 struct lola
*chip
= snd_kcontrol_chip(kcontrol
);
575 for (i
= 0; i
< chip
->pin
[CAPT
].num_pins
; i
++)
576 ucontrol
->value
.integer
.value
[i
] =
577 !!(chip
->input_src_mask
& (1 << i
));
581 static int lola_input_src_put(struct snd_kcontrol
*kcontrol
,
582 struct snd_ctl_elem_value
*ucontrol
)
584 struct lola
*chip
= snd_kcontrol_chip(kcontrol
);
589 for (i
= 0; i
< chip
->pin
[CAPT
].num_pins
; i
++)
590 if (ucontrol
->value
.integer
.value
[i
])
592 return lola_set_src_config(chip
, mask
, true);
595 static struct snd_kcontrol_new lola_input_src_mixer __devinitdata
= {
596 .name
= "Digital SRC Capture Switch",
597 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
598 .info
= lola_input_src_info
,
599 .get
= lola_input_src_get
,
600 .put
= lola_input_src_put
,
604 * Lola16161 or Lola881 can have Hardware sample rate converters
605 * on its digital input pins
607 static int __devinit
create_input_src_mixer(struct lola
*chip
)
609 if (!chip
->input_src_caps_mask
)
612 return snd_ctl_add(chip
->card
,
613 snd_ctl_new1(&lola_input_src_mixer
, chip
));
619 static int lola_src_gain_info(struct snd_kcontrol
*kcontrol
,
620 struct snd_ctl_elem_info
*uinfo
)
622 unsigned int count
= (kcontrol
->private_value
>> 8) & 0xff;
624 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
625 uinfo
->count
= count
;
626 uinfo
->value
.integer
.min
= 0;
627 uinfo
->value
.integer
.max
= 409;
631 static int lola_src_gain_get(struct snd_kcontrol
*kcontrol
,
632 struct snd_ctl_elem_value
*ucontrol
)
634 struct lola
*chip
= snd_kcontrol_chip(kcontrol
);
635 unsigned int ofs
= kcontrol
->private_value
& 0xff;
636 unsigned int count
= (kcontrol
->private_value
>> 8) & 0xff;
637 unsigned int mask
, i
;
639 mask
= readl(&chip
->mixer
.array
->src_gain_enable
);
640 for (i
= 0; i
< count
; i
++) {
641 unsigned int idx
= ofs
+ i
;
643 if (!(chip
->mixer
.src_mask
& (1 << idx
)))
645 if (mask
& (1 << idx
))
646 val
= readw(&chip
->mixer
.array
->src_gain
[idx
]) + 1;
649 ucontrol
->value
.integer
.value
[i
] = val
;
654 static int lola_src_gain_put(struct snd_kcontrol
*kcontrol
,
655 struct snd_ctl_elem_value
*ucontrol
)
657 struct lola
*chip
= snd_kcontrol_chip(kcontrol
);
658 unsigned int ofs
= kcontrol
->private_value
& 0xff;
659 unsigned int count
= (kcontrol
->private_value
>> 8) & 0xff;
662 for (i
= 0; i
< count
; i
++) {
663 unsigned int idx
= ofs
+ i
;
664 unsigned short val
= ucontrol
->value
.integer
.value
[i
];
667 err
= lola_mixer_set_src_gain(chip
, idx
, val
, !!val
);
674 /* raw value: 0 = -84dB, 336 = 0dB, 408=18dB, incremented 1 for mute */
675 static const DECLARE_TLV_DB_SCALE(lola_src_gain_tlv
, -8425, 25, 1);
677 static struct snd_kcontrol_new lola_src_gain_mixer __devinitdata
= {
678 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
679 .access
= (SNDRV_CTL_ELEM_ACCESS_READWRITE
|
680 SNDRV_CTL_ELEM_ACCESS_TLV_READ
),
681 .info
= lola_src_gain_info
,
682 .get
= lola_src_gain_get
,
683 .put
= lola_src_gain_put
,
684 .tlv
.p
= lola_src_gain_tlv
,
687 static int __devinit
create_src_gain_mixer(struct lola
*chip
,
688 int num
, int ofs
, char *name
)
690 lola_src_gain_mixer
.name
= name
;
691 lola_src_gain_mixer
.private_value
= ofs
+ (num
<< 8);
692 return snd_ctl_add(chip
->card
,
693 snd_ctl_new1(&lola_src_gain_mixer
, chip
));
697 * destination gain (matrix-like) mixer
699 static int lola_dest_gain_info(struct snd_kcontrol
*kcontrol
,
700 struct snd_ctl_elem_info
*uinfo
)
702 unsigned int src_num
= (kcontrol
->private_value
>> 8) & 0xff;
704 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
705 uinfo
->count
= src_num
;
706 uinfo
->value
.integer
.min
= 0;
707 uinfo
->value
.integer
.max
= 433;
711 static int lola_dest_gain_get(struct snd_kcontrol
*kcontrol
,
712 struct snd_ctl_elem_value
*ucontrol
)
714 struct lola
*chip
= snd_kcontrol_chip(kcontrol
);
715 unsigned int src_ofs
= kcontrol
->private_value
& 0xff;
716 unsigned int src_num
= (kcontrol
->private_value
>> 8) & 0xff;
717 unsigned int dst_ofs
= (kcontrol
->private_value
>> 16) & 0xff;
718 unsigned int dst
, mask
, i
;
720 dst
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
) + dst_ofs
;
721 mask
= readl(&chip
->mixer
.array
->dest_mix_gain_enable
[dst
]);
722 for (i
= 0; i
< src_num
; i
++) {
723 unsigned int src
= src_ofs
+ i
;
725 if (!(chip
->mixer
.src_mask
& (1 << src
)))
727 if (mask
& (1 << dst
))
728 val
= readw(&chip
->mixer
.array
->dest_mix_gain
[dst
][src
]) + 1;
731 ucontrol
->value
.integer
.value
[i
] = val
;
736 static int lola_dest_gain_put(struct snd_kcontrol
*kcontrol
,
737 struct snd_ctl_elem_value
*ucontrol
)
739 struct lola
*chip
= snd_kcontrol_chip(kcontrol
);
740 unsigned int src_ofs
= kcontrol
->private_value
& 0xff;
741 unsigned int src_num
= (kcontrol
->private_value
>> 8) & 0xff;
742 unsigned int dst_ofs
= (kcontrol
->private_value
>> 16) & 0xff;
743 unsigned int dst
, mask
;
744 unsigned short gains
[MAX_STREAM_COUNT
];
749 for (i
= 0; i
< src_num
; i
++) {
750 unsigned short val
= ucontrol
->value
.integer
.value
[i
];
752 gains
[num
++] = val
- 1;
757 dst
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
) + dst_ofs
;
758 return lola_mixer_set_dest_gains(chip
, dst
, mask
, gains
);
761 static const DECLARE_TLV_DB_SCALE(lola_dest_gain_tlv
, -8425, 25, 1);
763 static struct snd_kcontrol_new lola_dest_gain_mixer __devinitdata
= {
764 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
765 .access
= (SNDRV_CTL_ELEM_ACCESS_READWRITE
|
766 SNDRV_CTL_ELEM_ACCESS_TLV_READ
),
767 .info
= lola_dest_gain_info
,
768 .get
= lola_dest_gain_get
,
769 .put
= lola_dest_gain_put
,
770 .tlv
.p
= lola_dest_gain_tlv
,
773 static int __devinit
create_dest_gain_mixer(struct lola
*chip
,
774 int src_num
, int src_ofs
,
775 int num
, int ofs
, char *name
)
777 lola_dest_gain_mixer
.count
= num
;
778 lola_dest_gain_mixer
.name
= name
;
779 lola_dest_gain_mixer
.private_value
=
780 src_ofs
+ (src_num
<< 8) + (ofs
<< 16) + (num
<< 24);
781 return snd_ctl_add(chip
->card
,
782 snd_ctl_new1(&lola_dest_gain_mixer
, chip
));
787 int __devinit
lola_create_mixer(struct lola
*chip
)
791 err
= create_analog_mixer(chip
, PLAY
, "Analog Playback Volume");
794 err
= create_analog_mixer(chip
, CAPT
, "Analog Capture Volume");
797 err
= create_input_src_mixer(chip
);
800 err
= create_src_gain_mixer(chip
, chip
->mixer
.src_phys_ins
, 0,
801 "Line Source Gain Volume");
804 err
= create_src_gain_mixer(chip
, chip
->mixer
.src_stream_outs
,
805 chip
->mixer
.src_stream_out_ofs
,
806 "Stream Source Gain Volume");
809 err
= create_dest_gain_mixer(chip
,
810 chip
->mixer
.src_phys_ins
, 0,
811 chip
->mixer
.dest_stream_ins
, 0,
812 "Line Capture Volume");
815 err
= create_dest_gain_mixer(chip
,
816 chip
->mixer
.src_stream_outs
,
817 chip
->mixer
.src_stream_out_ofs
,
818 chip
->mixer
.dest_stream_ins
, 0,
819 "Stream-Loopback Capture Volume");
822 err
= create_dest_gain_mixer(chip
,
823 chip
->mixer
.src_phys_ins
, 0,
824 chip
->mixer
.dest_phys_outs
,
825 chip
->mixer
.dest_phys_out_ofs
,
826 "Line-Loopback Playback Volume");
829 err
= create_dest_gain_mixer(chip
,
830 chip
->mixer
.src_stream_outs
,
831 chip
->mixer
.src_stream_out_ofs
,
832 chip
->mixer
.dest_phys_outs
,
833 chip
->mixer
.dest_phys_out_ofs
,
834 "Stream Playback Volume");
838 return init_mixer_values(chip
);