Title: [6760] trunk/sound/soc: add I2S support for ad1938

Diff

Modified: trunk/sound/soc/blackfin/Kconfig (6759 => 6760)


--- trunk/sound/soc/blackfin/Kconfig	2009-06-17 07:22:34 UTC (rev 6759)
+++ trunk/sound/soc/blackfin/Kconfig	2009-06-17 08:02:40 UTC (rev 6760)
@@ -33,13 +33,6 @@
 	help
 	  Say Y if you want to add support for AD73311 codec on Blackfin.
 
-config SND_BF5XX_SOC_AD1938
-	tristate "SoC AD1938 Audio support for Blackfin"
-	depends on SND_BF5XX_TDM
-	select SND_BF5XX_SOC_TDM
-	select SND_SOC_AD1938
-	help
-	  Say Y if you want to add support for AD1938 codec on Blackfin.
 
 config SND_BFIN_AD73311_SE
 	int "PF pin for AD73311L Chip Select"
@@ -104,6 +97,37 @@
 	help
 	  Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT.
 
+config SND_BF5XX_SOC_AD1938
+	tristate "SoC AD1938 Audio support for Blackfin"
+	depends on (SND_BF5XX_TDM || SND_BF5XX_I2S)
+	select SND_BF5XX_SOC_TDM
+	select SND_BF5XX_SOC_I2S
+	select SND_SOC_AD1938
+	help
+	  Say Y if you want to add support for AD1938 codec on Blackfin.
+choice
+	prompt "Interface between Blackfin and AD1938"
+	depends on SND_BF5XX_SOC_AD1938
+	default SND_BF5XX_AD1938_TDM
+	help
+	  There are two types of interface can be supportted on Blackfin
+	  Stamp: TDM and I2S. TDM support 8 channels. I2S only support 2 channels.
+
+config SND_BF5XX_AD1938_TDM
+	boolean "TDM interface"
+	depends on SND_BF5XX_TDM
+	help
+	  TDM supports 8 channels ouput
+	  If unsure, say Y.
+
+config SND_BF5XX_AD1938_I2S
+	boolean "I2S interface"
+	depends on SND_BF5XX_I2S
+	help
+	  I2S support 2 channels ouput
+	  If unsure, say N.
+endchoice
+
 config SND_BF5XX_SPORT_NUM
 	int "Set a SPORT for Sound chip"
 	depends on (SND_BF5XX_I2S || SND_BF5XX_AC97 || SND_BF5XX_TDM)

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/blackfin/bf5xx-tdm-pcm.c (6759 => 6760)


--- trunk/sound/soc/blackfin/bf5xx-tdm-pcm.c	2009-06-17 07:22:34 UTC (rev 6759)
+++ trunk/sound/soc/blackfin/bf5xx-tdm-pcm.c	2009-06-17 08:02:40 UTC (rev 6760)
@@ -313,6 +313,18 @@
 };
 EXPORT_SYMBOL_GPL(bf5xx_tdm_soc_platform);
 
+static int __init bfin_tdm_init(void)
+{
+	return snd_soc_register_platform(&bf5xx_tdm_soc_platform);
+}
+module_init(bfin_tdm_init);
+
+static void __exit bfin_tdm_exit(void)
+{
+	snd_soc_unregister_platform(&bf5xx_tdm_soc_platform);
+}
+module_exit(bfin_tdm_exit);
+
 MODULE_AUTHOR("Barry Song");
 MODULE_DESCRIPTION("ADI Blackfin TDM PCM DMA module");
 MODULE_LICENSE("GPL");

Modified: trunk/sound/soc/blackfin/bf5xx-tdm.c (6759 => 6760)


--- trunk/sound/soc/blackfin/bf5xx-tdm.c	2009-06-17 07:22:34 UTC (rev 6759)
+++ trunk/sound/soc/blackfin/bf5xx-tdm.c	2009-06-17 08:02:40 UTC (rev 6760)
@@ -276,6 +276,18 @@
 };
 EXPORT_SYMBOL_GPL(bf5xx_tdm_dai);
 
+static int __init bfin_tdm_init(void)
+{
+	return snd_soc_register_dai(&bf5xx_tdm_dai);
+}
+module_init(bfin_tdm_init);
+
+static void __exit bfin_tdm_exit(void)
+{
+	snd_soc_unregister_dai(&bf5xx_tdm_dai);
+}
+MODULE_EXIT(bfin_tdm_exit);
+
 /* Module information */
 MODULE_AUTHOR("Barry Song");
 MODULE_DESCRIPTION("TDM driver for ADI Blackfin");

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;
 

Modified: trunk/sound/soc/codecs/ad1938.h (6759 => 6760)


--- trunk/sound/soc/codecs/ad1938.h	2009-06-17 07:22:34 UTC (rev 6759)
+++ trunk/sound/soc/codecs/ad1938.h	2009-06-17 08:02:40 UTC (rev 6760)
@@ -39,6 +39,7 @@
 #define DAC_SERFMT_TDM		(1 << 6)
 #define AD1938_DAC_CTRL1        3
 #define AD1938_DAC_CTRL2        4
+#define DAC_WORD_LEN_MASK	0xC
 #define AD1938_DAC_CHNL_MUTE    5
 #define AD1938_DAC_L1_VOL       6
 #define AD1938_DAC_R1_VOL       7
@@ -59,6 +60,7 @@
 #define ADC_SERFMT_MASK		0x60
 #define ADC_SERFMT_STEREO	(0 << 5)
 #define ADC_SERFMT_AUX		(2 << 5)
+#define ADC_WORD_LEN_MASK	0x3
 #define AD1938_ADC_CTRL2        16
 
 extern struct snd_soc_dai ad1938_dai;
_______________________________________________
Linux-kernel-commits mailing list
[email protected]
https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits

Reply via email to