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 lola_init_pin(struct lola
*chip
, struct lola_pin
*pin
,
38 err
= lola_read_param(chip
, nid
, LOLA_PAR_AUDIO_WIDGET_CAP
, &val
);
40 dev_err(chip
->card
->dev
, "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 dev_err(chip
->card
->dev
, "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 dev_err(chip
->card
->dev
, "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 dev_err(chip
->card
->dev
, "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 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 vfree(chip
->mixer
.array_saved
);
114 int lola_init_mixer_widget(struct lola
*chip
, int nid
)
119 err
= lola_read_param(chip
, nid
, LOLA_PAR_AUDIO_WIDGET_CAP
, &val
);
121 dev_err(chip
->card
->dev
, "Can't read wcaps for 0x%x\n", nid
);
125 if ((val
& 0xfff00000) != 0x02f00000) { /* test SubType and Type */
126 dev_dbg(chip
->card
->dev
, "No valid mixer widget\n");
130 chip
->mixer
.nid
= nid
;
131 chip
->mixer
.caps
= val
;
132 chip
->mixer
.array
= (struct lola_mixer_array __iomem
*)
133 (chip
->bar
[BAR1
].remap_addr
+ LOLA_BAR1_SOURCE_GAIN_ENABLE
);
135 /* reserve memory to copy mixer data for sleep mode transitions */
136 chip
->mixer
.array_saved
= vmalloc(sizeof(struct lola_mixer_array
));
138 /* mixer matrix sources are physical input data and play streams */
139 chip
->mixer
.src_stream_outs
= chip
->pcm
[PLAY
].num_streams
;
140 chip
->mixer
.src_phys_ins
= chip
->pin
[CAPT
].num_pins
;
142 /* mixer matrix destinations are record streams and physical output */
143 chip
->mixer
.dest_stream_ins
= chip
->pcm
[CAPT
].num_streams
;
144 chip
->mixer
.dest_phys_outs
= chip
->pin
[PLAY
].num_pins
;
146 /* mixer matrix may have unused areas between PhysIn and
147 * Play or Record and PhysOut zones
149 chip
->mixer
.src_stream_out_ofs
= chip
->mixer
.src_phys_ins
+
150 LOLA_MIXER_SRC_INPUT_PLAY_SEPARATION(val
);
151 chip
->mixer
.dest_phys_out_ofs
= chip
->mixer
.dest_stream_ins
+
152 LOLA_MIXER_DEST_REC_OUTPUT_SEPARATION(val
);
154 /* example : MixerMatrix of LoLa881 (LoLa16161 uses unused zones)
155 * +-+ 0-------8------16-------8------16
157 * |s| | INPUT | | INPUT | |
158 * | |->| -> |unused | -> |unused |
159 * |r| |CAPTURE| | OUTPUT| |
160 * | | | MIX | | MIX | |
161 * |c| 8--------------------------------
164 * |g| |unused |unused |unused |unused |
167 * | | 16-------------------------------
169 * | | | PLAYBK| | PLAYBK| |
170 * |n|->| -> |unused | -> |unused |
171 * | | |CAPTURE| | OUTPUT| |
172 * | | | MIX | | MIX | |
173 * |a| 8--------------------------------
176 * |a| |unused |unused |unused |unused |
179 * +++ 16--|---------------|------------
180 * +---V---------------V-----------+
181 * | dest_mix_gain_enable array |
182 * +-------------------------------+
184 /* example : MixerMatrix of LoLa280
187 * |s| | INPUT | | INPUT
189 * |c| |CAPTURE| | <- OUTPUT
193 * |i| | PLAYBK| | PLAYBACK
195 * | | |CAPTURE| | <- OUTPUT
198 * |r| +---V----V-------------------+
199 * |a| | dest_mix_gain_enable array |
200 * |y| +----------------------------+
202 if (chip
->mixer
.src_stream_out_ofs
> MAX_AUDIO_INOUT_COUNT
||
203 chip
->mixer
.dest_phys_out_ofs
> MAX_STREAM_IN_COUNT
) {
204 dev_err(chip
->card
->dev
, "Invalid mixer widget size\n");
208 chip
->mixer
.src_mask
= ((1U << chip
->mixer
.src_phys_ins
) - 1) |
209 (((1U << chip
->mixer
.src_stream_outs
) - 1)
210 << chip
->mixer
.src_stream_out_ofs
);
211 chip
->mixer
.dest_mask
= ((1U << chip
->mixer
.dest_stream_ins
) - 1) |
212 (((1U << chip
->mixer
.dest_phys_outs
) - 1)
213 << chip
->mixer
.dest_phys_out_ofs
);
215 dev_dbg(chip
->card
->dev
, "Mixer src_mask=%x, dest_mask=%x\n",
216 chip
->mixer
.src_mask
, chip
->mixer
.dest_mask
);
221 static int lola_mixer_set_src_gain(struct lola
*chip
, unsigned int id
,
222 unsigned short gain
, bool on
)
224 unsigned int oldval
, val
;
226 if (!(chip
->mixer
.src_mask
& (1 << id
)))
228 oldval
= val
= readl(&chip
->mixer
.array
->src_gain_enable
);
233 /* test if values unchanged */
234 if ((val
== oldval
) &&
235 (gain
== readw(&chip
->mixer
.array
->src_gain
[id
])))
238 dev_dbg(chip
->card
->dev
,
239 "lola_mixer_set_src_gain (id=%d, gain=%d) enable=%x\n",
241 writew(gain
, &chip
->mixer
.array
->src_gain
[id
]);
242 writel(val
, &chip
->mixer
.array
->src_gain_enable
);
243 lola_codec_flush(chip
);
244 /* inform micro-controller about the new source gain */
245 return lola_codec_write(chip
, chip
->mixer
.nid
,
246 LOLA_VERB_SET_SOURCE_GAIN
, id
, 0);
250 static int lola_mixer_set_src_gains(struct lola
*chip
, unsigned int mask
,
251 unsigned short *gains
)
255 if ((chip
->mixer
.src_mask
& mask
) != mask
)
257 for (i
= 0; i
< LOLA_MIXER_DIM
; i
++) {
258 if (mask
& (1 << i
)) {
259 writew(*gains
, &chip
->mixer
.array
->src_gain
[i
]);
263 writel(mask
, &chip
->mixer
.array
->src_gain_enable
);
264 lola_codec_flush(chip
);
265 if (chip
->mixer
.caps
& LOLA_PEAK_METER_CAN_AGC_MASK
) {
266 /* update for all srcs at once */
267 return lola_codec_write(chip
, chip
->mixer
.nid
,
268 LOLA_VERB_SET_SOURCE_GAIN
, 0x80, 0);
270 /* update manually */
271 for (i
= 0; i
< LOLA_MIXER_DIM
; i
++) {
272 if (mask
& (1 << i
)) {
273 lola_codec_write(chip
, chip
->mixer
.nid
,
274 LOLA_VERB_SET_SOURCE_GAIN
, i
, 0);
279 #endif /* not used */
281 static int lola_mixer_set_mapping_gain(struct lola
*chip
,
282 unsigned int src
, unsigned int dest
,
283 unsigned short gain
, bool on
)
287 if (!(chip
->mixer
.src_mask
& (1 << src
)) ||
288 !(chip
->mixer
.dest_mask
& (1 << dest
)))
291 writew(gain
, &chip
->mixer
.array
->dest_mix_gain
[dest
][src
]);
292 val
= readl(&chip
->mixer
.array
->dest_mix_gain_enable
[dest
]);
297 writel(val
, &chip
->mixer
.array
->dest_mix_gain_enable
[dest
]);
298 lola_codec_flush(chip
);
299 return lola_codec_write(chip
, chip
->mixer
.nid
, LOLA_VERB_SET_MIX_GAIN
,
304 static int lola_mixer_set_dest_gains(struct lola
*chip
, unsigned int id
,
305 unsigned int mask
, unsigned short *gains
)
309 if (!(chip
->mixer
.dest_mask
& (1 << id
)) ||
310 (chip
->mixer
.src_mask
& mask
) != mask
)
312 for (i
= 0; i
< LOLA_MIXER_DIM
; i
++) {
313 if (mask
& (1 << i
)) {
314 writew(*gains
, &chip
->mixer
.array
->dest_mix_gain
[id
][i
]);
318 writel(mask
, &chip
->mixer
.array
->dest_mix_gain_enable
[id
]);
319 lola_codec_flush(chip
);
320 /* update for all dests at once */
321 return lola_codec_write(chip
, chip
->mixer
.nid
,
322 LOLA_VERB_SET_DESTINATION_GAIN
, id
, 0);
324 #endif /* not used */
329 static int set_analog_volume(struct lola
*chip
, int dir
,
330 unsigned int idx
, unsigned int val
,
333 int lola_setup_all_analog_gains(struct lola
*chip
, int dir
, bool mute
)
335 struct lola_pin
*pin
;
338 pin
= chip
->pin
[dir
].pins
;
339 max_idx
= chip
->pin
[dir
].num_pins
;
340 for (idx
= 0; idx
< max_idx
; idx
++) {
341 if (pin
[idx
].is_analog
) {
342 unsigned int val
= mute
? 0 : pin
[idx
].cur_gain_step
;
343 /* set volume and do not save the value */
344 set_analog_volume(chip
, dir
, idx
, val
, false);
347 return lola_codec_flush(chip
);
350 void lola_save_mixer(struct lola
*chip
)
352 /* mute analog output */
353 if (chip
->mixer
.array_saved
) {
354 /* store contents of mixer array */
355 memcpy_fromio(chip
->mixer
.array_saved
, chip
->mixer
.array
,
356 sizeof(*chip
->mixer
.array
));
358 lola_setup_all_analog_gains(chip
, PLAY
, true); /* output mute */
361 void lola_restore_mixer(struct lola
*chip
)
365 /*lola_reset_setups(chip);*/
366 if (chip
->mixer
.array_saved
) {
367 /* restore contents of mixer array */
368 memcpy_toio(chip
->mixer
.array
, chip
->mixer
.array_saved
,
369 sizeof(*chip
->mixer
.array
));
370 /* inform micro-controller about all restored values
371 * and ignore return values
373 for (i
= 0; i
< chip
->mixer
.src_phys_ins
; i
++)
374 lola_codec_write(chip
, chip
->mixer
.nid
,
375 LOLA_VERB_SET_SOURCE_GAIN
,
377 for (i
= 0; i
< chip
->mixer
.src_stream_outs
; i
++)
378 lola_codec_write(chip
, chip
->mixer
.nid
,
379 LOLA_VERB_SET_SOURCE_GAIN
,
380 chip
->mixer
.src_stream_out_ofs
+ i
, 0);
381 for (i
= 0; i
< chip
->mixer
.dest_stream_ins
; i
++)
382 lola_codec_write(chip
, chip
->mixer
.nid
,
383 LOLA_VERB_SET_DESTINATION_GAIN
,
385 for (i
= 0; i
< chip
->mixer
.dest_phys_outs
; i
++)
386 lola_codec_write(chip
, chip
->mixer
.nid
,
387 LOLA_VERB_SET_DESTINATION_GAIN
,
388 chip
->mixer
.dest_phys_out_ofs
+ i
, 0);
389 lola_codec_flush(chip
);
396 static int set_analog_volume(struct lola
*chip
, int dir
,
397 unsigned int idx
, unsigned int val
,
400 struct lola_pin
*pin
;
403 if (idx
>= chip
->pin
[dir
].num_pins
)
405 pin
= &chip
->pin
[dir
].pins
[idx
];
406 if (!pin
->is_analog
|| pin
->amp_num_steps
<= val
)
408 if (external_call
&& pin
->cur_gain_step
== val
)
411 lola_codec_flush(chip
);
412 dev_dbg(chip
->card
->dev
,
413 "set_analog_volume (dir=%d idx=%d, volume=%d)\n",
415 err
= lola_codec_write(chip
, pin
->nid
,
416 LOLA_VERB_SET_AMP_GAIN_MUTE
, val
, 0);
420 pin
->cur_gain_step
= val
;
424 int lola_set_src_config(struct lola
*chip
, unsigned int src_mask
, bool update
)
430 /* SRC can be activated and the dwInputSRCMask is valid? */
431 if ((chip
->input_src_caps_mask
& src_mask
) != src_mask
)
433 /* handle all even Inputs - SRC is a stereo setting !!! */
434 for (n
= 0; n
< chip
->pin
[CAPT
].num_pins
; n
+= 2) {
435 unsigned int mask
= 3U << n
; /* handle the stereo case */
436 unsigned int new_src
, src_state
;
437 if (!(chip
->input_src_caps_mask
& mask
))
439 /* if one IO needs SRC, both stereo IO will get SRC */
440 new_src
= (src_mask
& mask
) != 0;
442 src_state
= (chip
->input_src_mask
& mask
) != 0;
443 if (src_state
== new_src
)
444 continue; /* nothing to change for this IO */
446 err
= lola_codec_write(chip
, chip
->pcm
[CAPT
].streams
[n
].nid
,
447 LOLA_VERB_SET_SRC
, new_src
, 0);
454 ret
= lola_codec_flush(chip
);
456 chip
->input_src_mask
= src_mask
;
462 static int init_mixer_values(struct lola
*chip
)
466 /* all sample rate converters on */
467 lola_set_src_config(chip
, (1 << chip
->pin
[CAPT
].num_pins
) - 1, false);
469 /* clear all mixer matrix settings */
470 memset_io(chip
->mixer
.array
, 0, sizeof(*chip
->mixer
.array
));
471 /* inform firmware about all updated matrix columns - capture part */
472 for (i
= 0; i
< chip
->mixer
.dest_stream_ins
; i
++)
473 lola_codec_write(chip
, chip
->mixer
.nid
,
474 LOLA_VERB_SET_DESTINATION_GAIN
,
476 /* inform firmware about all updated matrix columns - output part */
477 for (i
= 0; i
< chip
->mixer
.dest_phys_outs
; i
++)
478 lola_codec_write(chip
, chip
->mixer
.nid
,
479 LOLA_VERB_SET_DESTINATION_GAIN
,
480 chip
->mixer
.dest_phys_out_ofs
+ i
, 0);
482 /* set all digital input source (master) gains to 0dB */
483 for (i
= 0; i
< chip
->mixer
.src_phys_ins
; i
++)
484 lola_mixer_set_src_gain(chip
, i
, 336, true); /* 0dB */
486 /* set all digital playback source (master) gains to 0dB */
487 for (i
= 0; i
< chip
->mixer
.src_stream_outs
; i
++)
488 lola_mixer_set_src_gain(chip
,
489 i
+ chip
->mixer
.src_stream_out_ofs
,
490 336, true); /* 0dB */
491 /* set gain value 0dB diagonally in matrix - part INPUT -> CAPTURE */
492 for (i
= 0; i
< chip
->mixer
.dest_stream_ins
; i
++) {
493 int src
= i
% chip
->mixer
.src_phys_ins
;
494 lola_mixer_set_mapping_gain(chip
, src
, i
, 336, true);
496 /* set gain value 0dB diagonally in matrix , part PLAYBACK -> OUTPUT
497 * (LoLa280 : playback channel 0,2,4,6 linked to output channel 0)
498 * (LoLa280 : playback channel 1,3,5,7 linked to output channel 1)
500 for (i
= 0; i
< chip
->mixer
.src_stream_outs
; i
++) {
501 int src
= chip
->mixer
.src_stream_out_ofs
+ i
;
502 int dst
= chip
->mixer
.dest_phys_out_ofs
+
503 i
% chip
->mixer
.dest_phys_outs
;
504 lola_mixer_set_mapping_gain(chip
, src
, dst
, 336, true);
510 * analog mixer control element
512 static int lola_analog_vol_info(struct snd_kcontrol
*kcontrol
,
513 struct snd_ctl_elem_info
*uinfo
)
515 struct lola
*chip
= snd_kcontrol_chip(kcontrol
);
516 int dir
= kcontrol
->private_value
;
518 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
519 uinfo
->count
= chip
->pin
[dir
].num_pins
;
520 uinfo
->value
.integer
.min
= 0;
521 uinfo
->value
.integer
.max
= chip
->pin
[dir
].pins
[0].amp_num_steps
;
525 static int lola_analog_vol_get(struct snd_kcontrol
*kcontrol
,
526 struct snd_ctl_elem_value
*ucontrol
)
528 struct lola
*chip
= snd_kcontrol_chip(kcontrol
);
529 int dir
= kcontrol
->private_value
;
532 for (i
= 0; i
< chip
->pin
[dir
].num_pins
; i
++)
533 ucontrol
->value
.integer
.value
[i
] =
534 chip
->pin
[dir
].pins
[i
].cur_gain_step
;
538 static int lola_analog_vol_put(struct snd_kcontrol
*kcontrol
,
539 struct snd_ctl_elem_value
*ucontrol
)
541 struct lola
*chip
= snd_kcontrol_chip(kcontrol
);
542 int dir
= kcontrol
->private_value
;
545 for (i
= 0; i
< chip
->pin
[dir
].num_pins
; i
++) {
546 err
= set_analog_volume(chip
, dir
, i
,
547 ucontrol
->value
.integer
.value
[i
],
555 static int lola_analog_vol_tlv(struct snd_kcontrol
*kcontrol
, int op_flag
,
556 unsigned int size
, unsigned int __user
*tlv
)
558 struct lola
*chip
= snd_kcontrol_chip(kcontrol
);
559 int dir
= kcontrol
->private_value
;
560 unsigned int val1
, val2
;
561 struct lola_pin
*pin
;
563 if (size
< 4 * sizeof(unsigned int))
565 pin
= &chip
->pin
[dir
].pins
[0];
567 val2
= pin
->amp_step_size
* 25;
568 val1
= -1 * (int)pin
->amp_offset
* (int)val2
;
569 #ifdef TLV_DB_SCALE_MUTE
570 val2
|= TLV_DB_SCALE_MUTE
;
572 if (put_user(SNDRV_CTL_TLVT_DB_SCALE
, tlv
))
574 if (put_user(2 * sizeof(unsigned int), tlv
+ 1))
576 if (put_user(val1
, tlv
+ 2))
578 if (put_user(val2
, tlv
+ 3))
583 static struct snd_kcontrol_new lola_analog_mixer
= {
584 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
585 .access
= (SNDRV_CTL_ELEM_ACCESS_READWRITE
|
586 SNDRV_CTL_ELEM_ACCESS_TLV_READ
|
587 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK
),
588 .info
= lola_analog_vol_info
,
589 .get
= lola_analog_vol_get
,
590 .put
= lola_analog_vol_put
,
591 .tlv
.c
= lola_analog_vol_tlv
,
594 static int create_analog_mixer(struct lola
*chip
, int dir
, char *name
)
596 if (!chip
->pin
[dir
].num_pins
)
598 /* no analog volumes on digital only adapters */
599 if (chip
->pin
[dir
].num_pins
!= chip
->pin
[dir
].num_analog_pins
)
601 lola_analog_mixer
.name
= name
;
602 lola_analog_mixer
.private_value
= dir
;
603 return snd_ctl_add(chip
->card
,
604 snd_ctl_new1(&lola_analog_mixer
, chip
));
608 * Hardware sample rate converter on digital input
610 static int lola_input_src_info(struct snd_kcontrol
*kcontrol
,
611 struct snd_ctl_elem_info
*uinfo
)
613 struct lola
*chip
= snd_kcontrol_chip(kcontrol
);
615 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_BOOLEAN
;
616 uinfo
->count
= chip
->pin
[CAPT
].num_pins
;
617 uinfo
->value
.integer
.min
= 0;
618 uinfo
->value
.integer
.max
= 1;
622 static int lola_input_src_get(struct snd_kcontrol
*kcontrol
,
623 struct snd_ctl_elem_value
*ucontrol
)
625 struct lola
*chip
= snd_kcontrol_chip(kcontrol
);
628 for (i
= 0; i
< chip
->pin
[CAPT
].num_pins
; i
++)
629 ucontrol
->value
.integer
.value
[i
] =
630 !!(chip
->input_src_mask
& (1 << i
));
634 static int lola_input_src_put(struct snd_kcontrol
*kcontrol
,
635 struct snd_ctl_elem_value
*ucontrol
)
637 struct lola
*chip
= snd_kcontrol_chip(kcontrol
);
642 for (i
= 0; i
< chip
->pin
[CAPT
].num_pins
; i
++)
643 if (ucontrol
->value
.integer
.value
[i
])
645 return lola_set_src_config(chip
, mask
, true);
648 static const struct snd_kcontrol_new lola_input_src_mixer
= {
649 .name
= "Digital SRC Capture Switch",
650 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
651 .info
= lola_input_src_info
,
652 .get
= lola_input_src_get
,
653 .put
= lola_input_src_put
,
657 * Lola16161 or Lola881 can have Hardware sample rate converters
658 * on its digital input pins
660 static int create_input_src_mixer(struct lola
*chip
)
662 if (!chip
->input_src_caps_mask
)
665 return snd_ctl_add(chip
->card
,
666 snd_ctl_new1(&lola_input_src_mixer
, chip
));
672 static int lola_src_gain_info(struct snd_kcontrol
*kcontrol
,
673 struct snd_ctl_elem_info
*uinfo
)
675 unsigned int count
= (kcontrol
->private_value
>> 8) & 0xff;
677 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
678 uinfo
->count
= count
;
679 uinfo
->value
.integer
.min
= 0;
680 uinfo
->value
.integer
.max
= 409;
684 static int lola_src_gain_get(struct snd_kcontrol
*kcontrol
,
685 struct snd_ctl_elem_value
*ucontrol
)
687 struct lola
*chip
= snd_kcontrol_chip(kcontrol
);
688 unsigned int ofs
= kcontrol
->private_value
& 0xff;
689 unsigned int count
= (kcontrol
->private_value
>> 8) & 0xff;
690 unsigned int mask
, i
;
692 mask
= readl(&chip
->mixer
.array
->src_gain_enable
);
693 for (i
= 0; i
< count
; i
++) {
694 unsigned int idx
= ofs
+ i
;
696 if (!(chip
->mixer
.src_mask
& (1 << idx
)))
698 if (mask
& (1 << idx
))
699 val
= readw(&chip
->mixer
.array
->src_gain
[idx
]) + 1;
702 ucontrol
->value
.integer
.value
[i
] = val
;
707 static int lola_src_gain_put(struct snd_kcontrol
*kcontrol
,
708 struct snd_ctl_elem_value
*ucontrol
)
710 struct lola
*chip
= snd_kcontrol_chip(kcontrol
);
711 unsigned int ofs
= kcontrol
->private_value
& 0xff;
712 unsigned int count
= (kcontrol
->private_value
>> 8) & 0xff;
715 for (i
= 0; i
< count
; i
++) {
716 unsigned int idx
= ofs
+ i
;
717 unsigned short val
= ucontrol
->value
.integer
.value
[i
];
720 err
= lola_mixer_set_src_gain(chip
, idx
, val
, !!val
);
727 /* raw value: 0 = -84dB, 336 = 0dB, 408=18dB, incremented 1 for mute */
728 static const DECLARE_TLV_DB_SCALE(lola_src_gain_tlv
, -8425, 25, 1);
730 static struct snd_kcontrol_new lola_src_gain_mixer
= {
731 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
732 .access
= (SNDRV_CTL_ELEM_ACCESS_READWRITE
|
733 SNDRV_CTL_ELEM_ACCESS_TLV_READ
),
734 .info
= lola_src_gain_info
,
735 .get
= lola_src_gain_get
,
736 .put
= lola_src_gain_put
,
737 .tlv
.p
= lola_src_gain_tlv
,
740 static int create_src_gain_mixer(struct lola
*chip
,
741 int num
, int ofs
, char *name
)
743 lola_src_gain_mixer
.name
= name
;
744 lola_src_gain_mixer
.private_value
= ofs
+ (num
<< 8);
745 return snd_ctl_add(chip
->card
,
746 snd_ctl_new1(&lola_src_gain_mixer
, chip
));
751 * destination gain (matrix-like) mixer
753 static int lola_dest_gain_info(struct snd_kcontrol
*kcontrol
,
754 struct snd_ctl_elem_info
*uinfo
)
756 unsigned int src_num
= (kcontrol
->private_value
>> 8) & 0xff;
758 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
759 uinfo
->count
= src_num
;
760 uinfo
->value
.integer
.min
= 0;
761 uinfo
->value
.integer
.max
= 433;
765 static int lola_dest_gain_get(struct snd_kcontrol
*kcontrol
,
766 struct snd_ctl_elem_value
*ucontrol
)
768 struct lola
*chip
= snd_kcontrol_chip(kcontrol
);
769 unsigned int src_ofs
= kcontrol
->private_value
& 0xff;
770 unsigned int src_num
= (kcontrol
->private_value
>> 8) & 0xff;
771 unsigned int dst_ofs
= (kcontrol
->private_value
>> 16) & 0xff;
772 unsigned int dst
, mask
, i
;
774 dst
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
) + dst_ofs
;
775 mask
= readl(&chip
->mixer
.array
->dest_mix_gain_enable
[dst
]);
776 for (i
= 0; i
< src_num
; i
++) {
777 unsigned int src
= src_ofs
+ i
;
779 if (!(chip
->mixer
.src_mask
& (1 << src
)))
781 if (mask
& (1 << dst
))
782 val
= readw(&chip
->mixer
.array
->dest_mix_gain
[dst
][src
]) + 1;
785 ucontrol
->value
.integer
.value
[i
] = val
;
790 static int lola_dest_gain_put(struct snd_kcontrol
*kcontrol
,
791 struct snd_ctl_elem_value
*ucontrol
)
793 struct lola
*chip
= snd_kcontrol_chip(kcontrol
);
794 unsigned int src_ofs
= kcontrol
->private_value
& 0xff;
795 unsigned int src_num
= (kcontrol
->private_value
>> 8) & 0xff;
796 unsigned int dst_ofs
= (kcontrol
->private_value
>> 16) & 0xff;
797 unsigned int dst
, mask
;
798 unsigned short gains
[MAX_STREAM_COUNT
];
803 for (i
= 0; i
< src_num
; i
++) {
804 unsigned short val
= ucontrol
->value
.integer
.value
[i
];
806 gains
[num
++] = val
- 1;
811 dst
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
) + dst_ofs
;
812 return lola_mixer_set_dest_gains(chip
, dst
, mask
, gains
);
815 static const DECLARE_TLV_DB_SCALE(lola_dest_gain_tlv
, -8425, 25, 1);
817 static struct snd_kcontrol_new lola_dest_gain_mixer
= {
818 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
819 .access
= (SNDRV_CTL_ELEM_ACCESS_READWRITE
|
820 SNDRV_CTL_ELEM_ACCESS_TLV_READ
),
821 .info
= lola_dest_gain_info
,
822 .get
= lola_dest_gain_get
,
823 .put
= lola_dest_gain_put
,
824 .tlv
.p
= lola_dest_gain_tlv
,
827 static int create_dest_gain_mixer(struct lola
*chip
,
828 int src_num
, int src_ofs
,
829 int num
, int ofs
, char *name
)
831 lola_dest_gain_mixer
.count
= num
;
832 lola_dest_gain_mixer
.name
= name
;
833 lola_dest_gain_mixer
.private_value
=
834 src_ofs
+ (src_num
<< 8) + (ofs
<< 16) + (num
<< 24);
835 return snd_ctl_add(chip
->card
,
836 snd_ctl_new1(&lola_dest_gain_mixer
, chip
));
838 #endif /* not used */
842 int lola_create_mixer(struct lola
*chip
)
846 err
= create_analog_mixer(chip
, PLAY
, "Analog Playback Volume");
849 err
= create_analog_mixer(chip
, CAPT
, "Analog Capture Volume");
852 err
= create_input_src_mixer(chip
);
855 err
= create_src_gain_mixer(chip
, chip
->mixer
.src_phys_ins
, 0,
856 "Digital Capture Volume");
859 err
= create_src_gain_mixer(chip
, chip
->mixer
.src_stream_outs
,
860 chip
->mixer
.src_stream_out_ofs
,
861 "Digital Playback Volume");
865 /* FIXME: buggy mixer matrix handling */
866 err
= create_dest_gain_mixer(chip
,
867 chip
->mixer
.src_phys_ins
, 0,
868 chip
->mixer
.dest_stream_ins
, 0,
869 "Line Capture Volume");
872 err
= create_dest_gain_mixer(chip
,
873 chip
->mixer
.src_stream_outs
,
874 chip
->mixer
.src_stream_out_ofs
,
875 chip
->mixer
.dest_stream_ins
, 0,
876 "Stream-Loopback Capture Volume");
879 err
= create_dest_gain_mixer(chip
,
880 chip
->mixer
.src_phys_ins
, 0,
881 chip
->mixer
.dest_phys_outs
,
882 chip
->mixer
.dest_phys_out_ofs
,
883 "Line-Loopback Playback Volume");
886 err
= create_dest_gain_mixer(chip
,
887 chip
->mixer
.src_stream_outs
,
888 chip
->mixer
.src_stream_out_ofs
,
889 chip
->mixer
.dest_phys_outs
,
890 chip
->mixer
.dest_phys_out_ofs
,
891 "Stream Playback Volume");
895 return init_mixer_values(chip
);