From 1c0859a723e350d2ea9b82f0343da6195722b566 Mon Sep 17 00:00:00 2001 From: Nikolay Date: Mon, 4 Apr 2016 19:38:48 +0600 Subject: [PATCH 17/19] SPDIF experiments --- sound/soc/sunxi/spdif/sunxi_spdif.c | 92 +++++++++++++++---------------------- sound/soc/sunxi/spdif/sunxi_spdma.c | 11 ++--- 2 files changed, 41 insertions(+), 62 deletions(-) diff --git a/sound/soc/sunxi/spdif/sunxi_spdif.c b/sound/soc/sunxi/spdif/sunxi_spdif.c index 5400e3f..9608b14 100644 --- a/sound/soc/sunxi/spdif/sunxi_spdif.c +++ b/sound/soc/sunxi/spdif/sunxi_spdif.c @@ -62,51 +62,39 @@ static struct clk *spdif_apbclk, *spdif_pll2clk, *spdif_pllx8, *spdif_moduleclk; void sunxi_snd_txctrl(struct snd_pcm_substream *substream, int on) { u32 reg_val; + if (on) { + reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_FCTL); + reg_val |= SUNXI_SPDIF_FCTL_FTX; //flush TX FIFO + reg_val |= SUNXI_SPDIF_FCTL_TXTL(0x10); //TX FIFO empty Trigger Level + writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_FCTL); - reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCFG); - if (substream->runtime->channels == 1) { - reg_val |= SUNXI_SPDIF_TXCFG_SINGLEMOD; - } - else { - reg_val &= ~SUNXI_SPDIF_TXCFG_SINGLEMOD; - } - reg_val |= SUNXI_SPDIF_TXCFG_ASS; //Sending the last audio (may be 0?) - reg_val |= SUNXI_SPDIF_TXCFG_CHSTMODE; //Channel status A&B generated form TX_CHSTA - writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCFG); - - /*flush TX FIFO and set FIFO empty trigger level*/ - reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_FCTL); - reg_val |= SUNXI_SPDIF_FCTL_TXTL(0x10); //TX FIFO empty Trigger Level - reg_val |= SUNXI_SPDIF_FCTL_FTX; //flush TX FIFO - writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_FCTL); - - /*clear interrupt status*/ - reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_ISTA); - reg_val |= SUNXI_SPDIF_ISTA_TXCLR; - writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_ISTA); + reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_ISTA); + reg_val |= SUNXI_SPDIF_ISTA_TXCLR; //clear interrupt status + writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_ISTA); - /*clear TX counter*/ - writel(0, sunxi_spdif.regs + SUNXI_SPDIF_TXCNT); + writel(0, sunxi_spdif.regs + SUNXI_SPDIF_TXCNT); //clear TX counter - if (on) { - //SPDIF TX ENABLE reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCFG); - reg_val |= SUNXI_SPDIF_TXCFG_TXEN; + if (substream->runtime->channels == 1) + reg_val |= SUNXI_SPDIF_TXCFG_SINGLEMOD; + else + reg_val &= ~SUNXI_SPDIF_TXCFG_SINGLEMOD; + reg_val |= SUNXI_SPDIF_TXCFG_ASS; //Sending the last audio (may be 0?) + reg_val |= SUNXI_SPDIF_TXCFG_CHSTMODE; //Channel status A&B generated form TX_CHSTA + reg_val |= SUNXI_SPDIF_TXCFG_TXEN; //SPDIF TX ENABLE writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCFG); - //DRQ ENABLE reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_INT); - reg_val |= SUNXI_SPDIF_INT_TXDRQEN; + reg_val |= SUNXI_SPDIF_INT_TXDRQEN; //DRQ ENABLE writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_INT); + } else { - //SPDIF TX DISABLE reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCFG); - reg_val &= ~SUNXI_SPDIF_TXCFG_TXEN; + reg_val &= ~SUNXI_SPDIF_TXCFG_TXEN; //SPDIF TX DISABLE writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCFG); - //DRQ DISABLE reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_INT); - reg_val &= ~SUNXI_SPDIF_INT_TXDRQEN; + reg_val &= ~SUNXI_SPDIF_INT_TXDRQEN; //DRQ DISABLE writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_INT); } } @@ -114,40 +102,33 @@ void sunxi_snd_txctrl(struct snd_pcm_substream *substream, int on) void sunxi_snd_rxctrl(struct snd_pcm_substream *substream, int on) { u32 reg_val; - - /*flush RX FIFO and set FIFO empty trigger level*/ - reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_FCTL); - reg_val |= SUNXI_SPDIF_FCTL_RXTL(0x0F); //RX FIFO Trigger Level - reg_val |= SUNXI_SPDIF_FCTL_FRX; //flush RX FIFO - writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_FCTL); - - /*clear interrupt status*/ - reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_ISTA); - reg_val |= SUNXI_SPDIF_ISTA_RXCLR; - writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_ISTA); - /*clear RX counter*/ - writel(0, sunxi_spdif.regs + SUNXI_SPDIF_RXCNT); - if (on) { - /*SPDIF RX ENABLE*/ + reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_FCTL); + reg_val |= SUNXI_SPDIF_FCTL_RXTL(0x0F); //RX FIFO Trigger Level + reg_val |= SUNXI_SPDIF_FCTL_FRX; //flush RX FIFO + writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_FCTL); + + reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_ISTA); + reg_val |= SUNXI_SPDIF_ISTA_RXCLR; //clear interrupt status + writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_ISTA); + + writel(0, sunxi_spdif.regs + SUNXI_SPDIF_RXCNT); //clear RX counter + reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_RXCFG); - reg_val |= SUNXI_SPDIF_RXCFG_RXEN; + reg_val |= SUNXI_SPDIF_RXCFG_RXEN; //SPDIF RX ENABLE writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_RXCFG); - /*DRQ ENABLE*/ reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_INT); - reg_val |= SUNXI_SPDIF_INT_RXDRQEN; + reg_val |= SUNXI_SPDIF_INT_RXDRQEN; //DRQ ENABLE writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_INT); } else { - /*SPDIF TX DISABLE*/ reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_RXCFG); - reg_val &= ~SUNXI_SPDIF_RXCFG_RXEN; + reg_val &= ~SUNXI_SPDIF_RXCFG_RXEN; //SPDIF RX DISABLE writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_RXCFG); - /*DRQ DISABLE*/ reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_INT); - reg_val &= ~SUNXI_SPDIF_INT_RXDRQEN; + reg_val &= ~SUNXI_SPDIF_INT_RXDRQEN; //DRQ DISABLE writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_INT); } } @@ -286,8 +267,7 @@ static int sunxi_spdif_trigger(struct snd_pcm_substream *substream, { int ret = 0; struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct sunxi_dma_params *dma_data = - snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); + struct sunxi_dma_params *dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); switch (cmd) { case SNDRV_PCM_TRIGGER_START: diff --git a/sound/soc/sunxi/spdif/sunxi_spdma.c b/sound/soc/sunxi/spdif/sunxi_spdma.c index d5377fc..b2af6a9 100644 --- a/sound/soc/sunxi/spdif/sunxi_spdma.c +++ b/sound/soc/sunxi/spdif/sunxi_spdma.c @@ -45,7 +45,7 @@ static const struct snd_pcm_hardware sunxi_pcm_out_hardware = { .channels_min = 1, .channels_max = 2, .buffer_bytes_max = 128*1024, /* value must be (2^n)Kbyte size */ - .period_bytes_min = 1024,//1024*4, + .period_bytes_min = 1024*4, .period_bytes_max = 1024*32,//1024*128, .periods_min = 4, .periods_max = 8, @@ -63,7 +63,7 @@ static const struct snd_pcm_hardware sunxi_pcm_in_hardware = { .channels_min = 1, .channels_max = 2, .buffer_bytes_max = 128*1024, /* value must be (2^n)Kbyte size */ - .period_bytes_min = 1024,//1024*4, + .period_bytes_min = 1024*4, .period_bytes_max = 1024*32,//1024*128, .periods_min = 4, .periods_max = 8, @@ -88,12 +88,11 @@ static void sunxi_pcm_enqueue(struct snd_pcm_substream *substream) { struct sunxi_runtime_data *prtd = substream->runtime->private_data; dma_addr_t pos = prtd->dma_pos; - unsigned int limit; int ret; + unsigned int limit = prtd->dma_limit; unsigned long len = prtd->dma_period; int read = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? 0 : 1; - limit = prtd->dma_limit; while(prtd->dma_loaded < limit){ if((pos + len) > prtd->dma_end){ len = prtd->dma_end - pos; @@ -296,15 +295,20 @@ static int sunxi_pcm_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - sunxi_dma_start(prtd->params); prtd->state |= ST_RUNNING; + /* enqueue dma buffers */ + sunxi_pcm_enqueue(substream); + sunxi_dma_start(prtd->params); + ret =0; break; case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - sunxi_dma_stop(prtd->params); prtd->state &= ~ST_RUNNING; + sunxi_dma_stop(prtd->params); + prtd->dma_loaded = 0; + ret = 0; break; default: -- 1.9.1