On 2025-09-17 15:49, Melissa Wen wrote:
> 
> 
> On 12/09/2025 15:50, Harry Wentland wrote:
>>
>> On 2025-09-11 13:21, Melissa Wen wrote:
>>> Don't update DC stream color components during atomic check. The driver
>>> will continue validating the new CRTC color state but will not change DC
>>> stream color components. The DC stream color state will only be
>>> programmed at commit time in the `atomic_setup_commit` stage.
>>>
>>> It fixes gamma LUT loss reported by KDE users when changing brightness
>>> quickly or changing Display settings (such as overscan) with nightlight
>>> on and HDR. As KWin can do a test commit with color settings different
>>> from those that should be applied in a non-test-only commit, if the
>>> driver changes DC stream color state in atomic check, this state can be
>>> eventually HW programmed in commit tail, instead of the respective state
>>> set by the non-blocking commit.
> Hello,
> 
> I'm not sure if this series was already applied somewhere. I don't see it in 
> asdn.
> 

Applied. It should land soon after going through our CI pipeline.

Harry

> Can someone double check?
> 
> Thanks,
> 
> Melissa
> 
>>>
>>> Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4444
>>> Reported-by: Xaver Hugl <xaver.h...@gmail.com>
>>> Reviewed-by: Harry Wentland <harry.wentl...@amd.com> #v2
>>> Signed-off-by: Melissa Wen <m...@igalia.com>
>>> ---
>>>   .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  2 +-
>>>   .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  2 +
>>>   .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 86 ++++++++++++++-----
>>>   3 files changed, 66 insertions(+), 24 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 f6462ff7251f..50b3bd0e32dd 100644
>>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>>> @@ -11118,7 +11118,7 @@ static int dm_update_crtc_state(struct 
>>> amdgpu_display_manager *dm,
>>>       if (dm_new_crtc_state->base.color_mgmt_changed ||
>>>           dm_old_crtc_state->regamma_tf != dm_new_crtc_state->regamma_tf ||
>>>           drm_atomic_crtc_needs_modeset(new_crtc_state)) {
>>> -        ret = amdgpu_dm_update_crtc_color_mgmt(dm_new_crtc_state);
>>> +        ret = amdgpu_dm_check_crtc_color_mgmt(dm_new_crtc_state, true);
>>>           if (ret)
>>>               goto fail;
>>>       }
>>> 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 ce74125c713e..69125c3f08d5 100644
>>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
>>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
>>> @@ -1041,6 +1041,8 @@ void amdgpu_dm_init_color_mod(void);
>>>   int amdgpu_dm_create_color_properties(struct amdgpu_device *adev);
>>>   int amdgpu_dm_verify_lut_sizes(const struct drm_crtc_state *crtc_state);
>>>   int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc);
>>> +int amdgpu_dm_check_crtc_color_mgmt(struct dm_crtc_state *crtc,
>>> +                    bool check_only);
>>>   int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
>>>                         struct drm_plane_state *plane_state,
>>>                         struct dc_plane_state *dc_plane_state);
>>> 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 c7387af725d6..427bf8877df7 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
>>> @@ -566,12 +566,11 @@ static int __set_output_tf(struct dc_transfer_func 
>>> *func,
>>>       return res ? 0 : -ENOMEM;
>>>   }
>>>   -static int amdgpu_dm_set_atomic_regamma(struct dc_stream_state *stream,
>>> +static int amdgpu_dm_set_atomic_regamma(struct dc_transfer_func *out_tf,
>>>                       const struct drm_color_lut *regamma_lut,
>>>                       uint32_t regamma_size, bool has_rom,
>>>                       enum dc_transfer_func_predefined tf)
>>>   {
>>> -    struct dc_transfer_func *out_tf = &stream->out_transfer_func;
>>>       int ret = 0;
>>>         if (regamma_size || tf != TRANSFER_FUNCTION_LINEAR) {
>>> @@ -885,33 +884,33 @@ int amdgpu_dm_verify_lut_sizes(const struct 
>>> drm_crtc_state *crtc_state)
>>>   }
>>>     /**
>>> - * amdgpu_dm_update_crtc_color_mgmt: Maps DRM color management to DC 
>>> stream.
>>> + * amdgpu_dm_check_crtc_color_mgmt: Check if DRM color props are 
>>> programmable by DC.
>>>    * @crtc: amdgpu_dm crtc state
>>> + * @check_only: only check color state without update dc stream
>>>    *
>>> - * With no plane level color management properties we're free to use any
>>> - * of the HW blocks as long as the CRTC CTM always comes before the
>>> - * CRTC RGM and after the CRTC DGM.
>>> - *
>>> - * - The CRTC RGM block will be placed in the RGM LUT block if it is 
>>> non-linear.
>>> - * - The CRTC DGM block will be placed in the DGM LUT block if it is 
>>> non-linear.
>>> - * - The CRTC CTM will be placed in the gamut remap block if it is 
>>> non-linear.
>>> + * This function just verifies CRTC LUT sizes, if there is enough space for
>>> + * output transfer function and if its parameters can be calculated by AMD
>>> + * color module. It also adjusts some settings for programming CRTC 
>>> degamma at
>>> + * plane stage, using plane DGM block.
>>>    *
>>>    * The RGM block is typically more fully featured and accurate across
>>>    * all ASICs - DCE can't support a custom non-linear CRTC DGM.
>>>    *
>>>    * For supporting both plane level color management and CRTC level color
>>> - * management at once we have to either restrict the usage of CRTC 
>>> properties
>>> - * or blend adjustments together.
>>> + * management at once we have to either restrict the usage of some CRTC
>>> + * properties or blend adjustments together.
>>>    *
>>>    * Returns:
>>> - * 0 on success. Error code if setup fails.
>>> + * 0 on success. Error code if validation fails.
>>>    */
>>> -int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc)
>>> +
>>> +int amdgpu_dm_check_crtc_color_mgmt(struct dm_crtc_state *crtc,
>>> +                    bool check_only)
>>>   {
>>>       struct dc_stream_state *stream = crtc->stream;
>>>       struct amdgpu_device *adev = drm_to_adev(crtc->base.state->dev);
>>>       bool has_rom = adev->asic_type <= CHIP_RAVEN;
>>> -    struct drm_color_ctm *ctm = NULL;
>>> +    struct dc_transfer_func *out_tf;
>>>       const struct drm_color_lut *degamma_lut, *regamma_lut;
>>>       uint32_t degamma_size, regamma_size;
>>>       bool has_regamma, has_degamma;
>>> @@ -940,6 +939,14 @@ int amdgpu_dm_update_crtc_color_mgmt(struct 
>>> dm_crtc_state *crtc)
>>>       crtc->cm_has_degamma = false;
>>>       crtc->cm_is_degamma_srgb = false;
>>>   +    if (check_only) {
>>> +        out_tf = kvzalloc(sizeof(*out_tf), GFP_KERNEL);
>>> +        if (!out_tf)
>>> +            return -ENOMEM;
>>> +    } else {
>>> +        out_tf = &stream->out_transfer_func;
>>> +    }
>>> +
>>>       /* Setup regamma and degamma. */
>>>       if (is_legacy) {
>>>           /*
>>> @@ -954,8 +961,8 @@ int amdgpu_dm_update_crtc_color_mgmt(struct 
>>> dm_crtc_state *crtc)
>>>            * inverse color ramp in legacy userspace.
>>>            */
>>>           crtc->cm_is_degamma_srgb = true;
>>> -        stream->out_transfer_func.type = TF_TYPE_DISTRIBUTED_POINTS;
>>> -        stream->out_transfer_func.tf = TRANSFER_FUNCTION_SRGB;
>>> +        out_tf->type = TF_TYPE_DISTRIBUTED_POINTS;
>>> +        out_tf->tf = TRANSFER_FUNCTION_SRGB;
>>>           /*
>>>            * Note: although we pass has_rom as parameter here, we never
>>>            * actually use ROM because the color module only takes the ROM
>>> @@ -963,16 +970,12 @@ int amdgpu_dm_update_crtc_color_mgmt(struct 
>>> dm_crtc_state *crtc)
>>>            *
>>>            * See more in mod_color_calculate_regamma_params()
>>>            */
>>> -        r = __set_legacy_tf(&stream->out_transfer_func, regamma_lut,
>>> +        r = __set_legacy_tf(out_tf, regamma_lut,
>>>                       regamma_size, has_rom);
>>> -        if (r)
>>> -            return r;
>>>       } else {
>>>           regamma_size = has_regamma ? regamma_size : 0;
>>> -        r = amdgpu_dm_set_atomic_regamma(stream, regamma_lut,
>>> +        r = amdgpu_dm_set_atomic_regamma(out_tf, regamma_lut,
>>>                            regamma_size, has_rom, tf);
>>> -        if (r)
>>> -            return r;
>>>       }
>>>         /*
>>> @@ -981,6 +984,43 @@ int amdgpu_dm_update_crtc_color_mgmt(struct 
>>> dm_crtc_state *crtc)
>>>        * have to place the CTM in the OCSC in that case.
>>>        */
>>>       crtc->cm_has_degamma = has_degamma;
>>> +    if (check_only)
>>> +        kvfree(out_tf);
>>> +
>>> +    return r;
>>> +}
>>> +
>>> +/**
>>> + * amdgpu_dm_update_crtc_color_mgmt: Maps DRM color management to DC 
>>> stream.
>>> + * @crtc: amdgpu_dm crtc state
>>> + *
>>> + * With no plane level color management properties we're free to use any
>>> + * of the HW blocks as long as the CRTC CTM always comes before the
>>> + * CRTC RGM and after the CRTC DGM.
>>> + *
>>> + * - The CRTC RGM block will be placed in the RGM LUT block if it is 
>>> non-linear.
>>> + * - The CRTC DGM block will be placed in the DGM LUT block if it is 
>>> non-linear.
>>> + * - The CRTC CTM will be placed in the gamut remap block if it is 
>>> non-linear.
>>> + *
>>> + * The RGM block is typically more fully featured and accurate across
>>> + * all ASICs - DCE can't support a custom non-linear CRTC DGM.
>>> + *
>>> + * For supporting both plane level color management and CRTC level color
>>> + * management at once we have to either restrict the usage of CRTC 
>>> properties
>>> + * or blend adjustments together.
>>> + *
>>> + * Returns:
>>> + * 0 on success. Error code if setup fails.
>>> + */
>>> +int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc)
>>> +{
>>> +    struct dc_stream_state *stream = crtc->stream;
>>> +    struct drm_color_ctm *ctm = NULL;
>>> +    int ret;
>>> +
>>> +    ret = amdgpu_dm_check_crtc_color_mgmt(crtc, false);
>>> +    if (ret)
>>> +        return ret;
>> Thanks. I like it.
>>
>> Reviewed-by: Harry Wentland <harry.wentl...@amd.com>
>>
>> Harry
>>
>>>         /* Setup CRTC CTM. */
>>>       if (crtc->base.ctm) {
> 

Reply via email to