Re: [PATCH 08/11] drm/mediatek: ovl: Implement support for Gamma
From: CK Hu (胡俊光) <hidden>
Date: 2026-03-03 06:53:44
Also in:
dri-devel, linux-mediatek, lkml
On Tue, 2025-12-23 at 16:44 -0300, Nícolas F. R. A. Prado wrote:
quoted hunk ↗ jump to hunk
External email : Please do not click links or open attachments until you have verified the sender or the content. The OVL hardware allows selecting between different fixed transfer functions for each layer through the Gamma setting. Available functions are scRGB, BT.709, BT.2020 and HLG. Implement support for it and expose it as a colorop through the DRM plane color pipeline uAPI. Signed-off-by: Nícolas F. R. A. Prado <redacted> --- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 67 ++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 2 deletions(-)diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 4eaa31541ccc..a70092c792a9 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c@@ -52,10 +52,16 @@ #define OVL_CON_CLRFMT_10_BIT (1) #define DISP_REG_OVL_WCG_CFG1 0x2d8 #define IGAMMA_EN(layer) BIT(0 + 4 * (layer)) +#define GAMMA_EN(layer) BIT(2 + 4 * (layer)) #define DISP_REG_OVL_WCG_CFG2 0x2dc #define IGAMMA_MASK(layer) GENMASK((layer) * 4 + 1, (layer) * 4) #define IGAMMA_SCRGB 0 #define IGAMMA_BT709 1 +#define GAMMA_MASK(layer) GENMASK((layer) * 4 + 3, (layer) * 4 + 2) +#define GAMMA_SCRGB 0 +#define GAMMA_BT709 1 +#define GAMMA_BT2020 2 +#define GAMMA_HLG 3 #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)@@ -508,11 +514,41 @@ static int mtk_ovl_colorop_curve_to_reg_val(enum drm_colorop_curve_1d_type curve return IGAMMA_SCRGB; case DRM_COLOROP_1D_CURVE_BT2020_OETF: return IGAMMA_BT709; + case DRM_COLOROP_1D_CURVE_SRGB_EOTF: + return GAMMA_SCRGB; + case DRM_COLOROP_1D_CURVE_BT2020_INV_OETF:
Maybe DRM_COLOROP_1D_CURVE_BT2020_OETF?
+ return GAMMA_BT2020; + case DRM_COLOROP_1D_CURVE_HLG_EOTF: + return GAMMA_HLG;
igamma and gamma use the same function mtk_ovl_colorop_curve_to_reg_val() to check. If curve is DRM_COLOROP_1D_CURVE_HLG_EOTF for igamma, error happen but not detected.
default:
return -EINVAL;
}
}
+static void mtk_ovl_apply_gamma(struct mtk_disp_ovl *ovl, unsigned int idx,
+ struct drm_colorop *colorop,
+ struct cmdq_pkt *cmdq_pkt)
+{
+ int curve_reg_val;
+
+ curve_reg_val = mtk_ovl_colorop_curve_to_reg_val(colorop->state->curve_1d_type);
+ if (curve_reg_val < 0) {
+ drm_WARN(ovl->crtc->dev, 1, "Invalid curve 1d type %u\n",
+ colorop->state->curve_1d_type);
+ return;
+ }
+
+ mtk_ddp_write_mask(cmdq_pkt,
+ field_prep(GAMMA_MASK(idx), curve_reg_val),
+ &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_WCG_CFG2,
+ GAMMA_MASK(idx));
+When gamma is disable, I would like to disable first then clear curve value.
quoted hunk ↗ jump to hunk
+ mtk_ddp_write_mask(cmdq_pkt, + colorop->state->bypass ? 0 : GAMMA_EN(idx), + &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_WCG_CFG1, + GAMMA_EN(idx)); +} + static void mtk_ovl_apply_igamma(struct mtk_disp_ovl *ovl, unsigned int idx, struct drm_colorop *colorop, struct cmdq_pkt *cmdq_pkt)@@ -549,7 +585,11 @@ static void mtk_ovl_apply_colorop(struct mtk_disp_ovl *ovl, unsigned int idx, { switch (colorop->type) { case DRM_COLOROP_1D_CURVE: - mtk_ovl_apply_igamma(ovl, idx, colorop, cmdq_pkt); + /* gamma is the last colorop in pipeline */ + if (!colorop->next) + mtk_ovl_apply_gamma(ovl, idx, colorop, cmdq_pkt); + else + mtk_ovl_apply_igamma(ovl, idx, colorop, cmdq_pkt); break; default: drm_WARN(ovl->crtc->dev, 1, "Invalid colorop type %u\n", colorop->type);@@ -562,7 +602,7 @@ static void mtk_ovl_disable_colorops(struct mtk_disp_ovl *ovl, unsigned int idx, { mtk_ddp_write_mask(cmdq_pkt, 0, &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_WCG_CFG1, - IGAMMA_EN(idx)); + IGAMMA_EN(idx) | GAMMA_EN(idx)); /* igamma curve needs to be set to default when igamma is disabled */ mtk_ddp_write_mask(cmdq_pkt, IGAMMA_SCRGB, &ovl->cmdq_reg, ovl->regs,@@ -697,6 +737,11 @@ static const u64 igamma_supported_tfs = BIT(DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF) | BIT(DRM_COLOROP_1D_CURVE_BT2020_OETF); +static const u64 gamma_supported_tfs = + BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF) | + BIT(DRM_COLOROP_1D_CURVE_BT2020_INV_OETF) | + BIT(DRM_COLOROP_1D_CURVE_HLG_EOTF); + #define MAX_COLOR_PIPELINE_OPS 3 static int@@ -724,6 +769,24 @@ mtk_ovl_initialize_plane_color_pipeline(struct drm_plane *plane, if (ret) goto err_colorop_init; + i++; + + /* 3rd op: OVL's Gamma */
I would like you apply patch order according to op order. So apply 3x3 matrix patch before this patch.
+ ops[i] = kzalloc(sizeof(*ops[i]), GFP_KERNEL);
variable i is not necessary. Use constant value is enough. Regards, CK
+ if (!ops[i]) {
+ ret = -ENOMEM;
+ goto err_alloc;
+ }
+
+ ret = drm_plane_colorop_curve_1d_init(dev, ops[i], plane,
+ &mtk_ovl_colorop_funcs,
+ gamma_supported_tfs,
+ DRM_COLOROP_FLAG_ALLOW_BYPASS);
+ if (ret)
+ goto err_colorop_init;
+
+ drm_colorop_set_next_property(ops[i - 1], ops[i]);
+
pipeline->type = ops[0]->base.id;
pipeline->name = kasprintf(GFP_KERNEL, "Color Pipeline %d", ops[0]->base.id);
--
2.51.0