162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci// 362306a36Sopenharmony_ci// rk3328 ALSA SoC Audio driver 462306a36Sopenharmony_ci// 562306a36Sopenharmony_ci// Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd All rights reserved. 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/clk.h> 862306a36Sopenharmony_ci#include <linux/delay.h> 962306a36Sopenharmony_ci#include <linux/device.h> 1062306a36Sopenharmony_ci#include <linux/gpio/consumer.h> 1162306a36Sopenharmony_ci#include <linux/module.h> 1262306a36Sopenharmony_ci#include <linux/of.h> 1362306a36Sopenharmony_ci#include <linux/platform_device.h> 1462306a36Sopenharmony_ci#include <linux/regmap.h> 1562306a36Sopenharmony_ci#include <linux/mfd/syscon.h> 1662306a36Sopenharmony_ci#include <sound/dmaengine_pcm.h> 1762306a36Sopenharmony_ci#include <sound/pcm_params.h> 1862306a36Sopenharmony_ci#include "rk3328_codec.h" 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci/* 2162306a36Sopenharmony_ci * volume setting 2262306a36Sopenharmony_ci * 0: -39dB 2362306a36Sopenharmony_ci * 26: 0dB 2462306a36Sopenharmony_ci * 31: 6dB 2562306a36Sopenharmony_ci * Step: 1.5dB 2662306a36Sopenharmony_ci */ 2762306a36Sopenharmony_ci#define OUT_VOLUME (0x18) 2862306a36Sopenharmony_ci#define RK3328_GRF_SOC_CON2 (0x0408) 2962306a36Sopenharmony_ci#define RK3328_GRF_SOC_CON10 (0x0428) 3062306a36Sopenharmony_ci#define INITIAL_FREQ (11289600) 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistruct rk3328_codec_priv { 3362306a36Sopenharmony_ci struct regmap *regmap; 3462306a36Sopenharmony_ci struct gpio_desc *mute; 3562306a36Sopenharmony_ci struct clk *mclk; 3662306a36Sopenharmony_ci struct clk *pclk; 3762306a36Sopenharmony_ci unsigned int sclk; 3862306a36Sopenharmony_ci int spk_depop_time; /* msec */ 3962306a36Sopenharmony_ci}; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cistatic const struct reg_default rk3328_codec_reg_defaults[] = { 4262306a36Sopenharmony_ci { CODEC_RESET, 0x03 }, 4362306a36Sopenharmony_ci { DAC_INIT_CTRL1, 0x00 }, 4462306a36Sopenharmony_ci { DAC_INIT_CTRL2, 0x50 }, 4562306a36Sopenharmony_ci { DAC_INIT_CTRL3, 0x0e }, 4662306a36Sopenharmony_ci { DAC_PRECHARGE_CTRL, 0x01 }, 4762306a36Sopenharmony_ci { DAC_PWR_CTRL, 0x00 }, 4862306a36Sopenharmony_ci { DAC_CLK_CTRL, 0x00 }, 4962306a36Sopenharmony_ci { HPMIX_CTRL, 0x00 }, 5062306a36Sopenharmony_ci { HPOUT_CTRL, 0x00 }, 5162306a36Sopenharmony_ci { HPOUTL_GAIN_CTRL, 0x00 }, 5262306a36Sopenharmony_ci { HPOUTR_GAIN_CTRL, 0x00 }, 5362306a36Sopenharmony_ci { HPOUT_POP_CTRL, 0x11 }, 5462306a36Sopenharmony_ci}; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistatic int rk3328_codec_reset(struct rk3328_codec_priv *rk3328) 5762306a36Sopenharmony_ci{ 5862306a36Sopenharmony_ci regmap_write(rk3328->regmap, CODEC_RESET, 0x00); 5962306a36Sopenharmony_ci mdelay(10); 6062306a36Sopenharmony_ci regmap_write(rk3328->regmap, CODEC_RESET, 0x03); 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci return 0; 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistatic int rk3328_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) 6662306a36Sopenharmony_ci{ 6762306a36Sopenharmony_ci struct rk3328_codec_priv *rk3328 = 6862306a36Sopenharmony_ci snd_soc_component_get_drvdata(dai->component); 6962306a36Sopenharmony_ci unsigned int val; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { 7262306a36Sopenharmony_ci case SND_SOC_DAIFMT_CBC_CFC: 7362306a36Sopenharmony_ci val = PIN_DIRECTION_IN | DAC_I2S_MODE_SLAVE; 7462306a36Sopenharmony_ci break; 7562306a36Sopenharmony_ci case SND_SOC_DAIFMT_CBP_CFP: 7662306a36Sopenharmony_ci val = PIN_DIRECTION_OUT | DAC_I2S_MODE_MASTER; 7762306a36Sopenharmony_ci break; 7862306a36Sopenharmony_ci default: 7962306a36Sopenharmony_ci return -EINVAL; 8062306a36Sopenharmony_ci } 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL1, 8362306a36Sopenharmony_ci PIN_DIRECTION_MASK | DAC_I2S_MODE_MASK, val); 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 8662306a36Sopenharmony_ci case SND_SOC_DAIFMT_DSP_A: 8762306a36Sopenharmony_ci case SND_SOC_DAIFMT_DSP_B: 8862306a36Sopenharmony_ci val = DAC_MODE_PCM; 8962306a36Sopenharmony_ci break; 9062306a36Sopenharmony_ci case SND_SOC_DAIFMT_I2S: 9162306a36Sopenharmony_ci val = DAC_MODE_I2S; 9262306a36Sopenharmony_ci break; 9362306a36Sopenharmony_ci case SND_SOC_DAIFMT_RIGHT_J: 9462306a36Sopenharmony_ci val = DAC_MODE_RJM; 9562306a36Sopenharmony_ci break; 9662306a36Sopenharmony_ci case SND_SOC_DAIFMT_LEFT_J: 9762306a36Sopenharmony_ci val = DAC_MODE_LJM; 9862306a36Sopenharmony_ci break; 9962306a36Sopenharmony_ci default: 10062306a36Sopenharmony_ci return -EINVAL; 10162306a36Sopenharmony_ci } 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL2, 10462306a36Sopenharmony_ci DAC_MODE_MASK, val); 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci return 0; 10762306a36Sopenharmony_ci} 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_cistatic int rk3328_mute_stream(struct snd_soc_dai *dai, int mute, int direction) 11062306a36Sopenharmony_ci{ 11162306a36Sopenharmony_ci struct rk3328_codec_priv *rk3328 = 11262306a36Sopenharmony_ci snd_soc_component_get_drvdata(dai->component); 11362306a36Sopenharmony_ci unsigned int val; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci if (mute) 11662306a36Sopenharmony_ci val = HPOUTL_MUTE | HPOUTR_MUTE; 11762306a36Sopenharmony_ci else 11862306a36Sopenharmony_ci val = HPOUTL_UNMUTE | HPOUTR_UNMUTE; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci regmap_update_bits(rk3328->regmap, HPOUT_CTRL, 12162306a36Sopenharmony_ci HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK, val); 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci return 0; 12462306a36Sopenharmony_ci} 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_cistatic int rk3328_codec_power_on(struct rk3328_codec_priv *rk3328, int wait_ms) 12762306a36Sopenharmony_ci{ 12862306a36Sopenharmony_ci regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL, 12962306a36Sopenharmony_ci DAC_CHARGE_XCHARGE_MASK, DAC_CHARGE_PRECHARGE); 13062306a36Sopenharmony_ci mdelay(10); 13162306a36Sopenharmony_ci regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL, 13262306a36Sopenharmony_ci DAC_CHARGE_CURRENT_ALL_MASK, 13362306a36Sopenharmony_ci DAC_CHARGE_CURRENT_ALL_ON); 13462306a36Sopenharmony_ci mdelay(wait_ms); 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci return 0; 13762306a36Sopenharmony_ci} 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_cistatic int rk3328_codec_power_off(struct rk3328_codec_priv *rk3328, int wait_ms) 14062306a36Sopenharmony_ci{ 14162306a36Sopenharmony_ci regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL, 14262306a36Sopenharmony_ci DAC_CHARGE_XCHARGE_MASK, DAC_CHARGE_DISCHARGE); 14362306a36Sopenharmony_ci mdelay(10); 14462306a36Sopenharmony_ci regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL, 14562306a36Sopenharmony_ci DAC_CHARGE_CURRENT_ALL_MASK, 14662306a36Sopenharmony_ci DAC_CHARGE_CURRENT_ALL_ON); 14762306a36Sopenharmony_ci mdelay(wait_ms); 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci return 0; 15062306a36Sopenharmony_ci} 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_cistatic const struct rk3328_reg_msk_val playback_open_list[] = { 15362306a36Sopenharmony_ci { DAC_PWR_CTRL, DAC_PWR_MASK, DAC_PWR_ON }, 15462306a36Sopenharmony_ci { DAC_PWR_CTRL, DACL_PATH_REFV_MASK | DACR_PATH_REFV_MASK, 15562306a36Sopenharmony_ci DACL_PATH_REFV_ON | DACR_PATH_REFV_ON }, 15662306a36Sopenharmony_ci { DAC_PWR_CTRL, HPOUTL_ZERO_CROSSING_MASK | HPOUTR_ZERO_CROSSING_MASK, 15762306a36Sopenharmony_ci HPOUTL_ZERO_CROSSING_ON | HPOUTR_ZERO_CROSSING_ON }, 15862306a36Sopenharmony_ci { HPOUT_POP_CTRL, HPOUTR_POP_MASK | HPOUTL_POP_MASK, 15962306a36Sopenharmony_ci HPOUTR_POP_WORK | HPOUTL_POP_WORK }, 16062306a36Sopenharmony_ci { HPMIX_CTRL, HPMIXL_MASK | HPMIXR_MASK, HPMIXL_EN | HPMIXR_EN }, 16162306a36Sopenharmony_ci { HPMIX_CTRL, HPMIXL_INIT_MASK | HPMIXR_INIT_MASK, 16262306a36Sopenharmony_ci HPMIXL_INIT_EN | HPMIXR_INIT_EN }, 16362306a36Sopenharmony_ci { HPOUT_CTRL, HPOUTL_MASK | HPOUTR_MASK, HPOUTL_EN | HPOUTR_EN }, 16462306a36Sopenharmony_ci { HPOUT_CTRL, HPOUTL_INIT_MASK | HPOUTR_INIT_MASK, 16562306a36Sopenharmony_ci HPOUTL_INIT_EN | HPOUTR_INIT_EN }, 16662306a36Sopenharmony_ci { DAC_CLK_CTRL, DACL_REFV_MASK | DACR_REFV_MASK, 16762306a36Sopenharmony_ci DACL_REFV_ON | DACR_REFV_ON }, 16862306a36Sopenharmony_ci { DAC_CLK_CTRL, DACL_CLK_MASK | DACR_CLK_MASK, 16962306a36Sopenharmony_ci DACL_CLK_ON | DACR_CLK_ON }, 17062306a36Sopenharmony_ci { DAC_CLK_CTRL, DACL_MASK | DACR_MASK, DACL_ON | DACR_ON }, 17162306a36Sopenharmony_ci { DAC_CLK_CTRL, DACL_INIT_MASK | DACR_INIT_MASK, 17262306a36Sopenharmony_ci DACL_INIT_ON | DACR_INIT_ON }, 17362306a36Sopenharmony_ci { DAC_SELECT, DACL_SELECT_MASK | DACR_SELECT_MASK, 17462306a36Sopenharmony_ci DACL_SELECT | DACR_SELECT }, 17562306a36Sopenharmony_ci { HPMIX_CTRL, HPMIXL_INIT2_MASK | HPMIXR_INIT2_MASK, 17662306a36Sopenharmony_ci HPMIXL_INIT2_EN | HPMIXR_INIT2_EN }, 17762306a36Sopenharmony_ci { HPOUT_CTRL, HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK, 17862306a36Sopenharmony_ci HPOUTL_UNMUTE | HPOUTR_UNMUTE }, 17962306a36Sopenharmony_ci}; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_cistatic int rk3328_codec_open_playback(struct rk3328_codec_priv *rk3328) 18262306a36Sopenharmony_ci{ 18362306a36Sopenharmony_ci int i; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL, 18662306a36Sopenharmony_ci DAC_CHARGE_CURRENT_ALL_MASK, 18762306a36Sopenharmony_ci DAC_CHARGE_CURRENT_I); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(playback_open_list); i++) { 19062306a36Sopenharmony_ci regmap_update_bits(rk3328->regmap, 19162306a36Sopenharmony_ci playback_open_list[i].reg, 19262306a36Sopenharmony_ci playback_open_list[i].msk, 19362306a36Sopenharmony_ci playback_open_list[i].val); 19462306a36Sopenharmony_ci mdelay(1); 19562306a36Sopenharmony_ci } 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci msleep(rk3328->spk_depop_time); 19862306a36Sopenharmony_ci gpiod_set_value(rk3328->mute, 0); 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci regmap_update_bits(rk3328->regmap, HPOUTL_GAIN_CTRL, 20162306a36Sopenharmony_ci HPOUTL_GAIN_MASK, OUT_VOLUME); 20262306a36Sopenharmony_ci regmap_update_bits(rk3328->regmap, HPOUTR_GAIN_CTRL, 20362306a36Sopenharmony_ci HPOUTR_GAIN_MASK, OUT_VOLUME); 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci return 0; 20662306a36Sopenharmony_ci} 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_cistatic const struct rk3328_reg_msk_val playback_close_list[] = { 20962306a36Sopenharmony_ci { HPMIX_CTRL, HPMIXL_INIT2_MASK | HPMIXR_INIT2_MASK, 21062306a36Sopenharmony_ci HPMIXL_INIT2_DIS | HPMIXR_INIT2_DIS }, 21162306a36Sopenharmony_ci { DAC_SELECT, DACL_SELECT_MASK | DACR_SELECT_MASK, 21262306a36Sopenharmony_ci DACL_UNSELECT | DACR_UNSELECT }, 21362306a36Sopenharmony_ci { HPOUT_CTRL, HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK, 21462306a36Sopenharmony_ci HPOUTL_MUTE | HPOUTR_MUTE }, 21562306a36Sopenharmony_ci { HPOUT_CTRL, HPOUTL_INIT_MASK | HPOUTR_INIT_MASK, 21662306a36Sopenharmony_ci HPOUTL_INIT_DIS | HPOUTR_INIT_DIS }, 21762306a36Sopenharmony_ci { HPOUT_CTRL, HPOUTL_MASK | HPOUTR_MASK, HPOUTL_DIS | HPOUTR_DIS }, 21862306a36Sopenharmony_ci { HPMIX_CTRL, HPMIXL_MASK | HPMIXR_MASK, HPMIXL_DIS | HPMIXR_DIS }, 21962306a36Sopenharmony_ci { DAC_CLK_CTRL, DACL_MASK | DACR_MASK, DACL_OFF | DACR_OFF }, 22062306a36Sopenharmony_ci { DAC_CLK_CTRL, DACL_CLK_MASK | DACR_CLK_MASK, 22162306a36Sopenharmony_ci DACL_CLK_OFF | DACR_CLK_OFF }, 22262306a36Sopenharmony_ci { DAC_CLK_CTRL, DACL_REFV_MASK | DACR_REFV_MASK, 22362306a36Sopenharmony_ci DACL_REFV_OFF | DACR_REFV_OFF }, 22462306a36Sopenharmony_ci { HPOUT_POP_CTRL, HPOUTR_POP_MASK | HPOUTL_POP_MASK, 22562306a36Sopenharmony_ci HPOUTR_POP_XCHARGE | HPOUTL_POP_XCHARGE }, 22662306a36Sopenharmony_ci { DAC_PWR_CTRL, DACL_PATH_REFV_MASK | DACR_PATH_REFV_MASK, 22762306a36Sopenharmony_ci DACL_PATH_REFV_OFF | DACR_PATH_REFV_OFF }, 22862306a36Sopenharmony_ci { DAC_PWR_CTRL, DAC_PWR_MASK, DAC_PWR_OFF }, 22962306a36Sopenharmony_ci { HPMIX_CTRL, HPMIXL_INIT_MASK | HPMIXR_INIT_MASK, 23062306a36Sopenharmony_ci HPMIXL_INIT_DIS | HPMIXR_INIT_DIS }, 23162306a36Sopenharmony_ci { DAC_CLK_CTRL, DACL_INIT_MASK | DACR_INIT_MASK, 23262306a36Sopenharmony_ci DACL_INIT_OFF | DACR_INIT_OFF }, 23362306a36Sopenharmony_ci}; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_cistatic int rk3328_codec_close_playback(struct rk3328_codec_priv *rk3328) 23662306a36Sopenharmony_ci{ 23762306a36Sopenharmony_ci size_t i; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci gpiod_set_value(rk3328->mute, 1); 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci regmap_update_bits(rk3328->regmap, HPOUTL_GAIN_CTRL, 24262306a36Sopenharmony_ci HPOUTL_GAIN_MASK, 0); 24362306a36Sopenharmony_ci regmap_update_bits(rk3328->regmap, HPOUTR_GAIN_CTRL, 24462306a36Sopenharmony_ci HPOUTR_GAIN_MASK, 0); 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(playback_close_list); i++) { 24762306a36Sopenharmony_ci regmap_update_bits(rk3328->regmap, 24862306a36Sopenharmony_ci playback_close_list[i].reg, 24962306a36Sopenharmony_ci playback_close_list[i].msk, 25062306a36Sopenharmony_ci playback_close_list[i].val); 25162306a36Sopenharmony_ci mdelay(1); 25262306a36Sopenharmony_ci } 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci /* Workaround for silence when changed Fs 48 -> 44.1kHz */ 25562306a36Sopenharmony_ci rk3328_codec_reset(rk3328); 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL, 25862306a36Sopenharmony_ci DAC_CHARGE_CURRENT_ALL_MASK, 25962306a36Sopenharmony_ci DAC_CHARGE_CURRENT_ALL_ON); 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci return 0; 26262306a36Sopenharmony_ci} 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_cistatic int rk3328_hw_params(struct snd_pcm_substream *substream, 26562306a36Sopenharmony_ci struct snd_pcm_hw_params *params, 26662306a36Sopenharmony_ci struct snd_soc_dai *dai) 26762306a36Sopenharmony_ci{ 26862306a36Sopenharmony_ci struct rk3328_codec_priv *rk3328 = 26962306a36Sopenharmony_ci snd_soc_component_get_drvdata(dai->component); 27062306a36Sopenharmony_ci unsigned int val = 0; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci switch (params_format(params)) { 27362306a36Sopenharmony_ci case SNDRV_PCM_FORMAT_S16_LE: 27462306a36Sopenharmony_ci val = DAC_VDL_16BITS; 27562306a36Sopenharmony_ci break; 27662306a36Sopenharmony_ci case SNDRV_PCM_FORMAT_S20_3LE: 27762306a36Sopenharmony_ci val = DAC_VDL_20BITS; 27862306a36Sopenharmony_ci break; 27962306a36Sopenharmony_ci case SNDRV_PCM_FORMAT_S24_LE: 28062306a36Sopenharmony_ci val = DAC_VDL_24BITS; 28162306a36Sopenharmony_ci break; 28262306a36Sopenharmony_ci case SNDRV_PCM_FORMAT_S32_LE: 28362306a36Sopenharmony_ci val = DAC_VDL_32BITS; 28462306a36Sopenharmony_ci break; 28562306a36Sopenharmony_ci default: 28662306a36Sopenharmony_ci return -EINVAL; 28762306a36Sopenharmony_ci } 28862306a36Sopenharmony_ci regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL2, DAC_VDL_MASK, val); 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci val = DAC_WL_32BITS | DAC_RST_DIS; 29162306a36Sopenharmony_ci regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL3, 29262306a36Sopenharmony_ci DAC_WL_MASK | DAC_RST_MASK, val); 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci return 0; 29562306a36Sopenharmony_ci} 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_cistatic int rk3328_pcm_startup(struct snd_pcm_substream *substream, 29862306a36Sopenharmony_ci struct snd_soc_dai *dai) 29962306a36Sopenharmony_ci{ 30062306a36Sopenharmony_ci struct rk3328_codec_priv *rk3328 = 30162306a36Sopenharmony_ci snd_soc_component_get_drvdata(dai->component); 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci return rk3328_codec_open_playback(rk3328); 30462306a36Sopenharmony_ci} 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_cistatic void rk3328_pcm_shutdown(struct snd_pcm_substream *substream, 30762306a36Sopenharmony_ci struct snd_soc_dai *dai) 30862306a36Sopenharmony_ci{ 30962306a36Sopenharmony_ci struct rk3328_codec_priv *rk3328 = 31062306a36Sopenharmony_ci snd_soc_component_get_drvdata(dai->component); 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci rk3328_codec_close_playback(rk3328); 31362306a36Sopenharmony_ci} 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_cistatic const struct snd_soc_dai_ops rk3328_dai_ops = { 31662306a36Sopenharmony_ci .hw_params = rk3328_hw_params, 31762306a36Sopenharmony_ci .set_fmt = rk3328_set_dai_fmt, 31862306a36Sopenharmony_ci .mute_stream = rk3328_mute_stream, 31962306a36Sopenharmony_ci .startup = rk3328_pcm_startup, 32062306a36Sopenharmony_ci .shutdown = rk3328_pcm_shutdown, 32162306a36Sopenharmony_ci .no_capture_mute = 1, 32262306a36Sopenharmony_ci}; 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_cistatic struct snd_soc_dai_driver rk3328_dai[] = { 32562306a36Sopenharmony_ci { 32662306a36Sopenharmony_ci .name = "rk3328-hifi", 32762306a36Sopenharmony_ci .id = RK3328_HIFI, 32862306a36Sopenharmony_ci .playback = { 32962306a36Sopenharmony_ci .stream_name = "HIFI Playback", 33062306a36Sopenharmony_ci .channels_min = 1, 33162306a36Sopenharmony_ci .channels_max = 2, 33262306a36Sopenharmony_ci .rates = SNDRV_PCM_RATE_8000_96000, 33362306a36Sopenharmony_ci .formats = (SNDRV_PCM_FMTBIT_S16_LE | 33462306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S20_3LE | 33562306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S24_LE | 33662306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S32_LE), 33762306a36Sopenharmony_ci }, 33862306a36Sopenharmony_ci .capture = { 33962306a36Sopenharmony_ci .stream_name = "HIFI Capture", 34062306a36Sopenharmony_ci .channels_min = 2, 34162306a36Sopenharmony_ci .channels_max = 8, 34262306a36Sopenharmony_ci .rates = SNDRV_PCM_RATE_8000_96000, 34362306a36Sopenharmony_ci .formats = (SNDRV_PCM_FMTBIT_S16_LE | 34462306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S20_3LE | 34562306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S24_LE | 34662306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S32_LE), 34762306a36Sopenharmony_ci }, 34862306a36Sopenharmony_ci .ops = &rk3328_dai_ops, 34962306a36Sopenharmony_ci }, 35062306a36Sopenharmony_ci}; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_cistatic int rk3328_codec_probe(struct snd_soc_component *component) 35362306a36Sopenharmony_ci{ 35462306a36Sopenharmony_ci struct rk3328_codec_priv *rk3328 = 35562306a36Sopenharmony_ci snd_soc_component_get_drvdata(component); 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci rk3328_codec_reset(rk3328); 35862306a36Sopenharmony_ci rk3328_codec_power_on(rk3328, 0); 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci return 0; 36162306a36Sopenharmony_ci} 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_cistatic void rk3328_codec_remove(struct snd_soc_component *component) 36462306a36Sopenharmony_ci{ 36562306a36Sopenharmony_ci struct rk3328_codec_priv *rk3328 = 36662306a36Sopenharmony_ci snd_soc_component_get_drvdata(component); 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci rk3328_codec_close_playback(rk3328); 36962306a36Sopenharmony_ci rk3328_codec_power_off(rk3328, 0); 37062306a36Sopenharmony_ci} 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_cistatic const struct snd_soc_component_driver soc_codec_rk3328 = { 37362306a36Sopenharmony_ci .probe = rk3328_codec_probe, 37462306a36Sopenharmony_ci .remove = rk3328_codec_remove, 37562306a36Sopenharmony_ci}; 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_cistatic bool rk3328_codec_write_read_reg(struct device *dev, unsigned int reg) 37862306a36Sopenharmony_ci{ 37962306a36Sopenharmony_ci switch (reg) { 38062306a36Sopenharmony_ci case CODEC_RESET: 38162306a36Sopenharmony_ci case DAC_INIT_CTRL1: 38262306a36Sopenharmony_ci case DAC_INIT_CTRL2: 38362306a36Sopenharmony_ci case DAC_INIT_CTRL3: 38462306a36Sopenharmony_ci case DAC_PRECHARGE_CTRL: 38562306a36Sopenharmony_ci case DAC_PWR_CTRL: 38662306a36Sopenharmony_ci case DAC_CLK_CTRL: 38762306a36Sopenharmony_ci case HPMIX_CTRL: 38862306a36Sopenharmony_ci case DAC_SELECT: 38962306a36Sopenharmony_ci case HPOUT_CTRL: 39062306a36Sopenharmony_ci case HPOUTL_GAIN_CTRL: 39162306a36Sopenharmony_ci case HPOUTR_GAIN_CTRL: 39262306a36Sopenharmony_ci case HPOUT_POP_CTRL: 39362306a36Sopenharmony_ci return true; 39462306a36Sopenharmony_ci default: 39562306a36Sopenharmony_ci return false; 39662306a36Sopenharmony_ci } 39762306a36Sopenharmony_ci} 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_cistatic bool rk3328_codec_volatile_reg(struct device *dev, unsigned int reg) 40062306a36Sopenharmony_ci{ 40162306a36Sopenharmony_ci switch (reg) { 40262306a36Sopenharmony_ci case CODEC_RESET: 40362306a36Sopenharmony_ci return true; 40462306a36Sopenharmony_ci default: 40562306a36Sopenharmony_ci return false; 40662306a36Sopenharmony_ci } 40762306a36Sopenharmony_ci} 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_cistatic const struct regmap_config rk3328_codec_regmap_config = { 41062306a36Sopenharmony_ci .reg_bits = 32, 41162306a36Sopenharmony_ci .reg_stride = 4, 41262306a36Sopenharmony_ci .val_bits = 32, 41362306a36Sopenharmony_ci .max_register = HPOUT_POP_CTRL, 41462306a36Sopenharmony_ci .writeable_reg = rk3328_codec_write_read_reg, 41562306a36Sopenharmony_ci .readable_reg = rk3328_codec_write_read_reg, 41662306a36Sopenharmony_ci .volatile_reg = rk3328_codec_volatile_reg, 41762306a36Sopenharmony_ci .reg_defaults = rk3328_codec_reg_defaults, 41862306a36Sopenharmony_ci .num_reg_defaults = ARRAY_SIZE(rk3328_codec_reg_defaults), 41962306a36Sopenharmony_ci .cache_type = REGCACHE_FLAT, 42062306a36Sopenharmony_ci}; 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_cistatic int rk3328_platform_probe(struct platform_device *pdev) 42362306a36Sopenharmony_ci{ 42462306a36Sopenharmony_ci struct device_node *rk3328_np = pdev->dev.of_node; 42562306a36Sopenharmony_ci struct rk3328_codec_priv *rk3328; 42662306a36Sopenharmony_ci struct regmap *grf; 42762306a36Sopenharmony_ci void __iomem *base; 42862306a36Sopenharmony_ci int ret = 0; 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci rk3328 = devm_kzalloc(&pdev->dev, sizeof(*rk3328), GFP_KERNEL); 43162306a36Sopenharmony_ci if (!rk3328) 43262306a36Sopenharmony_ci return -ENOMEM; 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci grf = syscon_regmap_lookup_by_phandle(rk3328_np, 43562306a36Sopenharmony_ci "rockchip,grf"); 43662306a36Sopenharmony_ci if (IS_ERR(grf)) { 43762306a36Sopenharmony_ci dev_err(&pdev->dev, "missing 'rockchip,grf'\n"); 43862306a36Sopenharmony_ci return PTR_ERR(grf); 43962306a36Sopenharmony_ci } 44062306a36Sopenharmony_ci /* enable i2s_acodec_en */ 44162306a36Sopenharmony_ci regmap_write(grf, RK3328_GRF_SOC_CON2, 44262306a36Sopenharmony_ci (BIT(14) << 16 | BIT(14))); 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci ret = of_property_read_u32(rk3328_np, "spk-depop-time-ms", 44562306a36Sopenharmony_ci &rk3328->spk_depop_time); 44662306a36Sopenharmony_ci if (ret < 0) { 44762306a36Sopenharmony_ci dev_info(&pdev->dev, "spk_depop_time use default value.\n"); 44862306a36Sopenharmony_ci rk3328->spk_depop_time = 200; 44962306a36Sopenharmony_ci } 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci rk3328->mute = gpiod_get_optional(&pdev->dev, "mute", GPIOD_OUT_HIGH); 45262306a36Sopenharmony_ci if (IS_ERR(rk3328->mute)) 45362306a36Sopenharmony_ci return PTR_ERR(rk3328->mute); 45462306a36Sopenharmony_ci /* 45562306a36Sopenharmony_ci * Rock64 is the only supported platform to have widely relied on 45662306a36Sopenharmony_ci * this; if we do happen to come across an old DTB, just leave the 45762306a36Sopenharmony_ci * external mute forced off. 45862306a36Sopenharmony_ci */ 45962306a36Sopenharmony_ci if (!rk3328->mute && of_machine_is_compatible("pine64,rock64")) { 46062306a36Sopenharmony_ci dev_warn(&pdev->dev, "assuming implicit control of GPIO_MUTE; update devicetree if possible\n"); 46162306a36Sopenharmony_ci regmap_write(grf, RK3328_GRF_SOC_CON10, BIT(17) | BIT(1)); 46262306a36Sopenharmony_ci } 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci rk3328->mclk = devm_clk_get(&pdev->dev, "mclk"); 46562306a36Sopenharmony_ci if (IS_ERR(rk3328->mclk)) 46662306a36Sopenharmony_ci return PTR_ERR(rk3328->mclk); 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci ret = clk_prepare_enable(rk3328->mclk); 46962306a36Sopenharmony_ci if (ret) 47062306a36Sopenharmony_ci return ret; 47162306a36Sopenharmony_ci clk_set_rate(rk3328->mclk, INITIAL_FREQ); 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci rk3328->pclk = devm_clk_get(&pdev->dev, "pclk"); 47462306a36Sopenharmony_ci if (IS_ERR(rk3328->pclk)) { 47562306a36Sopenharmony_ci dev_err(&pdev->dev, "can't get acodec pclk\n"); 47662306a36Sopenharmony_ci ret = PTR_ERR(rk3328->pclk); 47762306a36Sopenharmony_ci goto err_unprepare_mclk; 47862306a36Sopenharmony_ci } 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci ret = clk_prepare_enable(rk3328->pclk); 48162306a36Sopenharmony_ci if (ret < 0) { 48262306a36Sopenharmony_ci dev_err(&pdev->dev, "failed to enable acodec pclk\n"); 48362306a36Sopenharmony_ci goto err_unprepare_mclk; 48462306a36Sopenharmony_ci } 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci base = devm_platform_ioremap_resource(pdev, 0); 48762306a36Sopenharmony_ci if (IS_ERR(base)) { 48862306a36Sopenharmony_ci ret = PTR_ERR(base); 48962306a36Sopenharmony_ci goto err_unprepare_pclk; 49062306a36Sopenharmony_ci } 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci rk3328->regmap = devm_regmap_init_mmio(&pdev->dev, base, 49362306a36Sopenharmony_ci &rk3328_codec_regmap_config); 49462306a36Sopenharmony_ci if (IS_ERR(rk3328->regmap)) { 49562306a36Sopenharmony_ci ret = PTR_ERR(rk3328->regmap); 49662306a36Sopenharmony_ci goto err_unprepare_pclk; 49762306a36Sopenharmony_ci } 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci platform_set_drvdata(pdev, rk3328); 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_rk3328, 50262306a36Sopenharmony_ci rk3328_dai, 50362306a36Sopenharmony_ci ARRAY_SIZE(rk3328_dai)); 50462306a36Sopenharmony_ci if (ret) 50562306a36Sopenharmony_ci goto err_unprepare_pclk; 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci return 0; 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_cierr_unprepare_pclk: 51062306a36Sopenharmony_ci clk_disable_unprepare(rk3328->pclk); 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_cierr_unprepare_mclk: 51362306a36Sopenharmony_ci clk_disable_unprepare(rk3328->mclk); 51462306a36Sopenharmony_ci return ret; 51562306a36Sopenharmony_ci} 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_cistatic const struct of_device_id rk3328_codec_of_match[] __maybe_unused = { 51862306a36Sopenharmony_ci { .compatible = "rockchip,rk3328-codec", }, 51962306a36Sopenharmony_ci {}, 52062306a36Sopenharmony_ci}; 52162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, rk3328_codec_of_match); 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_cistatic struct platform_driver rk3328_codec_driver = { 52462306a36Sopenharmony_ci .driver = { 52562306a36Sopenharmony_ci .name = "rk3328-codec", 52662306a36Sopenharmony_ci .of_match_table = of_match_ptr(rk3328_codec_of_match), 52762306a36Sopenharmony_ci }, 52862306a36Sopenharmony_ci .probe = rk3328_platform_probe, 52962306a36Sopenharmony_ci}; 53062306a36Sopenharmony_cimodule_platform_driver(rk3328_codec_driver); 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ciMODULE_AUTHOR("Sugar Zhang <sugar.zhang@rock-chips.com>"); 53362306a36Sopenharmony_ciMODULE_DESCRIPTION("ASoC rk3328 codec driver"); 53462306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 535