All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2/8] ASoC pxa2xx I2S support
@ 2006-10-10 16:11 Liam Girdwood
  2006-10-10 17:06 ` Takashi Iwai
  0 siblings, 1 reply; 6+ messages in thread
From: Liam Girdwood @ 2006-10-10 16:11 UTC (permalink / raw)
  To: alsa-devel

[-- Attachment #1: Type: text/plain, Size: 275 bytes --]

This patch adds pxa2xx I2S ASoC audio support. Features:-

 o Supports playback/capture
 o 16 bit PCM
 o 8k - 96k sample rates
 o Supports master and slave mode.

Signed-off-by: Richard Purdie <rpurdie@rpsys.net>
Signed-off-by: Liam Girdwood <liam.girdwood@wolfsonmicro.com>

[-- Attachment #2: asoc-pxa2xx-i2s.patch --]
[-- Type: text/x-patch, Size: 8395 bytes --]

Index: alsa-kernel/soc/pxa/pxa2xx-i2s.c
===================================================================
--- /dev/null
+++ alsa-kernel/soc/pxa/pxa2xx-i2s.c
@@ -0,0 +1,307 @@
+/*
+ * pxa2xx-i2s.c  --  ALSA Soc Audio Layer
+ *
+ * Copyright 2005 Wolfson Microelectronics PLC.
+ * Author: Liam Girdwood
+ *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  Revision history
+ *    12th Aug 2005   Initial version.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/audio.h>
+
+#include "pxa2xx-pcm.h"
+
+/* used to disable sysclk if external crystal is used */
+static int extclk = 0;
+module_param(extclk, int, 0);
+MODULE_PARM_DESC(extclk, "set to 1 to disable pxa2xx i2s sysclk");
+
+struct pxa_i2s_port {
+	u32 sadiv;
+	u32 sacr0;
+	u32 sacr1;
+	u32 saimr;
+	int master;
+};
+static struct pxa_i2s_port pxa_i2s;
+
+#define PXA_I2S_DAIFMT \
+	(SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF)
+
+#define PXA_I2S_DIR \
+	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
+
+#define PXA_I2S_RATES \
+	(SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
+	SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
+	SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
+
+/* priv is divider */
+static struct snd_soc_dai_mode pxa2xx_i2s_modes[] = {
+	/* pxa2xx I2S frame and clock master modes */
+	{PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS, SND_SOC_DAITDM_LRDW(0,0),
+		SNDRV_PCM_FMTBIT_S16_LE, SNDRV_PCM_RATE_8000, PXA_I2S_DIR,
+		SND_SOC_DAI_BFS_DIV, 256, SND_SOC_FSBD(4), 0x48},
+	{PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS, SND_SOC_DAITDM_LRDW(0,0),
+		SNDRV_PCM_FMTBIT_S16_LE, SNDRV_PCM_RATE_11025, PXA_I2S_DIR,
+		SND_SOC_DAI_BFS_DIV, 256, SND_SOC_FSBD(4), 0x34},
+	{PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS, SND_SOC_DAITDM_LRDW(0,0),
+		SNDRV_PCM_FMTBIT_S16_LE, SNDRV_PCM_RATE_16000, PXA_I2S_DIR,
+		SND_SOC_DAI_BFS_DIV, 256, SND_SOC_FSBD(4), 0x24},
+	{PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS, SND_SOC_DAITDM_LRDW(0,0),
+		SNDRV_PCM_FMTBIT_S16_LE, SNDRV_PCM_RATE_22050, PXA_I2S_DIR,
+		SND_SOC_DAI_BFS_DIV, 256, SND_SOC_FSBD(4), 0x1a},
+	{PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS, SND_SOC_DAITDM_LRDW(0,0),
+		SNDRV_PCM_FMTBIT_S16_LE, SNDRV_PCM_RATE_44100, PXA_I2S_DIR,
+		SND_SOC_DAI_BFS_DIV, 256, SND_SOC_FSBD(4), 0xd},
+	{PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS, SND_SOC_DAITDM_LRDW(0,0),
+		SNDRV_PCM_FMTBIT_S16_LE, SNDRV_PCM_RATE_48000, PXA_I2S_DIR,
+		SND_SOC_DAI_BFS_DIV, 256, SND_SOC_FSBD(4), 0xc},
+
+	/* pxa2xx I2S frame master and clock slave mode */
+	{PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBM_CFS, SND_SOC_DAITDM_LRDW(0,0),
+		SNDRV_PCM_FMTBIT_S16_LE, PXA_I2S_RATES, PXA_I2S_DIR, 0,
+		SND_SOC_FS_ALL, SND_SOC_FSB(64), 0x48},
+
+};
+
+static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_out = {
+	.name			= "I2S PCM Stereo out",
+	.dev_addr		= __PREG(SADR),
+	.drcmr			= &DRCMRTXSADR,
+	.dcmd			= DCMD_INCSRCADDR | DCMD_FLOWTRG |
+				  DCMD_BURST32 | DCMD_WIDTH4,
+};
+
+static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_in = {
+	.name			= "I2S PCM Stereo in",
+	.dev_addr		= __PREG(SADR),
+	.drcmr			= &DRCMRRXSADR,
+	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
+				  DCMD_BURST32 | DCMD_WIDTH4,
+};
+
+static struct pxa2xx_gpio gpio_bus[] = {
+	{ /* I2S SoC Slave */
+		.rx = GPIO29_SDATA_IN_I2S_MD,
+		.tx = GPIO30_SDATA_OUT_I2S_MD,
+		.clk = GPIO28_BITCLK_IN_I2S_MD,
+		.frm = GPIO31_SYNC_I2S_MD,
+	},
+	{ /* I2S SoC Master */
+#ifdef CONFIG_PXA27x
+		.sys = GPIO113_I2S_SYSCLK_MD,
+#else
+		.sys = GPIO32_SYSCLK_I2S_MD,
+#endif
+		.rx = GPIO29_SDATA_IN_I2S_MD,
+		.tx = GPIO30_SDATA_OUT_I2S_MD,
+		.clk = GPIO28_BITCLK_OUT_I2S_MD,
+		.frm = GPIO31_SYNC_I2S_MD,
+	},
+};
+
+static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+
+	if (!rtd->cpu_dai->active) {
+		SACR0 |= SACR0_RST;
+		SACR0 = 0;
+	}
+
+	return 0;
+}
+
+/* wait for I2S controller to be ready */
+static int pxa_i2s_wait(void)
+{
+	int i;
+
+	/* flush the Rx FIFO */
+	for(i = 0; i < 16; i++)
+		SADR;
+	return 0;
+}
+
+static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+
+	pxa_i2s.master = 0;
+	if (rtd->cpu_dai->dai_runtime.fmt & SND_SOC_DAIFMT_CBS_CFS)
+		pxa_i2s.master = 1;
+
+	if (pxa_i2s.master && !extclk) {
+		pxa_gpio_mode(gpio_bus[pxa_i2s.master].sys);
+	}
+
+	pxa_gpio_mode(gpio_bus[pxa_i2s.master].rx);
+	pxa_gpio_mode(gpio_bus[pxa_i2s.master].tx);
+	pxa_gpio_mode(gpio_bus[pxa_i2s.master].frm);
+	pxa_gpio_mode(gpio_bus[pxa_i2s.master].clk);
+	pxa_set_cken(CKEN8_I2S, 1);
+	pxa_i2s_wait();
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		rtd->cpu_dai->dma_data = &pxa2xx_i2s_pcm_stereo_out;
+	else
+		rtd->cpu_dai->dma_data = &pxa2xx_i2s_pcm_stereo_in;
+
+	/* is port used by another stream */
+	if (!(SACR0 & SACR0_ENB)) {
+
+		SACR0 = 0;
+		SACR1 = 0;
+		if (pxa_i2s.master)
+			SACR0 |= SACR0_BCKD;
+
+		SACR0 |= SACR0_RFTH(14) | SACR0_TFTH(1);
+
+		if (rtd->cpu_dai->dai_runtime.fmt & SND_SOC_DAIFMT_LEFT_J)
+			SACR1 |= SACR1_AMSL;
+	}
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		SAIMR |= SAIMR_TFS;
+	else
+		SAIMR |= SAIMR_RFS;
+
+	SADIV = rtd->cpu_dai->dai_runtime.priv;
+	return 0;
+}
+
+static int pxa2xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	int ret = 0;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		SACR0 |= SACR0_ENB;
+		break;
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream)
+{
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		SACR1 |= SACR1_DRPL;
+		SAIMR &= ~SAIMR_TFS;
+	} else {
+		SACR1 |= SACR1_DREC;
+		SAIMR &= ~SAIMR_RFS;
+	}
+
+	if (SACR1 & (SACR1_DREC | SACR1_DRPL)) {
+		SACR0 &= ~SACR0_ENB;
+		pxa_i2s_wait();
+		pxa_set_cken(CKEN8_I2S, 0);
+	}
+}
+
+#ifdef CONFIG_PM
+static int pxa2xx_i2s_suspend(struct platform_device *dev,
+	struct snd_soc_cpu_dai *dai)
+{
+	if (!dai->active)
+		return 0;
+
+	/* store registers */
+	pxa_i2s.sacr0 = SACR0;
+	pxa_i2s.sacr1 = SACR1;
+	pxa_i2s.saimr = SAIMR;
+	pxa_i2s.sadiv = SADIV;
+
+	/* deactivate link */
+	SACR0 &= ~SACR0_ENB;
+	pxa_i2s_wait();
+	return 0;
+}
+
+static int pxa2xx_i2s_resume(struct platform_device *pdev,
+	struct snd_soc_cpu_dai *dai)
+{
+	if (!dai->active)
+		return 0;
+
+	pxa_i2s_wait();
+
+	SACR0 = pxa_i2s.sacr0 &= ~SACR0_ENB;
+	SACR1 = pxa_i2s.sacr1;
+	SAIMR = pxa_i2s.saimr;
+	SADIV = pxa_i2s.sadiv;
+	SACR0 |= SACR0_ENB;
+
+	return 0;
+}
+
+#else
+#define pxa2xx_i2s_suspend	NULL
+#define pxa2xx_i2s_resume	NULL
+#endif
+
+/* pxa2xx I2S sysclock is always 256 FS */
+static unsigned int pxa_i2s_config_sysclk(struct snd_soc_cpu_dai *iface,
+	struct snd_soc_clock_info *info, unsigned int clk)
+{
+	return info->rate << 8;
+}
+
+struct snd_soc_cpu_dai pxa_i2s_dai = {
+	.name = "pxa2xx-i2s",
+	.id = 0,
+	.type = SND_SOC_DAI_I2S,
+	.suspend = pxa2xx_i2s_suspend,
+	.resume = pxa2xx_i2s_resume,
+	.config_sysclk = pxa_i2s_config_sysclk,
+	.playback = {
+		.channels_min = 2,
+		.channels_max = 2,},
+	.capture = {
+		.channels_min = 2,
+		.channels_max = 2,},
+	.ops = {
+		.startup = pxa2xx_i2s_startup,
+		.shutdown = pxa2xx_i2s_shutdown,
+		.trigger = pxa2xx_i2s_trigger,
+		.hw_params = pxa2xx_i2s_hw_params,},
+	.caps = {
+		.num_modes = ARRAY_SIZE(pxa2xx_i2s_modes),
+		.mode = pxa2xx_i2s_modes,},
+};
+
+EXPORT_SYMBOL_GPL(pxa_i2s_dai);
+
+/* Module information */
+MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
+MODULE_DESCRIPTION("pxa2xx I2S SoC Interface");
+MODULE_LICENSE("GPL");

[-- Attachment #3: Type: text/plain, Size: 348 bytes --]

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

[-- Attachment #4: Type: text/plain, Size: 161 bytes --]

_______________________________________________
Alsa-devel mailing list
Alsa-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 2/8] ASoC pxa2xx I2S support
  2006-10-10 16:11 [PATCH 2/8] ASoC pxa2xx I2S support Liam Girdwood
@ 2006-10-10 17:06 ` Takashi Iwai
  2006-10-12 10:14   ` Liam Girdwood
  0 siblings, 1 reply; 6+ messages in thread
From: Takashi Iwai @ 2006-10-10 17:06 UTC (permalink / raw)
  To: Liam Girdwood; +Cc: alsa-devel

At Tue, 10 Oct 2006 17:11:54 +0100,
Liam Girdwood wrote:
> 
> +/* used to disable sysclk if external crystal is used */
> +static int extclk = 0;

You can omit "= 0" for zero-initialization of a static variable.

> +static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
> +				struct snd_pcm_hw_params *params)
> +{
> +	struct snd_soc_pcm_runtime *rtd = substream->private_data;
> +
> +	pxa_i2s.master = 0;
> +	if (rtd->cpu_dai->dai_runtime.fmt & SND_SOC_DAIFMT_CBS_CFS)
> +		pxa_i2s.master = 1;
> +
> +	if (pxa_i2s.master && !extclk) {
> +		pxa_gpio_mode(gpio_bus[pxa_i2s.master].sys);
> +	}

Remove braces.


Takashi

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 2/8] ASoC pxa2xx I2S support
  2006-10-10 17:06 ` Takashi Iwai
@ 2006-10-12 10:14   ` Liam Girdwood
  2006-10-12 10:56     ` Takashi Iwai
  0 siblings, 1 reply; 6+ messages in thread
From: Liam Girdwood @ 2006-10-12 10:14 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel

[-- Attachment #1: Type: text/plain, Size: 795 bytes --]

On Tue, 2006-10-10 at 19:06 +0200, Takashi Iwai wrote:
> At Tue, 10 Oct 2006 17:11:54 +0100,
> Liam Girdwood wrote:
> > 
> > +/* used to disable sysclk if external crystal is used */
> > +static int extclk = 0;
> 
> You can omit "= 0" for zero-initialization of a static variable.

Removed, although I do like it for clarity. 

> 
> > +static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
> > +				struct snd_pcm_hw_params *params)
> > +{
> > +	struct snd_soc_pcm_runtime *rtd = substream->private_data;
> > +
> > +	pxa_i2s.master = 0;
> > +	if (rtd->cpu_dai->dai_runtime.fmt & SND_SOC_DAIFMT_CBS_CFS)
> > +		pxa_i2s.master = 1;
> > +
> > +	if (pxa_i2s.master && !extclk) {
> > +		pxa_gpio_mode(gpio_bus[pxa_i2s.master].sys);
> > +	}
> 
> Remove braces.
> 
Fixed.

Thanks

Liam


[-- Attachment #2: asoc-pxa2xx-i2s.patch --]
[-- Type: text/x-patch, Size: 8385 bytes --]

Index: alsa-kernel/soc/pxa/pxa2xx-i2s.c
===================================================================
--- /dev/null
+++ alsa-kernel/soc/pxa/pxa2xx-i2s.c
@@ -0,0 +1,306 @@
+/*
+ * pxa2xx-i2s.c  --  ALSA Soc Audio Layer
+ *
+ * Copyright 2005 Wolfson Microelectronics PLC.
+ * Author: Liam Girdwood
+ *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  Revision history
+ *    12th Aug 2005   Initial version.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/audio.h>
+
+#include "pxa2xx-pcm.h"
+
+/* used to disable sysclk if external crystal is used */
+static int extclk;
+module_param(extclk, int, 0);
+MODULE_PARM_DESC(extclk, "set to 1 to disable pxa2xx i2s sysclk");
+
+struct pxa_i2s_port {
+	u32 sadiv;
+	u32 sacr0;
+	u32 sacr1;
+	u32 saimr;
+	int master;
+};
+static struct pxa_i2s_port pxa_i2s;
+
+#define PXA_I2S_DAIFMT \
+	(SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF)
+
+#define PXA_I2S_DIR \
+	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
+
+#define PXA_I2S_RATES \
+	(SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
+	SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
+	SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
+
+/* priv is divider */
+static struct snd_soc_dai_mode pxa2xx_i2s_modes[] = {
+	/* pxa2xx I2S frame and clock master modes */
+	{PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS, SND_SOC_DAITDM_LRDW(0,0),
+		SNDRV_PCM_FMTBIT_S16_LE, SNDRV_PCM_RATE_8000, PXA_I2S_DIR,
+		SND_SOC_DAI_BFS_DIV, 256, SND_SOC_FSBD(4), 0x48},
+	{PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS, SND_SOC_DAITDM_LRDW(0,0),
+		SNDRV_PCM_FMTBIT_S16_LE, SNDRV_PCM_RATE_11025, PXA_I2S_DIR,
+		SND_SOC_DAI_BFS_DIV, 256, SND_SOC_FSBD(4), 0x34},
+	{PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS, SND_SOC_DAITDM_LRDW(0,0),
+		SNDRV_PCM_FMTBIT_S16_LE, SNDRV_PCM_RATE_16000, PXA_I2S_DIR,
+		SND_SOC_DAI_BFS_DIV, 256, SND_SOC_FSBD(4), 0x24},
+	{PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS, SND_SOC_DAITDM_LRDW(0,0),
+		SNDRV_PCM_FMTBIT_S16_LE, SNDRV_PCM_RATE_22050, PXA_I2S_DIR,
+		SND_SOC_DAI_BFS_DIV, 256, SND_SOC_FSBD(4), 0x1a},
+	{PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS, SND_SOC_DAITDM_LRDW(0,0),
+		SNDRV_PCM_FMTBIT_S16_LE, SNDRV_PCM_RATE_44100, PXA_I2S_DIR,
+		SND_SOC_DAI_BFS_DIV, 256, SND_SOC_FSBD(4), 0xd},
+	{PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS, SND_SOC_DAITDM_LRDW(0,0),
+		SNDRV_PCM_FMTBIT_S16_LE, SNDRV_PCM_RATE_48000, PXA_I2S_DIR,
+		SND_SOC_DAI_BFS_DIV, 256, SND_SOC_FSBD(4), 0xc},
+
+	/* pxa2xx I2S frame master and clock slave mode */
+	{PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBM_CFS, SND_SOC_DAITDM_LRDW(0,0),
+		SNDRV_PCM_FMTBIT_S16_LE, PXA_I2S_RATES, PXA_I2S_DIR, 0,
+		SND_SOC_FS_ALL, SND_SOC_FSB(64), 0x48},
+
+};
+
+static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_out = {
+	.name			= "I2S PCM Stereo out",
+	.dev_addr		= __PREG(SADR),
+	.drcmr			= &DRCMRTXSADR,
+	.dcmd			= DCMD_INCSRCADDR | DCMD_FLOWTRG |
+				  DCMD_BURST32 | DCMD_WIDTH4,
+};
+
+static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_in = {
+	.name			= "I2S PCM Stereo in",
+	.dev_addr		= __PREG(SADR),
+	.drcmr			= &DRCMRRXSADR,
+	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
+				  DCMD_BURST32 | DCMD_WIDTH4,
+};
+
+static struct pxa2xx_gpio gpio_bus[] = {
+	{ /* I2S SoC Slave */
+		.rx = GPIO29_SDATA_IN_I2S_MD,
+		.tx = GPIO30_SDATA_OUT_I2S_MD,
+		.clk = GPIO28_BITCLK_IN_I2S_MD,
+		.frm = GPIO31_SYNC_I2S_MD,
+	},
+	{ /* I2S SoC Master */
+#ifdef CONFIG_PXA27x
+		.sys = GPIO113_I2S_SYSCLK_MD,
+#else
+		.sys = GPIO32_SYSCLK_I2S_MD,
+#endif
+		.rx = GPIO29_SDATA_IN_I2S_MD,
+		.tx = GPIO30_SDATA_OUT_I2S_MD,
+		.clk = GPIO28_BITCLK_OUT_I2S_MD,
+		.frm = GPIO31_SYNC_I2S_MD,
+	},
+};
+
+static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+
+	if (!rtd->cpu_dai->active) {
+		SACR0 |= SACR0_RST;
+		SACR0 = 0;
+	}
+
+	return 0;
+}
+
+/* wait for I2S controller to be ready */
+static int pxa_i2s_wait(void)
+{
+	int i;
+
+	/* flush the Rx FIFO */
+	for(i = 0; i < 16; i++)
+		SADR;
+	return 0;
+}
+
+static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+
+	pxa_i2s.master = 0;
+	if (rtd->cpu_dai->dai_runtime.fmt & SND_SOC_DAIFMT_CBS_CFS)
+		pxa_i2s.master = 1;
+
+	if (pxa_i2s.master && !extclk)
+		pxa_gpio_mode(gpio_bus[pxa_i2s.master].sys);
+
+	pxa_gpio_mode(gpio_bus[pxa_i2s.master].rx);
+	pxa_gpio_mode(gpio_bus[pxa_i2s.master].tx);
+	pxa_gpio_mode(gpio_bus[pxa_i2s.master].frm);
+	pxa_gpio_mode(gpio_bus[pxa_i2s.master].clk);
+	pxa_set_cken(CKEN8_I2S, 1);
+	pxa_i2s_wait();
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		rtd->cpu_dai->dma_data = &pxa2xx_i2s_pcm_stereo_out;
+	else
+		rtd->cpu_dai->dma_data = &pxa2xx_i2s_pcm_stereo_in;
+
+	/* is port used by another stream */
+	if (!(SACR0 & SACR0_ENB)) {
+
+		SACR0 = 0;
+		SACR1 = 0;
+		if (pxa_i2s.master)
+			SACR0 |= SACR0_BCKD;
+
+		SACR0 |= SACR0_RFTH(14) | SACR0_TFTH(1);
+
+		if (rtd->cpu_dai->dai_runtime.fmt & SND_SOC_DAIFMT_LEFT_J)
+			SACR1 |= SACR1_AMSL;
+	}
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		SAIMR |= SAIMR_TFS;
+	else
+		SAIMR |= SAIMR_RFS;
+
+	SADIV = rtd->cpu_dai->dai_runtime.priv;
+	return 0;
+}
+
+static int pxa2xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	int ret = 0;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		SACR0 |= SACR0_ENB;
+		break;
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream)
+{
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		SACR1 |= SACR1_DRPL;
+		SAIMR &= ~SAIMR_TFS;
+	} else {
+		SACR1 |= SACR1_DREC;
+		SAIMR &= ~SAIMR_RFS;
+	}
+
+	if (SACR1 & (SACR1_DREC | SACR1_DRPL)) {
+		SACR0 &= ~SACR0_ENB;
+		pxa_i2s_wait();
+		pxa_set_cken(CKEN8_I2S, 0);
+	}
+}
+
+#ifdef CONFIG_PM
+static int pxa2xx_i2s_suspend(struct platform_device *dev,
+	struct snd_soc_cpu_dai *dai)
+{
+	if (!dai->active)
+		return 0;
+
+	/* store registers */
+	pxa_i2s.sacr0 = SACR0;
+	pxa_i2s.sacr1 = SACR1;
+	pxa_i2s.saimr = SAIMR;
+	pxa_i2s.sadiv = SADIV;
+
+	/* deactivate link */
+	SACR0 &= ~SACR0_ENB;
+	pxa_i2s_wait();
+	return 0;
+}
+
+static int pxa2xx_i2s_resume(struct platform_device *pdev,
+	struct snd_soc_cpu_dai *dai)
+{
+	if (!dai->active)
+		return 0;
+
+	pxa_i2s_wait();
+
+	SACR0 = pxa_i2s.sacr0 &= ~SACR0_ENB;
+	SACR1 = pxa_i2s.sacr1;
+	SAIMR = pxa_i2s.saimr;
+	SADIV = pxa_i2s.sadiv;
+	SACR0 |= SACR0_ENB;
+
+	return 0;
+}
+
+#else
+#define pxa2xx_i2s_suspend	NULL
+#define pxa2xx_i2s_resume	NULL
+#endif
+
+/* pxa2xx I2S sysclock is always 256 FS */
+static unsigned int pxa_i2s_config_sysclk(struct snd_soc_cpu_dai *iface,
+	struct snd_soc_clock_info *info, unsigned int clk)
+{
+	return info->rate << 8;
+}
+
+struct snd_soc_cpu_dai pxa_i2s_dai = {
+	.name = "pxa2xx-i2s",
+	.id = 0,
+	.type = SND_SOC_DAI_I2S,
+	.suspend = pxa2xx_i2s_suspend,
+	.resume = pxa2xx_i2s_resume,
+	.config_sysclk = pxa_i2s_config_sysclk,
+	.playback = {
+		.channels_min = 2,
+		.channels_max = 2,},
+	.capture = {
+		.channels_min = 2,
+		.channels_max = 2,},
+	.ops = {
+		.startup = pxa2xx_i2s_startup,
+		.shutdown = pxa2xx_i2s_shutdown,
+		.trigger = pxa2xx_i2s_trigger,
+		.hw_params = pxa2xx_i2s_hw_params,},
+	.caps = {
+		.num_modes = ARRAY_SIZE(pxa2xx_i2s_modes),
+		.mode = pxa2xx_i2s_modes,},
+};
+
+EXPORT_SYMBOL_GPL(pxa_i2s_dai);
+
+/* Module information */
+MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
+MODULE_DESCRIPTION("pxa2xx I2S SoC Interface");
+MODULE_LICENSE("GPL");

[-- Attachment #3: Type: text/plain, Size: 373 bytes --]

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642

[-- Attachment #4: Type: text/plain, Size: 161 bytes --]

_______________________________________________
Alsa-devel mailing list
Alsa-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 2/8] ASoC pxa2xx I2S support
  2006-10-12 10:14   ` Liam Girdwood
@ 2006-10-12 10:56     ` Takashi Iwai
  2006-10-12 15:47       ` Nicolas Pitre
  0 siblings, 1 reply; 6+ messages in thread
From: Takashi Iwai @ 2006-10-12 10:56 UTC (permalink / raw)
  To: Liam Girdwood; +Cc: alsa-devel

At Thu, 12 Oct 2006 11:14:02 +0100,
Liam Girdwood wrote:
> 
> On Tue, 2006-10-10 at 19:06 +0200, Takashi Iwai wrote:
> > At Tue, 10 Oct 2006 17:11:54 +0100,
> > Liam Girdwood wrote:
> > > 
> > > +/* used to disable sysclk if external crystal is used */
> > > +static int extclk = 0;
> > 
> > You can omit "= 0" for zero-initialization of a static variable.
> 
> Removed, although I do like it for clarity. 

IIRC, the code size is reduced by omitting '= 0'.  That is why kernel
code prefers the style without '= 0'. 
Maybe it doesn't matter any more with the recetn gcc, though.


Takashi

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 2/8] ASoC pxa2xx I2S support
  2006-10-12 10:56     ` Takashi Iwai
@ 2006-10-12 15:47       ` Nicolas Pitre
  2006-10-12 17:18         ` Daniel Jacobowitz
  0 siblings, 1 reply; 6+ messages in thread
From: Nicolas Pitre @ 2006-10-12 15:47 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: Liam Girdwood, alsa-devel

On Thu, 12 Oct 2006, Takashi Iwai wrote:

> At Thu, 12 Oct 2006 11:14:02 +0100,
> Liam Girdwood wrote:
> > 
> > On Tue, 2006-10-10 at 19:06 +0200, Takashi Iwai wrote:
> > > At Tue, 10 Oct 2006 17:11:54 +0100,
> > > Liam Girdwood wrote:
> > > > 
> > > > +/* used to disable sysclk if external crystal is used */
> > > > +static int extclk = 0;
> > > 
> > > You can omit "= 0" for zero-initialization of a static variable.
> > 
> > Removed, although I do like it for clarity. 
> 
> IIRC, the code size is reduced by omitting '= 0'.  That is why kernel
> code prefers the style without '= 0'. 
> Maybe it doesn't matter any more with the recetn gcc, though.

The reason is that global variables with explicit initial values are 
allocated to the .data section which is always present in the kernel 
binary.  When no explicit initial value is provided then the variable is 
allocated to the .bss section which is _not_ included in the kernel 
binary but initialized to zero at runtime.


Nicolas

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 2/8] ASoC pxa2xx I2S support
  2006-10-12 15:47       ` Nicolas Pitre
@ 2006-10-12 17:18         ` Daniel Jacobowitz
  0 siblings, 0 replies; 6+ messages in thread
From: Daniel Jacobowitz @ 2006-10-12 17:18 UTC (permalink / raw)
  To: alsa-devel

On Thu, Oct 12, 2006 at 11:47:16AM -0400, Nicolas Pitre wrote:
> > IIRC, the code size is reduced by omitting '= 0'.  That is why kernel
> > code prefers the style without '= 0'. 
> > Maybe it doesn't matter any more with the recetn gcc, though.
> 
> The reason is that global variables with explicit initial values are 
> allocated to the .data section which is always present in the kernel 
> binary.  When no explicit initial value is provided then the variable is 
> allocated to the .bss section which is _not_ included in the kernel 
> binary but initialized to zero at runtime.

GCC has included explicitly zero initialized variables in the .bss
section for a while now; this is controlled by
-fno-zero-initialized-in-bss.

-- 
Daniel Jacobowitz
CodeSourcery

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2006-10-12 17:18 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-10-10 16:11 [PATCH 2/8] ASoC pxa2xx I2S support Liam Girdwood
2006-10-10 17:06 ` Takashi Iwai
2006-10-12 10:14   ` Liam Girdwood
2006-10-12 10:56     ` Takashi Iwai
2006-10-12 15:47       ` Nicolas Pitre
2006-10-12 17:18         ` Daniel Jacobowitz

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.