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

Commit 7ad01814 authored by YoungJun Cho's avatar YoungJun Cho Committed by Inki Dae
Browse files

drm/exynos: Fix G2D core malfunctioning issue



This patch fixes G2D core malfunctioning issue once g2d dma is started.
Without 'DMA_HOLD_CMD_REG' register setting, there is only one interrupt
after the execution to all command lists have been completed. And that
induces watchdog. So this patch sets 'LIST_HOLD' command to the register
so that command execution interrupt can be occured whenever each command
list execution is finished.

Changelog v2:
- Consider for interrupt setup to each command list and all command lists
  And correct typo.

Signed-off-by: default avatarYoungJun Cho <yj44.cho@samsung.com>
Signed-off-by: default avatarInki Dae <inki.dae@samsung.com>
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
parent 5efc1d1b
Loading
Loading
Loading
Loading
+15 −5
Original line number Original line Diff line number Diff line
@@ -82,7 +82,7 @@
#define G2D_DMA_LIST_DONE_COUNT_OFFSET	17
#define G2D_DMA_LIST_DONE_COUNT_OFFSET	17


/* G2D_DMA_HOLD_CMD */
/* G2D_DMA_HOLD_CMD */
#define G2D_USET_HOLD			(1 << 2)
#define G2D_USER_HOLD			(1 << 2)
#define G2D_LIST_HOLD			(1 << 1)
#define G2D_LIST_HOLD			(1 << 1)
#define G2D_BITBLT_HOLD			(1 << 0)
#define G2D_BITBLT_HOLD			(1 << 0)


@@ -592,10 +592,6 @@ static void g2d_dma_start(struct g2d_data *g2d,
	pm_runtime_get_sync(g2d->dev);
	pm_runtime_get_sync(g2d->dev);
	clk_enable(g2d->gate_clk);
	clk_enable(g2d->gate_clk);


	/* interrupt enable */
	writel_relaxed(G2D_INTEN_ACF | G2D_INTEN_UCF | G2D_INTEN_GCF,
			g2d->regs + G2D_INTEN);

	writel_relaxed(node->dma_addr, g2d->regs + G2D_DMA_SFR_BASE_ADDR);
	writel_relaxed(node->dma_addr, g2d->regs + G2D_DMA_SFR_BASE_ADDR);
	writel_relaxed(G2D_DMA_START, g2d->regs + G2D_DMA_COMMAND);
	writel_relaxed(G2D_DMA_START, g2d->regs + G2D_DMA_COMMAND);
}
}
@@ -863,9 +859,23 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
	cmdlist->data[cmdlist->last++] = G2D_SRC_BASE_ADDR;
	cmdlist->data[cmdlist->last++] = G2D_SRC_BASE_ADDR;
	cmdlist->data[cmdlist->last++] = 0;
	cmdlist->data[cmdlist->last++] = 0;


	/*
	 * 'LIST_HOLD' command should be set to the DMA_HOLD_CMD_REG
	 * and GCF bit should be set to INTEN register if user wants
	 * G2D interrupt event once current command list execution is
	 * finished.
	 * Otherwise only ACF bit should be set to INTEN register so
	 * that one interrupt is occured after all command lists
	 * have been completed.
	 */
	if (node->event) {
	if (node->event) {
		cmdlist->data[cmdlist->last++] = G2D_INTEN;
		cmdlist->data[cmdlist->last++] = G2D_INTEN_ACF | G2D_INTEN_GCF;
		cmdlist->data[cmdlist->last++] = G2D_DMA_HOLD_CMD;
		cmdlist->data[cmdlist->last++] = G2D_DMA_HOLD_CMD;
		cmdlist->data[cmdlist->last++] = G2D_LIST_HOLD;
		cmdlist->data[cmdlist->last++] = G2D_LIST_HOLD;
	} else {
		cmdlist->data[cmdlist->last++] = G2D_INTEN;
		cmdlist->data[cmdlist->last++] = G2D_INTEN_ACF;
	}
	}


	/* Check size of cmdlist: last 2 is about G2D_BITBLT_START */
	/* Check size of cmdlist: last 2 is about G2D_BITBLT_START */