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