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

Commit c3d4913c authored by Tomoya MORINAGA's avatar Tomoya MORINAGA Committed by Vinod Koul
Browse files

pch_dma: fix DMA issue(ch8-ch11)



ISSUE: In case PCH_DMA with I2S communications with ch8~ch11, sometimes I2S data
is not send correctly.
CAUSE: The following patch I submitted before was not enough modification for
supporting DMA ch8~ch11. The modification for status register of ch8~11 was not
enough.

pch_dma: Support I2S for ML7213 IOH
author	Tomoya MORINAGA <tomoya-linux@dsn.okisemi.com>
	Mon, 9 May 2011 07:09:38 +0000 (16:09 +0900)
committer	Vinod Koul <vinod.koul@intel.com>
	Mon, 9 May 2011 11:42:23 +0000 (16:42 +0530)
commit	194f5f27
tree	c9d4903ea02b18939a4f390956a48be1a3734517
parent	60092d0b

This patch fixes the issue.
We can confirm PCH_DMA with I2S communications with ch8~ch11 works well.

Signed-off-by: default avatarTomoya MORINAGA <tomoya-linux@dsn.okisemi.com>
Signed-off-by: default avatarVinod Koul <vinod.koul@intel.com>
parent 55922c9d
Loading
Loading
Loading
Loading
+55 −14
Original line number Diff line number Diff line
@@ -45,7 +45,8 @@
#define DMA_STATUS_MASK_BITS		0x3
#define DMA_STATUS_SHIFT_BITS		16
#define DMA_STATUS_IRQ(x)		(0x1 << (x))
#define DMA_STATUS_ERR(x)		(0x1 << ((x) + 8))
#define DMA_STATUS0_ERR(x)		(0x1 << ((x) + 8))
#define DMA_STATUS2_ERR(x)		(0x1 << (x))

#define DMA_DESC_WIDTH_SHIFT_BITS	12
#define DMA_DESC_WIDTH_1_BYTE		(0x3 << DMA_DESC_WIDTH_SHIFT_BITS)
@@ -133,6 +134,7 @@ struct pch_dma {
#define PCH_DMA_CTL3	0x0C
#define PCH_DMA_STS0	0x10
#define PCH_DMA_STS1	0x14
#define PCH_DMA_STS2	0x18

#define dma_readl(pd, name) \
	readl((pd)->membase + PCH_DMA_##name)
@@ -183,13 +185,19 @@ static void pdc_enable_irq(struct dma_chan *chan, int enable)
{
	struct pch_dma *pd = to_pd(chan->device);
	u32 val;
	int pos;

	if (chan->chan_id < 8)
		pos = chan->chan_id;
	else
		pos = chan->chan_id + 8;

	val = dma_readl(pd, CTL2);

	if (enable)
		val |= 0x1 << chan->chan_id;
		val |= 0x1 << pos;
	else
		val &= ~(0x1 << chan->chan_id);
		val &= ~(0x1 << pos);

	dma_writel(pd, CTL2, val);

@@ -262,7 +270,7 @@ static void pdc_set_mode(struct dma_chan *chan, u32 mode)
		chan->chan_id, val);
}

static u32 pdc_get_status(struct pch_dma_chan *pd_chan)
static u32 pdc_get_status0(struct pch_dma_chan *pd_chan)
{
	struct pch_dma *pd = to_pd(pd_chan->chan.device);
	u32 val;
@@ -272,9 +280,27 @@ static u32 pdc_get_status(struct pch_dma_chan *pd_chan)
			DMA_STATUS_BITS_PER_CH * pd_chan->chan.chan_id));
}

static u32 pdc_get_status2(struct pch_dma_chan *pd_chan)
{
	struct pch_dma *pd = to_pd(pd_chan->chan.device);
	u32 val;

	val = dma_readl(pd, STS2);
	return DMA_STATUS_MASK_BITS & (val >> (DMA_STATUS_SHIFT_BITS +
			DMA_STATUS_BITS_PER_CH * (pd_chan->chan.chan_id - 8)));
}

static bool pdc_is_idle(struct pch_dma_chan *pd_chan)
{
	if (pdc_get_status(pd_chan) == DMA_STATUS_IDLE)
	u32 sts;

	if (pd_chan->chan.chan_id < 8)
		sts = pdc_get_status0(pd_chan);
	else
		sts = pdc_get_status2(pd_chan);


	if (sts == DMA_STATUS_IDLE)
		return true;
	else
		return false;
@@ -693,30 +719,45 @@ static irqreturn_t pd_irq(int irq, void *devid)
	struct pch_dma *pd = (struct pch_dma *)devid;
	struct pch_dma_chan *pd_chan;
	u32 sts0;
	u32 sts2;
	int i;
	int ret = IRQ_NONE;
	int ret0 = IRQ_NONE;
	int ret2 = IRQ_NONE;

	sts0 = dma_readl(pd, STS0);
	sts2 = dma_readl(pd, STS2);

	dev_dbg(pd->dma.dev, "pd_irq sts0: %x\n", sts0);

	for (i = 0; i < pd->dma.chancnt; i++) {
		pd_chan = &pd->channels[i];

		if (i < 8) {
			if (sts0 & DMA_STATUS_IRQ(i)) {
			if (sts0 & DMA_STATUS_ERR(i))
				if (sts0 & DMA_STATUS0_ERR(i))
					set_bit(0, &pd_chan->err_status);

				tasklet_schedule(&pd_chan->tasklet);
			ret = IRQ_HANDLED;
				ret0 = IRQ_HANDLED;
			}
		} else {
			if (sts2 & DMA_STATUS_IRQ(i - 8)) {
				if (sts2 & DMA_STATUS2_ERR(i))
					set_bit(0, &pd_chan->err_status);

				tasklet_schedule(&pd_chan->tasklet);
				ret2 = IRQ_HANDLED;
			}
		}
	}

	/* clear interrupt bits in status register */
	if (ret0)
		dma_writel(pd, STS0, sts0);
	if (ret2)
		dma_writel(pd, STS2, sts2);

	return ret;
	return ret0 | ret2;
}

#ifdef	CONFIG_PM