gpu: ipu-v3: pre: add tiled prefetch support
authorLucas Stach <l.stach@pengutronix.de>
Fri, 10 Nov 2017 16:09:58 +0000 (17:09 +0100)
committerPhilipp Zabel <p.zabel@pengutronix.de>
Tue, 19 Dec 2017 11:49:11 +0000 (12:49 +0100)
This configures the TPR unit, using the DRM format modifier. For now only
the single buffer modifiers are supported, as split buffer needs more
configuration for the required cropping.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
[p.zabel@pengutronix.de: rebased after ERR009624 workaround]
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
drivers/gpu/ipu-v3/ipu-pre.c
drivers/gpu/ipu-v3/ipu-prg.c
drivers/gpu/ipu-v3/ipu-prv.h

index c860a7997cb59c981557e01021d6a4278b2470ea..f1cec3d70498ab526f9765f66422e0835f338dc0 100644 (file)
 #define IPU_PRE_TPR_CTRL                               0x070
 #define  IPU_PRE_TPR_CTRL_TILE_FORMAT(v)               ((v & 0xff) << 0)
 #define  IPU_PRE_TPR_CTRL_TILE_FORMAT_MASK             0xff
+#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_16_BIT           (1 << 0)
+#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_SPLIT_BUF                (1 << 4)
+#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_SINGLE_BUF       (1 << 5)
+#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_SUPER_TILED      (1 << 6)
 
 #define IPU_PRE_PREFETCH_ENG_CTRL                      0x080
 #define  IPU_PRE_PREF_ENG_CTRL_PREFETCH_EN             (1 << 0)
@@ -147,7 +151,7 @@ int ipu_pre_get(struct ipu_pre *pre)
        val = IPU_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN |
              IPU_PRE_CTRL_HANDSHAKE_EN |
              IPU_PRE_CTRL_TPR_REST_SEL |
-             IPU_PRE_CTRL_BLOCK_16 | IPU_PRE_CTRL_SDW_UPDATE;
+             IPU_PRE_CTRL_SDW_UPDATE;
        writel(val, pre->regs + IPU_PRE_CTRL);
 
        pre->in_use = true;
@@ -163,14 +167,17 @@ void ipu_pre_put(struct ipu_pre *pre)
 
 void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
                       unsigned int height, unsigned int stride, u32 format,
-                      unsigned int bufaddr)
+                      uint64_t modifier, unsigned int bufaddr)
 {
        const struct drm_format_info *info = drm_format_info(format);
        u32 active_bpp = info->cpp[0] >> 1;
        u32 val;
 
        /* calculate safe window for ctrl register updates */
-       pre->safe_window_end = height - 2;
+       if (modifier == DRM_FORMAT_MOD_LINEAR)
+               pre->safe_window_end = height - 2;
+       else
+               pre->safe_window_end = DIV_ROUND_UP(height, 4) - 1;
 
        writel(bufaddr, pre->regs + IPU_PRE_CUR_BUF);
        writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
@@ -203,9 +210,25 @@ void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
 
        writel(pre->buffer_paddr, pre->regs + IPU_PRE_STORE_ENG_ADDR);
 
+       val = readl(pre->regs + IPU_PRE_TPR_CTRL);
+       val &= ~IPU_PRE_TPR_CTRL_TILE_FORMAT_MASK;
+       if (modifier != DRM_FORMAT_MOD_LINEAR) {
+               /* only support single buffer formats for now */
+               val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_SINGLE_BUF;
+               if (modifier == DRM_FORMAT_MOD_VIVANTE_SUPER_TILED)
+                       val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_SUPER_TILED;
+               if (info->cpp[0] == 2)
+                       val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_16_BIT;
+       }
+       writel(val, pre->regs + IPU_PRE_TPR_CTRL);
+
        val = readl(pre->regs + IPU_PRE_CTRL);
        val |= IPU_PRE_CTRL_EN_REPEAT | IPU_PRE_CTRL_ENABLE |
               IPU_PRE_CTRL_SDW_UPDATE;
+       if (modifier == DRM_FORMAT_MOD_LINEAR)
+               val &= ~IPU_PRE_CTRL_BLOCK_EN;
+       else
+               val |= IPU_PRE_CTRL_BLOCK_EN;
        writel(val, pre->regs + IPU_PRE_CTRL);
 }
 
index fd98f48e8a089123b54c36fa4957958fd3c64294..1a4d3a635d1d21d3f5eac1408bbf7c9461f107fe 100644 (file)
@@ -287,7 +287,7 @@ int ipu_prg_channel_configure(struct ipuv3_channel *ipu_chan,
                return ret;
 
        ipu_pre_configure(prg->pres[chan->used_pre],
-                         width, height, stride, format, *eba);
+                         width, height, stride, format, 0, *eba);
 
 
        pm_runtime_get_sync(prg->dev);
index ac4b8d658500865886716c6da552e6918e308de1..d6beee99b6b8c14a8bc31062656a62c2dd86354b 100644 (file)
@@ -269,8 +269,8 @@ int ipu_pre_get(struct ipu_pre *pre);
 void ipu_pre_put(struct ipu_pre *pre);
 u32 ipu_pre_get_baddr(struct ipu_pre *pre);
 void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
-                      unsigned int height,
-                      unsigned int stride, u32 format, unsigned int bufaddr);
+                      unsigned int height, unsigned int stride, u32 format,
+                      uint64_t modifier, unsigned int bufaddr);
 void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr);
 
 struct ipu_prg *ipu_prg_lookup_by_phandle(struct device *dev, const char *name,