mirror of https://gitee.com/openkylin/linux.git
drm/imx: i.MX5 regression fix and i.MX6QP PRE/PRG stability fixes
- Disable channel burst locking on IPUv3EX (i.MX51) and IPUv3M (i.MX53). This fixes a regression introduced by commit790cb4c7c9
("drm/imx: lock scanout transfers for consecutive bursts"). - Give PRG a head start. Waiting for both double buffers to fill up before enabling the IPU improves startup reliability. - Avoid PRE control register updates during unsafe window, workaround for ERR009624. -----BEGIN PGP SIGNATURE----- iQJLBAABCAA1FiEEBsBxhV1FaKwXuCOBUMKIHHCeYOsFAlnfPc8XHHAuemFiZWxA cGVuZ3V0cm9uaXguZGUACgkQUMKIHHCeYOttzRAApPc7BrPKKOr5UZaHqVvLHZSq xPAOnyVDRGYRYc9+vyCMLwopjnyAHmvt5GTEThY2kXSmgY9t1tYRkeW6As/3vanc 1LX/SBGkU/bocxMhWrDMVmKlwWcxtBPDJCvLHlDugSst92053Ox+M4ZKANnfilzr Z42zrwsv27B3DhRkl+PjcB+5sCYCf7cbUWQhO5bcJPTmquzm+5rxesfIooj4DPZP UISTZAY1peHZfdDSflBw+eOuBurI+foRFFIzhVDvbKsoiZFflNbzjde4jPM0B4ID 8EzIqv5EHskEzS0jYUy1xGExjz5cZgMLYkIzY8pq/10Poij6/7EIBm/N93J0fTn+ a46CLgPPT9xqwx3rfb1R1bPW2KmSccrWb8R1iI1slWQbHB5g773BBlDvd4RWt5MP CSEYsOLgHDEUjulRMLLcr8PgG8wP7DN0Kwtmc2igbF+7U25f5Cb9TONLpRsaWGG4 d+GC8nCrQHNlWwOkBuBOFBjbawrcNamguSS1IDwE8RJK/L0iAktH0PCTP+MVawx+ CxBIx7nnDrBy8NZeAJRbq8xYcnqmQo2FCKm7hLBvhJoUn3gKF6rqWgbP/l66r/hN PUqulcLcEtE9PbCaDwL8BkTH/WauPd17+2qrVAvgkawuvi0NojrukG4HriyU2JxU cibgIOp5XvnsMu050us= =ZPkL -----END PGP SIGNATURE----- Merge tag 'imx-drm-fixes-2017-10-12' of git://git.pengutronix.de/git/pza/linux into drm-fixes drm/imx: i.MX5 regression fix and i.MX6QP PRE/PRG stability fixes - Disable channel burst locking on IPUv3EX (i.MX51) and IPUv3M (i.MX53). This fixes a regression introduced by commit790cb4c7c9
("drm/imx: lock scanout transfers for consecutive bursts"). - Give PRG a head start. Waiting for both double buffers to fill up before enabling the IPU improves startup reliability. - Avoid PRE control register updates during unsafe window, workaround for ERR009624. * tag 'imx-drm-fixes-2017-10-12' of git://git.pengutronix.de/git/pza/linux: gpu: ipu-v3: pre: implement workaround for ERR009624 gpu: ipu-v3: prg: wait for double buffers to be filled on channel startup gpu: ipu-v3: Allow channel burst locking on i.MX6 only
This commit is contained in:
commit
a6402e80fa
|
@ -405,6 +405,14 @@ int ipu_idmac_lock_enable(struct ipuv3_channel *channel, int num_bursts)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* IPUv3EX / i.MX51 has a different register layout, and on IPUv3M /
|
||||
* i.MX53 channel arbitration locking doesn't seem to work properly.
|
||||
* Allow enabling the lock feature on IPUv3H / i.MX6 only.
|
||||
*/
|
||||
if (bursts && ipu->ipu_type != IPUV3H)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(idmac_lock_en_info); i++) {
|
||||
if (channel->num == idmac_lock_en_info[i].chnum)
|
||||
break;
|
||||
|
|
|
@ -73,6 +73,14 @@
|
|||
#define IPU_PRE_STORE_ENG_CTRL_WR_NUM_BYTES(v) ((v & 0x7) << 1)
|
||||
#define IPU_PRE_STORE_ENG_CTRL_OUTPUT_ACTIVE_BPP(v) ((v & 0x3) << 4)
|
||||
|
||||
#define IPU_PRE_STORE_ENG_STATUS 0x120
|
||||
#define IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_X_MASK 0xffff
|
||||
#define IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_X_SHIFT 0
|
||||
#define IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_MASK 0x3fff
|
||||
#define IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_SHIFT 16
|
||||
#define IPU_PRE_STORE_ENG_STATUS_STORE_FIFO_FULL (1 << 30)
|
||||
#define IPU_PRE_STORE_ENG_STATUS_STORE_FIELD (1 << 31)
|
||||
|
||||
#define IPU_PRE_STORE_ENG_SIZE 0x130
|
||||
#define IPU_PRE_STORE_ENG_SIZE_INPUT_WIDTH(v) ((v & 0xffff) << 0)
|
||||
#define IPU_PRE_STORE_ENG_SIZE_INPUT_HEIGHT(v) ((v & 0xffff) << 16)
|
||||
|
@ -93,6 +101,7 @@ struct ipu_pre {
|
|||
dma_addr_t buffer_paddr;
|
||||
void *buffer_virt;
|
||||
bool in_use;
|
||||
unsigned int safe_window_end;
|
||||
};
|
||||
|
||||
static DEFINE_MUTEX(ipu_pre_list_mutex);
|
||||
|
@ -160,6 +169,9 @@ void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
|
|||
u32 active_bpp = info->cpp[0] >> 1;
|
||||
u32 val;
|
||||
|
||||
/* calculate safe window for ctrl register updates */
|
||||
pre->safe_window_end = height - 2;
|
||||
|
||||
writel(bufaddr, pre->regs + IPU_PRE_CUR_BUF);
|
||||
writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
|
||||
|
||||
|
@ -199,7 +211,24 @@ void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
|
|||
|
||||
void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr)
|
||||
{
|
||||
unsigned long timeout = jiffies + msecs_to_jiffies(5);
|
||||
unsigned short current_yblock;
|
||||
u32 val;
|
||||
|
||||
writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
|
||||
|
||||
do {
|
||||
if (time_after(jiffies, timeout)) {
|
||||
dev_warn(pre->dev, "timeout waiting for PRE safe window\n");
|
||||
return;
|
||||
}
|
||||
|
||||
val = readl(pre->regs + IPU_PRE_STORE_ENG_STATUS);
|
||||
current_yblock =
|
||||
(val >> IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_SHIFT) &
|
||||
IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_MASK;
|
||||
} while (current_yblock == 0 || current_yblock >= pre->safe_window_end);
|
||||
|
||||
writel(IPU_PRE_CTRL_SDW_UPDATE, pre->regs + IPU_PRE_CTRL_SET);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <drm/drm_fourcc.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
|
||||
#include <linux/module.h>
|
||||
|
@ -329,6 +330,12 @@ int ipu_prg_channel_configure(struct ipuv3_channel *ipu_chan,
|
|||
val = IPU_PRG_REG_UPDATE_REG_UPDATE;
|
||||
writel(val, prg->regs + IPU_PRG_REG_UPDATE);
|
||||
|
||||
/* wait for both double buffers to be filled */
|
||||
readl_poll_timeout(prg->regs + IPU_PRG_STATUS, val,
|
||||
(val & IPU_PRG_STATUS_BUFFER0_READY(prg_chan)) &&
|
||||
(val & IPU_PRG_STATUS_BUFFER1_READY(prg_chan)),
|
||||
5, 1000);
|
||||
|
||||
clk_disable_unprepare(prg->clk_ipg);
|
||||
|
||||
chan->enabled = true;
|
||||
|
|
Loading…
Reference in New Issue