Tested on MT8195 and confirmed both correct video output and improved DRAM
bandwidth performance.
v4:
* Move modifier validation to format_mod_supported function.
* Add modifiers to drm_universal_plane_init() call.
* Make comparisons to DRM_FORMAT_MOD_LINEAR explicit rather than relying on
DRM_FORMAT_LINEAR being equal to 0.
* Gate AFBC control bit writes on device compatibility.
v3:
* Replaced pitch bitshift math with union based approach.
* Refactored overlay register writes to shared code between non-AFBC and
AFBC.
* Minor code cleanups.
v2:
* Marked mtk_ovl_set_afbc as static.
* Reflowed some lines to fit column limit.
Signed-off-by: Justin Green
---
drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 67 -
drivers/gpu/drm/mediatek/mtk_drm_plane.c | 74 +++-
drivers/gpu/drm/mediatek/mtk_drm_plane.h | 8 +++
3 files changed, 144 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index 002b0f6cae1a..6d4c0e44a2f1 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -29,17 +29,24 @@
#define DISP_REG_OVL_DATAPATH_CON 0x0024
#define OVL_LAYER_SMI_ID_ENBIT(0)
#define OVL_BGCLR_SEL_IN BIT(2)
+#define OVL_LAYER_AFBC_EN(n) BIT(4+n)
#define DISP_REG_OVL_ROI_BGCLR 0x0028
#define DISP_REG_OVL_SRC_CON 0x002c
#define DISP_REG_OVL_CON(n)(0x0030 + 0x20 * (n))
#define DISP_REG_OVL_SRC_SIZE(n) (0x0038 + 0x20 * (n))
#define DISP_REG_OVL_OFFSET(n) (0x003c + 0x20 * (n))
+#define DISP_REG_OVL_PITCH_MSB(n) (0x0040 + 0x20 * (n))
+#define OVL_PITCH_MSB_2ND_SUBBUF BIT(16)
+#define OVL_PITCH_MSB_YUV_TRANSBIT(20)
#define DISP_REG_OVL_PITCH(n) (0x0044 + 0x20 * (n))
+#define DISP_REG_OVL_CLIP(n) (0x004c + 0x20 * (n))
#define DISP_REG_OVL_RDMA_CTRL(n) (0x00c0 + 0x20 * (n))
#define DISP_REG_OVL_RDMA_GMC(n) (0x00c8 + 0x20 * (n))
#define DISP_REG_OVL_ADDR_MT2701 0x0040
#define DISP_REG_OVL_ADDR_MT8173 0x0f40
#define DISP_REG_OVL_ADDR(ovl, n) ((ovl)->data->addr + 0x20 * (n))
+#define DISP_REG_OVL_HDR_ADDR(ovl, n) ((ovl)->data->addr + 0x20 * (n)
+ 0x04)
+#define DISP_REG_OVL_HDR_PITCH(ovl, n) ((ovl)->data->addr + 0x20 * (n)
+ 0x08)
#define GMC_THRESHOLD_BITS 16
#define GMC_THRESHOLD_HIGH ((1 << GMC_THRESHOLD_BITS) / 4)
@@ -67,6 +74,7 @@ struct mtk_disp_ovl_data {
unsigned int layer_nr;
bool fmt_rgb565_is_0;
bool smi_id_en;
+ bool supports_afbc;
};
/*
@@ -172,7 +180,22 @@ void mtk_ovl_stop(struct device *dev)
reg = reg & ~OVL_LAYER_SMI_ID_EN;
writel_relaxed(reg, ovl->regs + DISP_REG_OVL_DATAPATH_CON);
}
+}
+
+static void mtk_ovl_set_afbc(struct device *dev, struct cmdq_pkt *cmdq_pkt,
+int idx, bool enabled)
+{
+ struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
+ unsigned int reg;
+ reg = readl(ovl->regs + DISP_REG_OVL_DATAPATH_CON);
+ if (enabled)
+ reg = reg | OVL_LAYER_AFBC_EN(idx);
+ else
+ reg = reg & ~OVL_LAYER_AFBC_EN(idx);
+
+ mtk_ddp_write_relaxed(cmdq_pkt, reg, >cmdq_reg,
+ ovl->regs, DISP_REG_OVL_DATAPATH_CON);
}
void mtk_ovl_config(struct device *dev, unsigned int w,
@@ -310,11 +333,23 @@ 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 = >pending;
unsigned int addr = pending->addr;
- unsigned int pitch = pending->pitch & 0x;
+ unsigned int hdr_addr = pending->hdr_addr;
+ unsigned int pitch = pending->pitch;
+ unsigned int hdr_pitch = pending->hdr_pitch;
unsigned int fmt = pending->format;
unsigned int offset = (pending->y << 16) | pending->x;
unsigned int src_size = (pending->height << 16) | pending->width;
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);
@@ -335,9 +370,12 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int
idx,
addr += pending->pitch - 1;
}
+ if (ovl->data->supports_afbc)
+ mtk_ovl_set_afbc(dev, cmdq_pkt, idx, is_afbc);
+