Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9ddc9aa9 authored by Kuninori Morimoto's avatar Kuninori Morimoto Committed by Mark Brown
Browse files

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: default avatarKuninori Morimoto <morimoto.kuninori@renesas.com>
Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
parent 67e646cd
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -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

+20 −121
Original line number Diff line number Diff line
@@ -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);