ASoC: sh: FSI: Remove DMA support
SuperH FSI device have the hardware limitation to use DMA. If DMA is used, LCD output will be broken. Maybe there are some solution. But I don't know how to do it now. This patch remove DMA support and use soft transfer. Signed-off-by: Kuninori Morimoto <morimoto.kuninori@renesas.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
This commit is contained in:
committed by
Mark Brown
parent
67e646cd7b
commit
9ddc9aa910
@@ -23,7 +23,6 @@ config SND_SOC_SH4_SSI
|
|||||||
config SND_SOC_SH4_FSI
|
config SND_SOC_SH4_FSI
|
||||||
tristate "SH4 FSI support"
|
tristate "SH4 FSI support"
|
||||||
depends on CPU_SUBTYPE_SH7724
|
depends on CPU_SUBTYPE_SH7724
|
||||||
select SH_DMA
|
|
||||||
help
|
help
|
||||||
This option enables FSI sound support
|
This option enables FSI sound support
|
||||||
|
|
||||||
|
@@ -26,8 +26,6 @@
|
|||||||
#include <sound/pcm_params.h>
|
#include <sound/pcm_params.h>
|
||||||
#include <sound/sh_fsi.h>
|
#include <sound/sh_fsi.h>
|
||||||
#include <asm/atomic.h>
|
#include <asm/atomic.h>
|
||||||
#include <asm/dma.h>
|
|
||||||
#include <asm/dma-sh.h>
|
|
||||||
|
|
||||||
#define DO_FMT 0x0000
|
#define DO_FMT 0x0000
|
||||||
#define DOFF_CTL 0x0004
|
#define DOFF_CTL 0x0004
|
||||||
@@ -97,7 +95,6 @@ struct fsi_priv {
|
|||||||
|
|
||||||
int fifo_max;
|
int fifo_max;
|
||||||
int chan;
|
int chan;
|
||||||
int dma_chan;
|
|
||||||
|
|
||||||
int byte_offset;
|
int byte_offset;
|
||||||
int period_len;
|
int period_len;
|
||||||
@@ -308,62 +305,6 @@ static int fsi_get_fifo_residue(struct fsi_priv *fsi, int is_play)
|
|||||||
return residue;
|
return residue;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fsi_get_residue(struct fsi_priv *fsi, int is_play)
|
|
||||||
{
|
|
||||||
int residue;
|
|
||||||
int width;
|
|
||||||
struct snd_pcm_runtime *runtime;
|
|
||||||
|
|
||||||
runtime = fsi->substream->runtime;
|
|
||||||
|
|
||||||
/* get 1 channel data width */
|
|
||||||
width = frames_to_bytes(runtime, 1) / fsi->chan;
|
|
||||||
|
|
||||||
if (2 == width)
|
|
||||||
residue = fsi_get_fifo_residue(fsi, is_play);
|
|
||||||
else
|
|
||||||
residue = get_dma_residue(fsi->dma_chan);
|
|
||||||
|
|
||||||
return residue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************************
|
|
||||||
|
|
||||||
|
|
||||||
basic dma function
|
|
||||||
|
|
||||||
|
|
||||||
************************************************************************/
|
|
||||||
#define PORTA_DMA 0
|
|
||||||
#define PORTB_DMA 1
|
|
||||||
|
|
||||||
static int fsi_get_dma_chan(void)
|
|
||||||
{
|
|
||||||
if (0 != request_dma(PORTA_DMA, "fsia"))
|
|
||||||
return -EIO;
|
|
||||||
|
|
||||||
if (0 != request_dma(PORTB_DMA, "fsib")) {
|
|
||||||
free_dma(PORTA_DMA);
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
master->fsia.dma_chan = PORTA_DMA;
|
|
||||||
master->fsib.dma_chan = PORTB_DMA;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fsi_free_dma_chan(void)
|
|
||||||
{
|
|
||||||
dma_wait_for_completion(PORTA_DMA);
|
|
||||||
dma_wait_for_completion(PORTB_DMA);
|
|
||||||
free_dma(PORTA_DMA);
|
|
||||||
free_dma(PORTB_DMA);
|
|
||||||
|
|
||||||
master->fsia.dma_chan = -1;
|
|
||||||
master->fsib.dma_chan = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
|
|
||||||
|
|
||||||
@@ -435,44 +376,6 @@ static void fsi_soft_all_reset(void)
|
|||||||
mdelay(10);
|
mdelay(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fsi_16data_push(struct fsi_priv *fsi,
|
|
||||||
struct snd_pcm_runtime *runtime,
|
|
||||||
int send)
|
|
||||||
{
|
|
||||||
u16 *dma_start;
|
|
||||||
u32 snd;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* get dma start position for FSI */
|
|
||||||
dma_start = (u16 *)runtime->dma_area;
|
|
||||||
dma_start += fsi->byte_offset / 2;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* soft dma
|
|
||||||
* FSI can not use DMA when 16bpp
|
|
||||||
*/
|
|
||||||
for (i = 0; i < send; i++) {
|
|
||||||
snd = (u32)dma_start[i];
|
|
||||||
fsi_reg_write(fsi, DODT, snd << 8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fsi_32data_push(struct fsi_priv *fsi,
|
|
||||||
struct snd_pcm_runtime *runtime,
|
|
||||||
int send)
|
|
||||||
{
|
|
||||||
u32 *dma_start;
|
|
||||||
|
|
||||||
/* get dma start position for FSI */
|
|
||||||
dma_start = (u32 *)runtime->dma_area;
|
|
||||||
dma_start += fsi->byte_offset / 4;
|
|
||||||
|
|
||||||
dma_wait_for_completion(fsi->dma_chan);
|
|
||||||
dma_configure_channel(fsi->dma_chan, (SM_INC|0x400|TS_32|TM_BUR));
|
|
||||||
dma_write(fsi->dma_chan, (u32)dma_start,
|
|
||||||
(u32)(fsi->base + DODT), send * 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* playback interrupt */
|
/* playback interrupt */
|
||||||
static int fsi_data_push(struct fsi_priv *fsi)
|
static int fsi_data_push(struct fsi_priv *fsi)
|
||||||
{
|
{
|
||||||
@@ -481,6 +384,8 @@ static int fsi_data_push(struct fsi_priv *fsi)
|
|||||||
int send;
|
int send;
|
||||||
int fifo_free;
|
int fifo_free;
|
||||||
int width;
|
int width;
|
||||||
|
u8 *start;
|
||||||
|
int i;
|
||||||
|
|
||||||
if (!fsi ||
|
if (!fsi ||
|
||||||
!fsi->substream ||
|
!fsi->substream ||
|
||||||
@@ -515,12 +420,22 @@ static int fsi_data_push(struct fsi_priv *fsi)
|
|||||||
if (fifo_free < send)
|
if (fifo_free < send)
|
||||||
send = fifo_free;
|
send = fifo_free;
|
||||||
|
|
||||||
if (2 == width)
|
start = runtime->dma_area;
|
||||||
fsi_16data_push(fsi, runtime, send);
|
start += fsi->byte_offset;
|
||||||
else if (4 == width)
|
|
||||||
fsi_32data_push(fsi, runtime, send);
|
switch (width) {
|
||||||
else
|
case 2:
|
||||||
|
for (i = 0; i < send; i++)
|
||||||
|
fsi_reg_write(fsi, DODT,
|
||||||
|
((u32)*((u16 *)start + i) << 8));
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
for (i = 0; i < send; i++)
|
||||||
|
fsi_reg_write(fsi, DODT, *((u32 *)start + i));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
fsi->byte_offset += send * width;
|
fsi->byte_offset += send * width;
|
||||||
|
|
||||||
@@ -664,8 +579,6 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fsi_reg_write(fsi, reg, data);
|
fsi_reg_write(fsi, reg, data);
|
||||||
dev_dbg(dai->dev, "use %s format (%d channel) use %d DMAC\n",
|
|
||||||
msg, fsi->chan, fsi->dma_chan);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* clear clk reset if master mode
|
* clear clk reset if master mode
|
||||||
@@ -780,10 +693,9 @@ static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream)
|
|||||||
{
|
{
|
||||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||||
struct fsi_priv *fsi = fsi_get(substream);
|
struct fsi_priv *fsi = fsi_get(substream);
|
||||||
int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
|
|
||||||
long location;
|
long location;
|
||||||
|
|
||||||
location = (fsi->byte_offset - 1) - fsi_get_residue(fsi, is_play);
|
location = (fsi->byte_offset - 1);
|
||||||
if (location < 0)
|
if (location < 0)
|
||||||
location = 0;
|
location = 0;
|
||||||
|
|
||||||
@@ -912,22 +824,13 @@ static int fsi_probe(struct platform_device *pdev)
|
|||||||
master->fsia.base = master->base;
|
master->fsia.base = master->base;
|
||||||
master->fsib.base = master->base + 0x40;
|
master->fsib.base = master->base + 0x40;
|
||||||
|
|
||||||
master->fsia.dma_chan = -1;
|
|
||||||
master->fsib.dma_chan = -1;
|
|
||||||
|
|
||||||
ret = fsi_get_dma_chan();
|
|
||||||
if (ret < 0) {
|
|
||||||
dev_err(&pdev->dev, "cannot get dma api\n");
|
|
||||||
goto exit_iounmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FSI is based on SPU mstp */
|
/* FSI is based on SPU mstp */
|
||||||
snprintf(clk_name, sizeof(clk_name), "spu%d", pdev->id);
|
snprintf(clk_name, sizeof(clk_name), "spu%d", pdev->id);
|
||||||
master->clk = clk_get(NULL, clk_name);
|
master->clk = clk_get(NULL, clk_name);
|
||||||
if (IS_ERR(master->clk)) {
|
if (IS_ERR(master->clk)) {
|
||||||
dev_err(&pdev->dev, "cannot get %s mstp\n", clk_name);
|
dev_err(&pdev->dev, "cannot get %s mstp\n", clk_name);
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto exit_free_dma;
|
goto exit_iounmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
fsi_soc_dai[0].dev = &pdev->dev;
|
fsi_soc_dai[0].dev = &pdev->dev;
|
||||||
@@ -938,7 +841,7 @@ static int fsi_probe(struct platform_device *pdev)
|
|||||||
ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, "fsi", master);
|
ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, "fsi", master);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&pdev->dev, "irq request err\n");
|
dev_err(&pdev->dev, "irq request err\n");
|
||||||
goto exit_free_dma;
|
goto exit_iounmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = snd_soc_register_platform(&fsi_soc_platform);
|
ret = snd_soc_register_platform(&fsi_soc_platform);
|
||||||
@@ -951,8 +854,6 @@ static int fsi_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
exit_free_irq:
|
exit_free_irq:
|
||||||
free_irq(irq, master);
|
free_irq(irq, master);
|
||||||
exit_free_dma:
|
|
||||||
fsi_free_dma_chan();
|
|
||||||
exit_iounmap:
|
exit_iounmap:
|
||||||
iounmap(master->base);
|
iounmap(master->base);
|
||||||
exit_kfree:
|
exit_kfree:
|
||||||
@@ -969,8 +870,6 @@ static int fsi_remove(struct platform_device *pdev)
|
|||||||
|
|
||||||
clk_put(master->clk);
|
clk_put(master->clk);
|
||||||
|
|
||||||
fsi_free_dma_chan();
|
|
||||||
|
|
||||||
free_irq(master->irq, master);
|
free_irq(master->irq, master);
|
||||||
|
|
||||||
iounmap(master->base);
|
iounmap(master->base);
|
||||||
|
Reference in New Issue
Block a user