[PATCH 10/11] drm/mediatek: ovl: Enable support for R2R Color Space Conversion
Nícolas F. R. A. Prado
nfraprado at collabora.com
Tue Dec 23 11:44:51 PST 2025
The OVL hardware allows applying a 3x3 matrix transformation for each
layer through the 'RGB to RGB Color Space Conversion' (R2R CSC) setting.
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 <nfraprado at collabora.com>
---
drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 55 ++++++++++++++++++++++++++++++++-
1 file changed, 54 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index a70092c792a9..c8a2b1b13035 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -4,6 +4,7 @@
*/
#include <drm/drm_blend.h>
+#include <drm/drm_color_mgmt.h>
#include <drm/drm_colorop.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
@@ -52,6 +53,7 @@
#define OVL_CON_CLRFMT_10_BIT (1)
#define DISP_REG_OVL_WCG_CFG1 0x2d8
#define IGAMMA_EN(layer) BIT(0 + 4 * (layer))
+#define CSC_EN(layer) BIT(1 + 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)
@@ -62,6 +64,7 @@
#define GAMMA_BT709 1
#define GAMMA_BT2020 2
#define GAMMA_HLG 3
+#define DISP_REG_OVL_R2R_PARA(layer) (0x500 + (layer) * 0x40)
#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)
@@ -579,11 +582,44 @@ static void mtk_ovl_apply_igamma(struct mtk_disp_ovl *ovl, unsigned int idx,
IGAMMA_EN(idx));
}
+static void mtk_ovl_write_r2r_para(struct mtk_disp_ovl *ovl, unsigned int idx,
+ struct drm_color_ctm *ctm,
+ struct cmdq_pkt *cmdq_pkt)
+{
+ unsigned int i;
+ u64 val;
+
+ for (i = 0; i < ARRAY_SIZE(ctm->matrix); i++) {
+ val = drm_color_ctm_s31_32_to_qm_n(ctm->matrix[i], 5, 18);
+ mtk_ddp_write(cmdq_pkt, val, &ovl->cmdq_reg, ovl->regs,
+ DISP_REG_OVL_R2R_PARA(idx) + i * 4);
+ }
+}
+
+static void mtk_ovl_apply_r2r_csc(struct mtk_disp_ovl *ovl, unsigned int idx,
+ struct drm_colorop *colorop,
+ struct cmdq_pkt *cmdq_pkt)
+{
+ struct drm_color_ctm *ctm;
+
+ if (colorop->state->data && colorop->state->data->data) {
+ ctm = (struct drm_color_ctm *)colorop->state->data->data;
+ mtk_ovl_write_r2r_para(ovl, idx, ctm, cmdq_pkt);
+ }
+
+ mtk_ddp_write_mask(cmdq_pkt, colorop->state->bypass ? 0 : CSC_EN(idx),
+ &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_WCG_CFG1,
+ CSC_EN(idx));
+}
+
static void mtk_ovl_apply_colorop(struct mtk_disp_ovl *ovl, unsigned int idx,
struct drm_colorop *colorop,
struct cmdq_pkt *cmdq_pkt)
{
switch (colorop->type) {
+ case DRM_COLOROP_CTM_3X3:
+ mtk_ovl_apply_r2r_csc(ovl, idx, colorop, cmdq_pkt);
+ break;
case DRM_COLOROP_1D_CURVE:
/* gamma is the last colorop in pipeline */
if (!colorop->next)
@@ -602,7 +638,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) | GAMMA_EN(idx));
+ IGAMMA_EN(idx) | CSC_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,
@@ -771,6 +807,23 @@ mtk_ovl_initialize_plane_color_pipeline(struct drm_plane *plane,
i++;
+ /* 2nd op: OVL's R2R Color Space Conversion */
+ ops[i] = kzalloc(sizeof(*ops[i]), GFP_KERNEL);
+ if (!ops[i]) {
+ ret = -ENOMEM;
+ goto err_alloc;
+ }
+
+ ret = drm_plane_colorop_ctm_3x3_init(dev, ops[i], plane,
+ &mtk_ovl_colorop_funcs,
+ DRM_COLOROP_FLAG_ALLOW_BYPASS);
+ if (ret)
+ goto err_colorop_init;
+
+ drm_colorop_set_next_property(ops[i - 1], ops[i]);
+
+ i++;
+
/* 3rd op: OVL's Gamma */
ops[i] = kzalloc(sizeof(*ops[i]), GFP_KERNEL);
if (!ops[i]) {
--
2.51.0
More information about the Linux-mediatek
mailing list