Hi,
We are using DVRRDK 03.00.00.00. And use the DVR board for our reference design. The SoC is DM8168, PG2.0
I followed this porting guide to attach my 9022a to McASP 1 as sound card0, port0, where the 5158 was.
http://processors.wiki.ti.com/index.php/TI81xx_PSP_Porting_Guide#Audio_driver_.28McASP.29
The only thing that I didn't do exactly what it said is the mux part, I am not sure what to do here.
According to the porting guide, "Note that McASP2 of TI816x/TI814x does not require any pin muxing."
I may need do something here, since I am using McASP1. But after checking the SoC spec,
http://www.ti.com/lit/ug/sprugx8/sprugx8.pdf Page, 367
McASP[1] is dedicated port and needs no muxing.
The boot log shows that I attach the audio device successfully to the mcasp I want.
[ 2.250000] Registered tvp5158 audio codec
[ 2.250000] Registered SiI9022a HDMI audio codec
[ 2.260000] asoc: sii9022a <-> davinci-mcasp.1 mapping ok
[ 2.270000] asoc: tlv320aic3x-hifi <-> davinci-mcasp.2 mapping ok
[ 2.270000] asoc: HDMI-DAI-CODEC <-> hdmi-dai mapping ok
[ 2.280000] ALSA device list:
[ 2.280000] #0: TI81XX DVR
and cat /proc/asound/pcm is
00-00: hdmi-sii9022a sii9022a-0 : : playback 1
00-01: AIC3X tlv320aic3x-hifi-1 : : playback 1 : capture 1
00-02: hdmi HDMI-DAI-CODEC-2 : : playback 1
However, I cannot make the i2s output any signal, even the clock!
I didn't initiate 9022a before pushing frames to McASP1, Should I initiate 9022a first?
when using snd_pcm_writei to output audio, the buffer can quickly overrun and this message occurs.
playback write error (DMA or IRQ trouble?)
Interestingly, I switched tlv320 with 9022a and attached them to mcasp 1, mcasp2, respectively
[ 2.220000] Registered tvp5158 audio codec
[ 2.220000] Registered SiI9022a HDMI audio codec
[ 2.230000] asoc: sii9022a <-> davinci-mcasp.2 mapping ok
[ 2.230000] asoc: tlv320aic3x-hifi <-> davinci-mcasp.1 mapping ok
[ 2.240000] asoc: HDMI-DAI-CODEC <-> hdmi-dai mapping ok
[ 2.250000] ALSA device list:
[ 2.250000] #0: TI81XX DVR
All of them cannot work and result in playback write error (DMA or IRQ trouble?)
Here are my modifications, what else should I do?
diff --git a/arch/arm/mach-omap2/board-ti8168dvr.c b/arch/arm/mach-omap2/board-ti8168dvr.c
index d21eb96..3c2e6f2 100644
--- a/arch/arm/mach-omap2/board-ti8168dvr.c
+++ b/arch/arm/mach-omap2/board-ti8168dvr.c
@@ -454,6 +454,14 @@ static struct platform_device tvp5158_audio_device = {
};
#endif
+static struct platform_device sii9022a_audio_device = {
+ .name = "sii9022a-audio",
+ .id = -1,
+};
+
+
#define UART_REG_OFFSET(x) ((UART_##x) << 2)
@@ -495,6 +503,10 @@ static void __init ti8168_dvr_init(void)
platform_device_register(&tvp5158_audio_device);
#endif
+ platform_device_register(&sii9022a_audio_device);
+
ti81xx_register_mcasp(0, &ti8168_dvr_snd_data);
ti816x_spi_init();
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -2642,7 +2642,60 @@ static struct platform_device ti81xx_mcasp0_device = {
.num_resources = ARRAY_SIZE(ti81xx_mcasp0_resource),
.resource = ti81xx_mcasp0_resource,
};
#endif
+
+static u8 sii9022a_iis_serializer_direction[] = {
+ TX_MODE, RX_MODE, INACTIVE_MODE, INACTIVE_MODE,
+ INACTIVE_MODE, INACTIVE_MODE, INACTIVE_MODE, INACTIVE_MODE,
+ INACTIVE_MODE, INACTIVE_MODE, INACTIVE_MODE, INACTIVE_MODE,
+ INACTIVE_MODE, INACTIVE_MODE, INACTIVE_MODE, INACTIVE_MODE,
+};
+
+static struct snd_platform_data sii9022a_snd_data = {
+ .tx_dma_offset = 0x46400000,
+ .rx_dma_offset = 0x46400000,
+ .asp_chan_q = EVENTQ_2,
+ .tdm_slots = 2, /* number of channels */
+ .op_mode = DAVINCI_MCASP_IIS_MODE,
+ .num_serializer = ARRAY_SIZE(sii9022a_iis_serializer_direction),
+ .serial_dir = sii9022a_iis_serializer_direction,
+ .version = MCASP_VERSION_2,
+ .txnumevt = 1,
+ .rxnumevt = 1,
+};
+
+static struct resource ti81xx_mcasp1_resource[] = {
+ {
+ .name = "mcasp1",
+ .start = TI81XX_ASP1_BASE,
+ .end = TI81XX_ASP1_BASE + (SZ_1K * 12) - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ /* TX event */
+ {
+ .start = TI81XX_DMA_MCASP1_AXEVT,
+ .end = TI81XX_DMA_MCASP1_AXEVT,
+ .flags = IORESOURCE_DMA,
+ },
+ /* RX event */
+ {
+ .start = TI81XX_DMA_MCASP1_AREVT,
+ .end = TI81XX_DMA_MCASP1_AREVT,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct platform_device ti81xx_mcasp1_device = {
+ .name = "davinci-mcasp", /* driver name */
+ .id = 1,
+ .dev = {
+ .platform_data = &sii9022a_snd_data,
+ },
+ .num_resources = ARRAY_SIZE(ti81xx_mcasp1_resource),
+ .resource = ti81xx_mcasp1_resource,
+};
@@ -2654,6 +2707,9 @@ void __init ti81xx_register_mcasp(int id, struct snd_platform_data *pdata)
platform_device_register(&ti81xx_mcasp_device);
platform_device_register(&ti81xx_mcasp0_device);
+ platform_device_register(&ti81xx_mcasp1_device);
}
#else
void __init ti81xx_register_mcasp(int id, struct snd_platform_data *pdata)
diff --git a/sound/soc/codecs/syno_sii9022a_hdmi_audio.c b/sound/soc/codecs/syno_sii9022a_hdmi_audio.c
new file mode 100644
index 0000000..c8d5ea6
--- /dev/null
+++ b/sound/soc/codecs/syno_sii9022a_hdmi_audio.c
@@ -0,0 +1,108 @@
+/*
+ * ALSA SiI9022a HDMI audio driver
+ *
+ * This driver is used by TI81XX devices to config SiI9022a HDMI audio
+ * where no codec is needed. This file provides stub codec that can be used
+ * in these configurations.
+ * Based on OMAP4 HDMI audio codec driver
+ *
+ * Author: ChengYeh Yu <cyyu@synology.com>
+ * Copyright: (C) 2012 synology Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/slab.h>
+#include <sound/soc.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <linux/i2c.h>
+
+static struct snd_soc_codec_driver soc_codec_sii9022a;
+static struct i2c_client *client;
+
+/* null function */
+static int sii9022a_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ return 0;
+}
+
+static int sii9022a_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ return 0;
+}
+
+static struct snd_soc_dai_ops sii9022a_dai_ops = {
+ .set_sysclk = sii9022a_set_dai_sysclk,
+ .set_fmt = sii9022a_set_dai_fmt,
+};
+
+/* Dummy dai driver for HDMI */
+static struct snd_soc_dai_driver sii9022a_dai = {
+ .name = "sii9022a",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_48000
+ | SNDRV_PCM_RATE_32000
+ | SNDRV_PCM_RATE_44100
+ | SNDRV_PCM_RATE_96000
+ | SNDRV_PCM_RATE_192000 ,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE
+ | SNDRV_PCM_FMTBIT_S32_LE
+ | SNDRV_PCM_FMTBIT_S24_LE,
+ },
+ .ops = &sii9022a_dai_ops,
+};
+
+static int sii9022a_audio_codec_probe(struct platform_device *pdev)
+{
+ int ret;
+
+ ret = snd_soc_register_codec(&pdev->dev, &soc_codec_sii9022a,
+ &sii9022a_dai, 1);
+ if (ret < 0)
+ printk(KERN_INFO "SiI9022a HDMI Codec register Failed\n");
+ else
+ printk(KERN_INFO "Registered SiI9022a HDMI audio codec\n");
+
+ return ret;
+}
+
+static int sii9022a_audio_codec_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_codec(&pdev->dev);
+ return 0;
+}
+
+static struct platform_driver sii9022a_audio_codec_driver = {
+ .probe = sii9022a_audio_codec_probe,
+ .remove = sii9022a_audio_codec_remove,
+ .driver = {
+ .name = "sii9022a-audio",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init sii9022a_audio_init(void)
+{
+ return platform_driver_register(&sii9022a_audio_codec_driver);
+}
+
+static void __exit sii9022a_audio_exit(void)
+{
+ platform_driver_unregister(&sii9022a_audio_codec_driver);
+}
+
+module_init(sii9022a_audio_init);
+module_exit(sii9022a_audio_exit);
+
+MODULE_DESCRIPTION(" SiI9022a Audio Dummy codec Interface");
+MODULE_LICENSE("GPL");
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -68,6 +68,7 @@ snd-soc-wm9713-objs := wm9713.o
snd-soc-wm-hubs-objs := wm_hubs.o
snd-soc-jz4740-codec-objs := jz4740.o
snd-soc-ti81xx-hdmi-objs := ti81xx_hdmi.o
+snd-soc-syno-sii9022a-hdmi-audio-objs := syno_sii9022a_hdmi_audio.o
# Amp
snd-soc-max9877-objs := max9877.o
@@ -145,6 +146,7 @@ obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o
obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o
obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o
obj-$(CONFIG_SND_SOC_TI81XX_HDMI) += snd-soc-ti81xx-hdmi.o
+obj-$(CONFIG_SYNO_TI816X_SII9022A_AUDIO) += snd-soc-syno-sii9022a-hdmi-audio.o
# Amp
obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index 81cade9..5c561fc 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -896,6 +896,29 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
.ops = &davinci_mcasp_dai_ops,
},
+ {
+ .name = "davinci-mcasp.1",
+ .playback = {
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = DAVINCI_MCASP_RATES,
+ .formats = SNDRV_PCM_FMTBIT_S8 |
+ SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S32_LE,
+ },
+ .capture = {
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = DAVINCI_MCASP_RATES,
+ .formats = SNDRV_PCM_FMTBIT_S8 |
+ SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S32_LE,
+ },
+ .ops = &davinci_mcasp_dai_ops,
+
+ },
diff --git a/sound/soc/davinci/ti81xx-dvr.c b/sound/soc/davinci/ti81xx-dvr.c
index 3a8802b..b3de89d 100644
--- a/sound/soc/davinci/ti81xx-dvr.c
+++ b/sound/soc/davinci/ti81xx-dvr.c
@@ -40,6 +40,7 @@ static int ti81xx_dvr_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
unsigned sysclk, fmt = 0;
+ int ret;
/* default */
sysclk = 24576000;
@@ -50,6 +51,13 @@ static int ti81xx_dvr_hw_params(struct snd_pcm_substream *substream,
*/
fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM |
SND_SOC_DAIFMT_NB_IF;
+ } else if (!strcmp(rtd->dai_link->name,"SII9022AAUDIO")){
+ /*
+ * I2S Mode
+ */
+ printk (KERN_INFO "Preparing hardware parameters");
+ fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM |
+ SND_SOC_DAIFMT_IB_NF;
} else {
/*
* DSP_B Mode
@@ -129,6 +145,17 @@ static int ti81xx_dvr_aic3x_init(struct snd_soc_pcm_runtime *rtd)
}
static struct snd_soc_dai_link ti81xx_mcasp_dai[] = {
+#ifdef CONFIG_SYNO_TI816X_SII9022A_AUDIO
+ {
+ .name = "SII9022AAUDIO",
+ .stream_name = "hdmi-sii9022a",
+ .cpu_dai_name= "davinci-mcasp.1",
+ .platform_name = "davinci-pcm-audio",
+ .codec_dai_name = "sii9022a", /* DAI name */
+ .codec_name = "sii9022a-audio",
+ .ops = &ti81xx_dvr_ops,
+ },
+#else /* not CONFIG_SYNO_TI816X_SII9022A_AUDIO */
{
.name = "TVP5158AUDIO",
.stream_name = "TVP-PCM",
@@ -138,6 +165,7 @@ static struct snd_soc_dai_link ti81xx_mcasp_dai[] = {
.codec_name = "tvp5158-audio",
.ops = &ti81xx_dvr_ops,
},
+#endif /* not CONFIG_SYNO_TI816X_SII9022A_AUDIO */
{
.name = "TLV320AIC3X",
.stream_name = "AIC3X",