Modified: trunk/sound/soc/blackfin/bf5xx-ad1938.c (6759 => 6760)
--- trunk/sound/soc/blackfin/bf5xx-ad1938.c 2009-06-17 07:22:34 UTC (rev 6759)
+++ trunk/sound/soc/blackfin/bf5xx-ad1938.c 2009-06-17 08:02:40 UTC (rev 6760)
@@ -40,8 +40,14 @@
#include "../codecs/ad1938.h"
#include "bf5xx-sport.h"
+
+#ifdef CONFIG_SND_BF5XX_AD1938_TDM
#include "bf5xx-tdm-pcm.h"
#include "bf5xx-tdm.h"
+#else
+#include "bf5xx-i2s-pcm.h"
+#include "bf5xx-i2s.h"
+#endif
static struct snd_soc_card bf5xx_ad1938;
@@ -70,13 +76,31 @@
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
int ret = 0;
-
+#ifdef CONFIG_SND_BF5XX_AD1938_TDM
/* set cpu DAI configuration */
ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_SPORT_TDM |
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
if (ret < 0)
return ret;
+ /* set codec DAI configuration */
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_SPORT_TDM |
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0)
+ return ret;
+#else
+ /* set cpu DAI configuration */
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0)
+ return ret;
+
+ /* set codec DAI configuration */
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0)
+ return ret;
+#endif
/* set codec DAI pll */
ret = snd_soc_dai_set_pll(codec_dai, 0, 12288000, 48000*512);
if (ret < 0)
@@ -94,14 +118,22 @@
static struct snd_soc_dai_link bf5xx_ad1938_dai = {
.name = "ad1938",
.stream_name = "AD1938",
+#ifdef CONFIG_SND_BF5XX_AD1938_TDM
.cpu_dai = &bf5xx_tdm_dai,
+#else
+ .cpu_dai = &bf5xx_i2s_dai,
+#endif
.codec_dai = &ad1938_dai,
.ops = &bf5xx_ad1938_ops,
};
static struct snd_soc_card bf5xx_ad1938 = {
.name = "bf5xx_ad1938",
+#ifdef CONFIG_SND_BF5XX_AD1938_TDM
.platform = &bf5xx_tdm_soc_platform,
+#else
+ .platform = &bf5xx_i2s_soc_platform,
+#endif
.dai_link = &bf5xx_ad1938_dai,
.num_links = 1,
};
Modified: trunk/sound/soc/codecs/ad1938.c (6759 => 6760)
--- trunk/sound/soc/codecs/ad1938.c 2009-06-17 07:22:34 UTC (rev 6759)
+++ trunk/sound/soc/codecs/ad1938.c 2009-06-17 08:02:40 UTC (rev 6760)
@@ -20,6 +20,7 @@
#include <linux/device.h>
#include <sound/core.h>
#include <sound/pcm.h>
+#include <sound/pcm_params.h>
#include <sound/initval.h>
#include <sound/soc.h>
#include <linux/spi/spi.h>
@@ -161,36 +162,45 @@
return 0;
}
+static int ad1938_tdm_set(struct snd_soc_codec *codec)
+{
+ codec->write(codec, AD1938_DAC_CTRL0, (codec->read(codec, AD1938_DAC_CTRL0) &
+ (~DAC_SERFMT_MASK)) | DAC_SERFMT_TDM);
+ codec->write(codec, AD1938_DAC_CTRL1, 0x84); /* invert bclk, 256bclk/frame, latch in mid */
+ codec->write(codec, AD1938_ADC_CTRL1, 0x43); /* sata delay=1, adc aux mode */
+ codec->write(codec, AD1938_ADC_CTRL2, 0x6F); /* left high, driver on rising edge */
+
+ return 0;
+}
+
+static int ad1938_i2s_set(struct snd_soc_codec *codec)
+{
+ codec->write(codec, AD1938_DAC_CTRL0, (codec->read(codec, AD1938_DAC_CTRL0) &
+ (~DAC_SERFMT_MASK)) | DAC_SERFMT_STEREO);
+ codec->write(codec, AD1938_DAC_CTRL1, 0x30); /* 64bclk/frame, latch in mid, left low */
+ codec->write(codec, AD1938_ADC_CTRL1, 0x3); /* sata delay=1, stereo mode */
+ codec->write(codec, AD1938_ADC_CTRL2, 0x48); /* left low, driver on falling edge */
+
+ return 0;
+}
+
static int ad1938_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned int fmt)
{
struct snd_soc_codec *codec = codec_dai->codec;
- int adc_reg, dac_reg;
- /* read back adc and dac control registers */
- adc_reg = codec->read(codec, AD1938_ADC_CTRL1);
- dac_reg = codec->read(codec, AD1938_DAC_CTRL0);
- adc_reg &= ~ADC_SERFMT_MASK;
- dac_reg &= ~DAC_SERFMT_MASK;
-
/* interface format */
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_SPORT_TDM:
- adc_reg |= ADC_SERFMT_AUX;
- dac_reg |= DAC_SERFMT_TDM;
+ ad1938_tdm_set(codec);
break;
case SND_SOC_DAIFMT_I2S:
- adc_reg |= ADC_SERFMT_STEREO;
- dac_reg |= DAC_SERFMT_STEREO;
+ ad1938_i2s_set(codec);
break;
default:
return -EINVAL;
}
- /* set new format */
- codec->write(codec, AD1938_ADC_CTRL1, adc_reg);
- codec->write(codec, AD1938_DAC_CTRL0, dac_reg);
-
return 0;
}
@@ -216,6 +226,41 @@
return 0;
}
+static int ad1938_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ int word_len = 0, reg = 0;
+
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->card->codec;
+
+ /* bit size */
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ word_len = 3;
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ word_len = 1;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ case SNDRV_PCM_FORMAT_S32_LE:
+ word_len = 0;
+ break;
+ }
+
+ reg = codec->read(codec, AD1938_DAC_CTRL2);
+ reg = (reg & (~DAC_WORD_LEN_MASK)) | word_len;
+ codec->write(codec, AD1938_DAC_CTRL2, reg);
+
+ reg = codec->read(codec, AD1938_ADC_CTRL1);
+ reg = (reg & (~ADC_WORD_LEN_MASK)) | word_len;
+ codec->write(codec, AD1938_DAC_CTRL1, reg);
+
+ return 0;
+}
+
static void ad1938_pcm_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
@@ -335,6 +380,7 @@
static struct snd_soc_dai_ops ad1938_dai_ops = {
.prepare = ad1938_pcm_prepare,
+ .hw_params = ad1938_hw_params,
.shutdown = ad1938_pcm_shutdown,
.digital_mute = ad1938_mute,
.set_pll = ad1938_set_pll,
@@ -349,13 +395,13 @@
.channels_min = 2,
.channels_max = 8,
.rates = SNDRV_PCM_RATE_48000,
- .formats = SNDRV_PCM_FMTBIT_S32_LE, },
+ .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, },
+ .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, },
.ops = &ad1938_dai_ops,
};
EXPORT_SYMBOL_GPL(ad1938_dai);
@@ -403,20 +449,17 @@
goto register_err;
}
- /* default setting for ad1938, poweroff dac/adc/pll */
- codec->write(codec, AD1938_DAC_CTRL0, 0x41); /* sample rate:32/44.1/48kHz, sata delay=1, tdm mode */
- codec->write(codec, AD1938_DAC_CTRL1, 0x84); /* invert bclk, 256bclk/frame, latch in mid */
- codec->write(codec, AD1938_DAC_CTRL2, 0x1A); /* de-emphasis: 48kHz */
- codec->write(codec, AD1938_ADC_CTRL0, 0x33); /* high-pass filter enable */
- codec->write(codec, AD1938_ADC_CTRL1, 0x43); /* sata delay=1, adc aux mode */
- codec->write(codec, AD1938_ADC_CTRL2, 0x6F); /* left high, driver on rising edge */
+ /* register controls for ad1938 */
+ ad1938_add_controls(codec);
+
+ /* default setting for ad1938 */
codec->write(codec, AD1938_DAC_CHNL_MUTE, 0xFF); /* mute all dac channels */
- codec->write(codec, AD1938_PLL_CLK_CTRL0, 0x9D); /* pll input:mclki/xi, master clock rate:512*fs */
+ codec->write(codec, AD1938_DAC_CTRL2, 0x1A); /* de-emphasis: 48kHz, powedown dac */
+ codec->write(codec, AD1938_DAC_CTRL0, 0x1); /* powerdown dac */
+ codec->write(codec, AD1938_ADC_CTRL0, 0x3); /* high-pass filter enable */
+ codec->write(codec, AD1938_PLL_CLK_CTRL0, 0x9D); /* pll input:mclki/xi */
codec->write(codec, AD1938_PLL_CLK_CTRL1, 0x04);
- /* register controls for ad1938 */
- ad1938_add_controls(codec);
-
printk(KERN_INFO "Analog Devices AD1938 codec registered\n");
return ret;