[alsa-devel] [PATCH 1/6] ASoC: AD1836: Fix setting the PCM format
Signed-off-by: Lars-Peter Clausen lars@metafoo.de
--- This patch doesn't need to go into stable since there are currently no users of PCM formats other than S32, which is the default.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de --- sound/soc/codecs/ad1836.c | 14 +++++++------- sound/soc/codecs/ad1836.h | 6 ++++++ 2 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index ab63d52..754c496 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c @@ -145,22 +145,22 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream, /* bit size */ switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: - word_len = 3; + word_len = AD1836_WORD_LEN_16; break; case SNDRV_PCM_FORMAT_S20_3LE: - word_len = 1; + word_len = AD1836_WORD_LEN_20; break; case SNDRV_PCM_FORMAT_S24_LE: case SNDRV_PCM_FORMAT_S32_LE: - word_len = 0; + word_len = AD1836_WORD_LEN_24; break; }
- snd_soc_update_bits(codec, AD1836_DAC_CTRL1, - AD1836_DAC_WORD_LEN_MASK, word_len); + snd_soc_update_bits(codec, AD1836_DAC_CTRL1, AD1836_DAC_WORD_LEN_MASK, + word_len << AD1836_DAC_WORD_LEN_OFFSET);
- snd_soc_update_bits(codec, AD1836_ADC_CTRL2, - AD1836_ADC_WORD_LEN_MASK, word_len); + snd_soc_update_bits(codec, AD1836_ADC_CTRL2, AD1836_ADC_WORD_LEN_MASK, + word_len << AD1836_ADC_WORD_OFFSET);
return 0; } diff --git a/sound/soc/codecs/ad1836.h b/sound/soc/codecs/ad1836.h index 8455967..9d6a3f8 100644 --- a/sound/soc/codecs/ad1836.h +++ b/sound/soc/codecs/ad1836.h @@ -25,6 +25,7 @@ #define AD1836_DAC_SERFMT_PCK256 (0x4 << 5) #define AD1836_DAC_SERFMT_PCK128 (0x5 << 5) #define AD1836_DAC_WORD_LEN_MASK 0x18 +#define AD1836_DAC_WORD_LEN_OFFSET 3
#define AD1836_DAC_CTRL2 1 #define AD1836_DACL1_MUTE 0 @@ -51,6 +52,7 @@ #define AD1836_ADCL2_MUTE 2 #define AD1836_ADCR2_MUTE 3 #define AD1836_ADC_WORD_LEN_MASK 0x30 +#define AD1836_ADC_WORD_OFFSET 5 #define AD1836_ADC_SERFMT_MASK (7 << 6) #define AD1836_ADC_SERFMT_PCK256 (0x4 << 6) #define AD1836_ADC_SERFMT_PCK128 (0x5 << 6) @@ -60,4 +62,8 @@
#define AD1836_NUM_REGS 16
+#define AD1836_WORD_LEN_24 0x0 +#define AD1836_WORD_LEN_20 0x1 +#define AD1836_WORD_LEN_16 0x2 + #endif
The different ADC and DAC controls follow the same scheme, so add some helper macros for declaring them. This should make the code a bit more readable and also decreases the code size a bit.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de --- sound/soc/codecs/ad1836.c | 48 ++++++++++++++++++++++++-------------------- sound/soc/codecs/ad1836.h | 23 ++++++--------------- 2 files changed, 33 insertions(+), 38 deletions(-)
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index 754c496..5c6d239 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c @@ -44,28 +44,32 @@ static const char *ad1836_deemp[] = {"None", "44.1kHz", "32kHz", "48kHz"}; static const struct soc_enum ad1836_deemp_enum = SOC_ENUM_SINGLE(AD1836_DAC_CTRL1, 8, 4, ad1836_deemp);
+#define AD1836_DAC_VOLUME(x) \ + SOC_DOUBLE_R("DAC" #x " Playback Volume", AD1836_DAC_L_VOL(x), \ + AD1836_DAC_R_VOL(x), 0, 0x3FF, 0) + +#define AD1836_DAC_SWITCH(x) \ + SOC_DOUBLE("DAC" #x " Playback Switch", AD1836_DAC_CTRL2, \ + AD1836_MUTE_LEFT(x), AD1836_MUTE_RIGHT(x), 1, 1) + +#define AD1836_ADC_SWITCH(x) \ + SOC_DOUBLE("ADC" #x " Capture Switch", AD1836_ADC_CTRL2, \ + AD1836_MUTE_LEFT(x), AD1836_MUTE_RIGHT(x), 1, 1) + static const struct snd_kcontrol_new ad1836_snd_controls[] = { /* DAC volume control */ - SOC_DOUBLE_R("DAC1 Volume", AD1836_DAC_L1_VOL, - AD1836_DAC_R1_VOL, 0, 0x3FF, 0), - SOC_DOUBLE_R("DAC2 Volume", AD1836_DAC_L2_VOL, - AD1836_DAC_R2_VOL, 0, 0x3FF, 0), - SOC_DOUBLE_R("DAC3 Volume", AD1836_DAC_L3_VOL, - AD1836_DAC_R3_VOL, 0, 0x3FF, 0), + AD1836_DAC_VOLUME(1), + AD1836_DAC_VOLUME(2), + AD1836_DAC_VOLUME(3),
/* ADC switch control */ - SOC_DOUBLE("ADC1 Switch", AD1836_ADC_CTRL2, AD1836_ADCL1_MUTE, - AD1836_ADCR1_MUTE, 1, 1), - SOC_DOUBLE("ADC2 Switch", AD1836_ADC_CTRL2, AD1836_ADCL2_MUTE, - AD1836_ADCR2_MUTE, 1, 1), + AD1836_ADC_SWITCH(1), + AD1836_ADC_SWITCH(2),
/* DAC switch control */ - SOC_DOUBLE("DAC1 Switch", AD1836_DAC_CTRL2, AD1836_DACL1_MUTE, - AD1836_DACR1_MUTE, 1, 1), - SOC_DOUBLE("DAC2 Switch", AD1836_DAC_CTRL2, AD1836_DACL2_MUTE, - AD1836_DACR2_MUTE, 1, 1), - SOC_DOUBLE("DAC3 Switch", AD1836_DAC_CTRL2, AD1836_DACL3_MUTE, - AD1836_DACR3_MUTE, 1, 1), + AD1836_DAC_SWITCH(1), + AD1836_DAC_SWITCH(2), + AD1836_DAC_SWITCH(3),
/* ADC high-pass filter */ SOC_SINGLE("ADC High Pass Filter Switch", AD1836_ADC_CTRL1, @@ -242,12 +246,12 @@ static int ad1836_probe(struct snd_soc_codec *codec) /* left/right diff:PGA/MUX */ snd_soc_write(codec, AD1836_ADC_CTRL3, 0x3A); /* volume */ - snd_soc_write(codec, AD1836_DAC_L1_VOL, 0x3FF); - snd_soc_write(codec, AD1836_DAC_R1_VOL, 0x3FF); - snd_soc_write(codec, AD1836_DAC_L2_VOL, 0x3FF); - snd_soc_write(codec, AD1836_DAC_R2_VOL, 0x3FF); - snd_soc_write(codec, AD1836_DAC_L3_VOL, 0x3FF); - snd_soc_write(codec, AD1836_DAC_R3_VOL, 0x3FF); + snd_soc_write(codec, AD1836_DAC_L_VOL(1), 0x3FF); + snd_soc_write(codec, AD1836_DAC_R_VOL(1), 0x3FF); + snd_soc_write(codec, AD1836_DAC_L_VOL(2), 0x3FF); + snd_soc_write(codec, AD1836_DAC_R_VOL(2), 0x3FF); + snd_soc_write(codec, AD1836_DAC_L_VOL(3), 0x3FF); + snd_soc_write(codec, AD1836_DAC_R_VOL(3), 0x3FF);
snd_soc_add_controls(codec, ad1836_snd_controls, ARRAY_SIZE(ad1836_snd_controls)); diff --git a/sound/soc/codecs/ad1836.h b/sound/soc/codecs/ad1836.h index 9d6a3f8..f13402f 100644 --- a/sound/soc/codecs/ad1836.h +++ b/sound/soc/codecs/ad1836.h @@ -28,29 +28,20 @@ #define AD1836_DAC_WORD_LEN_OFFSET 3
#define AD1836_DAC_CTRL2 1 -#define AD1836_DACL1_MUTE 0 -#define AD1836_DACR1_MUTE 1 -#define AD1836_DACL2_MUTE 2 -#define AD1836_DACR2_MUTE 3 -#define AD1836_DACL3_MUTE 4 -#define AD1836_DACR3_MUTE 5
-#define AD1836_DAC_L1_VOL 2 -#define AD1836_DAC_R1_VOL 3 -#define AD1836_DAC_L2_VOL 4 -#define AD1836_DAC_R2_VOL 5 -#define AD1836_DAC_L3_VOL 6 -#define AD1836_DAC_R3_VOL 7 +/* These macros are one-based. So AD183X_MUTE_LEFT(1) will return the mute bit + * for the first ADC/DAC */ +#define AD1836_MUTE_LEFT(x) (((x) * 2) - 2) +#define AD1836_MUTE_RIGHT(x) (((x) * 2) - 1) + +#define AD1836_DAC_L_VOL(x) ((x) * 2) +#define AD1836_DAC_R_VOL(x) (1 + ((x) * 2))
#define AD1836_ADC_CTRL1 12 #define AD1836_ADC_POWERDOWN 7 #define AD1836_ADC_HIGHPASS_FILTER 8
#define AD1836_ADC_CTRL2 13 -#define AD1836_ADCL1_MUTE 0 -#define AD1836_ADCR1_MUTE 1 -#define AD1836_ADCL2_MUTE 2 -#define AD1836_ADCR2_MUTE 3 #define AD1836_ADC_WORD_LEN_MASK 0x30 #define AD1836_ADC_WORD_OFFSET 5 #define AD1836_ADC_SERFMT_MASK (7 << 6)
Use snd_soc_update_bits for read-modify-write register access instead of open-coding it using snd_soc_read and snd_soc_write.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de --- sound/soc/codecs/ad1836.c | 18 ++++++------------ 1 files changed, 6 insertions(+), 12 deletions(-)
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index 5c6d239..fde0f17 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c @@ -174,19 +174,15 @@ static int ad1836_soc_suspend(struct snd_soc_codec *codec, pm_message_t state) { /* reset clock control mode */ - u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); - adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK; - - return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2); + return snd_soc_update_bits(codec, AD1836_ADC_CTRL2, + AD1836_ADC_SERFMT_MASK, 0); }
static int ad1836_soc_resume(struct snd_soc_codec *codec) { /* restore clock control mode */ - u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); - adc_ctrl2 |= AD1836_ADC_AUX; - - return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2); + return snd_soc_update_bits(codec, AD1836_ADC_CTRL2, + AD1836_ADC_SERFMT_MASK, AD1836_ADC_AUX); } #else #define ad1836_soc_suspend NULL @@ -266,10 +262,8 @@ static int ad1836_probe(struct snd_soc_codec *codec) static int ad1836_remove(struct snd_soc_codec *codec) { /* reset clock control mode */ - u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); - adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK; - - return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2); + return snd_soc_update_bits(codec, AD1836_ADC_CTRL2, + AD1836_ADC_SERFMT_MASK, 0); }
static struct snd_soc_codec_driver soc_codec_dev_ad1836 = {
The AD183X codec devices are mostly register compatible and can easily be supported by the same driver. The main difference between those devices is the number of DACs and ADCs.
This patch adjusts the driver to allocate the controls, DAPM widgets and routes for the DACs and ADCs dynamically based on the chip type.
The AD1836 is a bit special in that it supports different modes for its second ADC, so it needs some special handling. Right now the driver hardcodes the mode to the differential PGA mode.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de --- sound/soc/codecs/ad1836.c | 183 +++++++++++++++++++++++++++++++------------- 1 files changed, 129 insertions(+), 54 deletions(-)
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index fde0f17..a443cfe 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c @@ -30,10 +30,17 @@ #include <linux/spi/spi.h> #include "ad1836.h"
+enum ad1836_type { + AD1835, + AD1836, + AD1838, +}; + /* codec private data */ struct ad1836_priv { enum snd_soc_control_type control_type; void *control_data; + enum ad1836_type type; };
/* @@ -56,21 +63,48 @@ static const struct soc_enum ad1836_deemp_enum = SOC_DOUBLE("ADC" #x " Capture Switch", AD1836_ADC_CTRL2, \ AD1836_MUTE_LEFT(x), AD1836_MUTE_RIGHT(x), 1, 1)
-static const struct snd_kcontrol_new ad1836_snd_controls[] = { - /* DAC volume control */ +static const struct snd_kcontrol_new ad183x_dac_controls[] = { AD1836_DAC_VOLUME(1), + AD1836_DAC_SWITCH(1), AD1836_DAC_VOLUME(2), + AD1836_DAC_SWITCH(2), AD1836_DAC_VOLUME(3), + AD1836_DAC_SWITCH(3), + AD1836_DAC_VOLUME(4), + AD1836_DAC_SWITCH(4), +}; + +static const struct snd_soc_dapm_widget ad183x_dac_dapm_widgets[] = { + SND_SOC_DAPM_OUTPUT("DAC1OUT"), + SND_SOC_DAPM_OUTPUT("DAC2OUT"), + SND_SOC_DAPM_OUTPUT("DAC3OUT"), + SND_SOC_DAPM_OUTPUT("DAC4OUT"), +}; + +static const struct snd_soc_dapm_route ad183x_dac_routes[] = { + { "DAC1OUT", NULL, "DAC" }, + { "DAC2OUT", NULL, "DAC" }, + { "DAC3OUT", NULL, "DAC" }, + { "DAC4OUT", NULL, "DAC" }, +};
- /* ADC switch control */ +static const struct snd_kcontrol_new ad183x_adc_controls[] = { AD1836_ADC_SWITCH(1), AD1836_ADC_SWITCH(2), + AD1836_ADC_SWITCH(3), +};
- /* DAC switch control */ - AD1836_DAC_SWITCH(1), - AD1836_DAC_SWITCH(2), - AD1836_DAC_SWITCH(3), +static const struct snd_soc_dapm_widget ad183x_adc_dapm_widgets[] = { + SND_SOC_DAPM_INPUT("ADC1IN"), + SND_SOC_DAPM_INPUT("ADC2IN"), +}; + +static const struct snd_soc_dapm_route ad183x_adc_routes[] = { + { "ADC", NULL, "ADC1IN" }, + { "ADC", NULL, "ADC2IN" }, +};
+static const struct snd_kcontrol_new ad183x_controls[] = { /* ADC high-pass filter */ SOC_SINGLE("ADC High Pass Filter Switch", AD1836_ADC_CTRL1, AD1836_ADC_HIGHPASS_FILTER, 1, 0), @@ -79,27 +113,17 @@ static const struct snd_kcontrol_new ad1836_snd_controls[] = { SOC_ENUM("Playback Deemphasis", ad1836_deemp_enum), };
-static const struct snd_soc_dapm_widget ad1836_dapm_widgets[] = { +static const struct snd_soc_dapm_widget ad183x_dapm_widgets[] = { SND_SOC_DAPM_DAC("DAC", "Playback", AD1836_DAC_CTRL1, AD1836_DAC_POWERDOWN, 1), SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_SUPPLY("ADC_PWR", AD1836_ADC_CTRL1, AD1836_ADC_POWERDOWN, 1, NULL, 0), - SND_SOC_DAPM_OUTPUT("DAC1OUT"), - SND_SOC_DAPM_OUTPUT("DAC2OUT"), - SND_SOC_DAPM_OUTPUT("DAC3OUT"), - SND_SOC_DAPM_INPUT("ADC1IN"), - SND_SOC_DAPM_INPUT("ADC2IN"), };
-static const struct snd_soc_dapm_route audio_paths[] = { +static const struct snd_soc_dapm_route ad183x_dapm_routes[] = { { "DAC", NULL, "ADC_PWR" }, { "ADC", NULL, "ADC_PWR" }, - { "DAC1OUT", "DAC1 Switch", "DAC" }, - { "DAC2OUT", "DAC2 Switch", "DAC" }, - { "DAC3OUT", "DAC3 Switch", "DAC" }, - { "ADC", "ADC1 Switch", "ADC1IN" }, - { "ADC", "ADC2 Switch", "ADC2IN" }, };
/* @@ -194,33 +218,44 @@ static struct snd_soc_dai_ops ad1836_dai_ops = { .set_fmt = ad1836_set_dai_fmt, };
-/* codec DAI instance */ -static struct snd_soc_dai_driver ad1836_dai = { - .name = "ad1836-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 6, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 2, - .channels_max = 4, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, - }, - .ops = &ad1836_dai_ops, +#define AD183X_DAI(_name, num_dacs, num_adcs) \ +{ \ + .name = _name "-hifi", \ + .playback = { \ + .stream_name = "Playback", \ + .channels_min = 2, \ + .channels_max = (num_dacs) * 2, \ + .rates = SNDRV_PCM_RATE_48000, \ + .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, \ + }, \ + .capture = { \ + .stream_name = "Capture", \ + .channels_min = 2, \ + .channels_max = (num_adcs) * 2, \ + .rates = SNDRV_PCM_RATE_48000, \ + .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, \ + }, \ + .ops = &ad1836_dai_ops, \ +} + +static struct snd_soc_dai_driver ad183x_dais[] = { + [AD1835] = AD183X_DAI("ad1835", 4, 1), + [AD1836] = AD183X_DAI("ad1836", 3, 2), + [AD1838] = AD183X_DAI("ad1838", 3, 1), };
static int ad1836_probe(struct snd_soc_codec *codec) { struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec); struct snd_soc_dapm_context *dapm = &codec->dapm; + int num_dacs, num_adcs; int ret = 0; + int i; + + num_dacs = ad183x_dais[ad1836->type].playback.channels_max / 2; + num_adcs = ad183x_dais[ad1836->type].capture.channels_max / 2;
codec->control_data = ad1836->control_data; ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI); @@ -239,21 +274,42 @@ static int ad1836_probe(struct snd_soc_codec *codec) snd_soc_write(codec, AD1836_ADC_CTRL1, 0x100); /* unmute adc channles, adc aux mode */ snd_soc_write(codec, AD1836_ADC_CTRL2, 0x180); - /* left/right diff:PGA/MUX */ - snd_soc_write(codec, AD1836_ADC_CTRL3, 0x3A); /* volume */ - snd_soc_write(codec, AD1836_DAC_L_VOL(1), 0x3FF); - snd_soc_write(codec, AD1836_DAC_R_VOL(1), 0x3FF); - snd_soc_write(codec, AD1836_DAC_L_VOL(2), 0x3FF); - snd_soc_write(codec, AD1836_DAC_R_VOL(2), 0x3FF); - snd_soc_write(codec, AD1836_DAC_L_VOL(3), 0x3FF); - snd_soc_write(codec, AD1836_DAC_R_VOL(3), 0x3FF); - - snd_soc_add_controls(codec, ad1836_snd_controls, - ARRAY_SIZE(ad1836_snd_controls)); - snd_soc_dapm_new_controls(dapm, ad1836_dapm_widgets, - ARRAY_SIZE(ad1836_dapm_widgets)); - snd_soc_dapm_add_routes(dapm, audio_paths, ARRAY_SIZE(audio_paths)); + for (i = 1; i <= num_dacs; ++i) { + snd_soc_write(codec, AD1836_DAC_L_VOL(i), 0x3FF); + snd_soc_write(codec, AD1836_DAC_R_VOL(i), 0x3FF); + } + + if (ad1836->type == AD1836) { + /* left/right diff:PGA/MUX */ + snd_soc_write(codec, AD1836_ADC_CTRL3, 0x3A); + } else { + snd_soc_write(codec, AD1836_ADC_CTRL3, 0x00); + } + + ret = snd_soc_add_controls(codec, ad183x_dac_controls, num_dacs * 2); + if (ret) + return ret; + + ret = snd_soc_add_controls(codec, ad183x_adc_controls, num_adcs); + if (ret) + return ret; + + ret = snd_soc_dapm_new_controls(dapm, ad183x_dac_dapm_widgets, num_dacs); + if (ret) + return ret; + + ret = snd_soc_dapm_new_controls(dapm, ad183x_adc_dapm_widgets, num_adcs); + if (ret) + return ret; + + ret = snd_soc_dapm_add_routes(dapm, ad183x_dac_routes, num_dacs); + if (ret) + return ret; + + ret = snd_soc_dapm_add_routes(dapm, ad183x_adc_routes, num_adcs); + if (ret) + return ret;
return ret; } @@ -273,6 +329,13 @@ static struct snd_soc_codec_driver soc_codec_dev_ad1836 = { .resume = ad1836_soc_resume, .reg_cache_size = AD1836_NUM_REGS, .reg_word_size = sizeof(u16), + + .controls = ad183x_controls, + .num_controls = ARRAY_SIZE(ad183x_controls), + .dapm_widgets = ad183x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ad183x_dapm_widgets), + .dapm_routes = ad183x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(ad183x_dapm_routes), };
static int __devinit ad1836_spi_probe(struct spi_device *spi) @@ -284,12 +347,14 @@ static int __devinit ad1836_spi_probe(struct spi_device *spi) if (ad1836 == NULL) return -ENOMEM;
+ ad1836->type = spi_get_device_id(spi)->driver_data; + spi_set_drvdata(spi, ad1836); ad1836->control_data = spi; ad1836->control_type = SND_SOC_SPI;
ret = snd_soc_register_codec(&spi->dev, - &soc_codec_dev_ad1836, &ad1836_dai, 1); + &soc_codec_dev_ad1836, &ad183x_dais[ad1836->type], 1); if (ret < 0) kfree(ad1836); return ret; @@ -301,6 +366,15 @@ static int __devexit ad1836_spi_remove(struct spi_device *spi) kfree(spi_get_drvdata(spi)); return 0; } +static const struct spi_device_id ad1836_ids[] = { + { "ad1835", AD1835 }, + { "ad1836", AD1836 }, + { "ad1837", AD1835 }, + { "ad1838", AD1838 }, + { "ad1839", AD1838 }, + { }, +}; +MODULE_DEVICE_TABLE(spi, ad1836_ids);
static struct spi_driver ad1836_spi_driver = { .driver = { @@ -309,6 +383,7 @@ static struct spi_driver ad1836_spi_driver = { }, .probe = ad1836_spi_probe, .remove = __devexit_p(ad1836_spi_remove), + .id_table = ad1836_ids, };
static int __init ad1836_init(void)
On Mon, Jun 06, 2011 at 01:38:38PM +0200, Lars-Peter Clausen wrote:
The AD183X codec devices are mostly register compatible and can easily be supported by the same driver. The main difference between those devices is the number of DACs and ADCs.
Please try to fix whatever it is gives this really weird word wrapping in your changelogs - they frequently have line breaks in the middle of paragraphs for some reason.
The control_type field is never used, so it can be removed. The control_data field is used to initialize the codec's control_data field, but since this is also done by the snd-soc-cache core, the redundant assignment can be removed and the field can be dropped.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de --- sound/soc/codecs/ad1836.c | 5 ----- 1 files changed, 0 insertions(+), 5 deletions(-)
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index a443cfe..75ff5a5 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c @@ -38,8 +38,6 @@ enum ad1836_type {
/* codec private data */ struct ad1836_priv { - enum snd_soc_control_type control_type; - void *control_data; enum ad1836_type type; };
@@ -257,7 +255,6 @@ static int ad1836_probe(struct snd_soc_codec *codec) num_dacs = ad183x_dais[ad1836->type].playback.channels_max / 2; num_adcs = ad183x_dais[ad1836->type].capture.channels_max / 2;
- codec->control_data = ad1836->control_data; ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI); if (ret < 0) { dev_err(codec->dev, "failed to set cache I/O: %d\n", @@ -350,8 +347,6 @@ static int __devinit ad1836_spi_probe(struct spi_device *spi) ad1836->type = spi_get_device_id(spi)->driver_data;
spi_set_drvdata(spi, ad1836); - ad1836->control_data = spi; - ad1836->control_type = SND_SOC_SPI;
ret = snd_soc_register_codec(&spi->dev, &soc_codec_dev_ad1836, &ad183x_dais[ad1836->type], 1);
The AD1836 has a PGA for its second ADC. This patch adds a control for adjusting the the gain of the PGA.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de --- sound/soc/codecs/ad1836.c | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index 75ff5a5..1e9a801 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c @@ -124,6 +124,13 @@ static const struct snd_soc_dapm_route ad183x_dapm_routes[] = { { "ADC", NULL, "ADC_PWR" }, };
+static const DECLARE_TLV_DB_SCALE(ad1836_in_tlv, 0, 300, 0); + +static const struct snd_kcontrol_new ad1836_controls[] = { + SOC_DOUBLE_TLV("ADC2 Capture Volume", AD183X_ADC_CTRL1, 3, 0, 4, 0, + ad1836_in_tlv), +}; + /* * DAI ops entries */ @@ -280,6 +287,10 @@ static int ad1836_probe(struct snd_soc_codec *codec) if (ad1836->type == AD1836) { /* left/right diff:PGA/MUX */ snd_soc_write(codec, AD1836_ADC_CTRL3, 0x3A); + ret = snd_soc_add_controls(codec, ad1836_controls, + ARRAY_SIZE(ad1836_controls)); + if (ret) + return ret; } else { snd_soc_write(codec, AD1836_ADC_CTRL3, 0x00); }
On 06/06/11 12:38, Lars-Peter Clausen wrote:
Signed-off-by: Lars-Peter Clausen lars@metafoo.de
This patch doesn't need to go into stable since there are currently no users of PCM formats other than S32, which is the default.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de
All
Acked-by: Liam Girdwood lrg@ti.com
On Mon, Jun 06, 2011 at 01:38:35PM +0200, Lars-Peter Clausen wrote:
Signed-off-by: Lars-Peter Clausen lars@metafoo.de
All applied, thanks.
This patch doesn't need to go into stable since there are currently no users of PCM formats other than S32, which is the default.
Even if there's no mainline users it's still worth distributing the fix so out of tree users get to pick it up.
participants (3)
-
Lars-Peter Clausen
-
Liam Girdwood
-
Mark Brown