Skip to content

Commit 65db7a1

Browse files
ckborahjnikula
authored andcommitted
drm/i915/color: Add 3D LUT to color pipeline
Add helpers to program the 3D LUT registers and arm them. LUT_3D_READY in LUT_3D_CLT is cleared off by the HW once the LUT buffer is loaded into it's internal working RAM. So by the time we try to load/commit new values, we expect it to be cleared off. If not, log an error and return without writing new values. Do it only when writing with MMIO. There is no way to read register within DSB execution. v2: - Add information regarding LUT_3D_READY to commit message (Jani) - Log error instead of a drm_warn and return without committing changes if 3DLUT HW is not ready to accept new values. - Refactor intel_color_crtc_has_3dlut() Also remove Gen10 check (Suraj) v3: - Addressed review comments (Suraj) Reviewed-by: Suraj Kandpal <suraj.kandpal@intel.com> Signed-off-by: Chaitanya Kumar Borah <chaitanya.kumar.borah@intel.com> Signed-off-by: Uma Shankar <uma.shankar@intel.com> Link: https://patch.msgid.link/20251203085211.3663374-15-uma.shankar@intel.com Signed-off-by: Jani Nikula <jani.nikula@intel.com>
1 parent 55b0f3c commit 65db7a1

7 files changed

Lines changed: 112 additions & 7 deletions

File tree

drivers/gpu/drm/i915/display/intel_color.c

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4062,6 +4062,52 @@ xelpd_plane_load_luts(struct intel_dsb *dsb, const struct intel_plane_state *pla
40624062
xelpd_program_plane_post_csc_lut(dsb, plane_state);
40634063
}
40644064

4065+
static u32 glk_3dlut_10(const struct drm_color_lut32 *color)
4066+
{
4067+
return REG_FIELD_PREP(LUT_3D_DATA_RED_MASK, drm_color_lut32_extract(color->red, 10)) |
4068+
REG_FIELD_PREP(LUT_3D_DATA_GREEN_MASK, drm_color_lut32_extract(color->green, 10)) |
4069+
REG_FIELD_PREP(LUT_3D_DATA_BLUE_MASK, drm_color_lut32_extract(color->blue, 10));
4070+
}
4071+
4072+
static void glk_load_lut_3d(struct intel_dsb *dsb,
4073+
struct intel_crtc *crtc,
4074+
const struct drm_property_blob *blob)
4075+
{
4076+
struct intel_display *display = to_intel_display(crtc->base.dev);
4077+
const struct drm_color_lut32 *lut = blob->data;
4078+
int i, lut_size = drm_color_lut32_size(blob);
4079+
enum pipe pipe = crtc->pipe;
4080+
4081+
if (!dsb && intel_de_read(display, LUT_3D_CTL(pipe)) & LUT_3D_READY) {
4082+
drm_err(display->drm, "[CRTC:%d:%s] 3D LUT not ready, not loading LUTs\n",
4083+
crtc->base.base.id, crtc->base.name);
4084+
return;
4085+
}
4086+
4087+
intel_de_write_dsb(display, dsb, LUT_3D_INDEX(pipe), LUT_3D_AUTO_INCREMENT);
4088+
for (i = 0; i < lut_size; i++)
4089+
intel_de_write_dsb(display, dsb, LUT_3D_DATA(pipe), glk_3dlut_10(&lut[i]));
4090+
intel_de_write_dsb(display, dsb, LUT_3D_INDEX(pipe), 0);
4091+
}
4092+
4093+
static void glk_lut_3d_commit(struct intel_dsb *dsb, struct intel_crtc *crtc, bool enable)
4094+
{
4095+
struct intel_display *display = to_intel_display(crtc);
4096+
enum pipe pipe = crtc->pipe;
4097+
u32 val = 0;
4098+
4099+
if (!dsb && intel_de_read(display, LUT_3D_CTL(pipe)) & LUT_3D_READY) {
4100+
drm_err(display->drm, "[CRTC:%d:%s] 3D LUT not ready, not committing change\n",
4101+
crtc->base.base.id, crtc->base.name);
4102+
return;
4103+
}
4104+
4105+
if (enable)
4106+
val = LUT_3D_ENABLE | LUT_3D_READY | LUT_3D_BIND_PLANE_1;
4107+
4108+
intel_de_write_dsb(display, dsb, LUT_3D_CTL(pipe), val);
4109+
}
4110+
40654111
static const struct intel_color_funcs chv_color_funcs = {
40664112
.color_check = chv_color_check,
40674113
.color_commit_arm = i9xx_color_commit_arm,
@@ -4191,6 +4237,16 @@ static const struct intel_color_funcs ilk_color_funcs = {
41914237
.get_config = ilk_get_config,
41924238
};
41934239

4240+
void intel_color_plane_commit_arm(struct intel_dsb *dsb,
4241+
const struct intel_plane_state *plane_state)
4242+
{
4243+
struct intel_display *display = to_intel_display(plane_state);
4244+
struct intel_crtc *crtc = to_intel_crtc(plane_state->uapi.crtc);
4245+
4246+
if (crtc && intel_color_crtc_has_3dlut(display, crtc->pipe))
4247+
glk_lut_3d_commit(dsb, crtc, !!plane_state->hw.lut_3d);
4248+
}
4249+
41944250
static void
41954251
intel_color_load_plane_csc_matrix(struct intel_dsb *dsb,
41964252
const struct intel_plane_state *plane_state)
@@ -4211,13 +4267,35 @@ intel_color_load_plane_luts(struct intel_dsb *dsb,
42114267
display->funcs.color->load_plane_luts(dsb, plane_state);
42124268
}
42134269

4270+
bool
4271+
intel_color_crtc_has_3dlut(struct intel_display *display, enum pipe pipe)
4272+
{
4273+
if (DISPLAY_VER(display) >= 12)
4274+
return pipe == PIPE_A || pipe == PIPE_B;
4275+
else
4276+
return false;
4277+
}
4278+
4279+
static void
4280+
intel_color_load_3dlut(struct intel_dsb *dsb,
4281+
const struct intel_plane_state *plane_state)
4282+
{
4283+
struct intel_display *display = to_intel_display(plane_state);
4284+
struct intel_crtc *crtc = to_intel_crtc(plane_state->uapi.crtc);
4285+
4286+
if (crtc && intel_color_crtc_has_3dlut(display, crtc->pipe))
4287+
glk_load_lut_3d(dsb, crtc, plane_state->hw.lut_3d);
4288+
}
4289+
42144290
void intel_color_plane_program_pipeline(struct intel_dsb *dsb,
42154291
const struct intel_plane_state *plane_state)
42164292
{
42174293
if (plane_state->hw.ctm)
42184294
intel_color_load_plane_csc_matrix(dsb, plane_state);
42194295
if (plane_state->hw.degamma_lut || plane_state->hw.gamma_lut)
42204296
intel_color_load_plane_luts(dsb, plane_state);
4297+
if (plane_state->hw.lut_3d)
4298+
intel_color_load_3dlut(dsb, plane_state);
42214299
}
42224300

42234301
void intel_color_crtc_init(struct intel_crtc *crtc)

drivers/gpu/drm/i915/display/intel_color.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ struct intel_display;
1515
struct intel_dsb;
1616
struct intel_plane_state;
1717
struct drm_property_blob;
18+
enum pipe;
1819

1920
void intel_color_init_hooks(struct intel_display *display);
2021
int intel_color_init(struct intel_display *display);
@@ -43,4 +44,7 @@ bool intel_color_lut_equal(const struct intel_crtc_state *crtc_state,
4344
void intel_color_assert_luts(const struct intel_crtc_state *crtc_state);
4445
void intel_color_plane_program_pipeline(struct intel_dsb *dsb,
4546
const struct intel_plane_state *plane_state);
47+
void intel_color_plane_commit_arm(struct intel_dsb *dsb,
48+
const struct intel_plane_state *plane_state);
49+
bool intel_color_crtc_has_3dlut(struct intel_display *display, enum pipe pipe);
4650
#endif /* __INTEL_COLOR_H__ */

drivers/gpu/drm/i915/display/intel_color_pipeline.c

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
/*
33
* Copyright © 2025 Intel Corporation
44
*/
5+
#include "intel_color.h"
56
#include "intel_colorop.h"
67
#include "intel_color_pipeline.h"
78
#include "intel_de.h"
@@ -13,12 +14,14 @@
1314
#define PLANE_GAMMA_SIZE 32
1415

1516
static
16-
int _intel_color_pipeline_plane_init(struct drm_plane *plane, struct drm_prop_enum_list *list)
17+
int _intel_color_pipeline_plane_init(struct drm_plane *plane, struct drm_prop_enum_list *list,
18+
enum pipe pipe)
1719
{
18-
struct intel_colorop *colorop;
1920
struct drm_device *dev = plane->dev;
20-
int ret;
21+
struct intel_display *display = to_intel_display(dev);
2122
struct drm_colorop *prev_op;
23+
struct intel_colorop *colorop;
24+
int ret;
2225

2326
colorop = intel_colorop_create(INTEL_PLANE_CB_PRE_CSC_LUT);
2427

@@ -36,6 +39,22 @@ int _intel_color_pipeline_plane_init(struct drm_plane *plane, struct drm_prop_en
3639
/* TODO: handle failures and clean up */
3740
prev_op = &colorop->base;
3841

42+
if (DISPLAY_VER(display) >= 35 &&
43+
intel_color_crtc_has_3dlut(display, pipe) &&
44+
plane->type == DRM_PLANE_TYPE_PRIMARY) {
45+
colorop = intel_colorop_create(INTEL_PLANE_CB_3DLUT);
46+
47+
ret = drm_plane_colorop_3dlut_init(dev, &colorop->base, plane, 17,
48+
DRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL,
49+
true);
50+
if (ret)
51+
return ret;
52+
53+
drm_colorop_set_next_property(prev_op, &colorop->base);
54+
55+
prev_op = &colorop->base;
56+
}
57+
3958
colorop = intel_colorop_create(INTEL_PLANE_CB_CSC);
4059
ret = drm_plane_colorop_ctm_3x4_init(dev, &colorop->base, plane,
4160
DRM_COLOROP_FLAG_ALLOW_BYPASS);
@@ -58,7 +77,7 @@ int _intel_color_pipeline_plane_init(struct drm_plane *plane, struct drm_prop_en
5877
return 0;
5978
}
6079

61-
int intel_color_pipeline_plane_init(struct drm_plane *plane)
80+
int intel_color_pipeline_plane_init(struct drm_plane *plane, enum pipe pipe)
6281
{
6382
struct drm_device *dev = plane->dev;
6483
struct intel_display *display = to_intel_display(dev);
@@ -71,7 +90,7 @@ int intel_color_pipeline_plane_init(struct drm_plane *plane)
7190
return 0;
7291

7392
/* Add pipeline consisting of transfer functions */
74-
ret = _intel_color_pipeline_plane_init(plane, &pipelines[len]);
93+
ret = _intel_color_pipeline_plane_init(plane, &pipelines[len], pipe);
7594
if (ret)
7695
return ret;
7796
len++;

drivers/gpu/drm/i915/display/intel_color_pipeline.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
#define __INTEL_COLOR_PIPELINE_H__
88

99
struct drm_plane;
10+
enum pipe;
1011

11-
int intel_color_pipeline_plane_init(struct drm_plane *plane);
12+
int intel_color_pipeline_plane_init(struct drm_plane *plane, enum pipe pipe);
1213

1314
#endif /* __INTEL_COLOR_PIPELINE_H__ */

drivers/gpu/drm/i915/display/intel_display_limits.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ enum intel_color_block {
142142
INTEL_PLANE_CB_PRE_CSC_LUT,
143143
INTEL_PLANE_CB_CSC,
144144
INTEL_PLANE_CB_POST_CSC_LUT,
145+
INTEL_PLANE_CB_3DLUT,
145146

146147
INTEL_CB_MAX
147148
};

drivers/gpu/drm/i915/display/intel_display_types.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,7 @@ struct intel_plane_state {
646646
enum drm_color_encoding color_encoding;
647647
enum drm_color_range color_range;
648648
enum drm_scaling_filter scaling_filter;
649-
struct drm_property_blob *ctm, *degamma_lut, *gamma_lut;
649+
struct drm_property_blob *ctm, *degamma_lut, *gamma_lut, *lut_3d;
650650
} hw;
651651

652652
struct i915_vma *ggtt_vma;

drivers/gpu/drm/i915/display/intel_plane.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,8 @@ intel_plane_colorop_replace_blob(struct intel_plane_state *plane_state,
348348
return drm_property_replace_blob(&plane_state->hw.degamma_lut, blob);
349349
else if (intel_colorop->id == INTEL_PLANE_CB_POST_CSC_LUT)
350350
return drm_property_replace_blob(&plane_state->hw.gamma_lut, blob);
351+
else if (intel_colorop->id == INTEL_PLANE_CB_3DLUT)
352+
return drm_property_replace_blob(&plane_state->hw.lut_3d, blob);
351353

352354
return false;
353355
}

0 commit comments

Comments
 (0)