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