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