From: Daniel Ribeiro <drwyrm@gmail.com>
To: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: alsa-devel@alsa-project.org, Eric Miao <eric.y.miao@gmail.com>,
linux-arm-kernel <linux-arm-kernel@lists.arm.linux.org.uk>,
pHilipp Zabel <philipp.zabel@gmail.com>
Subject: [RFC] Auto setup TDM when needed. Add frame_width and rx/tx masks to set_tdm_slots.
Date: Mon, 08 Jun 2009 18:07:24 -0300 [thread overview]
Message-ID: <1244495244.17327.184.camel@brutus> (raw)
In-Reply-To: <20090608165328.GB14026@rakim.wolfsonmicro.main>
[-- Attachment #1.1: Type: text/plain, Size: 7664 bytes --]
Em Seg, 2009-06-08 às 17:53 +0100, Mark Brown escreveu:
> I'd like to see all these details handled within the driver - knowing if
> and when network mode are to be set up is the sort of thing that users
> ought to be able to rely on the driver for.
Untested, RFC only version of patch.
(plus some minor copynpaste and whitespace fixes)
Am I on the right direction? :)
include/sound/soc-dai.h | 3 +
sound/soc/pxa/pxa-ssp.c | 86 +++++++++++++++++++++++++++++-------------------
sound/soc/soc-core.c | 13 ++++---
3 files changed, 62 insertions(+), 40 deletions(-)
--
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index 1367647..0bf9502 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -154,7 +154,8 @@ struct snd_soc_dai_ops {
*/
int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt);
int (*set_tdm_slot)(struct snd_soc_dai *dai,
- unsigned int mask, int slots);
+ unsigned int tx_mask, unsigned int rx_mask,
+ int slots, int frame_width);
int (*set_tristate)(struct snd_soc_dai *dai, int tristate);
/*
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index 92838af..a0b7bad 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -490,21 +490,31 @@ static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai,
* Set the active slots in TDM/Network mode
*/
static int pxa_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,
- unsigned int mask, int slots)
+ unsigned int tx_mask, unsigned int rx_mask, int slots, int frame_width)
{
struct ssp_priv *priv = cpu_dai->private_data;
struct ssp_device *ssp = priv->dev.ssp;
u32 sscr0;
- sscr0 = ssp_read_reg(ssp, SSCR0) & ~SSCR0_SlotsPerFrm(7);
+ sscr0 = ssp_read_reg(ssp, SSCR0);
+ sscr0 &= ~(SSCR0_SlotsPerFrm(7) | SSCR0_EDSS | SSCR0_DSS);
+
+ /* enable network mode */
+ sscr0 |= SSCR0_MOD;
+
+ /* set frame width */
+ if (frame_width > 16)
+ sscr0 |= SSCR0_EDSS | SSCR0_DataSize(frame_width - 16);
+ else
+ sscr0 |= SSCR0_DataSize(frame_width);
/* set number of active slots */
sscr0 |= SSCR0_SlotsPerFrm(slots);
ssp_write_reg(ssp, SSCR0, sscr0);
/* set active slot mask */
- ssp_write_reg(ssp, SSTSA, mask);
- ssp_write_reg(ssp, SSRSA, mask);
+ ssp_write_reg(ssp, SSTSA, tx_mask);
+ ssp_write_reg(ssp, SSRSA, rx_mask);
return 0;
}
@@ -555,7 +565,7 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
/* reset port settings */
sscr0 = ssp_read_reg(ssp, SSCR0) &
- (SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ACS);
+ (SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ACS);
sscr1 = SSCR1_RxTresh(8) | SSCR1_TxTresh(7);
sspsp = 0;
@@ -602,7 +612,7 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
case SND_SOC_DAIFMT_DSP_A:
sspsp |= SSPSP_FSRT;
case SND_SOC_DAIFMT_DSP_B:
- sscr0 |= SSCR0_MOD | SSCR0_PSP;
+ sscr0 |= SSCR0_PSP;
sscr1 |= SSCR1_TRAIL | SSCR1_RWOT;
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
@@ -652,10 +662,10 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
struct ssp_priv *priv = cpu_dai->private_data;
struct ssp_device *ssp = priv->dev.ssp;
int dma = 0, chn = params_channels(params);
- u32 sscr0;
+ u32 sscr0, sscr1;
u32 sspsp;
int width = snd_pcm_format_physical_width(params_format(params));
- int ttsa = ssp_read_reg(ssp, SSTSA) & 0xf;
+ int frame_width = width * chn;
/* select correct DMA params */
if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
@@ -664,7 +674,7 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
* to force 16-bit frame width on the wire (for S16_LE), even
* with two channels. Use 16-bit DMA transfers for this case.
*/
- if (((chn == 2) && (ttsa != 1)) || (width == 32))
+ if (frame_width >= 32)
dma += 2; /* 32-bit DMA offset is 2, 16-bit is 0 */
cpu_dai->dma_data = ssp_dma_params[cpu_dai->id][dma];
@@ -675,32 +685,48 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
if (ssp_read_reg(ssp, SSCR0) & SSCR0_SSE)
return 0;
- /* clear selected SSP bits */
- sscr0 = ssp_read_reg(ssp, SSCR0) & ~(SSCR0_DSS | SSCR0_EDSS);
- ssp_write_reg(ssp, SSCR0, sscr0);
+ /* frame width */
+ sscr0 = ssp_read_reg(ssp, SSCR0) & ~(SSCR0_EDSS | SSCR0_DSS);
- /* bit size */
- sscr0 = ssp_read_reg(ssp, SSCR0);
- switch (params_format(params)) {
- case SNDRV_PCM_FORMAT_S16_LE:
+ /* FIXME: Is this needed? */
#ifdef CONFIG_PXA3xx
- if (cpu_is_pxa3xx())
- sscr0 |= SSCR0_FPCKE;
+ if (width == 16 && cpu_is_pxa3xx())
+ sscr0 |= SSCR0_FPCKE;
#endif
+
+ if (!(sscr0 & SSCR0_MOD)) {
+
+ /* Not on network mode, setup the frame width */
sscr0 |= SSCR0_DataSize(16);
- break;
- case SNDRV_PCM_FORMAT_S24_LE:
- sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(8));
- break;
- case SNDRV_PCM_FORMAT_S32_LE:
- sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(16));
- break;
+ if (frame_width >= 32)
+ sscr0 |= SSCR0_EDSS;
+
+ if (frame_width > 32) {
+ /*
+ * Network mode is needed to support this frame_width
+ * We assume that the wire is not networked and setup
+ * a "fake" network mode here.
+ */
+ int slots = frame_width / 32;
+
+ sscr0 |= SSCR0_MOD;
+ sscr0 |= SSCR0_SlotsPerFrm(slots);
+ ssp_write_reg(ssp, SSTSA, slots - 1);
+ ssp_write_reg(ssp, SSRSA, slots - 1);
+ }
+ }
+
+ /* If SSCR0_MOD is set we can't use SSCR1_RWOT */
+ if (sscr0 & SSCR0_MOD) {
+ sscr1 = ssp_read_reg(ssp, SSCR1);
+ ssp_write_reg(ssp, SSCR1, sscr1 & ~SSCR1_RWOT);
}
+
ssp_write_reg(ssp, SSCR0, sscr0);
switch (priv->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
- sspsp = ssp_read_reg(ssp, SSPSP);
+ sspsp = ssp_read_reg(ssp, SSPSP);
if ((ssp_get_scr(ssp) == 4) && (width == 16)) {
/* This is a special case where the bitclk is 64fs
@@ -742,14 +768,6 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
break;
}
- /* When we use a network mode, we always require TDM slots
- * - complain loudly and fail if they've not been set up yet.
- */
- if ((sscr0 & SSCR0_MOD) && !ttsa) {
- dev_err(&ssp->pdev->dev, "No TDM timeslot configured\n");
- return -EINVAL;
- }
-
dump_registers(ssp);
return 0;
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index c9f19d0..ce13b6d 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -2130,17 +2130,20 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt);
/**
* snd_soc_dai_set_tdm_slot - configure DAI TDM.
* @dai: DAI
- * @mask: DAI specific mask representing used slots.
+ * @tx_mask: DAI specific mask representing TX slots.
+ * @rx_mask: DAI specific mask representing RX slots.
* @slots: Number of slots in use.
+ * @frame_width: Width in bits for each slot.
*
* Configures a DAI for TDM operation. Both mask and slots are codec and DAI
* specific.
*/
int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
- unsigned int mask, int slots)
+ unsigned int tx_mask, unsigned int rx_mask, int slots, int frame_width)
{
- if (dai->ops->set_sysclk)
- return dai->ops->set_tdm_slot(dai, mask, slots);
+ if (dai->ops->set_tdm_slot)
+ return dai->ops->set_tdm_slot(dai, tx_mask, rx_mask,
+ slots, frame_width);
else
return -EINVAL;
}
@@ -2155,7 +2158,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot);
*/
int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate)
{
- if (dai->ops->set_sysclk)
+ if (dai->ops->set_tristate)
return dai->ops->set_tristate(dai, tristate);
else
return -EINVAL;
--
Daniel Ribeiro
[-- Attachment #1.2: Esta é uma parte de mensagem assinada digitalmente --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
next prev parent reply other threads:[~2009-06-08 21:08 UTC|newest]
Thread overview: 53+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-06-03 12:33 [PATCH 1/4] ASoC: pxa-ssp: enhance I2S and add Left_J support Eric Miao
2009-06-03 13:18 ` Daniel Mack
2009-06-03 14:22 ` Eric Miao
2009-06-03 14:23 ` Mark Brown
2009-06-03 14:24 ` Daniel Mack
[not found] ` <37b631400906040207o169abbc2ob33100879ac68911@mail.gmail.com>
2009-06-04 9:44 ` Paul Shen
2009-06-05 17:26 ` Daniel Mack
2009-06-05 22:47 ` Mark Brown
2009-06-04 12:36 ` Mark Brown
2009-06-04 13:12 ` Daniel Mack
2009-06-06 8:26 ` Daniel Ribeiro
2009-06-09 9:39 ` Paul Shen
2009-06-09 9:54 ` Daniel Mack
2009-06-09 10:10 ` Daniel Ribeiro
2009-06-06 20:12 ` Mark Brown
2009-06-08 12:12 ` pHilipp Zabel
2009-06-08 12:40 ` Mark Brown
2009-06-08 15:58 ` pHilipp Zabel
2009-06-08 16:25 ` Daniel Ribeiro
2009-06-08 16:38 ` Mark Brown
2009-06-08 17:18 ` pHilipp Zabel
2009-06-08 17:41 ` Mark Brown
2009-06-08 18:59 ` pHilipp Zabel
2009-06-08 16:03 ` Daniel Ribeiro
2009-06-08 16:53 ` Mark Brown
2009-06-08 17:26 ` Daniel Ribeiro
2009-06-08 18:06 ` Mark Brown
2009-06-08 20:52 ` Daniel Ribeiro
2009-06-09 9:39 ` Eric Miao
2009-06-09 9:41 ` Eric Miao
2009-06-09 9:58 ` Mark Brown
2009-06-09 11:40 ` pHilipp Zabel
2009-06-10 22:24 ` Daniel Ribeiro
2009-06-11 9:00 ` Mark Brown
2009-06-11 15:13 ` Daniel Mack
2009-06-11 13:34 ` Eric Miao
2009-06-11 14:36 ` [RFC] I2S and LEFT_J (was: ASoC: pxa-ssp: enhance I2S and add Left_J support) Daniel Ribeiro
2009-06-15 8:45 ` Eric Miao
2009-06-15 14:57 ` Daniel Ribeiro
2009-06-15 15:04 ` Mark Brown
2009-06-15 17:20 ` Daniel Ribeiro
2009-06-15 17:40 ` Daniel Mack
2009-06-16 2:11 ` Daniel Ribeiro
2009-06-15 18:00 ` Mark Brown
2009-06-18 7:58 ` [RFC] I2S and LEFT_J Eric Miao
2009-06-18 12:30 ` Daniel Ribeiro
2009-06-22 22:14 ` Daniel Mack
2009-06-27 0:28 ` Daniel Ribeiro
2009-07-01 12:17 ` Daniel Mack
2009-06-08 21:07 ` Daniel Ribeiro [this message]
2009-06-09 9:10 ` [RFC] Auto setup TDM when needed. Add frame_width and rx/tx masks to set_tdm_slots Mark Brown
2009-06-08 14:13 ` [PATCH 1/4] ASoC: pxa-ssp: enhance I2S and add Left_J support Eric Miao
2009-06-08 15:06 ` Mark Brown
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1244495244.17327.184.camel@brutus \
--to=drwyrm@gmail.com \
--cc=alsa-devel@alsa-project.org \
--cc=broonie@opensource.wolfsonmicro.com \
--cc=eric.y.miao@gmail.com \
--cc=linux-arm-kernel@lists.arm.linux.org.uk \
--cc=philipp.zabel@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.