mirror of
https://github.com/torvalds/linux.git
synced 2024-11-04 11:04:38 +00:00
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:
parent
67e646cd7b
commit
9ddc9aa910
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user