Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: ad193x: add support to ad1934

The AD1934 codec has no ADC feature. Hence it register mapping is slightly
different from the register mapping of other members of the AD193x family.

Some ASoC controls and widgets are related to the DAC feature so are not
relevant in the case of an AD1934 codec.

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
Acked-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Cyrille Pitchen and committed by
Mark Brown
e5224f58 6ff33f39

+122 -35
+5 -3
sound/soc/codecs/ad193x-i2c.c
··· 15 15 #include "ad193x.h" 16 16 17 17 static const struct i2c_device_id ad193x_id[] = { 18 - { "ad1936", 0 }, 19 - { "ad1937", 0 }, 18 + { "ad1936", AD193X }, 19 + { "ad1937", AD193X }, 20 20 { } 21 21 }; 22 22 MODULE_DEVICE_TABLE(i2c, ad193x_id); ··· 30 30 config.val_bits = 8; 31 31 config.reg_bits = 8; 32 32 33 - return ad193x_probe(&client->dev, devm_regmap_init_i2c(client, &config)); 33 + return ad193x_probe(&client->dev, 34 + devm_regmap_init_i2c(client, &config), 35 + (enum ad193x_type)id->driver_data); 34 36 } 35 37 36 38 static int ad193x_i2c_remove(struct i2c_client *client)
+15 -1
sound/soc/codecs/ad193x-spi.c
··· 16 16 17 17 static int ad193x_spi_probe(struct spi_device *spi) 18 18 { 19 + const struct spi_device_id *id = spi_get_device_id(spi); 19 20 struct regmap_config config; 20 21 21 22 config = ad193x_regmap_config; ··· 25 24 config.read_flag_mask = 0x09; 26 25 config.write_flag_mask = 0x08; 27 26 28 - return ad193x_probe(&spi->dev, devm_regmap_init_spi(spi, &config)); 27 + return ad193x_probe(&spi->dev, devm_regmap_init_spi(spi, &config), 28 + (enum ad193x_type)id->driver_data); 29 29 } 30 30 31 31 static int ad193x_spi_remove(struct spi_device *spi) ··· 35 33 return 0; 36 34 } 37 35 36 + static const struct spi_device_id ad193x_spi_id[] = { 37 + { "ad193x", AD193X }, 38 + { "ad1933", AD1933 }, 39 + { "ad1934", AD1934 }, 40 + { "ad1936", AD193X }, 41 + { "ad1937", AD193X }, 42 + { "ad1938", AD193X }, 43 + { } 44 + }; 45 + MODULE_DEVICE_TABLE(spi, ad193x_spi_id); 46 + 38 47 static struct spi_driver ad193x_spi_driver = { 39 48 .driver = { 40 49 .name = "ad193x", ··· 53 40 }, 54 41 .probe = ad193x_spi_probe, 55 42 .remove = ad193x_spi_remove, 43 + .id_table = ad193x_spi_id, 56 44 }; 57 45 module_spi_driver(ad193x_spi_driver); 58 46
+94 -30
sound/soc/codecs/ad193x.c
··· 23 23 /* codec private data */ 24 24 struct ad193x_priv { 25 25 struct regmap *regmap; 26 + enum ad193x_type type; 26 27 int sysclk; 27 28 }; 28 29 ··· 48 47 SOC_DOUBLE_R_TLV("DAC4 Volume", AD193X_DAC_L4_VOL, 49 48 AD193X_DAC_R4_VOL, 0, 0xFF, 1, adau193x_tlv), 50 49 51 - /* ADC switch control */ 52 - SOC_DOUBLE("ADC1 Switch", AD193X_ADC_CTRL0, AD193X_ADCL1_MUTE, 53 - AD193X_ADCR1_MUTE, 1, 1), 54 - SOC_DOUBLE("ADC2 Switch", AD193X_ADC_CTRL0, AD193X_ADCL2_MUTE, 55 - AD193X_ADCR2_MUTE, 1, 1), 56 - 57 50 /* DAC switch control */ 58 51 SOC_DOUBLE("DAC1 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL1_MUTE, 59 52 AD193X_DACR1_MUTE, 1, 1), ··· 58 63 SOC_DOUBLE("DAC4 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL4_MUTE, 59 64 AD193X_DACR4_MUTE, 1, 1), 60 65 66 + /* DAC de-emphasis */ 67 + SOC_ENUM("Playback Deemphasis", ad193x_deemp_enum), 68 + }; 69 + 70 + static const struct snd_kcontrol_new ad193x_adc_snd_controls[] = { 71 + /* ADC switch control */ 72 + SOC_DOUBLE("ADC1 Switch", AD193X_ADC_CTRL0, AD193X_ADCL1_MUTE, 73 + AD193X_ADCR1_MUTE, 1, 1), 74 + SOC_DOUBLE("ADC2 Switch", AD193X_ADC_CTRL0, AD193X_ADCL2_MUTE, 75 + AD193X_ADCR2_MUTE, 1, 1), 76 + 61 77 /* ADC high-pass filter */ 62 78 SOC_SINGLE("ADC High Pass Filter Switch", AD193X_ADC_CTRL0, 63 79 AD193X_ADC_HIGHPASS_FILTER, 1, 0), 64 - 65 - /* DAC de-emphasis */ 66 - SOC_ENUM("Playback Deemphasis", ad193x_deemp_enum), 67 80 }; 68 81 69 82 static const struct snd_soc_dapm_widget ad193x_dapm_widgets[] = { 70 83 SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0), 71 84 SND_SOC_DAPM_PGA("DAC Output", AD193X_DAC_CTRL0, 0, 1, NULL, 0), 72 - SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0), 73 85 SND_SOC_DAPM_SUPPLY("PLL_PWR", AD193X_PLL_CLK_CTRL0, 0, 1, NULL, 0), 74 - SND_SOC_DAPM_SUPPLY("ADC_PWR", AD193X_ADC_CTRL0, 0, 1, NULL, 0), 75 86 SND_SOC_DAPM_SUPPLY("SYSCLK", AD193X_PLL_CLK_CTRL0, 7, 0, NULL, 0), 76 87 SND_SOC_DAPM_VMID("VMID"), 77 88 SND_SOC_DAPM_OUTPUT("DAC1OUT"), 78 89 SND_SOC_DAPM_OUTPUT("DAC2OUT"), 79 90 SND_SOC_DAPM_OUTPUT("DAC3OUT"), 80 91 SND_SOC_DAPM_OUTPUT("DAC4OUT"), 92 + }; 93 + 94 + static const struct snd_soc_dapm_widget ad193x_adc_widgets[] = { 95 + SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0), 96 + SND_SOC_DAPM_SUPPLY("ADC_PWR", AD193X_ADC_CTRL0, 0, 1, NULL, 0), 81 97 SND_SOC_DAPM_INPUT("ADC1IN"), 82 98 SND_SOC_DAPM_INPUT("ADC2IN"), 83 99 }; ··· 97 91 { "DAC", NULL, "SYSCLK" }, 98 92 { "DAC Output", NULL, "DAC" }, 99 93 { "DAC Output", NULL, "VMID" }, 100 - { "ADC", NULL, "SYSCLK" }, 101 - { "DAC", NULL, "ADC_PWR" }, 102 - { "ADC", NULL, "ADC_PWR" }, 103 94 { "DAC1OUT", NULL, "DAC Output" }, 104 95 { "DAC2OUT", NULL, "DAC Output" }, 105 96 { "DAC3OUT", NULL, "DAC Output" }, 106 97 { "DAC4OUT", NULL, "DAC Output" }, 107 - { "ADC", NULL, "ADC1IN" }, 108 - { "ADC", NULL, "ADC2IN" }, 109 98 { "SYSCLK", NULL, "PLL_PWR" }, 110 99 }; 100 + 101 + static const struct snd_soc_dapm_route ad193x_adc_audio_paths[] = { 102 + { "ADC", NULL, "SYSCLK" }, 103 + { "ADC", NULL, "ADC_PWR" }, 104 + { "ADC", NULL, "ADC1IN" }, 105 + { "ADC", NULL, "ADC2IN" }, 106 + }; 107 + 108 + static inline bool ad193x_has_adc(const struct ad193x_priv *ad193x) 109 + { 110 + switch (ad193x->type) { 111 + case AD1933: 112 + case AD1934: 113 + return false; 114 + default: 115 + break; 116 + } 117 + 118 + return true; 119 + } 111 120 112 121 /* 113 122 * DAI ops entries ··· 168 147 169 148 regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL1, 170 149 AD193X_DAC_CHAN_MASK, channels << AD193X_DAC_CHAN_SHFT); 171 - regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL2, 172 - AD193X_ADC_CHAN_MASK, channels << AD193X_ADC_CHAN_SHFT); 150 + if (ad193x_has_adc(ad193x)) 151 + regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL2, 152 + AD193X_ADC_CHAN_MASK, 153 + channels << AD193X_ADC_CHAN_SHFT); 173 154 174 155 return 0; 175 156 } ··· 195 172 adc_serfmt |= AD193X_ADC_SERFMT_AUX; 196 173 break; 197 174 default: 198 - return -EINVAL; 175 + if (ad193x_has_adc(ad193x)) 176 + return -EINVAL; 177 + break; 199 178 } 200 179 201 180 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { ··· 242 217 return -EINVAL; 243 218 } 244 219 245 - regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL1, 246 - AD193X_ADC_SERFMT_MASK, adc_serfmt); 247 - regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL2, 248 - AD193X_ADC_FMT_MASK, adc_fmt); 220 + if (ad193x_has_adc(ad193x)) { 221 + regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL1, 222 + AD193X_ADC_SERFMT_MASK, adc_serfmt); 223 + regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL2, 224 + AD193X_ADC_FMT_MASK, adc_fmt); 225 + } 249 226 regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL1, 250 227 AD193X_DAC_FMT_MASK, dac_fmt); 251 228 ··· 314 287 AD193X_DAC_WORD_LEN_MASK, 315 288 word_len << AD193X_DAC_WORD_LEN_SHFT); 316 289 317 - regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL1, 318 - AD193X_ADC_WORD_LEN_MASK, word_len); 290 + if (ad193x_has_adc(ad193x)) 291 + regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL1, 292 + AD193X_ADC_WORD_LEN_MASK, word_len); 319 293 320 294 return 0; 321 295 } ··· 354 326 static int ad193x_codec_probe(struct snd_soc_codec *codec) 355 327 { 356 328 struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); 329 + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); 330 + int num, ret; 357 331 358 332 /* default setting for ad193x */ 359 333 ··· 365 335 regmap_write(ad193x->regmap, AD193X_DAC_CTRL2, 0x1A); 366 336 /* dac in tdm mode */ 367 337 regmap_write(ad193x->regmap, AD193X_DAC_CTRL0, 0x40); 368 - /* high-pass filter enable */ 369 - regmap_write(ad193x->regmap, AD193X_ADC_CTRL0, 0x3); 370 - /* sata delay=1, adc aux mode */ 371 - regmap_write(ad193x->regmap, AD193X_ADC_CTRL1, 0x43); 338 + 339 + /* adc only */ 340 + if (ad193x_has_adc(ad193x)) { 341 + /* high-pass filter enable */ 342 + regmap_write(ad193x->regmap, AD193X_ADC_CTRL0, 0x3); 343 + /* sata delay=1, adc aux mode */ 344 + regmap_write(ad193x->regmap, AD193X_ADC_CTRL1, 0x43); 345 + } 346 + 372 347 /* pll input: mclki/xi */ 373 348 regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */ 374 349 regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL1, 0x04); 350 + 351 + /* adc only */ 352 + if (ad193x_has_adc(ad193x)) { 353 + /* add adc controls */ 354 + num = ARRAY_SIZE(ad193x_adc_snd_controls); 355 + ret = snd_soc_add_codec_controls(codec, 356 + ad193x_adc_snd_controls, 357 + num); 358 + if (ret) 359 + return ret; 360 + 361 + /* add adc widgets */ 362 + num = ARRAY_SIZE(ad193x_adc_widgets); 363 + ret = snd_soc_dapm_new_controls(dapm, 364 + ad193x_adc_widgets, 365 + num); 366 + if (ret) 367 + return ret; 368 + 369 + /* add adc routes */ 370 + num = ARRAY_SIZE(ad193x_adc_audio_paths); 371 + ret = snd_soc_dapm_add_routes(dapm, 372 + ad193x_adc_audio_paths, 373 + num); 374 + if (ret) 375 + return ret; 376 + } 375 377 376 378 return 0; 377 379 } ··· 429 367 }; 430 368 EXPORT_SYMBOL_GPL(ad193x_regmap_config); 431 369 432 - int ad193x_probe(struct device *dev, struct regmap *regmap) 370 + int ad193x_probe(struct device *dev, struct regmap *regmap, 371 + enum ad193x_type type) 433 372 { 434 373 struct ad193x_priv *ad193x; 435 374 ··· 442 379 return -ENOMEM; 443 380 444 381 ad193x->regmap = regmap; 382 + ad193x->type = type; 445 383 446 384 dev_set_drvdata(dev, ad193x); 447 385
+8 -1
sound/soc/codecs/ad193x.h
··· 13 13 14 14 struct device; 15 15 16 + enum ad193x_type { 17 + AD193X, 18 + AD1933, 19 + AD1934, 20 + }; 21 + 16 22 extern const struct regmap_config ad193x_regmap_config; 17 - int ad193x_probe(struct device *dev, struct regmap *regmap); 23 + int ad193x_probe(struct device *dev, struct regmap *regmap, 24 + enum ad193x_type type); 18 25 19 26 #define AD193X_PLL_CLK_CTRL0 0x00 20 27 #define AD193X_PLL_POWERDOWN 0x01