xref: /freebsd/sys/dev/sound/macio/onyx.c (revision 9c3fbfbd6a739b053611d35ead0a67a5ecba8825)
1*9c3fbfbdSAndreas Tobler /*-
2*9c3fbfbdSAndreas Tobler  * Copyright 2012 by Andreas Tobler. All rights reserved.
3*9c3fbfbdSAndreas Tobler  *
4*9c3fbfbdSAndreas Tobler  * Redistribution and use in source and binary forms, with or without
5*9c3fbfbdSAndreas Tobler  * modification, are permitted provided that the following conditions
6*9c3fbfbdSAndreas Tobler  * are met:
7*9c3fbfbdSAndreas Tobler  * 1. Redistributions of source code must retain the above copyright
8*9c3fbfbdSAndreas Tobler  *    notice, this list of conditions and the following disclaimer.
9*9c3fbfbdSAndreas Tobler  * 2. Redistributions in binary form must reproduce the above copyright
10*9c3fbfbdSAndreas Tobler  *    notice, this list of conditions and the following disclaimer in the
11*9c3fbfbdSAndreas Tobler  *    documentation and/or other materials provided with the distribution.
12*9c3fbfbdSAndreas Tobler  *
13*9c3fbfbdSAndreas Tobler  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14*9c3fbfbdSAndreas Tobler  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15*9c3fbfbdSAndreas Tobler  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16*9c3fbfbdSAndreas Tobler  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17*9c3fbfbdSAndreas Tobler  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
18*9c3fbfbdSAndreas Tobler  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19*9c3fbfbdSAndreas Tobler  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
20*9c3fbfbdSAndreas Tobler  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
21*9c3fbfbdSAndreas Tobler  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22*9c3fbfbdSAndreas Tobler  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23*9c3fbfbdSAndreas Tobler  * SUCH DAMAGE.
24*9c3fbfbdSAndreas Tobler  *
25*9c3fbfbdSAndreas Tobler  * $FreeBSD$
26*9c3fbfbdSAndreas Tobler  */
27*9c3fbfbdSAndreas Tobler 
28*9c3fbfbdSAndreas Tobler /*
29*9c3fbfbdSAndreas Tobler  * Apple PCM3052 aka Onyx audio codec.
30*9c3fbfbdSAndreas Tobler  *
31*9c3fbfbdSAndreas Tobler  * Datasheet: http://www.ti.com/product/pcm3052a
32*9c3fbfbdSAndreas Tobler  */
33*9c3fbfbdSAndreas Tobler 
34*9c3fbfbdSAndreas Tobler #include <sys/param.h>
35*9c3fbfbdSAndreas Tobler #include <sys/systm.h>
36*9c3fbfbdSAndreas Tobler #include <sys/kernel.h>
37*9c3fbfbdSAndreas Tobler #include <sys/module.h>
38*9c3fbfbdSAndreas Tobler #include <sys/bus.h>
39*9c3fbfbdSAndreas Tobler #include <sys/malloc.h>
40*9c3fbfbdSAndreas Tobler #include <sys/lock.h>
41*9c3fbfbdSAndreas Tobler #include <sys/mutex.h>
42*9c3fbfbdSAndreas Tobler #include <machine/dbdma.h>
43*9c3fbfbdSAndreas Tobler #include <machine/intr_machdep.h>
44*9c3fbfbdSAndreas Tobler #include <machine/resource.h>
45*9c3fbfbdSAndreas Tobler #include <machine/bus.h>
46*9c3fbfbdSAndreas Tobler #include <machine/pio.h>
47*9c3fbfbdSAndreas Tobler #include <sys/rman.h>
48*9c3fbfbdSAndreas Tobler 
49*9c3fbfbdSAndreas Tobler #include <dev/iicbus/iicbus.h>
50*9c3fbfbdSAndreas Tobler #include <dev/iicbus/iiconf.h>
51*9c3fbfbdSAndreas Tobler #include <dev/ofw/ofw_bus.h>
52*9c3fbfbdSAndreas Tobler 
53*9c3fbfbdSAndreas Tobler #ifdef HAVE_KERNEL_OPTION_HEADERS
54*9c3fbfbdSAndreas Tobler #include "opt_snd.h"
55*9c3fbfbdSAndreas Tobler #endif
56*9c3fbfbdSAndreas Tobler 
57*9c3fbfbdSAndreas Tobler #include <dev/sound/pcm/sound.h>
58*9c3fbfbdSAndreas Tobler 
59*9c3fbfbdSAndreas Tobler #include "mixer_if.h"
60*9c3fbfbdSAndreas Tobler 
61*9c3fbfbdSAndreas Tobler extern kobj_class_t i2s_mixer_class;
62*9c3fbfbdSAndreas Tobler extern device_t	i2s_mixer;
63*9c3fbfbdSAndreas Tobler 
64*9c3fbfbdSAndreas Tobler struct onyx_softc
65*9c3fbfbdSAndreas Tobler {
66*9c3fbfbdSAndreas Tobler 	device_t sc_dev;
67*9c3fbfbdSAndreas Tobler 	uint32_t sc_addr;
68*9c3fbfbdSAndreas Tobler };
69*9c3fbfbdSAndreas Tobler 
70*9c3fbfbdSAndreas Tobler static int	onyx_probe(device_t);
71*9c3fbfbdSAndreas Tobler static int	onyx_attach(device_t);
72*9c3fbfbdSAndreas Tobler static int	onyx_init(struct snd_mixer *m);
73*9c3fbfbdSAndreas Tobler static int	onyx_uninit(struct snd_mixer *m);
74*9c3fbfbdSAndreas Tobler static int	onyx_reinit(struct snd_mixer *m);
75*9c3fbfbdSAndreas Tobler static int	onyx_set(struct snd_mixer *m, unsigned dev, unsigned left,
76*9c3fbfbdSAndreas Tobler 			    unsigned right);
77*9c3fbfbdSAndreas Tobler static u_int32_t	onyx_setrecsrc(struct snd_mixer *m, u_int32_t src);
78*9c3fbfbdSAndreas Tobler 
79*9c3fbfbdSAndreas Tobler static device_method_t onyx_methods[] = {
80*9c3fbfbdSAndreas Tobler 	/* Device interface. */
81*9c3fbfbdSAndreas Tobler 	DEVMETHOD(device_probe,		onyx_probe),
82*9c3fbfbdSAndreas Tobler 	DEVMETHOD(device_attach,	onyx_attach),
83*9c3fbfbdSAndreas Tobler 	{ 0, 0 }
84*9c3fbfbdSAndreas Tobler };
85*9c3fbfbdSAndreas Tobler 
86*9c3fbfbdSAndreas Tobler static driver_t onyx_driver = {
87*9c3fbfbdSAndreas Tobler 	"onyx",
88*9c3fbfbdSAndreas Tobler 	onyx_methods,
89*9c3fbfbdSAndreas Tobler 	sizeof(struct onyx_softc)
90*9c3fbfbdSAndreas Tobler };
91*9c3fbfbdSAndreas Tobler static devclass_t onyx_devclass;
92*9c3fbfbdSAndreas Tobler 
93*9c3fbfbdSAndreas Tobler DRIVER_MODULE(onyx, iicbus, onyx_driver, onyx_devclass, 0, 0);
94*9c3fbfbdSAndreas Tobler MODULE_VERSION(onyx, 1);
95*9c3fbfbdSAndreas Tobler MODULE_DEPEND(onyx, iicbus, 1, 1, 1);
96*9c3fbfbdSAndreas Tobler 
97*9c3fbfbdSAndreas Tobler static kobj_method_t onyx_mixer_methods[] = {
98*9c3fbfbdSAndreas Tobler 	KOBJMETHOD(mixer_init,		onyx_init),
99*9c3fbfbdSAndreas Tobler 	KOBJMETHOD(mixer_uninit,	onyx_uninit),
100*9c3fbfbdSAndreas Tobler 	KOBJMETHOD(mixer_reinit,	onyx_reinit),
101*9c3fbfbdSAndreas Tobler 	KOBJMETHOD(mixer_set,		onyx_set),
102*9c3fbfbdSAndreas Tobler 	KOBJMETHOD(mixer_setrecsrc,	onyx_setrecsrc),
103*9c3fbfbdSAndreas Tobler 	KOBJMETHOD_END
104*9c3fbfbdSAndreas Tobler };
105*9c3fbfbdSAndreas Tobler 
106*9c3fbfbdSAndreas Tobler MIXER_DECLARE(onyx_mixer);
107*9c3fbfbdSAndreas Tobler 
108*9c3fbfbdSAndreas Tobler #define PCM3052_IICADDR	0x8C	/* Hard-coded I2C slave addr */
109*9c3fbfbdSAndreas Tobler 
110*9c3fbfbdSAndreas Tobler /*
111*9c3fbfbdSAndreas Tobler  * PCM3052 registers.
112*9c3fbfbdSAndreas Tobler  * Numbering in decimal as used in the data sheet.
113*9c3fbfbdSAndreas Tobler  */
114*9c3fbfbdSAndreas Tobler #define PCM3052_REG_LEFT_ATTN       65
115*9c3fbfbdSAndreas Tobler #define PCM3052_REG_RIGHT_ATTN      66
116*9c3fbfbdSAndreas Tobler #define PCM3052_REG_CONTROL         67
117*9c3fbfbdSAndreas Tobler #define PCM3052_MRST                (1 << 7)
118*9c3fbfbdSAndreas Tobler #define PCM3052_SRST                (1 << 6)
119*9c3fbfbdSAndreas Tobler #define PCM3052_REG_DAC_CONTROL     68
120*9c3fbfbdSAndreas Tobler #define PCM3052_OVR1                (1 << 6)
121*9c3fbfbdSAndreas Tobler #define PCM3052_MUTE_L              (1 << 1)
122*9c3fbfbdSAndreas Tobler #define PCM3052_MUTE_R              (1 << 0)
123*9c3fbfbdSAndreas Tobler #define PCM3052_REG_DAC_DEEMPH      69
124*9c3fbfbdSAndreas Tobler #define PCM3052_REG_DAC_FILTER      70
125*9c3fbfbdSAndreas Tobler #define PCM3052_DAC_FILTER_ALWAYS   (1 << 2)
126*9c3fbfbdSAndreas Tobler #define PCM3052_REG_OUT_PHASE       71
127*9c3fbfbdSAndreas Tobler #define PCM3052_REG_ADC_CONTROL     72
128*9c3fbfbdSAndreas Tobler #define PCM3052_REG_ADC_HPF_BP      75
129*9c3fbfbdSAndreas Tobler #define PCM3052_HPF_ALWAYS          (1 << 2)
130*9c3fbfbdSAndreas Tobler #define PCM3052_REG_INFO_1          77
131*9c3fbfbdSAndreas Tobler #define PCM3052_REG_INFO_2          78
132*9c3fbfbdSAndreas Tobler #define PCM3052_REG_INFO_3          79
133*9c3fbfbdSAndreas Tobler #define PCM3052_REG_INFO_4          80
134*9c3fbfbdSAndreas Tobler 
135*9c3fbfbdSAndreas Tobler struct onyx_reg {
136*9c3fbfbdSAndreas Tobler 	u_char LEFT_ATTN;
137*9c3fbfbdSAndreas Tobler 	u_char RIGHT_ATTN;
138*9c3fbfbdSAndreas Tobler 	u_char CONTROL;
139*9c3fbfbdSAndreas Tobler 	u_char DAC_CONTROL;
140*9c3fbfbdSAndreas Tobler 	u_char DAC_DEEMPH;
141*9c3fbfbdSAndreas Tobler 	u_char DAC_FILTER;
142*9c3fbfbdSAndreas Tobler 	u_char OUT_PHASE;
143*9c3fbfbdSAndreas Tobler 	u_char ADC_CONTROL;
144*9c3fbfbdSAndreas Tobler 	u_char ADC_HPF_BP;
145*9c3fbfbdSAndreas Tobler 	u_char INFO_1;
146*9c3fbfbdSAndreas Tobler 	u_char INFO_2;
147*9c3fbfbdSAndreas Tobler 	u_char INFO_3;
148*9c3fbfbdSAndreas Tobler 	u_char INFO_4;
149*9c3fbfbdSAndreas Tobler };
150*9c3fbfbdSAndreas Tobler 
151*9c3fbfbdSAndreas Tobler static const struct onyx_reg onyx_initdata = {
152*9c3fbfbdSAndreas Tobler 	0x80,				  /* LEFT_ATTN, Mute default */
153*9c3fbfbdSAndreas Tobler 	0x80,				  /* RIGHT_ATTN, Mute default */
154*9c3fbfbdSAndreas Tobler 	PCM3052_MRST | PCM3052_SRST,      /* CONTROL */
155*9c3fbfbdSAndreas Tobler 	0,                                /* DAC_CONTROL */
156*9c3fbfbdSAndreas Tobler 	0,				  /* DAC_DEEMPH */
157*9c3fbfbdSAndreas Tobler 	PCM3052_DAC_FILTER_ALWAYS,	  /* DAC_FILTER */
158*9c3fbfbdSAndreas Tobler 	0,				  /* OUT_PHASE */
159*9c3fbfbdSAndreas Tobler 	(-1 /* dB */ + 8) & 0xf,          /* ADC_CONTROL */
160*9c3fbfbdSAndreas Tobler 	PCM3052_HPF_ALWAYS,		  /* ADC_HPF_BP */
161*9c3fbfbdSAndreas Tobler 	(1 << 2),			  /* INFO_1 */
162*9c3fbfbdSAndreas Tobler 	2,				  /* INFO_2,  */
163*9c3fbfbdSAndreas Tobler 	0,				  /* INFO_3, CLK 0 (level II),
164*9c3fbfbdSAndreas Tobler 					     SF 0 (44.1 kHz) */
165*9c3fbfbdSAndreas Tobler 	1				  /* INFO_4, VALIDL/R 0,
166*9c3fbfbdSAndreas Tobler 					     WL 24-bit depth */
167*9c3fbfbdSAndreas Tobler };
168*9c3fbfbdSAndreas Tobler 
169*9c3fbfbdSAndreas Tobler static int
170*9c3fbfbdSAndreas Tobler onyx_write(struct onyx_softc *sc, uint8_t reg, const uint8_t value)
171*9c3fbfbdSAndreas Tobler {
172*9c3fbfbdSAndreas Tobler 	u_int size;
173*9c3fbfbdSAndreas Tobler 	uint8_t buf[16];
174*9c3fbfbdSAndreas Tobler 
175*9c3fbfbdSAndreas Tobler 	struct iic_msg msg[] = {
176*9c3fbfbdSAndreas Tobler 		{ sc->sc_addr, IIC_M_WR, 0, buf }
177*9c3fbfbdSAndreas Tobler 	};
178*9c3fbfbdSAndreas Tobler 
179*9c3fbfbdSAndreas Tobler 	size = 1;
180*9c3fbfbdSAndreas Tobler 	msg[0].len = size + 1;
181*9c3fbfbdSAndreas Tobler 	buf[0] = reg;
182*9c3fbfbdSAndreas Tobler 	buf[1] = value;
183*9c3fbfbdSAndreas Tobler 
184*9c3fbfbdSAndreas Tobler 	iicbus_transfer(sc->sc_dev, msg, 1);
185*9c3fbfbdSAndreas Tobler 
186*9c3fbfbdSAndreas Tobler 	return (0);
187*9c3fbfbdSAndreas Tobler }
188*9c3fbfbdSAndreas Tobler 
189*9c3fbfbdSAndreas Tobler static int
190*9c3fbfbdSAndreas Tobler onyx_probe(device_t dev)
191*9c3fbfbdSAndreas Tobler {
192*9c3fbfbdSAndreas Tobler 	const char *name, *compat;
193*9c3fbfbdSAndreas Tobler 
194*9c3fbfbdSAndreas Tobler 	name = ofw_bus_get_name(dev);
195*9c3fbfbdSAndreas Tobler 	if (name == NULL)
196*9c3fbfbdSAndreas Tobler 		return (ENXIO);
197*9c3fbfbdSAndreas Tobler 
198*9c3fbfbdSAndreas Tobler 	if (strcmp(name, "codec") == 0) {
199*9c3fbfbdSAndreas Tobler 		if (iicbus_get_addr(dev) != PCM3052_IICADDR)
200*9c3fbfbdSAndreas Tobler 			return (ENXIO);
201*9c3fbfbdSAndreas Tobler 	} else if (strcmp(name, "codec") == 0) {
202*9c3fbfbdSAndreas Tobler 		compat = ofw_bus_get_compat(dev);
203*9c3fbfbdSAndreas Tobler 		if (compat == NULL || strcmp(compat, "pcm3052") != 0)
204*9c3fbfbdSAndreas Tobler 			return (ENXIO);
205*9c3fbfbdSAndreas Tobler 	} else
206*9c3fbfbdSAndreas Tobler 		return (ENXIO);
207*9c3fbfbdSAndreas Tobler 
208*9c3fbfbdSAndreas Tobler 	device_set_desc(dev, "Texas Instruments PCM3052 Audio Codec");
209*9c3fbfbdSAndreas Tobler 	return (0);
210*9c3fbfbdSAndreas Tobler }
211*9c3fbfbdSAndreas Tobler 
212*9c3fbfbdSAndreas Tobler static int
213*9c3fbfbdSAndreas Tobler onyx_attach(device_t dev)
214*9c3fbfbdSAndreas Tobler {
215*9c3fbfbdSAndreas Tobler 	struct onyx_softc *sc;
216*9c3fbfbdSAndreas Tobler 
217*9c3fbfbdSAndreas Tobler 	sc = device_get_softc(dev);
218*9c3fbfbdSAndreas Tobler 	sc->sc_dev = dev;
219*9c3fbfbdSAndreas Tobler 	sc->sc_addr = iicbus_get_addr(dev);
220*9c3fbfbdSAndreas Tobler 
221*9c3fbfbdSAndreas Tobler 	i2s_mixer_class = &onyx_mixer_class;
222*9c3fbfbdSAndreas Tobler 	i2s_mixer = dev;
223*9c3fbfbdSAndreas Tobler 
224*9c3fbfbdSAndreas Tobler 	return (0);
225*9c3fbfbdSAndreas Tobler }
226*9c3fbfbdSAndreas Tobler 
227*9c3fbfbdSAndreas Tobler static int
228*9c3fbfbdSAndreas Tobler onyx_init(struct snd_mixer *m)
229*9c3fbfbdSAndreas Tobler {
230*9c3fbfbdSAndreas Tobler 	struct onyx_softc *sc;
231*9c3fbfbdSAndreas Tobler 	u_int  x = 0;
232*9c3fbfbdSAndreas Tobler 
233*9c3fbfbdSAndreas Tobler 	sc = device_get_softc(mix_getdevinfo(m));
234*9c3fbfbdSAndreas Tobler 
235*9c3fbfbdSAndreas Tobler 	onyx_write(sc, PCM3052_REG_LEFT_ATTN, onyx_initdata.LEFT_ATTN);
236*9c3fbfbdSAndreas Tobler 	onyx_write(sc, PCM3052_REG_RIGHT_ATTN, onyx_initdata.RIGHT_ATTN);
237*9c3fbfbdSAndreas Tobler 	onyx_write(sc, PCM3052_REG_CONTROL, onyx_initdata.CONTROL);
238*9c3fbfbdSAndreas Tobler 	onyx_write(sc, PCM3052_REG_DAC_CONTROL,
239*9c3fbfbdSAndreas Tobler 		      onyx_initdata.DAC_CONTROL);
240*9c3fbfbdSAndreas Tobler 	onyx_write(sc, PCM3052_REG_DAC_DEEMPH, onyx_initdata.DAC_DEEMPH);
241*9c3fbfbdSAndreas Tobler 	onyx_write(sc, PCM3052_REG_DAC_FILTER, onyx_initdata.DAC_FILTER);
242*9c3fbfbdSAndreas Tobler 	onyx_write(sc, PCM3052_REG_OUT_PHASE, onyx_initdata.OUT_PHASE);
243*9c3fbfbdSAndreas Tobler 	onyx_write(sc, PCM3052_REG_ADC_CONTROL,
244*9c3fbfbdSAndreas Tobler 		      onyx_initdata.ADC_CONTROL);
245*9c3fbfbdSAndreas Tobler 	onyx_write(sc, PCM3052_REG_ADC_HPF_BP, onyx_initdata.ADC_HPF_BP);
246*9c3fbfbdSAndreas Tobler 	onyx_write(sc, PCM3052_REG_INFO_1, onyx_initdata.INFO_1);
247*9c3fbfbdSAndreas Tobler 	onyx_write(sc, PCM3052_REG_INFO_2, onyx_initdata.INFO_2);
248*9c3fbfbdSAndreas Tobler 	onyx_write(sc, PCM3052_REG_INFO_3, onyx_initdata.INFO_3);
249*9c3fbfbdSAndreas Tobler 	onyx_write(sc, PCM3052_REG_INFO_4, onyx_initdata.INFO_4);
250*9c3fbfbdSAndreas Tobler 
251*9c3fbfbdSAndreas Tobler 	x |= SOUND_MASK_VOLUME;
252*9c3fbfbdSAndreas Tobler 	mix_setdevs(m, x);
253*9c3fbfbdSAndreas Tobler 
254*9c3fbfbdSAndreas Tobler 	return (0);
255*9c3fbfbdSAndreas Tobler }
256*9c3fbfbdSAndreas Tobler 
257*9c3fbfbdSAndreas Tobler static int
258*9c3fbfbdSAndreas Tobler onyx_uninit(struct snd_mixer *m)
259*9c3fbfbdSAndreas Tobler {
260*9c3fbfbdSAndreas Tobler 	return (0);
261*9c3fbfbdSAndreas Tobler }
262*9c3fbfbdSAndreas Tobler 
263*9c3fbfbdSAndreas Tobler static int
264*9c3fbfbdSAndreas Tobler onyx_reinit(struct snd_mixer *m)
265*9c3fbfbdSAndreas Tobler {
266*9c3fbfbdSAndreas Tobler 	return (0);
267*9c3fbfbdSAndreas Tobler }
268*9c3fbfbdSAndreas Tobler 
269*9c3fbfbdSAndreas Tobler static int
270*9c3fbfbdSAndreas Tobler onyx_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
271*9c3fbfbdSAndreas Tobler {
272*9c3fbfbdSAndreas Tobler 	struct onyx_softc *sc;
273*9c3fbfbdSAndreas Tobler 	struct mtx *mixer_lock;
274*9c3fbfbdSAndreas Tobler 	int locked;
275*9c3fbfbdSAndreas Tobler 	uint8_t l, r;
276*9c3fbfbdSAndreas Tobler 
277*9c3fbfbdSAndreas Tobler 	sc = device_get_softc(mix_getdevinfo(m));
278*9c3fbfbdSAndreas Tobler 	mixer_lock = mixer_get_lock(m);
279*9c3fbfbdSAndreas Tobler 	locked = mtx_owned(mixer_lock);
280*9c3fbfbdSAndreas Tobler 
281*9c3fbfbdSAndreas Tobler 	switch (dev) {
282*9c3fbfbdSAndreas Tobler 	case SOUND_MIXER_VOLUME:
283*9c3fbfbdSAndreas Tobler 
284*9c3fbfbdSAndreas Tobler 		/*
285*9c3fbfbdSAndreas Tobler 		 * We need to unlock the mixer lock because iicbus_transfer()
286*9c3fbfbdSAndreas Tobler 		 * may sleep. The mixer lock itself is unnecessary here
287*9c3fbfbdSAndreas Tobler 		 * because it is meant to serialize hardware access, which
288*9c3fbfbdSAndreas Tobler 		 * is taken care of by the I2C layer, so this is safe.
289*9c3fbfbdSAndreas Tobler 		 */
290*9c3fbfbdSAndreas Tobler 		if (left > 100 || right > 100)
291*9c3fbfbdSAndreas Tobler 			return (0);
292*9c3fbfbdSAndreas Tobler 
293*9c3fbfbdSAndreas Tobler 		l = left + 128;
294*9c3fbfbdSAndreas Tobler 		r = right + 128;
295*9c3fbfbdSAndreas Tobler 
296*9c3fbfbdSAndreas Tobler 		if (locked)
297*9c3fbfbdSAndreas Tobler 			mtx_unlock(mixer_lock);
298*9c3fbfbdSAndreas Tobler 
299*9c3fbfbdSAndreas Tobler 		onyx_write(sc, PCM3052_REG_LEFT_ATTN, l);
300*9c3fbfbdSAndreas Tobler 		onyx_write(sc, PCM3052_REG_RIGHT_ATTN, r);
301*9c3fbfbdSAndreas Tobler 
302*9c3fbfbdSAndreas Tobler 		if (locked)
303*9c3fbfbdSAndreas Tobler 			mtx_lock(mixer_lock);
304*9c3fbfbdSAndreas Tobler 
305*9c3fbfbdSAndreas Tobler 		return (left | (right << 8));
306*9c3fbfbdSAndreas Tobler 	}
307*9c3fbfbdSAndreas Tobler 
308*9c3fbfbdSAndreas Tobler 	return (0);
309*9c3fbfbdSAndreas Tobler }
310*9c3fbfbdSAndreas Tobler 
311*9c3fbfbdSAndreas Tobler static u_int32_t
312*9c3fbfbdSAndreas Tobler onyx_setrecsrc(struct snd_mixer *m, u_int32_t src)
313*9c3fbfbdSAndreas Tobler {
314*9c3fbfbdSAndreas Tobler 	return (0);
315*9c3fbfbdSAndreas Tobler }
316