summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSumit Bhattacharya <sumitb@nvidia.com>2011-09-22 14:39:49 +0530
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:49:01 -0800
commitedd202e25c578a91a2167e8535230ef16ce8e984 (patch)
tree36df013680c41ea7aefb43d8fef9fe17511adf9c
parent38cf56edd48272404b84a6da88f4babc5db81f94 (diff)
ASoC: Tegra SPDIF: Set ch status and fifo attn bits
Add code to enable channel status transmit and set channel status bits according to pcm stream sample rate. Set transmit attention level to 4-slot and remove redundant spdif clock refcounting code. Bug 872652 Change-Id: I1bb1928e263c033993fa1f4db7609b373976da62 Signed-off-by: Sumit Bhattacharya <sumitb@nvidia.com> Reviewed-on: http://git-master/r/53976 Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com> Rebase-Id: Reaf4877ab3f05cd6c6e37908fc284bb93315f17f
-rw-r--r--sound/soc/tegra/tegra20_spdif.c49
-rw-r--r--sound/soc/tegra/tegra20_spdif.h77
2 files changed, 117 insertions, 9 deletions
diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c
index 7189d3e820b2..c14e467017a7 100644
--- a/sound/soc/tegra/tegra20_spdif.c
+++ b/sound/soc/tegra/tegra20_spdif.c
@@ -128,6 +128,7 @@ static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream,
struct device *dev = substream->pcm->card->dev;
struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai);
int ret, srate, spdifclock;
+ u32 ch_sta[2] = {0, 0};
spdif->reg_ctrl &= ~TEGRA20_SPDIF_CTRL_PACK;
spdif->reg_ctrl &= ~TEGRA20_SPDIF_CTRL_BIT_MODE_MASK;
@@ -141,27 +142,45 @@ static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream,
}
srate = params_rate(params);
+ ch_sta[0] = tegra20_spdif_read(spdif, TEGRA20_SPDIF_CH_STA_TX_A);
+ ch_sta[0] &= ~TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_MASK;
+ ch_sta[1] = tegra20_spdif_read(spdif, TEGRA20_SPDIF_CH_STA_TX_B);
+ ch_sta[1] &= ~TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_MASK;
switch (params_rate(params)) {
case 32000:
spdifclock = 4096000;
+ ch_sta[0] |= TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_32000;
+ ch_sta[1] |= TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_32000;
break;
case 44100:
spdifclock = 5644800;
+ ch_sta[0] |= TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_44100;
+ ch_sta[1] |= TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_44100;
break;
case 48000:
spdifclock = 6144000;
+ ch_sta[0] |= TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_48000;
+ ch_sta[1] |= TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_48000;
break;
case 88200:
spdifclock = 11289600;
+ ch_sta[0] |= TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_88200;
+ ch_sta[1] |= TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_88200;
break;
case 96000:
spdifclock = 12288000;
+ ch_sta[0] |= TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_96000;
+ ch_sta[1] |= TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_96000;
break;
case 176400:
spdifclock = 22579200;
+ ch_sta[0] |= TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_176400;
+ ch_sta[1] |= TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_176400;
break;
case 192000:
spdifclock = 24576000;
+ ch_sta[0] |= TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_192000;
+ ch_sta[1] |= TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_192000;
break;
default:
return -EINVAL;
@@ -173,18 +192,26 @@ static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream,
return ret;
}
+ clk_enable(spdif->clk_spdif_out);
+
+ tegra20_spdif_write(spdif, TEGRA20_SPDIF_CH_STA_TX_A, ch_sta[0]);
+ tegra20_spdif_write(spdif, TEGRA20_SPDIF_CH_STA_TX_B, ch_sta[1]);
+
+ clk_disable(spdif->clk_spdif_out);
+
return 0;
}
static void tegra20_spdif_start_playback(struct tegra20_spdif *spdif)
{
- spdif->reg_ctrl |= TEGRA20_SPDIF_CTRL_TX_EN;
+ spdif->reg_ctrl |= TEGRA20_SPDIF_CTRL_TC_EN | TEGRA20_SPDIF_CTRL_TX_EN;
tegra20_spdif_write(spdif, TEGRA20_SPDIF_CTRL, spdif->reg_ctrl);
}
static void tegra20_spdif_stop_playback(struct tegra20_spdif *spdif)
{
- spdif->reg_ctrl &= ~TEGRA20_SPDIF_CTRL_TX_EN;
+ spdif->reg_ctrl &= ~(TEGRA20_SPDIF_CTRL_TX_EN |
+ TEGRA20_SPDIF_CTRL_TC_EN);
tegra20_spdif_write(spdif, TEGRA20_SPDIF_CTRL, spdif->reg_ctrl);
}
@@ -197,18 +224,14 @@ static int tegra20_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
case SNDRV_PCM_TRIGGER_RESUME:
- if (!spdif->clk_refs)
- clk_enable(spdif->clk_spdif_out);
- spdif->clk_refs++;
+ clk_enable(spdif->clk_spdif_out);
tegra20_spdif_start_playback(spdif);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_SUSPEND:
tegra20_spdif_stop_playback(spdif);
- spdif->clk_refs--;
- if (!spdif->clk_refs)
- clk_disable(spdif->clk_spdif_out);
+ clk_disable(spdif->clk_spdif_out);
break;
default:
return -EINVAL;
@@ -250,6 +273,7 @@ static __devinit int tegra20_spdif_platform_probe(struct platform_device *pdev)
struct tegra20_spdif *spdif;
struct resource *mem, *memregion, *dmareq;
int ret;
+ u32 reg_val;
spdif = kzalloc(sizeof(struct tegra20_spdif), GFP_KERNEL);
if (!spdif) {
@@ -300,6 +324,15 @@ static __devinit int tegra20_spdif_platform_probe(struct platform_device *pdev)
spdif->playback_dma_data.width = 32;
spdif->playback_dma_data.req_sel = dmareq->start;
+ clk_enable(spdif->clk_spdif_out);
+
+ reg_val = tegra20_spdif_read(spdif, TEGRA20_SPDIF_DATA_FIFO_CSR);
+ reg_val &= ~TEGRA20_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_MASK;
+ reg_val |= TEGRA20_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_TU4_WORD_FULL;
+ tegra20_spdif_write(spdif, TEGRA20_SPDIF_DATA_FIFO_CSR, reg_val);
+
+ clk_disable(spdif->clk_spdif_out);
+
ret = snd_soc_register_dai(&pdev->dev, &tegra20_spdif_dai);
if (ret) {
dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
diff --git a/sound/soc/tegra/tegra20_spdif.h b/sound/soc/tegra/tegra20_spdif.h
index 7281c0e1ba6a..1938aa67917f 100644
--- a/sound/soc/tegra/tegra20_spdif.h
+++ b/sound/soc/tegra/tegra20_spdif.h
@@ -434,7 +434,83 @@
*/
/* Fields in TEGRA20_SPDIF_CH_STA_TX_A */
+#define TEGRA20_SPDIF_CH_STA_TX_A_SF_22050 0x4
+#define TEGRA20_SPDIF_CH_STA_TX_A_SF_24000 0x6
+#define TEGRA20_SPDIF_CH_STA_TX_A_SF_32000 0x3
+#define TEGRA20_SPDIF_CH_STA_TX_A_SF_44100 0x0
+#define TEGRA20_SPDIF_CH_STA_TX_A_SF_48000 0x2
+#define TEGRA20_SPDIF_CH_STA_TX_A_SF_88200 0x8
+#define TEGRA20_SPDIF_CH_STA_TX_A_SF_96000 0xA
+#define TEGRA20_SPDIF_CH_STA_TX_A_SF_176400 0xC
+#define TEGRA20_SPDIF_CH_STA_TX_A_SF_192000 0xE
+
+#define TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT 24
+#define TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_MASK \
+ (0xF << TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT)
+#define TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_22050 \
+ (TEGRA20_SPDIF_CH_STA_TX_A_SF_22050 << TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT)
+#define TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_24000 \
+ (TEGRA20_SPDIF_CH_STA_TX_A_SF_24000 << TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT)
+#define TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_32000 \
+ (TEGRA20_SPDIF_CH_STA_TX_A_SF_32000 << TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT)
+#define TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_44100 \
+ (TEGRA20_SPDIF_CH_STA_TX_A_SF_44100 << TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT)
+#define TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_48000 \
+ (TEGRA20_SPDIF_CH_STA_TX_A_SF_48000 << TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT)
+#define TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_88200 \
+ (TEGRA20_SPDIF_CH_STA_TX_A_SF_88200 << TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT)
+#define TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_96000 \
+ (TEGRA20_SPDIF_CH_STA_TX_A_SF_96000 << TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT)
+#define TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_176400 \
+ (TEGRA20_SPDIF_CH_STA_TX_A_SF_176400 << TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT)
+#define TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_192000 \
+ (TEGRA20_SPDIF_CH_STA_TX_A_SF_192000 << TEGRA20_SPDIF_CH_STA_TX_A_SAMP_FREQ_SHIFT)
+
/* Fields in TEGRA20_SPDIF_CH_STA_TX_B */
+#define TEGRA20_SPDIF_CH_STA_TX_B_SF_8000 0x6
+#define TEGRA20_SPDIF_CH_STA_TX_B_SF_11025 0xA
+#define TEGRA20_SPDIF_CH_STA_TX_B_SF_12000 0x2
+#define TEGRA20_SPDIF_CH_STA_TX_B_SF_16000 0x8
+#define TEGRA20_SPDIF_CH_STA_TX_B_SF_22050 0xB
+#define TEGRA20_SPDIF_CH_STA_TX_B_SF_24000 0x9
+#define TEGRA20_SPDIF_CH_STA_TX_B_SF_32000 0xC
+#define TEGRA20_SPDIF_CH_STA_TX_B_SF_44100 0xF
+#define TEGRA20_SPDIF_CH_STA_TX_B_SF_48000 0xD
+#define TEGRA20_SPDIF_CH_STA_TX_B_SF_88200 0x7
+#define TEGRA20_SPDIF_CH_STA_TX_B_SF_96000 0x5
+#define TEGRA20_SPDIF_CH_STA_TX_B_SF_176400 0x3
+#define TEGRA20_SPDIF_CH_STA_TX_B_SF_192000 0x1
+
+#define TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT 4
+#define TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_MASK \
+ (0xF << TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
+#define TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_8000 \
+ (TEGRA20_SPDIF_CH_STA_TX_B_SF_8000 << TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
+#define TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_11025 \
+ (TEGRA20_SPDIF_CH_STA_TX_B_SF_11025 << TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
+#define TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_12000 \
+ (TEGRA20_SPDIF_CH_STA_TX_B_SF_12000 << TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
+#define TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_16000 \
+ (TEGRA20_SPDIF_CH_STA_TX_B_SF_16000 << TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
+#define TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_22050 \
+ (TEGRA20_SPDIF_CH_STA_TX_B_SF_22025 << TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
+#define TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_24000 \
+ (TEGRA20_SPDIF_CH_STA_TX_B_SF_24000 << TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
+#define TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_32000 \
+ (TEGRA20_SPDIF_CH_STA_TX_B_SF_32000 << TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
+#define TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_44100 \
+ (TEGRA20_SPDIF_CH_STA_TX_B_SF_44100 << TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
+#define TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_48000 \
+ (TEGRA20_SPDIF_CH_STA_TX_B_SF_48000 << TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
+#define TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_88200 \
+ (TEGRA20_SPDIF_CH_STA_TX_B_SF_88200 << TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
+#define TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_96000 \
+ (TEGRA20_SPDIF_CH_STA_TX_B_SF_96000 << TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
+#define TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_176400 \
+ (TEGRA20_SPDIF_CH_STA_TX_B_SF_176400 << TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
+#define TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_192000 \
+ (TEGRA20_SPDIF_CH_STA_TX_B_SF_192000 << TEGRA20_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_SHIFT)
+
/* Fields in TEGRA20_SPDIF_CH_STA_TX_C */
/* Fields in TEGRA20_SPDIF_CH_STA_TX_D */
/* Fields in TEGRA20_SPDIF_CH_STA_TX_E */
@@ -462,7 +538,6 @@
struct tegra20_spdif {
struct clk *clk_spdif_out;
- int clk_refs;
struct tegra_pcm_dma_params capture_dma_data;
struct tegra_pcm_dma_params playback_dma_data;
void __iomem *regs;