We currently have 1D LUTs to define output transfer function but using a 1D LUT is not always the best way to define a transfer function for HW that has ROMs for certain transfer functions, or for HW that has complex PWL definition for accurate LUT definitions. For this reason we're introducing named transfer functions. The original LUT behavior is preserved with the default "1D LUT" transfer function. Signed-off-by: Harry Wentland <harry.wentland@xxxxxxx> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 11 +++- .../gpu/drm/arm/display/komeda/komeda_crtc.c | 7 ++- drivers/gpu/drm/arm/malidp_crtc.c | 7 ++- drivers/gpu/drm/armada/armada_crtc.c | 5 +- .../gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 7 ++- drivers/gpu/drm/drm_color_mgmt.c | 54 ++++++++++++++++--- drivers/gpu/drm/i915/display/intel_color.c | 11 ++-- drivers/gpu/drm/i915/display/intel_color.h | 2 +- drivers/gpu/drm/i915/display/intel_crtc.c | 4 +- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 9 +++- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 8 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 9 +++- drivers/gpu/drm/nouveau/dispnv50/head.c | 13 +++-- drivers/gpu/drm/omapdrm/omap_crtc.c | 10 +++- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 7 ++- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 5 +- drivers/gpu/drm/stm/ltdc.c | 8 ++- drivers/gpu/drm/tidss/tidss_crtc.c | 9 +++- drivers/gpu/drm/vc4/vc4_crtc.c | 16 +++++- include/drm/drm_color_mgmt.h | 37 +++++++------ include/drm/drm_crtc.h | 20 +++++++ 21 files changed, 208 insertions(+), 51 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 63ddae9c5abe..b6d072211bf9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7343,8 +7343,15 @@ static int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, acrtc->otg_inst = -1; dm->adev->mode_info.crtcs[crtc_index] = acrtc; - drm_crtc_enable_color_mgmt(&acrtc->base, MAX_COLOR_LUT_ENTRIES, - true, MAX_COLOR_LUT_ENTRIES); + + res = drm_crtc_enable_color_mgmt(&acrtc->base, MAX_COLOR_LUT_ENTRIES, + true, MAX_COLOR_LUT_ENTRIES, + BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT); + if (res) { + drm_crtc_cleanup(&acrtc->base); + goto fail; + } + drm_mode_crtc_set_gamma_size(&acrtc->base, MAX_COLOR_LEGACY_LUT_ENTRIES); return 0; diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c index 59172acb9738..f364d37232b5 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c @@ -626,7 +626,12 @@ static int komeda_crtc_add(struct komeda_kms_dev *kms, crtc->port = kcrtc->master->of_output_port; - drm_crtc_enable_color_mgmt(crtc, 0, true, KOMEDA_COLOR_LUT_SIZE); + err = drm_crtc_enable_color_mgmt(crtc, 0, true, KOMEDA_COLOR_LUT_SIZE, + BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT); + if (err) { + drm_crtc_cleanup(crtc); + return err; + } return err; } diff --git a/drivers/gpu/drm/arm/malidp_crtc.c b/drivers/gpu/drm/arm/malidp_crtc.c index 494075ddbef6..7af87002c375 100644 --- a/drivers/gpu/drm/arm/malidp_crtc.c +++ b/drivers/gpu/drm/arm/malidp_crtc.c @@ -552,7 +552,12 @@ int malidp_crtc_init(struct drm_device *drm) drm_crtc_helper_add(&malidp->crtc, &malidp_crtc_helper_funcs); drm_mode_crtc_set_gamma_size(&malidp->crtc, MALIDP_GAMMA_LUT_SIZE); /* No inverse-gamma: it is per-plane. */ - drm_crtc_enable_color_mgmt(&malidp->crtc, 0, true, MALIDP_GAMMA_LUT_SIZE); + ret = drm_crtc_enable_color_mgmt(&malidp->crtc, 0, true, MALIDP_GAMMA_LUT_SIZE, + BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT); + if (ret) { + drm_crtc_cleanup(&malidp->crtc); + return ret; + } malidp_se_set_enh_coeffs(malidp->dev); diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index b7bb90ae787f..d44a1d4fa475 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -992,7 +992,10 @@ static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev, if (ret) return ret; - drm_crtc_enable_color_mgmt(&dcrtc->crtc, 0, false, 256); + ret = drm_crtc_enable_color_mgmt(&dcrtc->crtc, 0, false, , + BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT); + if (ret) + return ret; return armada_overlay_plane_create(drm, 1 << dcrtc->num); diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c index 05ad75d155e8..e5911826d002 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c @@ -528,8 +528,11 @@ int atmel_hlcdc_crtc_create(struct drm_device *dev) drm_crtc_helper_add(&crtc->base, &lcdc_crtc_helper_funcs); drm_mode_crtc_set_gamma_size(&crtc->base, ATMEL_HLCDC_CLUT_SIZE); - drm_crtc_enable_color_mgmt(&crtc->base, 0, false, - ATMEL_HLCDC_CLUT_SIZE); + ret = drm_crtc_enable_color_mgmt(&crtc->base, 0, false, + ATMEL_HLCDC_CLUT_SIZE, + BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT); + if (ret) + goto fail; dc->crtc = &crtc->base; diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index daf62fb090a6..196544951ab7 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -147,12 +147,21 @@ u64 drm_color_ctm_s31_32_to_qm_n(u64 user_input, u32 m, u32 n) } EXPORT_SYMBOL(drm_color_ctm_s31_32_to_qm_n); +static const char * const tf_name[] = { + [DRM_TF_UNDEFINED] = "undefined", + [DRM_TF_SRGB] = "sRGB", + [DRM_TF_PQ2084] = "PQ2084", + [DRM_TF_1D_LUT] = "1D LUT", +}; + /** * drm_crtc_enable_color_mgmt - enable color management properties * @crtc: DRM CRTC * @degamma_lut_size: the size of the degamma lut (before CSC) * @has_ctm: whether to attach ctm_property for CSC matrix * @gamma_lut_size: the size of the gamma lut (after CSC) + * @supported_tfs: bitfield indicating supported transfer functions + * @default_tf: default output transfer function * * This function lets the driver enable the color correction * properties on a CRTC. This includes 3 degamma, csc and gamma @@ -162,13 +171,27 @@ EXPORT_SYMBOL(drm_color_ctm_s31_32_to_qm_n); * their size is not 0 and ctm_property is only attached if has_ctm is * true. */ -void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc, +bool drm_crtc_enable_color_mgmt(struct drm_crtc *crtc, uint degamma_lut_size, bool has_ctm, - uint gamma_lut_size) + uint gamma_lut_size, + u32 supported_tfs, + enum drm_transfer_function default_tf) { struct drm_device *dev = crtc->dev; struct drm_mode_config *config = &dev->mode_config; + struct drm_property *prop; + struct drm_prop_enum_list enum_list[DRM_TF_MAX]; + int i, len; + + if (WARN_ON(supported_tfs == 0 || + (supported_tfs & -BIT(DRM_TF_MAX)) != 0 || + (supported_tfs & BIT(default_tf)) == 0)) + return -EINVAL; + + if (!!(supported_tfs & BIT(DRM_TF_1D_LUT)) != + !!(degamma_lut_size || gamma_lut_size)) + return -EINVAL; if (degamma_lut_size) { drm_object_attach_property(&crtc->base, @@ -189,6 +212,28 @@ void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc, config->gamma_lut_size_property, gamma_lut_size); } + + len = 0; + for (i = 0; i < DRM_TF_MAX; i++) { + if ((supported_tfs & BIT(i)) == 0) + continue; + + enum_list[len].type = i; + enum_list[len].name = tf_name[i]; + len++; + } + + prop = drm_property_create_enum(dev, 0, "OUT TRANSFER_FUNCTION", + enum_list, len); + if (!prop) + return -ENOMEM; + crtc->out_transfer_function_property = prop; + drm_object_attach_property(&crtc->base, prop, default_tf); + if (crtc->state) + crtc->state->out_transfer_function = default_tf; + + return 0; + } EXPORT_SYMBOL(drm_crtc_enable_color_mgmt); @@ -481,11 +526,6 @@ static const char * const color_range_name[] = { [DRM_COLOR_YCBCR_LIMITED_RANGE] = "YCbCr limited range", }; -static const char * const tf_name[] = { - [DRM_TF_UNDEFINED] = "undefined", - [DRM_TF_SRGB] = "sRGB", - [DRM_TF_PQ2084] = "PQ2084", -}; /** * drm_get_color_encoding_name - return a string for color encoding * @encoding: color encoding to compute name of diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index dab892d2251b..a9332080efe5 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -2093,7 +2093,7 @@ static void icl_read_luts(struct intel_crtc_state *crtc_state) } } -void intel_color_init(struct intel_crtc *crtc) +bool intel_color_init(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); bool has_ctm = INTEL_INFO(dev_priv)->color.degamma_lut_size != 0; @@ -2150,8 +2150,9 @@ void intel_color_init(struct intel_crtc *crtc) } } - drm_crtc_enable_color_mgmt(&crtc->base, - INTEL_INFO(dev_priv)->color.degamma_lut_size, - has_ctm, - INTEL_INFO(dev_priv)->color.gamma_lut_size); + return drm_crtc_enable_color_mgmt(&crtc->base, + INTEL_INFO(dev_priv)->color.degamma_lut_size, + has_ctm, + INTEL_INFO(dev_priv)->color.gamma_lut_size, + BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT); } diff --git a/drivers/gpu/drm/i915/display/intel_color.h b/drivers/gpu/drm/i915/display/intel_color.h index 173727aaa24d..a8e015acc60c 100644 --- a/drivers/gpu/drm/i915/display/intel_color.h +++ b/drivers/gpu/drm/i915/display/intel_color.h @@ -12,7 +12,7 @@ struct intel_crtc_state; struct intel_crtc; struct drm_property_blob; -void intel_color_init(struct intel_crtc *crtc); +bool intel_color_init(struct intel_crtc *crtc); int intel_color_check(struct intel_crtc_state *crtc_state); void intel_color_commit(const struct intel_crtc_state *crtc_state); void intel_color_load_luts(const struct intel_crtc_state *crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c index 95ff1707b4bd..0846fb4ef14e 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc.c +++ b/drivers/gpu/drm/i915/display/intel_crtc.c @@ -340,7 +340,9 @@ int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe) BIT(DRM_SCALING_FILTER_DEFAULT) | BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR)); - intel_color_init(crtc); + ret = intel_color_init(crtc); + if (ret) + goto fail; intel_crtc_crc_init(crtc); diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index 5244f4763477..f21fdd7e5f2a 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -1017,8 +1017,13 @@ static int ingenic_drm_bind(struct device *dev, bool has_components) return ret; } - drm_crtc_enable_color_mgmt(&priv->crtc, 0, false, - ARRAY_SIZE(priv->dma_hwdescs->palette)); + ret = drm_crtc_enable_color_mgmt(&priv->crtc, 0, false, + ARRAY_SIZE(priv->dma_hwdescs->palette), + BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT); + if (ret) { + dev_err(dev, "Failed to init color management: %i\n", ret); + return ret; + } if (soc_info->has_osd) { drm_plane_helper_add(&priv->f0, diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index 474efb844249..d2496ad16931 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -827,7 +827,13 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, if (gamma_lut_size) drm_mode_crtc_set_gamma_size(&mtk_crtc->base, gamma_lut_size); - drm_crtc_enable_color_mgmt(&mtk_crtc->base, 0, has_ctm, gamma_lut_size); + ret = drm_crtc_enable_color_mgmt(&mtk_crtc->base, 0, has_ctm, gamma_lut_size, + BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT); + if (ret) { + drm_crtc_cleanup(mtk_crtc->base); + kfree(mtk_crtc); + return ret; + priv->num_pipes++; mutex_init(&mtk_crtc->hw_lock); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index 9a5c70c87cc8..9b7e947e8c8b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -1337,6 +1337,7 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane, struct drm_crtc *crtc = NULL; struct dpu_crtc *dpu_crtc = NULL; int i; + int ret = 0; dpu_crtc = kzalloc(sizeof(*dpu_crtc), GFP_KERNEL); if (!dpu_crtc) @@ -1365,7 +1366,13 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane, drm_crtc_helper_add(crtc, &dpu_crtc_helper_funcs); - drm_crtc_enable_color_mgmt(crtc, 0, true, 0); + ret = drm_crtc_enable_color_mgmt(crtc, 0, true, 0, + BIT(DRM_TF_UNDEFINED), DRM_TF_UNDEFINED); + if (ret) { + drm_crtc_cleanup(crtc); + kfree(dpu_crtc); + return ERR_PTR(ret); + } /* save user friendly CRTC name for later */ snprintf(dpu_crtc->name, DPU_CRTC_NAME_SIZE, "crtc%u", crtc->base.id); diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.c b/drivers/gpu/drm/nouveau/dispnv50/head.c index ec361d17e900..f97b3f70152b 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/head.c +++ b/drivers/gpu/drm/nouveau/dispnv50/head.c @@ -589,9 +589,16 @@ nv50_head_create(struct drm_device *dev, int index) drm_crtc_helper_add(crtc, &nv50_head_help); /* Keep the legacy gamma size at 256 to avoid compatibility issues */ drm_mode_crtc_set_gamma_size(crtc, 256); - drm_crtc_enable_color_mgmt(crtc, base->func->ilut_size, - disp->disp->object.oclass >= GF110_DISP, - head->func->olut_size); + ret = drm_crtc_enable_color_mgmt(crtc, base->func->ilut_size, + disp->disp->object.oclass >= GF110_DISP, + head->func->olut_size, + BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT); + if (ret) { + drm_crtc_cleanup(crtc); + kfree(head); + return ERR_PTR(ret); + } + if (head->func->olut_set) { ret = nv50_lut_init(disp, &drm->client.mmu, &head->olut); diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 06a719c104f4..a618b3338c38 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -839,7 +839,15 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, if (dispc_mgr_gamma_size(priv->dispc, channel)) { unsigned int gamma_lut_size = 256; - drm_crtc_enable_color_mgmt(crtc, gamma_lut_size, true, 0); + ret = drm_crtc_enable_color_mgmt(crtc, gamma_lut_size, true, 0, + BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT); + if (ret) { + dev_err(dev->dev, "$s(): could not init color management for: %s\n", + __func__, pipe->output->name); + drm_crtc_cleanup(crtc); + kfree(omap_crtc); + return ERR_PTR(ret); + } drm_mode_crtc_set_gamma_size(crtc, gamma_lut_size); } diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index ea7e39d03545..02d8737e6603 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -1263,7 +1263,12 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int swindex, rgrp->cmms_mask |= BIT(hwindex % 2); drm_mode_crtc_set_gamma_size(crtc, CM2_LUT_SIZE); - drm_crtc_enable_color_mgmt(crtc, 0, false, CM2_LUT_SIZE); + ret = drm_crtc_enable_color_mgmt(crtc, 0, false, CM2_LUT_SIZE, + BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT); + if (ret) { + drm_crtc_cleanup(crtc); + return ret; + } } drm_crtc_helper_add(crtc, &crtc_helper_funcs); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index f5b9028a16a3..68d3a7b1f041 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -1817,7 +1817,10 @@ static int vop_create_crtc(struct vop *vop) drm_crtc_helper_add(crtc, &vop_crtc_helper_funcs); if (vop->lut_regs) { drm_mode_crtc_set_gamma_size(crtc, vop_data->lut_size); - drm_crtc_enable_color_mgmt(crtc, 0, false, vop_data->lut_size); + ret = drm_crtc_enable_color_mgmt(crtc, 0, false, vop_data->lut_size, + BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT); + if (ret) + goto err_cleanup_crtc; } /* diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c index 08b71248044d..ffdf7114f50a 100644 --- a/drivers/gpu/drm/stm/ltdc.c +++ b/drivers/gpu/drm/stm/ltdc.c @@ -1035,7 +1035,13 @@ static int ltdc_crtc_init(struct drm_device *ddev, struct drm_crtc *crtc) drm_crtc_helper_add(crtc, <dc_crtc_helper_funcs); drm_mode_crtc_set_gamma_size(crtc, CLUT_SIZE); - drm_crtc_enable_color_mgmt(crtc, 0, false, CLUT_SIZE); + ret = drm_crtc_enable_color_mgmt(crtc, 0, false, CLUT_SIZE, + BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT); + if (ret) { + DRM_ERROR("Can not initialize color management\n"); + drm_crtc_cleanup(crtc); + goto cleanup; + } DRM_DEBUG_DRIVER("CRTC:%d created\n", crtc->base.id); diff --git a/drivers/gpu/drm/tidss/tidss_crtc.c b/drivers/gpu/drm/tidss/tidss_crtc.c index 2218da3b3ca3..34ed098887bc 100644 --- a/drivers/gpu/drm/tidss/tidss_crtc.c +++ b/drivers/gpu/drm/tidss/tidss_crtc.c @@ -439,7 +439,14 @@ struct tidss_crtc *tidss_crtc_create(struct tidss_device *tidss, if (tidss->feat->vp_feat.color.gamma_size) gamma_lut_size = 256; - drm_crtc_enable_color_mgmt(crtc, 0, has_ctm, gamma_lut_size); + ret = drm_crtc_enable_color_mgmt(crtc, 0, has_ctm, gamma_lut_size, + BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT); + if (ret) { + drm_crtc_cleanup(crtc); + kfree(tcrtc); + return ERR_PTR(ret); + } + if (gamma_lut_size) drm_mode_crtc_set_gamma_size(crtc, gamma_lut_size); diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 18f5009ce90e..3bb2c0dba09a 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -1118,12 +1118,24 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc, if (!vc4->hvs->hvs5) { drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r)); - drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size); + ret = drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size, + BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT); + if (ret) { + dev_err(drm->dev, "failed to enable color management\n"); + drm_crtc_cleanup(crtc); + return ret; + } /* We support CTM, but only for one CRTC at a time. It's therefore * implemented as private driver state in vc4_kms, not here. */ - drm_crtc_enable_color_mgmt(crtc, 0, true, crtc->gamma_size); + ret = drm_crtc_enable_color_mgmt(crtc, 0, true, crtc->gamma_size, + BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT); + if (ret) { + dev_err(drm->dev, "failed to enable color management\n"); + drm_crtc_cleanup(crtc); + return ret; + } } for (i = 0; i < crtc->gamma_size; i++) { diff --git a/include/drm/drm_color_mgmt.h b/include/drm/drm_color_mgmt.h index 370bbc55b744..408561acdb3d 100644 --- a/include/drm/drm_color_mgmt.h +++ b/include/drm/drm_color_mgmt.h @@ -54,10 +54,29 @@ static inline u32 drm_color_lut_extract(u32 user_input, int bit_precision) u64 drm_color_ctm_s31_32_to_qm_n(u64 user_input, u32 m, u32 n); -void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc, +/** + * enum drm_transfer_function - common transfer function used for sdr/hdr formats + * + * DRM_TF_UNDEFINED - The legacy case where a TF in and out of the blending + * space is undefined + * DRM_TF_SRGB - Based on gamma curve and is used for printer/monitors/web + * DRM_TF_PQ2084 - Used for HDR and allows for up to 10,000 nit support. + * DRM_TF_1D_LUT - Use 1D gamma/degamma LUTs (currently only defined on crtc) +*/ +enum drm_transfer_function { + DRM_TF_UNDEFINED, + DRM_TF_SRGB, + DRM_TF_PQ2084, + DRM_TF_1D_LUT, + DRM_TF_MAX, +}; + +bool drm_crtc_enable_color_mgmt(struct drm_crtc *crtc, uint degamma_lut_size, bool has_ctm, - uint gamma_lut_size); + uint gamma_lut_size, + u32 supported_tfs, + enum drm_transfer_function default_tf); int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, int gamma_size); @@ -87,20 +106,6 @@ enum drm_color_range { DRM_COLOR_RANGE_MAX, }; -/** - * enum drm_transfer_function - common transfer function used for sdr/hdr formats - * - * DRM_TF_UNDEFINED - The legacy case where a TF in and out of the blending - * space is undefined - * DRM_TF_SRGB - Based on gamma curve and is used for printer/monitors/web - * DRM_TF_PQ2084 - Used for HDR and allows for up to 10,000 nit support. -*/ -enum drm_transfer_function { - DRM_TF_UNDEFINED, - DRM_TF_SRGB, - DRM_TF_PQ2084, - DRM_TF_MAX, -}; int drm_plane_create_color_properties(struct drm_plane *plane, u32 supported_encodings, u32 supported_ranges, diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 13eeba2a750a..35580dd36294 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -288,6 +288,15 @@ struct drm_crtc_state { */ struct drm_property_blob *gamma_lut; + /** + * @out_transfer_function: + * + * Transfer function for conversion from blending space to + * display space. DRM_TF_1D_LUT can be specified to use the + * gamma/degamma LUTs from mode_config instead. + */ + enum drm_transfer_function out_transfer_function; + /** * @target_vblank: * @@ -1096,6 +1105,17 @@ struct drm_crtc { */ struct drm_property *scaling_filter_property; + /** + * @out_transfer_function_property: + * + * Optional "OUT TRANSFER FUNCTION" enum property for specifying + * an output transfer function, i.e. a TF to convert from + * blending space to luminance space. Use DRM_TF_1D_LUT to + * indicate using the 1D gamma/degamma LUTs instead of a + * named transfer function. + */ + struct drm_property *out_transfer_function_property; + /** * @state: * -- 2.32.0