Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 257503
b: refs/heads/master
c: 874ce77
h: refs/heads/master
i:
  257501: 7cfd207
  257499: eaf068c
  257495: 1af46cd
  257487: 3c5e15f
  257471: 567dfc5
v: v3
  • Loading branch information
Lars-Peter Clausen authored and Mark Brown committed Jun 6, 2011
1 parent 1f19aba commit 6d3bdc6
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 55 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 2cf034282205a2115777b7a899f6f12d06943b62
refs/heads/master: 874ce77bc3027ce08e3ee35c3edad3b254e496d1
183 changes: 129 additions & 54 deletions trunk/sound/soc/codecs/ad1836.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

/*
Expand All @@ -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),
Expand All @@ -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" },
};

/*
Expand Down Expand Up @@ -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);
Expand All @@ -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;
}
Expand All @@ -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)
Expand All @@ -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;
Expand All @@ -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 = {
Expand All @@ -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)
Expand Down

0 comments on commit 6d3bdc6

Please sign in to comment.