File Index
Files and directories
Sign in
FILE

vx_mixer.c

File preview with syntax highlighting.

linux-6.19.14/sound/drivers/vx/vx_mixer.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Driver for Digigram VX soundcards
  4 *
  5 * Common mixer part
  6 *
  7 * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
  8 */
  9
 10#include <sound/core.h>
 11#include <sound/control.h>
 12#include <sound/tlv.h>
 13#include <sound/vx_core.h>
 14#include "vx_cmd.h"
 15
 16
 17/*
 18 * write a codec data (24bit)
 19 */
 20static void vx_write_codec_reg(struct vx_core *chip, int codec, unsigned int data)
 21{
 22	if (snd_BUG_ON(!chip->ops->write_codec))
 23		return;
 24
 25	if (chip->chip_status & VX_STAT_IS_STALE)
 26		return;
 27
 28	guard(mutex)(&chip->lock);
 29	chip->ops->write_codec(chip, codec, data);
 30}
 31
 32/*
 33 * Data type used to access the Codec
 34 */
 35union vx_codec_data {
 36	u32 l;
 37#ifdef SNDRV_BIG_ENDIAN
 38	struct w {
 39		u16 h;
 40		u16 l;
 41	} w;
 42	struct b {
 43		u8 hh;
 44		u8 mh;
 45		u8 ml;
 46		u8 ll;
 47	} b;
 48#else /* LITTLE_ENDIAN */
 49	struct w {
 50		u16 l;
 51		u16 h;
 52	} w;
 53	struct b {
 54		u8 ll;
 55		u8 ml;
 56		u8 mh;
 57		u8 hh;
 58	} b;
 59#endif
 60};
 61
 62#define SET_CDC_DATA_SEL(di,s)          ((di).b.mh = (u8) (s))
 63#define SET_CDC_DATA_REG(di,r)          ((di).b.ml = (u8) (r))
 64#define SET_CDC_DATA_VAL(di,d)          ((di).b.ll = (u8) (d))
 65#define SET_CDC_DATA_INIT(di)           ((di).l = 0L, SET_CDC_DATA_SEL(di,XX_CODEC_SELECTOR))
 66
 67/*
 68 * set up codec register and write the value
 69 * @codec: the codec id, 0 or 1
 70 * @reg: register index
 71 * @val: data value
 72 */
 73static void vx_set_codec_reg(struct vx_core *chip, int codec, int reg, int val)
 74{
 75	union vx_codec_data data;
 76	/* DAC control register */
 77	SET_CDC_DATA_INIT(data);
 78	SET_CDC_DATA_REG(data, reg);
 79	SET_CDC_DATA_VAL(data, val);
 80	vx_write_codec_reg(chip, codec, data.l);
 81}
 82
 83
 84/*
 85 * vx_set_analog_output_level - set the output attenuation level
 86 * @codec: the output codec, 0 or 1.  (1 for VXP440 only)
 87 * @left: left output level, 0 = mute
 88 * @right: right output level
 89 */
 90static void vx_set_analog_output_level(struct vx_core *chip, int codec, int left, int right)
 91{
 92	left  = chip->hw->output_level_max - left;
 93	right = chip->hw->output_level_max - right;
 94
 95	if (chip->ops->akm_write) {
 96		chip->ops->akm_write(chip, XX_CODEC_LEVEL_LEFT_REGISTER, left);
 97		chip->ops->akm_write(chip, XX_CODEC_LEVEL_RIGHT_REGISTER, right);
 98	} else {
 99		/* convert to attenuation level: 0 = 0dB (max), 0xe3 = -113.5 dB (min) */
100		vx_set_codec_reg(chip, codec, XX_CODEC_LEVEL_LEFT_REGISTER, left);
101		vx_set_codec_reg(chip, codec, XX_CODEC_LEVEL_RIGHT_REGISTER, right);
102	}
103}
104
105
106/*
107 * vx_toggle_dac_mute -  mute/unmute DAC
108 * @mute: 0 = unmute, 1 = mute
109 */
110
111#define DAC_ATTEN_MIN	0x08
112#define DAC_ATTEN_MAX	0x38
113
114void vx_toggle_dac_mute(struct vx_core *chip, int mute)
115{
116	unsigned int i;
117	for (i = 0; i < chip->hw->num_codecs; i++) {
118		if (chip->ops->akm_write)
119			chip->ops->akm_write(chip, XX_CODEC_DAC_CONTROL_REGISTER, mute); /* XXX */
120		else
121			vx_set_codec_reg(chip, i, XX_CODEC_DAC_CONTROL_REGISTER,
122					 mute ? DAC_ATTEN_MAX : DAC_ATTEN_MIN);
123	}
124}
125
126/*
127 * vx_reset_codec - reset and initialize the codecs
128 */
129void vx_reset_codec(struct vx_core *chip, int cold_reset)
130{
131	unsigned int i;
132	int port = chip->type >= VX_TYPE_VXPOCKET ? 0x75 : 0x65;
133
134	chip->ops->reset_codec(chip);
135
136	/* AKM codecs should be initialized in reset_codec callback */
137	if (! chip->ops->akm_write) {
138		/* initialize old codecs */
139		for (i = 0; i < chip->hw->num_codecs; i++) {
140			/* DAC control register (change level when zero crossing + mute) */
141			vx_set_codec_reg(chip, i, XX_CODEC_DAC_CONTROL_REGISTER, DAC_ATTEN_MAX);
142			/* ADC control register */
143			vx_set_codec_reg(chip, i, XX_CODEC_ADC_CONTROL_REGISTER, 0x00);
144			/* Port mode register */
145			vx_set_codec_reg(chip, i, XX_CODEC_PORT_MODE_REGISTER, port);
146			/* Clock control register */
147			vx_set_codec_reg(chip, i, XX_CODEC_CLOCK_CONTROL_REGISTER, 0x00);
148		}
149	}
150
151	/* mute analog output */
152	for (i = 0; i < chip->hw->num_codecs; i++) {
153		chip->output_level[i][0] = 0;
154		chip->output_level[i][1] = 0;
155		vx_set_analog_output_level(chip, i, 0, 0);
156	}
157}
158
159/*
160 * change the audio input source
161 * @src: the target source (VX_AUDIO_SRC_XXX)
162 */
163static void vx_change_audio_source(struct vx_core *chip, int src)
164{
165	if (chip->chip_status & VX_STAT_IS_STALE)
166		return;
167
168	guard(mutex)(&chip->lock);
169	chip->ops->change_audio_source(chip, src);
170}
171
172
173/*
174 * change the audio source if necessary and possible
175 * returns 1 if the source is actually changed.
176 */
177int vx_sync_audio_source(struct vx_core *chip)
178{
179	if (chip->audio_source_target == chip->audio_source ||
180	    chip->pcm_running)
181		return 0;
182	vx_change_audio_source(chip, chip->audio_source_target);
183	chip->audio_source = chip->audio_source_target;
184	return 1;
185}
186
187
188/*
189 * audio level, mute, monitoring
190 */
191struct vx_audio_level {
192	unsigned int has_level: 1;
193	unsigned int has_monitor_level: 1;
194	unsigned int has_mute: 1;
195	unsigned int has_monitor_mute: 1;
196	unsigned int mute;
197	unsigned int monitor_mute;
198	short level;
199	short monitor_level;
200};
201
202static int vx_adjust_audio_level(struct vx_core *chip, int audio, int capture,
203				 struct vx_audio_level *info)
204{
205	struct vx_rmh rmh;
206
207	if (chip->chip_status & VX_STAT_IS_STALE)
208		return -EBUSY;
209
210        vx_init_rmh(&rmh, CMD_AUDIO_LEVEL_ADJUST);
211	if (capture)
212		rmh.Cmd[0] |= COMMAND_RECORD_MASK;
213	/* Add Audio IO mask */
214	rmh.Cmd[1] = 1 << audio;
215	rmh.Cmd[2] = 0;
216	if (info->has_level) {
217		rmh.Cmd[0] |=  VALID_AUDIO_IO_DIGITAL_LEVEL;
218		rmh.Cmd[2] |= info->level;
219        }
220	if (info->has_monitor_level) {
221		rmh.Cmd[0] |=  VALID_AUDIO_IO_MONITORING_LEVEL;
222		rmh.Cmd[2] |= ((unsigned int)info->monitor_level << 10);
223        }
224	if (info->has_mute) { 
225		rmh.Cmd[0] |= VALID_AUDIO_IO_MUTE_LEVEL;
226		if (info->mute)
227			rmh.Cmd[2] |= AUDIO_IO_HAS_MUTE_LEVEL;
228	}
229	if (info->has_monitor_mute) {
230		/* validate flag for M2 at least to unmute it */ 
231		rmh.Cmd[0] |=  VALID_AUDIO_IO_MUTE_MONITORING_1 | VALID_AUDIO_IO_MUTE_MONITORING_2;
232		if (info->monitor_mute)
233			rmh.Cmd[2] |= AUDIO_IO_HAS_MUTE_MONITORING_1;
234	}
235
236	return vx_send_msg(chip, &rmh);
237}
238
239    
240#if 0 // not used
241static int vx_read_audio_level(struct vx_core *chip, int audio, int capture,
242			       struct vx_audio_level *info)
243{
244	int err;
245	struct vx_rmh rmh;
246
247	memset(info, 0, sizeof(*info));
248        vx_init_rmh(&rmh, CMD_GET_AUDIO_LEVELS);
249	if (capture)
250		rmh.Cmd[0] |= COMMAND_RECORD_MASK;
251	/* Add Audio IO mask */
252	rmh.Cmd[1] = 1 << audio;
253	err = vx_send_msg(chip, &rmh);
254	if (err < 0)
255		return err;
256	info.level = rmh.Stat[0] & MASK_DSP_WORD_LEVEL;
257	info.monitor_level = (rmh.Stat[0] >> 10) & MASK_DSP_WORD_LEVEL;
258	info.mute = (rmh.Stat[i] & AUDIO_IO_HAS_MUTE_LEVEL) ? 1 : 0;
259	info.monitor_mute = (rmh.Stat[i] & AUDIO_IO_HAS_MUTE_MONITORING_1) ? 1 : 0;
260	return 0;
261}
262#endif // not used
263
264/*
265 * set the monitoring level and mute state of the given audio
266 * no more static, because must be called from vx_pcm to demute monitoring
267 */
268int vx_set_monitor_level(struct vx_core *chip, int audio, int level, int active)
269{
270	struct vx_audio_level info;
271
272	memset(&info, 0, sizeof(info));
273	info.has_monitor_level = 1;
274	info.monitor_level = level;
275	info.has_monitor_mute = 1;
276	info.monitor_mute = !active;
277	chip->audio_monitor[audio] = level;
278	chip->audio_monitor_active[audio] = active;
279	return vx_adjust_audio_level(chip, audio, 0, &info); /* playback only */
280}
281
282
283/*
284 * set the mute status of the given audio
285 */
286static int vx_set_audio_switch(struct vx_core *chip, int audio, int active)
287{
288	struct vx_audio_level info;
289
290	memset(&info, 0, sizeof(info));
291	info.has_mute = 1;
292	info.mute = !active;
293	chip->audio_active[audio] = active;
294	return vx_adjust_audio_level(chip, audio, 0, &info); /* playback only */
295}
296
297/*
298 * set the mute status of the given audio
299 */
300static int vx_set_audio_gain(struct vx_core *chip, int audio, int capture, int level)
301{
302	struct vx_audio_level info;
303
304	memset(&info, 0, sizeof(info));
305	info.has_level = 1;
306	info.level = level;
307	chip->audio_gain[capture][audio] = level;
308	return vx_adjust_audio_level(chip, audio, capture, &info);
309}
310
311/*
312 * reset all audio levels
313 */
314static void vx_reset_audio_levels(struct vx_core *chip)
315{
316	unsigned int i, c;
317	struct vx_audio_level info;
318
319	memset(chip->audio_gain, 0, sizeof(chip->audio_gain));
320	memset(chip->audio_active, 0, sizeof(chip->audio_active));
321	memset(chip->audio_monitor, 0, sizeof(chip->audio_monitor));
322	memset(chip->audio_monitor_active, 0, sizeof(chip->audio_monitor_active));
323
324	for (c = 0; c < 2; c++) {
325		for (i = 0; i < chip->hw->num_ins * 2; i++) {
326			memset(&info, 0, sizeof(info));
327			if (c == 0) {
328				info.has_monitor_level = 1;
329				info.has_mute = 1;
330				info.has_monitor_mute = 1;
331			}
332			info.has_level = 1;
333			info.level = CVAL_0DB; /* default: 0dB */
334			vx_adjust_audio_level(chip, i, c, &info);
335			chip->audio_gain[c][i] = CVAL_0DB;
336			chip->audio_monitor[i] = CVAL_0DB;
337		}
338	}
339}
340
341
342/*
343 * VU, peak meter record
344 */
345
346#define VU_METER_CHANNELS	2
347
348struct vx_vu_meter {
349	int saturated;
350	int vu_level;
351	int peak_level;
352};
353
354/*
355 * get the VU and peak meter values
356 * @audio: the audio index
357 * @capture: 0 = playback, 1 = capture operation
358 * @info: the array of vx_vu_meter records (size = 2).
359 */
360static int vx_get_audio_vu_meter(struct vx_core *chip, int audio, int capture, struct vx_vu_meter *info)
361{
362	struct vx_rmh rmh;
363	int i, err;
364
365	if (chip->chip_status & VX_STAT_IS_STALE)
366		return -EBUSY;
367
368	vx_init_rmh(&rmh, CMD_AUDIO_VU_PIC_METER);
369	rmh.LgStat += 2 * VU_METER_CHANNELS;
370	if (capture)
371		rmh.Cmd[0] |= COMMAND_RECORD_MASK;
372    
373        /* Add Audio IO mask */
374	rmh.Cmd[1] = 0;
375	for (i = 0; i < VU_METER_CHANNELS; i++)
376		rmh.Cmd[1] |= 1 << (audio + i);
377	err = vx_send_msg(chip, &rmh);
378	if (err < 0)
379		return err;
380	/* Read response */
381	for (i = 0; i < 2 * VU_METER_CHANNELS; i +=2) {
382		info->saturated = (rmh.Stat[0] & (1 << (audio + i))) ? 1 : 0;
383		info->vu_level = rmh.Stat[i + 1];
384		info->peak_level = rmh.Stat[i + 2];
385		info++;
386	}
387	return 0;
388}
389   
390
391/*
392 * control API entries
393 */
394
395/*
396 * output level control
397 */
398static int vx_output_level_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
399{
400	struct vx_core *chip = snd_kcontrol_chip(kcontrol);
401	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
402	uinfo->count = 2;
403	uinfo->value.integer.min = 0;
404	uinfo->value.integer.max = chip->hw->output_level_max;
405	return 0;
406}
407
408static int vx_output_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
409{
410	struct vx_core *chip = snd_kcontrol_chip(kcontrol);
411	int codec = kcontrol->id.index;
412
413	guard(mutex)(&chip->mixer_mutex);
414	ucontrol->value.integer.value[0] = chip->output_level[codec][0];
415	ucontrol->value.integer.value[1] = chip->output_level[codec][1];
416	return 0;
417}
418
419static int vx_output_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
420{
421	struct vx_core *chip = snd_kcontrol_chip(kcontrol);
422	int codec = kcontrol->id.index;
423	unsigned int val[2], vmax;
424
425	vmax = chip->hw->output_level_max;
426	val[0] = ucontrol->value.integer.value[0];
427	val[1] = ucontrol->value.integer.value[1];
428	if (val[0] > vmax || val[1] > vmax)
429		return -EINVAL;
430	guard(mutex)(&chip->mixer_mutex);
431	if (val[0] != chip->output_level[codec][0] ||
432	    val[1] != chip->output_level[codec][1]) {
433		vx_set_analog_output_level(chip, codec, val[0], val[1]);
434		chip->output_level[codec][0] = val[0];
435		chip->output_level[codec][1] = val[1];
436		return 1;
437	}
438	return 0;
439}
440
441static const struct snd_kcontrol_new vx_control_output_level = {
442	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
443	.access =	(SNDRV_CTL_ELEM_ACCESS_READWRITE |
444			 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
445	.name =		"Master Playback Volume",
446	.info =		vx_output_level_info,
447	.get =		vx_output_level_get,
448	.put =		vx_output_level_put,
449	/* tlv will be filled later */
450};
451
452/*
453 * audio source select
454 */
455static int vx_audio_src_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
456{
457	static const char * const texts_mic[3] = {
458		"Digital", "Line", "Mic"
459	};
460	static const char * const texts_vx2[2] = {
461		"Digital", "Analog"
462	};
463	struct vx_core *chip = snd_kcontrol_chip(kcontrol);
464
465	if (chip->type >= VX_TYPE_VXPOCKET)
466		return snd_ctl_enum_info(uinfo, 1, 3, texts_mic);
467	else
468		return snd_ctl_enum_info(uinfo, 1, 2, texts_vx2);
469}
470
471static int vx_audio_src_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
472{
473	struct vx_core *chip = snd_kcontrol_chip(kcontrol);
474	ucontrol->value.enumerated.item[0] = chip->audio_source_target;
475	return 0;
476}
477
478static int vx_audio_src_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
479{
480	struct vx_core *chip = snd_kcontrol_chip(kcontrol);
481
482	if (chip->type >= VX_TYPE_VXPOCKET) {
483		if (ucontrol->value.enumerated.item[0] > 2)
484			return -EINVAL;
485	} else {
486		if (ucontrol->value.enumerated.item[0] > 1)
487			return -EINVAL;
488	}
489	guard(mutex)(&chip->mixer_mutex);
490	if (chip->audio_source_target != ucontrol->value.enumerated.item[0]) {
491		chip->audio_source_target = ucontrol->value.enumerated.item[0];
492		vx_sync_audio_source(chip);
493		return 1;
494	}
495	return 0;
496}
497
498static const struct snd_kcontrol_new vx_control_audio_src = {
499	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
500	.name =		"Capture Source",
501	.info =		vx_audio_src_info,
502	.get =		vx_audio_src_get,
503	.put =		vx_audio_src_put,
504};
505
506/*
507 * clock mode selection
508 */
509static int vx_clock_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
510{
511	static const char * const texts[3] = {
512		"Auto", "Internal", "External"
513	};
514
515	return snd_ctl_enum_info(uinfo, 1, 3, texts);
516}
517
518static int vx_clock_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
519{
520	struct vx_core *chip = snd_kcontrol_chip(kcontrol);
521	ucontrol->value.enumerated.item[0] = chip->clock_mode;
522	return 0;
523}
524
525static int vx_clock_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
526{
527	struct vx_core *chip = snd_kcontrol_chip(kcontrol);
528
529	if (ucontrol->value.enumerated.item[0] > 2)
530		return -EINVAL;
531	guard(mutex)(&chip->mixer_mutex);
532	if (chip->clock_mode != ucontrol->value.enumerated.item[0]) {
533		chip->clock_mode = ucontrol->value.enumerated.item[0];
534		vx_set_clock(chip, chip->freq);
535		return 1;
536	}
537	return 0;
538}
539
540static const struct snd_kcontrol_new vx_control_clock_mode = {
541	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
542	.name =		"Clock Mode",
543	.info =		vx_clock_mode_info,
544	.get =		vx_clock_mode_get,
545	.put =		vx_clock_mode_put,
546};
547
548/*
549 * Audio Gain
550 */
551static int vx_audio_gain_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
552{
553	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
554	uinfo->count = 2;
555	uinfo->value.integer.min = 0;
556	uinfo->value.integer.max = CVAL_MAX;
557	return 0;
558}
559
560static int vx_audio_gain_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
561{
562	struct vx_core *chip = snd_kcontrol_chip(kcontrol);
563	int audio = kcontrol->private_value & 0xff;
564	int capture = (kcontrol->private_value >> 8) & 1;
565
566	guard(mutex)(&chip->mixer_mutex);
567	ucontrol->value.integer.value[0] = chip->audio_gain[capture][audio];
568	ucontrol->value.integer.value[1] = chip->audio_gain[capture][audio+1];
569	return 0;
570}
571
572static int vx_audio_gain_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
573{
574	struct vx_core *chip = snd_kcontrol_chip(kcontrol);
575	int audio = kcontrol->private_value & 0xff;
576	int capture = (kcontrol->private_value >> 8) & 1;
577	unsigned int val[2];
578
579	val[0] = ucontrol->value.integer.value[0];
580	val[1] = ucontrol->value.integer.value[1];
581	if (val[0] > CVAL_MAX || val[1] > CVAL_MAX)
582		return -EINVAL;
583	guard(mutex)(&chip->mixer_mutex);
584	if (val[0] != chip->audio_gain[capture][audio] ||
585	    val[1] != chip->audio_gain[capture][audio+1]) {
586		vx_set_audio_gain(chip, audio, capture, val[0]);
587		vx_set_audio_gain(chip, audio+1, capture, val[1]);
588		return 1;
589	}
590	return 0;
591}
592
593static int vx_audio_monitor_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
594{
595	struct vx_core *chip = snd_kcontrol_chip(kcontrol);
596	int audio = kcontrol->private_value & 0xff;
597
598	guard(mutex)(&chip->mixer_mutex);
599	ucontrol->value.integer.value[0] = chip->audio_monitor[audio];
600	ucontrol->value.integer.value[1] = chip->audio_monitor[audio+1];
601	return 0;
602}
603
604static int vx_audio_monitor_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
605{
606	struct vx_core *chip = snd_kcontrol_chip(kcontrol);
607	int audio = kcontrol->private_value & 0xff;
608	unsigned int val[2];
609
610	val[0] = ucontrol->value.integer.value[0];
611	val[1] = ucontrol->value.integer.value[1];
612	if (val[0] > CVAL_MAX || val[1] > CVAL_MAX)
613		return -EINVAL;
614
615	guard(mutex)(&chip->mixer_mutex);
616	if (val[0] != chip->audio_monitor[audio] ||
617	    val[1] != chip->audio_monitor[audio+1]) {
618		vx_set_monitor_level(chip, audio, val[0],
619				     chip->audio_monitor_active[audio]);
620		vx_set_monitor_level(chip, audio+1, val[1],
621				     chip->audio_monitor_active[audio+1]);
622		return 1;
623	}
624	return 0;
625}
626
627#define vx_audio_sw_info	snd_ctl_boolean_stereo_info
628
629static int vx_audio_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
630{
631	struct vx_core *chip = snd_kcontrol_chip(kcontrol);
632	int audio = kcontrol->private_value & 0xff;
633
634	guard(mutex)(&chip->mixer_mutex);
635	ucontrol->value.integer.value[0] = chip->audio_active[audio];
636	ucontrol->value.integer.value[1] = chip->audio_active[audio+1];
637	return 0;
638}
639
640static int vx_audio_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
641{
642	struct vx_core *chip = snd_kcontrol_chip(kcontrol);
643	int audio = kcontrol->private_value & 0xff;
644
645	guard(mutex)(&chip->mixer_mutex);
646	if (ucontrol->value.integer.value[0] != chip->audio_active[audio] ||
647	    ucontrol->value.integer.value[1] != chip->audio_active[audio+1]) {
648		vx_set_audio_switch(chip, audio,
649				    !!ucontrol->value.integer.value[0]);
650		vx_set_audio_switch(chip, audio+1,
651				    !!ucontrol->value.integer.value[1]);
652		return 1;
653	}
654	return 0;
655}
656
657static int vx_monitor_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
658{
659	struct vx_core *chip = snd_kcontrol_chip(kcontrol);
660	int audio = kcontrol->private_value & 0xff;
661
662	guard(mutex)(&chip->mixer_mutex);
663	ucontrol->value.integer.value[0] = chip->audio_monitor_active[audio];
664	ucontrol->value.integer.value[1] = chip->audio_monitor_active[audio+1];
665	return 0;
666}
667
668static int vx_monitor_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
669{
670	struct vx_core *chip = snd_kcontrol_chip(kcontrol);
671	int audio = kcontrol->private_value & 0xff;
672
673	guard(mutex)(&chip->mixer_mutex);
674	if (ucontrol->value.integer.value[0] != chip->audio_monitor_active[audio] ||
675	    ucontrol->value.integer.value[1] != chip->audio_monitor_active[audio+1]) {
676		vx_set_monitor_level(chip, audio, chip->audio_monitor[audio],
677				     !!ucontrol->value.integer.value[0]);
678		vx_set_monitor_level(chip, audio+1, chip->audio_monitor[audio+1],
679				     !!ucontrol->value.integer.value[1]);
680		return 1;
681	}
682	return 0;
683}
684
685static const DECLARE_TLV_DB_SCALE(db_scale_audio_gain, -10975, 25, 0);
686
687static const struct snd_kcontrol_new vx_control_audio_gain = {
688	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
689	.access =	(SNDRV_CTL_ELEM_ACCESS_READWRITE |
690			 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
691	/* name will be filled later */
692	.info =         vx_audio_gain_info,
693	.get =          vx_audio_gain_get,
694	.put =          vx_audio_gain_put,
695	.tlv = { .p = db_scale_audio_gain },
696};
697static const struct snd_kcontrol_new vx_control_output_switch = {
698	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
699	.name =         "PCM Playback Switch",
700	.info =         vx_audio_sw_info,
701	.get =          vx_audio_sw_get,
702	.put =          vx_audio_sw_put
703};
704static const struct snd_kcontrol_new vx_control_monitor_gain = {
705	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
706	.name =         "Monitoring Volume",
707	.access =	(SNDRV_CTL_ELEM_ACCESS_READWRITE |
708			 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
709	.info =         vx_audio_gain_info,	/* shared */
710	.get =          vx_audio_monitor_get,
711	.put =          vx_audio_monitor_put,
712	.tlv = { .p = db_scale_audio_gain },
713};
714static const struct snd_kcontrol_new vx_control_monitor_switch = {
715	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
716	.name =         "Monitoring Switch",
717	.info =         vx_audio_sw_info,	/* shared */
718	.get =          vx_monitor_sw_get,
719	.put =          vx_monitor_sw_put
720};
721
722
723/*
724 * IEC958 status bits
725 */
726static int vx_iec958_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
727{
728	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
729	uinfo->count = 1;
730	return 0;
731}
732
733static int vx_iec958_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
734{
735	struct vx_core *chip = snd_kcontrol_chip(kcontrol);
736
737	guard(mutex)(&chip->mixer_mutex);
738	ucontrol->value.iec958.status[0] = (chip->uer_bits >> 0) & 0xff;
739	ucontrol->value.iec958.status[1] = (chip->uer_bits >> 8) & 0xff;
740	ucontrol->value.iec958.status[2] = (chip->uer_bits >> 16) & 0xff;
741	ucontrol->value.iec958.status[3] = (chip->uer_bits >> 24) & 0xff;
742        return 0;
743}
744
745static int vx_iec958_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
746{
747	ucontrol->value.iec958.status[0] = 0xff;
748	ucontrol->value.iec958.status[1] = 0xff;
749	ucontrol->value.iec958.status[2] = 0xff;
750	ucontrol->value.iec958.status[3] = 0xff;
751        return 0;
752}
753
754static int vx_iec958_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
755{
756	struct vx_core *chip = snd_kcontrol_chip(kcontrol);
757	unsigned int val;
758
759	val = (ucontrol->value.iec958.status[0] << 0) |
760	      (ucontrol->value.iec958.status[1] << 8) |
761	      (ucontrol->value.iec958.status[2] << 16) |
762	      (ucontrol->value.iec958.status[3] << 24);
763	guard(mutex)(&chip->mixer_mutex);
764	if (chip->uer_bits != val) {
765		chip->uer_bits = val;
766		vx_set_iec958_status(chip, val);
767		return 1;
768	}
769	return 0;
770}
771
772static const struct snd_kcontrol_new vx_control_iec958_mask = {
773	.access =	SNDRV_CTL_ELEM_ACCESS_READ,
774	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
775	.name =		SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
776	.info =		vx_iec958_info,	/* shared */
777	.get =		vx_iec958_mask_get,
778};
779
780static const struct snd_kcontrol_new vx_control_iec958 = {
781	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
782	.name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
783	.info =         vx_iec958_info,
784	.get =          vx_iec958_get,
785	.put =          vx_iec958_put
786};
787
788
789/*
790 * VU meter
791 */
792
793#define METER_MAX	0xff
794#define METER_SHIFT	16
795
796static int vx_vu_meter_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
797{
798	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
799	uinfo->count = 2;
800	uinfo->value.integer.min = 0;
801	uinfo->value.integer.max = METER_MAX;
802	return 0;
803}
804
805static int vx_vu_meter_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
806{
807	struct vx_core *chip = snd_kcontrol_chip(kcontrol);
808	struct vx_vu_meter meter[2];
809	int audio = kcontrol->private_value & 0xff;
810	int capture = (kcontrol->private_value >> 8) & 1;
811
812	vx_get_audio_vu_meter(chip, audio, capture, meter);
813	ucontrol->value.integer.value[0] = meter[0].vu_level >> METER_SHIFT;
814	ucontrol->value.integer.value[1] = meter[1].vu_level >> METER_SHIFT;
815	return 0;
816}
817
818static int vx_peak_meter_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
819{
820	struct vx_core *chip = snd_kcontrol_chip(kcontrol);
821	struct vx_vu_meter meter[2];
822	int audio = kcontrol->private_value & 0xff;
823	int capture = (kcontrol->private_value >> 8) & 1;
824
825	vx_get_audio_vu_meter(chip, audio, capture, meter);
826	ucontrol->value.integer.value[0] = meter[0].peak_level >> METER_SHIFT;
827	ucontrol->value.integer.value[1] = meter[1].peak_level >> METER_SHIFT;
828	return 0;
829}
830
831#define vx_saturation_info	snd_ctl_boolean_stereo_info
832
833static int vx_saturation_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
834{
835	struct vx_core *chip = snd_kcontrol_chip(kcontrol);
836	struct vx_vu_meter meter[2];
837	int audio = kcontrol->private_value & 0xff;
838
839	vx_get_audio_vu_meter(chip, audio, 1, meter); /* capture only */
840	ucontrol->value.integer.value[0] = meter[0].saturated;
841	ucontrol->value.integer.value[1] = meter[1].saturated;
842	return 0;
843}
844
845static const struct snd_kcontrol_new vx_control_vu_meter = {
846	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
847	.access =	SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
848	/* name will be filled later */
849	.info =		vx_vu_meter_info,
850	.get =		vx_vu_meter_get,
851};
852
853static const struct snd_kcontrol_new vx_control_peak_meter = {
854	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
855	.access =	SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
856	/* name will be filled later */
857	.info =		vx_vu_meter_info,	/* shared */
858	.get =		vx_peak_meter_get,
859};
860
861static const struct snd_kcontrol_new vx_control_saturation = {
862	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
863	.name =		"Input Saturation",
864	.access =	SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
865	.info =		vx_saturation_info,
866	.get =		vx_saturation_get,
867};
868
869
870
871/*
872 *
873 */
874
875int snd_vx_mixer_new(struct vx_core *chip)
876{
877	unsigned int i, c;
878	int err;
879	struct snd_kcontrol_new temp;
880	struct snd_card *card = chip->card;
881	char name[32];
882
883	strscpy(card->mixername, card->driver);
884
885	/* output level controls */
886	for (i = 0; i < chip->hw->num_outs; i++) {
887		temp = vx_control_output_level;
888		temp.index = i;
889		temp.tlv.p = chip->hw->output_level_db_scale;
890		err = snd_ctl_add(card, snd_ctl_new1(&temp, chip));
891		if (err < 0)
892			return err;
893	}
894
895	/* PCM volumes, switches, monitoring */
896	for (i = 0; i < chip->hw->num_outs; i++) {
897		int val = i * 2;
898		temp = vx_control_audio_gain;
899		temp.index = i;
900		temp.name = "PCM Playback Volume";
901		temp.private_value = val;
902		err = snd_ctl_add(card, snd_ctl_new1(&temp, chip));
903		if (err < 0)
904			return err;
905		temp = vx_control_output_switch;
906		temp.index = i;
907		temp.private_value = val;
908		err = snd_ctl_add(card, snd_ctl_new1(&temp, chip));
909		if (err < 0)
910			return err;
911		temp = vx_control_monitor_gain;
912		temp.index = i;
913		temp.private_value = val;
914		err = snd_ctl_add(card, snd_ctl_new1(&temp, chip));
915		if (err < 0)
916			return err;
917		temp = vx_control_monitor_switch;
918		temp.index = i;
919		temp.private_value = val;
920		err = snd_ctl_add(card, snd_ctl_new1(&temp, chip));
921		if (err < 0)
922			return err;
923	}
924	for (i = 0; i < chip->hw->num_outs; i++) {
925		temp = vx_control_audio_gain;
926		temp.index = i;
927		temp.name = "PCM Capture Volume";
928		temp.private_value = (i * 2) | (1 << 8);
929		err = snd_ctl_add(card, snd_ctl_new1(&temp, chip));
930		if (err < 0)
931			return err;
932	}
933
934	/* Audio source */
935	err = snd_ctl_add(card, snd_ctl_new1(&vx_control_audio_src, chip));
936	if (err < 0)
937		return err;
938	/* clock mode */
939	err = snd_ctl_add(card, snd_ctl_new1(&vx_control_clock_mode, chip));
940	if (err < 0)
941		return err;
942	/* IEC958 controls */
943	err = snd_ctl_add(card, snd_ctl_new1(&vx_control_iec958_mask, chip));
944	if (err < 0)
945		return err;
946	err = snd_ctl_add(card, snd_ctl_new1(&vx_control_iec958, chip));
947	if (err < 0)
948		return err;
949	/* VU, peak, saturation meters */
950	for (c = 0; c < 2; c++) {
951		static const char * const dir[2] = { "Output", "Input" };
952		for (i = 0; i < chip->hw->num_ins; i++) {
953			int val = (i * 2) | (c << 8);
954			if (c == 1) {
955				temp = vx_control_saturation;
956				temp.index = i;
957				temp.private_value = val;
958				err = snd_ctl_add(card, snd_ctl_new1(&temp, chip));
959				if (err < 0)
960					return err;
961			}
962			sprintf(name, "%s VU Meter", dir[c]);
963			temp = vx_control_vu_meter;
964			temp.index = i;
965			temp.name = name;
966			temp.private_value = val;
967			err = snd_ctl_add(card, snd_ctl_new1(&temp, chip));
968			if (err < 0)
969				return err;
970			sprintf(name, "%s Peak Meter", dir[c]);
971			temp = vx_control_peak_meter;
972			temp.index = i;
973			temp.name = name;
974			temp.private_value = val;
975			err = snd_ctl_add(card, snd_ctl_new1(&temp, chip));
976			if (err < 0)
977				return err;
978		}
979	}
980	vx_reset_audio_levels(chip);
981	return 0;
982}
~/ Read-only file preview.