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