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 <[email protected]> --- 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
