1/*-
2 * Copyright (c) 2012 The NetBSD Foundation, Inc.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to The NetBSD Foundation
6 * by Paul Fleischer <paul@xpg.dk>
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
31
32#include <sys/param.h>
33#include <sys/device.h>
34#include <sys/audioio.h>
35#include <sys/fcntl.h>
36
37#include <dev/audio_if.h>
38
39#include <dev/ic/uda1341var.h>
40#include <dev/ic/uda1341reg.h>
41
42/*#define UDA1341_DEBUG*/
43
44#ifdef UDA1341_DEBUG
45#define DPRINTF(x) do {printf x; } while (/*CONSTCOND*/0)
46#else
47#define DPRINTF(s) do {} while (/*CONSTCOND*/0)
48#endif
49
50const struct audio_format uda1341_formats[UDA1341_NFORMATS] =
51{
52	{NULL, AUMODE_PLAY|AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 8, 8, 2,
53	 AUFMT_STEREO, 0, {8000, 48000}
54	},
55	{NULL, AUMODE_PLAY|AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 16, 16, 2,
56	 AUFMT_STEREO, 0, {8000, 48000}
57	},
58	{NULL, AUMODE_PLAY|AUMODE_RECORD, AUDIO_ENCODING_ULINEAR_LE, 8, 8, 2,
59	 AUFMT_STEREO, 0, {8000, 48000}
60	},
61	{NULL, AUMODE_PLAY|AUMODE_RECORD, AUDIO_ENCODING_ULINEAR_LE, 16, 16, 2,
62	 AUFMT_STEREO, 0, {8000, 48000}
63	},
64};
65
66static void uda1341_update_sound_settings(struct uda1341_softc *sc);
67
68
69int
70uda1341_attach(struct uda1341_softc *sc)
71{
72	sc->sc_system_clock = UDA1341_CLOCK_NA;
73	sc->sc_l3_write = NULL;
74	sc->sc_volume = 127;
75	sc->sc_bass = 0;
76	sc->sc_treble = 0;
77	sc->sc_mode = 0;
78	sc->sc_mute = 0;
79	sc->sc_ogain = 0;
80	sc->sc_deemphasis = UDA1341_DEEMPHASIS_AUTO;
81	sc->sc_dac_power = 0;
82	sc->sc_adc_power = 0;
83	sc->sc_inmix1 = 0;
84	sc->sc_inmix2 = 0;
85	sc->sc_micvol = 0;
86	sc->sc_inmode = 0;
87	sc->sc_agc = 0;
88	sc->sc_agc_lvl = 0;
89	sc->sc_ch2_gain = 0;
90
91	return 0;
92}
93
94int
95uda1341_query_encodings(void *handle, audio_encoding_t *ae)
96{
97	switch(ae->index) {
98	case 0:
99		strlcpy(ae->name, AudioEmulaw, sizeof(ae->name));
100		ae->encoding = AUDIO_ENCODING_ULAW;
101		ae->precision = 8;
102		ae->flags = AUDIO_ENCODINGFLAG_EMULATED;
103		break;
104	case 1:
105		strlcpy(ae->name, AudioEslinear_le, sizeof(ae->name));
106		ae->encoding = AUDIO_ENCODING_SLINEAR_LE;
107		ae->precision = 8;
108		ae->flags = 0;
109		break;
110	case 2:
111		strlcpy(ae->name, AudioEslinear_le, sizeof(ae->name));
112		ae->encoding = AUDIO_ENCODING_SLINEAR_LE;
113		ae->precision = 16;
114		ae->flags = 0;
115		break;
116	case 3:
117		strlcpy(ae->name, AudioEulinear_le, sizeof(ae->name));
118		ae->encoding = AUDIO_ENCODING_ULINEAR_LE;
119		ae->precision = 8;
120		ae->flags = 0;
121		break;
122	case 4:
123		strlcpy(ae->name, AudioEulinear_le, sizeof(ae->name));
124		ae->encoding = AUDIO_ENCODING_ULINEAR_LE;
125		ae->precision = 16;
126		ae->flags = 0;
127		break;
128
129	default:
130		return EINVAL;
131	}
132
133	return 0;
134}
135
136int
137uda1341_open(void *handle, int flags)
138{
139	struct uda1341_softc *sc = handle;
140
141	/* Reset the UDA1341 */
142	sc->sc_l3_write(sc, 0, UDA1341_L3_ADDR_DEVICE |
143			UDA1341_L3_ADDR_STATUS);
144	sc->sc_l3_write(sc, 1,
145			UDA1341_L3_STATUS0 |
146			UDA1341_L3_STATUS0_RST);
147
148	if (flags & FREAD) {
149		sc->sc_adc_power = 1;
150	}
151	if (flags & FWRITE) {
152		sc->sc_dac_power = 1;
153	}
154
155#if 0
156	/* Power on DAC */
157	sc->sc_l3_write(sc, 1,
158			UDA1341_L3_STATUS1 | UDA1341_L3_STATUS1_PC_DAC);
159#endif
160	uda1341_update_sound_settings(sc);
161
162#if 0
163	/* TODO: Add mixer support */
164	sc->sc_l3_write(sc, 0, 0x14 | 0x0);
165	sc->sc_l3_write(sc, 1, 0x15);  /* Volume */
166#endif
167
168	return 0;
169}
170
171void
172uda1341_close(void *handle)
173{
174	struct uda1341_softc *sc = handle;
175	/* Reset the UDA1341 */
176	sc->sc_l3_write(sc, 0, UDA1341_L3_ADDR_DEVICE |
177			UDA1341_L3_ADDR_STATUS);
178
179	/* Power off DAC and ADC*/
180	sc->sc_l3_write(sc, 1,
181			UDA1341_L3_STATUS1);
182
183	sc->sc_dac_power = 0;
184	sc->sc_adc_power = 0;
185}
186
187int
188uda1341_set_params(void *handle, int setmode, int usemode,
189		   audio_params_t *play, audio_params_t *rec,
190		   stream_filter_list_t *pfil, stream_filter_list_t *rfil)
191{
192	struct uda1341_softc *sc = handle;
193	if (sc->sc_system_clock == UDA1341_CLOCK_NA)
194		panic("uda1341_set_params was called without sc_system_clock set!\n");
195
196	/* Select status register */
197	sc->sc_l3_write(sc, 0, UDA1341_L3_ADDR_DEVICE |
198			UDA1341_L3_ADDR_STATUS);
199
200	sc->sc_l3_write(sc, 1, UDA1341_L3_STATUS0 |
201			sc->sc_system_clock << UDA1341_L3_STATUS0_SC_SHIFT |
202			sc->sc_bus_format << UDA1341_L3_STATUS0_IF_SHIFT
203			);
204
205	if (sc->sc_sample_rate_approx != play->sample_rate) {
206		sc->sc_sample_rate_approx = play->sample_rate;
207		uda1341_update_sound_settings(sc);
208	}
209
210	return 0;
211}
212
213#define AUDIO_LEVELS	(AUDIO_MAX_GAIN-AUDIO_MIN_GAIN+1)
214static void
215uda1341_update_sound_settings(struct uda1341_softc *sc)
216{
217	/* TODO: Refactor this function into smaller parts, such that
218	 * a volume change does not trigger updates of all the
219	 * other -- unrelated -- registers.
220	 */
221
222	uint8_t val, volume, bass, treble, deemphasis;
223
224	sc->sc_l3_write(sc, 0, UDA1341_L3_ADDR_DEVICE | UDA1341_L3_ADDR_STATUS);
225	val = UDA1341_L3_STATUS1;
226	if (sc->sc_dac_power)
227		val |= UDA1341_L3_STATUS1_PC_DAC;
228	if (sc->sc_adc_power)
229		val |= UDA1341_L3_STATUS1_PC_ADC;
230	if (sc->sc_ogain)
231		val |= UDA1341_L3_STATUS1_OGS_6DB;
232
233	sc->sc_l3_write(sc, 1, val);
234
235	sc->sc_l3_write(sc, 0, UDA1341_L3_ADDR_DEVICE | UDA1341_L3_ADDR_DATA0);
236
237	/* Update volume */
238	/* On the UDA1341 maximal volume is 0x0,
239	   while minimal volume is 0x3f */
240	volume = (0x3f) - ((sc->sc_volume*(0x3f+1)) / (AUDIO_LEVELS));
241
242	val = UDA1341_L3_DATA0_VOLUME;
243	val |= volume & UDA1341_L3_DATA0_VOLUME_MASK;
244	sc->sc_l3_write(sc, 1, val);
245
246	/* Update bass and treble */
247	bass = (sc->sc_bass*(0xf+1)) / AUDIO_LEVELS;
248	treble = (sc->sc_treble*(0x3+1)) / AUDIO_LEVELS;
249	val = UDA1341_L3_DATA0_BASS_TREBLE;
250	val |= (bass << UDA1341_L3_DATA0_BASS_SHIFT) &
251		UDA1341_L3_DATA0_BASS_MASK;
252	val |= (treble << UDA1341_L3_DATA0_TREBLE_SHIFT) &
253		UDA1341_L3_DATA0_TREBLE_MASK;
254	sc->sc_l3_write(sc, 1, val);
255
256	/* Update the remaining output sound controls:
257	 * - Peak-detect position
258	 * - De-emphasis
259	 * - Mute
260	 * - Mode Switch
261	 * XXX: Only Mode-switch, de-emphasis, and mute is currently supported.
262	 */
263	val = UDA1341_L3_DATA0_SOUNDC;
264
265	deemphasis = sc->sc_deemphasis;
266	if( deemphasis == UDA1341_DEEMPHASIS_AUTO) {
267		/* Set deemphasis according to current sample rate */
268		switch (sc->sc_sample_rate_approx) {
269		case 32000:
270			deemphasis = 0x1;
271			break;
272		case 44100:
273			deemphasis = 0x2;
274			break;
275		case 48000:
276			deemphasis = 0x3;
277			break;
278		default:
279			deemphasis = 0x0;
280		}
281	}
282
283	DPRINTF(("Deemphasis: %d\n", deemphasis));
284	val |= (deemphasis << UDA1341_L3_DATA0_SOUNDC_DE_SHIFT) &
285		UDA1341_L3_DATA0_SOUNDC_DE_MASK;
286
287	if (sc->sc_mute)
288		val |= UDA1341_L3_DATA0_SOUNDC_MUTE;
289	val |= sc->sc_mode & UDA1341_L3_DATA0_SOUNDC_MODE_MASK;
290	sc->sc_l3_write(sc, 1, val);
291
292	/* Extended Register 0: MA */
293	val = UDA1341_L3_DATA0_ED;
294	val |= (sc->sc_inmix1 & UDA1341_L3_DATA0_MA_MASK);
295	sc->sc_l3_write(sc, 1, UDA1341_L3_DATA0_EA | 0x0);
296	sc->sc_l3_write(sc, 1, val);
297
298	/* Extended Register 1: MB */
299	val = UDA1341_L3_DATA0_ED;
300	val |= (sc->sc_inmix2 & UDA1341_L3_DATA0_MB_MASK);
301	sc->sc_l3_write(sc, 1, UDA1341_L3_DATA0_EA | 0x01);
302	sc->sc_l3_write(sc, 1, val);
303
304	/* Extended Register 2: MIC sensitivity and mixer mode  */
305	val = UDA1341_L3_DATA0_ED;
306	val |= (sc->sc_micvol << UDA1341_L3_DATA0_MS_SHIFT) &
307		UDA1341_L3_DATA0_MS_MASK;
308	val |= sc->sc_inmode & UDA1341_L3_DATA0_MM_MASK;
309	sc->sc_l3_write(sc, 1, UDA1341_L3_DATA0_EA | 0x02);
310	sc->sc_l3_write(sc, 1, val);
311
312	/* Extended Register 4: AGC and IG (ch2_gain) */
313	val = UDA1341_L3_DATA0_ED;
314
315	val |= (sc->sc_agc << UDA1341_L3_DATA0_AGC_SHIFT) &
316		UDA1341_L3_DATA0_AGC_MASK;
317	val |= (sc->sc_ch2_gain & 0x03) & UDA1341_L3_DATA0_IG_LOW_MASK;
318	sc->sc_l3_write(sc, 1, UDA1341_L3_DATA0_EA | 0x04);
319	sc->sc_l3_write(sc, 1, val);
320
321	/* Extended Register 5: IG (ch2_gain) */
322	val = UDA1341_L3_DATA0_ED;
323	val |= (sc->sc_ch2_gain >> 2 ) & UDA1341_L3_DATA0_IG_HIGH_MASK;
324	sc->sc_l3_write(sc, 1, UDA1341_L3_DATA0_EA | 0x05);
325	sc->sc_l3_write(sc, 1, val);
326
327	/* Extended Register 6: AT and AL */
328	/* XXX: Only AL is supported at this point */
329	val = UDA1341_L3_DATA0_ED;
330	val |= sc->sc_agc_lvl & UDA1341_L3_DATA0_AL_MASK;
331	sc->sc_l3_write(sc, 1, UDA1341_L3_DATA0_EA | 0x06);
332	sc->sc_l3_write(sc, 1, val);
333}
334
335#define UDA1341_MIXER_VOL	0
336#define UDA1341_MIXER_BASS	1
337#define UDA1341_MIXER_TREBLE	2
338#define UDA1341_MIXER_MODE	3
339#define UDA1341_MIXER_MUTE	4
340#define UDA1341_MIXER_OGAIN	5
341#define UDA1341_MIXER_DE	6
342#define UDA1341_OUTPUT_CLASS	7
343
344#define UDA1341_MIXER_INMIX1	8
345#define UDA1341_MIXER_INMIX2	9
346#define UDA1341_MIXER_MICVOL	10
347#define UDA1341_MIXER_INMODE	11
348#define UDA1341_MIXER_AGC	12
349#define UDA1341_MIXER_AGC_LVL	13
350#define UDA1341_MIXER_IN_GAIN2	14
351/*#define UDA1341_MIXER_AGC_SETTINGS 15*/
352#define UDA1341_INPUT_CLASS	15
353
354int
355uda1341_query_devinfo(void *handle, mixer_devinfo_t *mi)
356{
357
358	switch(mi->index) {
359	case UDA1341_MIXER_VOL:
360		strlcpy(mi->label.name, AudioNspeaker,
361			sizeof(mi->label.name));
362		mi->type = AUDIO_MIXER_VALUE;
363		mi->mixer_class = UDA1341_OUTPUT_CLASS;
364		mi->next = UDA1341_MIXER_BASS;
365		mi->prev = AUDIO_MIXER_LAST;
366		strlcpy(mi->un.v.units.name, AudioNvolume,
367			sizeof(mi->un.v.units.name));
368		mi->un.v.num_channels = 1;
369		mi->un.v.delta = 256/64;
370		break;
371	case UDA1341_MIXER_BASS:
372		strlcpy(mi->label.name, AudioNbass,
373			sizeof(mi->label.name));
374		mi->type = AUDIO_MIXER_VALUE;
375		mi->mixer_class = UDA1341_OUTPUT_CLASS;
376		mi->next = UDA1341_MIXER_TREBLE;
377		mi->prev = UDA1341_MIXER_VOL;
378		strlcpy(mi->un.v.units.name, AudioNbass,
379			sizeof(mi->un.v.units.name));
380		mi->un.v.num_channels = 1;
381		mi->un.v.delta = 256/16;
382		break;
383	case UDA1341_MIXER_TREBLE:
384		strlcpy(mi->label.name, AudioNtreble,
385			sizeof(mi->label.name));
386		mi->type = AUDIO_MIXER_VALUE;
387		mi->mixer_class = UDA1341_OUTPUT_CLASS;
388		mi->next = UDA1341_MIXER_MODE;
389		mi->prev = UDA1341_MIXER_BASS;
390		strlcpy(mi->un.v.units.name, AudioNtreble,
391			sizeof(mi->un.v.units.name));
392		mi->un.v.num_channels = 1;
393		mi->un.v.delta = 256/4;
394		break;
395	case UDA1341_MIXER_MODE:
396		strlcpy(mi->label.name, AudioNmode,
397			sizeof(mi->label.name));
398		mi->type = AUDIO_MIXER_ENUM;
399		mi->mixer_class = UDA1341_OUTPUT_CLASS;
400		mi->next = UDA1341_MIXER_MUTE;
401		mi->prev = UDA1341_MIXER_TREBLE;
402		mi->un.e.num_mem = 3;
403
404		strlcpy(mi->un.e.member[0].label.name,
405			"flat", sizeof(mi->un.e.member[0].label.name));
406		mi->un.e.member[0].ord = 0;
407
408		strlcpy(mi->un.e.member[1].label.name,
409			"minimum", sizeof(mi->un.e.member[1].label.name));
410		mi->un.e.member[1].ord = 1;
411
412		strlcpy(mi->un.e.member[2].label.name,
413			"maximum", sizeof(mi->un.e.member[2].label.name));
414		mi->un.e.member[2].ord = 3;
415
416		break;
417	case UDA1341_MIXER_MUTE:
418		strlcpy(mi->label.name, AudioNmute,
419			sizeof(mi->label.name));
420		mi->type = AUDIO_MIXER_ENUM;
421		mi->mixer_class = UDA1341_OUTPUT_CLASS;
422		mi->next = UDA1341_MIXER_OGAIN;
423		mi->prev = UDA1341_MIXER_MODE;
424		mi->un.e.num_mem = 2;
425
426		strlcpy(mi->un.e.member[0].label.name,
427			"off", sizeof(mi->un.e.member[0].label.name));
428		mi->un.e.member[0].ord = 0;
429
430		strlcpy(mi->un.e.member[1].label.name,
431			"on", sizeof(mi->un.e.member[1].label.name));
432		mi->un.e.member[1].ord = 1;
433		break;
434	case UDA1341_MIXER_OGAIN:
435		strlcpy(mi->label.name, "gain",
436			sizeof(mi->label.name));
437		mi->type = AUDIO_MIXER_ENUM;
438		mi->mixer_class = UDA1341_OUTPUT_CLASS;
439		mi->next = UDA1341_MIXER_DE;
440		mi->prev = UDA1341_MIXER_MUTE;
441		mi->un.e.num_mem = 2;
442
443		strlcpy(mi->un.e.member[0].label.name,
444			"off", sizeof(mi->un.e.member[0].label.name));
445		mi->un.e.member[0].ord = 0;
446
447		strlcpy(mi->un.e.member[1].label.name,
448			"on", sizeof(mi->un.e.member[1].label.name));
449		mi->un.e.member[1].ord = 1;
450		break;
451	case UDA1341_MIXER_DE:
452		strlcpy(mi->label.name, "deemphasis",
453			sizeof(mi->label.name));
454		mi->type = AUDIO_MIXER_ENUM;
455		mi->mixer_class = UDA1341_OUTPUT_CLASS;
456		mi->next = AUDIO_MIXER_LAST;
457		mi->prev = UDA1341_MIXER_OGAIN;
458		mi->un.e.num_mem = 5;
459
460		strlcpy(mi->un.e.member[0].label.name,
461			"none", sizeof(mi->un.e.member[0].label.name));
462		mi->un.e.member[0].ord = 0;
463
464		strlcpy(mi->un.e.member[1].label.name,
465			"32KHz", sizeof(mi->un.e.member[1].label.name));
466		mi->un.e.member[1].ord = 1;
467
468		strlcpy(mi->un.e.member[2].label.name,
469			"44.1KHz", sizeof(mi->un.e.member[2].label.name));
470		mi->un.e.member[2].ord = 2;
471
472		strlcpy(mi->un.e.member[3].label.name,
473			"48KHz", sizeof(mi->un.e.member[3].label.name));
474		mi->un.e.member[3].ord = 3;
475
476		strlcpy(mi->un.e.member[4].label.name,
477			"auto", sizeof(mi->un.e.member[4].label.name));
478		mi->un.e.member[4].ord = 4;
479
480		break;
481	case UDA1341_OUTPUT_CLASS:
482		mi->type = AUDIO_MIXER_CLASS;
483		mi->mixer_class = UDA1341_OUTPUT_CLASS;
484		mi->prev = AUDIO_MIXER_LAST;
485		mi->next = AUDIO_MIXER_LAST;
486		strlcpy(mi->label.name, AudioCoutputs,
487			sizeof(mi->label.name));
488		break;
489	case UDA1341_MIXER_INMIX1:
490		strlcpy(mi->label.name, "inmix1",
491			sizeof(mi->label.name));
492		mi->type = AUDIO_MIXER_VALUE;
493		mi->mixer_class = UDA1341_INPUT_CLASS;
494		mi->next = AUDIO_MIXER_LAST;
495		mi->prev = AUDIO_MIXER_LAST;
496		strlcpy(mi->un.v.units.name, AudioNvolume,
497			sizeof(mi->un.v.units.name));
498		mi->un.v.num_channels = 1;
499		mi->un.v.delta = 256/64;
500		break;
501	case UDA1341_MIXER_INMIX2:
502		strlcpy(mi->label.name, "inmix2",
503			sizeof(mi->label.name));
504		mi->type = AUDIO_MIXER_VALUE;
505		mi->mixer_class = UDA1341_INPUT_CLASS;
506		mi->next = AUDIO_MIXER_LAST;
507		mi->prev = AUDIO_MIXER_LAST;
508		strlcpy(mi->un.v.units.name, AudioNvolume,
509			sizeof(mi->un.v.units.name));
510		mi->un.v.num_channels = 1;
511		mi->un.v.delta = 256/64;
512		break;
513	case UDA1341_MIXER_MICVOL:
514		strlcpy(mi->label.name, AudioNmicrophone,
515			sizeof(mi->label.name));
516		mi->type = AUDIO_MIXER_VALUE;
517		mi->mixer_class = UDA1341_INPUT_CLASS;
518		mi->next = AUDIO_MIXER_LAST;
519		mi->prev = AUDIO_MIXER_LAST;
520		strlcpy(mi->un.v.units.name, AudioNvolume,
521			sizeof(mi->un.v.units.name));
522		mi->un.v.num_channels = 1;
523		mi->un.v.delta = 256/8;
524		break;
525	case UDA1341_MIXER_INMODE:
526		strlcpy(mi->label.name, "inmode",
527			sizeof(mi->label.name));
528		mi->type = AUDIO_MIXER_ENUM;
529		mi->mixer_class = UDA1341_INPUT_CLASS;
530		mi->next = AUDIO_MIXER_LAST;
531		mi->prev = AUDIO_MIXER_LAST;
532		mi->un.e.num_mem = 4;
533
534		strlcpy(mi->un.e.member[0].label.name,
535			"dd", sizeof(mi->un.e.member[0].label.name));
536		mi->un.e.member[0].ord = 0;
537
538		strlcpy(mi->un.e.member[1].label.name,
539			"ch1", sizeof(mi->un.e.member[1].label.name));
540		mi->un.e.member[1].ord = 1;
541
542		strlcpy(mi->un.e.member[2].label.name,
543			"ch2", sizeof(mi->un.e.member[2].label.name));
544		mi->un.e.member[2].ord = 2;
545
546		strlcpy(mi->un.e.member[3].label.name,
547			"mix", sizeof(mi->un.e.member[3].label.name));
548		mi->un.e.member[3].ord = 3;
549		break;
550	case UDA1341_MIXER_AGC:
551		strlcpy(mi->label.name, "agc",
552			sizeof(mi->label.name));
553		mi->type = AUDIO_MIXER_ENUM;
554		mi->mixer_class = UDA1341_INPUT_CLASS;
555		mi->next = AUDIO_MIXER_LAST;
556		mi->prev = AUDIO_MIXER_LAST;
557		mi->un.e.num_mem = 2;
558
559		strlcpy(mi->un.e.member[0].label.name,
560			"off", sizeof(mi->un.e.member[0].label.name));
561		mi->un.e.member[0].ord = 0;
562
563		strlcpy(mi->un.e.member[1].label.name,
564			"on", sizeof(mi->un.e.member[1].label.name));
565		mi->un.e.member[1].ord = 1;
566		break;
567	case UDA1341_MIXER_AGC_LVL:
568		strlcpy(mi->label.name, "agclevel",
569			sizeof(mi->label.name));
570		mi->type = AUDIO_MIXER_VALUE;
571		mi->mixer_class = UDA1341_INPUT_CLASS;
572		mi->next = AUDIO_MIXER_LAST;
573		mi->prev = AUDIO_MIXER_LAST;
574		strlcpy(mi->un.v.units.name, AudioNvolume,
575			sizeof(mi->un.v.units.name));
576		mi->un.v.num_channels = 1;
577		mi->un.v.delta = 256/4;
578		break;
579	case UDA1341_MIXER_IN_GAIN2:
580		strlcpy(mi->label.name, "ch2gain",
581			sizeof(mi->label.name));
582		mi->type = AUDIO_MIXER_VALUE;
583		mi->mixer_class = UDA1341_INPUT_CLASS;
584		mi->next = AUDIO_MIXER_LAST;
585		mi->prev = AUDIO_MIXER_LAST;
586		strlcpy(mi->un.v.units.name, AudioNvolume,
587			sizeof(mi->un.v.units.name));
588		mi->un.v.num_channels = 1;
589		mi->un.v.delta = 256/128;
590		break;
591	case UDA1341_INPUT_CLASS:
592		mi->type = AUDIO_MIXER_CLASS;
593		mi->mixer_class = UDA1341_INPUT_CLASS;
594		mi->prev = AUDIO_MIXER_LAST;
595		mi->next = AUDIO_MIXER_LAST;
596		strlcpy(mi->label.name, AudioCinputs,
597			sizeof(mi->label.name));
598		break;
599	default:
600		return ENXIO;
601	}
602
603	return 0;
604}
605
606int
607uda1341_get_port(void *handle, mixer_ctrl_t *mixer)
608{
609	struct uda1341_softc *sc = handle;
610
611	switch(mixer->dev) {
612	case UDA1341_MIXER_VOL:
613		if (mixer->type != AUDIO_MIXER_VALUE)
614			return EINVAL;
615		if (mixer->un.value.num_channels != 1)
616			return EINVAL;
617		mixer->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
618			sc->sc_volume;
619		break;
620	case UDA1341_MIXER_BASS:
621		if (mixer->type != AUDIO_MIXER_VALUE ||
622		    mixer->un.value.num_channels != 1)
623			return EINVAL;
624
625		mixer->un.value.level[0] = sc->sc_bass;
626		break;
627	case UDA1341_MIXER_TREBLE:
628		if (mixer->type != AUDIO_MIXER_VALUE ||
629		    mixer->un.value.num_channels != 1)
630			return EINVAL;
631
632		mixer->un.value.level[0] = sc->sc_treble;
633		break;
634	case UDA1341_MIXER_MODE:
635		if (mixer->type != AUDIO_MIXER_ENUM)
636			return EINVAL;
637
638		mixer->un.ord = sc->sc_mode;
639		break;
640	case UDA1341_MIXER_MUTE:
641		if (mixer->type != AUDIO_MIXER_ENUM)
642			return EINVAL;
643
644		mixer->un.ord = sc->sc_mute;
645		break;
646	case UDA1341_MIXER_OGAIN:
647		if (mixer->type != AUDIO_MIXER_ENUM)
648			return EINVAL;
649
650		mixer->un.ord = sc->sc_ogain;
651		break;
652	case UDA1341_MIXER_DE:
653		if (mixer->type != AUDIO_MIXER_ENUM)
654			return EINVAL;
655
656		mixer->un.ord = sc->sc_deemphasis;
657		break;
658	case UDA1341_MIXER_INMIX1:
659		if (mixer->type != AUDIO_MIXER_VALUE)
660			return EINVAL;
661
662		mixer->un.value.level[0] = sc->sc_inmix1;
663		break;
664	case UDA1341_MIXER_INMIX2:
665		if (mixer->type != AUDIO_MIXER_VALUE)
666			return EINVAL;
667
668		mixer->un.value.level[0] = sc->sc_inmix2;
669		break;
670	case UDA1341_MIXER_MICVOL:
671		if (mixer->type != AUDIO_MIXER_VALUE)
672			return EINVAL;
673
674		mixer->un.value.level[0] = sc->sc_micvol;
675		break;
676	case UDA1341_MIXER_INMODE:
677		if (mixer->type != AUDIO_MIXER_ENUM)
678			return EINVAL;
679
680		mixer->un.ord =	sc->sc_inmode;
681		break;
682	case UDA1341_MIXER_AGC:
683		if (mixer->type != AUDIO_MIXER_ENUM)
684			return EINVAL;
685
686		mixer->un.ord =	sc->sc_agc;
687		break;
688	case UDA1341_MIXER_AGC_LVL:
689		if (mixer->type != AUDIO_MIXER_VALUE)
690			return EINVAL;
691
692		mixer->un.value.level[0] = sc->sc_agc_lvl;
693		break;
694	case UDA1341_MIXER_IN_GAIN2:
695		if (mixer->type != AUDIO_MIXER_VALUE)
696			return EINVAL;
697
698		mixer->un.value.level[0] = sc->sc_ch2_gain;
699		break;
700	default:
701		return EINVAL;
702	}
703
704	return 0;
705}
706
707int
708uda1341_set_port(void *handle, mixer_ctrl_t *mixer)
709{
710	struct uda1341_softc *sc = handle;
711
712	switch(mixer->dev) {
713	case UDA1341_MIXER_VOL:
714		sc->sc_volume = mixer->un.value.level[0];
715		break;
716	case UDA1341_MIXER_BASS:
717		sc->sc_bass = mixer->un.value.level[0];
718		break;
719	case UDA1341_MIXER_TREBLE:
720		sc->sc_treble = mixer->un.value.level[0];
721		break;
722	case UDA1341_MIXER_MODE:
723		sc->sc_mode = mixer->un.ord;
724		break;
725	case UDA1341_MIXER_MUTE:
726		sc->sc_mute = mixer->un.ord;
727		break;
728	case UDA1341_MIXER_OGAIN:
729		sc->sc_ogain = mixer->un.ord;
730		break;
731	case UDA1341_MIXER_DE:
732		sc->sc_deemphasis = mixer->un.ord;
733		break;
734	case UDA1341_MIXER_INMIX1:
735		sc->sc_inmix1 = mixer->un.value.level[0];
736		break;
737	case UDA1341_MIXER_INMIX2:
738		sc->sc_inmix2 = mixer->un.value.level[0];
739		break;
740	case UDA1341_MIXER_MICVOL:
741		sc->sc_micvol = mixer->un.value.level[0];
742		break;
743	case UDA1341_MIXER_INMODE:
744		sc->sc_inmode = mixer->un.ord;
745		break;
746	case UDA1341_MIXER_AGC:
747		sc->sc_agc = mixer->un.ord;
748		break;
749	case UDA1341_MIXER_AGC_LVL:
750		sc->sc_agc_lvl = mixer->un.value.level[0];
751		break;
752	case UDA1341_MIXER_IN_GAIN2:
753		sc->sc_ch2_gain = mixer->un.value.level[0];
754		break;
755	default:
756		return EINVAL;
757	}
758
759	uda1341_update_sound_settings(sc);
760
761	return 0;
762}
763