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