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 commit 790cb4c7c9 ("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 commit 790cb4c7c9 ("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:
Dave Airlie 2017-10-13 17:32:30 +10:00
commit a6402e80fa
3 changed files with 44 additions and 0 deletions

View File

@ -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;

View File

@ -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);
}

View File

@ -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;