1*c3275903SKatsuhiro Suzuki // SPDX-License-Identifier: GPL-2.0 2*c3275903SKatsuhiro Suzuki // 3*c3275903SKatsuhiro Suzuki // rk3328 ALSA SoC Audio driver 4*c3275903SKatsuhiro Suzuki // 5*c3275903SKatsuhiro Suzuki // Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd All rights reserved. 6*c3275903SKatsuhiro Suzuki 7*c3275903SKatsuhiro Suzuki #include <linux/clk.h> 8*c3275903SKatsuhiro Suzuki #include <linux/delay.h> 9*c3275903SKatsuhiro Suzuki #include <linux/device.h> 10*c3275903SKatsuhiro Suzuki #include <linux/module.h> 11*c3275903SKatsuhiro Suzuki #include <linux/of.h> 12*c3275903SKatsuhiro Suzuki #include <linux/platform_device.h> 13*c3275903SKatsuhiro Suzuki #include <linux/pm_runtime.h> 14*c3275903SKatsuhiro Suzuki #include <linux/regmap.h> 15*c3275903SKatsuhiro Suzuki #include <linux/mfd/syscon.h> 16*c3275903SKatsuhiro Suzuki #include <sound/dmaengine_pcm.h> 17*c3275903SKatsuhiro Suzuki #include <sound/pcm_params.h> 18*c3275903SKatsuhiro Suzuki #include "rk3328_codec.h" 19*c3275903SKatsuhiro Suzuki 20*c3275903SKatsuhiro Suzuki /* 21*c3275903SKatsuhiro Suzuki * volume setting 22*c3275903SKatsuhiro Suzuki * 0: -39dB 23*c3275903SKatsuhiro Suzuki * 26: 0dB 24*c3275903SKatsuhiro Suzuki * 31: 6dB 25*c3275903SKatsuhiro Suzuki * Step: 1.5dB 26*c3275903SKatsuhiro Suzuki */ 27*c3275903SKatsuhiro Suzuki #define OUT_VOLUME (0x18) 28*c3275903SKatsuhiro Suzuki #define RK3328_GRF_SOC_CON2 (0x0408) 29*c3275903SKatsuhiro Suzuki #define RK3328_GRF_SOC_CON10 (0x0428) 30*c3275903SKatsuhiro Suzuki #define INITIAL_FREQ (11289600) 31*c3275903SKatsuhiro Suzuki 32*c3275903SKatsuhiro Suzuki struct rk3328_codec_priv { 33*c3275903SKatsuhiro Suzuki struct regmap *regmap; 34*c3275903SKatsuhiro Suzuki struct regmap *grf; 35*c3275903SKatsuhiro Suzuki struct clk *mclk; 36*c3275903SKatsuhiro Suzuki struct clk *pclk; 37*c3275903SKatsuhiro Suzuki unsigned int sclk; 38*c3275903SKatsuhiro Suzuki int spk_depop_time; /* msec */ 39*c3275903SKatsuhiro Suzuki }; 40*c3275903SKatsuhiro Suzuki 41*c3275903SKatsuhiro Suzuki static const struct reg_default rk3328_codec_reg_defaults[] = { 42*c3275903SKatsuhiro Suzuki { CODEC_RESET, 0x03 }, 43*c3275903SKatsuhiro Suzuki { DAC_INIT_CTRL1, 0x00 }, 44*c3275903SKatsuhiro Suzuki { DAC_INIT_CTRL2, 0x50 }, 45*c3275903SKatsuhiro Suzuki { DAC_INIT_CTRL3, 0x0e }, 46*c3275903SKatsuhiro Suzuki { DAC_PRECHARGE_CTRL, 0x01 }, 47*c3275903SKatsuhiro Suzuki { DAC_PWR_CTRL, 0x00 }, 48*c3275903SKatsuhiro Suzuki { DAC_CLK_CTRL, 0x00 }, 49*c3275903SKatsuhiro Suzuki { HPMIX_CTRL, 0x00 }, 50*c3275903SKatsuhiro Suzuki { HPOUT_CTRL, 0x00 }, 51*c3275903SKatsuhiro Suzuki { HPOUTL_GAIN_CTRL, 0x00 }, 52*c3275903SKatsuhiro Suzuki { HPOUTR_GAIN_CTRL, 0x00 }, 53*c3275903SKatsuhiro Suzuki { HPOUT_POP_CTRL, 0x11 }, 54*c3275903SKatsuhiro Suzuki }; 55*c3275903SKatsuhiro Suzuki 56*c3275903SKatsuhiro Suzuki static int rk3328_codec_reset(struct rk3328_codec_priv *rk3328) 57*c3275903SKatsuhiro Suzuki { 58*c3275903SKatsuhiro Suzuki regmap_write(rk3328->regmap, CODEC_RESET, 0x00); 59*c3275903SKatsuhiro Suzuki mdelay(10); 60*c3275903SKatsuhiro Suzuki regmap_write(rk3328->regmap, CODEC_RESET, 0x03); 61*c3275903SKatsuhiro Suzuki 62*c3275903SKatsuhiro Suzuki return 0; 63*c3275903SKatsuhiro Suzuki } 64*c3275903SKatsuhiro Suzuki 65*c3275903SKatsuhiro Suzuki static int rk3328_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) 66*c3275903SKatsuhiro Suzuki { 67*c3275903SKatsuhiro Suzuki struct rk3328_codec_priv *rk3328 = 68*c3275903SKatsuhiro Suzuki snd_soc_component_get_drvdata(dai->component); 69*c3275903SKatsuhiro Suzuki unsigned int val; 70*c3275903SKatsuhiro Suzuki 71*c3275903SKatsuhiro Suzuki switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 72*c3275903SKatsuhiro Suzuki case SND_SOC_DAIFMT_CBS_CFS: 73*c3275903SKatsuhiro Suzuki val = PIN_DIRECTION_IN | DAC_I2S_MODE_SLAVE; 74*c3275903SKatsuhiro Suzuki break; 75*c3275903SKatsuhiro Suzuki case SND_SOC_DAIFMT_CBM_CFM: 76*c3275903SKatsuhiro Suzuki val = PIN_DIRECTION_OUT | DAC_I2S_MODE_MASTER; 77*c3275903SKatsuhiro Suzuki break; 78*c3275903SKatsuhiro Suzuki default: 79*c3275903SKatsuhiro Suzuki return -EINVAL; 80*c3275903SKatsuhiro Suzuki } 81*c3275903SKatsuhiro Suzuki 82*c3275903SKatsuhiro Suzuki regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL1, 83*c3275903SKatsuhiro Suzuki PIN_DIRECTION_MASK | DAC_I2S_MODE_MASK, val); 84*c3275903SKatsuhiro Suzuki 85*c3275903SKatsuhiro Suzuki switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 86*c3275903SKatsuhiro Suzuki case SND_SOC_DAIFMT_DSP_A: 87*c3275903SKatsuhiro Suzuki case SND_SOC_DAIFMT_DSP_B: 88*c3275903SKatsuhiro Suzuki val = DAC_MODE_PCM; 89*c3275903SKatsuhiro Suzuki break; 90*c3275903SKatsuhiro Suzuki case SND_SOC_DAIFMT_I2S: 91*c3275903SKatsuhiro Suzuki val = DAC_MODE_I2S; 92*c3275903SKatsuhiro Suzuki break; 93*c3275903SKatsuhiro Suzuki case SND_SOC_DAIFMT_RIGHT_J: 94*c3275903SKatsuhiro Suzuki val = DAC_MODE_RJM; 95*c3275903SKatsuhiro Suzuki break; 96*c3275903SKatsuhiro Suzuki case SND_SOC_DAIFMT_LEFT_J: 97*c3275903SKatsuhiro Suzuki val = DAC_MODE_LJM; 98*c3275903SKatsuhiro Suzuki break; 99*c3275903SKatsuhiro Suzuki default: 100*c3275903SKatsuhiro Suzuki return -EINVAL; 101*c3275903SKatsuhiro Suzuki } 102*c3275903SKatsuhiro Suzuki 103*c3275903SKatsuhiro Suzuki regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL2, 104*c3275903SKatsuhiro Suzuki DAC_MODE_MASK, val); 105*c3275903SKatsuhiro Suzuki 106*c3275903SKatsuhiro Suzuki return 0; 107*c3275903SKatsuhiro Suzuki } 108*c3275903SKatsuhiro Suzuki 109*c3275903SKatsuhiro Suzuki static void rk3328_analog_output(struct rk3328_codec_priv *rk3328, int mute) 110*c3275903SKatsuhiro Suzuki { 111*c3275903SKatsuhiro Suzuki unsigned int val = BIT(17); 112*c3275903SKatsuhiro Suzuki 113*c3275903SKatsuhiro Suzuki if (mute) 114*c3275903SKatsuhiro Suzuki val |= BIT(1); 115*c3275903SKatsuhiro Suzuki 116*c3275903SKatsuhiro Suzuki regmap_write(rk3328->grf, RK3328_GRF_SOC_CON10, val); 117*c3275903SKatsuhiro Suzuki } 118*c3275903SKatsuhiro Suzuki 119*c3275903SKatsuhiro Suzuki static int rk3328_digital_mute(struct snd_soc_dai *dai, int mute) 120*c3275903SKatsuhiro Suzuki { 121*c3275903SKatsuhiro Suzuki struct rk3328_codec_priv *rk3328 = 122*c3275903SKatsuhiro Suzuki snd_soc_component_get_drvdata(dai->component); 123*c3275903SKatsuhiro Suzuki unsigned int val; 124*c3275903SKatsuhiro Suzuki 125*c3275903SKatsuhiro Suzuki if (mute) 126*c3275903SKatsuhiro Suzuki val = HPOUTL_MUTE | HPOUTR_MUTE; 127*c3275903SKatsuhiro Suzuki else 128*c3275903SKatsuhiro Suzuki val = HPOUTL_UNMUTE | HPOUTR_UNMUTE; 129*c3275903SKatsuhiro Suzuki 130*c3275903SKatsuhiro Suzuki regmap_update_bits(rk3328->regmap, HPOUT_CTRL, 131*c3275903SKatsuhiro Suzuki HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK, val); 132*c3275903SKatsuhiro Suzuki 133*c3275903SKatsuhiro Suzuki return 0; 134*c3275903SKatsuhiro Suzuki } 135*c3275903SKatsuhiro Suzuki 136*c3275903SKatsuhiro Suzuki static int rk3328_codec_power_on(struct rk3328_codec_priv *rk3328, int wait_ms) 137*c3275903SKatsuhiro Suzuki { 138*c3275903SKatsuhiro Suzuki regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL, 139*c3275903SKatsuhiro Suzuki DAC_CHARGE_XCHARGE_MASK, DAC_CHARGE_PRECHARGE); 140*c3275903SKatsuhiro Suzuki mdelay(10); 141*c3275903SKatsuhiro Suzuki regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL, 142*c3275903SKatsuhiro Suzuki DAC_CHARGE_CURRENT_ALL_MASK, 143*c3275903SKatsuhiro Suzuki DAC_CHARGE_CURRENT_ALL_ON); 144*c3275903SKatsuhiro Suzuki mdelay(wait_ms); 145*c3275903SKatsuhiro Suzuki 146*c3275903SKatsuhiro Suzuki return 0; 147*c3275903SKatsuhiro Suzuki } 148*c3275903SKatsuhiro Suzuki 149*c3275903SKatsuhiro Suzuki static int rk3328_codec_power_off(struct rk3328_codec_priv *rk3328, int wait_ms) 150*c3275903SKatsuhiro Suzuki { 151*c3275903SKatsuhiro Suzuki regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL, 152*c3275903SKatsuhiro Suzuki DAC_CHARGE_XCHARGE_MASK, DAC_CHARGE_DISCHARGE); 153*c3275903SKatsuhiro Suzuki mdelay(10); 154*c3275903SKatsuhiro Suzuki regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL, 155*c3275903SKatsuhiro Suzuki DAC_CHARGE_CURRENT_ALL_MASK, 156*c3275903SKatsuhiro Suzuki DAC_CHARGE_CURRENT_ALL_ON); 157*c3275903SKatsuhiro Suzuki mdelay(wait_ms); 158*c3275903SKatsuhiro Suzuki 159*c3275903SKatsuhiro Suzuki return 0; 160*c3275903SKatsuhiro Suzuki } 161*c3275903SKatsuhiro Suzuki 162*c3275903SKatsuhiro Suzuki static const struct rk3328_reg_msk_val playback_open_list[] = { 163*c3275903SKatsuhiro Suzuki { DAC_PWR_CTRL, DAC_PWR_MASK, DAC_PWR_ON }, 164*c3275903SKatsuhiro Suzuki { DAC_PWR_CTRL, DACL_PATH_REFV_MASK | DACR_PATH_REFV_MASK, 165*c3275903SKatsuhiro Suzuki DACL_PATH_REFV_ON | DACR_PATH_REFV_ON }, 166*c3275903SKatsuhiro Suzuki { DAC_PWR_CTRL, HPOUTL_ZERO_CROSSING_MASK | HPOUTR_ZERO_CROSSING_MASK, 167*c3275903SKatsuhiro Suzuki HPOUTL_ZERO_CROSSING_ON | HPOUTR_ZERO_CROSSING_ON }, 168*c3275903SKatsuhiro Suzuki { HPOUT_POP_CTRL, HPOUTR_POP_MASK | HPOUTL_POP_MASK, 169*c3275903SKatsuhiro Suzuki HPOUTR_POP_WORK | HPOUTL_POP_WORK }, 170*c3275903SKatsuhiro Suzuki { HPMIX_CTRL, HPMIXL_MASK | HPMIXR_MASK, HPMIXL_EN | HPMIXR_EN }, 171*c3275903SKatsuhiro Suzuki { HPMIX_CTRL, HPMIXL_INIT_MASK | HPMIXR_INIT_MASK, 172*c3275903SKatsuhiro Suzuki HPMIXL_INIT_EN | HPMIXR_INIT_EN }, 173*c3275903SKatsuhiro Suzuki { HPOUT_CTRL, HPOUTL_MASK | HPOUTR_MASK, HPOUTL_EN | HPOUTR_EN }, 174*c3275903SKatsuhiro Suzuki { HPOUT_CTRL, HPOUTL_INIT_MASK | HPOUTR_INIT_MASK, 175*c3275903SKatsuhiro Suzuki HPOUTL_INIT_EN | HPOUTR_INIT_EN }, 176*c3275903SKatsuhiro Suzuki { DAC_CLK_CTRL, DACL_REFV_MASK | DACR_REFV_MASK, 177*c3275903SKatsuhiro Suzuki DACL_REFV_ON | DACR_REFV_ON }, 178*c3275903SKatsuhiro Suzuki { DAC_CLK_CTRL, DACL_CLK_MASK | DACR_CLK_MASK, 179*c3275903SKatsuhiro Suzuki DACL_CLK_ON | DACR_CLK_ON }, 180*c3275903SKatsuhiro Suzuki { DAC_CLK_CTRL, DACL_MASK | DACR_MASK, DACL_ON | DACR_ON }, 181*c3275903SKatsuhiro Suzuki { DAC_CLK_CTRL, DACL_INIT_MASK | DACR_INIT_MASK, 182*c3275903SKatsuhiro Suzuki DACL_INIT_ON | DACR_INIT_ON }, 183*c3275903SKatsuhiro Suzuki { DAC_SELECT, DACL_SELECT_MASK | DACR_SELECT_MASK, 184*c3275903SKatsuhiro Suzuki DACL_SELECT | DACR_SELECT }, 185*c3275903SKatsuhiro Suzuki { HPMIX_CTRL, HPMIXL_INIT2_MASK | HPMIXR_INIT2_MASK, 186*c3275903SKatsuhiro Suzuki HPMIXL_INIT2_EN | HPMIXR_INIT2_EN }, 187*c3275903SKatsuhiro Suzuki { HPOUT_CTRL, HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK, 188*c3275903SKatsuhiro Suzuki HPOUTL_UNMUTE | HPOUTR_UNMUTE }, 189*c3275903SKatsuhiro Suzuki }; 190*c3275903SKatsuhiro Suzuki 191*c3275903SKatsuhiro Suzuki static int rk3328_codec_open_playback(struct rk3328_codec_priv *rk3328) 192*c3275903SKatsuhiro Suzuki { 193*c3275903SKatsuhiro Suzuki int i; 194*c3275903SKatsuhiro Suzuki 195*c3275903SKatsuhiro Suzuki regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL, 196*c3275903SKatsuhiro Suzuki DAC_CHARGE_CURRENT_ALL_MASK, 197*c3275903SKatsuhiro Suzuki DAC_CHARGE_CURRENT_I); 198*c3275903SKatsuhiro Suzuki 199*c3275903SKatsuhiro Suzuki for (i = 0; i < ARRAY_SIZE(playback_open_list); i++) { 200*c3275903SKatsuhiro Suzuki regmap_update_bits(rk3328->regmap, 201*c3275903SKatsuhiro Suzuki playback_open_list[i].reg, 202*c3275903SKatsuhiro Suzuki playback_open_list[i].msk, 203*c3275903SKatsuhiro Suzuki playback_open_list[i].val); 204*c3275903SKatsuhiro Suzuki mdelay(1); 205*c3275903SKatsuhiro Suzuki } 206*c3275903SKatsuhiro Suzuki 207*c3275903SKatsuhiro Suzuki msleep(rk3328->spk_depop_time); 208*c3275903SKatsuhiro Suzuki rk3328_analog_output(rk3328, 1); 209*c3275903SKatsuhiro Suzuki 210*c3275903SKatsuhiro Suzuki regmap_update_bits(rk3328->regmap, HPOUTL_GAIN_CTRL, 211*c3275903SKatsuhiro Suzuki HPOUTL_GAIN_MASK, OUT_VOLUME); 212*c3275903SKatsuhiro Suzuki regmap_update_bits(rk3328->regmap, HPOUTR_GAIN_CTRL, 213*c3275903SKatsuhiro Suzuki HPOUTR_GAIN_MASK, OUT_VOLUME); 214*c3275903SKatsuhiro Suzuki 215*c3275903SKatsuhiro Suzuki return 0; 216*c3275903SKatsuhiro Suzuki } 217*c3275903SKatsuhiro Suzuki 218*c3275903SKatsuhiro Suzuki static const struct rk3328_reg_msk_val playback_close_list[] = { 219*c3275903SKatsuhiro Suzuki { HPMIX_CTRL, HPMIXL_INIT2_MASK | HPMIXR_INIT2_MASK, 220*c3275903SKatsuhiro Suzuki HPMIXL_INIT2_DIS | HPMIXR_INIT2_DIS }, 221*c3275903SKatsuhiro Suzuki { DAC_SELECT, DACL_SELECT_MASK | DACR_SELECT_MASK, 222*c3275903SKatsuhiro Suzuki DACL_UNSELECT | DACR_UNSELECT }, 223*c3275903SKatsuhiro Suzuki { HPOUT_CTRL, HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK, 224*c3275903SKatsuhiro Suzuki HPOUTL_MUTE | HPOUTR_MUTE }, 225*c3275903SKatsuhiro Suzuki { HPOUT_CTRL, HPOUTL_INIT_MASK | HPOUTR_INIT_MASK, 226*c3275903SKatsuhiro Suzuki HPOUTL_INIT_DIS | HPOUTR_INIT_DIS }, 227*c3275903SKatsuhiro Suzuki { HPOUT_CTRL, HPOUTL_MASK | HPOUTR_MASK, HPOUTL_DIS | HPOUTR_DIS }, 228*c3275903SKatsuhiro Suzuki { HPMIX_CTRL, HPMIXL_MASK | HPMIXR_MASK, HPMIXL_DIS | HPMIXR_DIS }, 229*c3275903SKatsuhiro Suzuki { DAC_CLK_CTRL, DACL_MASK | DACR_MASK, DACL_OFF | DACR_OFF }, 230*c3275903SKatsuhiro Suzuki { DAC_CLK_CTRL, DACL_CLK_MASK | DACR_CLK_MASK, 231*c3275903SKatsuhiro Suzuki DACL_CLK_OFF | DACR_CLK_OFF }, 232*c3275903SKatsuhiro Suzuki { DAC_CLK_CTRL, DACL_REFV_MASK | DACR_REFV_MASK, 233*c3275903SKatsuhiro Suzuki DACL_REFV_OFF | DACR_REFV_OFF }, 234*c3275903SKatsuhiro Suzuki { HPOUT_POP_CTRL, HPOUTR_POP_MASK | HPOUTL_POP_MASK, 235*c3275903SKatsuhiro Suzuki HPOUTR_POP_XCHARGE | HPOUTL_POP_XCHARGE }, 236*c3275903SKatsuhiro Suzuki { DAC_PWR_CTRL, DACL_PATH_REFV_MASK | DACR_PATH_REFV_MASK, 237*c3275903SKatsuhiro Suzuki DACL_PATH_REFV_OFF | DACR_PATH_REFV_OFF }, 238*c3275903SKatsuhiro Suzuki { DAC_PWR_CTRL, DAC_PWR_MASK, DAC_PWR_OFF }, 239*c3275903SKatsuhiro Suzuki { HPMIX_CTRL, HPMIXL_INIT_MASK | HPMIXR_INIT_MASK, 240*c3275903SKatsuhiro Suzuki HPMIXL_INIT_DIS | HPMIXR_INIT_DIS }, 241*c3275903SKatsuhiro Suzuki { DAC_CLK_CTRL, DACL_INIT_MASK | DACR_INIT_MASK, 242*c3275903SKatsuhiro Suzuki DACL_INIT_OFF | DACR_INIT_OFF }, 243*c3275903SKatsuhiro Suzuki }; 244*c3275903SKatsuhiro Suzuki 245*c3275903SKatsuhiro Suzuki static int rk3328_codec_close_playback(struct rk3328_codec_priv *rk3328) 246*c3275903SKatsuhiro Suzuki { 247*c3275903SKatsuhiro Suzuki size_t i; 248*c3275903SKatsuhiro Suzuki 249*c3275903SKatsuhiro Suzuki rk3328_analog_output(rk3328, 0); 250*c3275903SKatsuhiro Suzuki 251*c3275903SKatsuhiro Suzuki regmap_update_bits(rk3328->regmap, HPOUTL_GAIN_CTRL, 252*c3275903SKatsuhiro Suzuki HPOUTL_GAIN_MASK, 0); 253*c3275903SKatsuhiro Suzuki regmap_update_bits(rk3328->regmap, HPOUTR_GAIN_CTRL, 254*c3275903SKatsuhiro Suzuki HPOUTR_GAIN_MASK, 0); 255*c3275903SKatsuhiro Suzuki 256*c3275903SKatsuhiro Suzuki for (i = 0; i < ARRAY_SIZE(playback_close_list); i++) { 257*c3275903SKatsuhiro Suzuki regmap_update_bits(rk3328->regmap, 258*c3275903SKatsuhiro Suzuki playback_close_list[i].reg, 259*c3275903SKatsuhiro Suzuki playback_close_list[i].msk, 260*c3275903SKatsuhiro Suzuki playback_close_list[i].val); 261*c3275903SKatsuhiro Suzuki mdelay(1); 262*c3275903SKatsuhiro Suzuki } 263*c3275903SKatsuhiro Suzuki 264*c3275903SKatsuhiro Suzuki regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL, 265*c3275903SKatsuhiro Suzuki DAC_CHARGE_CURRENT_ALL_MASK, 266*c3275903SKatsuhiro Suzuki DAC_CHARGE_CURRENT_I); 267*c3275903SKatsuhiro Suzuki 268*c3275903SKatsuhiro Suzuki return 0; 269*c3275903SKatsuhiro Suzuki } 270*c3275903SKatsuhiro Suzuki 271*c3275903SKatsuhiro Suzuki static int rk3328_hw_params(struct snd_pcm_substream *substream, 272*c3275903SKatsuhiro Suzuki struct snd_pcm_hw_params *params, 273*c3275903SKatsuhiro Suzuki struct snd_soc_dai *dai) 274*c3275903SKatsuhiro Suzuki { 275*c3275903SKatsuhiro Suzuki struct rk3328_codec_priv *rk3328 = 276*c3275903SKatsuhiro Suzuki snd_soc_component_get_drvdata(dai->component); 277*c3275903SKatsuhiro Suzuki unsigned int val = 0; 278*c3275903SKatsuhiro Suzuki 279*c3275903SKatsuhiro Suzuki switch (params_format(params)) { 280*c3275903SKatsuhiro Suzuki case SNDRV_PCM_FORMAT_S16_LE: 281*c3275903SKatsuhiro Suzuki val = DAC_VDL_16BITS; 282*c3275903SKatsuhiro Suzuki break; 283*c3275903SKatsuhiro Suzuki case SNDRV_PCM_FORMAT_S20_3LE: 284*c3275903SKatsuhiro Suzuki val = DAC_VDL_20BITS; 285*c3275903SKatsuhiro Suzuki break; 286*c3275903SKatsuhiro Suzuki case SNDRV_PCM_FORMAT_S24_LE: 287*c3275903SKatsuhiro Suzuki val = DAC_VDL_24BITS; 288*c3275903SKatsuhiro Suzuki break; 289*c3275903SKatsuhiro Suzuki case SNDRV_PCM_FORMAT_S32_LE: 290*c3275903SKatsuhiro Suzuki val = DAC_VDL_32BITS; 291*c3275903SKatsuhiro Suzuki break; 292*c3275903SKatsuhiro Suzuki default: 293*c3275903SKatsuhiro Suzuki return -EINVAL; 294*c3275903SKatsuhiro Suzuki } 295*c3275903SKatsuhiro Suzuki regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL2, DAC_VDL_MASK, val); 296*c3275903SKatsuhiro Suzuki 297*c3275903SKatsuhiro Suzuki val = DAC_WL_32BITS | DAC_RST_DIS; 298*c3275903SKatsuhiro Suzuki regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL3, 299*c3275903SKatsuhiro Suzuki DAC_WL_MASK | DAC_RST_MASK, val); 300*c3275903SKatsuhiro Suzuki 301*c3275903SKatsuhiro Suzuki return 0; 302*c3275903SKatsuhiro Suzuki } 303*c3275903SKatsuhiro Suzuki 304*c3275903SKatsuhiro Suzuki static int rk3328_pcm_startup(struct snd_pcm_substream *substream, 305*c3275903SKatsuhiro Suzuki struct snd_soc_dai *dai) 306*c3275903SKatsuhiro Suzuki { 307*c3275903SKatsuhiro Suzuki struct rk3328_codec_priv *rk3328 = 308*c3275903SKatsuhiro Suzuki snd_soc_component_get_drvdata(dai->component); 309*c3275903SKatsuhiro Suzuki 310*c3275903SKatsuhiro Suzuki return rk3328_codec_open_playback(rk3328); 311*c3275903SKatsuhiro Suzuki } 312*c3275903SKatsuhiro Suzuki 313*c3275903SKatsuhiro Suzuki static void rk3328_pcm_shutdown(struct snd_pcm_substream *substream, 314*c3275903SKatsuhiro Suzuki struct snd_soc_dai *dai) 315*c3275903SKatsuhiro Suzuki { 316*c3275903SKatsuhiro Suzuki struct rk3328_codec_priv *rk3328 = 317*c3275903SKatsuhiro Suzuki snd_soc_component_get_drvdata(dai->component); 318*c3275903SKatsuhiro Suzuki 319*c3275903SKatsuhiro Suzuki rk3328_codec_close_playback(rk3328); 320*c3275903SKatsuhiro Suzuki } 321*c3275903SKatsuhiro Suzuki 322*c3275903SKatsuhiro Suzuki static const struct snd_soc_dai_ops rk3328_dai_ops = { 323*c3275903SKatsuhiro Suzuki .hw_params = rk3328_hw_params, 324*c3275903SKatsuhiro Suzuki .set_fmt = rk3328_set_dai_fmt, 325*c3275903SKatsuhiro Suzuki .digital_mute = rk3328_digital_mute, 326*c3275903SKatsuhiro Suzuki .startup = rk3328_pcm_startup, 327*c3275903SKatsuhiro Suzuki .shutdown = rk3328_pcm_shutdown, 328*c3275903SKatsuhiro Suzuki }; 329*c3275903SKatsuhiro Suzuki 330*c3275903SKatsuhiro Suzuki static struct snd_soc_dai_driver rk3328_dai[] = { 331*c3275903SKatsuhiro Suzuki { 332*c3275903SKatsuhiro Suzuki .name = "rk3328-hifi", 333*c3275903SKatsuhiro Suzuki .id = RK3328_HIFI, 334*c3275903SKatsuhiro Suzuki .playback = { 335*c3275903SKatsuhiro Suzuki .stream_name = "HIFI Playback", 336*c3275903SKatsuhiro Suzuki .channels_min = 1, 337*c3275903SKatsuhiro Suzuki .channels_max = 2, 338*c3275903SKatsuhiro Suzuki .rates = SNDRV_PCM_RATE_8000_96000, 339*c3275903SKatsuhiro Suzuki .formats = (SNDRV_PCM_FMTBIT_S16_LE | 340*c3275903SKatsuhiro Suzuki SNDRV_PCM_FMTBIT_S20_3LE | 341*c3275903SKatsuhiro Suzuki SNDRV_PCM_FMTBIT_S24_LE | 342*c3275903SKatsuhiro Suzuki SNDRV_PCM_FMTBIT_S32_LE), 343*c3275903SKatsuhiro Suzuki }, 344*c3275903SKatsuhiro Suzuki .capture = { 345*c3275903SKatsuhiro Suzuki .stream_name = "HIFI Capture", 346*c3275903SKatsuhiro Suzuki .channels_min = 2, 347*c3275903SKatsuhiro Suzuki .channels_max = 8, 348*c3275903SKatsuhiro Suzuki .rates = SNDRV_PCM_RATE_8000_96000, 349*c3275903SKatsuhiro Suzuki .formats = (SNDRV_PCM_FMTBIT_S16_LE | 350*c3275903SKatsuhiro Suzuki SNDRV_PCM_FMTBIT_S20_3LE | 351*c3275903SKatsuhiro Suzuki SNDRV_PCM_FMTBIT_S24_LE | 352*c3275903SKatsuhiro Suzuki SNDRV_PCM_FMTBIT_S32_LE), 353*c3275903SKatsuhiro Suzuki }, 354*c3275903SKatsuhiro Suzuki .ops = &rk3328_dai_ops, 355*c3275903SKatsuhiro Suzuki }, 356*c3275903SKatsuhiro Suzuki }; 357*c3275903SKatsuhiro Suzuki 358*c3275903SKatsuhiro Suzuki static int rk3328_codec_probe(struct snd_soc_component *component) 359*c3275903SKatsuhiro Suzuki { 360*c3275903SKatsuhiro Suzuki struct rk3328_codec_priv *rk3328 = 361*c3275903SKatsuhiro Suzuki snd_soc_component_get_drvdata(component); 362*c3275903SKatsuhiro Suzuki 363*c3275903SKatsuhiro Suzuki rk3328_codec_reset(rk3328); 364*c3275903SKatsuhiro Suzuki rk3328_codec_power_on(rk3328, 0); 365*c3275903SKatsuhiro Suzuki 366*c3275903SKatsuhiro Suzuki return 0; 367*c3275903SKatsuhiro Suzuki } 368*c3275903SKatsuhiro Suzuki 369*c3275903SKatsuhiro Suzuki static void rk3328_codec_remove(struct snd_soc_component *component) 370*c3275903SKatsuhiro Suzuki { 371*c3275903SKatsuhiro Suzuki struct rk3328_codec_priv *rk3328 = 372*c3275903SKatsuhiro Suzuki snd_soc_component_get_drvdata(component); 373*c3275903SKatsuhiro Suzuki 374*c3275903SKatsuhiro Suzuki rk3328_codec_close_playback(rk3328); 375*c3275903SKatsuhiro Suzuki rk3328_codec_power_off(rk3328, 0); 376*c3275903SKatsuhiro Suzuki } 377*c3275903SKatsuhiro Suzuki 378*c3275903SKatsuhiro Suzuki static const struct snd_soc_component_driver soc_codec_rk3328 = { 379*c3275903SKatsuhiro Suzuki .probe = rk3328_codec_probe, 380*c3275903SKatsuhiro Suzuki .remove = rk3328_codec_remove, 381*c3275903SKatsuhiro Suzuki }; 382*c3275903SKatsuhiro Suzuki 383*c3275903SKatsuhiro Suzuki static bool rk3328_codec_write_read_reg(struct device *dev, unsigned int reg) 384*c3275903SKatsuhiro Suzuki { 385*c3275903SKatsuhiro Suzuki switch (reg) { 386*c3275903SKatsuhiro Suzuki case CODEC_RESET: 387*c3275903SKatsuhiro Suzuki case DAC_INIT_CTRL1: 388*c3275903SKatsuhiro Suzuki case DAC_INIT_CTRL2: 389*c3275903SKatsuhiro Suzuki case DAC_INIT_CTRL3: 390*c3275903SKatsuhiro Suzuki case DAC_PRECHARGE_CTRL: 391*c3275903SKatsuhiro Suzuki case DAC_PWR_CTRL: 392*c3275903SKatsuhiro Suzuki case DAC_CLK_CTRL: 393*c3275903SKatsuhiro Suzuki case HPMIX_CTRL: 394*c3275903SKatsuhiro Suzuki case DAC_SELECT: 395*c3275903SKatsuhiro Suzuki case HPOUT_CTRL: 396*c3275903SKatsuhiro Suzuki case HPOUTL_GAIN_CTRL: 397*c3275903SKatsuhiro Suzuki case HPOUTR_GAIN_CTRL: 398*c3275903SKatsuhiro Suzuki case HPOUT_POP_CTRL: 399*c3275903SKatsuhiro Suzuki return true; 400*c3275903SKatsuhiro Suzuki default: 401*c3275903SKatsuhiro Suzuki return false; 402*c3275903SKatsuhiro Suzuki } 403*c3275903SKatsuhiro Suzuki } 404*c3275903SKatsuhiro Suzuki 405*c3275903SKatsuhiro Suzuki static bool rk3328_codec_volatile_reg(struct device *dev, unsigned int reg) 406*c3275903SKatsuhiro Suzuki { 407*c3275903SKatsuhiro Suzuki switch (reg) { 408*c3275903SKatsuhiro Suzuki case CODEC_RESET: 409*c3275903SKatsuhiro Suzuki return true; 410*c3275903SKatsuhiro Suzuki default: 411*c3275903SKatsuhiro Suzuki return false; 412*c3275903SKatsuhiro Suzuki } 413*c3275903SKatsuhiro Suzuki } 414*c3275903SKatsuhiro Suzuki 415*c3275903SKatsuhiro Suzuki static const struct regmap_config rk3328_codec_regmap_config = { 416*c3275903SKatsuhiro Suzuki .reg_bits = 32, 417*c3275903SKatsuhiro Suzuki .reg_stride = 4, 418*c3275903SKatsuhiro Suzuki .val_bits = 32, 419*c3275903SKatsuhiro Suzuki .max_register = HPOUT_POP_CTRL, 420*c3275903SKatsuhiro Suzuki .writeable_reg = rk3328_codec_write_read_reg, 421*c3275903SKatsuhiro Suzuki .readable_reg = rk3328_codec_write_read_reg, 422*c3275903SKatsuhiro Suzuki .volatile_reg = rk3328_codec_volatile_reg, 423*c3275903SKatsuhiro Suzuki .reg_defaults = rk3328_codec_reg_defaults, 424*c3275903SKatsuhiro Suzuki .num_reg_defaults = ARRAY_SIZE(rk3328_codec_reg_defaults), 425*c3275903SKatsuhiro Suzuki .cache_type = REGCACHE_FLAT, 426*c3275903SKatsuhiro Suzuki }; 427*c3275903SKatsuhiro Suzuki 428*c3275903SKatsuhiro Suzuki static int rk3328_platform_probe(struct platform_device *pdev) 429*c3275903SKatsuhiro Suzuki { 430*c3275903SKatsuhiro Suzuki struct device_node *rk3328_np = pdev->dev.of_node; 431*c3275903SKatsuhiro Suzuki struct rk3328_codec_priv *rk3328; 432*c3275903SKatsuhiro Suzuki struct resource *res; 433*c3275903SKatsuhiro Suzuki struct regmap *grf; 434*c3275903SKatsuhiro Suzuki void __iomem *base; 435*c3275903SKatsuhiro Suzuki int ret = 0; 436*c3275903SKatsuhiro Suzuki 437*c3275903SKatsuhiro Suzuki rk3328 = devm_kzalloc(&pdev->dev, sizeof(*rk3328), GFP_KERNEL); 438*c3275903SKatsuhiro Suzuki if (!rk3328) 439*c3275903SKatsuhiro Suzuki return -ENOMEM; 440*c3275903SKatsuhiro Suzuki 441*c3275903SKatsuhiro Suzuki grf = syscon_regmap_lookup_by_phandle(rk3328_np, 442*c3275903SKatsuhiro Suzuki "rockchip,grf"); 443*c3275903SKatsuhiro Suzuki if (IS_ERR(grf)) { 444*c3275903SKatsuhiro Suzuki dev_err(&pdev->dev, "missing 'rockchip,grf'\n"); 445*c3275903SKatsuhiro Suzuki return PTR_ERR(grf); 446*c3275903SKatsuhiro Suzuki } 447*c3275903SKatsuhiro Suzuki rk3328->grf = grf; 448*c3275903SKatsuhiro Suzuki /* enable i2s_acodec_en */ 449*c3275903SKatsuhiro Suzuki regmap_write(grf, RK3328_GRF_SOC_CON2, 450*c3275903SKatsuhiro Suzuki (BIT(14) << 16 | BIT(14))); 451*c3275903SKatsuhiro Suzuki 452*c3275903SKatsuhiro Suzuki ret = of_property_read_u32(rk3328_np, "spk-depop-time-ms", 453*c3275903SKatsuhiro Suzuki &rk3328->spk_depop_time); 454*c3275903SKatsuhiro Suzuki if (ret < 0) { 455*c3275903SKatsuhiro Suzuki dev_info(&pdev->dev, "spk_depop_time use default value.\n"); 456*c3275903SKatsuhiro Suzuki rk3328->spk_depop_time = 200; 457*c3275903SKatsuhiro Suzuki } 458*c3275903SKatsuhiro Suzuki 459*c3275903SKatsuhiro Suzuki rk3328_analog_output(rk3328, 0); 460*c3275903SKatsuhiro Suzuki 461*c3275903SKatsuhiro Suzuki rk3328->mclk = devm_clk_get(&pdev->dev, "mclk"); 462*c3275903SKatsuhiro Suzuki if (IS_ERR(rk3328->mclk)) 463*c3275903SKatsuhiro Suzuki return PTR_ERR(rk3328->mclk); 464*c3275903SKatsuhiro Suzuki 465*c3275903SKatsuhiro Suzuki ret = clk_prepare_enable(rk3328->mclk); 466*c3275903SKatsuhiro Suzuki if (ret) 467*c3275903SKatsuhiro Suzuki return ret; 468*c3275903SKatsuhiro Suzuki clk_set_rate(rk3328->mclk, INITIAL_FREQ); 469*c3275903SKatsuhiro Suzuki 470*c3275903SKatsuhiro Suzuki rk3328->pclk = devm_clk_get(&pdev->dev, "pclk"); 471*c3275903SKatsuhiro Suzuki if (IS_ERR(rk3328->pclk)) { 472*c3275903SKatsuhiro Suzuki dev_err(&pdev->dev, "can't get acodec pclk\n"); 473*c3275903SKatsuhiro Suzuki return PTR_ERR(rk3328->pclk); 474*c3275903SKatsuhiro Suzuki } 475*c3275903SKatsuhiro Suzuki 476*c3275903SKatsuhiro Suzuki ret = clk_prepare_enable(rk3328->pclk); 477*c3275903SKatsuhiro Suzuki if (ret < 0) { 478*c3275903SKatsuhiro Suzuki dev_err(&pdev->dev, "failed to enable acodec pclk\n"); 479*c3275903SKatsuhiro Suzuki return ret; 480*c3275903SKatsuhiro Suzuki } 481*c3275903SKatsuhiro Suzuki 482*c3275903SKatsuhiro Suzuki res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 483*c3275903SKatsuhiro Suzuki base = devm_ioremap_resource(&pdev->dev, res); 484*c3275903SKatsuhiro Suzuki if (IS_ERR(base)) 485*c3275903SKatsuhiro Suzuki return PTR_ERR(base); 486*c3275903SKatsuhiro Suzuki 487*c3275903SKatsuhiro Suzuki rk3328->regmap = devm_regmap_init_mmio(&pdev->dev, base, 488*c3275903SKatsuhiro Suzuki &rk3328_codec_regmap_config); 489*c3275903SKatsuhiro Suzuki if (IS_ERR(rk3328->regmap)) 490*c3275903SKatsuhiro Suzuki return PTR_ERR(rk3328->regmap); 491*c3275903SKatsuhiro Suzuki 492*c3275903SKatsuhiro Suzuki platform_set_drvdata(pdev, rk3328); 493*c3275903SKatsuhiro Suzuki 494*c3275903SKatsuhiro Suzuki return devm_snd_soc_register_component(&pdev->dev, &soc_codec_rk3328, 495*c3275903SKatsuhiro Suzuki rk3328_dai, 496*c3275903SKatsuhiro Suzuki ARRAY_SIZE(rk3328_dai)); 497*c3275903SKatsuhiro Suzuki } 498*c3275903SKatsuhiro Suzuki 499*c3275903SKatsuhiro Suzuki static const struct of_device_id rk3328_codec_of_match[] = { 500*c3275903SKatsuhiro Suzuki { .compatible = "rockchip,rk3328-codec", }, 501*c3275903SKatsuhiro Suzuki {}, 502*c3275903SKatsuhiro Suzuki }; 503*c3275903SKatsuhiro Suzuki MODULE_DEVICE_TABLE(of, rk3328_codec_of_match); 504*c3275903SKatsuhiro Suzuki 505*c3275903SKatsuhiro Suzuki static struct platform_driver rk3328_codec_driver = { 506*c3275903SKatsuhiro Suzuki .driver = { 507*c3275903SKatsuhiro Suzuki .name = "rk3328-codec", 508*c3275903SKatsuhiro Suzuki .owner = THIS_MODULE, 509*c3275903SKatsuhiro Suzuki .of_match_table = of_match_ptr(rk3328_codec_of_match), 510*c3275903SKatsuhiro Suzuki }, 511*c3275903SKatsuhiro Suzuki .probe = rk3328_platform_probe, 512*c3275903SKatsuhiro Suzuki }; 513*c3275903SKatsuhiro Suzuki module_platform_driver(rk3328_codec_driver); 514*c3275903SKatsuhiro Suzuki 515*c3275903SKatsuhiro Suzuki MODULE_AUTHOR("Sugar Zhang <sugar.zhang@rock-chips.com>"); 516*c3275903SKatsuhiro Suzuki MODULE_DESCRIPTION("ASoC rk3328 codec driver"); 517*c3275903SKatsuhiro Suzuki MODULE_LICENSE("GPL v2"); 518