dect
/
linux-2.6
Archived
13
0
Fork 0

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:
Kuninori Morimoto 2009-10-30 12:02:39 +09:00 committed by Mark Brown
parent 67e646cd7b
commit 9ddc9aa910
2 changed files with 20 additions and 122 deletions

View File

@ -23,7 +23,6 @@ config SND_SOC_SH4_SSI
config SND_SOC_SH4_FSI
tristate "SH4 FSI support"
depends on CPU_SUBTYPE_SH7724
select SH_DMA
help
This option enables FSI sound support

View File

@ -26,8 +26,6 @@
#include <sound/pcm_params.h>
#include <sound/sh_fsi.h>
#include <asm/atomic.h>
#include <asm/dma.h>
#include <asm/dma-sh.h>
#define DO_FMT 0x0000
#define DOFF_CTL 0x0004
@ -97,7 +95,6 @@ struct fsi_priv {
int fifo_max;
int chan;
int dma_chan;
int byte_offset;
int period_len;
@ -308,62 +305,6 @@ static int fsi_get_fifo_residue(struct fsi_priv *fsi, int is_play)
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);
}
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 */
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 fifo_free;
int width;
u8 *start;
int i;
if (!fsi ||
!fsi->substream ||
@ -515,12 +420,22 @@ static int fsi_data_push(struct fsi_priv *fsi)
if (fifo_free < send)
send = fifo_free;
if (2 == width)
fsi_16data_push(fsi, runtime, send);
else if (4 == width)
fsi_32data_push(fsi, runtime, send);
else
start = runtime->dma_area;
start += fsi->byte_offset;
switch (width) {
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;
}
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);
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
@ -780,10 +693,9 @@ static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct fsi_priv *fsi = fsi_get(substream);
int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
long location;
location = (fsi->byte_offset - 1) - fsi_get_residue(fsi, is_play);
location = (fsi->byte_offset - 1);
if (location < 0)
location = 0;
@ -912,22 +824,13 @@ static int fsi_probe(struct platform_device *pdev)
master->fsia.base = master->base;
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 */
snprintf(clk_name, sizeof(clk_name), "spu%d", pdev->id);
master->clk = clk_get(NULL, clk_name);
if (IS_ERR(master->clk)) {
dev_err(&pdev->dev, "cannot get %s mstp\n", clk_name);
ret = -EIO;
goto exit_free_dma;
goto exit_iounmap;
}
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);
if (ret) {
dev_err(&pdev->dev, "irq request err\n");
goto exit_free_dma;
goto exit_iounmap;
}
ret = snd_soc_register_platform(&fsi_soc_platform);
@ -951,8 +854,6 @@ static int fsi_probe(struct platform_device *pdev)
exit_free_irq:
free_irq(irq, master);
exit_free_dma:
fsi_free_dma_chan();
exit_iounmap:
iounmap(master->base);
exit_kfree:
@ -969,8 +870,6 @@ static int fsi_remove(struct platform_device *pdev)
clk_put(master->clk);
fsi_free_dma_chan();
free_irq(master->irq, master);
iounmap(master->base);