xref: /freebsd/sys/arm64/rockchip/rk3328_codec.c (revision aa917184a9c04b41e055e13b1ab158dfacca4c66)
1*aa917184SOleksandr Tymoshenko /*-
2*aa917184SOleksandr Tymoshenko  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3*aa917184SOleksandr Tymoshenko  *
4*aa917184SOleksandr Tymoshenko  * Copyright (c) 2020 Oleksandr Tymoshenko <gonzo@FreeBSD.org>
5*aa917184SOleksandr Tymoshenko  * Copyright (c) 2018 Jared McNeill <jmcneill@invisible.ca>
6*aa917184SOleksandr Tymoshenko  *
7*aa917184SOleksandr Tymoshenko  * Redistribution and use in source and binary forms, with or without
8*aa917184SOleksandr Tymoshenko  * modification, are permitted provided that the following conditions
9*aa917184SOleksandr Tymoshenko  * are met:
10*aa917184SOleksandr Tymoshenko  * 1. Redistributions of source code must retain the above copyright
11*aa917184SOleksandr Tymoshenko  *    notice, this list of conditions and the following disclaimer.
12*aa917184SOleksandr Tymoshenko  * 2. Redistributions in binary form must reproduce the above copyright
13*aa917184SOleksandr Tymoshenko  *    notice, this list of conditions and the following disclaimer in the
14*aa917184SOleksandr Tymoshenko  *    documentation and/or other materials provided with the distribution.
15*aa917184SOleksandr Tymoshenko  *
16*aa917184SOleksandr Tymoshenko  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17*aa917184SOleksandr Tymoshenko  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18*aa917184SOleksandr Tymoshenko  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19*aa917184SOleksandr Tymoshenko  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20*aa917184SOleksandr Tymoshenko  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21*aa917184SOleksandr Tymoshenko  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22*aa917184SOleksandr Tymoshenko  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23*aa917184SOleksandr Tymoshenko  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24*aa917184SOleksandr Tymoshenko  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25*aa917184SOleksandr Tymoshenko  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26*aa917184SOleksandr Tymoshenko  * SUCH DAMAGE.
27*aa917184SOleksandr Tymoshenko  *
28*aa917184SOleksandr Tymoshenko  * $FreeBSD$
29*aa917184SOleksandr Tymoshenko  */
30*aa917184SOleksandr Tymoshenko 
31*aa917184SOleksandr Tymoshenko #include <sys/cdefs.h>
32*aa917184SOleksandr Tymoshenko __FBSDID("$FreeBSD$");
33*aa917184SOleksandr Tymoshenko 
34*aa917184SOleksandr Tymoshenko #include <sys/param.h>
35*aa917184SOleksandr Tymoshenko #include <sys/systm.h>
36*aa917184SOleksandr Tymoshenko #include <sys/bus.h>
37*aa917184SOleksandr Tymoshenko #include <sys/kernel.h>
38*aa917184SOleksandr Tymoshenko #include <sys/lock.h>
39*aa917184SOleksandr Tymoshenko #include <sys/module.h>
40*aa917184SOleksandr Tymoshenko #include <sys/mutex.h>
41*aa917184SOleksandr Tymoshenko #include <sys/rman.h>
42*aa917184SOleksandr Tymoshenko #include <sys/resource.h>
43*aa917184SOleksandr Tymoshenko #include <machine/bus.h>
44*aa917184SOleksandr Tymoshenko 
45*aa917184SOleksandr Tymoshenko #include <dev/ofw/ofw_bus.h>
46*aa917184SOleksandr Tymoshenko #include <dev/ofw/ofw_bus_subr.h>
47*aa917184SOleksandr Tymoshenko 
48*aa917184SOleksandr Tymoshenko #include <dev/extres/clk/clk.h>
49*aa917184SOleksandr Tymoshenko #include <dev/extres/syscon/syscon.h>
50*aa917184SOleksandr Tymoshenko 
51*aa917184SOleksandr Tymoshenko #include "syscon_if.h"
52*aa917184SOleksandr Tymoshenko 
53*aa917184SOleksandr Tymoshenko #include "opt_snd.h"
54*aa917184SOleksandr Tymoshenko #include <dev/sound/pcm/sound.h>
55*aa917184SOleksandr Tymoshenko #include <dev/sound/fdt/audio_dai.h>
56*aa917184SOleksandr Tymoshenko #include "audio_dai_if.h"
57*aa917184SOleksandr Tymoshenko #include "mixer_if.h"
58*aa917184SOleksandr Tymoshenko 
59*aa917184SOleksandr Tymoshenko #define	RKCODEC_MIXER_DEVS		(1 << SOUND_MIXER_VOLUME)
60*aa917184SOleksandr Tymoshenko 
61*aa917184SOleksandr Tymoshenko #define	GRF_SOC_CON2			0x0408
62*aa917184SOleksandr Tymoshenko #define	 SOC_CON2_I2S_ACODEC_EN			(1 << 14)
63*aa917184SOleksandr Tymoshenko #define	 SOC_CON2_I2S_ACODEC_EN_MASK		((1 << 14) << 16)
64*aa917184SOleksandr Tymoshenko #define	GRF_SOC_CON10			0x0428
65*aa917184SOleksandr Tymoshenko #define	 SOC_CON10_GPIOMUT			(1 << 1)
66*aa917184SOleksandr Tymoshenko #define	 SOC_CON10_GPIOMUT_MASK			((1 << 1) << 16)
67*aa917184SOleksandr Tymoshenko #define	 SOC_CON10_GPIOMUT_EN			(1 << 0)
68*aa917184SOleksandr Tymoshenko #define	 SOC_CON10_GPIOMUT_EN_MASK			((1 << 0) << 16)
69*aa917184SOleksandr Tymoshenko 
70*aa917184SOleksandr Tymoshenko #define	CODEC_RESET			0x00
71*aa917184SOleksandr Tymoshenko #define	 RESET_DIG_CORE_RST			(1 << 1)
72*aa917184SOleksandr Tymoshenko #define	 RESET_SYS_RST				(1 << 0)
73*aa917184SOleksandr Tymoshenko #define	CODEC_DAC_INIT_CTRL1		0x0c
74*aa917184SOleksandr Tymoshenko #define	 DAC_INIT_CTRL1_DIRECTION_IN		(0 << 5)
75*aa917184SOleksandr Tymoshenko #define	 DAC_INIT_CTRL1_DIRECTION_OUT		(1 << 5)
76*aa917184SOleksandr Tymoshenko #define	 DAC_INIT_CTRL1_DAC_I2S_MODE_SLAVE	(0 << 4)
77*aa917184SOleksandr Tymoshenko #define	 DAC_INIT_CTRL1_DAC_I2S_MODE_MASTER	(1 << 4)
78*aa917184SOleksandr Tymoshenko #define	 DAC_INIT_CTRL1_MODE_MASK		(3 << 4)
79*aa917184SOleksandr Tymoshenko #define	CODEC_DAC_INIT_CTRL2		0x10
80*aa917184SOleksandr Tymoshenko #define	 DAC_INIT_CTRL2_DAC_VDL_16BITS		(0 << 5)
81*aa917184SOleksandr Tymoshenko #define	 DAC_INIT_CTRL2_DAC_VDL_20BITS		(1 << 5)
82*aa917184SOleksandr Tymoshenko #define	 DAC_INIT_CTRL2_DAC_VDL_24BITS		(2 << 5)
83*aa917184SOleksandr Tymoshenko #define	 DAC_INIT_CTRL2_DAC_VDL_32BITS		(3 << 5)
84*aa917184SOleksandr Tymoshenko #define	 DAC_INIT_CTRL2_DAC_VDL_MASK		(3 << 5)
85*aa917184SOleksandr Tymoshenko #define	 DAC_INIT_CTRL2_DAC_MODE_RJM		(0 << 3)
86*aa917184SOleksandr Tymoshenko #define	 DAC_INIT_CTRL2_DAC_MODE_LJM		(1 << 3)
87*aa917184SOleksandr Tymoshenko #define	 DAC_INIT_CTRL2_DAC_MODE_I2S		(2 << 3)
88*aa917184SOleksandr Tymoshenko #define	 DAC_INIT_CTRL2_DAC_MODE_PCM		(3 << 3)
89*aa917184SOleksandr Tymoshenko #define	 DAC_INIT_CTRL2_DAC_MODE_MASK		(3 << 3)
90*aa917184SOleksandr Tymoshenko #define	CODEC_DAC_INIT_CTRL3		0x14
91*aa917184SOleksandr Tymoshenko #define	 DAC_INIT_CTRL3_WL_16BITS		(0 << 2)
92*aa917184SOleksandr Tymoshenko #define	 DAC_INIT_CTRL3_WL_20BITS		(1 << 2)
93*aa917184SOleksandr Tymoshenko #define	 DAC_INIT_CTRL3_WL_24BITS		(2 << 2)
94*aa917184SOleksandr Tymoshenko #define	 DAC_INIT_CTRL3_WL_32BITS		(3 << 2)
95*aa917184SOleksandr Tymoshenko #define	 DAC_INIT_CTRL3_WL_MASK			(3 << 2)
96*aa917184SOleksandr Tymoshenko #define	 DAC_INIT_CTRL3_RST_MASK		(1 << 1)
97*aa917184SOleksandr Tymoshenko #define	 DAC_INIT_CTRL3_RST_DIS			(1 << 1)
98*aa917184SOleksandr Tymoshenko #define	 DAC_INIT_CTRL3_DAC_BCP_REVERSAL	(1 << 0)
99*aa917184SOleksandr Tymoshenko #define	 DAC_INIT_CTRL3_DAC_BCP_NORMAL		(0 << 0)
100*aa917184SOleksandr Tymoshenko #define	 DAC_INIT_CTRL3_DAC_BCP_MASK		(1 << 0)
101*aa917184SOleksandr Tymoshenko #define	CODEC_DAC_PRECHARGE_CTRL	0x88
102*aa917184SOleksandr Tymoshenko #define	 DAC_PRECHARGE_CTRL_DAC_CHARGE_PRECHARGE	(1 << 7)
103*aa917184SOleksandr Tymoshenko #define	 DAC_PRECHARGE_CTRL_DAC_CHARGE_CURRENT_I	(1 << 0)
104*aa917184SOleksandr Tymoshenko #define	 DAC_PRECHARGE_CTRL_DAC_CHARGE_CURRENT_ALL	(0x7f)
105*aa917184SOleksandr Tymoshenko #define	CODEC_DAC_PWR_CTRL		0x8c
106*aa917184SOleksandr Tymoshenko #define	 DAC_PWR_CTRL_DAC_PWR			(1 << 6)
107*aa917184SOleksandr Tymoshenko #define	 DAC_PWR_CTRL_DACL_PATH_REFV		(1 << 5)
108*aa917184SOleksandr Tymoshenko #define	 DAC_PWR_CTRL_HPOUTL_ZERO_CROSSING	(1 << 4)
109*aa917184SOleksandr Tymoshenko #define	 DAC_PWR_CTRL_DACR_PATH_REFV		(1 << 1)
110*aa917184SOleksandr Tymoshenko #define	 DAC_PWR_CTRL_HPOUTR_ZERO_CROSSING	(1 << 0)
111*aa917184SOleksandr Tymoshenko #define	CODEC_DAC_CLK_CTRL		0x90
112*aa917184SOleksandr Tymoshenko #define	 DAC_CLK_CTRL_DACL_REFV_ON		(1 << 7)
113*aa917184SOleksandr Tymoshenko #define	 DAC_CLK_CTRL_DACL_CLK_ON		(1 << 6)
114*aa917184SOleksandr Tymoshenko #define	 DAC_CLK_CTRL_DACL_ON			(1 << 5)
115*aa917184SOleksandr Tymoshenko #define	 DAC_CLK_CTRL_DACL_INIT_ON		(1 << 4)
116*aa917184SOleksandr Tymoshenko #define	 DAC_CLK_CTRL_DACR_REFV_ON		(1 << 3)
117*aa917184SOleksandr Tymoshenko #define	 DAC_CLK_CTRL_DACR_CLK_ON		(1 << 2)
118*aa917184SOleksandr Tymoshenko #define	 DAC_CLK_CTRL_DACR_ON			(1 << 1)
119*aa917184SOleksandr Tymoshenko #define	 DAC_CLK_CTRL_DACR_INIT_ON		(1 << 0)
120*aa917184SOleksandr Tymoshenko #define	CODEC_HPMIX_CTRL		0x94
121*aa917184SOleksandr Tymoshenko #define	 HPMIX_CTRL_HPMIXL_EN			(1 << 6)
122*aa917184SOleksandr Tymoshenko #define	 HPMIX_CTRL_HPMIXL_INIT_EN		(1 << 5)
123*aa917184SOleksandr Tymoshenko #define	 HPMIX_CTRL_HPMIXL_INIT2_EN		(1 << 4)
124*aa917184SOleksandr Tymoshenko #define	 HPMIX_CTRL_HPMIXR_EN			(1 << 2)
125*aa917184SOleksandr Tymoshenko #define	 HPMIX_CTRL_HPMIXR_INIT_EN		(1 << 1)
126*aa917184SOleksandr Tymoshenko #define	 HPMIX_CTRL_HPMIXR_INIT2_EN		(1 << 0)
127*aa917184SOleksandr Tymoshenko #define	CODEC_DAC_SELECT		0x98
128*aa917184SOleksandr Tymoshenko #define	 DAC_SELECT_DACL_SELECT			(1 << 4)
129*aa917184SOleksandr Tymoshenko #define	 DAC_SELECT_DACR_SELECT			(1 << 0)
130*aa917184SOleksandr Tymoshenko #define	CODEC_HPOUT_CTRL		0x9c
131*aa917184SOleksandr Tymoshenko #define	 HPOUT_CTRL_HPOUTL_EN			(1 << 7)
132*aa917184SOleksandr Tymoshenko #define	 HPOUT_CTRL_HPOUTL_INIT_EN		(1 << 6)
133*aa917184SOleksandr Tymoshenko #define	 HPOUT_CTRL_HPOUTL_UNMUTE		(1 << 5)
134*aa917184SOleksandr Tymoshenko #define	 HPOUT_CTRL_HPOUTR_EN			(1 << 4)
135*aa917184SOleksandr Tymoshenko #define	 HPOUT_CTRL_HPOUTR_INIT_EN		(1 << 3)
136*aa917184SOleksandr Tymoshenko #define	 HPOUT_CTRL_HPOUTR_UNMUTE		(1 << 2)
137*aa917184SOleksandr Tymoshenko #define	CODEC_HPOUTL_GAIN_CTRL		0xa0
138*aa917184SOleksandr Tymoshenko #define	CODEC_HPOUTR_GAIN_CTRL		0xa4
139*aa917184SOleksandr Tymoshenko #define	CODEC_HPOUT_POP_CTRL		0xa8
140*aa917184SOleksandr Tymoshenko #define	 HPOUT_POP_CTRL_HPOUTR_POP		(1 << 5)
141*aa917184SOleksandr Tymoshenko #define	 HPOUT_POP_CTRL_HPOUTR_POP_XCHARGE	(1 << 4)
142*aa917184SOleksandr Tymoshenko #define	 HPOUT_POP_CTRL_HPOUTL_POP		(1 << 1)
143*aa917184SOleksandr Tymoshenko #define	 HPOUT_POP_CTRL_HPOUTL_POP_XCHARGE	(1 << 0)
144*aa917184SOleksandr Tymoshenko 
145*aa917184SOleksandr Tymoshenko #define	DEFAULT_RATE			(48000 * 256)
146*aa917184SOleksandr Tymoshenko 
147*aa917184SOleksandr Tymoshenko static struct ofw_compat_data compat_data[] = {
148*aa917184SOleksandr Tymoshenko 	{ "rockchip,rk3328-codec",	1},
149*aa917184SOleksandr Tymoshenko 	{ NULL,				0 }
150*aa917184SOleksandr Tymoshenko };
151*aa917184SOleksandr Tymoshenko 
152*aa917184SOleksandr Tymoshenko struct rkcodec_softc {
153*aa917184SOleksandr Tymoshenko 	device_t	dev;
154*aa917184SOleksandr Tymoshenko 	struct resource	*res;
155*aa917184SOleksandr Tymoshenko 	struct mtx	mtx;
156*aa917184SOleksandr Tymoshenko 	clk_t		mclk;
157*aa917184SOleksandr Tymoshenko 	clk_t		pclk;
158*aa917184SOleksandr Tymoshenko 	struct syscon	*grf;
159*aa917184SOleksandr Tymoshenko 	u_int	regaddr;	/* address for the sysctl */
160*aa917184SOleksandr Tymoshenko };
161*aa917184SOleksandr Tymoshenko 
162*aa917184SOleksandr Tymoshenko #define	RKCODEC_LOCK(sc)		mtx_lock(&(sc)->mtx)
163*aa917184SOleksandr Tymoshenko #define	RKCODEC_UNLOCK(sc)		mtx_unlock(&(sc)->mtx)
164*aa917184SOleksandr Tymoshenko #define	RKCODEC_READ(sc, reg)		bus_read_4((sc)->res, (reg))
165*aa917184SOleksandr Tymoshenko #define	RKCODEC_WRITE(sc, reg, val)	bus_write_4((sc)->res, (reg), (val))
166*aa917184SOleksandr Tymoshenko 
167*aa917184SOleksandr Tymoshenko static int rkcodec_probe(device_t dev);
168*aa917184SOleksandr Tymoshenko static int rkcodec_attach(device_t dev);
169*aa917184SOleksandr Tymoshenko static int rkcodec_detach(device_t dev);
170*aa917184SOleksandr Tymoshenko 
171*aa917184SOleksandr Tymoshenko static void
172*aa917184SOleksandr Tymoshenko rkcodec_set_power(struct rkcodec_softc *sc, bool poweron)
173*aa917184SOleksandr Tymoshenko {
174*aa917184SOleksandr Tymoshenko 	uint32_t val;
175*aa917184SOleksandr Tymoshenko 	val = RKCODEC_READ(sc, CODEC_DAC_PRECHARGE_CTRL);
176*aa917184SOleksandr Tymoshenko 	if (poweron)
177*aa917184SOleksandr Tymoshenko 		val |= DAC_PRECHARGE_CTRL_DAC_CHARGE_PRECHARGE;
178*aa917184SOleksandr Tymoshenko 	else
179*aa917184SOleksandr Tymoshenko 		val &= ~(DAC_PRECHARGE_CTRL_DAC_CHARGE_PRECHARGE);
180*aa917184SOleksandr Tymoshenko 	RKCODEC_WRITE(sc, CODEC_DAC_PRECHARGE_CTRL, val);
181*aa917184SOleksandr Tymoshenko 	DELAY(10);
182*aa917184SOleksandr Tymoshenko 	if (poweron)
183*aa917184SOleksandr Tymoshenko 		val |= DAC_PRECHARGE_CTRL_DAC_CHARGE_CURRENT_ALL;
184*aa917184SOleksandr Tymoshenko 	else
185*aa917184SOleksandr Tymoshenko 		val &= ~(DAC_PRECHARGE_CTRL_DAC_CHARGE_CURRENT_ALL);
186*aa917184SOleksandr Tymoshenko 	RKCODEC_WRITE(sc, CODEC_DAC_PRECHARGE_CTRL, val);
187*aa917184SOleksandr Tymoshenko 
188*aa917184SOleksandr Tymoshenko }
189*aa917184SOleksandr Tymoshenko 
190*aa917184SOleksandr Tymoshenko static void
191*aa917184SOleksandr Tymoshenko rkcodec_set_mute(struct rkcodec_softc *sc, bool muted)
192*aa917184SOleksandr Tymoshenko {
193*aa917184SOleksandr Tymoshenko 	uint32_t val;
194*aa917184SOleksandr Tymoshenko 	val = SOC_CON10_GPIOMUT_MASK;
195*aa917184SOleksandr Tymoshenko 	if (!muted)
196*aa917184SOleksandr Tymoshenko 		val |= SOC_CON10_GPIOMUT;
197*aa917184SOleksandr Tymoshenko 	SYSCON_WRITE_4(sc->grf, GRF_SOC_CON10, val);
198*aa917184SOleksandr Tymoshenko }
199*aa917184SOleksandr Tymoshenko 
200*aa917184SOleksandr Tymoshenko static void
201*aa917184SOleksandr Tymoshenko rkcodec_reset(struct rkcodec_softc *sc)
202*aa917184SOleksandr Tymoshenko {
203*aa917184SOleksandr Tymoshenko 
204*aa917184SOleksandr Tymoshenko 	RKCODEC_WRITE(sc, CODEC_RESET, 0);
205*aa917184SOleksandr Tymoshenko 	DELAY(10);
206*aa917184SOleksandr Tymoshenko 	RKCODEC_WRITE(sc, CODEC_RESET, RESET_DIG_CORE_RST | RESET_SYS_RST);
207*aa917184SOleksandr Tymoshenko }
208*aa917184SOleksandr Tymoshenko 
209*aa917184SOleksandr Tymoshenko static int
210*aa917184SOleksandr Tymoshenko rkcodec_probe(device_t dev)
211*aa917184SOleksandr Tymoshenko {
212*aa917184SOleksandr Tymoshenko 	if (!ofw_bus_status_okay(dev))
213*aa917184SOleksandr Tymoshenko 		return (ENXIO);
214*aa917184SOleksandr Tymoshenko 
215*aa917184SOleksandr Tymoshenko 	if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
216*aa917184SOleksandr Tymoshenko 		return (ENXIO);
217*aa917184SOleksandr Tymoshenko 
218*aa917184SOleksandr Tymoshenko 	device_set_desc(dev, "Rockchip RK3328 CODEC");
219*aa917184SOleksandr Tymoshenko 	return (BUS_PROBE_DEFAULT);
220*aa917184SOleksandr Tymoshenko }
221*aa917184SOleksandr Tymoshenko 
222*aa917184SOleksandr Tymoshenko static int
223*aa917184SOleksandr Tymoshenko rkcodec_attach(device_t dev)
224*aa917184SOleksandr Tymoshenko {
225*aa917184SOleksandr Tymoshenko 	struct rkcodec_softc *sc;
226*aa917184SOleksandr Tymoshenko 	int error, rid;
227*aa917184SOleksandr Tymoshenko 	phandle_t node;
228*aa917184SOleksandr Tymoshenko 	uint32_t val;
229*aa917184SOleksandr Tymoshenko 
230*aa917184SOleksandr Tymoshenko 	sc = device_get_softc(dev);
231*aa917184SOleksandr Tymoshenko 	sc->dev = dev;
232*aa917184SOleksandr Tymoshenko 
233*aa917184SOleksandr Tymoshenko 	mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
234*aa917184SOleksandr Tymoshenko 
235*aa917184SOleksandr Tymoshenko 	rid = 0;
236*aa917184SOleksandr Tymoshenko 	sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
237*aa917184SOleksandr Tymoshenko 	if (!sc->res) {
238*aa917184SOleksandr Tymoshenko 		device_printf(dev, "could not allocate resource for device\n");
239*aa917184SOleksandr Tymoshenko 		error = ENXIO;
240*aa917184SOleksandr Tymoshenko 		goto fail;
241*aa917184SOleksandr Tymoshenko 	}
242*aa917184SOleksandr Tymoshenko 
243*aa917184SOleksandr Tymoshenko 	node = ofw_bus_get_node(dev);
244*aa917184SOleksandr Tymoshenko 	if (syscon_get_by_ofw_property(dev, node,
245*aa917184SOleksandr Tymoshenko 	    "rockchip,grf", &sc->grf) != 0) {
246*aa917184SOleksandr Tymoshenko 		device_printf(dev, "cannot get rockchip,grf handle\n");
247*aa917184SOleksandr Tymoshenko 		return (ENXIO);
248*aa917184SOleksandr Tymoshenko 	}
249*aa917184SOleksandr Tymoshenko 
250*aa917184SOleksandr Tymoshenko 	val = SOC_CON2_I2S_ACODEC_EN_MASK  | (SOC_CON2_I2S_ACODEC_EN << 16);
251*aa917184SOleksandr Tymoshenko 	SYSCON_WRITE_4(sc->grf, GRF_SOC_CON2, val);
252*aa917184SOleksandr Tymoshenko 
253*aa917184SOleksandr Tymoshenko 	val = 0 | (SOC_CON10_GPIOMUT_EN << 16);
254*aa917184SOleksandr Tymoshenko 	SYSCON_WRITE_4(sc->grf, GRF_SOC_CON10, val);
255*aa917184SOleksandr Tymoshenko 
256*aa917184SOleksandr Tymoshenko 	error = clk_get_by_ofw_name(dev, 0, "pclk", &sc->pclk);
257*aa917184SOleksandr Tymoshenko 	if (error != 0) {
258*aa917184SOleksandr Tymoshenko 		device_printf(dev, "could not get pclk clock\n");
259*aa917184SOleksandr Tymoshenko 		goto fail;
260*aa917184SOleksandr Tymoshenko 	}
261*aa917184SOleksandr Tymoshenko 
262*aa917184SOleksandr Tymoshenko 	error = clk_get_by_ofw_name(dev, 0, "mclk", &sc->mclk);
263*aa917184SOleksandr Tymoshenko 	if (error != 0) {
264*aa917184SOleksandr Tymoshenko 		device_printf(dev, "could not get mclk clock\n");
265*aa917184SOleksandr Tymoshenko 		goto fail;
266*aa917184SOleksandr Tymoshenko 	}
267*aa917184SOleksandr Tymoshenko 
268*aa917184SOleksandr Tymoshenko 	error = clk_enable(sc->pclk);
269*aa917184SOleksandr Tymoshenko 	if (error != 0) {
270*aa917184SOleksandr Tymoshenko 		device_printf(sc->dev, "could not enable pclk clock\n");
271*aa917184SOleksandr Tymoshenko 		goto fail;
272*aa917184SOleksandr Tymoshenko 	}
273*aa917184SOleksandr Tymoshenko 
274*aa917184SOleksandr Tymoshenko 	error = clk_enable(sc->mclk);
275*aa917184SOleksandr Tymoshenko 	if (error != 0) {
276*aa917184SOleksandr Tymoshenko 		device_printf(sc->dev, "could not enable mclk clock\n");
277*aa917184SOleksandr Tymoshenko 		goto fail;
278*aa917184SOleksandr Tymoshenko 	}
279*aa917184SOleksandr Tymoshenko 
280*aa917184SOleksandr Tymoshenko #if 0
281*aa917184SOleksandr Tymoshenko 	error = clk_set_freq(sc->mclk, DEFAULT_RATE, 0);
282*aa917184SOleksandr Tymoshenko 	if (error != 0) {
283*aa917184SOleksandr Tymoshenko 		device_printf(sc->dev, "could not set frequency for mclk clock\n");
284*aa917184SOleksandr Tymoshenko 		goto fail;
285*aa917184SOleksandr Tymoshenko 	}
286*aa917184SOleksandr Tymoshenko #endif
287*aa917184SOleksandr Tymoshenko 
288*aa917184SOleksandr Tymoshenko 	/* TODO: handle mute-gpios */
289*aa917184SOleksandr Tymoshenko 
290*aa917184SOleksandr Tymoshenko 	rkcodec_reset(sc);
291*aa917184SOleksandr Tymoshenko 	rkcodec_set_power(sc, true);
292*aa917184SOleksandr Tymoshenko 
293*aa917184SOleksandr Tymoshenko 	val = RKCODEC_READ(sc, CODEC_DAC_PWR_CTRL);
294*aa917184SOleksandr Tymoshenko 	val |= DAC_PWR_CTRL_DAC_PWR;
295*aa917184SOleksandr Tymoshenko 	RKCODEC_WRITE(sc, CODEC_DAC_PWR_CTRL, val);
296*aa917184SOleksandr Tymoshenko 
297*aa917184SOleksandr Tymoshenko 	val |= DAC_PWR_CTRL_DACL_PATH_REFV |
298*aa917184SOleksandr Tymoshenko 	    DAC_PWR_CTRL_DACR_PATH_REFV;
299*aa917184SOleksandr Tymoshenko 	RKCODEC_WRITE(sc, CODEC_DAC_PWR_CTRL, val);
300*aa917184SOleksandr Tymoshenko 
301*aa917184SOleksandr Tymoshenko 	val |= DAC_PWR_CTRL_HPOUTL_ZERO_CROSSING |
302*aa917184SOleksandr Tymoshenko 	    DAC_PWR_CTRL_HPOUTR_ZERO_CROSSING;
303*aa917184SOleksandr Tymoshenko 	RKCODEC_WRITE(sc, CODEC_DAC_PWR_CTRL, val);
304*aa917184SOleksandr Tymoshenko 
305*aa917184SOleksandr Tymoshenko 	val = RKCODEC_READ(sc, CODEC_HPOUT_POP_CTRL);
306*aa917184SOleksandr Tymoshenko 	val |= HPOUT_POP_CTRL_HPOUTR_POP | HPOUT_POP_CTRL_HPOUTL_POP;
307*aa917184SOleksandr Tymoshenko 	val &= ~(HPOUT_POP_CTRL_HPOUTR_POP_XCHARGE | HPOUT_POP_CTRL_HPOUTL_POP_XCHARGE);
308*aa917184SOleksandr Tymoshenko 	RKCODEC_WRITE(sc, CODEC_HPOUT_POP_CTRL, val);
309*aa917184SOleksandr Tymoshenko 
310*aa917184SOleksandr Tymoshenko 	val = RKCODEC_READ(sc, CODEC_HPMIX_CTRL);
311*aa917184SOleksandr Tymoshenko 	val |= HPMIX_CTRL_HPMIXL_EN | HPMIX_CTRL_HPMIXR_EN;
312*aa917184SOleksandr Tymoshenko 	RKCODEC_WRITE(sc, CODEC_HPMIX_CTRL, val);
313*aa917184SOleksandr Tymoshenko 
314*aa917184SOleksandr Tymoshenko 	val |= HPMIX_CTRL_HPMIXL_INIT_EN | HPMIX_CTRL_HPMIXR_INIT_EN;
315*aa917184SOleksandr Tymoshenko 	RKCODEC_WRITE(sc, CODEC_HPMIX_CTRL, val);
316*aa917184SOleksandr Tymoshenko 
317*aa917184SOleksandr Tymoshenko 	val = RKCODEC_READ(sc, CODEC_HPOUT_CTRL);
318*aa917184SOleksandr Tymoshenko 	val |= HPOUT_CTRL_HPOUTL_EN | HPOUT_CTRL_HPOUTR_EN;
319*aa917184SOleksandr Tymoshenko 	RKCODEC_WRITE(sc, CODEC_HPOUT_CTRL, val);
320*aa917184SOleksandr Tymoshenko 
321*aa917184SOleksandr Tymoshenko 	val |= HPOUT_CTRL_HPOUTL_INIT_EN | HPOUT_CTRL_HPOUTR_INIT_EN;
322*aa917184SOleksandr Tymoshenko 	RKCODEC_WRITE(sc, CODEC_HPOUT_CTRL, val);
323*aa917184SOleksandr Tymoshenko 
324*aa917184SOleksandr Tymoshenko 	val = RKCODEC_READ(sc, CODEC_DAC_CLK_CTRL);
325*aa917184SOleksandr Tymoshenko 	val |= DAC_CLK_CTRL_DACL_REFV_ON | DAC_CLK_CTRL_DACR_REFV_ON;
326*aa917184SOleksandr Tymoshenko 	RKCODEC_WRITE(sc, CODEC_DAC_CLK_CTRL, val);
327*aa917184SOleksandr Tymoshenko 
328*aa917184SOleksandr Tymoshenko 	val |= DAC_CLK_CTRL_DACL_CLK_ON | DAC_CLK_CTRL_DACR_CLK_ON;
329*aa917184SOleksandr Tymoshenko 	RKCODEC_WRITE(sc, CODEC_DAC_CLK_CTRL, val);
330*aa917184SOleksandr Tymoshenko 
331*aa917184SOleksandr Tymoshenko 	val |= DAC_CLK_CTRL_DACL_ON | DAC_CLK_CTRL_DACR_ON;
332*aa917184SOleksandr Tymoshenko 	RKCODEC_WRITE(sc, CODEC_DAC_CLK_CTRL, val);
333*aa917184SOleksandr Tymoshenko 
334*aa917184SOleksandr Tymoshenko 	val |= DAC_CLK_CTRL_DACL_INIT_ON | DAC_CLK_CTRL_DACR_INIT_ON;
335*aa917184SOleksandr Tymoshenko 	RKCODEC_WRITE(sc, CODEC_DAC_CLK_CTRL, val);
336*aa917184SOleksandr Tymoshenko 
337*aa917184SOleksandr Tymoshenko 	val = RKCODEC_READ(sc, CODEC_DAC_SELECT);
338*aa917184SOleksandr Tymoshenko 	val |= DAC_SELECT_DACL_SELECT | DAC_SELECT_DACR_SELECT;
339*aa917184SOleksandr Tymoshenko 	RKCODEC_WRITE(sc, CODEC_DAC_SELECT, val);
340*aa917184SOleksandr Tymoshenko 
341*aa917184SOleksandr Tymoshenko 	val = RKCODEC_READ(sc, CODEC_HPMIX_CTRL);
342*aa917184SOleksandr Tymoshenko 	val |= HPMIX_CTRL_HPMIXL_INIT2_EN | HPMIX_CTRL_HPMIXR_INIT2_EN;
343*aa917184SOleksandr Tymoshenko 	RKCODEC_WRITE(sc, CODEC_HPMIX_CTRL, val);
344*aa917184SOleksandr Tymoshenko 
345*aa917184SOleksandr Tymoshenko 	val = RKCODEC_READ(sc, CODEC_HPOUT_CTRL);
346*aa917184SOleksandr Tymoshenko 	val |= HPOUT_CTRL_HPOUTL_UNMUTE | HPOUT_CTRL_HPOUTR_UNMUTE;
347*aa917184SOleksandr Tymoshenko 	RKCODEC_WRITE(sc, CODEC_HPOUT_CTRL, val);
348*aa917184SOleksandr Tymoshenko 
349*aa917184SOleksandr Tymoshenko 	RKCODEC_WRITE(sc, CODEC_HPOUTL_GAIN_CTRL, 0x1f);
350*aa917184SOleksandr Tymoshenko 	RKCODEC_WRITE(sc, CODEC_HPOUTR_GAIN_CTRL, 0x1f);
351*aa917184SOleksandr Tymoshenko 
352*aa917184SOleksandr Tymoshenko 	rkcodec_set_mute(sc, false);
353*aa917184SOleksandr Tymoshenko 
354*aa917184SOleksandr Tymoshenko 	node = ofw_bus_get_node(dev);
355*aa917184SOleksandr Tymoshenko 	OF_device_register_xref(OF_xref_from_node(node), dev);
356*aa917184SOleksandr Tymoshenko 
357*aa917184SOleksandr Tymoshenko 	return (0);
358*aa917184SOleksandr Tymoshenko 
359*aa917184SOleksandr Tymoshenko fail:
360*aa917184SOleksandr Tymoshenko 	rkcodec_detach(dev);
361*aa917184SOleksandr Tymoshenko 	return (error);
362*aa917184SOleksandr Tymoshenko }
363*aa917184SOleksandr Tymoshenko 
364*aa917184SOleksandr Tymoshenko static int
365*aa917184SOleksandr Tymoshenko rkcodec_detach(device_t dev)
366*aa917184SOleksandr Tymoshenko {
367*aa917184SOleksandr Tymoshenko 	struct rkcodec_softc *sc;
368*aa917184SOleksandr Tymoshenko 
369*aa917184SOleksandr Tymoshenko 	sc = device_get_softc(dev);
370*aa917184SOleksandr Tymoshenko 
371*aa917184SOleksandr Tymoshenko 	if (sc->res)
372*aa917184SOleksandr Tymoshenko 		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->res);
373*aa917184SOleksandr Tymoshenko 	mtx_destroy(&sc->mtx);
374*aa917184SOleksandr Tymoshenko 
375*aa917184SOleksandr Tymoshenko 	return (0);
376*aa917184SOleksandr Tymoshenko }
377*aa917184SOleksandr Tymoshenko 
378*aa917184SOleksandr Tymoshenko static int
379*aa917184SOleksandr Tymoshenko rkcodec_mixer_init(struct snd_mixer *m)
380*aa917184SOleksandr Tymoshenko {
381*aa917184SOleksandr Tymoshenko 
382*aa917184SOleksandr Tymoshenko 	mix_setdevs(m, RKCODEC_MIXER_DEVS);
383*aa917184SOleksandr Tymoshenko 
384*aa917184SOleksandr Tymoshenko 	return (0);
385*aa917184SOleksandr Tymoshenko }
386*aa917184SOleksandr Tymoshenko 
387*aa917184SOleksandr Tymoshenko static int
388*aa917184SOleksandr Tymoshenko rkcodec_mixer_uninit(struct snd_mixer *m)
389*aa917184SOleksandr Tymoshenko {
390*aa917184SOleksandr Tymoshenko 
391*aa917184SOleksandr Tymoshenko 	return (0);
392*aa917184SOleksandr Tymoshenko }
393*aa917184SOleksandr Tymoshenko 
394*aa917184SOleksandr Tymoshenko static int
395*aa917184SOleksandr Tymoshenko rkcodec_mixer_reinit(struct snd_mixer *m)
396*aa917184SOleksandr Tymoshenko {
397*aa917184SOleksandr Tymoshenko 
398*aa917184SOleksandr Tymoshenko 	return (0);
399*aa917184SOleksandr Tymoshenko }
400*aa917184SOleksandr Tymoshenko 
401*aa917184SOleksandr Tymoshenko static int
402*aa917184SOleksandr Tymoshenko rkcodec_mixer_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
403*aa917184SOleksandr Tymoshenko {
404*aa917184SOleksandr Tymoshenko 	struct rkcodec_softc *sc;
405*aa917184SOleksandr Tymoshenko 	struct mtx *mixer_lock;
406*aa917184SOleksandr Tymoshenko 	uint8_t do_unlock;
407*aa917184SOleksandr Tymoshenko 
408*aa917184SOleksandr Tymoshenko 	sc = device_get_softc(mix_getdevinfo(m));
409*aa917184SOleksandr Tymoshenko 	mixer_lock = mixer_get_lock(m);
410*aa917184SOleksandr Tymoshenko 
411*aa917184SOleksandr Tymoshenko 	if (mtx_owned(mixer_lock)) {
412*aa917184SOleksandr Tymoshenko 		do_unlock = 0;
413*aa917184SOleksandr Tymoshenko 	} else {
414*aa917184SOleksandr Tymoshenko 		do_unlock = 1;
415*aa917184SOleksandr Tymoshenko 		mtx_lock(mixer_lock);
416*aa917184SOleksandr Tymoshenko 	}
417*aa917184SOleksandr Tymoshenko 
418*aa917184SOleksandr Tymoshenko 	right = left;
419*aa917184SOleksandr Tymoshenko 
420*aa917184SOleksandr Tymoshenko 	RKCODEC_LOCK(sc);
421*aa917184SOleksandr Tymoshenko 	switch(dev) {
422*aa917184SOleksandr Tymoshenko 	case SOUND_MIXER_VOLUME:
423*aa917184SOleksandr Tymoshenko 		printf("[%s] %s:%d\n", __func__, __FILE__, __LINE__);
424*aa917184SOleksandr Tymoshenko 		break;
425*aa917184SOleksandr Tymoshenko 
426*aa917184SOleksandr Tymoshenko 	case SOUND_MIXER_MIC:
427*aa917184SOleksandr Tymoshenko 		printf("[%s] %s:%d\n", __func__, __FILE__, __LINE__);
428*aa917184SOleksandr Tymoshenko 		break;
429*aa917184SOleksandr Tymoshenko 	default:
430*aa917184SOleksandr Tymoshenko 		break;
431*aa917184SOleksandr Tymoshenko 	}
432*aa917184SOleksandr Tymoshenko 	RKCODEC_UNLOCK(sc);
433*aa917184SOleksandr Tymoshenko 
434*aa917184SOleksandr Tymoshenko 	if (do_unlock) {
435*aa917184SOleksandr Tymoshenko 		mtx_unlock(mixer_lock);
436*aa917184SOleksandr Tymoshenko 	}
437*aa917184SOleksandr Tymoshenko 
438*aa917184SOleksandr Tymoshenko 	return (left | (right << 8));
439*aa917184SOleksandr Tymoshenko }
440*aa917184SOleksandr Tymoshenko 
441*aa917184SOleksandr Tymoshenko static unsigned
442*aa917184SOleksandr Tymoshenko rkcodec_mixer_setrecsrc(struct snd_mixer *m, unsigned src)
443*aa917184SOleksandr Tymoshenko {
444*aa917184SOleksandr Tymoshenko 
445*aa917184SOleksandr Tymoshenko 	return (0);
446*aa917184SOleksandr Tymoshenko }
447*aa917184SOleksandr Tymoshenko 
448*aa917184SOleksandr Tymoshenko static kobj_method_t rkcodec_mixer_methods[] = {
449*aa917184SOleksandr Tymoshenko 	KOBJMETHOD(mixer_init,		rkcodec_mixer_init),
450*aa917184SOleksandr Tymoshenko 	KOBJMETHOD(mixer_uninit,	rkcodec_mixer_uninit),
451*aa917184SOleksandr Tymoshenko 	KOBJMETHOD(mixer_reinit,	rkcodec_mixer_reinit),
452*aa917184SOleksandr Tymoshenko 	KOBJMETHOD(mixer_set,		rkcodec_mixer_set),
453*aa917184SOleksandr Tymoshenko 	KOBJMETHOD(mixer_setrecsrc,	rkcodec_mixer_setrecsrc),
454*aa917184SOleksandr Tymoshenko 	KOBJMETHOD_END
455*aa917184SOleksandr Tymoshenko };
456*aa917184SOleksandr Tymoshenko 
457*aa917184SOleksandr Tymoshenko MIXER_DECLARE(rkcodec_mixer);
458*aa917184SOleksandr Tymoshenko 
459*aa917184SOleksandr Tymoshenko static int
460*aa917184SOleksandr Tymoshenko rkcodec_dai_init(device_t dev, uint32_t format)
461*aa917184SOleksandr Tymoshenko {
462*aa917184SOleksandr Tymoshenko 	struct rkcodec_softc *sc;
463*aa917184SOleksandr Tymoshenko 	int fmt, pol, clk;
464*aa917184SOleksandr Tymoshenko 	uint32_t ctrl1, ctrl2, ctrl3;
465*aa917184SOleksandr Tymoshenko 
466*aa917184SOleksandr Tymoshenko 	sc = device_get_softc(dev);
467*aa917184SOleksandr Tymoshenko 
468*aa917184SOleksandr Tymoshenko 	fmt = AUDIO_DAI_FORMAT_FORMAT(format);
469*aa917184SOleksandr Tymoshenko 	pol = AUDIO_DAI_FORMAT_POLARITY(format);
470*aa917184SOleksandr Tymoshenko 	clk = AUDIO_DAI_FORMAT_CLOCK(format);
471*aa917184SOleksandr Tymoshenko 
472*aa917184SOleksandr Tymoshenko 	ctrl1 = RKCODEC_READ(sc, CODEC_DAC_INIT_CTRL1);
473*aa917184SOleksandr Tymoshenko 	ctrl2 = RKCODEC_READ(sc, CODEC_DAC_INIT_CTRL2);
474*aa917184SOleksandr Tymoshenko 	ctrl3 = RKCODEC_READ(sc, CODEC_DAC_INIT_CTRL3);
475*aa917184SOleksandr Tymoshenko 
476*aa917184SOleksandr Tymoshenko 	ctrl3 &= ~(DAC_INIT_CTRL3_DAC_BCP_MASK);
477*aa917184SOleksandr Tymoshenko 	switch (pol) {
478*aa917184SOleksandr Tymoshenko 	case AUDIO_DAI_POLARITY_IB_NF:
479*aa917184SOleksandr Tymoshenko 		ctrl3 |= DAC_INIT_CTRL3_DAC_BCP_REVERSAL;
480*aa917184SOleksandr Tymoshenko 		break;
481*aa917184SOleksandr Tymoshenko 	case AUDIO_DAI_POLARITY_NB_NF:
482*aa917184SOleksandr Tymoshenko 		ctrl3 |= DAC_INIT_CTRL3_DAC_BCP_NORMAL;
483*aa917184SOleksandr Tymoshenko 		break;
484*aa917184SOleksandr Tymoshenko 	default:
485*aa917184SOleksandr Tymoshenko 		return (EINVAL);
486*aa917184SOleksandr Tymoshenko 	}
487*aa917184SOleksandr Tymoshenko 
488*aa917184SOleksandr Tymoshenko 	ctrl1 &= ~(DAC_INIT_CTRL1_MODE_MASK);
489*aa917184SOleksandr Tymoshenko 	switch (clk) {
490*aa917184SOleksandr Tymoshenko 	case AUDIO_DAI_CLOCK_CBM_CFM:
491*aa917184SOleksandr Tymoshenko 		ctrl1 |= DAC_INIT_CTRL1_DIRECTION_OUT |
492*aa917184SOleksandr Tymoshenko 		    DAC_INIT_CTRL1_DAC_I2S_MODE_SLAVE;
493*aa917184SOleksandr Tymoshenko 		break;
494*aa917184SOleksandr Tymoshenko 	case AUDIO_DAI_CLOCK_CBS_CFS:
495*aa917184SOleksandr Tymoshenko 		ctrl1 |= DAC_INIT_CTRL1_DIRECTION_IN |
496*aa917184SOleksandr Tymoshenko 		    DAC_INIT_CTRL1_DAC_I2S_MODE_SLAVE;
497*aa917184SOleksandr Tymoshenko 		break;
498*aa917184SOleksandr Tymoshenko 	default:
499*aa917184SOleksandr Tymoshenko 		return (EINVAL);
500*aa917184SOleksandr Tymoshenko 	}
501*aa917184SOleksandr Tymoshenko 
502*aa917184SOleksandr Tymoshenko 	ctrl2 &= ~(DAC_INIT_CTRL2_DAC_VDL_MASK | DAC_INIT_CTRL2_DAC_MODE_MASK);
503*aa917184SOleksandr Tymoshenko 	ctrl2 |= DAC_INIT_CTRL2_DAC_VDL_16BITS;
504*aa917184SOleksandr Tymoshenko 	ctrl3 &= ~(DAC_INIT_CTRL3_WL_MASK);
505*aa917184SOleksandr Tymoshenko 	ctrl3 |= DAC_INIT_CTRL3_WL_32BITS;
506*aa917184SOleksandr Tymoshenko 	switch (fmt) {
507*aa917184SOleksandr Tymoshenko 	case AUDIO_DAI_FORMAT_I2S:
508*aa917184SOleksandr Tymoshenko 		ctrl2 |= DAC_INIT_CTRL2_DAC_MODE_I2S;
509*aa917184SOleksandr Tymoshenko 		break;
510*aa917184SOleksandr Tymoshenko 	case AUDIO_DAI_FORMAT_LJ:
511*aa917184SOleksandr Tymoshenko 		ctrl2 |= DAC_INIT_CTRL2_DAC_MODE_LJM;
512*aa917184SOleksandr Tymoshenko 		break;
513*aa917184SOleksandr Tymoshenko 	case AUDIO_DAI_FORMAT_RJ:
514*aa917184SOleksandr Tymoshenko 		ctrl2 |= DAC_INIT_CTRL2_DAC_MODE_RJM;
515*aa917184SOleksandr Tymoshenko 		break;
516*aa917184SOleksandr Tymoshenko 	default:
517*aa917184SOleksandr Tymoshenko 		return EINVAL;
518*aa917184SOleksandr Tymoshenko 	}
519*aa917184SOleksandr Tymoshenko 
520*aa917184SOleksandr Tymoshenko 	ctrl3 &= ~(DAC_INIT_CTRL3_RST_MASK);
521*aa917184SOleksandr Tymoshenko 	ctrl3 |= DAC_INIT_CTRL3_RST_DIS;
522*aa917184SOleksandr Tymoshenko 
523*aa917184SOleksandr Tymoshenko 	RKCODEC_WRITE(sc, CODEC_DAC_INIT_CTRL1, ctrl1);
524*aa917184SOleksandr Tymoshenko 	RKCODEC_WRITE(sc, CODEC_DAC_INIT_CTRL2, ctrl2);
525*aa917184SOleksandr Tymoshenko 	RKCODEC_WRITE(sc, CODEC_DAC_INIT_CTRL3, ctrl3);
526*aa917184SOleksandr Tymoshenko 
527*aa917184SOleksandr Tymoshenko 	return (0);
528*aa917184SOleksandr Tymoshenko }
529*aa917184SOleksandr Tymoshenko 
530*aa917184SOleksandr Tymoshenko static int
531*aa917184SOleksandr Tymoshenko rkcodec_dai_trigger(device_t dev, int go, int pcm_dir)
532*aa917184SOleksandr Tymoshenko {
533*aa917184SOleksandr Tymoshenko 	// struct rkcodec_softc 	*sc = device_get_softc(dev);
534*aa917184SOleksandr Tymoshenko 
535*aa917184SOleksandr Tymoshenko 	if ((pcm_dir != PCMDIR_PLAY) && (pcm_dir != PCMDIR_REC))
536*aa917184SOleksandr Tymoshenko 		return (EINVAL);
537*aa917184SOleksandr Tymoshenko 
538*aa917184SOleksandr Tymoshenko 	switch (go) {
539*aa917184SOleksandr Tymoshenko 	case PCMTRIG_START:
540*aa917184SOleksandr Tymoshenko 		if (pcm_dir == PCMDIR_PLAY) {
541*aa917184SOleksandr Tymoshenko 			printf("[%s] %s:%d\n", __func__, __FILE__, __LINE__);
542*aa917184SOleksandr Tymoshenko 		}
543*aa917184SOleksandr Tymoshenko 		else if (pcm_dir == PCMDIR_REC) {
544*aa917184SOleksandr Tymoshenko 			printf("[%s] %s:%d\n", __func__, __FILE__, __LINE__);
545*aa917184SOleksandr Tymoshenko 		}
546*aa917184SOleksandr Tymoshenko 		break;
547*aa917184SOleksandr Tymoshenko 
548*aa917184SOleksandr Tymoshenko 	case PCMTRIG_STOP:
549*aa917184SOleksandr Tymoshenko 	case PCMTRIG_ABORT:
550*aa917184SOleksandr Tymoshenko 		if (pcm_dir == PCMDIR_PLAY) {
551*aa917184SOleksandr Tymoshenko 			printf("[%s] %s:%d\n", __func__, __FILE__, __LINE__);
552*aa917184SOleksandr Tymoshenko 		}
553*aa917184SOleksandr Tymoshenko 		else if (pcm_dir == PCMDIR_REC) {
554*aa917184SOleksandr Tymoshenko 			printf("[%s] %s:%d\n", __func__, __FILE__, __LINE__);
555*aa917184SOleksandr Tymoshenko 		}
556*aa917184SOleksandr Tymoshenko 		break;
557*aa917184SOleksandr Tymoshenko 	}
558*aa917184SOleksandr Tymoshenko 
559*aa917184SOleksandr Tymoshenko 	return (0);
560*aa917184SOleksandr Tymoshenko }
561*aa917184SOleksandr Tymoshenko 
562*aa917184SOleksandr Tymoshenko static int
563*aa917184SOleksandr Tymoshenko rkcodec_dai_setup_mixer(device_t dev, device_t pcmdev)
564*aa917184SOleksandr Tymoshenko {
565*aa917184SOleksandr Tymoshenko 
566*aa917184SOleksandr Tymoshenko 	mixer_init(pcmdev, &rkcodec_mixer_class, dev);
567*aa917184SOleksandr Tymoshenko 
568*aa917184SOleksandr Tymoshenko 	return (0);
569*aa917184SOleksandr Tymoshenko }
570*aa917184SOleksandr Tymoshenko 
571*aa917184SOleksandr Tymoshenko static device_method_t rkcodec_methods[] = {
572*aa917184SOleksandr Tymoshenko 	/* Device interface */
573*aa917184SOleksandr Tymoshenko 	DEVMETHOD(device_probe,		rkcodec_probe),
574*aa917184SOleksandr Tymoshenko 	DEVMETHOD(device_attach,	rkcodec_attach),
575*aa917184SOleksandr Tymoshenko 	DEVMETHOD(device_detach,	rkcodec_detach),
576*aa917184SOleksandr Tymoshenko 
577*aa917184SOleksandr Tymoshenko 	DEVMETHOD(audio_dai_init,	rkcodec_dai_init),
578*aa917184SOleksandr Tymoshenko 	DEVMETHOD(audio_dai_setup_mixer,	rkcodec_dai_setup_mixer),
579*aa917184SOleksandr Tymoshenko 	DEVMETHOD(audio_dai_trigger,	rkcodec_dai_trigger),
580*aa917184SOleksandr Tymoshenko 
581*aa917184SOleksandr Tymoshenko 	DEVMETHOD_END
582*aa917184SOleksandr Tymoshenko };
583*aa917184SOleksandr Tymoshenko 
584*aa917184SOleksandr Tymoshenko static driver_t rkcodec_driver = {
585*aa917184SOleksandr Tymoshenko 	"rk3328codec",
586*aa917184SOleksandr Tymoshenko 	rkcodec_methods,
587*aa917184SOleksandr Tymoshenko 	sizeof(struct rkcodec_softc),
588*aa917184SOleksandr Tymoshenko };
589*aa917184SOleksandr Tymoshenko 
590*aa917184SOleksandr Tymoshenko static devclass_t rkcodec_devclass;
591*aa917184SOleksandr Tymoshenko 
592*aa917184SOleksandr Tymoshenko DRIVER_MODULE(rkcodec, simplebus, rkcodec_driver, rkcodec_devclass, 0, 0);
593*aa917184SOleksandr Tymoshenko SIMPLEBUS_PNP_INFO(compat_data);
594