1 /* 2 * AD193X Audio Codec driver supporting AD1936/7/8/9 3 * 4 * Copyright 2010 Analog Devices Inc. 5 * 6 * Licensed under the GPL-2 or later. 7 */ 8 9 #include <linux/module.h> 10 #include <linux/kernel.h> 11 #include <linux/device.h> 12 #include <linux/regmap.h> 13 #include <linux/slab.h> 14 #include <sound/core.h> 15 #include <sound/pcm.h> 16 #include <sound/pcm_params.h> 17 #include <sound/initval.h> 18 #include <sound/soc.h> 19 #include <sound/tlv.h> 20 21 #include "ad193x.h" 22 23 /* codec private data */ 24 struct ad193x_priv { 25 struct regmap *regmap; 26 int sysclk; 27 }; 28 29 /* 30 * AD193X volume/mute/de-emphasis etc. controls 31 */ 32 static const char * const ad193x_deemp[] = {"None", "48kHz", "44.1kHz", "32kHz"}; 33 34 static SOC_ENUM_SINGLE_DECL(ad193x_deemp_enum, AD193X_DAC_CTRL2, 1, 35 ad193x_deemp); 36 37 static const DECLARE_TLV_DB_MINMAX(adau193x_tlv, -9563, 0); 38 39 static const struct snd_kcontrol_new ad193x_snd_controls[] = { 40 /* DAC volume control */ 41 SOC_DOUBLE_R_TLV("DAC1 Volume", AD193X_DAC_L1_VOL, 42 AD193X_DAC_R1_VOL, 0, 0xFF, 1, adau193x_tlv), 43 SOC_DOUBLE_R_TLV("DAC2 Volume", AD193X_DAC_L2_VOL, 44 AD193X_DAC_R2_VOL, 0, 0xFF, 1, adau193x_tlv), 45 SOC_DOUBLE_R_TLV("DAC3 Volume", AD193X_DAC_L3_VOL, 46 AD193X_DAC_R3_VOL, 0, 0xFF, 1, adau193x_tlv), 47 SOC_DOUBLE_R_TLV("DAC4 Volume", AD193X_DAC_L4_VOL, 48 AD193X_DAC_R4_VOL, 0, 0xFF, 1, adau193x_tlv), 49 50 /* ADC switch control */ 51 SOC_DOUBLE("ADC1 Switch", AD193X_ADC_CTRL0, AD193X_ADCL1_MUTE, 52 AD193X_ADCR1_MUTE, 1, 1), 53 SOC_DOUBLE("ADC2 Switch", AD193X_ADC_CTRL0, AD193X_ADCL2_MUTE, 54 AD193X_ADCR2_MUTE, 1, 1), 55 56 /* DAC switch control */ 57 SOC_DOUBLE("DAC1 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL1_MUTE, 58 AD193X_DACR1_MUTE, 1, 1), 59 SOC_DOUBLE("DAC2 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL2_MUTE, 60 AD193X_DACR2_MUTE, 1, 1), 61 SOC_DOUBLE("DAC3 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL3_MUTE, 62 AD193X_DACR3_MUTE, 1, 1), 63 SOC_DOUBLE("DAC4 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL4_MUTE, 64 AD193X_DACR4_MUTE, 1, 1), 65 66 /* ADC high-pass filter */ 67 SOC_SINGLE("ADC High Pass Filter Switch", AD193X_ADC_CTRL0, 68 AD193X_ADC_HIGHPASS_FILTER, 1, 0), 69 70 /* DAC de-emphasis */ 71 SOC_ENUM("Playback Deemphasis", ad193x_deemp_enum), 72 }; 73 74 static const struct snd_soc_dapm_widget ad193x_dapm_widgets[] = { 75 SND_SOC_DAPM_DAC("DAC", "Playback", AD193X_DAC_CTRL0, 0, 1), 76 SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0), 77 SND_SOC_DAPM_SUPPLY("PLL_PWR", AD193X_PLL_CLK_CTRL0, 0, 1, NULL, 0), 78 SND_SOC_DAPM_SUPPLY("ADC_PWR", AD193X_ADC_CTRL0, 0, 1, NULL, 0), 79 SND_SOC_DAPM_SUPPLY("SYSCLK", AD193X_PLL_CLK_CTRL0, 7, 0, NULL, 0), 80 SND_SOC_DAPM_OUTPUT("DAC1OUT"), 81 SND_SOC_DAPM_OUTPUT("DAC2OUT"), 82 SND_SOC_DAPM_OUTPUT("DAC3OUT"), 83 SND_SOC_DAPM_OUTPUT("DAC4OUT"), 84 SND_SOC_DAPM_INPUT("ADC1IN"), 85 SND_SOC_DAPM_INPUT("ADC2IN"), 86 }; 87 88 static const struct snd_soc_dapm_route audio_paths[] = { 89 { "DAC", NULL, "SYSCLK" }, 90 { "ADC", NULL, "SYSCLK" }, 91 { "DAC", NULL, "ADC_PWR" }, 92 { "ADC", NULL, "ADC_PWR" }, 93 { "DAC1OUT", NULL, "DAC" }, 94 { "DAC2OUT", NULL, "DAC" }, 95 { "DAC3OUT", NULL, "DAC" }, 96 { "DAC4OUT", NULL, "DAC" }, 97 { "ADC", NULL, "ADC1IN" }, 98 { "ADC", NULL, "ADC2IN" }, 99 { "SYSCLK", NULL, "PLL_PWR" }, 100 }; 101 102 /* 103 * DAI ops entries 104 */ 105 106 static int ad193x_mute(struct snd_soc_dai *dai, int mute) 107 { 108 struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(dai->codec); 109 110 if (mute) 111 regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL2, 112 AD193X_DAC_MASTER_MUTE, 113 AD193X_DAC_MASTER_MUTE); 114 else 115 regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL2, 116 AD193X_DAC_MASTER_MUTE, 0); 117 118 return 0; 119 } 120 121 static int ad193x_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, 122 unsigned int rx_mask, int slots, int width) 123 { 124 struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(dai->codec); 125 unsigned int channels; 126 127 switch (slots) { 128 case 2: 129 channels = AD193X_2_CHANNELS; 130 break; 131 case 4: 132 channels = AD193X_4_CHANNELS; 133 break; 134 case 8: 135 channels = AD193X_8_CHANNELS; 136 break; 137 case 16: 138 channels = AD193X_16_CHANNELS; 139 break; 140 default: 141 return -EINVAL; 142 } 143 144 regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL1, 145 AD193X_DAC_CHAN_MASK, channels << AD193X_DAC_CHAN_SHFT); 146 regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL2, 147 AD193X_ADC_CHAN_MASK, channels << AD193X_ADC_CHAN_SHFT); 148 149 return 0; 150 } 151 152 static int ad193x_set_dai_fmt(struct snd_soc_dai *codec_dai, 153 unsigned int fmt) 154 { 155 struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec_dai->codec); 156 unsigned int adc_serfmt = 0; 157 unsigned int adc_fmt = 0; 158 unsigned int dac_fmt = 0; 159 160 /* At present, the driver only support AUX ADC mode(SND_SOC_DAIFMT_I2S 161 * with TDM) and ADC&DAC TDM mode(SND_SOC_DAIFMT_DSP_A) 162 */ 163 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 164 case SND_SOC_DAIFMT_I2S: 165 adc_serfmt |= AD193X_ADC_SERFMT_TDM; 166 break; 167 case SND_SOC_DAIFMT_DSP_A: 168 adc_serfmt |= AD193X_ADC_SERFMT_AUX; 169 break; 170 default: 171 return -EINVAL; 172 } 173 174 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 175 case SND_SOC_DAIFMT_NB_NF: /* normal bit clock + frame */ 176 break; 177 case SND_SOC_DAIFMT_NB_IF: /* normal bclk + invert frm */ 178 adc_fmt |= AD193X_ADC_LEFT_HIGH; 179 dac_fmt |= AD193X_DAC_LEFT_HIGH; 180 break; 181 case SND_SOC_DAIFMT_IB_NF: /* invert bclk + normal frm */ 182 adc_fmt |= AD193X_ADC_BCLK_INV; 183 dac_fmt |= AD193X_DAC_BCLK_INV; 184 break; 185 case SND_SOC_DAIFMT_IB_IF: /* invert bclk + frm */ 186 adc_fmt |= AD193X_ADC_LEFT_HIGH; 187 adc_fmt |= AD193X_ADC_BCLK_INV; 188 dac_fmt |= AD193X_DAC_LEFT_HIGH; 189 dac_fmt |= AD193X_DAC_BCLK_INV; 190 break; 191 default: 192 return -EINVAL; 193 } 194 195 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 196 case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & frm master */ 197 adc_fmt |= AD193X_ADC_LCR_MASTER; 198 adc_fmt |= AD193X_ADC_BCLK_MASTER; 199 dac_fmt |= AD193X_DAC_LCR_MASTER; 200 dac_fmt |= AD193X_DAC_BCLK_MASTER; 201 break; 202 case SND_SOC_DAIFMT_CBS_CFM: /* codec clk slave & frm master */ 203 adc_fmt |= AD193X_ADC_LCR_MASTER; 204 dac_fmt |= AD193X_DAC_LCR_MASTER; 205 break; 206 case SND_SOC_DAIFMT_CBM_CFS: /* codec clk master & frame slave */ 207 adc_fmt |= AD193X_ADC_BCLK_MASTER; 208 dac_fmt |= AD193X_DAC_BCLK_MASTER; 209 break; 210 case SND_SOC_DAIFMT_CBS_CFS: /* codec clk & frm slave */ 211 break; 212 default: 213 return -EINVAL; 214 } 215 216 regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL1, 217 AD193X_ADC_SERFMT_MASK, adc_serfmt); 218 regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL2, 219 AD193X_ADC_FMT_MASK, adc_fmt); 220 regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL1, 221 AD193X_DAC_FMT_MASK, dac_fmt); 222 223 return 0; 224 } 225 226 static int ad193x_set_dai_sysclk(struct snd_soc_dai *codec_dai, 227 int clk_id, unsigned int freq, int dir) 228 { 229 struct snd_soc_codec *codec = codec_dai->codec; 230 struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); 231 switch (freq) { 232 case 12288000: 233 case 18432000: 234 case 24576000: 235 case 36864000: 236 ad193x->sysclk = freq; 237 return 0; 238 } 239 return -EINVAL; 240 } 241 242 static int ad193x_hw_params(struct snd_pcm_substream *substream, 243 struct snd_pcm_hw_params *params, 244 struct snd_soc_dai *dai) 245 { 246 int word_len = 0, master_rate = 0; 247 struct snd_soc_codec *codec = dai->codec; 248 struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); 249 250 /* bit size */ 251 switch (params_width(params)) { 252 case 16: 253 word_len = 3; 254 break; 255 case 20: 256 word_len = 1; 257 break; 258 case 24: 259 case 32: 260 word_len = 0; 261 break; 262 } 263 264 switch (ad193x->sysclk) { 265 case 12288000: 266 master_rate = AD193X_PLL_INPUT_256; 267 break; 268 case 18432000: 269 master_rate = AD193X_PLL_INPUT_384; 270 break; 271 case 24576000: 272 master_rate = AD193X_PLL_INPUT_512; 273 break; 274 case 36864000: 275 master_rate = AD193X_PLL_INPUT_768; 276 break; 277 } 278 279 regmap_update_bits(ad193x->regmap, AD193X_PLL_CLK_CTRL0, 280 AD193X_PLL_INPUT_MASK, master_rate); 281 282 regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL2, 283 AD193X_DAC_WORD_LEN_MASK, 284 word_len << AD193X_DAC_WORD_LEN_SHFT); 285 286 regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL1, 287 AD193X_ADC_WORD_LEN_MASK, word_len); 288 289 return 0; 290 } 291 292 static const struct snd_soc_dai_ops ad193x_dai_ops = { 293 .hw_params = ad193x_hw_params, 294 .digital_mute = ad193x_mute, 295 .set_tdm_slot = ad193x_set_tdm_slot, 296 .set_sysclk = ad193x_set_dai_sysclk, 297 .set_fmt = ad193x_set_dai_fmt, 298 }; 299 300 /* codec DAI instance */ 301 static struct snd_soc_dai_driver ad193x_dai = { 302 .name = "ad193x-hifi", 303 .playback = { 304 .stream_name = "Playback", 305 .channels_min = 2, 306 .channels_max = 8, 307 .rates = SNDRV_PCM_RATE_48000, 308 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | 309 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, 310 }, 311 .capture = { 312 .stream_name = "Capture", 313 .channels_min = 2, 314 .channels_max = 4, 315 .rates = SNDRV_PCM_RATE_48000, 316 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | 317 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, 318 }, 319 .ops = &ad193x_dai_ops, 320 }; 321 322 static int ad193x_codec_probe(struct snd_soc_codec *codec) 323 { 324 struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); 325 326 /* default setting for ad193x */ 327 328 /* unmute dac channels */ 329 regmap_write(ad193x->regmap, AD193X_DAC_CHNL_MUTE, 0x0); 330 /* de-emphasis: 48kHz, powedown dac */ 331 regmap_write(ad193x->regmap, AD193X_DAC_CTRL2, 0x1A); 332 /* powerdown dac, dac in tdm mode */ 333 regmap_write(ad193x->regmap, AD193X_DAC_CTRL0, 0x41); 334 /* high-pass filter enable */ 335 regmap_write(ad193x->regmap, AD193X_ADC_CTRL0, 0x3); 336 /* sata delay=1, adc aux mode */ 337 regmap_write(ad193x->regmap, AD193X_ADC_CTRL1, 0x43); 338 /* pll input: mclki/xi */ 339 regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */ 340 regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL1, 0x04); 341 342 return 0; 343 } 344 345 static struct snd_soc_codec_driver soc_codec_dev_ad193x = { 346 .probe = ad193x_codec_probe, 347 .controls = ad193x_snd_controls, 348 .num_controls = ARRAY_SIZE(ad193x_snd_controls), 349 .dapm_widgets = ad193x_dapm_widgets, 350 .num_dapm_widgets = ARRAY_SIZE(ad193x_dapm_widgets), 351 .dapm_routes = audio_paths, 352 .num_dapm_routes = ARRAY_SIZE(audio_paths), 353 }; 354 355 static bool adau193x_reg_volatile(struct device *dev, unsigned int reg) 356 { 357 return false; 358 } 359 360 const struct regmap_config ad193x_regmap_config = { 361 .max_register = AD193X_NUM_REGS - 1, 362 .volatile_reg = adau193x_reg_volatile, 363 }; 364 EXPORT_SYMBOL_GPL(ad193x_regmap_config); 365 366 int ad193x_probe(struct device *dev, struct regmap *regmap) 367 { 368 struct ad193x_priv *ad193x; 369 370 if (IS_ERR(regmap)) 371 return PTR_ERR(regmap); 372 373 ad193x = devm_kzalloc(dev, sizeof(*ad193x), GFP_KERNEL); 374 if (ad193x == NULL) 375 return -ENOMEM; 376 377 ad193x->regmap = regmap; 378 379 dev_set_drvdata(dev, ad193x); 380 381 return snd_soc_register_codec(dev, &soc_codec_dev_ad193x, 382 &ad193x_dai, 1); 383 } 384 EXPORT_SYMBOL_GPL(ad193x_probe); 385 386 MODULE_DESCRIPTION("ASoC ad193x driver"); 387 MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); 388 MODULE_LICENSE("GPL"); 389