xref: /netbsd-src/sys/dev/ic/uda1341.c (revision 5bbd2a12505d72a8177929a37b5cee489d0a1cfd)
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 
50 const 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 
66 static void uda1341_update_sound_settings(struct uda1341_softc *sc);
67 
68 
69 int
70 uda1341_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 
94 int
95 uda1341_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 
136 int
137 uda1341_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 
171 void
172 uda1341_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 
187 int
188 uda1341_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)
214 static void
215 uda1341_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 
354 int
355 uda1341_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 
606 int
607 uda1341_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 
707 int
708 uda1341_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