From: Melissa Wen <mwen@igalia.com>
To: airlied@gmail.com, alexander.deucher@amd.com, alex.hung@amd.com,
aurabindo.pillai@amd.com, christian.koenig@amd.com,
contact@emersion.fr, daniels@collabora.com,
harry.wentland@amd.com, louis.chauvet@bootlin.com,
maarten.lankhorst@linux.intel.com, mripard@kernel.org,
mwen@igalia.com, sebastian.wick@redhat.com, simona@ffwll.ch,
siqueira@igalia.com, sunpeng.li@amd.com, tzimmermann@suse.de
Cc: Uma Shankar <uma.shankar@intel.com>,
Chaitanya Kumar Borah <chaitanya.kumar.borah@intel.com>,
Xaver Hugl <xaver.hugl@kde.org>,
Pekka Paalanen <pekka.paalanen@collabora.com>,
Matthew Schwartz <matthew.schwartz@linux.dev>,
amd-gfx@lists.freedesktop.org, kernel-dev@igalia.com,
Rob Clark <robin.clark@oss.qualcomm.com>,
Dmitry Baryshkov <lumag@kernel.org>, Sean Paul <sean@poorly.run>,
Marijn Suijten <marijn.suijten@somainline.org>,
linux-arm-msm@vger.kernel.org, freedreno@lists.freedesktop.org,
intel-xe@lists.freedesktop.org, intel-gfx@lists.freedesktop.org,
dri-devel@lists.freedesktop.org
Subject: [PATCH v4 10/11] drm/amd/display: allow individual colorop changes
Date: Tue, 11 Aug 2026 18:45:59 +0200 [thread overview]
Message-ID: <20260811171011.184964-11-mwen@igalia.com> (raw)
In-Reply-To: <20260811171011.184964-1-mwen@igalia.com>
Every AMD colorop helper requires new colorop state to update a single
active colorop, i.e. if the userspace modifies a single property of a
colorop, but doesn't resubmit the whole color pipeline, the driver
silently falls back to the legacy color path, instead of just restore
colorop settings from committed state. Change all colorop helpers to get
the committed state if there's no new state for a given colorop. It
keeps walking in the active color pipeline and update a color block if
the related colorop changed.
Fixes: 9ba25915efba ("drm/amd/display: Add support for sRGB EOTF in DEGAM block")
Acked-by: Harry Wentland <harry.wentland@amd.com> #v3
Signed-off-by: Melissa Wen <mwen@igalia.com>
---
.../amd/display/amdgpu_dm/amdgpu_dm_color.c | 183 +++++++-----------
1 file changed, 66 insertions(+), 117 deletions(-)
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 c528daefac5e..f6a2af5d2e96 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
@@ -1550,24 +1550,13 @@ __set_dm_plane_colorop_degamma(struct drm_plane_state *plane_state,
struct dc_plane_state *dc_plane_state,
struct drm_colorop *colorop)
{
- struct drm_colorop *old_colorop;
- struct drm_colorop_state *colorop_state = NULL, *new_colorop_state;
+ struct drm_colorop_state *colorop_state;
struct drm_atomic_commit *state = plane_state->state;
- int i = 0;
-
- old_colorop = colorop;
/* 1st op: 1d curve - degamma */
- for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
- if (new_colorop_state->colorop == old_colorop &&
- (BIT(new_colorop_state->curve_1d_type) & amdgpu_dm_supported_degam_tfs)) {
- colorop_state = new_colorop_state;
- break;
- }
- }
-
+ colorop_state = drm_atomic_get_new_colorop_state(state, colorop);
if (!colorop_state)
- return -EINVAL;
+ colorop_state = colorop->state;
return __set_colorop_in_tf_1d_curve(dc_plane_state, colorop_state);
}
@@ -1577,43 +1566,37 @@ __set_dm_plane_colorop_3x4_matrix(struct drm_plane_state *plane_state,
struct dc_plane_state *dc_plane_state,
struct drm_colorop *colorop)
{
- struct drm_colorop *old_colorop;
- struct drm_colorop_state *colorop_state = NULL, *new_colorop_state;
+ struct drm_colorop_state *colorop_state;
struct drm_atomic_commit *state = plane_state->state;
const struct drm_device *dev = colorop->dev;
const struct drm_property_blob *blob;
struct drm_color_ctm_3x4 *ctm = NULL;
- int i = 0;
/* 3x4 matrix */
- old_colorop = colorop;
- for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
- if (new_colorop_state->colorop == old_colorop &&
- new_colorop_state->colorop->type == DRM_COLOROP_CTM_3X4) {
- colorop_state = new_colorop_state;
- break;
- }
+ colorop_state = drm_atomic_get_new_colorop_state(state, colorop);
+ if (!colorop_state)
+ colorop_state = colorop->state;
+
+ if (colorop_state->colorop->type != DRM_COLOROP_CTM_3X4)
+ return -EINVAL;
+
+ if (colorop_state->bypass) {
+ dc_plane_state->gamut_remap_matrix.enable_remap = false;
+ dc_plane_state->input_csc_color_matrix.enable_adjustment = false;
+ return 0;
}
- if (colorop_state && colorop->type == DRM_COLOROP_CTM_3X4) {
- if (colorop_state->bypass) {
- dc_plane_state->gamut_remap_matrix.enable_remap = false;
- dc_plane_state->input_csc_color_matrix.enable_adjustment = false;
- return 0;
- }
-
- drm_dbg(dev, "3x4 matrix colorop with ID: %d\n", colorop->base.id);
- blob = colorop_state->data;
- if (blob->length == sizeof(struct drm_color_ctm_3x4)) {
- ctm = (struct drm_color_ctm_3x4 *) blob->data;
- __drm_ctm_3x4_to_dc_matrix(ctm, dc_plane_state->gamut_remap_matrix.matrix);
- dc_plane_state->gamut_remap_matrix.enable_remap = true;
- dc_plane_state->input_csc_color_matrix.enable_adjustment = false;
- } else {
- drm_warn(dev, "blob->length (%zu) isn't equal to drm_color_ctm_3x4 (%zu)\n",
- blob->length, sizeof(struct drm_color_ctm_3x4));
- return -EINVAL;
- }
+ drm_dbg(dev, "3x4 matrix colorop with ID: %d\n", colorop->base.id);
+ blob = colorop_state->data;
+ if (blob->length == sizeof(struct drm_color_ctm_3x4)) {
+ ctm = (struct drm_color_ctm_3x4 *) blob->data;
+ __drm_ctm_3x4_to_dc_matrix(ctm, dc_plane_state->gamut_remap_matrix.matrix);
+ dc_plane_state->gamut_remap_matrix.enable_remap = true;
+ dc_plane_state->input_csc_color_matrix.enable_adjustment = false;
+ } else {
+ drm_warn(dev, "blob->length (%zu) isn't equal to drm_color_ctm_3x4 (%zu)\n",
+ blob->length, sizeof(struct drm_color_ctm_3x4));
+ return -EINVAL;
}
return 0;
@@ -1624,29 +1607,23 @@ __set_dm_plane_colorop_multiplier(struct drm_plane_state *plane_state,
struct dc_plane_state *dc_plane_state,
struct drm_colorop *colorop)
{
- struct drm_colorop *old_colorop;
- struct drm_colorop_state *colorop_state = NULL, *new_colorop_state;
+ struct drm_colorop_state *colorop_state;
struct drm_atomic_commit *state = plane_state->state;
const struct drm_device *dev = colorop->dev;
- int i = 0;
/* Multiplier */
- old_colorop = colorop;
- for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
- if (new_colorop_state->colorop == old_colorop &&
- new_colorop_state->colorop->type == DRM_COLOROP_MULTIPLIER) {
- colorop_state = new_colorop_state;
- break;
- }
- }
+ colorop_state = drm_atomic_get_new_colorop_state(state, colorop);
+ if (!colorop_state)
+ colorop_state = colorop->state;
- if (colorop_state && colorop->type == DRM_COLOROP_MULTIPLIER) {
- if (colorop_state->bypass) {
- dc_plane_state->hdr_mult = dc_fixpt_one;
- } else {
- drm_dbg(dev, "Multiplier colorop with ID: %d\n", colorop->base.id);
- dc_plane_state->hdr_mult = amdgpu_dm_fixpt_from_s3132(colorop_state->multiplier);
- }
+ if (colorop_state->colorop->type != DRM_COLOROP_MULTIPLIER)
+ return -EINVAL;
+
+ if (colorop_state->bypass) {
+ dc_plane_state->hdr_mult = dc_fixpt_one;
+ } else {
+ drm_dbg(dev, "Multiplier colorop with ID: %d\n", colorop->base.id);
+ dc_plane_state->hdr_mult = amdgpu_dm_fixpt_from_s3132(colorop_state->multiplier);
}
return 0;
@@ -1657,8 +1634,6 @@ __set_dm_plane_colorop_shaper(struct drm_plane_state *plane_state,
struct dc_plane_state *dc_plane_state,
struct drm_colorop *colorop)
{
- struct drm_colorop *old_colorop;
- struct drm_colorop_state *new_colorop_state;
struct drm_colorop_state *tf_state = NULL, *lut_state = NULL;
struct drm_atomic_commit *state = plane_state->state;
struct drm_colorop *lut_colorop;
@@ -1667,38 +1642,29 @@ __set_dm_plane_colorop_shaper(struct drm_plane_state *plane_state,
const struct drm_color_lut32 *shaper_lut;
struct drm_device *dev = colorop->dev;
u32 shaper_size;
- int i = 0, ret = 0;
+ int ret = 0;
tf->type = TF_TYPE_BYPASS;
dc_plane_state->cm.flags.bits.shaper_enable = 0;
/* 1D Curve - SHAPER TF: find state */
- old_colorop = colorop;
- for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
- if (new_colorop_state->colorop == old_colorop &&
- (BIT(new_colorop_state->curve_1d_type) & amdgpu_dm_supported_shaper_tfs)) {
- tf_state = new_colorop_state;
- break;
- }
- }
+ tf_state = drm_atomic_get_new_colorop_state(state, colorop);
+ if (!tf_state)
+ tf_state = colorop->state;
/* 1D LUT - SHAPER LUT: find state */
- lut_colorop = old_colorop->next;
+ lut_colorop = colorop->next;
if (!lut_colorop) {
drm_dbg(dev, "no Shaper LUT colorop found\n");
return -EINVAL;
}
- for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
- if (new_colorop_state->colorop == lut_colorop &&
- new_colorop_state->colorop->type == DRM_COLOROP_1D_LUT) {
- lut_state = new_colorop_state;
- break;
- }
- }
+ lut_state = drm_atomic_get_new_colorop_state(state, lut_colorop);
+ if (!lut_state)
+ lut_state = lut_colorop->state;
- if (tf_state && !tf_state->bypass) {
- drm_dbg(dev, "Shaper TF colorop with ID: %d\n", old_colorop->base.id);
+ if (!tf_state->bypass) {
+ drm_dbg(dev, "Shaper TF colorop with ID: %d\n", colorop->base.id);
tf->type = TF_TYPE_DISTRIBUTED_POINTS;
tf->tf = default_tf = amdgpu_colorop_tf_to_dc_tf(tf_state->curve_1d_type);
tf->sdr_ref_white_level = SDR_WHITE_LEVEL_INIT_VALUE;
@@ -1708,7 +1674,7 @@ __set_dm_plane_colorop_shaper(struct drm_plane_state *plane_state,
dc_plane_state->cm.flags.bits.shaper_enable = 1;
}
- if (lut_state && !lut_state->bypass) {
+ if (!lut_state->bypass) {
drm_dbg(dev, "Shaper LUT colorop with ID: %d\n", lut_colorop->base.id);
tf->type = TF_TYPE_DISTRIBUTED_POINTS;
tf->tf = default_tf;
@@ -1765,8 +1731,7 @@ __set_dm_plane_colorop_3dlut(struct drm_plane_state *plane_state,
struct dc_plane_state *dc_plane_state,
struct drm_colorop *colorop)
{
- struct drm_colorop *old_colorop;
- struct drm_colorop_state *colorop_state = NULL, *new_colorop_state;
+ struct drm_colorop_state *colorop_state;
struct dc_transfer_func *tf = &dc_plane_state->cm.shaper_func;
struct drm_atomic_commit *state = plane_state->state;
const struct amdgpu_device *adev = drm_to_adev(colorop->dev);
@@ -1774,19 +1739,14 @@ __set_dm_plane_colorop_3dlut(struct drm_plane_state *plane_state,
const struct drm_device *dev = colorop->dev;
const struct drm_color_lut32 *lut3d;
uint32_t lut3d_size;
- int i = 0, ret = 0;
+ int ret = 0;
/* 3D LUT */
- old_colorop = colorop;
- for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
- if (new_colorop_state->colorop == old_colorop &&
- new_colorop_state->colorop->type == DRM_COLOROP_3D_LUT) {
- colorop_state = new_colorop_state;
- break;
- }
- }
+ colorop_state = drm_atomic_get_new_colorop_state(state, colorop);
+ if (!colorop_state)
+ colorop_state = colorop->state;
- if (colorop_state && !colorop_state->bypass && colorop->type == DRM_COLOROP_3D_LUT) {
+ if (!colorop_state->bypass && colorop->type == DRM_COLOROP_3D_LUT) {
if (!has_3dlut) {
drm_dbg(dev, "3D LUT is not supported by hardware\n");
return -EINVAL;
@@ -1825,8 +1785,6 @@ __set_dm_plane_colorop_blend(struct drm_plane_state *plane_state,
struct dc_plane_state *dc_plane_state,
struct drm_colorop *colorop)
{
- struct drm_colorop *old_colorop;
- struct drm_colorop_state *new_colorop_state;
struct drm_colorop_state *tf_state = NULL, *lut_state = NULL;
struct drm_atomic_commit *state = plane_state->state;
struct drm_colorop *lut_colorop;
@@ -1835,38 +1793,29 @@ __set_dm_plane_colorop_blend(struct drm_plane_state *plane_state,
const struct drm_color_lut32 *blend_lut = NULL;
struct drm_device *dev = colorop->dev;
uint32_t blend_size = 0;
- int i = 0, ret;
+ int ret;
tf->type = TF_TYPE_BYPASS;
dc_plane_state->cm.flags.bits.blend_enable = 0;
/* 1D Curve - BLND TF: find state */
- old_colorop = colorop;
- for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
- if (new_colorop_state->colorop == old_colorop &&
- (BIT(new_colorop_state->curve_1d_type) & amdgpu_dm_supported_blnd_tfs)) {
- tf_state = new_colorop_state;
- break;
- }
- }
+ tf_state = drm_atomic_get_new_colorop_state(state, colorop);
+ if (!tf_state)
+ tf_state = colorop->state;
/* 1D LUT - BLND LUT: find state */
- lut_colorop = old_colorop->next;
+ lut_colorop = colorop->next;
if (!lut_colorop) {
drm_dbg(dev, "no Blend LUT colorop found\n");
return -EINVAL;
}
- for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
- if (new_colorop_state->colorop == lut_colorop &&
- new_colorop_state->colorop->type == DRM_COLOROP_1D_LUT) {
- lut_state = new_colorop_state;
- break;
- }
- }
+ lut_state = drm_atomic_get_new_colorop_state(state, lut_colorop);
+ if (!lut_state)
+ lut_state = lut_colorop->state;
- if (tf_state && !tf_state->bypass) {
- drm_dbg(dev, "Blend TF colorop with ID: %d\n", old_colorop->base.id);
+ if (!tf_state->bypass) {
+ drm_dbg(dev, "Blend TF colorop with ID: %d\n", colorop->base.id);
tf->type = TF_TYPE_DISTRIBUTED_POINTS;
tf->tf = default_tf = amdgpu_colorop_tf_to_dc_tf(tf_state->curve_1d_type);
tf->sdr_ref_white_level = SDR_WHITE_LEVEL_INIT_VALUE;
@@ -1876,7 +1825,7 @@ __set_dm_plane_colorop_blend(struct drm_plane_state *plane_state,
dc_plane_state->cm.flags.bits.blend_enable = 1;
}
- if (lut_state && !lut_state->bypass) {
+ if (!lut_state->bypass) {
drm_dbg(dev, "Blend LUT colorop with ID: %d\n", lut_colorop->base.id);
tf->type = TF_TYPE_DISTRIBUTED_POINTS;
tf->tf = default_tf;
--
2.53.0
next prev parent reply other threads:[~2026-08-11 17:11 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-11 16:45 [PATCH v4 00/11] drm/atomic: don't allow changes to inactive colorops & other fixes Melissa Wen
2026-08-11 16:45 ` [PATCH v4 01/11] drm/atomic: only add states of active or transient active colorops Melissa Wen
2026-09-30 19:11 ` Harry Wentland
2026-08-11 16:45 ` [PATCH v4 02/11] drm/atomic: reject colorop update from inactive color pipeline Melissa Wen
2026-09-30 19:18 ` Harry Wentland
2026-08-11 16:45 ` [PATCH v4 03/11] drm/atomic: duplicate state of all colorops Melissa Wen
2026-09-30 19:20 ` Harry Wentland
2026-08-11 16:45 ` [PATCH v4 04/11] drm/atomic: check if an active colorop has a blob if its type requires one Melissa Wen
2026-09-30 19:25 ` Harry Wentland
2026-08-11 16:45 ` [PATCH v4 05/11] drm/amd/display: only check colorops of an active color pipeline Melissa Wen
2026-09-30 19:32 ` Harry Wentland
2026-08-11 16:45 ` [PATCH v4 06/11] drm/amd/display: truly bypass plane colorop 3x4 matrix and hdr mult Melissa Wen
2026-09-30 19:34 ` Harry Wentland
2026-08-11 16:45 ` [PATCH v4 07/11] drm/amd/display: make shaper bypass mode cleaner Melissa Wen
2026-09-30 19:35 ` Harry Wentland
2026-08-11 16:45 ` [PATCH v4 08/11] drm/amd/display: make blnd bypass mode clearer Melissa Wen
2026-09-30 19:36 ` Harry Wentland
2026-08-11 16:45 ` [PATCH v4 09/11] drm/amd/display: don't ignore failure on blend colorop setup Melissa Wen
2026-09-30 19:38 ` Harry Wentland
2026-08-11 16:45 ` Melissa Wen [this message]
2026-09-30 20:57 ` [PATCH v4 10/11] drm/amd/display: allow individual colorop changes Harry Wentland
2026-08-11 16:46 ` [PATCH v4 11/11] drm/amd/display: distinguish colorop setup error from no colorop support Melissa Wen
2026-09-30 20:23 ` Harry Wentland
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260811171011.184964-11-mwen@igalia.com \
--to=mwen@igalia.com \
--cc=airlied@gmail.com \
--cc=alex.hung@amd.com \
--cc=alexander.deucher@amd.com \
--cc=amd-gfx@lists.freedesktop.org \
--cc=aurabindo.pillai@amd.com \
--cc=chaitanya.kumar.borah@intel.com \
--cc=christian.koenig@amd.com \
--cc=contact@emersion.fr \
--cc=daniels@collabora.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=freedreno@lists.freedesktop.org \
--cc=harry.wentland@amd.com \
--cc=intel-gfx@lists.freedesktop.org \
--cc=intel-xe@lists.freedesktop.org \
--cc=kernel-dev@igalia.com \
--cc=linux-arm-msm@vger.kernel.org \
--cc=louis.chauvet@bootlin.com \
--cc=lumag@kernel.org \
--cc=maarten.lankhorst@linux.intel.com \
--cc=marijn.suijten@somainline.org \
--cc=matthew.schwartz@linux.dev \
--cc=mripard@kernel.org \
--cc=pekka.paalanen@collabora.com \
--cc=robin.clark@oss.qualcomm.com \
--cc=sean@poorly.run \
--cc=sebastian.wick@redhat.com \
--cc=simona@ffwll.ch \
--cc=siqueira@igalia.com \
--cc=sunpeng.li@amd.com \
--cc=tzimmermann@suse.de \
--cc=uma.shankar@intel.com \
--cc=xaver.hugl@kde.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox