Path: blob/main/sys/arm64/rockchip/rk3328_codec.c
101206 views
/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2020 Oleksandr Tymoshenko <[email protected]>4* Copyright (c) 2018 Jared McNeill <[email protected]>5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11* 2. Redistributions in binary form must reproduce the above copyright12* notice, this list of conditions and the following disclaimer in the13* documentation and/or other materials provided with the distribution.14*15* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR16* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES17* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.18* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,19* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,20* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;21* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED22* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,23* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY24* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF25* SUCH DAMAGE.26*/2728#include <sys/param.h>29#include <sys/systm.h>30#include <sys/bus.h>31#include <sys/kernel.h>32#include <sys/lock.h>33#include <sys/module.h>34#include <sys/mutex.h>35#include <sys/rman.h>36#include <sys/resource.h>37#include <machine/bus.h>3839#include <dev/ofw/ofw_bus.h>40#include <dev/ofw/ofw_bus_subr.h>4142#include <dev/clk/clk.h>43#include <dev/syscon/syscon.h>4445#include "syscon_if.h"4647#include "opt_snd.h"48#include <dev/sound/pcm/sound.h>49#include <dev/sound/fdt/audio_dai.h>50#include "audio_dai_if.h"51#include "mixer_if.h"5253#define RKCODEC_MIXER_DEVS (1 << SOUND_MIXER_VOLUME)5455#define GRF_SOC_CON2 0x040856#define SOC_CON2_I2S_ACODEC_EN (1 << 14)57#define SOC_CON2_I2S_ACODEC_EN_MASK ((1 << 14) << 16)58#define GRF_SOC_CON10 0x042859#define SOC_CON10_GPIOMUT (1 << 1)60#define SOC_CON10_GPIOMUT_MASK ((1 << 1) << 16)61#define SOC_CON10_GPIOMUT_EN (1 << 0)62#define SOC_CON10_GPIOMUT_EN_MASK ((1 << 0) << 16)6364#define CODEC_RESET 0x0065#define RESET_DIG_CORE_RST (1 << 1)66#define RESET_SYS_RST (1 << 0)67#define CODEC_DAC_INIT_CTRL1 0x0c68#define DAC_INIT_CTRL1_DIRECTION_IN (0 << 5)69#define DAC_INIT_CTRL1_DIRECTION_OUT (1 << 5)70#define DAC_INIT_CTRL1_DAC_I2S_MODE_SLAVE (0 << 4)71#define DAC_INIT_CTRL1_DAC_I2S_MODE_MASTER (1 << 4)72#define DAC_INIT_CTRL1_MODE_MASK (3 << 4)73#define CODEC_DAC_INIT_CTRL2 0x1074#define DAC_INIT_CTRL2_DAC_VDL_16BITS (0 << 5)75#define DAC_INIT_CTRL2_DAC_VDL_20BITS (1 << 5)76#define DAC_INIT_CTRL2_DAC_VDL_24BITS (2 << 5)77#define DAC_INIT_CTRL2_DAC_VDL_32BITS (3 << 5)78#define DAC_INIT_CTRL2_DAC_VDL_MASK (3 << 5)79#define DAC_INIT_CTRL2_DAC_MODE_RJM (0 << 3)80#define DAC_INIT_CTRL2_DAC_MODE_LJM (1 << 3)81#define DAC_INIT_CTRL2_DAC_MODE_I2S (2 << 3)82#define DAC_INIT_CTRL2_DAC_MODE_PCM (3 << 3)83#define DAC_INIT_CTRL2_DAC_MODE_MASK (3 << 3)84#define CODEC_DAC_INIT_CTRL3 0x1485#define DAC_INIT_CTRL3_WL_16BITS (0 << 2)86#define DAC_INIT_CTRL3_WL_20BITS (1 << 2)87#define DAC_INIT_CTRL3_WL_24BITS (2 << 2)88#define DAC_INIT_CTRL3_WL_32BITS (3 << 2)89#define DAC_INIT_CTRL3_WL_MASK (3 << 2)90#define DAC_INIT_CTRL3_RST_MASK (1 << 1)91#define DAC_INIT_CTRL3_RST_DIS (1 << 1)92#define DAC_INIT_CTRL3_DAC_BCP_REVERSAL (1 << 0)93#define DAC_INIT_CTRL3_DAC_BCP_NORMAL (0 << 0)94#define DAC_INIT_CTRL3_DAC_BCP_MASK (1 << 0)95#define CODEC_DAC_PRECHARGE_CTRL 0x8896#define DAC_PRECHARGE_CTRL_DAC_CHARGE_PRECHARGE (1 << 7)97#define DAC_PRECHARGE_CTRL_DAC_CHARGE_CURRENT_I (1 << 0)98#define DAC_PRECHARGE_CTRL_DAC_CHARGE_CURRENT_ALL (0x7f)99#define CODEC_DAC_PWR_CTRL 0x8c100#define DAC_PWR_CTRL_DAC_PWR (1 << 6)101#define DAC_PWR_CTRL_DACL_PATH_REFV (1 << 5)102#define DAC_PWR_CTRL_HPOUTL_ZERO_CROSSING (1 << 4)103#define DAC_PWR_CTRL_DACR_PATH_REFV (1 << 1)104#define DAC_PWR_CTRL_HPOUTR_ZERO_CROSSING (1 << 0)105#define CODEC_DAC_CLK_CTRL 0x90106#define DAC_CLK_CTRL_DACL_REFV_ON (1 << 7)107#define DAC_CLK_CTRL_DACL_CLK_ON (1 << 6)108#define DAC_CLK_CTRL_DACL_ON (1 << 5)109#define DAC_CLK_CTRL_DACL_INIT_ON (1 << 4)110#define DAC_CLK_CTRL_DACR_REFV_ON (1 << 3)111#define DAC_CLK_CTRL_DACR_CLK_ON (1 << 2)112#define DAC_CLK_CTRL_DACR_ON (1 << 1)113#define DAC_CLK_CTRL_DACR_INIT_ON (1 << 0)114#define CODEC_HPMIX_CTRL 0x94115#define HPMIX_CTRL_HPMIXL_EN (1 << 6)116#define HPMIX_CTRL_HPMIXL_INIT_EN (1 << 5)117#define HPMIX_CTRL_HPMIXL_INIT2_EN (1 << 4)118#define HPMIX_CTRL_HPMIXR_EN (1 << 2)119#define HPMIX_CTRL_HPMIXR_INIT_EN (1 << 1)120#define HPMIX_CTRL_HPMIXR_INIT2_EN (1 << 0)121#define CODEC_DAC_SELECT 0x98122#define DAC_SELECT_DACL_SELECT (1 << 4)123#define DAC_SELECT_DACR_SELECT (1 << 0)124#define CODEC_HPOUT_CTRL 0x9c125#define HPOUT_CTRL_HPOUTL_EN (1 << 7)126#define HPOUT_CTRL_HPOUTL_INIT_EN (1 << 6)127#define HPOUT_CTRL_HPOUTL_UNMUTE (1 << 5)128#define HPOUT_CTRL_HPOUTR_EN (1 << 4)129#define HPOUT_CTRL_HPOUTR_INIT_EN (1 << 3)130#define HPOUT_CTRL_HPOUTR_UNMUTE (1 << 2)131#define CODEC_HPOUTL_GAIN_CTRL 0xa0132#define CODEC_HPOUTR_GAIN_CTRL 0xa4133#define CODEC_HPOUT_POP_CTRL 0xa8134#define HPOUT_POP_CTRL_HPOUTR_POP (1 << 5)135#define HPOUT_POP_CTRL_HPOUTR_POP_XCHARGE (1 << 4)136#define HPOUT_POP_CTRL_HPOUTL_POP (1 << 1)137#define HPOUT_POP_CTRL_HPOUTL_POP_XCHARGE (1 << 0)138139#define DEFAULT_RATE (48000 * 256)140141static struct ofw_compat_data compat_data[] = {142{ "rockchip,rk3328-codec", 1},143{ NULL, 0 }144};145146struct rkcodec_softc {147device_t dev;148struct resource *res;149struct mtx mtx;150clk_t mclk;151clk_t pclk;152struct syscon *grf;153u_int regaddr; /* address for the sysctl */154};155156#define RKCODEC_LOCK(sc) mtx_lock(&(sc)->mtx)157#define RKCODEC_UNLOCK(sc) mtx_unlock(&(sc)->mtx)158#define RKCODEC_READ(sc, reg) bus_read_4((sc)->res, (reg))159#define RKCODEC_WRITE(sc, reg, val) bus_write_4((sc)->res, (reg), (val))160161static int rkcodec_probe(device_t dev);162static int rkcodec_attach(device_t dev);163static int rkcodec_detach(device_t dev);164165static void166rkcodec_set_power(struct rkcodec_softc *sc, bool poweron)167{168uint32_t val;169val = RKCODEC_READ(sc, CODEC_DAC_PRECHARGE_CTRL);170if (poweron)171val |= DAC_PRECHARGE_CTRL_DAC_CHARGE_PRECHARGE;172else173val &= ~(DAC_PRECHARGE_CTRL_DAC_CHARGE_PRECHARGE);174RKCODEC_WRITE(sc, CODEC_DAC_PRECHARGE_CTRL, val);175176DELAY(10000);177178val = RKCODEC_READ(sc, CODEC_DAC_PRECHARGE_CTRL);179if (poweron)180val |= DAC_PRECHARGE_CTRL_DAC_CHARGE_CURRENT_ALL;181else182val &= ~(DAC_PRECHARGE_CTRL_DAC_CHARGE_CURRENT_ALL);183RKCODEC_WRITE(sc, CODEC_DAC_PRECHARGE_CTRL, val);184185}186187static void188rkcodec_set_mute(struct rkcodec_softc *sc, bool muted)189{190uint32_t val;191val = SOC_CON10_GPIOMUT_MASK;192if (!muted)193val |= SOC_CON10_GPIOMUT;194SYSCON_WRITE_4(sc->grf, GRF_SOC_CON10, val);195}196197static void198rkcodec_reset(struct rkcodec_softc *sc)199{200201RKCODEC_WRITE(sc, CODEC_RESET, 0);202DELAY(10000);203RKCODEC_WRITE(sc, CODEC_RESET, RESET_DIG_CORE_RST | RESET_SYS_RST);204}205206static int207rkcodec_probe(device_t dev)208{209if (!ofw_bus_status_okay(dev))210return (ENXIO);211212if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)213return (ENXIO);214215device_set_desc(dev, "Rockchip RK3328 CODEC");216return (BUS_PROBE_DEFAULT);217}218219static int220rkcodec_attach(device_t dev)221{222struct rkcodec_softc *sc;223int error, rid;224phandle_t node;225uint32_t val;226227sc = device_get_softc(dev);228sc->dev = dev;229230mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);231232rid = 0;233sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);234if (!sc->res) {235device_printf(dev, "could not allocate resource for device\n");236error = ENXIO;237goto fail;238}239240node = ofw_bus_get_node(dev);241if (syscon_get_by_ofw_property(dev, node,242"rockchip,grf", &sc->grf) != 0) {243device_printf(dev, "cannot get rockchip,grf handle\n");244return (ENXIO);245}246247val = SOC_CON2_I2S_ACODEC_EN | SOC_CON2_I2S_ACODEC_EN_MASK;248SYSCON_WRITE_4(sc->grf, GRF_SOC_CON2, val);249250val = 0 | SOC_CON10_GPIOMUT_EN_MASK;251SYSCON_WRITE_4(sc->grf, GRF_SOC_CON10, val);252253error = clk_get_by_ofw_name(dev, 0, "pclk", &sc->pclk);254if (error != 0) {255device_printf(dev, "could not get pclk clock\n");256goto fail;257}258259error = clk_get_by_ofw_name(dev, 0, "mclk", &sc->mclk);260if (error != 0) {261device_printf(dev, "could not get mclk clock\n");262goto fail;263}264265error = clk_enable(sc->pclk);266if (error != 0) {267device_printf(sc->dev, "could not enable pclk clock\n");268goto fail;269}270271error = clk_enable(sc->mclk);272if (error != 0) {273device_printf(sc->dev, "could not enable mclk clock\n");274goto fail;275}276277#if 0278error = clk_set_freq(sc->mclk, DEFAULT_RATE, 0);279if (error != 0) {280device_printf(sc->dev, "could not set frequency for mclk clock\n");281goto fail;282}283#endif284285/* TODO: handle mute-gpios */286287rkcodec_reset(sc);288rkcodec_set_power(sc, true);289290val = RKCODEC_READ(sc, CODEC_DAC_PWR_CTRL);291val |= DAC_PWR_CTRL_DAC_PWR;292RKCODEC_WRITE(sc, CODEC_DAC_PWR_CTRL, val);293DELAY(1000);294295val |= DAC_PWR_CTRL_DACL_PATH_REFV |296DAC_PWR_CTRL_DACR_PATH_REFV;297RKCODEC_WRITE(sc, CODEC_DAC_PWR_CTRL, val);298DELAY(1000);299300val |= DAC_PWR_CTRL_HPOUTL_ZERO_CROSSING |301DAC_PWR_CTRL_HPOUTR_ZERO_CROSSING;302RKCODEC_WRITE(sc, CODEC_DAC_PWR_CTRL, val);303DELAY(1000);304305val = RKCODEC_READ(sc, CODEC_HPOUT_POP_CTRL);306val |= HPOUT_POP_CTRL_HPOUTR_POP | HPOUT_POP_CTRL_HPOUTL_POP;307val &= ~(HPOUT_POP_CTRL_HPOUTR_POP_XCHARGE | HPOUT_POP_CTRL_HPOUTL_POP_XCHARGE);308RKCODEC_WRITE(sc, CODEC_HPOUT_POP_CTRL, val);309DELAY(1000);310311val = RKCODEC_READ(sc, CODEC_HPMIX_CTRL);312val |= HPMIX_CTRL_HPMIXL_EN | HPMIX_CTRL_HPMIXR_EN;313RKCODEC_WRITE(sc, CODEC_HPMIX_CTRL, val);314DELAY(1000);315316val |= HPMIX_CTRL_HPMIXL_INIT_EN | HPMIX_CTRL_HPMIXR_INIT_EN;317RKCODEC_WRITE(sc, CODEC_HPMIX_CTRL, val);318DELAY(1000);319320val = RKCODEC_READ(sc, CODEC_HPOUT_CTRL);321val |= HPOUT_CTRL_HPOUTL_EN | HPOUT_CTRL_HPOUTR_EN;322RKCODEC_WRITE(sc, CODEC_HPOUT_CTRL, val);323DELAY(1000);324325val |= HPOUT_CTRL_HPOUTL_INIT_EN | HPOUT_CTRL_HPOUTR_INIT_EN;326RKCODEC_WRITE(sc, CODEC_HPOUT_CTRL, val);327DELAY(1000);328329val = RKCODEC_READ(sc, CODEC_DAC_CLK_CTRL);330val |= DAC_CLK_CTRL_DACL_REFV_ON | DAC_CLK_CTRL_DACR_REFV_ON;331RKCODEC_WRITE(sc, CODEC_DAC_CLK_CTRL, val);332DELAY(1000);333334val |= DAC_CLK_CTRL_DACL_CLK_ON | DAC_CLK_CTRL_DACR_CLK_ON;335RKCODEC_WRITE(sc, CODEC_DAC_CLK_CTRL, val);336DELAY(1000);337338val |= DAC_CLK_CTRL_DACL_ON | DAC_CLK_CTRL_DACR_ON;339RKCODEC_WRITE(sc, CODEC_DAC_CLK_CTRL, val);340DELAY(1000);341342val |= DAC_CLK_CTRL_DACL_INIT_ON | DAC_CLK_CTRL_DACR_INIT_ON;343RKCODEC_WRITE(sc, CODEC_DAC_CLK_CTRL, val);344DELAY(1000);345346val = RKCODEC_READ(sc, CODEC_DAC_SELECT);347val |= DAC_SELECT_DACL_SELECT | DAC_SELECT_DACR_SELECT;348RKCODEC_WRITE(sc, CODEC_DAC_SELECT, val);349DELAY(1000);350351val = RKCODEC_READ(sc, CODEC_HPMIX_CTRL);352val |= HPMIX_CTRL_HPMIXL_INIT2_EN | HPMIX_CTRL_HPMIXR_INIT2_EN;353RKCODEC_WRITE(sc, CODEC_HPMIX_CTRL, val);354DELAY(1000);355356val = RKCODEC_READ(sc, CODEC_HPOUT_CTRL);357val |= HPOUT_CTRL_HPOUTL_UNMUTE | HPOUT_CTRL_HPOUTR_UNMUTE;358RKCODEC_WRITE(sc, CODEC_HPOUT_CTRL, val);359DELAY(1000);360361RKCODEC_WRITE(sc, CODEC_HPOUTL_GAIN_CTRL, 0x18);362RKCODEC_WRITE(sc, CODEC_HPOUTR_GAIN_CTRL, 0x18);363DELAY(1000);364365rkcodec_set_mute(sc, false);366367node = ofw_bus_get_node(dev);368OF_device_register_xref(OF_xref_from_node(node), dev);369370return (0);371372fail:373rkcodec_detach(dev);374return (error);375}376377static int378rkcodec_detach(device_t dev)379{380struct rkcodec_softc *sc;381382sc = device_get_softc(dev);383384if (sc->res)385bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->res);386mtx_destroy(&sc->mtx);387388return (0);389}390391static int392rkcodec_mixer_init(struct snd_mixer *m)393{394395mix_setdevs(m, RKCODEC_MIXER_DEVS);396397return (0);398}399400static int401rkcodec_mixer_uninit(struct snd_mixer *m)402{403404return (0);405}406407static int408rkcodec_mixer_reinit(struct snd_mixer *m)409{410411return (0);412}413414static int415rkcodec_mixer_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)416{417struct rkcodec_softc *sc;418struct mtx *mixer_lock;419uint8_t do_unlock;420421sc = device_get_softc(mix_getdevinfo(m));422mixer_lock = mixer_get_lock(m);423424if (mtx_owned(mixer_lock)) {425do_unlock = 0;426} else {427do_unlock = 1;428mtx_lock(mixer_lock);429}430431right = left;432433RKCODEC_LOCK(sc);434switch(dev) {435case SOUND_MIXER_VOLUME:436break;437438case SOUND_MIXER_MIC:439break;440default:441break;442}443RKCODEC_UNLOCK(sc);444445if (do_unlock) {446mtx_unlock(mixer_lock);447}448449return (left | (right << 8));450}451452static unsigned453rkcodec_mixer_setrecsrc(struct snd_mixer *m, unsigned src)454{455456return (0);457}458459static kobj_method_t rkcodec_mixer_methods[] = {460KOBJMETHOD(mixer_init, rkcodec_mixer_init),461KOBJMETHOD(mixer_uninit, rkcodec_mixer_uninit),462KOBJMETHOD(mixer_reinit, rkcodec_mixer_reinit),463KOBJMETHOD(mixer_set, rkcodec_mixer_set),464KOBJMETHOD(mixer_setrecsrc, rkcodec_mixer_setrecsrc),465KOBJMETHOD_END466};467468MIXER_DECLARE(rkcodec_mixer);469470static int471rkcodec_dai_init(device_t dev, uint32_t format)472{473struct rkcodec_softc *sc;474int fmt, pol, clk;475uint32_t ctrl1, ctrl2, ctrl3;476477sc = device_get_softc(dev);478479fmt = AUDIO_DAI_FORMAT_FORMAT(format);480pol = AUDIO_DAI_FORMAT_POLARITY(format);481clk = AUDIO_DAI_FORMAT_CLOCK(format);482483ctrl1 = RKCODEC_READ(sc, CODEC_DAC_INIT_CTRL1);484ctrl2 = RKCODEC_READ(sc, CODEC_DAC_INIT_CTRL2);485ctrl3 = RKCODEC_READ(sc, CODEC_DAC_INIT_CTRL3);486487ctrl3 &= ~(DAC_INIT_CTRL3_DAC_BCP_MASK);488switch (pol) {489case AUDIO_DAI_POLARITY_IB_NF:490ctrl3 |= DAC_INIT_CTRL3_DAC_BCP_REVERSAL;491break;492case AUDIO_DAI_POLARITY_NB_NF:493ctrl3 |= DAC_INIT_CTRL3_DAC_BCP_NORMAL;494break;495default:496return (EINVAL);497}498499ctrl1 &= ~(DAC_INIT_CTRL1_MODE_MASK);500switch (clk) {501case AUDIO_DAI_CLOCK_CBM_CFM:502ctrl1 |= DAC_INIT_CTRL1_DIRECTION_OUT |503DAC_INIT_CTRL1_DAC_I2S_MODE_SLAVE;504break;505case AUDIO_DAI_CLOCK_CBS_CFS:506ctrl1 |= DAC_INIT_CTRL1_DIRECTION_IN |507DAC_INIT_CTRL1_DAC_I2S_MODE_SLAVE;508break;509default:510return (EINVAL);511}512513ctrl2 &= ~(DAC_INIT_CTRL2_DAC_VDL_MASK | DAC_INIT_CTRL2_DAC_MODE_MASK);514ctrl2 |= DAC_INIT_CTRL2_DAC_VDL_16BITS;515ctrl3 &= ~(DAC_INIT_CTRL3_WL_MASK);516ctrl3 |= DAC_INIT_CTRL3_WL_32BITS;517switch (fmt) {518case AUDIO_DAI_FORMAT_I2S:519ctrl2 |= DAC_INIT_CTRL2_DAC_MODE_I2S;520break;521case AUDIO_DAI_FORMAT_LJ:522ctrl2 |= DAC_INIT_CTRL2_DAC_MODE_LJM;523break;524case AUDIO_DAI_FORMAT_RJ:525ctrl2 |= DAC_INIT_CTRL2_DAC_MODE_RJM;526break;527default:528return EINVAL;529}530531ctrl3 &= ~(DAC_INIT_CTRL3_RST_MASK);532ctrl3 |= DAC_INIT_CTRL3_RST_DIS;533534RKCODEC_WRITE(sc, CODEC_DAC_INIT_CTRL1, ctrl1);535RKCODEC_WRITE(sc, CODEC_DAC_INIT_CTRL2, ctrl2);536RKCODEC_WRITE(sc, CODEC_DAC_INIT_CTRL3, ctrl3);537538return (0);539}540541static int542rkcodec_dai_trigger(device_t dev, int go, int pcm_dir)543{544// struct rkcodec_softc *sc = device_get_softc(dev);545546if (pcm_dir != PCMDIR_PLAY && pcm_dir != PCMDIR_REC)547return (EINVAL);548549switch (go) {550case PCMTRIG_START:551break;552553case PCMTRIG_STOP:554case PCMTRIG_ABORT:555break;556}557558return (0);559}560561static int562rkcodec_dai_setup_mixer(device_t dev, device_t pcmdev)563{564565mixer_init(pcmdev, &rkcodec_mixer_class, dev);566567return (0);568}569570static int571rkcodec_dai_set_sysclk(device_t dev, unsigned int rate, int dai_dir)572{573return (0);574}575576static device_method_t rkcodec_methods[] = {577/* Device interface */578DEVMETHOD(device_probe, rkcodec_probe),579DEVMETHOD(device_attach, rkcodec_attach),580DEVMETHOD(device_detach, rkcodec_detach),581582DEVMETHOD(audio_dai_init, rkcodec_dai_init),583DEVMETHOD(audio_dai_setup_mixer, rkcodec_dai_setup_mixer),584DEVMETHOD(audio_dai_trigger, rkcodec_dai_trigger),585DEVMETHOD(audio_dai_set_sysclk, rkcodec_dai_set_sysclk),586587DEVMETHOD_END588};589590static driver_t rkcodec_driver = {591"rk3328codec",592rkcodec_methods,593sizeof(struct rkcodec_softc),594};595596DRIVER_MODULE(rkcodec, simplebus, rkcodec_driver, 0, 0);597SIMPLEBUS_PNP_INFO(compat_data);598599600