1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 *  Support for Digigram Lola PCI-e boards
4 *
5 *  Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
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
18static 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; /* test TYPE and bits 0..11 */
31	if (val == 0x00400200)    /* Type = 4, Digital = 1 */
32		pin->is_analog = false;
33	else if (val == 0x0040000a && dir == CAPT) /* Dig=0, InAmp/ovrd */
34		pin->is_analog = true;
35	else if (val == 0x0040000c && dir == PLAY) /* Dig=0, OutAmp/ovrd */
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	/* analog parameters only following, so continue in case of Digital pin
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		/* zero as mute state */
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;   /* 10 bits */
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
81int 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
96void lola_free_mixer(struct lola *chip)
97{
98	vfree(chip->mixer.array_saved);
99}
100
101int 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) { /* test SubType and Type */
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	/* reserve memory to copy mixer data for sleep mode transitions */
123	chip->mixer.array_saved = vmalloc(sizeof(struct lola_mixer_array));
124
125	/* mixer matrix sources are physical input data and play streams */
126	chip->mixer.src_stream_outs = chip->pcm[PLAY].num_streams;
127	chip->mixer.src_phys_ins = chip->pin[CAPT].num_pins;
128
129	/* mixer matrix destinations are record streams and physical output */
130	chip->mixer.dest_stream_ins = chip->pcm[CAPT].num_streams;
131	chip->mixer.dest_phys_outs = chip->pin[PLAY].num_pins;
132
133	/* mixer matrix may have unused areas between PhysIn and
134	 * Play or Record and PhysOut zones
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	/* example : MixerMatrix of LoLa881 (LoLa16161 uses unused zones)
142	 * +-+  0-------8------16-------8------16
143	 * | |  |       |       |       |       |
144	 * |s|  | INPUT |       | INPUT |       |
145	 * | |->|  ->   |unused |  ->   |unused |
146	 * |r|  |CAPTURE|       | OUTPUT|       |
147	 * | |  |  MIX  |       |  MIX  |       |
148	 * |c|  8--------------------------------
149	 * | |  |       |       |       |       |
150	 * | |  |       |       |       |       |
151	 * |g|  |unused |unused |unused |unused |
152	 * | |  |       |       |       |       |
153	 * |a|  |       |       |       |       |
154	 * | |  16-------------------------------
155	 * |i|  |       |       |       |       |
156	 * | |  | PLAYBK|       | PLAYBK|       |
157	 * |n|->|  ->   |unused |  ->   |unused |
158	 * | |  |CAPTURE|       | OUTPUT|       |
159	 * | |  |  MIX  |       |  MIX  |       |
160	 * |a|  8--------------------------------
161	 * |r|  |       |       |       |       |
162	 * |r|  |       |       |       |       |
163	 * |a|  |unused |unused |unused |unused |
164	 * |y|  |       |       |       |       |
165	 * | |  |       |       |       |       |
166	 * +++  16--|---------------|------------
167	 *      +---V---------------V-----------+
168	 *      |  dest_mix_gain_enable array   |
169	 *      +-------------------------------+
170	 */
171	/* example : MixerMatrix of LoLa280
172	 * +-+  0-------8-2
173	 * | |  |       | |
174	 * |s|  | INPUT | |     INPUT
175	 * |r|->|  ->   | |      ->
176	 * |c|  |CAPTURE| | <-  OUTPUT
177	 * | |  |  MIX  | |      MIX
178	 * |g|  8----------
179	 * |a|  |       | |
180	 * |i|  | PLAYBK| |     PLAYBACK
181	 * |n|->|  ->   | |      ->
182	 * | |  |CAPTURE| | <-  OUTPUT
183	 * |a|  |  MIX  | |      MIX
184	 * |r|  8---|----|-
185	 * |r|  +---V----V-------------------+
186	 * |a|  | dest_mix_gain_enable array |
187	 * |y|  +----------------------------+
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
208static 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	/* test if values unchanged */
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	/* inform micro-controller about the new source gain */
232	return lola_codec_write(chip, chip->mixer.nid,
233				LOLA_VERB_SET_SOURCE_GAIN, id, 0);
234}
235
236#if 0 /* not used */
237static 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		/* update for all srcs at once */
254		return lola_codec_write(chip, chip->mixer.nid,
255					LOLA_VERB_SET_SOURCE_GAIN, 0x80, 0);
256	}
257	/* update manually */
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 /* not used */
267
268static 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 /* not used */
291static 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	/* update for all dests at once */
308	return lola_codec_write(chip, chip->mixer.nid,
309				LOLA_VERB_SET_DESTINATION_GAIN, id, 0);
310}
311#endif /* not used */
312
313/*
314 */
315
316static int set_analog_volume(struct lola *chip, int dir,
317			     unsigned int idx, unsigned int val,
318			     bool external_call);
319
320int 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			/* set volume and do not save the value */
331			set_analog_volume(chip, dir, idx, val, false);
332		}
333	}
334	return lola_codec_flush(chip);
335}
336
337void lola_save_mixer(struct lola *chip)
338{
339	/* mute analog output */
340	if (chip->mixer.array_saved) {
341		/* store contents of mixer array */
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); /* output mute */
346}
347
348void lola_restore_mixer(struct lola *chip)
349{
350	int i;
351
352	/*lola_reset_setups(chip);*/
353	if (chip->mixer.array_saved) {
354		/* restore contents of mixer array */
355		memcpy_toio(chip->mixer.array, chip->mixer.array_saved,
356			    sizeof(*chip->mixer.array));
357		/* inform micro-controller about all restored values
358		 * and ignore return values
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
383static 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
411int 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	/* SRC can be activated and the dwInputSRCMask is valid? */
418	if ((chip->input_src_caps_mask & src_mask) != src_mask)
419		return -EINVAL;
420	/* handle all even Inputs - SRC is a stereo setting !!! */
421	for (n = 0; n < chip->pin[CAPT].num_pins; n += 2) {
422		unsigned int mask = 3U << n; /* handle the stereo case */
423		unsigned int new_src, src_state;
424		if (!(chip->input_src_caps_mask & mask))
425			continue;
426		/* if one IO needs SRC, both stereo IO will get SRC */
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;   /* nothing to change for this IO */
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 */
449static int init_mixer_values(struct lola *chip)
450{
451	int i;
452
453	/* all sample rate converters on */
454	lola_set_src_config(chip, (1 << chip->pin[CAPT].num_pins) - 1, false);
455
456	/* clear all mixer matrix settings */
457	memset_io(chip->mixer.array, 0, sizeof(*chip->mixer.array));
458	/* inform firmware about all updated matrix columns - capture part */
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	/* inform firmware about all updated matrix columns - output part */
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	/* set all digital input source (master) gains to 0dB */
470	for (i = 0; i < chip->mixer.src_phys_ins; i++)
471		lola_mixer_set_src_gain(chip, i, 336, true); /* 0dB */
472
473	/* set all digital playback source (master) gains to 0dB */
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); /* 0dB */
478	/* set gain value 0dB diagonally in matrix - part INPUT -> CAPTURE */
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	/* set gain value 0dB diagonally in matrix , part PLAYBACK -> OUTPUT
484	 * (LoLa280 : playback channel 0,2,4,6 linked to output channel 0)
485	 * (LoLa280 : playback channel 1,3,5,7 linked to output channel 1)
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 * analog mixer control element
498 */
499static 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
512static 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
525static 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
542static 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
570static 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
581static int create_analog_mixer(struct lola *chip, int dir, char *name)
582{
583	if (!chip->pin[dir].num_pins)
584		return 0;
585	/* no analog volumes on digital only adapters */
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 * Hardware sample rate converter on digital input
596 */
597static 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
609static 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
621static 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
635static 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 * Lola16161 or Lola881 can have Hardware sample rate converters
645 * on its digital input pins
646 */
647static 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 * src gain mixer
658 */
659static 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
671static 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
694static 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/* raw value: 0 = -84dB, 336 = 0dB, 408=18dB, incremented 1 for mute */
715static const DECLARE_TLV_DB_SCALE(lola_src_gain_tlv, -8425, 25, 1);
716
717static 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
727static 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 /* not used */
737/*
738 * destination gain (matrix-like) mixer
739 */
740static 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
752static 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
777static 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
802static const DECLARE_TLV_DB_SCALE(lola_dest_gain_tlv, -8425, 25, 1);
803
804static 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
814static 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 /* not used */
826
827/*
828 */
829int 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/* FIXME: buggy mixer matrix handling */
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 /* FIXME */
882	return init_mixer_values(chip);
883}
884