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