]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/mediatek: Only touch DISP_REG_OVL_PITCH_MSB if AFBC is supported
authorDaniel Golle <daniel@makrotopia.org>
Tue, 17 Dec 2024 01:18:01 +0000 (01:18 +0000)
committerChun-Kuang Hu <chunkuang.hu@kernel.org>
Wed, 25 Dec 2024 15:19:27 +0000 (15:19 +0000)
Touching DISP_REG_OVL_PITCH_MSB leads to video overlay on MT2701, MT7623N
and probably other older SoCs being broken.

Move setting up AFBC layer configuration into a separate function only
being called on hardware which actually supports AFBC which restores the
behavior as it was before commit c410fa9b07c3 ("drm/mediatek: Add AFBC
support to Mediatek DRM driver") on non-AFBC hardware.

Fixes: c410fa9b07c3 ("drm/mediatek: Add AFBC support to Mediatek DRM driver")
Cc: stable@vger.kernel.org
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Reviewed-by: CK Hu <ck.hu@mediatek.com>
Link: https://patchwork.kernel.org/project/dri-devel/patch/c7fbd3c3e633c0b7dd6d1cd78ccbdded31e1ca0f.1734397800.git.daniel@makrotopia.org/
Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
drivers/gpu/drm/mediatek/mtk_disp_ovl.c

index e0c0bb01f65ae006828a9a94e945dac62c56763c..0e4da239cbeb89961b1a5e0aba41e0e454833541 100644 (file)
@@ -460,6 +460,29 @@ static unsigned int mtk_ovl_fmt_convert(struct mtk_disp_ovl *ovl,
        }
 }
 
+static void mtk_ovl_afbc_layer_config(struct mtk_disp_ovl *ovl,
+                                     unsigned int idx,
+                                     struct mtk_plane_pending_state *pending,
+                                     struct cmdq_pkt *cmdq_pkt)
+{
+       unsigned int pitch_msb = pending->pitch >> 16;
+       unsigned int hdr_pitch = pending->hdr_pitch;
+       unsigned int hdr_addr = pending->hdr_addr;
+
+       if (pending->modifier != DRM_FORMAT_MOD_LINEAR) {
+               mtk_ddp_write_relaxed(cmdq_pkt, hdr_addr, &ovl->cmdq_reg, ovl->regs,
+                                     DISP_REG_OVL_HDR_ADDR(ovl, idx));
+               mtk_ddp_write_relaxed(cmdq_pkt,
+                                     OVL_PITCH_MSB_2ND_SUBBUF | pitch_msb,
+                                     &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH_MSB(idx));
+               mtk_ddp_write_relaxed(cmdq_pkt, hdr_pitch, &ovl->cmdq_reg, ovl->regs,
+                                     DISP_REG_OVL_HDR_PITCH(ovl, idx));
+       } else {
+               mtk_ddp_write_relaxed(cmdq_pkt, pitch_msb,
+                                     &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH_MSB(idx));
+       }
+}
+
 void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
                          struct mtk_plane_state *state,
                          struct cmdq_pkt *cmdq_pkt)
@@ -467,25 +490,13 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
        struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
        struct mtk_plane_pending_state *pending = &state->pending;
        unsigned int addr = pending->addr;
-       unsigned int hdr_addr = pending->hdr_addr;
-       unsigned int pitch = pending->pitch;
-       unsigned int hdr_pitch = pending->hdr_pitch;
+       unsigned int pitch_lsb = pending->pitch & GENMASK(15, 0);
        unsigned int fmt = pending->format;
        unsigned int offset = (pending->y << 16) | pending->x;
        unsigned int src_size = (pending->height << 16) | pending->width;
        unsigned int blend_mode = state->base.pixel_blend_mode;
        unsigned int ignore_pixel_alpha = 0;
        unsigned int con;
-       bool is_afbc = pending->modifier != DRM_FORMAT_MOD_LINEAR;
-       union overlay_pitch {
-               struct split_pitch {
-                       u16 lsb;
-                       u16 msb;
-               } split_pitch;
-               u32 pitch;
-       } overlay_pitch;
-
-       overlay_pitch.pitch = pitch;
 
        if (!pending->enable) {
                mtk_ovl_layer_off(dev, idx, cmdq_pkt);
@@ -524,11 +535,12 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
        }
 
        if (ovl->data->supports_afbc)
-               mtk_ovl_set_afbc(ovl, cmdq_pkt, idx, is_afbc);
+               mtk_ovl_set_afbc(ovl, cmdq_pkt, idx,
+                                pending->modifier != DRM_FORMAT_MOD_LINEAR);
 
        mtk_ddp_write_relaxed(cmdq_pkt, con, &ovl->cmdq_reg, ovl->regs,
                              DISP_REG_OVL_CON(idx));
-       mtk_ddp_write_relaxed(cmdq_pkt, overlay_pitch.split_pitch.lsb | ignore_pixel_alpha,
+       mtk_ddp_write_relaxed(cmdq_pkt, pitch_lsb | ignore_pixel_alpha,
                              &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH(idx));
        mtk_ddp_write_relaxed(cmdq_pkt, src_size, &ovl->cmdq_reg, ovl->regs,
                              DISP_REG_OVL_SRC_SIZE(idx));
@@ -537,19 +549,8 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
        mtk_ddp_write_relaxed(cmdq_pkt, addr, &ovl->cmdq_reg, ovl->regs,
                              DISP_REG_OVL_ADDR(ovl, idx));
 
-       if (is_afbc) {
-               mtk_ddp_write_relaxed(cmdq_pkt, hdr_addr, &ovl->cmdq_reg, ovl->regs,
-                                     DISP_REG_OVL_HDR_ADDR(ovl, idx));
-               mtk_ddp_write_relaxed(cmdq_pkt,
-                                     OVL_PITCH_MSB_2ND_SUBBUF | overlay_pitch.split_pitch.msb,
-                                     &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH_MSB(idx));
-               mtk_ddp_write_relaxed(cmdq_pkt, hdr_pitch, &ovl->cmdq_reg, ovl->regs,
-                                     DISP_REG_OVL_HDR_PITCH(ovl, idx));
-       } else {
-               mtk_ddp_write_relaxed(cmdq_pkt,
-                                     overlay_pitch.split_pitch.msb,
-                                     &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH_MSB(idx));
-       }
+       if (ovl->data->supports_afbc)
+               mtk_ovl_afbc_layer_config(ovl, idx, pending, cmdq_pkt);
 
        mtk_ovl_set_bit_depth(dev, idx, fmt, cmdq_pkt);
        mtk_ovl_layer_on(dev, idx, cmdq_pkt);