xref: /netbsd-src/sys/dev/ic/uda1341.c (revision e622eac459adf11c2e710d7a4de0f05510bbbe61)
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/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 static void uda1341_update_sound_settings(struct uda1341_softc *sc);
51 
52 
53 int
uda1341_attach(struct uda1341_softc * sc)54 uda1341_attach(struct uda1341_softc *sc)
55 {
56 	sc->sc_system_clock = UDA1341_CLOCK_NA;
57 	sc->sc_l3_write = NULL;
58 	sc->sc_volume = 127;
59 	sc->sc_bass = 0;
60 	sc->sc_treble = 0;
61 	sc->sc_mode = 0;
62 	sc->sc_mute = 0;
63 	sc->sc_ogain = 0;
64 	sc->sc_deemphasis = UDA1341_DEEMPHASIS_AUTO;
65 	sc->sc_dac_power = 0;
66 	sc->sc_adc_power = 0;
67 	sc->sc_inmix1 = 0;
68 	sc->sc_inmix2 = 0;
69 	sc->sc_micvol = 0;
70 	sc->sc_inmode = 0;
71 	sc->sc_agc = 0;
72 	sc->sc_agc_lvl = 0;
73 	sc->sc_ch2_gain = 0;
74 
75 	return 0;
76 }
77 
78 int
uda1341_open(void * handle,int flags)79 uda1341_open(void *handle, int flags)
80 {
81 	struct uda1341_softc *sc = handle;
82 
83 	/* Reset the UDA1341 */
84 	sc->sc_l3_write(sc, 0, UDA1341_L3_ADDR_DEVICE |
85 			UDA1341_L3_ADDR_STATUS);
86 	sc->sc_l3_write(sc, 1,
87 			UDA1341_L3_STATUS0 |
88 			UDA1341_L3_STATUS0_RST);
89 
90 	if (flags & FREAD) {
91 		sc->sc_adc_power = 1;
92 	}
93 	if (flags & FWRITE) {
94 		sc->sc_dac_power = 1;
95 	}
96 
97 #if 0
98 	/* Power on DAC */
99 	sc->sc_l3_write(sc, 1,
100 			UDA1341_L3_STATUS1 | UDA1341_L3_STATUS1_PC_DAC);
101 #endif
102 	uda1341_update_sound_settings(sc);
103 
104 #if 0
105 	/* TODO: Add mixer support */
106 	sc->sc_l3_write(sc, 0, 0x14 | 0x0);
107 	sc->sc_l3_write(sc, 1, 0x15);  /* Volume */
108 #endif
109 
110 	return 0;
111 }
112 
113 void
uda1341_close(void * handle)114 uda1341_close(void *handle)
115 {
116 	struct uda1341_softc *sc = handle;
117 	/* Reset the UDA1341 */
118 	sc->sc_l3_write(sc, 0, UDA1341_L3_ADDR_DEVICE |
119 			UDA1341_L3_ADDR_STATUS);
120 
121 	/* Power off DAC and ADC*/
122 	sc->sc_l3_write(sc, 1,
123 			UDA1341_L3_STATUS1);
124 
125 	sc->sc_dac_power = 0;
126 	sc->sc_adc_power = 0;
127 }
128 
129 int
uda1341_set_format(void * handle,int setmode,const audio_params_t * play,const audio_params_t * rec,audio_filter_reg_t * pfil,audio_filter_reg_t * rfil)130 uda1341_set_format(void *handle, int setmode,
131 		   const audio_params_t *play, const audio_params_t *rec,
132 		   audio_filter_reg_t *pfil, audio_filter_reg_t *rfil)
133 {
134 	struct uda1341_softc *sc = handle;
135 	if (sc->sc_system_clock == UDA1341_CLOCK_NA)
136 		panic("%s was called without sc_system_clock set!\n", __func__);
137 
138 	/* Select status register */
139 	sc->sc_l3_write(sc, 0, UDA1341_L3_ADDR_DEVICE |
140 			UDA1341_L3_ADDR_STATUS);
141 
142 	sc->sc_l3_write(sc, 1, UDA1341_L3_STATUS0 |
143 			sc->sc_system_clock << UDA1341_L3_STATUS0_SC_SHIFT |
144 			sc->sc_bus_format << UDA1341_L3_STATUS0_IF_SHIFT
145 			);
146 
147 	if (sc->sc_sample_rate_approx != play->sample_rate) {
148 		sc->sc_sample_rate_approx = play->sample_rate;
149 		uda1341_update_sound_settings(sc);
150 	}
151 
152 	return 0;
153 }
154 
155 #define AUDIO_LEVELS	(AUDIO_MAX_GAIN-AUDIO_MIN_GAIN+1)
156 static void
uda1341_update_sound_settings(struct uda1341_softc * sc)157 uda1341_update_sound_settings(struct uda1341_softc *sc)
158 {
159 	/* TODO: Refactor this function into smaller parts, such that
160 	 * a volume change does not trigger updates of all the
161 	 * other -- unrelated -- registers.
162 	 */
163 
164 	uint8_t val, volume, bass, treble, deemphasis;
165 
166 	sc->sc_l3_write(sc, 0, UDA1341_L3_ADDR_DEVICE | UDA1341_L3_ADDR_STATUS);
167 	val = UDA1341_L3_STATUS1;
168 	if (sc->sc_dac_power)
169 		val |= UDA1341_L3_STATUS1_PC_DAC;
170 	if (sc->sc_adc_power)
171 		val |= UDA1341_L3_STATUS1_PC_ADC;
172 	if (sc->sc_ogain)
173 		val |= UDA1341_L3_STATUS1_OGS_6DB;
174 
175 	sc->sc_l3_write(sc, 1, val);
176 
177 	sc->sc_l3_write(sc, 0, UDA1341_L3_ADDR_DEVICE | UDA1341_L3_ADDR_DATA0);
178 
179 	/* Update volume */
180 	/* On the UDA1341 maximal volume is 0x0,
181 	   while minimal volume is 0x3f */
182 	volume = (0x3f) - ((sc->sc_volume*(0x3f+1)) / (AUDIO_LEVELS));
183 
184 	val = UDA1341_L3_DATA0_VOLUME;
185 	val |= volume & UDA1341_L3_DATA0_VOLUME_MASK;
186 	sc->sc_l3_write(sc, 1, val);
187 
188 	/* Update bass and treble */
189 	bass = (sc->sc_bass*(0xf+1)) / AUDIO_LEVELS;
190 	treble = (sc->sc_treble*(0x3+1)) / AUDIO_LEVELS;
191 	val = UDA1341_L3_DATA0_BASS_TREBLE;
192 	val |= (bass << UDA1341_L3_DATA0_BASS_SHIFT) &
193 		UDA1341_L3_DATA0_BASS_MASK;
194 	val |= (treble << UDA1341_L3_DATA0_TREBLE_SHIFT) &
195 		UDA1341_L3_DATA0_TREBLE_MASK;
196 	sc->sc_l3_write(sc, 1, val);
197 
198 	/* Update the remaining output sound controls:
199 	 * - Peak-detect position
200 	 * - De-emphasis
201 	 * - Mute
202 	 * - Mode Switch
203 	 * XXX: Only Mode-switch, de-emphasis, and mute is currently supported.
204 	 */
205 	val = UDA1341_L3_DATA0_SOUNDC;
206 
207 	deemphasis = sc->sc_deemphasis;
208 	if( deemphasis == UDA1341_DEEMPHASIS_AUTO) {
209 		/* Set deemphasis according to current sample rate */
210 		switch (sc->sc_sample_rate_approx) {
211 		case 32000:
212 			deemphasis = 0x1;
213 			break;
214 		case 44100:
215 			deemphasis = 0x2;
216 			break;
217 		case 48000:
218 			deemphasis = 0x3;
219 			break;
220 		default:
221 			deemphasis = 0x0;
222 		}
223 	}
224 
225 	DPRINTF(("Deemphasis: %d\n", deemphasis));
226 	val |= (deemphasis << UDA1341_L3_DATA0_SOUNDC_DE_SHIFT) &
227 		UDA1341_L3_DATA0_SOUNDC_DE_MASK;
228 
229 	if (sc->sc_mute)
230 		val |= UDA1341_L3_DATA0_SOUNDC_MUTE;
231 	val |= sc->sc_mode & UDA1341_L3_DATA0_SOUNDC_MODE_MASK;
232 	sc->sc_l3_write(sc, 1, val);
233 
234 	/* Extended Register 0: MA */
235 	val = UDA1341_L3_DATA0_ED;
236 	val |= (sc->sc_inmix1 & UDA1341_L3_DATA0_MA_MASK);
237 	sc->sc_l3_write(sc, 1, UDA1341_L3_DATA0_EA | 0x0);
238 	sc->sc_l3_write(sc, 1, val);
239 
240 	/* Extended Register 1: MB */
241 	val = UDA1341_L3_DATA0_ED;
242 	val |= (sc->sc_inmix2 & UDA1341_L3_DATA0_MB_MASK);
243 	sc->sc_l3_write(sc, 1, UDA1341_L3_DATA0_EA | 0x01);
244 	sc->sc_l3_write(sc, 1, val);
245 
246 	/* Extended Register 2: MIC sensitivity and mixer mode  */
247 	val = UDA1341_L3_DATA0_ED;
248 	val |= (sc->sc_micvol << UDA1341_L3_DATA0_MS_SHIFT) &
249 		UDA1341_L3_DATA0_MS_MASK;
250 	val |= sc->sc_inmode & UDA1341_L3_DATA0_MM_MASK;
251 	sc->sc_l3_write(sc, 1, UDA1341_L3_DATA0_EA | 0x02);
252 	sc->sc_l3_write(sc, 1, val);
253 
254 	/* Extended Register 4: AGC and IG (ch2_gain) */
255 	val = UDA1341_L3_DATA0_ED;
256 
257 	val |= (sc->sc_agc << UDA1341_L3_DATA0_AGC_SHIFT) &
258 		UDA1341_L3_DATA0_AGC_MASK;
259 	val |= (sc->sc_ch2_gain & 0x03) & UDA1341_L3_DATA0_IG_LOW_MASK;
260 	sc->sc_l3_write(sc, 1, UDA1341_L3_DATA0_EA | 0x04);
261 	sc->sc_l3_write(sc, 1, val);
262 
263 	/* Extended Register 5: IG (ch2_gain) */
264 	val = UDA1341_L3_DATA0_ED;
265 	val |= (sc->sc_ch2_gain >> 2 ) & UDA1341_L3_DATA0_IG_HIGH_MASK;
266 	sc->sc_l3_write(sc, 1, UDA1341_L3_DATA0_EA | 0x05);
267 	sc->sc_l3_write(sc, 1, val);
268 
269 	/* Extended Register 6: AT and AL */
270 	/* XXX: Only AL is supported at this point */
271 	val = UDA1341_L3_DATA0_ED;
272 	val |= sc->sc_agc_lvl & UDA1341_L3_DATA0_AL_MASK;
273 	sc->sc_l3_write(sc, 1, UDA1341_L3_DATA0_EA | 0x06);
274 	sc->sc_l3_write(sc, 1, val);
275 }
276 
277 #define UDA1341_MIXER_VOL	0
278 #define UDA1341_MIXER_BASS	1
279 #define UDA1341_MIXER_TREBLE	2
280 #define UDA1341_MIXER_MODE	3
281 #define UDA1341_MIXER_MUTE	4
282 #define UDA1341_MIXER_OGAIN	5
283 #define UDA1341_MIXER_DE	6
284 #define UDA1341_OUTPUT_CLASS	7
285 
286 #define UDA1341_MIXER_INMIX1	8
287 #define UDA1341_MIXER_INMIX2	9
288 #define UDA1341_MIXER_MICVOL	10
289 #define UDA1341_MIXER_INMODE	11
290 #define UDA1341_MIXER_AGC	12
291 #define UDA1341_MIXER_AGC_LVL	13
292 #define UDA1341_MIXER_IN_GAIN2	14
293 /*#define UDA1341_MIXER_AGC_SETTINGS 15*/
294 #define UDA1341_INPUT_CLASS	15
295 
296 int
uda1341_query_devinfo(void * handle,mixer_devinfo_t * mi)297 uda1341_query_devinfo(void *handle, mixer_devinfo_t *mi)
298 {
299 
300 	switch(mi->index) {
301 	case UDA1341_MIXER_VOL:
302 		strlcpy(mi->label.name, AudioNspeaker,
303 			sizeof(mi->label.name));
304 		mi->type = AUDIO_MIXER_VALUE;
305 		mi->mixer_class = UDA1341_OUTPUT_CLASS;
306 		mi->next = UDA1341_MIXER_BASS;
307 		mi->prev = AUDIO_MIXER_LAST;
308 		strlcpy(mi->un.v.units.name, AudioNvolume,
309 			sizeof(mi->un.v.units.name));
310 		mi->un.v.num_channels = 1;
311 		mi->un.v.delta = 256/64;
312 		break;
313 	case UDA1341_MIXER_BASS:
314 		strlcpy(mi->label.name, AudioNbass,
315 			sizeof(mi->label.name));
316 		mi->type = AUDIO_MIXER_VALUE;
317 		mi->mixer_class = UDA1341_OUTPUT_CLASS;
318 		mi->next = UDA1341_MIXER_TREBLE;
319 		mi->prev = UDA1341_MIXER_VOL;
320 		strlcpy(mi->un.v.units.name, AudioNbass,
321 			sizeof(mi->un.v.units.name));
322 		mi->un.v.num_channels = 1;
323 		mi->un.v.delta = 256/16;
324 		break;
325 	case UDA1341_MIXER_TREBLE:
326 		strlcpy(mi->label.name, AudioNtreble,
327 			sizeof(mi->label.name));
328 		mi->type = AUDIO_MIXER_VALUE;
329 		mi->mixer_class = UDA1341_OUTPUT_CLASS;
330 		mi->next = UDA1341_MIXER_MODE;
331 		mi->prev = UDA1341_MIXER_BASS;
332 		strlcpy(mi->un.v.units.name, AudioNtreble,
333 			sizeof(mi->un.v.units.name));
334 		mi->un.v.num_channels = 1;
335 		mi->un.v.delta = 256/4;
336 		break;
337 	case UDA1341_MIXER_MODE:
338 		strlcpy(mi->label.name, AudioNmode,
339 			sizeof(mi->label.name));
340 		mi->type = AUDIO_MIXER_ENUM;
341 		mi->mixer_class = UDA1341_OUTPUT_CLASS;
342 		mi->next = UDA1341_MIXER_MUTE;
343 		mi->prev = UDA1341_MIXER_TREBLE;
344 		mi->un.e.num_mem = 3;
345 
346 		strlcpy(mi->un.e.member[0].label.name,
347 			"flat", sizeof(mi->un.e.member[0].label.name));
348 		mi->un.e.member[0].ord = 0;
349 
350 		strlcpy(mi->un.e.member[1].label.name,
351 			"minimum", sizeof(mi->un.e.member[1].label.name));
352 		mi->un.e.member[1].ord = 1;
353 
354 		strlcpy(mi->un.e.member[2].label.name,
355 			"maximum", sizeof(mi->un.e.member[2].label.name));
356 		mi->un.e.member[2].ord = 3;
357 
358 		break;
359 	case UDA1341_MIXER_MUTE:
360 		strlcpy(mi->label.name, AudioNmute,
361 			sizeof(mi->label.name));
362 		mi->type = AUDIO_MIXER_ENUM;
363 		mi->mixer_class = UDA1341_OUTPUT_CLASS;
364 		mi->next = UDA1341_MIXER_OGAIN;
365 		mi->prev = UDA1341_MIXER_MODE;
366 		mi->un.e.num_mem = 2;
367 
368 		strlcpy(mi->un.e.member[0].label.name,
369 			"off", sizeof(mi->un.e.member[0].label.name));
370 		mi->un.e.member[0].ord = 0;
371 
372 		strlcpy(mi->un.e.member[1].label.name,
373 			"on", sizeof(mi->un.e.member[1].label.name));
374 		mi->un.e.member[1].ord = 1;
375 		break;
376 	case UDA1341_MIXER_OGAIN:
377 		strlcpy(mi->label.name, "gain",
378 			sizeof(mi->label.name));
379 		mi->type = AUDIO_MIXER_ENUM;
380 		mi->mixer_class = UDA1341_OUTPUT_CLASS;
381 		mi->next = UDA1341_MIXER_DE;
382 		mi->prev = UDA1341_MIXER_MUTE;
383 		mi->un.e.num_mem = 2;
384 
385 		strlcpy(mi->un.e.member[0].label.name,
386 			"off", sizeof(mi->un.e.member[0].label.name));
387 		mi->un.e.member[0].ord = 0;
388 
389 		strlcpy(mi->un.e.member[1].label.name,
390 			"on", sizeof(mi->un.e.member[1].label.name));
391 		mi->un.e.member[1].ord = 1;
392 		break;
393 	case UDA1341_MIXER_DE:
394 		strlcpy(mi->label.name, "deemphasis",
395 			sizeof(mi->label.name));
396 		mi->type = AUDIO_MIXER_ENUM;
397 		mi->mixer_class = UDA1341_OUTPUT_CLASS;
398 		mi->next = AUDIO_MIXER_LAST;
399 		mi->prev = UDA1341_MIXER_OGAIN;
400 		mi->un.e.num_mem = 5;
401 
402 		strlcpy(mi->un.e.member[0].label.name,
403 			"none", sizeof(mi->un.e.member[0].label.name));
404 		mi->un.e.member[0].ord = 0;
405 
406 		strlcpy(mi->un.e.member[1].label.name,
407 			"32KHz", sizeof(mi->un.e.member[1].label.name));
408 		mi->un.e.member[1].ord = 1;
409 
410 		strlcpy(mi->un.e.member[2].label.name,
411 			"44.1KHz", sizeof(mi->un.e.member[2].label.name));
412 		mi->un.e.member[2].ord = 2;
413 
414 		strlcpy(mi->un.e.member[3].label.name,
415 			"48KHz", sizeof(mi->un.e.member[3].label.name));
416 		mi->un.e.member[3].ord = 3;
417 
418 		strlcpy(mi->un.e.member[4].label.name,
419 			"auto", sizeof(mi->un.e.member[4].label.name));
420 		mi->un.e.member[4].ord = 4;
421 
422 		break;
423 	case UDA1341_OUTPUT_CLASS:
424 		mi->type = AUDIO_MIXER_CLASS;
425 		mi->mixer_class = UDA1341_OUTPUT_CLASS;
426 		mi->prev = AUDIO_MIXER_LAST;
427 		mi->next = AUDIO_MIXER_LAST;
428 		strlcpy(mi->label.name, AudioCoutputs,
429 			sizeof(mi->label.name));
430 		break;
431 	case UDA1341_MIXER_INMIX1:
432 		strlcpy(mi->label.name, "inmix1",
433 			sizeof(mi->label.name));
434 		mi->type = AUDIO_MIXER_VALUE;
435 		mi->mixer_class = UDA1341_INPUT_CLASS;
436 		mi->next = AUDIO_MIXER_LAST;
437 		mi->prev = AUDIO_MIXER_LAST;
438 		strlcpy(mi->un.v.units.name, AudioNvolume,
439 			sizeof(mi->un.v.units.name));
440 		mi->un.v.num_channels = 1;
441 		mi->un.v.delta = 256/64;
442 		break;
443 	case UDA1341_MIXER_INMIX2:
444 		strlcpy(mi->label.name, "inmix2",
445 			sizeof(mi->label.name));
446 		mi->type = AUDIO_MIXER_VALUE;
447 		mi->mixer_class = UDA1341_INPUT_CLASS;
448 		mi->next = AUDIO_MIXER_LAST;
449 		mi->prev = AUDIO_MIXER_LAST;
450 		strlcpy(mi->un.v.units.name, AudioNvolume,
451 			sizeof(mi->un.v.units.name));
452 		mi->un.v.num_channels = 1;
453 		mi->un.v.delta = 256/64;
454 		break;
455 	case UDA1341_MIXER_MICVOL:
456 		strlcpy(mi->label.name, AudioNmicrophone,
457 			sizeof(mi->label.name));
458 		mi->type = AUDIO_MIXER_VALUE;
459 		mi->mixer_class = UDA1341_INPUT_CLASS;
460 		mi->next = AUDIO_MIXER_LAST;
461 		mi->prev = AUDIO_MIXER_LAST;
462 		strlcpy(mi->un.v.units.name, AudioNvolume,
463 			sizeof(mi->un.v.units.name));
464 		mi->un.v.num_channels = 1;
465 		mi->un.v.delta = 256/8;
466 		break;
467 	case UDA1341_MIXER_INMODE:
468 		strlcpy(mi->label.name, "inmode",
469 			sizeof(mi->label.name));
470 		mi->type = AUDIO_MIXER_ENUM;
471 		mi->mixer_class = UDA1341_INPUT_CLASS;
472 		mi->next = AUDIO_MIXER_LAST;
473 		mi->prev = AUDIO_MIXER_LAST;
474 		mi->un.e.num_mem = 4;
475 
476 		strlcpy(mi->un.e.member[0].label.name,
477 			"dd", sizeof(mi->un.e.member[0].label.name));
478 		mi->un.e.member[0].ord = 0;
479 
480 		strlcpy(mi->un.e.member[1].label.name,
481 			"ch1", sizeof(mi->un.e.member[1].label.name));
482 		mi->un.e.member[1].ord = 1;
483 
484 		strlcpy(mi->un.e.member[2].label.name,
485 			"ch2", sizeof(mi->un.e.member[2].label.name));
486 		mi->un.e.member[2].ord = 2;
487 
488 		strlcpy(mi->un.e.member[3].label.name,
489 			"mix", sizeof(mi->un.e.member[3].label.name));
490 		mi->un.e.member[3].ord = 3;
491 		break;
492 	case UDA1341_MIXER_AGC:
493 		strlcpy(mi->label.name, "agc",
494 			sizeof(mi->label.name));
495 		mi->type = AUDIO_MIXER_ENUM;
496 		mi->mixer_class = UDA1341_INPUT_CLASS;
497 		mi->next = AUDIO_MIXER_LAST;
498 		mi->prev = AUDIO_MIXER_LAST;
499 		mi->un.e.num_mem = 2;
500 
501 		strlcpy(mi->un.e.member[0].label.name,
502 			"off", sizeof(mi->un.e.member[0].label.name));
503 		mi->un.e.member[0].ord = 0;
504 
505 		strlcpy(mi->un.e.member[1].label.name,
506 			"on", sizeof(mi->un.e.member[1].label.name));
507 		mi->un.e.member[1].ord = 1;
508 		break;
509 	case UDA1341_MIXER_AGC_LVL:
510 		strlcpy(mi->label.name, "agclevel",
511 			sizeof(mi->label.name));
512 		mi->type = AUDIO_MIXER_VALUE;
513 		mi->mixer_class = UDA1341_INPUT_CLASS;
514 		mi->next = AUDIO_MIXER_LAST;
515 		mi->prev = AUDIO_MIXER_LAST;
516 		strlcpy(mi->un.v.units.name, AudioNvolume,
517 			sizeof(mi->un.v.units.name));
518 		mi->un.v.num_channels = 1;
519 		mi->un.v.delta = 256/4;
520 		break;
521 	case UDA1341_MIXER_IN_GAIN2:
522 		strlcpy(mi->label.name, "ch2gain",
523 			sizeof(mi->label.name));
524 		mi->type = AUDIO_MIXER_VALUE;
525 		mi->mixer_class = UDA1341_INPUT_CLASS;
526 		mi->next = AUDIO_MIXER_LAST;
527 		mi->prev = AUDIO_MIXER_LAST;
528 		strlcpy(mi->un.v.units.name, AudioNvolume,
529 			sizeof(mi->un.v.units.name));
530 		mi->un.v.num_channels = 1;
531 		mi->un.v.delta = 256/128;
532 		break;
533 	case UDA1341_INPUT_CLASS:
534 		mi->type = AUDIO_MIXER_CLASS;
535 		mi->mixer_class = UDA1341_INPUT_CLASS;
536 		mi->prev = AUDIO_MIXER_LAST;
537 		mi->next = AUDIO_MIXER_LAST;
538 		strlcpy(mi->label.name, AudioCinputs,
539 			sizeof(mi->label.name));
540 		break;
541 	default:
542 		return ENXIO;
543 	}
544 
545 	return 0;
546 }
547 
548 int
uda1341_get_port(void * handle,mixer_ctrl_t * mixer)549 uda1341_get_port(void *handle, mixer_ctrl_t *mixer)
550 {
551 	struct uda1341_softc *sc = handle;
552 
553 	switch(mixer->dev) {
554 	case UDA1341_MIXER_VOL:
555 		if (mixer->type != AUDIO_MIXER_VALUE)
556 			return EINVAL;
557 		if (mixer->un.value.num_channels != 1)
558 			return EINVAL;
559 		mixer->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
560 			sc->sc_volume;
561 		break;
562 	case UDA1341_MIXER_BASS:
563 		if (mixer->type != AUDIO_MIXER_VALUE ||
564 		    mixer->un.value.num_channels != 1)
565 			return EINVAL;
566 
567 		mixer->un.value.level[0] = sc->sc_bass;
568 		break;
569 	case UDA1341_MIXER_TREBLE:
570 		if (mixer->type != AUDIO_MIXER_VALUE ||
571 		    mixer->un.value.num_channels != 1)
572 			return EINVAL;
573 
574 		mixer->un.value.level[0] = sc->sc_treble;
575 		break;
576 	case UDA1341_MIXER_MODE:
577 		if (mixer->type != AUDIO_MIXER_ENUM)
578 			return EINVAL;
579 
580 		mixer->un.ord = sc->sc_mode;
581 		break;
582 	case UDA1341_MIXER_MUTE:
583 		if (mixer->type != AUDIO_MIXER_ENUM)
584 			return EINVAL;
585 
586 		mixer->un.ord = sc->sc_mute;
587 		break;
588 	case UDA1341_MIXER_OGAIN:
589 		if (mixer->type != AUDIO_MIXER_ENUM)
590 			return EINVAL;
591 
592 		mixer->un.ord = sc->sc_ogain;
593 		break;
594 	case UDA1341_MIXER_DE:
595 		if (mixer->type != AUDIO_MIXER_ENUM)
596 			return EINVAL;
597 
598 		mixer->un.ord = sc->sc_deemphasis;
599 		break;
600 	case UDA1341_MIXER_INMIX1:
601 		if (mixer->type != AUDIO_MIXER_VALUE)
602 			return EINVAL;
603 
604 		mixer->un.value.level[0] = sc->sc_inmix1;
605 		break;
606 	case UDA1341_MIXER_INMIX2:
607 		if (mixer->type != AUDIO_MIXER_VALUE)
608 			return EINVAL;
609 
610 		mixer->un.value.level[0] = sc->sc_inmix2;
611 		break;
612 	case UDA1341_MIXER_MICVOL:
613 		if (mixer->type != AUDIO_MIXER_VALUE)
614 			return EINVAL;
615 
616 		mixer->un.value.level[0] = sc->sc_micvol;
617 		break;
618 	case UDA1341_MIXER_INMODE:
619 		if (mixer->type != AUDIO_MIXER_ENUM)
620 			return EINVAL;
621 
622 		mixer->un.ord =	sc->sc_inmode;
623 		break;
624 	case UDA1341_MIXER_AGC:
625 		if (mixer->type != AUDIO_MIXER_ENUM)
626 			return EINVAL;
627 
628 		mixer->un.ord =	sc->sc_agc;
629 		break;
630 	case UDA1341_MIXER_AGC_LVL:
631 		if (mixer->type != AUDIO_MIXER_VALUE)
632 			return EINVAL;
633 
634 		mixer->un.value.level[0] = sc->sc_agc_lvl;
635 		break;
636 	case UDA1341_MIXER_IN_GAIN2:
637 		if (mixer->type != AUDIO_MIXER_VALUE)
638 			return EINVAL;
639 
640 		mixer->un.value.level[0] = sc->sc_ch2_gain;
641 		break;
642 	default:
643 		return EINVAL;
644 	}
645 
646 	return 0;
647 }
648 
649 int
uda1341_set_port(void * handle,mixer_ctrl_t * mixer)650 uda1341_set_port(void *handle, mixer_ctrl_t *mixer)
651 {
652 	struct uda1341_softc *sc = handle;
653 
654 	switch(mixer->dev) {
655 	case UDA1341_MIXER_VOL:
656 		sc->sc_volume = mixer->un.value.level[0];
657 		break;
658 	case UDA1341_MIXER_BASS:
659 		sc->sc_bass = mixer->un.value.level[0];
660 		break;
661 	case UDA1341_MIXER_TREBLE:
662 		sc->sc_treble = mixer->un.value.level[0];
663 		break;
664 	case UDA1341_MIXER_MODE:
665 		sc->sc_mode = mixer->un.ord;
666 		break;
667 	case UDA1341_MIXER_MUTE:
668 		sc->sc_mute = mixer->un.ord;
669 		break;
670 	case UDA1341_MIXER_OGAIN:
671 		sc->sc_ogain = mixer->un.ord;
672 		break;
673 	case UDA1341_MIXER_DE:
674 		sc->sc_deemphasis = mixer->un.ord;
675 		break;
676 	case UDA1341_MIXER_INMIX1:
677 		sc->sc_inmix1 = mixer->un.value.level[0];
678 		break;
679 	case UDA1341_MIXER_INMIX2:
680 		sc->sc_inmix2 = mixer->un.value.level[0];
681 		break;
682 	case UDA1341_MIXER_MICVOL:
683 		sc->sc_micvol = mixer->un.value.level[0];
684 		break;
685 	case UDA1341_MIXER_INMODE:
686 		sc->sc_inmode = mixer->un.ord;
687 		break;
688 	case UDA1341_MIXER_AGC:
689 		sc->sc_agc = mixer->un.ord;
690 		break;
691 	case UDA1341_MIXER_AGC_LVL:
692 		sc->sc_agc_lvl = mixer->un.value.level[0];
693 		break;
694 	case UDA1341_MIXER_IN_GAIN2:
695 		sc->sc_ch2_gain = mixer->un.value.level[0];
696 		break;
697 	default:
698 		return EINVAL;
699 	}
700 
701 	uda1341_update_sound_settings(sc);
702 
703 	return 0;
704 }
705