ASoC: spdif: fix spdif work abnormally when xrun occurs.
authorSugar Zhang <sugar.zhang@rock-chips.com>
Wed, 19 Aug 2015 10:33:16 +0000 (18:33 +0800)
committerSugar Zhang <sugar.zhang@rock-chips.com>
Wed, 19 Aug 2015 10:43:27 +0000 (18:43 +0800)
when xrun occurs, it will do snd_pcm_stop to disable spdif
and then clear logic, next snd_pcm_lib_write1 will trigger
snd_pcm_start to enable spdif, but not to excute hw_params
to configue spdif, so need to save spdif configuration to
reconfigure spdif.

Signed-off-by: Sugar Zhang <sugar.zhang@rock-chips.com>
sound/soc/rockchip/rk_spdif.c

index 9ef46cd42777027c1e8683013811b2211915b3a8..003569a9ff7433baa047800858bc48c31d12ff2c 100755 (executable)
@@ -143,6 +143,8 @@ struct rockchip_spdif_info {
        struct clk *clk;
        struct device *dev;
        struct snd_dmaengine_dai_dma_data dma_playback;
+       u32 cfgr;
+       u32 dmac;
 };
 
 static inline struct rockchip_spdif_info *to_info(struct snd_soc_dai *cpu_dai)
@@ -161,6 +163,8 @@ static void spdif_snd_txctrl(struct rockchip_spdif_info *spdif, int on)
        if (on) {
                xfer |= XFER_TRAN_START;
                dmacr |= DMACR_TRAN_DMA_ENABLE;
+               dmacr |= spdif->dmac;
+               writel(spdif->cfgr, regs + CFGR);
                writel(dmacr, regs + DMACR);
                writel(xfer, regs + XFER);
        } else {
@@ -227,7 +231,7 @@ static int spdif_hw_params(struct snd_pcm_substream *substream,
        void __iomem *regs = spdif->regs;
        unsigned long flags;
        unsigned int val;
-       int cfgr, dmac, intcr, chnregval;
+       u32 cfgr, dmac, intcr, chnregval;
        char chnsta[CHNSTA_BYTES];
 
        dev_dbg(spdif->dev, "%s\n", __func__);
@@ -277,6 +281,7 @@ static int spdif_hw_params(struct snd_pcm_substream *substream,
        cfgr &= ~CFGR_PRE_CHANGE_MASK;
        cfgr |= CFGR_PRE_CHANGE_ENALBLE;
 
+       spdif->cfgr = cfgr;
        writel(cfgr, regs + CFGR);
 
        intcr = readl(regs + INTCR) & (~INTCR_SDBEIE_MASK);
@@ -285,6 +290,7 @@ static int spdif_hw_params(struct snd_pcm_substream *substream,
 
        dmac = readl(regs + DMACR) & (~DMACR_TRAN_DATA_LEVEL_MASK);
        dmac |= DMA_DATA_LEVEL_16;
+       spdif->dmac = dmac;
        writel(dmac, regs + DMACR);
 
        /* channel status bit */