build/patch/kernel/sun7i-default/1017-SPDIF-experiments.patch

214 lines
7.9 KiB
Diff

From 1c0859a723e350d2ea9b82f0343da6195722b566 Mon Sep 17 00:00:00 2001
From: Nikolay <nikkov@gmail.com>
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