diff options
author | Sumit Bhattacharya <sumitb@nvidia.com> | 2011-09-22 14:39:49 +0530 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:49:01 -0800 |
commit | edd202e25c578a91a2167e8535230ef16ce8e984 (patch) | |
tree | 36df013680c41ea7aefb43d8fef9fe17511adf9c | |
parent | 38cf56edd48272404b84a6da88f4babc5db81f94 (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.c | 49 | ||||
-rw-r--r-- | sound/soc/tegra/tegra20_spdif.h | 77 |
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; |