162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * AD193X Audio Codec driver supporting AD1936/7/8/9 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2010 Analog Devices Inc. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/module.h> 962306a36Sopenharmony_ci#include <linux/kernel.h> 1062306a36Sopenharmony_ci#include <linux/device.h> 1162306a36Sopenharmony_ci#include <linux/regmap.h> 1262306a36Sopenharmony_ci#include <linux/slab.h> 1362306a36Sopenharmony_ci#include <sound/core.h> 1462306a36Sopenharmony_ci#include <sound/pcm.h> 1562306a36Sopenharmony_ci#include <sound/pcm_params.h> 1662306a36Sopenharmony_ci#include <sound/initval.h> 1762306a36Sopenharmony_ci#include <sound/soc.h> 1862306a36Sopenharmony_ci#include <sound/tlv.h> 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#include "ad193x.h" 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci/* codec private data */ 2362306a36Sopenharmony_cistruct ad193x_priv { 2462306a36Sopenharmony_ci struct regmap *regmap; 2562306a36Sopenharmony_ci enum ad193x_type type; 2662306a36Sopenharmony_ci int sysclk; 2762306a36Sopenharmony_ci}; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci/* 3062306a36Sopenharmony_ci * AD193X volume/mute/de-emphasis etc. controls 3162306a36Sopenharmony_ci */ 3262306a36Sopenharmony_cistatic const char * const ad193x_deemp[] = {"None", "48kHz", "44.1kHz", "32kHz"}; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(ad193x_deemp_enum, AD193X_DAC_CTRL2, 1, 3562306a36Sopenharmony_ci ad193x_deemp); 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cistatic const DECLARE_TLV_DB_MINMAX(adau193x_tlv, -9563, 0); 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistatic const unsigned int ad193x_sb[] = {32}; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cistatic struct snd_pcm_hw_constraint_list constr = { 4262306a36Sopenharmony_ci .list = ad193x_sb, 4362306a36Sopenharmony_ci .count = ARRAY_SIZE(ad193x_sb), 4462306a36Sopenharmony_ci}; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cistatic const struct snd_kcontrol_new ad193x_snd_controls[] = { 4762306a36Sopenharmony_ci /* DAC volume control */ 4862306a36Sopenharmony_ci SOC_DOUBLE_R_TLV("DAC1 Volume", AD193X_DAC_L1_VOL, 4962306a36Sopenharmony_ci AD193X_DAC_R1_VOL, 0, 0xFF, 1, adau193x_tlv), 5062306a36Sopenharmony_ci SOC_DOUBLE_R_TLV("DAC2 Volume", AD193X_DAC_L2_VOL, 5162306a36Sopenharmony_ci AD193X_DAC_R2_VOL, 0, 0xFF, 1, adau193x_tlv), 5262306a36Sopenharmony_ci SOC_DOUBLE_R_TLV("DAC3 Volume", AD193X_DAC_L3_VOL, 5362306a36Sopenharmony_ci AD193X_DAC_R3_VOL, 0, 0xFF, 1, adau193x_tlv), 5462306a36Sopenharmony_ci SOC_DOUBLE_R_TLV("DAC4 Volume", AD193X_DAC_L4_VOL, 5562306a36Sopenharmony_ci AD193X_DAC_R4_VOL, 0, 0xFF, 1, adau193x_tlv), 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci /* DAC switch control */ 5862306a36Sopenharmony_ci SOC_DOUBLE("DAC1 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL1_MUTE, 5962306a36Sopenharmony_ci AD193X_DACR1_MUTE, 1, 1), 6062306a36Sopenharmony_ci SOC_DOUBLE("DAC2 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL2_MUTE, 6162306a36Sopenharmony_ci AD193X_DACR2_MUTE, 1, 1), 6262306a36Sopenharmony_ci SOC_DOUBLE("DAC3 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL3_MUTE, 6362306a36Sopenharmony_ci AD193X_DACR3_MUTE, 1, 1), 6462306a36Sopenharmony_ci SOC_DOUBLE("DAC4 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL4_MUTE, 6562306a36Sopenharmony_ci AD193X_DACR4_MUTE, 1, 1), 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci /* DAC de-emphasis */ 6862306a36Sopenharmony_ci SOC_ENUM("Playback Deemphasis", ad193x_deemp_enum), 6962306a36Sopenharmony_ci}; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_cistatic const struct snd_kcontrol_new ad193x_adc_snd_controls[] = { 7262306a36Sopenharmony_ci /* ADC switch control */ 7362306a36Sopenharmony_ci SOC_DOUBLE("ADC1 Switch", AD193X_ADC_CTRL0, AD193X_ADCL1_MUTE, 7462306a36Sopenharmony_ci AD193X_ADCR1_MUTE, 1, 1), 7562306a36Sopenharmony_ci SOC_DOUBLE("ADC2 Switch", AD193X_ADC_CTRL0, AD193X_ADCL2_MUTE, 7662306a36Sopenharmony_ci AD193X_ADCR2_MUTE, 1, 1), 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci /* ADC high-pass filter */ 7962306a36Sopenharmony_ci SOC_SINGLE("ADC High Pass Filter Switch", AD193X_ADC_CTRL0, 8062306a36Sopenharmony_ci AD193X_ADC_HIGHPASS_FILTER, 1, 0), 8162306a36Sopenharmony_ci}; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget ad193x_dapm_widgets[] = { 8462306a36Sopenharmony_ci SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0), 8562306a36Sopenharmony_ci SND_SOC_DAPM_PGA("DAC Output", AD193X_DAC_CTRL0, 0, 1, NULL, 0), 8662306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("PLL_PWR", AD193X_PLL_CLK_CTRL0, 0, 1, NULL, 0), 8762306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("SYSCLK", AD193X_PLL_CLK_CTRL0, 7, 0, NULL, 0), 8862306a36Sopenharmony_ci SND_SOC_DAPM_VMID("VMID"), 8962306a36Sopenharmony_ci SND_SOC_DAPM_OUTPUT("DAC1OUT"), 9062306a36Sopenharmony_ci SND_SOC_DAPM_OUTPUT("DAC2OUT"), 9162306a36Sopenharmony_ci SND_SOC_DAPM_OUTPUT("DAC3OUT"), 9262306a36Sopenharmony_ci SND_SOC_DAPM_OUTPUT("DAC4OUT"), 9362306a36Sopenharmony_ci}; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget ad193x_adc_widgets[] = { 9662306a36Sopenharmony_ci SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0), 9762306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("ADC_PWR", AD193X_ADC_CTRL0, 0, 1, NULL, 0), 9862306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("ADC1IN"), 9962306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("ADC2IN"), 10062306a36Sopenharmony_ci}; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_cistatic int ad193x_check_pll(struct snd_soc_dapm_widget *source, 10362306a36Sopenharmony_ci struct snd_soc_dapm_widget *sink) 10462306a36Sopenharmony_ci{ 10562306a36Sopenharmony_ci struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); 10662306a36Sopenharmony_ci struct ad193x_priv *ad193x = snd_soc_component_get_drvdata(component); 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci return !!ad193x->sysclk; 10962306a36Sopenharmony_ci} 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_cistatic const struct snd_soc_dapm_route audio_paths[] = { 11262306a36Sopenharmony_ci { "DAC", NULL, "SYSCLK" }, 11362306a36Sopenharmony_ci { "DAC Output", NULL, "DAC" }, 11462306a36Sopenharmony_ci { "DAC Output", NULL, "VMID" }, 11562306a36Sopenharmony_ci { "DAC1OUT", NULL, "DAC Output" }, 11662306a36Sopenharmony_ci { "DAC2OUT", NULL, "DAC Output" }, 11762306a36Sopenharmony_ci { "DAC3OUT", NULL, "DAC Output" }, 11862306a36Sopenharmony_ci { "DAC4OUT", NULL, "DAC Output" }, 11962306a36Sopenharmony_ci { "SYSCLK", NULL, "PLL_PWR", &ad193x_check_pll }, 12062306a36Sopenharmony_ci}; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_cistatic const struct snd_soc_dapm_route ad193x_adc_audio_paths[] = { 12362306a36Sopenharmony_ci { "ADC", NULL, "SYSCLK" }, 12462306a36Sopenharmony_ci { "ADC", NULL, "ADC_PWR" }, 12562306a36Sopenharmony_ci { "ADC", NULL, "ADC1IN" }, 12662306a36Sopenharmony_ci { "ADC", NULL, "ADC2IN" }, 12762306a36Sopenharmony_ci}; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cistatic inline bool ad193x_has_adc(const struct ad193x_priv *ad193x) 13062306a36Sopenharmony_ci{ 13162306a36Sopenharmony_ci switch (ad193x->type) { 13262306a36Sopenharmony_ci case AD1933: 13362306a36Sopenharmony_ci case AD1934: 13462306a36Sopenharmony_ci return false; 13562306a36Sopenharmony_ci default: 13662306a36Sopenharmony_ci break; 13762306a36Sopenharmony_ci } 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci return true; 14062306a36Sopenharmony_ci} 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci/* 14362306a36Sopenharmony_ci * DAI ops entries 14462306a36Sopenharmony_ci */ 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_cistatic int ad193x_mute(struct snd_soc_dai *dai, int mute, int direction) 14762306a36Sopenharmony_ci{ 14862306a36Sopenharmony_ci struct ad193x_priv *ad193x = snd_soc_component_get_drvdata(dai->component); 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci if (mute) 15162306a36Sopenharmony_ci regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL2, 15262306a36Sopenharmony_ci AD193X_DAC_MASTER_MUTE, 15362306a36Sopenharmony_ci AD193X_DAC_MASTER_MUTE); 15462306a36Sopenharmony_ci else 15562306a36Sopenharmony_ci regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL2, 15662306a36Sopenharmony_ci AD193X_DAC_MASTER_MUTE, 0); 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci return 0; 15962306a36Sopenharmony_ci} 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_cistatic int ad193x_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, 16262306a36Sopenharmony_ci unsigned int rx_mask, int slots, int width) 16362306a36Sopenharmony_ci{ 16462306a36Sopenharmony_ci struct ad193x_priv *ad193x = snd_soc_component_get_drvdata(dai->component); 16562306a36Sopenharmony_ci unsigned int channels; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci switch (slots) { 16862306a36Sopenharmony_ci case 2: 16962306a36Sopenharmony_ci channels = AD193X_2_CHANNELS; 17062306a36Sopenharmony_ci break; 17162306a36Sopenharmony_ci case 4: 17262306a36Sopenharmony_ci channels = AD193X_4_CHANNELS; 17362306a36Sopenharmony_ci break; 17462306a36Sopenharmony_ci case 8: 17562306a36Sopenharmony_ci channels = AD193X_8_CHANNELS; 17662306a36Sopenharmony_ci break; 17762306a36Sopenharmony_ci case 16: 17862306a36Sopenharmony_ci channels = AD193X_16_CHANNELS; 17962306a36Sopenharmony_ci break; 18062306a36Sopenharmony_ci default: 18162306a36Sopenharmony_ci return -EINVAL; 18262306a36Sopenharmony_ci } 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL1, 18562306a36Sopenharmony_ci AD193X_DAC_CHAN_MASK, channels << AD193X_DAC_CHAN_SHFT); 18662306a36Sopenharmony_ci if (ad193x_has_adc(ad193x)) 18762306a36Sopenharmony_ci regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL2, 18862306a36Sopenharmony_ci AD193X_ADC_CHAN_MASK, 18962306a36Sopenharmony_ci channels << AD193X_ADC_CHAN_SHFT); 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci return 0; 19262306a36Sopenharmony_ci} 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_cistatic int ad193x_set_dai_fmt(struct snd_soc_dai *codec_dai, 19562306a36Sopenharmony_ci unsigned int fmt) 19662306a36Sopenharmony_ci{ 19762306a36Sopenharmony_ci struct ad193x_priv *ad193x = snd_soc_component_get_drvdata(codec_dai->component); 19862306a36Sopenharmony_ci unsigned int adc_serfmt = 0; 19962306a36Sopenharmony_ci unsigned int dac_serfmt = 0; 20062306a36Sopenharmony_ci unsigned int adc_fmt = 0; 20162306a36Sopenharmony_ci unsigned int dac_fmt = 0; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci /* At present, the driver only support AUX ADC mode(SND_SOC_DAIFMT_I2S 20462306a36Sopenharmony_ci * with TDM), ADC&DAC TDM mode(SND_SOC_DAIFMT_DSP_A) and DAC I2S mode 20562306a36Sopenharmony_ci * (SND_SOC_DAIFMT_I2S) 20662306a36Sopenharmony_ci */ 20762306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 20862306a36Sopenharmony_ci case SND_SOC_DAIFMT_I2S: 20962306a36Sopenharmony_ci adc_serfmt |= AD193X_ADC_SERFMT_TDM; 21062306a36Sopenharmony_ci dac_serfmt |= AD193X_DAC_SERFMT_STEREO; 21162306a36Sopenharmony_ci break; 21262306a36Sopenharmony_ci case SND_SOC_DAIFMT_DSP_A: 21362306a36Sopenharmony_ci adc_serfmt |= AD193X_ADC_SERFMT_AUX; 21462306a36Sopenharmony_ci dac_serfmt |= AD193X_DAC_SERFMT_TDM; 21562306a36Sopenharmony_ci break; 21662306a36Sopenharmony_ci default: 21762306a36Sopenharmony_ci if (ad193x_has_adc(ad193x)) 21862306a36Sopenharmony_ci return -EINVAL; 21962306a36Sopenharmony_ci } 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 22262306a36Sopenharmony_ci case SND_SOC_DAIFMT_NB_NF: /* normal bit clock + frame */ 22362306a36Sopenharmony_ci break; 22462306a36Sopenharmony_ci case SND_SOC_DAIFMT_NB_IF: /* normal bclk + invert frm */ 22562306a36Sopenharmony_ci adc_fmt |= AD193X_ADC_LEFT_HIGH; 22662306a36Sopenharmony_ci dac_fmt |= AD193X_DAC_LEFT_HIGH; 22762306a36Sopenharmony_ci break; 22862306a36Sopenharmony_ci case SND_SOC_DAIFMT_IB_NF: /* invert bclk + normal frm */ 22962306a36Sopenharmony_ci adc_fmt |= AD193X_ADC_BCLK_INV; 23062306a36Sopenharmony_ci dac_fmt |= AD193X_DAC_BCLK_INV; 23162306a36Sopenharmony_ci break; 23262306a36Sopenharmony_ci case SND_SOC_DAIFMT_IB_IF: /* invert bclk + frm */ 23362306a36Sopenharmony_ci adc_fmt |= AD193X_ADC_LEFT_HIGH; 23462306a36Sopenharmony_ci adc_fmt |= AD193X_ADC_BCLK_INV; 23562306a36Sopenharmony_ci dac_fmt |= AD193X_DAC_LEFT_HIGH; 23662306a36Sopenharmony_ci dac_fmt |= AD193X_DAC_BCLK_INV; 23762306a36Sopenharmony_ci break; 23862306a36Sopenharmony_ci default: 23962306a36Sopenharmony_ci return -EINVAL; 24062306a36Sopenharmony_ci } 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci /* For DSP_*, LRCLK's polarity must be inverted */ 24362306a36Sopenharmony_ci if (fmt & SND_SOC_DAIFMT_DSP_A) 24462306a36Sopenharmony_ci dac_fmt ^= AD193X_DAC_LEFT_HIGH; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { 24762306a36Sopenharmony_ci case SND_SOC_DAIFMT_CBP_CFP: 24862306a36Sopenharmony_ci adc_fmt |= AD193X_ADC_LCR_MASTER; 24962306a36Sopenharmony_ci adc_fmt |= AD193X_ADC_BCLK_MASTER; 25062306a36Sopenharmony_ci dac_fmt |= AD193X_DAC_LCR_MASTER; 25162306a36Sopenharmony_ci dac_fmt |= AD193X_DAC_BCLK_MASTER; 25262306a36Sopenharmony_ci break; 25362306a36Sopenharmony_ci case SND_SOC_DAIFMT_CBC_CFP: 25462306a36Sopenharmony_ci adc_fmt |= AD193X_ADC_LCR_MASTER; 25562306a36Sopenharmony_ci dac_fmt |= AD193X_DAC_LCR_MASTER; 25662306a36Sopenharmony_ci break; 25762306a36Sopenharmony_ci case SND_SOC_DAIFMT_CBP_CFC: 25862306a36Sopenharmony_ci adc_fmt |= AD193X_ADC_BCLK_MASTER; 25962306a36Sopenharmony_ci dac_fmt |= AD193X_DAC_BCLK_MASTER; 26062306a36Sopenharmony_ci break; 26162306a36Sopenharmony_ci case SND_SOC_DAIFMT_CBC_CFC: 26262306a36Sopenharmony_ci break; 26362306a36Sopenharmony_ci default: 26462306a36Sopenharmony_ci return -EINVAL; 26562306a36Sopenharmony_ci } 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci if (ad193x_has_adc(ad193x)) { 26862306a36Sopenharmony_ci regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL1, 26962306a36Sopenharmony_ci AD193X_ADC_SERFMT_MASK, adc_serfmt); 27062306a36Sopenharmony_ci regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL2, 27162306a36Sopenharmony_ci AD193X_ADC_FMT_MASK, adc_fmt); 27262306a36Sopenharmony_ci } 27362306a36Sopenharmony_ci regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL0, 27462306a36Sopenharmony_ci AD193X_DAC_SERFMT_MASK, dac_serfmt); 27562306a36Sopenharmony_ci regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL1, 27662306a36Sopenharmony_ci AD193X_DAC_FMT_MASK, dac_fmt); 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci return 0; 27962306a36Sopenharmony_ci} 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_cistatic int ad193x_set_dai_sysclk(struct snd_soc_dai *codec_dai, 28262306a36Sopenharmony_ci int clk_id, unsigned int freq, int dir) 28362306a36Sopenharmony_ci{ 28462306a36Sopenharmony_ci struct snd_soc_component *component = codec_dai->component; 28562306a36Sopenharmony_ci struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 28662306a36Sopenharmony_ci struct ad193x_priv *ad193x = snd_soc_component_get_drvdata(component); 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci if (clk_id == AD193X_SYSCLK_MCLK) { 28962306a36Sopenharmony_ci /* MCLK must be 512 x fs */ 29062306a36Sopenharmony_ci if (dir == SND_SOC_CLOCK_OUT || freq != 24576000) 29162306a36Sopenharmony_ci return -EINVAL; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci regmap_update_bits(ad193x->regmap, AD193X_PLL_CLK_CTRL1, 29462306a36Sopenharmony_ci AD193X_PLL_SRC_MASK, 29562306a36Sopenharmony_ci AD193X_PLL_DAC_SRC_MCLK | 29662306a36Sopenharmony_ci AD193X_PLL_CLK_SRC_MCLK); 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci snd_soc_dapm_sync(dapm); 29962306a36Sopenharmony_ci return 0; 30062306a36Sopenharmony_ci } 30162306a36Sopenharmony_ci switch (freq) { 30262306a36Sopenharmony_ci case 12288000: 30362306a36Sopenharmony_ci case 18432000: 30462306a36Sopenharmony_ci case 24576000: 30562306a36Sopenharmony_ci case 36864000: 30662306a36Sopenharmony_ci ad193x->sysclk = freq; 30762306a36Sopenharmony_ci return 0; 30862306a36Sopenharmony_ci } 30962306a36Sopenharmony_ci return -EINVAL; 31062306a36Sopenharmony_ci} 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_cistatic int ad193x_hw_params(struct snd_pcm_substream *substream, 31362306a36Sopenharmony_ci struct snd_pcm_hw_params *params, 31462306a36Sopenharmony_ci struct snd_soc_dai *dai) 31562306a36Sopenharmony_ci{ 31662306a36Sopenharmony_ci int word_len = 0, master_rate = 0; 31762306a36Sopenharmony_ci struct snd_soc_component *component = dai->component; 31862306a36Sopenharmony_ci struct ad193x_priv *ad193x = snd_soc_component_get_drvdata(component); 31962306a36Sopenharmony_ci bool is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; 32062306a36Sopenharmony_ci u8 dacc0; 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci dev_dbg(dai->dev, "%s() rate=%u format=%#x width=%u channels=%u\n", 32362306a36Sopenharmony_ci __func__, params_rate(params), params_format(params), 32462306a36Sopenharmony_ci params_width(params), params_channels(params)); 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci /* bit size */ 32862306a36Sopenharmony_ci switch (params_width(params)) { 32962306a36Sopenharmony_ci case 16: 33062306a36Sopenharmony_ci word_len = 3; 33162306a36Sopenharmony_ci break; 33262306a36Sopenharmony_ci case 20: 33362306a36Sopenharmony_ci word_len = 1; 33462306a36Sopenharmony_ci break; 33562306a36Sopenharmony_ci case 24: 33662306a36Sopenharmony_ci case 32: 33762306a36Sopenharmony_ci word_len = 0; 33862306a36Sopenharmony_ci break; 33962306a36Sopenharmony_ci } 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci switch (ad193x->sysclk) { 34262306a36Sopenharmony_ci case 12288000: 34362306a36Sopenharmony_ci master_rate = AD193X_PLL_INPUT_256; 34462306a36Sopenharmony_ci break; 34562306a36Sopenharmony_ci case 18432000: 34662306a36Sopenharmony_ci master_rate = AD193X_PLL_INPUT_384; 34762306a36Sopenharmony_ci break; 34862306a36Sopenharmony_ci case 24576000: 34962306a36Sopenharmony_ci master_rate = AD193X_PLL_INPUT_512; 35062306a36Sopenharmony_ci break; 35162306a36Sopenharmony_ci case 36864000: 35262306a36Sopenharmony_ci master_rate = AD193X_PLL_INPUT_768; 35362306a36Sopenharmony_ci break; 35462306a36Sopenharmony_ci } 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci if (is_playback) { 35762306a36Sopenharmony_ci switch (params_rate(params)) { 35862306a36Sopenharmony_ci case 48000: 35962306a36Sopenharmony_ci dacc0 = AD193X_DAC_SR_48; 36062306a36Sopenharmony_ci break; 36162306a36Sopenharmony_ci case 96000: 36262306a36Sopenharmony_ci dacc0 = AD193X_DAC_SR_96; 36362306a36Sopenharmony_ci break; 36462306a36Sopenharmony_ci case 192000: 36562306a36Sopenharmony_ci dacc0 = AD193X_DAC_SR_192; 36662306a36Sopenharmony_ci break; 36762306a36Sopenharmony_ci default: 36862306a36Sopenharmony_ci dev_err(dai->dev, "invalid sampling rate: %d\n", params_rate(params)); 36962306a36Sopenharmony_ci return -EINVAL; 37062306a36Sopenharmony_ci } 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL0, AD193X_DAC_SR_MASK, dacc0); 37362306a36Sopenharmony_ci } 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci regmap_update_bits(ad193x->regmap, AD193X_PLL_CLK_CTRL0, 37662306a36Sopenharmony_ci AD193X_PLL_INPUT_MASK, master_rate); 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL2, 37962306a36Sopenharmony_ci AD193X_DAC_WORD_LEN_MASK, 38062306a36Sopenharmony_ci word_len << AD193X_DAC_WORD_LEN_SHFT); 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci if (ad193x_has_adc(ad193x)) 38362306a36Sopenharmony_ci regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL1, 38462306a36Sopenharmony_ci AD193X_ADC_WORD_LEN_MASK, word_len); 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci return 0; 38762306a36Sopenharmony_ci} 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_cistatic int ad193x_startup(struct snd_pcm_substream *substream, 39062306a36Sopenharmony_ci struct snd_soc_dai *dai) 39162306a36Sopenharmony_ci{ 39262306a36Sopenharmony_ci return snd_pcm_hw_constraint_list(substream->runtime, 0, 39362306a36Sopenharmony_ci SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 39462306a36Sopenharmony_ci &constr); 39562306a36Sopenharmony_ci} 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_cistatic const struct snd_soc_dai_ops ad193x_dai_ops = { 39862306a36Sopenharmony_ci .startup = ad193x_startup, 39962306a36Sopenharmony_ci .hw_params = ad193x_hw_params, 40062306a36Sopenharmony_ci .mute_stream = ad193x_mute, 40162306a36Sopenharmony_ci .set_tdm_slot = ad193x_set_tdm_slot, 40262306a36Sopenharmony_ci .set_sysclk = ad193x_set_dai_sysclk, 40362306a36Sopenharmony_ci .set_fmt = ad193x_set_dai_fmt, 40462306a36Sopenharmony_ci .no_capture_mute = 1, 40562306a36Sopenharmony_ci}; 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci/* codec DAI instance */ 40862306a36Sopenharmony_cistatic struct snd_soc_dai_driver ad193x_dai = { 40962306a36Sopenharmony_ci .name = "ad193x-hifi", 41062306a36Sopenharmony_ci .playback = { 41162306a36Sopenharmony_ci .stream_name = "Playback", 41262306a36Sopenharmony_ci .channels_min = 2, 41362306a36Sopenharmony_ci .channels_max = 8, 41462306a36Sopenharmony_ci .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000, 41562306a36Sopenharmony_ci .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | 41662306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, 41762306a36Sopenharmony_ci }, 41862306a36Sopenharmony_ci .capture = { 41962306a36Sopenharmony_ci .stream_name = "Capture", 42062306a36Sopenharmony_ci .channels_min = 2, 42162306a36Sopenharmony_ci .channels_max = 4, 42262306a36Sopenharmony_ci .rates = SNDRV_PCM_RATE_48000, 42362306a36Sopenharmony_ci .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | 42462306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, 42562306a36Sopenharmony_ci }, 42662306a36Sopenharmony_ci .ops = &ad193x_dai_ops, 42762306a36Sopenharmony_ci}; 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci/* codec DAI instance for DAC only */ 43062306a36Sopenharmony_cistatic struct snd_soc_dai_driver ad193x_no_adc_dai = { 43162306a36Sopenharmony_ci .name = "ad193x-hifi", 43262306a36Sopenharmony_ci .playback = { 43362306a36Sopenharmony_ci .stream_name = "Playback", 43462306a36Sopenharmony_ci .channels_min = 2, 43562306a36Sopenharmony_ci .channels_max = 8, 43662306a36Sopenharmony_ci .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000, 43762306a36Sopenharmony_ci .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | 43862306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, 43962306a36Sopenharmony_ci }, 44062306a36Sopenharmony_ci .ops = &ad193x_dai_ops, 44162306a36Sopenharmony_ci}; 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci/* codec register values to set after reset */ 44462306a36Sopenharmony_cistatic void ad193x_reg_default_init(struct ad193x_priv *ad193x) 44562306a36Sopenharmony_ci{ 44662306a36Sopenharmony_ci static const struct reg_sequence reg_init[] = { 44762306a36Sopenharmony_ci { 0, 0x99 }, /* PLL_CLK_CTRL0: pll input: mclki/xi 12.288Mhz */ 44862306a36Sopenharmony_ci { 1, 0x04 }, /* PLL_CLK_CTRL1: no on-chip Vref */ 44962306a36Sopenharmony_ci { 2, 0x40 }, /* DAC_CTRL0: TDM mode */ 45062306a36Sopenharmony_ci { 3, 0x00 }, /* DAC_CTRL1: reset */ 45162306a36Sopenharmony_ci { 4, 0x1A }, /* DAC_CTRL2: 48kHz de-emphasis, unmute dac */ 45262306a36Sopenharmony_ci { 5, 0x00 }, /* DAC_CHNL_MUTE: unmute DAC channels */ 45362306a36Sopenharmony_ci { 6, 0x00 }, /* DAC_L1_VOL: no attenuation */ 45462306a36Sopenharmony_ci { 7, 0x00 }, /* DAC_R1_VOL: no attenuation */ 45562306a36Sopenharmony_ci { 8, 0x00 }, /* DAC_L2_VOL: no attenuation */ 45662306a36Sopenharmony_ci { 9, 0x00 }, /* DAC_R2_VOL: no attenuation */ 45762306a36Sopenharmony_ci { 10, 0x00 }, /* DAC_L3_VOL: no attenuation */ 45862306a36Sopenharmony_ci { 11, 0x00 }, /* DAC_R3_VOL: no attenuation */ 45962306a36Sopenharmony_ci { 12, 0x00 }, /* DAC_L4_VOL: no attenuation */ 46062306a36Sopenharmony_ci { 13, 0x00 }, /* DAC_R4_VOL: no attenuation */ 46162306a36Sopenharmony_ci }; 46262306a36Sopenharmony_ci static const struct reg_sequence reg_adc_init[] = { 46362306a36Sopenharmony_ci { 14, 0x03 }, /* ADC_CTRL0: high-pass filter enable */ 46462306a36Sopenharmony_ci { 15, 0x43 }, /* ADC_CTRL1: sata delay=1, adc aux mode */ 46562306a36Sopenharmony_ci { 16, 0x00 }, /* ADC_CTRL2: reset */ 46662306a36Sopenharmony_ci }; 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci regmap_multi_reg_write(ad193x->regmap, reg_init, ARRAY_SIZE(reg_init)); 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci if (ad193x_has_adc(ad193x)) { 47162306a36Sopenharmony_ci regmap_multi_reg_write(ad193x->regmap, reg_adc_init, 47262306a36Sopenharmony_ci ARRAY_SIZE(reg_adc_init)); 47362306a36Sopenharmony_ci } 47462306a36Sopenharmony_ci} 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_cistatic int ad193x_component_probe(struct snd_soc_component *component) 47762306a36Sopenharmony_ci{ 47862306a36Sopenharmony_ci struct ad193x_priv *ad193x = snd_soc_component_get_drvdata(component); 47962306a36Sopenharmony_ci struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 48062306a36Sopenharmony_ci int num, ret; 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci /* default setting for ad193x */ 48362306a36Sopenharmony_ci ad193x_reg_default_init(ad193x); 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci /* adc only */ 48662306a36Sopenharmony_ci if (ad193x_has_adc(ad193x)) { 48762306a36Sopenharmony_ci /* add adc controls */ 48862306a36Sopenharmony_ci num = ARRAY_SIZE(ad193x_adc_snd_controls); 48962306a36Sopenharmony_ci ret = snd_soc_add_component_controls(component, 49062306a36Sopenharmony_ci ad193x_adc_snd_controls, 49162306a36Sopenharmony_ci num); 49262306a36Sopenharmony_ci if (ret) 49362306a36Sopenharmony_ci return ret; 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci /* add adc widgets */ 49662306a36Sopenharmony_ci num = ARRAY_SIZE(ad193x_adc_widgets); 49762306a36Sopenharmony_ci ret = snd_soc_dapm_new_controls(dapm, 49862306a36Sopenharmony_ci ad193x_adc_widgets, 49962306a36Sopenharmony_ci num); 50062306a36Sopenharmony_ci if (ret) 50162306a36Sopenharmony_ci return ret; 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci /* add adc routes */ 50462306a36Sopenharmony_ci num = ARRAY_SIZE(ad193x_adc_audio_paths); 50562306a36Sopenharmony_ci ret = snd_soc_dapm_add_routes(dapm, 50662306a36Sopenharmony_ci ad193x_adc_audio_paths, 50762306a36Sopenharmony_ci num); 50862306a36Sopenharmony_ci if (ret) 50962306a36Sopenharmony_ci return ret; 51062306a36Sopenharmony_ci } 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci return 0; 51362306a36Sopenharmony_ci} 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_cistatic const struct snd_soc_component_driver soc_component_dev_ad193x = { 51662306a36Sopenharmony_ci .probe = ad193x_component_probe, 51762306a36Sopenharmony_ci .controls = ad193x_snd_controls, 51862306a36Sopenharmony_ci .num_controls = ARRAY_SIZE(ad193x_snd_controls), 51962306a36Sopenharmony_ci .dapm_widgets = ad193x_dapm_widgets, 52062306a36Sopenharmony_ci .num_dapm_widgets = ARRAY_SIZE(ad193x_dapm_widgets), 52162306a36Sopenharmony_ci .dapm_routes = audio_paths, 52262306a36Sopenharmony_ci .num_dapm_routes = ARRAY_SIZE(audio_paths), 52362306a36Sopenharmony_ci .idle_bias_on = 1, 52462306a36Sopenharmony_ci .use_pmdown_time = 1, 52562306a36Sopenharmony_ci .endianness = 1, 52662306a36Sopenharmony_ci}; 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ciconst struct regmap_config ad193x_regmap_config = { 52962306a36Sopenharmony_ci .max_register = AD193X_NUM_REGS - 1, 53062306a36Sopenharmony_ci}; 53162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ad193x_regmap_config); 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ciint ad193x_probe(struct device *dev, struct regmap *regmap, 53462306a36Sopenharmony_ci enum ad193x_type type) 53562306a36Sopenharmony_ci{ 53662306a36Sopenharmony_ci struct ad193x_priv *ad193x; 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci if (IS_ERR(regmap)) 53962306a36Sopenharmony_ci return PTR_ERR(regmap); 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci ad193x = devm_kzalloc(dev, sizeof(*ad193x), GFP_KERNEL); 54262306a36Sopenharmony_ci if (ad193x == NULL) 54362306a36Sopenharmony_ci return -ENOMEM; 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci ad193x->regmap = regmap; 54662306a36Sopenharmony_ci ad193x->type = type; 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci dev_set_drvdata(dev, ad193x); 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci if (ad193x_has_adc(ad193x)) 55162306a36Sopenharmony_ci return devm_snd_soc_register_component(dev, &soc_component_dev_ad193x, 55262306a36Sopenharmony_ci &ad193x_dai, 1); 55362306a36Sopenharmony_ci return devm_snd_soc_register_component(dev, &soc_component_dev_ad193x, 55462306a36Sopenharmony_ci &ad193x_no_adc_dai, 1); 55562306a36Sopenharmony_ci} 55662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ad193x_probe); 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ciMODULE_DESCRIPTION("ASoC ad193x driver"); 55962306a36Sopenharmony_ciMODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); 56062306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 561