Message ID | 20231005171527.203657-13-mwen@igalia.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | drm/amd/display: add AMD driver-specific properties for color mgmt | expand |
On 2023-10-05 13:15, Melissa Wen wrote: > Add AMD pre-defined transfer function property to default DRM CRTC gamma > to convert to wire encoding with or without a user gamma LUT. There is > no post-blending regamma ROM for pre-defined TF. When setting Gamma TF > (!= Identity) and LUT at the same time, the color module will combine > the pre-defined TF and the custom LUT values into the LUT that's > actually programmed. > > v2: > - enable CRTC prop in the end of driver-specific prop sequence > - define inverse EOTFs as supported regamma TFs > - reword driver-specific function doc to remove shaper/3D LUT > > v3: > - spell out TF+LUT behavior in the commit and comments (Harry) > > Co-developed-by: Joshua Ashton <joshua@froggi.es> > Signed-off-by: Joshua Ashton <joshua@froggi.es> > Signed-off-by: Melissa Wen <mwen@igalia.com> Reviewed-by: Harry Wentland <harry.wentland@amd.com> Harry > --- > drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 7 ++ > .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 8 +++ > .../amd/display/amdgpu_dm/amdgpu_dm_color.c | 7 ++ > .../amd/display/amdgpu_dm/amdgpu_dm_crtc.c | 72 +++++++++++++++++++ > 4 files changed, 94 insertions(+) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h > index dee35d208493..071cc10bfd90 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h > @@ -424,6 +424,13 @@ struct amdgpu_mode_info { > * from a combination of pre-defined TF and the custom 1D LUT). > */ > struct drm_property *plane_blend_tf_property; > + /* @regamma_tf_property: Transfer function for CRTC regamma > + * (post-blending). Possible values are defined by `enum > + * amdgpu_transfer_function`. There is no regamma ROM, but we can use > + * AMD color modules to program LUT parameters from predefined TF (or > + * from a combination of pre-defined TF and the custom 1D LUT). > + */ > + struct drm_property *regamma_tf_property; > }; > > #define AMDGPU_MAX_BL_LEVEL 0xFF > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h > index 1b96c742d747..c138457ff12e 100644 > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h > @@ -836,6 +836,14 @@ struct dm_crtc_state { > struct dc_info_packet vrr_infopacket; > > int abm_level; > + > + /** > + * @regamma_tf: > + * > + * Pre-defined transfer function for converting internal FB -> wire > + * encoding. > + */ > + enum amdgpu_transfer_function regamma_tf; > }; > > #define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base) > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c > index 82c554662faa..2ecfa0e886e8 100644 > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c > @@ -294,6 +294,13 @@ amdgpu_dm_create_color_properties(struct amdgpu_device *adev) > return -ENOMEM; > adev->mode_info.plane_blend_tf_property = prop; > > + prop = amdgpu_create_tf_property(adev_to_drm(adev), > + "AMD_CRTC_REGAMMA_TF", > + amdgpu_inv_eotf); > + if (!prop) > + return -ENOMEM; > + adev->mode_info.regamma_tf_property = prop; > + > return 0; > } > #endif > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c > index 440fc0869a34..d746f0aa0f11 100644 > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c > @@ -253,6 +253,7 @@ static struct drm_crtc_state *dm_crtc_duplicate_state(struct drm_crtc *crtc) > state->freesync_config = cur->freesync_config; > state->cm_has_degamma = cur->cm_has_degamma; > state->cm_is_degamma_srgb = cur->cm_is_degamma_srgb; > + state->regamma_tf = cur->regamma_tf; > state->crc_skip_count = cur->crc_skip_count; > state->mpo_requested = cur->mpo_requested; > /* TODO Duplicate dc_stream after objects are stream object is flattened */ > @@ -289,6 +290,70 @@ static int amdgpu_dm_crtc_late_register(struct drm_crtc *crtc) > } > #endif > > +#ifdef AMD_PRIVATE_COLOR > +/** > + * drm_crtc_additional_color_mgmt - enable additional color properties > + * @crtc: DRM CRTC > + * > + * This function lets the driver enable post-blending CRTC regamma transfer > + * function property in addition to DRM CRTC gamma LUT. Default value means > + * linear transfer function, which is the default CRTC gamma LUT behaviour > + * without this property. > + */ > +static void > +dm_crtc_additional_color_mgmt(struct drm_crtc *crtc) > +{ > + struct amdgpu_device *adev = drm_to_adev(crtc->dev); > + > + if(adev->dm.dc->caps.color.mpc.ogam_ram) > + drm_object_attach_property(&crtc->base, > + adev->mode_info.regamma_tf_property, > + AMDGPU_TRANSFER_FUNCTION_DEFAULT); > +} > + > +static int > +amdgpu_dm_atomic_crtc_set_property(struct drm_crtc *crtc, > + struct drm_crtc_state *state, > + struct drm_property *property, > + uint64_t val) > +{ > + struct amdgpu_device *adev = drm_to_adev(crtc->dev); > + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(state); > + > + if (property == adev->mode_info.regamma_tf_property) { > + if (acrtc_state->regamma_tf != val) { > + acrtc_state->regamma_tf = val; > + acrtc_state->base.color_mgmt_changed |= 1; > + } > + } else { > + drm_dbg_atomic(crtc->dev, > + "[CRTC:%d:%s] unknown property [PROP:%d:%s]]\n", > + crtc->base.id, crtc->name, > + property->base.id, property->name); > + return -EINVAL; > + } > + > + return 0; > +} > + > +static int > +amdgpu_dm_atomic_crtc_get_property(struct drm_crtc *crtc, > + const struct drm_crtc_state *state, > + struct drm_property *property, > + uint64_t *val) > +{ > + struct amdgpu_device *adev = drm_to_adev(crtc->dev); > + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(state); > + > + if (property == adev->mode_info.regamma_tf_property) > + *val = acrtc_state->regamma_tf; > + else > + return -EINVAL; > + > + return 0; > +} > +#endif > + > /* Implemented only the options currently available for the driver */ > static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = { > .reset = dm_crtc_reset_state, > @@ -307,6 +372,10 @@ static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = { > #if defined(CONFIG_DEBUG_FS) > .late_register = amdgpu_dm_crtc_late_register, > #endif > +#ifdef AMD_PRIVATE_COLOR > + .atomic_set_property = amdgpu_dm_atomic_crtc_set_property, > + .atomic_get_property = amdgpu_dm_atomic_crtc_get_property, > +#endif > }; > > static void dm_crtc_helper_disable(struct drm_crtc *crtc) > @@ -470,6 +539,9 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, > > drm_mode_crtc_set_gamma_size(&acrtc->base, MAX_COLOR_LEGACY_LUT_ENTRIES); > > +#ifdef AMD_PRIVATE_COLOR > + dm_crtc_additional_color_mgmt(&acrtc->base); > +#endif > return 0; > > fail:
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index dee35d208493..071cc10bfd90 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -424,6 +424,13 @@ struct amdgpu_mode_info { * from a combination of pre-defined TF and the custom 1D LUT). */ struct drm_property *plane_blend_tf_property; + /* @regamma_tf_property: Transfer function for CRTC regamma + * (post-blending). Possible values are defined by `enum + * amdgpu_transfer_function`. There is no regamma ROM, but we can use + * AMD color modules to program LUT parameters from predefined TF (or + * from a combination of pre-defined TF and the custom 1D LUT). + */ + struct drm_property *regamma_tf_property; }; #define AMDGPU_MAX_BL_LEVEL 0xFF diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index 1b96c742d747..c138457ff12e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -836,6 +836,14 @@ struct dm_crtc_state { struct dc_info_packet vrr_infopacket; int abm_level; + + /** + * @regamma_tf: + * + * Pre-defined transfer function for converting internal FB -> wire + * encoding. + */ + enum amdgpu_transfer_function regamma_tf; }; #define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c index 82c554662faa..2ecfa0e886e8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c @@ -294,6 +294,13 @@ amdgpu_dm_create_color_properties(struct amdgpu_device *adev) return -ENOMEM; adev->mode_info.plane_blend_tf_property = prop; + prop = amdgpu_create_tf_property(adev_to_drm(adev), + "AMD_CRTC_REGAMMA_TF", + amdgpu_inv_eotf); + if (!prop) + return -ENOMEM; + adev->mode_info.regamma_tf_property = prop; + return 0; } #endif diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c index 440fc0869a34..d746f0aa0f11 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c @@ -253,6 +253,7 @@ static struct drm_crtc_state *dm_crtc_duplicate_state(struct drm_crtc *crtc) state->freesync_config = cur->freesync_config; state->cm_has_degamma = cur->cm_has_degamma; state->cm_is_degamma_srgb = cur->cm_is_degamma_srgb; + state->regamma_tf = cur->regamma_tf; state->crc_skip_count = cur->crc_skip_count; state->mpo_requested = cur->mpo_requested; /* TODO Duplicate dc_stream after objects are stream object is flattened */ @@ -289,6 +290,70 @@ static int amdgpu_dm_crtc_late_register(struct drm_crtc *crtc) } #endif +#ifdef AMD_PRIVATE_COLOR +/** + * drm_crtc_additional_color_mgmt - enable additional color properties + * @crtc: DRM CRTC + * + * This function lets the driver enable post-blending CRTC regamma transfer + * function property in addition to DRM CRTC gamma LUT. Default value means + * linear transfer function, which is the default CRTC gamma LUT behaviour + * without this property. + */ +static void +dm_crtc_additional_color_mgmt(struct drm_crtc *crtc) +{ + struct amdgpu_device *adev = drm_to_adev(crtc->dev); + + if(adev->dm.dc->caps.color.mpc.ogam_ram) + drm_object_attach_property(&crtc->base, + adev->mode_info.regamma_tf_property, + AMDGPU_TRANSFER_FUNCTION_DEFAULT); +} + +static int +amdgpu_dm_atomic_crtc_set_property(struct drm_crtc *crtc, + struct drm_crtc_state *state, + struct drm_property *property, + uint64_t val) +{ + struct amdgpu_device *adev = drm_to_adev(crtc->dev); + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(state); + + if (property == adev->mode_info.regamma_tf_property) { + if (acrtc_state->regamma_tf != val) { + acrtc_state->regamma_tf = val; + acrtc_state->base.color_mgmt_changed |= 1; + } + } else { + drm_dbg_atomic(crtc->dev, + "[CRTC:%d:%s] unknown property [PROP:%d:%s]]\n", + crtc->base.id, crtc->name, + property->base.id, property->name); + return -EINVAL; + } + + return 0; +} + +static int +amdgpu_dm_atomic_crtc_get_property(struct drm_crtc *crtc, + const struct drm_crtc_state *state, + struct drm_property *property, + uint64_t *val) +{ + struct amdgpu_device *adev = drm_to_adev(crtc->dev); + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(state); + + if (property == adev->mode_info.regamma_tf_property) + *val = acrtc_state->regamma_tf; + else + return -EINVAL; + + return 0; +} +#endif + /* Implemented only the options currently available for the driver */ static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = { .reset = dm_crtc_reset_state, @@ -307,6 +372,10 @@ static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = { #if defined(CONFIG_DEBUG_FS) .late_register = amdgpu_dm_crtc_late_register, #endif +#ifdef AMD_PRIVATE_COLOR + .atomic_set_property = amdgpu_dm_atomic_crtc_set_property, + .atomic_get_property = amdgpu_dm_atomic_crtc_get_property, +#endif }; static void dm_crtc_helper_disable(struct drm_crtc *crtc) @@ -470,6 +539,9 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, drm_mode_crtc_set_gamma_size(&acrtc->base, MAX_COLOR_LEGACY_LUT_ENTRIES); +#ifdef AMD_PRIVATE_COLOR + dm_crtc_additional_color_mgmt(&acrtc->base); +#endif return 0; fail: