mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 20:32:04 +09:00
i2s0针对音频随机性出噪声修改:
1) i2s0的rx, tx两者都为master,通过修改i2s0的clk来保证lrck_tx与lrck_rx同步
2) 硬件上针对只有一路LRCK的codec,例如alc5631/5621,可以单独将I2S0_LRCK连接到codec的LRCK, 也可以将I2S0_LRCK与I2S0_LRCK_RX一起连接到codec的LRCK
This commit is contained in:
@@ -31,6 +31,7 @@
|
||||
#include <mach/rk29_iomap.h>
|
||||
#include <mach/rk29-dma-pl330.h>
|
||||
#include <mach/iomux.h>
|
||||
#include <mach/cru.h>
|
||||
|
||||
#include "rk29_pcm.h"
|
||||
#include "rk29_i2s.h"
|
||||
@@ -117,8 +118,31 @@ static struct rockchip_pcm_dma_params rockchip_i2s_pcm_stereo_in[MAX_I2S] = {
|
||||
};
|
||||
*/
|
||||
|
||||
#if 1
|
||||
static u32 i2s0_clk_enter()
|
||||
{
|
||||
u32 clk = cru_readl(CRU_CLKSEL3_CON);
|
||||
cru_writel(0x1ffff, CRU_CLKSEL3_CON);
|
||||
mdelay(1);
|
||||
return clk;
|
||||
}
|
||||
|
||||
static void i2s0_clk_exit(u32 clk)
|
||||
{
|
||||
mdelay(1);
|
||||
cru_writel(clk, CRU_CLKSEL3_CON);
|
||||
mdelay(1);
|
||||
}
|
||||
#else
|
||||
static u32 i2s0_clk_enter()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void i2s0_clk_exit(u32 clk)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
*Turn on or off the transmission path.
|
||||
@@ -126,9 +150,10 @@ static struct rockchip_pcm_dma_params rockchip_i2s_pcm_stereo_in[MAX_I2S] = {
|
||||
|
||||
static int flag_i2s_tx = 0;
|
||||
static int flag_i2s_rx = 0;
|
||||
static void rockchip_snd_txctrl(struct rk29_i2s_info *i2s, int on)
|
||||
static void rockchip_snd_txctrl(struct rk29_i2s_info *i2s, int on, bool stopI2S)
|
||||
{
|
||||
u32 opr,xfer;
|
||||
u32 clk;
|
||||
|
||||
opr = readl(&(pheadi2s->I2S_DMACR));
|
||||
xfer = readl(&(pheadi2s->I2S_XFER));
|
||||
@@ -138,12 +163,17 @@ static void rockchip_snd_txctrl(struct rk29_i2s_info *i2s, int on)
|
||||
I2S_DBG("rockchip_snd_txctrl: on\n");
|
||||
|
||||
//start tx
|
||||
if ((flag_i2s_tx == 0) && (flag_i2s_rx == 0))
|
||||
//if ((flag_i2s_tx == 0) && (flag_i2s_rx == 0))
|
||||
if ((xfer&I2S_TX_TRAN_START)==0 || (xfer&I2S_RX_TRAN_START)==0)
|
||||
{
|
||||
clk = i2s0_clk_enter();
|
||||
|
||||
//if start tx & rx clk, need reset i2s
|
||||
xfer |= I2S_TX_TRAN_START;
|
||||
xfer |= I2S_RX_TRAN_START;
|
||||
writel(xfer, &(pheadi2s->I2S_XFER));
|
||||
|
||||
i2s0_clk_exit(clk);
|
||||
}
|
||||
|
||||
if ((opr & I2S_TRAN_DMA_ENABLE) == 0)
|
||||
@@ -163,23 +193,30 @@ static void rockchip_snd_txctrl(struct rk29_i2s_info *i2s, int on)
|
||||
{
|
||||
opr &= ~I2S_TRAN_DMA_ENABLE;
|
||||
writel(opr, &(pheadi2s->I2S_DMACR));
|
||||
|
||||
xfer &= ~I2S_RX_TRAN_START;
|
||||
xfer &= ~I2S_TX_TRAN_START;
|
||||
writel(xfer, &(pheadi2s->I2S_XFER));
|
||||
if(stopI2S)
|
||||
{
|
||||
clk = i2s0_clk_enter();
|
||||
|
||||
xfer &= ~I2S_RX_TRAN_START;
|
||||
xfer &= ~I2S_TX_TRAN_START;
|
||||
writel(xfer, &(pheadi2s->I2S_XFER));
|
||||
|
||||
i2s0_clk_exit(clk);
|
||||
}
|
||||
|
||||
//after stop rx & tx clk, reset i2s
|
||||
writel(0x001,&(pheadi2s->I2S_TXRST));
|
||||
writel(0x001,&(pheadi2s->I2S_RXRST));
|
||||
//writel(0x001,&(pheadi2s->I2S_TXRST));
|
||||
//writel(0x001,&(pheadi2s->I2S_RXRST));
|
||||
}
|
||||
|
||||
I2S_DBG("rockchip_snd_txctrl: off\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void rockchip_snd_rxctrl(struct rk29_i2s_info *i2s, int on)
|
||||
static void rockchip_snd_rxctrl(struct rk29_i2s_info *i2s, int on, bool stopI2S)
|
||||
{
|
||||
u32 opr,xfer;
|
||||
u32 clk;
|
||||
|
||||
opr = readl(&(pheadi2s->I2S_DMACR));
|
||||
xfer = readl(&(pheadi2s->I2S_XFER));
|
||||
@@ -189,40 +226,52 @@ static void rockchip_snd_rxctrl(struct rk29_i2s_info *i2s, int on)
|
||||
I2S_DBG("rockchip_snd_rxctrl: on\n");
|
||||
|
||||
//start rx
|
||||
if ((flag_i2s_tx == 0) && (flag_i2s_rx == 0))
|
||||
//if ((flag_i2s_tx == 0) && (flag_i2s_rx == 0))
|
||||
if ((xfer&I2S_TX_TRAN_START)==0 || (xfer&I2S_RX_TRAN_START)==0)
|
||||
{
|
||||
xfer |= I2S_TX_TRAN_START;
|
||||
xfer |= I2S_RX_TRAN_START;
|
||||
writel(xfer, &(pheadi2s->I2S_XFER));
|
||||
}
|
||||
clk = i2s0_clk_enter();
|
||||
|
||||
xfer |= I2S_TX_TRAN_START;
|
||||
xfer |= I2S_RX_TRAN_START;
|
||||
writel(xfer, &(pheadi2s->I2S_XFER));
|
||||
|
||||
i2s0_clk_exit(clk);
|
||||
}
|
||||
|
||||
if ((opr & I2S_RECE_DMA_ENABLE) == 0)
|
||||
{
|
||||
if ((opr & I2S_RECE_DMA_ENABLE) == 0)
|
||||
{
|
||||
opr |= I2S_RECE_DMA_ENABLE;
|
||||
writel(opr, &(pheadi2s->I2S_DMACR));
|
||||
}
|
||||
|
||||
flag_i2s_rx = 1;
|
||||
flag_i2s_rx = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
//stop rx
|
||||
flag_i2s_rx = 0;
|
||||
if ((flag_i2s_rx == 0) && (flag_i2s_tx == 0))
|
||||
{
|
||||
flag_i2s_rx = 0;
|
||||
if ((flag_i2s_rx == 0) && (flag_i2s_tx == 0))
|
||||
{
|
||||
opr &= ~I2S_RECE_DMA_ENABLE;
|
||||
writel(opr, &(pheadi2s->I2S_DMACR));
|
||||
|
||||
xfer &= ~I2S_RX_TRAN_START;
|
||||
xfer &= ~I2S_TX_TRAN_START;
|
||||
writel(xfer, &(pheadi2s->I2S_XFER));
|
||||
|
||||
if(stopI2S)
|
||||
{
|
||||
clk = i2s0_clk_enter();
|
||||
|
||||
xfer &= ~I2S_RX_TRAN_START;
|
||||
xfer &= ~I2S_TX_TRAN_START;
|
||||
writel(xfer, &(pheadi2s->I2S_XFER));
|
||||
|
||||
i2s0_clk_exit(clk);
|
||||
}
|
||||
|
||||
//after stop rx & tx clk, reset i2s
|
||||
writel(0x001,&(pheadi2s->I2S_TXRST));
|
||||
writel(0x001,&(pheadi2s->I2S_RXRST));
|
||||
}
|
||||
//writel(0x001,&(pheadi2s->I2S_TXRST));
|
||||
//writel(0x001,&(pheadi2s->I2S_RXRST));
|
||||
}
|
||||
|
||||
I2S_DBG("rockchip_snd_rxctrl: off\n");
|
||||
I2S_DBG("rockchip_snd_rxctrl: off\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -364,25 +413,27 @@ static int rockchip_i2s_trigger(struct snd_pcm_substream *substream, int cmd, st
|
||||
int ret = 0;
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct rk29_i2s_info *i2s = to_info(rtd->dai->cpu_dai);
|
||||
bool stopI2S = false;
|
||||
|
||||
I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
|
||||
|
||||
switch (cmd) {
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
case SNDRV_PCM_TRIGGER_RESUME:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
|
||||
rockchip_snd_rxctrl(i2s, 1);
|
||||
rockchip_snd_rxctrl(i2s, 1, stopI2S);
|
||||
else
|
||||
rockchip_snd_txctrl(i2s, 1);
|
||||
rockchip_snd_txctrl(i2s, 1, stopI2S);
|
||||
break;
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
stopI2S = true;
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
|
||||
rockchip_snd_rxctrl(i2s, 0);
|
||||
rockchip_snd_rxctrl(i2s, 0, stopI2S);
|
||||
else
|
||||
rockchip_snd_txctrl(i2s, 0);
|
||||
rockchip_snd_txctrl(i2s, 0, stopI2S);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
@@ -581,8 +632,8 @@ static int rk29_i2s_probe(struct platform_device *pdev,
|
||||
|
||||
/* Mark ourselves as in TXRX mode so we can run through our cleanup
|
||||
* process without warnings. */
|
||||
rockchip_snd_txctrl(i2s, 0);
|
||||
rockchip_snd_rxctrl(i2s, 0);
|
||||
rockchip_snd_txctrl(i2s, 0, true);
|
||||
rockchip_snd_rxctrl(i2s, 0, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user