From: Louis Chauvet <louis.chauvet@bootlin.com>
To: "Nícolas F. R. A. Prado" <nfraprado@collabora.com>,
"Maarten Lankhorst" <maarten.lankhorst@linux.intel.com>,
"Maxime Ripard" <mripard@kernel.org>,
"Thomas Zimmermann" <tzimmermann@suse.de>,
"David Airlie" <airlied@gmail.com>,
"Simona Vetter" <simona@ffwll.ch>,
"Chun-Kuang Hu" <chunkuang.hu@kernel.org>,
"Philipp Zabel" <p.zabel@pengutronix.de>,
"Matthias Brugger" <matthias.bgg@gmail.com>,
"AngeloGioacchino Del Regno"
<angelogioacchino.delregno@collabora.com>
Cc: Alex Hung <alex.hung@amd.com>,
wayland-devel@lists.freedesktop.org, harry.wentland@amd.com,
leo.liu@amd.com, ville.syrjala@linux.intel.com,
pekka.paalanen@collabora.com, contact@emersion.fr,
mwen@igalia.com, jadahl@redhat.com, sebastian.wick@redhat.com,
shashank.sharma@amd.com, agoins@nvidia.com, joshua@froggi.es,
mdaenzer@redhat.com, aleixpol@kde.org, xaver.hugl@gmail.com,
victoria@system76.com, uma.shankar@intel.com,
quic_naseer@quicinc.com, quic_cbraga@quicinc.com,
quic_abhinavk@quicinc.com, marcan@marcan.st, Liviu.Dudau@arm.com,
sashamcintosh@google.com, chaitanya.kumar.borah@intel.com,
mcanal@igalia.com, kernel@collabora.com, daniels@collabora.com,
dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org,
linux-mediatek@lists.infradead.org,
linux-arm-kernel@lists.infradead.org,
Simona Vetter <simona.vetter@ffwll.ch>
Subject: Re: [PATCH RFC 3/5] drm/mediatek: Support post-blend colorops for gamma and ctm
Date: Fri, 5 Sep 2025 19:55:52 +0200 [thread overview]
Message-ID: <22a8894a-6eb9-4f7a-b485-6259c3abc300@bootlin.com> (raw)
In-Reply-To: <20250822-mtk-post-blend-color-pipeline-v1-3-a9446d4aca82@collabora.com>
Le 22/08/2025 à 20:36, Nícolas F. R. A. Prado a écrit :
> Allow configuring the gamma and ccorr blocks through the post-blend
> color pipeline API instead of the GAMMA_LUT and CTM properties.
>
> In order to achieve this, initialize the color pipeline property and
> colorops on the CRTC based on the DDP components available in the CRTC
> path. Then introduce a struct mtk_drm_colorop that extends drm_colorop
> and tracks the mtk_ddp_comp that implements it in hardware, and include
> new ddp_comp helper functions for setting gamma and ctm through the new
> API. These helpers will then be called during commit flush for every
> updated colorop if the DRM client supports the post-blend color pipeline
> API.
>
> Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
> ---
> drivers/gpu/drm/mediatek/mtk_crtc.c | 211 +++++++++++++++++++++++++++++++-
> drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 2 +
> 2 files changed, 208 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.c b/drivers/gpu/drm/mediatek/mtk_crtc.c
> index bc7527542fdc6fb89fc36794cee7d6dc26f7dcce..80ed061de1af31916d814f29f9111973cffd10dd 100644
> --- a/drivers/gpu/drm/mediatek/mtk_crtc.c
> +++ b/drivers/gpu/drm/mediatek/mtk_crtc.c
> @@ -82,6 +82,12 @@ struct mtk_crtc_state {
> unsigned int pending_vrefresh;
> };
>
> +struct mtk_drm_colorop {
> + struct drm_colorop colorop;
> + struct mtk_ddp_comp *comp;
> + uint32_t data_id;
> +};
> +
@Alex: This is exactly a case where I think the current
drm_colorop_pipeline_destroy will break.
> static inline struct mtk_crtc *to_mtk_crtc(struct drm_crtc *c)
> {
> return container_of(c, struct mtk_crtc, base);
> @@ -92,6 +98,11 @@ static inline struct mtk_crtc_state *to_mtk_crtc_state(struct drm_crtc_state *s)
> return container_of(s, struct mtk_crtc_state, base);
> }
>
> +static inline struct mtk_drm_colorop *to_mtk_colorop(struct drm_colorop *colorop)
> +{
> + return container_of(colorop, struct mtk_drm_colorop, colorop);
> +}
> +
> static void mtk_crtc_finish_page_flip(struct mtk_crtc *mtk_crtc)
> {
> struct drm_crtc *crtc = &mtk_crtc->base;
> @@ -125,6 +136,19 @@ static void mtk_drm_finish_page_flip(struct mtk_crtc *mtk_crtc)
> spin_unlock_irqrestore(&mtk_crtc->config_lock, flags);
> }
>
> +static void mtk_drm_colorop_pipeline_destroy(struct drm_device *dev)
> +{
> + struct drm_mode_config *config = &dev->mode_config;
> + struct drm_colorop *colorop, *next;
> + struct mtk_drm_colorop *mtk_colorop;
> +
> + list_for_each_entry_safe(colorop, next, &config->colorop_list, head) {
> + drm_colorop_cleanup(colorop);
> + mtk_colorop = to_mtk_colorop(colorop);
> + kfree(mtk_colorop);
> + }
> +}
> +
> static void mtk_crtc_destroy(struct drm_crtc *crtc)
> {
> struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
> @@ -146,6 +170,8 @@ static void mtk_crtc_destroy(struct drm_crtc *crtc)
> mtk_ddp_comp_unregister_vblank_cb(comp);
> }
>
> + mtk_drm_colorop_pipeline_destroy(crtc->dev);
> +
> drm_crtc_cleanup(crtc);
> }
>
> @@ -854,20 +880,103 @@ static void mtk_crtc_atomic_begin(struct drm_crtc *crtc,
> }
> }
>
> +static bool colorop_data_update_flush_status(struct drm_colorop_state *colorop_state)
> +{
> + struct drm_colorop *colorop = colorop_state->colorop;
> + struct mtk_drm_colorop *mtk_colorop = to_mtk_colorop(colorop);
> + struct drm_property_blob *data_blob = colorop_state->data;
> + uint32_t data_id = colorop_state->bypass ? 0 : data_blob->base.id;
> + bool needs_flush = mtk_colorop->data_id != data_id;
> +
> + mtk_colorop->data_id = data_id;
> +
> + return needs_flush;
> +}
> +
> +static void mtk_crtc_ddp_comp_apply_colorop(struct drm_colorop_state *colorop_state)
> +{
> + struct drm_colorop *colorop = colorop_state->colorop;
> + struct mtk_drm_colorop *mtk_colorop = to_mtk_colorop(colorop);
> + struct drm_property_blob *data_blob = colorop_state->data;
> + struct mtk_ddp_comp *ddp_comp = mtk_colorop->comp;
> + struct drm_color_ctm_3x4 *ctm = NULL;
> + struct drm_color_lut32 *lut = NULL;
> +
> + switch (colorop->type) {
> + case DRM_COLOROP_1D_LUT:
> + if (!colorop_data_update_flush_status(colorop_state))
> + return;
> +
> + if (!colorop_state->bypass)
> + lut = (struct drm_color_lut32 *)data_blob->data;
> +
> + ddp_comp->funcs->gamma_set_color_pipeline(ddp_comp->dev, lut);
> + break;
> + case DRM_COLOROP_CTM_3X4:
> + if (!colorop_data_update_flush_status(colorop_state))
> + return;
> +
> + if (!colorop_state->bypass)
> + ctm = (struct drm_color_ctm_3x4 *)data_blob->data;
> +
> + ddp_comp->funcs->ctm_set_color_pipeline(ddp_comp->dev, ctm);
> + break;
> + default:
> + /* If this happens the driver is broken */
> + drm_WARN(colorop->dev, 1,
> + "Trying to atomic flush COLOROP of type unsupported by driver: %d\n",
> + colorop->type);
> + break;
> + }
> +}
> +
> static void mtk_crtc_atomic_flush(struct drm_crtc *crtc,
> struct drm_atomic_state *state)
> {
> struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
> + struct drm_colorop_state *new_colorop_state;
> + struct drm_colorop *colorop;
> int i;
>
> - if (crtc->state->color_mgmt_changed)
> - for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
> - mtk_ddp_gamma_set(mtk_crtc->ddp_comp[i], crtc->state);
> - mtk_ddp_ctm_set(mtk_crtc->ddp_comp[i], crtc->state);
> - }
> + if (state->post_blend_color_pipeline) {
> + for_each_new_colorop_in_state(state, colorop, new_colorop_state, i)
> + mtk_crtc_ddp_comp_apply_colorop(new_colorop_state);
> + } else {
> + if (crtc->state->color_mgmt_changed)
> + for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
> + mtk_ddp_gamma_set(mtk_crtc->ddp_comp[i], crtc->state);
> + mtk_ddp_ctm_set(mtk_crtc->ddp_comp[i], crtc->state);
> + }
> + }
> mtk_crtc_update_config(mtk_crtc, !!mtk_crtc->event);
> }
>
> +static int mtk_crtc_atomic_check(struct drm_crtc *crtc,
> + struct drm_atomic_state *state)
> +{
> + struct drm_colorop_state *new_colorop_state;
> + struct drm_colorop *colorop;
> + int i;
> +
> + for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
> + switch (colorop->type) {
> + case DRM_COLOROP_1D_LUT:
> + case DRM_COLOROP_CTM_3X4:
> + if (!new_colorop_state->bypass && !new_colorop_state->data) {
> + drm_dbg_atomic(crtc->dev,
> + "Missing required DATA property for COLOROP:%d\n",
> + colorop->base.id);
> + return -EINVAL;
> + }
> + break;
> + default:
> + break;
> + }
> + }
> +
> + return 0;
> +}
> +
> static const struct drm_crtc_funcs mtk_crtc_funcs = {
> .set_config = drm_atomic_helper_set_config,
> .page_flip = drm_atomic_helper_page_flip,
> @@ -885,6 +994,7 @@ static const struct drm_crtc_helper_funcs mtk_crtc_helper_funcs = {
> .mode_valid = mtk_crtc_mode_valid,
> .atomic_begin = mtk_crtc_atomic_begin,
> .atomic_flush = mtk_crtc_atomic_flush,
> + .atomic_check = mtk_crtc_atomic_check,
> .atomic_enable = mtk_crtc_atomic_enable,
> .atomic_disable = mtk_crtc_atomic_disable,
> };
> @@ -987,6 +1097,95 @@ struct device *mtk_crtc_dma_dev_get(struct drm_crtc *crtc)
> return mtk_crtc->dma_dev;
> }
>
> +#define MAX_COLOR_PIPELINE_OPS 2
> +#define MAX_COLOR_PIPELINES 1
> +
> +static int mtk_colorop_init(struct mtk_crtc *mtk_crtc,
> + struct mtk_drm_colorop *mtk_colorop,
> + struct mtk_ddp_comp *ddp_comp)
> +{
> + struct drm_colorop *colorop = &mtk_colorop->colorop;
> + int ret = 0;
> +
> + if (ddp_comp->funcs->gamma_set_color_pipeline) {
> + unsigned int lut_sz = mtk_ddp_gamma_get_lut_size(ddp_comp);
> +
> + ret = drm_crtc_colorop_curve_1d_lut_init(mtk_crtc->base.dev, colorop,
> + &mtk_crtc->base,
> + lut_sz,
> + DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR,
> + DRM_COLOROP_FLAG_ALLOW_BYPASS);
> + } else if (ddp_comp->funcs->ctm_set_color_pipeline) {
> + ret = drm_crtc_colorop_ctm_3x4_init(mtk_crtc->base.dev,
> + colorop,
> + &mtk_crtc->base,
> + DRM_COLOROP_FLAG_ALLOW_BYPASS);
> + }
> +
> + mtk_colorop->comp = ddp_comp;
> +
> + return ret;
> +}
> +
> +static int mtk_crtc_init_post_blend_color_pipeline(struct mtk_crtc *mtk_crtc,
> + unsigned int gamma_lut_size)
> +{
> + struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES];
> + struct drm_colorop *ops[MAX_COLOR_PIPELINE_OPS];
> + struct mtk_drm_colorop *mtk_colorop;
> + unsigned int num_pipelines = 0;
> + unsigned int op_idx = 0;
> + int ret;
> +
> + memset(ops, 0, sizeof(ops));
> +
> + for (unsigned int i = 0;
> + i < mtk_crtc->ddp_comp_nr && op_idx < MAX_COLOR_PIPELINE_OPS;
> + i++) {
> + struct mtk_ddp_comp *ddp_comp = mtk_crtc->ddp_comp[i];
> +
> + if (!(ddp_comp->funcs->gamma_set_color_pipeline ||
> + ddp_comp->funcs->ctm_set_color_pipeline))
> + continue;
> +
> + mtk_colorop = kzalloc(sizeof(struct mtk_drm_colorop), GFP_KERNEL);
> + if (!mtk_colorop) {
> + ret = -ENOMEM;
> + goto cleanup;
> + }
> +
> + ops[op_idx] = &mtk_colorop->colorop;
> +
> + ret = mtk_colorop_init(mtk_crtc, mtk_colorop, ddp_comp);
> + if (ret)
> + goto cleanup;
> +
> + if (op_idx > 0)
> + drm_colorop_set_next_property(ops[op_idx-1], ops[op_idx]);
> +
> + op_idx++;
> + }
> +
> + if (op_idx > 0) {
> + pipelines[0].type = ops[0]->base.id;
> + pipelines[0].name = kasprintf(GFP_KERNEL, "Color Pipeline %d", ops[0]->base.id);
> + num_pipelines = 1;
> + }
> +
> + /* Create COLOR_PIPELINE property and attach */
> + drm_crtc_create_color_pipeline_property(&mtk_crtc->base, pipelines, num_pipelines);
> +
> + return 0;
> +
> +cleanup:
> + if (ret == -ENOMEM)
> + drm_err(mtk_crtc->base.dev, "KMS: Failed to allocate colorop\n");
> +
> + mtk_drm_colorop_pipeline_destroy(mtk_crtc->base.dev);
> +
> + return ret;
> +}
> +
> int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
> unsigned int path_len, int priv_data_index,
> const struct mtk_drm_route *conn_routes,
> @@ -1103,6 +1302,8 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
> if (ret < 0)
> return ret;
>
> + mtk_crtc_init_post_blend_color_pipeline(mtk_crtc, gamma_lut_size);
> +
> 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);
> diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> index 7289b3dcf22f22f344016beee0c7c144cf7b93c8..554c3cc8ad7b266b8b8eee74ceb8f7383fe2f8df 100644
> --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> @@ -75,10 +75,12 @@ struct mtk_ddp_comp_funcs {
> unsigned int (*gamma_get_lut_size)(struct device *dev);
> void (*gamma_set)(struct device *dev,
> struct drm_crtc_state *state);
> + void (*gamma_set_color_pipeline)(struct device *dev, struct drm_color_lut32 *lut);
> void (*bgclr_in_on)(struct device *dev);
> void (*bgclr_in_off)(struct device *dev);
> void (*ctm_set)(struct device *dev,
> struct drm_crtc_state *state);
> + void (*ctm_set_color_pipeline)(struct device *dev, struct drm_color_ctm_3x4 *ctm);
> struct device * (*dma_dev_get)(struct device *dev);
> u32 (*get_blend_modes)(struct device *dev);
> const u32 *(*get_formats)(struct device *dev);
>
--
Louis Chauvet, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
next prev parent reply other threads:[~2025-09-05 17:56 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-22 18:36 [PATCH RFC 0/5] Introduce support for post-blend color pipeline Nícolas F. R. A. Prado
2025-08-22 18:36 ` [PATCH RFC 1/5] drm: Support post-blend color pipeline API Nícolas F. R. A. Prado
2025-08-25 13:34 ` Daniel Stone
2025-08-25 18:45 ` Xaver Hugl
2025-08-26 12:25 ` Daniel Stone
2025-09-03 18:42 ` Nícolas F. R. A. Prado
2025-09-15 12:31 ` Daniel Stone
2025-09-26 13:51 ` Sebastian Wick
2025-09-29 10:33 ` Harry Wentland
[not found] ` <2a985767-0fe1-40fc-b45e-921bbf201e07@app.fastmail.com>
2025-09-30 12:20 ` Daniel Stone
2025-10-02 8:00 ` Pekka Paalanen
2025-08-27 11:17 ` Sebastian Wick
2025-08-27 11:32 ` Daniel Stone
2025-09-05 17:55 ` Louis Chauvet
2025-09-09 19:31 ` Nícolas F. R. A. Prado
2025-08-22 18:36 ` [PATCH RFC 2/5] drm/colorop: Export drm_colorop_cleanup() so drivers can extend it Nícolas F. R. A. Prado
2025-09-05 17:55 ` Louis Chauvet
2025-08-22 18:36 ` [PATCH RFC 3/5] drm/mediatek: Support post-blend colorops for gamma and ctm Nícolas F. R. A. Prado
2025-09-05 17:55 ` Louis Chauvet [this message]
2025-08-22 18:36 ` [PATCH RFC 4/5] drm/mediatek: ccorr: Support post-blend color pipeline API Nícolas F. R. A. Prado
2025-08-22 18:36 ` [PATCH RFC 5/5] drm/mediatek: gamma: " Nícolas F. R. A. Prado
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=22a8894a-6eb9-4f7a-b485-6259c3abc300@bootlin.com \
--to=louis.chauvet@bootlin.com \
--cc=Liviu.Dudau@arm.com \
--cc=agoins@nvidia.com \
--cc=airlied@gmail.com \
--cc=aleixpol@kde.org \
--cc=alex.hung@amd.com \
--cc=angelogioacchino.delregno@collabora.com \
--cc=chaitanya.kumar.borah@intel.com \
--cc=chunkuang.hu@kernel.org \
--cc=contact@emersion.fr \
--cc=daniels@collabora.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=harry.wentland@amd.com \
--cc=jadahl@redhat.com \
--cc=joshua@froggi.es \
--cc=kernel@collabora.com \
--cc=leo.liu@amd.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mediatek@lists.infradead.org \
--cc=maarten.lankhorst@linux.intel.com \
--cc=marcan@marcan.st \
--cc=matthias.bgg@gmail.com \
--cc=mcanal@igalia.com \
--cc=mdaenzer@redhat.com \
--cc=mripard@kernel.org \
--cc=mwen@igalia.com \
--cc=nfraprado@collabora.com \
--cc=p.zabel@pengutronix.de \
--cc=pekka.paalanen@collabora.com \
--cc=quic_abhinavk@quicinc.com \
--cc=quic_cbraga@quicinc.com \
--cc=quic_naseer@quicinc.com \
--cc=sashamcintosh@google.com \
--cc=sebastian.wick@redhat.com \
--cc=shashank.sharma@amd.com \
--cc=simona.vetter@ffwll.ch \
--cc=simona@ffwll.ch \
--cc=tzimmermann@suse.de \
--cc=uma.shankar@intel.com \
--cc=victoria@system76.com \
--cc=ville.syrjala@linux.intel.com \
--cc=wayland-devel@lists.freedesktop.org \
--cc=xaver.hugl@gmail.com \
/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