Re: [PATCH v2] drm/mediatek: add ctm property support
From: CK Hu
Date: Tue Dec 03 2019 - 00:20:38 EST
Hi, Yongqiang:
On Mon, 2019-12-02 at 17:03 +0800, yongqiang.niu@xxxxxxxxxxxx wrote:
> From: Yongqiang Niu <yongqiang.niu@xxxxxxxxxxxx>
>
> add ctm property support
>
> Change-Id: I8111da7b309b1809c6302e7748dd9fd06dc97bde
Remove this Change-Id.
> Signed-off-by: Yongqiang Niu <yongqiang.niu@xxxxxxxxxxxx>
> ---
> drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 15 ++++++-
> drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 61 ++++++++++++++++++++++++++++-
> drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 11 ++++++
> 3 files changed, 84 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
> index 4fb346c..12dc684 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
> @@ -666,10 +666,13 @@ static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc,
> int i;
>
> if (crtc->state->color_mgmt_changed)
> - for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
> + for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
> mtk_ddp_gamma_set(mtk_crtc->ddp_comp[i],
> crtc->state,
> mtk_crtc_state->cmdq_handle);
> + mtk_ddp_ctm_set(mtk_crtc->ddp_comp[i], crtc->state);
Sorry, I'm not noticed that the code here would not write register in
vblank period. If ctm could be set out of vblank period, place the code
here and do not need to support cmdq. If ctm should be set inside vblank
period, move the code to mtk_crtc_ddp_config() and support cmdq
interface.
> + }
> +
> #ifdef CONFIG_MTK_CMDQ
> if (mtk_crtc->cmdq_client) {
> drm_atomic_state_get(old_atomic_state);
> @@ -819,6 +822,8 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
> int pipe = priv->num_pipes;
> int ret;
> int i;
> + bool has_ctm = false;
> + uint gamma_lut_size = 0;
>
> if (!path)
> return 0;
> @@ -870,6 +875,12 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
> }
>
> mtk_crtc->ddp_comp[i] = comp;
> +
> + if (comp_id == DDP_COMPONENT_CCORR)
> + has_ctm = true;
> +
> + if (comp_id == DDP_COMPONENT_GAMMA)
> + gamma_lut_size = MTK_LUT_SIZE;
> }
>
> for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
> @@ -891,7 +902,7 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
> if (ret < 0)
> return ret;
> drm_mode_crtc_set_gamma_size(&mtk_crtc->base, MTK_LUT_SIZE);
> - drm_crtc_enable_color_mgmt(&mtk_crtc->base, 0, false, MTK_LUT_SIZE);
> + drm_crtc_enable_color_mgmt(&mtk_crtc->base, 0, has_ctm, gamma_lut_size);
> priv->num_pipes++;
> #ifdef CONFIG_MTK_CMDQ
> mtk_crtc->cmdq_client =
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
> index 9cc12af..2fd52ba 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
> @@ -38,7 +38,15 @@
> #define CCORR_EN BIT(0)
> #define DISP_CCORR_CFG 0x0020
> #define CCORR_RELAY_MODE BIT(0)
> +#define CCORR_ENGINE_EN BIT(1)
> +#define CCORR_GAMMA_OFF BIT(2)
> +#define CCORR_WGAMUT_SRC_CLIP BIT(3)
> #define DISP_CCORR_SIZE 0x0030
> +#define DISP_CCORR_COEF_0 0x0080
> +#define DISP_CCORR_COEF_1 0x0084
> +#define DISP_CCORR_COEF_2 0x0088
> +#define DISP_CCORR_COEF_3 0x008C
> +#define DISP_CCORR_COEF_4 0x0090
>
> #define DISP_DITHER_EN 0x0000
> #define DITHER_EN BIT(0)
> @@ -187,7 +195,7 @@ static void mtk_ccorr_config(struct mtk_ddp_comp *comp, unsigned int w,
> unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
> {
> mtk_ddp_write(cmdq_pkt, h << 16 | w, comp, DISP_CCORR_SIZE);
> - mtk_ddp_write(cmdq_pkt, CCORR_RELAY_MODE, comp, DISP_CCORR_CFG);
> + mtk_ddp_write(cmdq_pkt, CCORR_ENGINE_EN, comp, DISP_CCORR_CFG);
> }
>
> static void mtk_ccorr_start(struct mtk_ddp_comp *comp)
> @@ -200,6 +208,56 @@ static void mtk_ccorr_stop(struct mtk_ddp_comp *comp)
> writel_relaxed(0x0, comp->regs + DISP_CCORR_EN);
> }
>
> +/* Converts a DRM S31.32 value to the HW S0.11 format. */
> +static u16 mtk_ctm_s31_32_to_s0_11(u64 in)
> +{
> + u16 r;
> +
> + /* Sign bit. */
> + r = in & BIT_ULL(63) ? BIT(11) : 0;
> +
> + if ((in & GENMASK_ULL(62, 33)) > 0) {
if ((in & GENMASK_ULL(62, 32)) > 0) {
> + /* We have zero integer bits so we can only saturate here. */
> + r |= GENMASK(10, 0);
> + } else {
> + /* Otherwise take the 9 most important fractional bits. */
> + r |= (in >> 22) & GENMASK(10, 0);
r |= (in >> 21) & GENMASK(10, 0);
Regards,
CK
> + }
> +
> + return r;
> +}
> +
> +static void mtk_ccorr_ctm_set(struct mtk_ddp_comp *comp,
> + struct drm_crtc_state *state
> + struct cmdq_pkt *cmdq_pkt)
> +{
> + struct drm_property_blob *blob = state->ctm;
> + struct drm_color_ctm *ctm;
> + const u64 *input;
> + uint16_t coeffs[9] = { 0 };
> + int i;
> +
> + if (!blob)
> + return;
> +
> + ctm = (struct drm_color_ctm *)blob->data;
> + input = ctm->matrix;
> +
> + for (i = 0; i < ARRAY_SIZE(coeffs); i++)
> + coeffs[i] = mtk_ctm_s31_32_to_s0_11(input[i]);
> +
> + mtk_ddp_write(cmdq_pkt, coeffs[0] << 16 | coeffs[1],
> + comp, DISP_CCORR_COEF_0);
> + mtk_ddp_write(cmdq_pkt, coeffs[2] << 16 | coeffs[3],
> + comp, DISP_CCORR_COEF_1);
> + mtk_ddp_write(cmdq_pkt, coeffs[4] << 16 | coeffs[5],
> + comp, DISP_CCORR_COEF_2);
> + mtk_ddp_write(cmdq_pkt, coeffs[6] << 16 | coeffs[7],
> + comp, DISP_CCORR_COEF_3);
> + mtk_ddp_write(cmdq_pkt, coeffs[8] << 16,
> + comp, DISP_CCORR_COEF_4);
> +}
> +
> static void mtk_dither_config(struct mtk_ddp_comp *comp, unsigned int w,
> unsigned int h, unsigned int vrefresh,
> unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
> @@ -269,6 +327,7 @@ static void mtk_gamma_set(struct mtk_ddp_comp *comp,
> .config = mtk_ccorr_config,
> .start = mtk_ccorr_start,
> .stop = mtk_ccorr_stop,
> + .ctm_set = mtk_ccorr_ctm_set,
> };
>
> static const struct mtk_ddp_comp_funcs ddp_dither = {
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
> index 5b0a3d4..4e3e5aa 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
> @@ -95,6 +95,9 @@ struct mtk_ddp_comp_funcs {
> struct cmdq_pkt *cmdq_pkt);
> void (*bgclr_in_on)(struct mtk_ddp_comp *comp);
> void (*bgclr_in_off)(struct mtk_ddp_comp *comp);
> + void (*ctm_set)(struct mtk_ddp_comp *comp,
> + struct drm_crtc_state *state
> + struct cmdq_pkt *cmdq_pkt);
> };
>
> struct mtk_ddp_comp {
> @@ -213,6 +216,14 @@ static inline void mtk_ddp_comp_bgclr_in_off(struct mtk_ddp_comp *comp)
> comp->funcs->bgclr_in_off(comp);
> }
>
> +static inline void mtk_ddp_ctm_set(struct mtk_ddp_comp *comp,
> + struct drm_crtc_state *state
> + struct cmdq_pkt *cmdq_pkt)
> +{
> + if (comp->funcs && comp->funcs->ctm_set)
> + comp->funcs->ctm_set(comp, state);
> +}
> +
> int mtk_ddp_comp_get_id(struct device_node *node,
> enum mtk_ddp_comp_type comp_type);
> int mtk_ddp_comp_init(struct device *dev, struct device_node *comp_node,