[PATCH 28/28] drm/i915/color: Enable Plane Color Pipelines
From: Chaitanya Kumar Borah Expose color pipeline and add capability to program it. Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/skl_universal_plane.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 7096ea8a3454..64e70cc34ddb 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -11,6 +11,7 @@ #include "i915_drv.h" #include "i915_reg.h" #include "intel_atomic_plane.h" +#include "intel_color.h" #include "intel_de.h" #include "intel_display_irq.h" #include "intel_display_types.h" @@ -1279,6 +1280,8 @@ icl_plane_update_noarm(struct intel_plane *plane, plane_color_ctl = plane_state->color_ctl | glk_plane_color_ctl_crtc(crtc_state); + intel_program_pipeline(_state->uapi, _color_ctl); + /* The scaler will handle the output position */ if (plane_state->scaler_id >= 0) { crtc_x = 0; @@ -2432,6 +2435,8 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, BIT(DRM_COLOR_YCBCR_FULL_RANGE), DRM_COLOR_YCBCR_BT709, DRM_COLOR_YCBCR_LIMITED_RANGE); + else + intel_plane_color_init(>base); drm_plane_create_alpha_property(>base); drm_plane_create_blend_mode_property(>base, -- 2.42.0
[PATCH 27/28] FIXME: force disable legacy plane color properties for TGL and beyond
From: Chaitanya Kumar Borah The decision should be made based on the DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE. Right now the value of this cap is not passed on to the driver. Signed-off-by: Chaitanya Kumar Borah --- drivers/gpu/drm/i915/display/skl_universal_plane.c | 14 -- 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index e941e2e4fd14..7096ea8a3454 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -2424,12 +2424,14 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, if (DISPLAY_VER(dev_priv) >= 10) supported_csc |= BIT(DRM_COLOR_YCBCR_BT2020); - drm_plane_create_color_properties(>base, - supported_csc, - BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | - BIT(DRM_COLOR_YCBCR_FULL_RANGE), - DRM_COLOR_YCBCR_BT709, - DRM_COLOR_YCBCR_LIMITED_RANGE); + /* TODO: Make it based on client cap */ + if (DISPLAY_VER(dev_priv) <= 11) + drm_plane_create_color_properties(>base, + supported_csc, + BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | + BIT(DRM_COLOR_YCBCR_FULL_RANGE), + DRM_COLOR_YCBCR_BT709, + DRM_COLOR_YCBCR_LIMITED_RANGE); drm_plane_create_alpha_property(>base); drm_plane_create_blend_mode_property(>base, -- 2.42.0
[PATCH 26/28] drm/i915/xelpd: Program Plane Post CSC Registers
Extract the LUT and program plane post csc registers. Signed-off-by: Uma Shankar Signed-off-by: Chaitanya Kumar Borah --- drivers/gpu/drm/i915/display/intel_color.c | 88 ++ 1 file changed, 88 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 6dd9b8e43352..68e1c91a2b39 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -3863,6 +3863,92 @@ static void xelpd_program_plane_pre_csc_lut(const struct drm_plane_state *state, } } +static void xelpd_program_plane_post_csc_lut(const struct drm_plane_state *state, +const struct drm_color_lut_ext *post_csc_lut, +u32 offset) +{ + struct drm_i915_private *dev_priv = to_i915(state->plane->dev); + enum pipe pipe = to_intel_plane(state->plane)->pipe; + enum plane_id plane = to_intel_plane(state->plane)->id; + u32 i, lut_size; + + if (icl_is_hdr_plane(dev_priv, plane)) { + intel_de_write_fw(dev_priv, PLANE_POST_CSC_GAMC_INDEX_ENH(pipe, plane, 0), + offset | PLANE_PAL_PREC_AUTO_INCREMENT); + if (post_csc_lut) { + lut_size = 32; + for (i = 0; i < lut_size; i++) { + u64 word = drm_color_lut_extract_ext(post_csc_lut[i].green, 24); + u32 lut_val = (word & 0xff); + + intel_de_write_fw(dev_priv, + PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, 0), + lut_val); + } + + do { + /* Program the max register to clamp values > 1.0. */ + intel_de_write_fw(dev_priv, + PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, 0), + post_csc_lut[i].green); + } while (i++ < 34); + } else { + lut_size = 32; + for (i = 0; i < lut_size; i++) { + u32 v = (i * ((1 << 24) - 1)) / (lut_size - 1); + + intel_de_write_fw(dev_priv, + PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, 0), v); + } + + do { + intel_de_write_fw(dev_priv, + PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, 0), + 1 << 24); + } while (i++ < 34); + } + + intel_de_write_fw(dev_priv, PLANE_POST_CSC_GAMC_INDEX_ENH(pipe, plane, 0), 0); + } else { + lut_size = 32; + /* +* First 3 planes are HDR, so reduce by 3 to get to the right +* SDR plane offset +*/ + plane = plane - 3; + + intel_de_write_fw(dev_priv, PLANE_POST_CSC_GAMC_INDEX(pipe, plane, 0), + offset | PLANE_PAL_PREC_AUTO_INCREMENT); + + if (post_csc_lut) { + for (i = 0; i < lut_size; i++) + intel_de_write_fw(dev_priv, + PLANE_POST_CSC_GAMC_DATA(pipe, plane, 0), + post_csc_lut[i].green & 0x); + /* Program the max register to clamp values > 1.0. */ + while (i < 35) + intel_de_write_fw(dev_priv, + PLANE_POST_CSC_GAMC_DATA(pipe, plane, 0), + post_csc_lut[i++].green & 0x3); + } else { + for (i = 0; i < lut_size; i++) { + u32 v = (i * ((1 << 16) - 1)) / (lut_size - 1); + + intel_de_write_fw(dev_priv, + PLANE_POST_CSC_GAMC_DATA(pipe, plane, 0), v); + } + + do { + intel_de_write_fw(dev_priv, + PLANE_POST_CSC_GAMC_DATA(pipe, plane, 0), + (1 << 16)); + } while (i++ < 34); + } + + intel_de_write_fw(dev_priv, PLANE_POST_CSC_GAMC_INDEX(pipe, plane, 0), 0); + } +} + static void xelpd_plane_load_luts(const struct drm_plane_
[PATCH 25/28] drm/i915/color: Program Pre-CSC registers
Add callback for programming Pre-CSC LUT for TGL and beyond Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 88 ++ 1 file changed, 88 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 0d68f8303502..6dd9b8e43352 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -3779,9 +3779,97 @@ void intel_color_load_plane_csc_matrix(const struct drm_plane_state *plane_state i915->display.funcs.color->load_plane_csc_matrix(plane_state, blob); } +static void xelpd_program_plane_pre_csc_lut(const struct drm_plane_state *state, + const struct drm_color_lut_ext *pre_csc_lut, + u32 offset) +{ + struct drm_i915_private *dev_priv = to_i915(state->plane->dev); + enum pipe pipe = to_intel_plane(state->plane)->pipe; + enum plane_id plane = to_intel_plane(state->plane)->id; + u32 i, lut_size; + + if (icl_is_hdr_plane(dev_priv, plane)) { + lut_size = 128; + + intel_de_write_fw(dev_priv, PLANE_PRE_CSC_GAMC_INDEX_ENH(pipe, plane, 0), + offset | PLANE_PAL_PREC_AUTO_INCREMENT); + + if (pre_csc_lut) { + for (i = 0; i < lut_size; i++) { + u64 word = drm_color_lut_extract_ext(pre_csc_lut[i].green, 24); + u32 lut_val = (word & 0xff); + + intel_de_write_fw(dev_priv, + PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0), + lut_val); + } + + /* Program the max register to clamp values > 1.0. */ + while (i < 131) + intel_de_write_fw(dev_priv, + PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0), + pre_csc_lut[i++].green); + } else { + for (i = 0; i < lut_size; i++) { + u32 v = (i * ((1 << 24) - 1)) / (lut_size - 1); + + intel_de_write_fw(dev_priv, + PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0), v); + } + + do { + intel_de_write_fw(dev_priv, + PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0), + 1 << 24); + } while (i++ < 130); + } + + intel_de_write_fw(dev_priv, PLANE_PRE_CSC_GAMC_INDEX_ENH(pipe, plane, 0), 0); + } else { + lut_size = 32; + + /* +* First 3 planes are HDR, so reduce by 3 to get to the right +* SDR plane offset +*/ + plane = plane - 3; + + intel_de_write_fw(dev_priv, PLANE_PRE_CSC_GAMC_INDEX(pipe, plane, 0), + offset | PLANE_PAL_PREC_AUTO_INCREMENT); + + if (pre_csc_lut) { + for (i = 0; i < lut_size; i++) + intel_de_write_fw(dev_priv, PLANE_PRE_CSC_GAMC_DATA(pipe, plane, 0), + pre_csc_lut[i].green); + /* Program the max register to clamp values > 1.0. */ + while (i < 35) + intel_de_write_fw(dev_priv, PLANE_PRE_CSC_GAMC_DATA(pipe, plane, 0), + pre_csc_lut[i++].green); + } else { + for (i = 0; i < lut_size; i++) { + u32 v = (i * ((1 << 16) - 1)) / (lut_size - 1); + + intel_de_write_fw(dev_priv, + PLANE_PRE_CSC_GAMC_DATA(pipe, plane, 0), v); + } + + do { + intel_de_write_fw(dev_priv, PLANE_PRE_CSC_GAMC_DATA(pipe, plane, 0), + 1 << 16); + } while (i++ < 34); + } + + intel_de_write_fw(dev_priv, PLANE_PRE_CSC_GAMC_INDEX(pipe, plane, 0), 0); + } +} + static void xelpd_plane_load_luts(const struct drm_plane_state *plane_state, const struct drm_property_blob *blob, bool is_pre_csc) { + struct drm_color_lut_ext *lut = blob->data; + + if (is_pre_
[PATCH 24/28] drm/i915: Add register definitions for Plane Post CSC
Add macros to define Plane Post CSC registers Signed-off-by: Uma Shankar Signed-off-by: Chaitanya Kumar Borah --- drivers/gpu/drm/i915/i915_reg.h | 73 + 1 file changed, 73 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 633c0d0cb8f4..ea711be031e7 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6244,6 +6244,79 @@ enum skl_power_gate { #define _MMIO_PLANE_GAMC(plane, i, a, b) _MMIO(_PIPE(plane, a, b) + (i) * 4) +/* Display13 Plane Gamma Reg */ +#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1_A0x70160 +#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1_B0x71160 +#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2_A0x70260 +#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2_B0x71260 +#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1(pipe)_PIPE(pipe, _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1_A, \ + _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1_B) +#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2(pipe)_PIPE(pipe, _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2_A, \ + _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2_B) +#define PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1(pipe), \ + _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2(pipe)) + +#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1_A 0x70164 +#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1_B 0x71164 +#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2_A 0x70264 +#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2_B 0x71264 +#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1_A, \ + _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1_B) +#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2_A, \ + _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2_B) +#define PLANE_POST_CSC_GAMC_SEG0_DATA_ENH(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1(pipe), \ + _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2(pipe)) + +#define _PLANE_POST_CSC_GAMC_INDEX_ENH_1_A 0x701d8 +#define _PLANE_POST_CSC_GAMC_INDEX_ENH_1_B 0x711d8 +#define _PLANE_POST_CSC_GAMC_INDEX_ENH_2_A 0x702d8 +#define _PLANE_POST_CSC_GAMC_INDEX_ENH_2_B 0x712d8 +#define _PLANE_POST_CSC_GAMC_INDEX_ENH_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_INDEX_ENH_1_A, \ + _PLANE_POST_CSC_GAMC_INDEX_ENH_1_B) +#define _PLANE_POST_CSC_GAMC_INDEX_ENH_2(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_INDEX_ENH_2_A, \ + _PLANE_POST_CSC_GAMC_INDEX_ENH_2_B) +#define PLANE_POST_CSC_GAMC_INDEX_ENH(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_INDEX_ENH_1(pipe), \ + _PLANE_POST_CSC_GAMC_INDEX_ENH_2(pipe)) + +#define _PLANE_POST_CSC_GAMC_DATA_ENH_1_A 0x701dc +#define _PLANE_POST_CSC_GAMC_DATA_ENH_1_B 0x711dc +#define _PLANE_POST_CSC_GAMC_DATA_ENH_2_A 0x702dc +#define _PLANE_POST_CSC_GAMC_DATA_ENH_2_B 0x712dc +#define _PLANE_POST_CSC_GAMC_DATA_ENH_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_DATA_ENH_1_A, \ + _PLANE_POST_CSC_GAMC_DATA_ENH_1_B) +#define _PLANE_POST_CSC_GAMC_DATA_ENH_2(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_DATA_ENH_2_A, \ + _PLANE_POST_CSC_GAMC_DATA_ENH_2_B) +#define PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_DATA_ENH_1(pipe), \ + _PLANE_POST_CSC_GAMC_DATA_ENH_2(pipe)) + +#define _PLANE_POST_CSC_GAMC_INDEX_1_A 0x704d8 +#define _PLANE_POST_CSC_GAMC_INDEX_1_B 0x714d8 +#define _PLANE_POST_CSC_GAMC_INDEX_2_A 0x705d8 +#define _PLANE_POST_CSC_GAMC_INDEX_2_B 0x715d8 +#define _PLANE_POST_CSC_GAMC_INDEX_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_INDEX_1_A, \ + _PLANE_POST_CSC_GAMC_INDEX_1_B) +#define _PLANE_POST_CSC_GAMC_INDEX_2(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_INDEX_2_A, \ + _PLANE_POST_CSC_GAMC_INDEX_2_B) +#define PLANE_POST_CSC_GAMC_INDEX(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_INDEX_1(pipe), \ + _PLANE_POST_CSC_GAMC_INDEX_2(pipe)) + +#define _PLANE_POST_CSC_GAMC_DATA_1_A 0x704dc +#define _PLANE_POST_CSC_GAMC_DATA_1_B 0x714dc +#define _PLANE_POST_CSC_GAMC_DATA_2_A 0x705dc +#define _PLANE_POST_CSC_GAMC_DATA_2_B 0x715dc +#define _PLANE_POST_CSC_GAMC_DATA_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_DATA_1_A
[PATCH 23/28] drm/i915/color: Add framework to program PRE/POST CSC LUT
From: Chaitanya Kumar Borah Add framework that will help in loading LUT to Pre/Post CSC color blocks. Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 27 ++ drivers/gpu/drm/i915/display/intel_color.h | 2 ++ 2 files changed, 29 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 85c4b6a9d5f9..0d68f8303502 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -85,6 +85,10 @@ struct intel_color_funcs { /* Plane CSC*/ void (*load_plane_csc_matrix)(const struct drm_plane_state *plane_state, const struct drm_property_blob *blob); + + /* Plane Pre/Post CSC */ + void (*load_plane_luts)(const struct drm_plane_state *plane_state, + const struct drm_property_blob *blob, bool is_pre_csc); }; #define CTM_COEFF_SIGN (1ULL << 63) @@ -3775,6 +3779,20 @@ void intel_color_load_plane_csc_matrix(const struct drm_plane_state *plane_state i915->display.funcs.color->load_plane_csc_matrix(plane_state, blob); } +static void xelpd_plane_load_luts(const struct drm_plane_state *plane_state, + const struct drm_property_blob *blob, bool is_pre_csc) +{ +} + +void intel_color_load_plane_luts(const struct drm_plane_state *plane_state, +const struct drm_property_blob *blob, bool is_pre_csc) +{ + struct drm_i915_private *i915 = to_i915(plane_state->plane->dev); + + if (i915->display.funcs.color->load_plane_luts) + i915->display.funcs.color->load_plane_luts(plane_state, blob, is_pre_csc); +} + static const struct intel_color_funcs chv_color_funcs = { .color_check = chv_color_check, .color_commit_arm = i9xx_color_commit_arm, @@ -3823,6 +3841,7 @@ static const struct intel_color_funcs tgl_color_funcs = { .read_csc = icl_read_csc, .get_config = skl_get_config, .load_plane_csc_matrix = xelpd_load_plane_csc_matrix, + .load_plane_luts = xelpd_plane_load_luts, }; static const struct intel_color_funcs icl_color_funcs = { @@ -4053,6 +4072,14 @@ static void apply_colorop(const struct drm_plane_state *plane_state, (*plane_color_ctl) |= PLANE_COLOR_PLANE_CSC_ENABLE; if (state->data && intel_colorop->id == CB_PLANE_CSC) intel_color_load_plane_csc_matrix(plane_state, state->data); + } else if (colorop->type == DRM_COLOROP_1D_LUT) { + if (state->data && intel_colorop->id == CB_PLANE_PRE_CSC_LUT) { + (*plane_color_ctl) |= PLANE_COLOR_PRE_CSC_GAMMA_ENABLE; + intel_color_load_plane_luts(plane_state, state->data, true); + } else if (state->data && intel_colorop->id == CB_PLANE_POST_CSC_LUT) { + (*plane_color_ctl) &= ~PLANE_COLOR_PLANE_GAMMA_DISABLE; + intel_color_load_plane_luts(plane_state, state->data, false); + } } } diff --git a/drivers/gpu/drm/i915/display/intel_color.h b/drivers/gpu/drm/i915/display/intel_color.h index 3f1466f88c11..1830a85a696b 100644 --- a/drivers/gpu/drm/i915/display/intel_color.h +++ b/drivers/gpu/drm/i915/display/intel_color.h @@ -45,5 +45,7 @@ void intel_program_pipeline(const struct drm_plane_state *plane_state, u32 *plane_color_ctl); void intel_color_load_plane_csc_matrix(const struct drm_plane_state *plane_state, const struct drm_property_blob *blob); +void intel_color_load_plane_luts(const struct drm_plane_state *plane_state, +const struct drm_property_blob *blob, bool is_pre_csc); #endif /* __INTEL_COLOR_H__ */ -- 2.42.0
[PATCH 22/28] drm/i915: Add register definitions for Plane Degamma
Add macros to define Plane Degamma registers Signed-off-by: Uma Shankar Signed-off-by: Chaitanya Kumar Borah --- drivers/gpu/drm/i915/i915_reg.h | 51 + 1 file changed, 51 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index e00557e1a57f..633c0d0cb8f4 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3732,6 +3732,7 @@ #define PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709 REG_FIELD_PREP(PLANE_COLOR_CSC_MODE_MASK, 2) #define PLANE_COLOR_CSC_MODE_YUV2020_TO_RGB2020 REG_FIELD_PREP(PLANE_COLOR_CSC_MODE_MASK, 3) #define PLANE_COLOR_CSC_MODE_RGB709_TO_RGB2020 REG_FIELD_PREP(PLANE_COLOR_CSC_MODE_MASK, 4) +#define PLANE_COLOR_PRE_CSC_GAMMA_ENABLE REG_BIT(14) #define PLANE_COLOR_PLANE_GAMMA_DISABLE REG_BIT(13) #define PLANE_COLOR_ALPHA_MASK REG_GENMASK(5, 4) #define PLANE_COLOR_ALPHA_DISABLE REG_FIELD_PREP(PLANE_COLOR_ALPHA_MASK, 0) @@ -6243,6 +6244,56 @@ enum skl_power_gate { #define _MMIO_PLANE_GAMC(plane, i, a, b) _MMIO(_PIPE(plane, a, b) + (i) * 4) +/* Display13 Plane Degmma Reg */ +#define _PLANE_PRE_CSC_GAMC_INDEX_ENH_1_A 0x701d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_ENH_1_B 0x711d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_ENH_2_A 0x702d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_ENH_2_B 0x712d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_ENH_1(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_INDEX_ENH_1_A, \ + _PLANE_PRE_CSC_GAMC_INDEX_ENH_1_B) +#define _PLANE_PRE_CSC_GAMC_INDEX_ENH_2(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_INDEX_ENH_2_A, \ + _PLANE_PRE_CSC_GAMC_INDEX_ENH_2_B) +#define PLANE_PRE_CSC_GAMC_INDEX_ENH(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_PRE_CSC_GAMC_INDEX_ENH_1(pipe), \ + _PLANE_PRE_CSC_GAMC_INDEX_ENH_2(pipe)) +#define PLANE_PAL_PREC_AUTO_INCREMENT REG_BIT(10) + +#define _PLANE_PRE_CSC_GAMC_DATA_ENH_1_A 0x701d4 +#define _PLANE_PRE_CSC_GAMC_DATA_ENH_1_B 0x711d4 +#define _PLANE_PRE_CSC_GAMC_DATA_ENH_2_A 0x702d4 +#define _PLANE_PRE_CSC_GAMC_DATA_ENH_2_B 0x712d4 +#define _PLANE_PRE_CSC_GAMC_DATA_ENH_1(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_DATA_ENH_1_A, \ + _PLANE_PRE_CSC_GAMC_DATA_ENH_1_B) +#define _PLANE_PRE_CSC_GAMC_DATA_ENH_2(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_DATA_ENH_2_A, \ + _PLANE_PRE_CSC_GAMC_DATA_ENH_2_B) +#define PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, i)\ + _MMIO_PLANE_GAMC(plane, i, _PLANE_PRE_CSC_GAMC_DATA_ENH_1(pipe), \ + _PLANE_PRE_CSC_GAMC_DATA_ENH_2(pipe)) + +#define _PLANE_PRE_CSC_GAMC_INDEX_1_A 0x704d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_1_B 0x714d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_2_A 0x705d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_2_B 0x715d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_1(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_INDEX_1_A, \ + _PLANE_PRE_CSC_GAMC_INDEX_1_B) +#define _PLANE_PRE_CSC_GAMC_INDEX_2(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_INDEX_2_A, \ + _PLANE_PRE_CSC_GAMC_INDEX_2_B) +#define PLANE_PRE_CSC_GAMC_INDEX(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_PRE_CSC_GAMC_INDEX_1(pipe), \ + _PLANE_PRE_CSC_GAMC_INDEX_2(pipe)) + +#define _PLANE_PRE_CSC_GAMC_DATA_1_A 0x704d4 +#define _PLANE_PRE_CSC_GAMC_DATA_1_B 0x714d4 +#define _PLANE_PRE_CSC_GAMC_DATA_2_A 0x705d4 +#define _PLANE_PRE_CSC_GAMC_DATA_2_B 0x715d4 +#define _PLANE_PRE_CSC_GAMC_DATA_1(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_DATA_1_A, \ + _PLANE_PRE_CSC_GAMC_DATA_1_B) +#define _PLANE_PRE_CSC_GAMC_DATA_2(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_DATA_2_A, \ + _PLANE_PRE_CSC_GAMC_DATA_2_B) +#define PLANE_PRE_CSC_GAMC_DATA(pipe, plane, i)\ + _MMIO_PLANE_GAMC(plane, i, _PLANE_PRE_CSC_GAMC_DATA_1(pipe), \ + _PLANE_PRE_CSC_GAMC_DATA_2(pipe)) + /* Plane CSC Registers */ #define _PLANE_CSC_RY_GY_1_A 0x70210 #define _PLANE_CSC_RY_GY_2_A 0x70310 -- 2.42.0
[PATCH 21/28] drm/i915/color: Add plane CTM callback for TGL and beyond
Add callback for setting CTM block in platforms TGL and beyond Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 79 ++ 1 file changed, 79 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 8dc72ad25700..85c4b6a9d5f9 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -3688,6 +3688,84 @@ static void icl_read_luts(struct intel_crtc_state *crtc_state) } } +static void xelpd_load_plane_csc_matrix(const struct drm_plane_state *state, + const struct drm_property_blob *blob) +{ + struct drm_i915_private *dev_priv = to_i915(state->plane->dev); + enum pipe pipe = to_intel_plane(state->plane)->pipe; + enum plane_id plane = to_intel_plane(state->plane)->id; + struct drm_color_ctm *ctm; + const u64 *input; + u16 coeffs[9] = {}; + u16 postoff = 0; + int i; + + if (!icl_is_hdr_plane(dev_priv, plane) || !blob) + return; + + ctm = blob->data; + input = ctm->matrix; + + /* +* Convert fixed point S31.32 input to format supported by the +* hardware. +*/ + for (i = 0; i < ARRAY_SIZE(coeffs); i++) { + u64 abs_coeff = ((1ULL << 63) - 1) & input[i]; + + /* +* Clamp input value to min/max supported by +* hardware. +*/ + abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_4_0 - 1); + + /* sign bit */ + if (CTM_COEFF_NEGATIVE(input[i])) + coeffs[i] |= 1 << 15; + + if (abs_coeff < CTM_COEFF_0_125) + coeffs[i] |= (3 << 12) | + ILK_CSC_COEFF_FP(abs_coeff, 12); + else if (abs_coeff < CTM_COEFF_0_25) + coeffs[i] |= (2 << 12) | + ILK_CSC_COEFF_FP(abs_coeff, 11); + else if (abs_coeff < CTM_COEFF_0_5) + coeffs[i] |= (1 << 12) | + ILK_CSC_COEFF_FP(abs_coeff, 10); + else if (abs_coeff < CTM_COEFF_1_0) + coeffs[i] |= ILK_CSC_COEFF_FP(abs_coeff, 9); + else if (abs_coeff < CTM_COEFF_2_0) + coeffs[i] |= (7 << 12) | + ILK_CSC_COEFF_FP(abs_coeff, 8); + else + coeffs[i] |= (6 << 12) | + ILK_CSC_COEFF_FP(abs_coeff, 7); + } + + intel_de_write_fw(dev_priv, PLANE_CSC_COEFF(pipe, plane, 0), + coeffs[0] << 16 | coeffs[1]); + intel_de_write_fw(dev_priv, PLANE_CSC_COEFF(pipe, plane, 1), + coeffs[2] << 16); + + intel_de_write_fw(dev_priv, PLANE_CSC_COEFF(pipe, plane, 2), + coeffs[3] << 16 | coeffs[4]); + intel_de_write_fw(dev_priv, PLANE_CSC_COEFF(pipe, plane, 3), + coeffs[5] << 16); + + intel_de_write_fw(dev_priv, PLANE_CSC_COEFF(pipe, plane, 4), + coeffs[6] << 16 | coeffs[7]); + intel_de_write_fw(dev_priv, PLANE_CSC_COEFF(pipe, plane, 5), + coeffs[8] << 16); + + intel_de_write_fw(dev_priv, PLANE_CSC_PREOFF(pipe, plane, 0), 0); + intel_de_write_fw(dev_priv, PLANE_CSC_PREOFF(pipe, plane, 1), 0); + intel_de_write_fw(dev_priv, PLANE_CSC_PREOFF(pipe, plane, 2), 0); + + intel_de_write_fw(dev_priv, PLANE_CSC_POSTOFF(pipe, plane, 0), postoff); + intel_de_write_fw(dev_priv, PLANE_CSC_POSTOFF(pipe, plane, 1), postoff); + intel_de_write_fw(dev_priv, PLANE_CSC_POSTOFF(pipe, plane, 2), postoff); +} + void intel_color_load_plane_csc_matrix(const struct drm_plane_state *plane_state, const struct drm_property_blob *blob) { @@ -3744,6 +3822,7 @@ static const struct intel_color_funcs tgl_color_funcs = { .lut_equal = icl_lut_equal, .read_csc = icl_read_csc, .get_config = skl_get_config, + .load_plane_csc_matrix = xelpd_load_plane_csc_matrix, }; static const struct intel_color_funcs icl_color_funcs = { -- 2.42.0
[PATCH 20/28] drm/i915/color: Add callbacks to set plane CTM
From: Chaitanya Kumar Borah Add callback to intel color functions for setting plane CTM. Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 22 ++ drivers/gpu/drm/i915/display/intel_color.h | 2 ++ 2 files changed, 24 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 06268e89125e..8dc72ad25700 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -81,6 +81,10 @@ struct intel_color_funcs { * Read config other than LUTs and CSCs, before them. Optional. */ void (*get_config)(struct intel_crtc_state *crtc_state); + + /* Plane CSC*/ + void (*load_plane_csc_matrix)(const struct drm_plane_state *plane_state, + const struct drm_property_blob *blob); }; #define CTM_COEFF_SIGN (1ULL << 63) @@ -3684,6 +3688,15 @@ static void icl_read_luts(struct intel_crtc_state *crtc_state) } } +void intel_color_load_plane_csc_matrix(const struct drm_plane_state *plane_state, + const struct drm_property_blob *blob) +{ + struct drm_i915_private *i915 = to_i915(plane_state->plane->dev); + + if (i915->display.funcs.color->load_plane_csc_matrix) + i915->display.funcs.color->load_plane_csc_matrix(plane_state, blob); +} + static const struct intel_color_funcs chv_color_funcs = { .color_check = chv_color_check, .color_commit_arm = i9xx_color_commit_arm, @@ -3953,6 +3966,15 @@ static void apply_colorop(const struct drm_plane_state *plane_state, struct drm_colorop *colorop, u32 *plane_color_ctl) { + struct drm_colorop_state *state = colorop->state; + struct intel_plane_colorop *intel_colorop = to_intel_plane_colorop(colorop); + + if (colorop->type == DRM_COLOROP_CTM_3X3) { + /* TODO: use intel_color_op state data */ + (*plane_color_ctl) |= PLANE_COLOR_PLANE_CSC_ENABLE; + if (state->data && intel_colorop->id == CB_PLANE_CSC) + intel_color_load_plane_csc_matrix(plane_state, state->data); + } } void intel_program_pipeline(const struct drm_plane_state *plane_state, u32 *plane_color_ctl) diff --git a/drivers/gpu/drm/i915/display/intel_color.h b/drivers/gpu/drm/i915/display/intel_color.h index bde880370ecc..3f1466f88c11 100644 --- a/drivers/gpu/drm/i915/display/intel_color.h +++ b/drivers/gpu/drm/i915/display/intel_color.h @@ -43,5 +43,7 @@ int intel_plane_tf_pipeline_init(struct drm_plane *plane, struct drm_prop_enum_l int intel_plane_color_init(struct drm_plane *plane); void intel_program_pipeline(const struct drm_plane_state *plane_state, u32 *plane_color_ctl); +void intel_color_load_plane_csc_matrix(const struct drm_plane_state *plane_state, + const struct drm_property_blob *blob); #endif /* __INTEL_COLOR_H__ */ -- 2.42.0
[PATCH 19/28] drm/i915/color: Add framework to set colorop
From: Chaitanya Kumar Borah Add infrastructure to set colorop. We iterate through all the color ops in a selected COLOR PIPELINE and set them one by one. Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 31 ++ drivers/gpu/drm/i915/display/intel_color.h | 3 +++ 2 files changed, 34 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index d6d5e56b4f2c..06268e89125e 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -3949,6 +3949,37 @@ struct intel_plane_colorop *intel_plane_colorop_create(enum intel_color_block id return colorop; } +static void apply_colorop(const struct drm_plane_state *plane_state, + struct drm_colorop *colorop, + u32 *plane_color_ctl) +{ +} + +void intel_program_pipeline(const struct drm_plane_state *plane_state, u32 *plane_color_ctl) +{ + struct drm_colorop *colorop; + + colorop = plane_state->color_pipeline; + + while (colorop) { + struct drm_colorop_state *colorop_state; + + if (!colorop) + return; + + /* TODO this is probably wrong */ + colorop_state = colorop->state; + + if (!colorop_state) + return; + + if (!colorop_state->bypass) + apply_colorop(plane_state, colorop, plane_color_ctl); + + colorop = colorop->next; + } +} + int intel_plane_tf_pipeline_init(struct drm_plane *plane, struct drm_prop_enum_list *list) { struct intel_plane *intel_plane = to_intel_plane(plane); diff --git a/drivers/gpu/drm/i915/display/intel_color.h b/drivers/gpu/drm/i915/display/intel_color.h index df0e1f6be067..bde880370ecc 100644 --- a/drivers/gpu/drm/i915/display/intel_color.h +++ b/drivers/gpu/drm/i915/display/intel_color.h @@ -13,6 +13,7 @@ struct intel_crtc; struct drm_i915_private; struct drm_property_blob; struct drm_plane; +struct drm_plane_state; struct drm_prop_enum_list; enum intel_color_block; @@ -40,5 +41,7 @@ struct intel_plane_colorop *intel_colorop_alloc(void); struct intel_plane_colorop *intel_plane_colorop_create(enum intel_color_block id); int intel_plane_tf_pipeline_init(struct drm_plane *plane, struct drm_prop_enum_list *list); int intel_plane_color_init(struct drm_plane *plane); +void intel_program_pipeline(const struct drm_plane_state *plane_state, + u32 *plane_color_ctl); #endif /* __INTEL_COLOR_H__ */ -- 2.42.0
[PATCH 18/28] drm/i915/color: Add and attach COLORPIPELINE plane property
From: Chaitanya Kumar Borah Add supported color pipelines and attach it to plane. Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 37 ++ drivers/gpu/drm/i915/display/intel_color.h | 3 ++ 2 files changed, 40 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 223cd1ff7291..d6d5e56b4f2c 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -4000,6 +4000,43 @@ int intel_plane_tf_pipeline_init(struct drm_plane *plane, struct drm_prop_enum_l return 0; } +int intel_plane_color_init(struct drm_plane *plane) +{ + struct drm_device *dev = plane->dev; + struct drm_property *prop; + struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES]; + int len = 0; + int ret; + + /* Add "Bypass" (i.e. NULL) pipeline */ + pipelines[len].type = 0; + pipelines[len].name = "Bypass"; + len++; + + /* Add pipeline consisting of transfer functions */ + ret = intel_plane_tf_pipeline_init(plane, [len]); + if (ret) + return ret; + len++; + + /* Create COLOR_PIPELINE property and attach */ + prop = drm_property_create_enum(dev, DRM_MODE_PROP_ATOMIC, + "COLOR_PIPELINE", + pipelines, len); + if (!prop) + return -ENOMEM; + + plane->color_pipeline_property = prop; + + drm_object_attach_property(>base, prop, 0); + + /* TODO check if needed */ + if (plane->state) + plane->state->color_pipeline = NULL; + + return 0; +} + void intel_color_crtc_init(struct intel_crtc *crtc) { struct drm_i915_private *i915 = to_i915(crtc->base.dev); diff --git a/drivers/gpu/drm/i915/display/intel_color.h b/drivers/gpu/drm/i915/display/intel_color.h index e0b75dcb1b65..df0e1f6be067 100644 --- a/drivers/gpu/drm/i915/display/intel_color.h +++ b/drivers/gpu/drm/i915/display/intel_color.h @@ -16,6 +16,8 @@ struct drm_plane; struct drm_prop_enum_list; enum intel_color_block; +#define MAX_COLOR_PIPELINES 5 + void intel_color_init_hooks(struct drm_i915_private *i915); int intel_color_init(struct drm_i915_private *i915); void intel_color_crtc_init(struct intel_crtc *crtc); @@ -37,5 +39,6 @@ void intel_color_assert_luts(const struct intel_crtc_state *crtc_state); struct intel_plane_colorop *intel_colorop_alloc(void); struct intel_plane_colorop *intel_plane_colorop_create(enum intel_color_block id); int intel_plane_tf_pipeline_init(struct drm_plane *plane, struct drm_prop_enum_list *list); +int intel_plane_color_init(struct drm_plane *plane); #endif /* __INTEL_COLOR_H__ */ -- 2.42.0
[PATCH 17/28] drm/i915: Define segmented Lut and add capabilities to colorop
This defines the lut segments and create the color pipeline Signed-off-by: Uma Shankar Signed-off-by: Chaitanya Kumar Borah --- drivers/gpu/drm/i915/display/intel_color.c | 109 + 1 file changed, 109 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index e223edbe4c13..223cd1ff7291 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -3811,6 +3811,105 @@ static const struct intel_color_funcs ilk_color_funcs = { .get_config = ilk_get_config, }; +static const struct drm_color_lut_range xelpd_degamma_hdr[] = { + /* segment 1 */ + { + .flags = (DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_NON_DECREASING), + .count = 128, + .input_bpc = 24, .output_bpc = 16, + .start = 0, .end = (1 << 24) - 1, + .min = 0, .max = (1 << 24) - 1, + }, + /* segment 2 */ + { + .flags = (DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 24, .output_bpc = 16, + .start = (1 << 24) - 1, .end = 1 << 24, + .min = 0, .max = (1 << 27) - 1, + }, + /* Segment 3 */ + { + .flags = (DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 24, .output_bpc = 16, + .start = 1 << 24, .end = 3 << 24, + .min = 0, .max = (1 << 27) - 1, + }, + /* Segment 4 */ + { + .flags = (DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 24, .output_bpc = 16, + .start = 3 << 24, .end = 7 << 24, + .min = 0, .max = (1 << 27) - 1, + } +}; + +/* FIXME input bpc? */ +static const struct drm_color_lut_range xelpd_gamma_hdr[] = { + /* +* ToDo: Add Segment 1 +* There is an optional fine segment added with 9 lut values +* Will be added later +*/ + + /* segment 2 */ + { + .flags = (DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_NON_DECREASING), + .count = 32, + .input_bpc = 24, .output_bpc = 16, + .start = 0, .end = (1 << 24) - 1, + .min = 0, .max = (1 << 24) - 1, + }, + /* segment 3 */ + { + .flags = (DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 24, .output_bpc = 16, + .start = (1 << 24) - 1, .end = 1 << 24, + .min = 0, .max = 1 << 24, + }, + /* Segment 4 */ + { + .flags = (DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 24, .output_bpc = 16, + .start = 1 << 24, .end = 3 << 24, + .min = 0, .max = (3 << 24), + }, + /* Segment 5 */ + { + .flags = (DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 24, .output_bpc = 16, + .start = 3 << 24, .end = 7 << 24, + .min = 0, .max = (7 << 24), + }, +}; + /* TODO: Move to another file */ struct intel_plane_colorop *intel_colorop_alloc(void) { @@ -3865,6 +3964,11 @@ int intel_plane_tf_pipeline_init(struct drm_plane *plane, struct drm_prop_enum_l if (ret) return ret; + if (icl_is_hdr_plane(i915, to_intel_plane(plane)->id)) { + drm_colorop_lutcaps_init(>base, plane, xelp
[PATCH 16/28] drm/i915/color: Create a transfer function color pipeline
From: Chaitanya Kumar Borah Add a color pipeline with three colorops in the sequence 1D LUT - CTM - 1D LUT This pipeline can be used to do any color space conversion or HDR tone mapping Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 42 ++ drivers/gpu/drm/i915/display/intel_color.h | 3 ++ 2 files changed, 45 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index e187135d4363..e223edbe4c13 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -28,6 +28,7 @@ #include "intel_de.h" #include "intel_display_types.h" #include "intel_dsb.h" +#include "skl_universal_plane.h" struct intel_color_funcs { int (*color_check)(struct intel_crtc_state *crtc_state); @@ -3849,6 +3850,47 @@ struct intel_plane_colorop *intel_plane_colorop_create(enum intel_color_block id return colorop; } +int intel_plane_tf_pipeline_init(struct drm_plane *plane, struct drm_prop_enum_list *list) +{ + struct intel_plane *intel_plane = to_intel_plane(plane); + struct intel_plane_colorop *colorop; + struct drm_device *dev = plane->dev; + struct drm_i915_private *i915 = to_i915(dev); + int ret; + struct drm_colorop *prev_op; + + colorop = intel_plane_colorop_create(CB_PLANE_PRE_CSC_LUT); + + ret = drm_colorop_init(dev, >base, plane, DRM_COLOROP_1D_LUT); + if (ret) + return ret; + + list->type = colorop->base.base.id; + list->name = kasprintf(GFP_KERNEL, "Color Pipeline %d", colorop->base.base.id); + + /* TODO: handle failures and clean up*/ + prev_op = >base; + + if (icl_is_hdr_plane(i915, intel_plane->id)) { + colorop = intel_plane_colorop_create(CB_PLANE_CSC); + ret = drm_colorop_init(dev, >base, plane, DRM_COLOROP_CTM_3X3); + if (ret) + return ret; + + drm_colorop_set_next_property(prev_op, >base); + prev_op = >base; + } + + colorop = intel_plane_colorop_create(CB_PLANE_POST_CSC_LUT); + ret = drm_colorop_init(dev, >base, plane, DRM_COLOROP_1D_LUT); + if (ret) + return ret; + + drm_colorop_set_next_property(prev_op, >base); + + return 0; +} + void intel_color_crtc_init(struct intel_crtc *crtc) { struct drm_i915_private *i915 = to_i915(crtc->base.dev); diff --git a/drivers/gpu/drm/i915/display/intel_color.h b/drivers/gpu/drm/i915/display/intel_color.h index d03dad425671..e0b75dcb1b65 100644 --- a/drivers/gpu/drm/i915/display/intel_color.h +++ b/drivers/gpu/drm/i915/display/intel_color.h @@ -12,6 +12,8 @@ struct intel_crtc_state; struct intel_crtc; struct drm_i915_private; struct drm_property_blob; +struct drm_plane; +struct drm_prop_enum_list; enum intel_color_block; void intel_color_init_hooks(struct drm_i915_private *i915); @@ -34,5 +36,6 @@ bool intel_color_lut_equal(const struct intel_crtc_state *crtc_state, void intel_color_assert_luts(const struct intel_crtc_state *crtc_state); struct intel_plane_colorop *intel_colorop_alloc(void); struct intel_plane_colorop *intel_plane_colorop_create(enum intel_color_block id); +int intel_plane_tf_pipeline_init(struct drm_plane *plane, struct drm_prop_enum_list *list); #endif /* __INTEL_COLOR_H__ */ -- 2.42.0
[PATCH 15/28] drm/i915/color: Add helper to create intel colorop
From: Chaitanya Kumar Borah Add intel colorop create helper Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 14 ++ drivers/gpu/drm/i915/display/intel_color.h | 2 ++ 2 files changed, 16 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 949c2efe105f..e187135d4363 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -3835,6 +3835,20 @@ struct intel_plane_colorop *intel_colorop_alloc(void) return colorop; } +struct intel_plane_colorop *intel_plane_colorop_create(enum intel_color_block id) +{ + struct intel_plane_colorop *colorop; + + colorop = intel_colorop_alloc(); + + if (IS_ERR(colorop)) + return colorop; + + colorop->id = id; + + return colorop; +} + void intel_color_crtc_init(struct intel_crtc *crtc) { struct drm_i915_private *i915 = to_i915(crtc->base.dev); diff --git a/drivers/gpu/drm/i915/display/intel_color.h b/drivers/gpu/drm/i915/display/intel_color.h index e111d115724c..d03dad425671 100644 --- a/drivers/gpu/drm/i915/display/intel_color.h +++ b/drivers/gpu/drm/i915/display/intel_color.h @@ -12,6 +12,7 @@ struct intel_crtc_state; struct intel_crtc; struct drm_i915_private; struct drm_property_blob; +enum intel_color_block; void intel_color_init_hooks(struct drm_i915_private *i915); int intel_color_init(struct drm_i915_private *i915); @@ -32,5 +33,6 @@ bool intel_color_lut_equal(const struct intel_crtc_state *crtc_state, bool is_pre_csc_lut); void intel_color_assert_luts(const struct intel_crtc_state *crtc_state); struct intel_plane_colorop *intel_colorop_alloc(void); +struct intel_plane_colorop *intel_plane_colorop_create(enum intel_color_block id); #endif /* __INTEL_COLOR_H__ */ -- 2.42.0
[PATCH 14/28] drm/i915/color: Add helper to allocate intel colorop
From: Chaitanya Kumar Borah Add helper to allocate memory for intel colorop Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 25 ++ drivers/gpu/drm/i915/display/intel_color.h | 1 + 2 files changed, 26 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index ca7112b32cb3..949c2efe105f 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -3810,6 +3810,31 @@ static const struct intel_color_funcs ilk_color_funcs = { .get_config = ilk_get_config, }; +/* TODO: Move to another file */ +struct intel_plane_colorop *intel_colorop_alloc(void) +{ + struct intel_plane_colorop *colorop; + struct intel_plane_colorop_state *colorop_state; + + colorop = kzalloc(sizeof(*colorop), GFP_KERNEL); + if (!colorop) + return ERR_PTR(-ENOMEM); + + colorop_state = kzalloc(sizeof(*colorop_state), GFP_KERNEL); + if (!colorop_state) { + kfree(colorop); + return ERR_PTR(-ENOMEM); + } + + /* TODO: Add color op reset +* intel_colorop_state_reset(plane_state, plane); +*/ + + colorop->base.state = _state->uapi; + + return colorop; +} + void intel_color_crtc_init(struct intel_crtc *crtc) { struct drm_i915_private *i915 = to_i915(crtc->base.dev); diff --git a/drivers/gpu/drm/i915/display/intel_color.h b/drivers/gpu/drm/i915/display/intel_color.h index 8ecd36149def..e111d115724c 100644 --- a/drivers/gpu/drm/i915/display/intel_color.h +++ b/drivers/gpu/drm/i915/display/intel_color.h @@ -31,5 +31,6 @@ bool intel_color_lut_equal(const struct intel_crtc_state *crtc_state, const struct drm_property_blob *blob2, bool is_pre_csc_lut); void intel_color_assert_luts(const struct intel_crtc_state *crtc_state); +struct intel_plane_colorop *intel_colorop_alloc(void); #endif /* __INTEL_COLOR_H__ */ -- 2.42.0
[PATCH 13/28] drm/i915: Add intel_color_op
From: Chaitanya Kumar Borah Add data structure to store intel specific details of colorop Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- .../gpu/drm/i915/display/intel_display_types.h | 17 + 1 file changed, 17 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 01eb6e4e6049..edc61ea0fe29 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1606,6 +1606,8 @@ struct intel_watermark_params { #define to_intel_plane(x) container_of(x, struct intel_plane, base) #define to_intel_plane_state(x) container_of(x, struct intel_plane_state, uapi) #define intel_fb_obj(x) ((x) ? to_intel_bo((x)->obj[0]) : NULL) +#define to_intel_plane_colorop(x) container_of(x, struct intel_plane_colorop, base) +#define to_intel_colorop_state(x) container_of(x, struct intel_plane_colorop_state, uapi) struct intel_hdmi { i915_reg_t hdmi_reg; @@ -1915,6 +1917,21 @@ struct intel_dp_mst_encoder { struct intel_connector *connector; }; +struct intel_plane_colorop { + struct drm_colorop base; + enum intel_color_block id; +}; + +struct intel_plane_colorop_state { + struct drm_colorop_state uapi; + + /* TODO: Add hw implementation */ + struct { + bool active, enable; + struct drm_property_blob *data; + } hw; +}; + static inline struct intel_encoder * intel_attached_encoder(struct intel_connector *connector) { -- 2.42.0
[PATCH 12/28] drm/i915: Add identifiers for intel color blocks
From: Chaitanya Kumar Borah Add macros to identify intel color blocks. It will help in mapping drm_color_ops to intel color HW blocks Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_display_limits.h | 13 + 1 file changed, 13 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display_limits.h b/drivers/gpu/drm/i915/display/intel_display_limits.h index 5126d0b5ae5d..67ceb79309f2 100644 --- a/drivers/gpu/drm/i915/display/intel_display_limits.h +++ b/drivers/gpu/drm/i915/display/intel_display_limits.h @@ -121,4 +121,17 @@ enum hpd_pin { HPD_NUM_PINS }; +/* + * Intel Color Blocks + * + */ + +enum intel_color_block { + CB_PLANE_PRE_CSC_LUT, + CB_PLANE_CSC, + CB_PLANE_POST_CSC_LUT, + + I915_MAX_CB +}; + #endif /* __INTEL_DISPLAY_LIMITS_H__ */ -- 2.42.0
[PATCH 11/28] drm: Define helper for adding capability property for 1D LUT
This adds helper functions to create 1D Lut color block capabilities. It exposes the hardware block as segments which are converted to blob and passed in the property. Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- drivers/gpu/drm/drm_colorop.c | 24 +++- include/drm/drm_colorop.h | 4 +++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c index cfdc8e751012..98aef26c0c55 100644 --- a/drivers/gpu/drm/drm_colorop.c +++ b/drivers/gpu/drm/drm_colorop.c @@ -43,7 +43,6 @@ static const struct drm_prop_enum_list drm_colorop_curve_1d_type_enum_list[] = { }; /* Init Helpers */ -__maybe_unused static int drm_create_colorop_capability_prop(struct drm_device *dev, struct drm_colorop *colorop, struct drm_property_blob *blob) @@ -65,6 +64,29 @@ static int drm_create_colorop_capability_prop(struct drm_device *dev, return 0; } +int drm_colorop_lutcaps_init(struct drm_colorop *colorop, +struct drm_plane *plane, +const struct drm_color_lut_range *ranges, +size_t length) +{ + struct drm_device *dev = plane->dev; + struct drm_property_blob *blob; + + /* Create Color Caps property for 1D LUT */ + if (colorop->type != DRM_COLOROP_1D_LUT) + return -EINVAL; + + if (WARN_ON(length == 0 || length % sizeof(ranges[0]) != 0)) + return -EINVAL; + + blob = drm_property_create_blob(plane->dev, length, ranges); + if (IS_ERR(blob)) + return PTR_ERR(blob); + + return drm_create_colorop_capability_prop(dev, colorop, blob); +} +EXPORT_SYMBOL(drm_colorop_lutcaps_init); + int drm_colorop_init(struct drm_device *dev, struct drm_colorop *colorop, struct drm_plane *plane, enum drm_colorop_type type) { diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h index f417e109c40a..d15d5b489401 100644 --- a/include/drm/drm_colorop.h +++ b/include/drm/drm_colorop.h @@ -233,7 +233,9 @@ static inline struct drm_colorop *drm_colorop_find(struct drm_device *dev, int drm_colorop_init(struct drm_device *dev, struct drm_colorop *colorop, struct drm_plane *plane, enum drm_colorop_type type); - +int drm_colorop_lutcaps_init(struct drm_colorop *colorop, struct drm_plane *plane, +const struct drm_color_lut_range *ranges, +size_t length); struct drm_colorop_state * drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colorop); -- 2.42.0
[PATCH 10/28] drm: Define helper to create color ops capability property
Add a helper to create capability property for a colorop Signed-off-by: Uma Shankar Signed-off-by: Chaitanya Kumar Borah --- drivers/gpu/drm/drm_colorop.c | 21 + 1 file changed, 21 insertions(+) diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c index 4d57eaef04aa..cfdc8e751012 100644 --- a/drivers/gpu/drm/drm_colorop.c +++ b/drivers/gpu/drm/drm_colorop.c @@ -43,6 +43,27 @@ static const struct drm_prop_enum_list drm_colorop_curve_1d_type_enum_list[] = { }; /* Init Helpers */ +__maybe_unused +static int drm_create_colorop_capability_prop(struct drm_device *dev, + struct drm_colorop *colorop, + struct drm_property_blob *blob) +{ + struct drm_property *prop = NULL; + + prop = drm_property_create(dev, DRM_MODE_PROP_BLOB | + DRM_MODE_PROP_ATOMIC | + DRM_MODE_PROP_IMMUTABLE, + "HW_CAPS", 1); + if (!prop) + return -ENOMEM; + + colorop->hw_caps_property = prop; + drm_object_attach_property(>base, + colorop->hw_caps_property, + blob->base.id); + + return 0; +} int drm_colorop_init(struct drm_device *dev, struct drm_colorop *colorop, struct drm_plane *plane, enum drm_colorop_type type) -- 2.42.0
[PATCH 09/28] drm: Add Color ops capability property
Add capability property which a colorop can expose it's hardware's abilities. It's a blob property that can be filled with respective data structures depending on the colorop. The user space is expected to read this property and program the colorop accordingly. Signed-off-by: Uma Shankar Signed-off-by: Chaitanya Kumar Borah --- drivers/gpu/drm/drm_atomic_uapi.c | 3 +++ include/drm/drm_colorop.h | 13 + 2 files changed, 16 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 9f6a3a1c8020..95f1df73209c 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -770,6 +770,9 @@ drm_atomic_colorop_get_property(struct drm_colorop *colorop, *val = state->curve_1d_type; } else if (property == colorop->data_property) { *val = (state->data) ? state->data->base.id : 0; + } else if (property == colorop->hw_caps_property) { + *val = state->hw_caps ? + state->hw_caps->base.id : 0; } else { return -EINVAL; } diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h index 5b8c36538491..f417e109c40a 100644 --- a/include/drm/drm_colorop.h +++ b/include/drm/drm_colorop.h @@ -59,6 +59,12 @@ struct drm_colorop_state { */ enum drm_colorop_curve_1d_type curve_1d_type; + /** +* @hw_caps: +* +*/ + struct drm_property_blob *hw_caps; + /** * @data: * @@ -167,6 +173,13 @@ struct drm_colorop { */ struct drm_property *bypass_property; + /** +* @hwlut_caps_property: +* +* Property to expose hardware lut capbilities. +*/ + struct drm_property *hw_caps_property; + /** * @curve_1d_type: * -- 2.42.0
[PATCH 08/28] drm: Add Color lut range attributes
This defines a new structure to define color lut ranges, along with related macro definitions and enums. This will help describe segmented lut ranges/PWL LUTs in the hardware. Signed-off-by: Uma Shankar Signed-off-by: Chaitanya Kumar Borah --- include/uapi/drm/drm_mode.h | 58 + 1 file changed, 58 insertions(+) diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index af67f32e0087..376498715d0e 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -1014,6 +1014,64 @@ struct hdr_output_metadata { DRM_MODE_PAGE_FLIP_ASYNC | \ DRM_MODE_PAGE_FLIP_TARGET) +/** + * DRM_MODE_LUT_INTERPOLATE + * + * linearly interpolate between the points + */ +#define DRM_MODE_LUT_INTERPOLATE BIT(0) + +/** + * DRM_MODE_LUT_REUSE_LAST + * + * the last value of the previous range is the + * first value of the current range. + */ +#define DRM_MODE_LUT_REUSE_LAST BIT(1) + +/** + * DRM_MODE_LUT_NON_DECREASING + * + * the curve must be non-decreasing + */ +#define DRM_MODE_LUT_NON_DECREASING BIT(2) + +/** + * DRM_MODE_LUT_REFLECT_NEGATIVE + * + * the curve is reflected across origin for negative inputs + */ +#define DRM_MODE_LUT_REFLECT_NEGATIVE BIT(3) + +/** + * DRM_MODE_LUT_SINGLE_CHANNEL + * + * the same curve (red) is used for blue and green channels as well + */ +#define DRM_MODE_LUT_SINGLE_CHANNEL BIT(4) + +/** + * struct drm_color_lut_range + * + * structure to advertise capability of a color hardware + * block that accepts LUT values. It can represent LUTs with + * varied number of entries and distributions + * (Multi segmented, Logarithmic etc). + */ + +struct drm_color_lut_range { + /* DRM_MODE_LUT_* */ + __u32 flags; + /* number of points on the curve */ + __u16 count; + /* input/output bits per component */ + __u8 input_bpc, output_bpc; + /* input start/end values */ + __s32 start, end; + /* output min/max values */ + __s32 min, max; +}; + /* * Request a page flip on the specified crtc. * -- 2.42.0
[PATCH 07/28] drm: Add 1D LUT color op
From: Chaitanya Kumar Borah Add support for color ops that can be programmed by 1 dimensional Look Up Tables. Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- drivers/gpu/drm/drm_atomic_uapi.c | 3 +++ drivers/gpu/drm/drm_colorop.c | 2 +- include/uapi/drm/drm_mode.h | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index c54b0d6c133e..9f6a3a1c8020 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -719,6 +719,9 @@ static int drm_atomic_color_set_data_property(struct drm_colorop *colorop, case DRM_COLOROP_CTM_3X3: size = sizeof(struct drm_color_ctm); break; + case DRM_COLOROP_1D_LUT: + elem_size = sizeof(struct drm_color_lut_ext); + break; default: /* should never get here */ return -EINVAL; diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c index 6bae6dc8e54b..4d57eaef04aa 100644 --- a/drivers/gpu/drm/drm_colorop.c +++ b/drivers/gpu/drm/drm_colorop.c @@ -107,7 +107,7 @@ int drm_colorop_init(struct drm_device *dev, struct drm_colorop *colorop, 0); /* data */ - if (type == DRM_COLOROP_CTM_3X4 || type == DRM_COLOROP_CTM_3X3) { + if (type == DRM_COLOROP_CTM_3X4 || type == DRM_COLOROP_CTM_3X3 || DRM_COLOROP_1D_LUT) { prop = drm_property_create(dev, DRM_MODE_PROP_ATOMIC | DRM_MODE_PROP_BLOB, "DATA", 0); if (!prop) diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index bbc5be97c80f..af67f32e0087 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -885,6 +885,7 @@ struct drm_color_lut_ext { enum drm_colorop_type { DRM_COLOROP_1D_CURVE, + DRM_COLOROP_1D_LUT, DRM_COLOROP_CTM_3X3, DRM_COLOROP_CTM_3X4, }; -- 2.42.0
[PATCH 06/28] drm: Add Enhanced LUT precision structure
Existing LUT precision structure is having only 16 bit precision. This is not enough for upcoming enhanced hardwares and advance usecases like HDR processing. Hence added a new structure with 32 bit precision values. Signed-off-by: Uma Shankar Signed-off-by: Chaitanya Kumar Borah --- include/drm/drm_color_mgmt.h | 23 +++ include/uapi/drm/drm_mode.h | 17 + 2 files changed, 40 insertions(+) diff --git a/include/drm/drm_color_mgmt.h b/include/drm/drm_color_mgmt.h index ed81741036d7..72a08b5f7d14 100644 --- a/include/drm/drm_color_mgmt.h +++ b/include/drm/drm_color_mgmt.h @@ -50,6 +50,29 @@ static inline u32 drm_color_lut_extract(u32 user_input, int bit_precision) (1 << 16) - 1); } +/* TODO: Add uapi documentation + * Added to accommodate enhanced LUT precision. + * Max LUT precision is 32 bits. + */ +static inline u64 drm_color_lut_extract_ext(u64 user_input, u32 bit_precision) +{ + u64 val = user_input & 0x; + u32 max; + + if (bit_precision > 32) + return 0; + + max = 0x >> (32 - bit_precision); + /* Round only if we're not using full precision. */ + if (bit_precision < 32) { + val += 1UL << (32 - bit_precision - 1); + val >>= 32 - bit_precision; + } + + return ((user_input & 0x) | + clamp_val(val, 0, max)); +} + u64 drm_color_ctm_s31_32_to_qm_n(u64 user_input, u32 m, u32 n); void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc, diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 68696253867e..bbc5be97c80f 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -866,6 +866,23 @@ struct drm_color_lut { __u16 reserved; }; +/** + * struct drm_color_lut_ext - Represents high precision lut values + * + * Creating 64 bit palette entries for better data + * precision. This will be required for HDR and + * similar color processing usecases. + */ +struct drm_color_lut_ext { + /* +* Data is U32.32 fixed point format. +*/ + __u64 red; + __u64 green; + __u64 blue; + __u64 reserved; +}; + enum drm_colorop_type { DRM_COLOROP_1D_CURVE, DRM_COLOROP_CTM_3X3, -- 2.42.0
[PATCH 05/28] drm: Add support for 3x3 CTM
From: Chaitanya Kumar Borah Add support for 3x3 Color Transformation Matrices in Color Pipeline. Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- drivers/gpu/drm/drm_atomic_uapi.c | 3 +++ drivers/gpu/drm/drm_colorop.c | 2 +- include/uapi/drm/drm_mode.h | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index e7bf1fb054af..c54b0d6c133e 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -716,6 +716,9 @@ static int drm_atomic_color_set_data_property(struct drm_colorop *colorop, case DRM_COLOROP_CTM_3X4: size = sizeof(struct drm_color_ctm_3x4); break; + case DRM_COLOROP_CTM_3X3: + size = sizeof(struct drm_color_ctm); + break; default: /* should never get here */ return -EINVAL; diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c index 462ffec42cdf..6bae6dc8e54b 100644 --- a/drivers/gpu/drm/drm_colorop.c +++ b/drivers/gpu/drm/drm_colorop.c @@ -107,7 +107,7 @@ int drm_colorop_init(struct drm_device *dev, struct drm_colorop *colorop, 0); /* data */ - if (type == DRM_COLOROP_CTM_3X4) { + if (type == DRM_COLOROP_CTM_3X4 || type == DRM_COLOROP_CTM_3X3) { prop = drm_property_create(dev, DRM_MODE_PROP_ATOMIC | DRM_MODE_PROP_BLOB, "DATA", 0); if (!prop) diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index f16318f1785f..68696253867e 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -868,6 +868,7 @@ struct drm_color_lut { enum drm_colorop_type { DRM_COLOROP_1D_CURVE, + DRM_COLOROP_CTM_3X3, DRM_COLOROP_CTM_3X4, }; -- 2.42.0
[PATCH 04/28] drm: Fix error logging in set Color Pipeline
From: Chaitanya Kumar Borah Fix error logging in set Color Pipeline Note: This patch can be squashed with the following patch ("drm/colorop: Introduce DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE") [1] [1] https://patchwork.freedesktop.org/patch/566623/?series=123446=3 Signed-off-by: Chaitanya Kumar Borah --- drivers/gpu/drm/drm_atomic_uapi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 64657d961755..e7bf1fb054af 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -570,14 +570,14 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane, } else if (property == plane->color_encoding_property) { if (file_priv->plane_color_pipeline) { drm_dbg_atomic(dev, - "Setting COLOR_PIPELINE plane property not permitted when DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE is set\n"); + "Setting COLOR_ENCODING plane property not permitted when DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE is set\n"); return -EINVAL; } state->color_encoding = val; } else if (property == plane->color_range_property) { if (file_priv->plane_color_pipeline) { drm_dbg_atomic(dev, - "Setting COLOR_PIPELINE plane property not permitted when DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE is set\n"); + "Setting COLOR_RANGE plane property not permitted when DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE is set\n"); return -EINVAL; } state->color_range = val; -- 2.42.0
[PATCH 03/28] drm: handle NULL next colorop in drm_colorop_set_next_property
From: Chaitanya Kumar Borah In scenarios, where there is only one colorop in a colorpipeline, the user of the helper drm_colorop_set_next_property could use it to set the next colorop as NULL explicitly. Make the helper handle this case. Note: This patch can be squashed with following patch ("drm/colorop: Add NEXT property") [1] [1] https://patchwork.freedesktop.org/patch/566588/?series=123446=3 Signed-off-by: Chaitanya Kumar Borah --- drivers/gpu/drm/drm_colorop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c index 67e6efc90803..462ffec42cdf 100644 --- a/drivers/gpu/drm/drm_colorop.c +++ b/drivers/gpu/drm/drm_colorop.c @@ -286,7 +286,7 @@ void drm_colorop_set_next_property(struct drm_colorop *colorop, struct drm_color drm_object_property_set_value(>base, colorop->next_property, - next->base.id); + next ? next->base.id : 0); colorop->next = next; } EXPORT_SYMBOL(drm_colorop_set_next_property); -- 2.42.0
[PATCH 02/28] drm: Add missing function declarations
From: Chaitanya Kumar Borah add missing declarations to avoid warnings. Note: This patch should be squashed with patches it fixes in the colorop series by Harry [1] ("drm/colorop: Introduce new drm_colorop mode object") [2] ("drm/plane: Add COLOR PIPELINE property") [3] [1] https://patchwork.freedesktop.org/series/123446/ [2] https://patchwork.freedesktop.org/patch/566617/?series=123446=3 [3] https://patchwork.freedesktop.org/patch/566616/?series=123446=3 Signed-off-by: Chaitanya Kumar Borah --- include/drm/drm_atomic.h | 3 +++ include/drm/drm_colorop.h | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 898b02689d6d..5cf025895baf 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -847,6 +847,9 @@ drm_atomic_add_affected_connectors(struct drm_atomic_state *state, int __must_check drm_atomic_add_affected_planes(struct drm_atomic_state *state, struct drm_crtc *crtc); +int __must_check +drm_atomic_add_affected_colorops(struct drm_atomic_state *state, +struct drm_plane *plane); int __must_check drm_atomic_check_only(struct drm_atomic_state *state); int __must_check drm_atomic_commit(struct drm_atomic_state *state); diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h index faca6eba10e1..5b8c36538491 100644 --- a/include/drm/drm_colorop.h +++ b/include/drm/drm_colorop.h @@ -249,7 +249,8 @@ const char *drm_get_color_pipeline_name(struct drm_colorop *colorop); const char *drm_get_colorop_type_name(enum drm_colorop_type type); const char *drm_get_colorop_curve_1d_type_name(enum drm_colorop_curve_1d_type type); - +void drm_colorop_destroy_state(struct drm_colorop *colorop, + struct drm_colorop_state *state); void drm_colorop_set_next_property(struct drm_colorop *colorop, struct drm_colorop *next); uint32_t drm_colorop_get_next_property(struct drm_colorop *colorop); struct drm_colorop *drm_colorop_get_next(struct drm_colorop *colorop); -- 2.42.0
[PATCH 01/28] [NOT FOR REVIEW] drm: color pipeline base work
From: Harry Wentland This is a squashed patch based on a series sent out by Harry wentland. It contains all the changes in the series(v3) currently under review below. https://patchwork.freedesktop.org/patch/566614/?series=123446=3 This patch lays the ground work for incremental changes and Intel specific pipeline changes. NOTE: This patch is not meant for review. Any review related to this patch should be done on the original series. In order not to diverge the discussion from the main series. Signed-off-by: Harry Wentland Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- Documentation/gpu/rfc/color_pipeline.rst | 352 drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/drm_atomic.c | 147 drivers/gpu/drm/drm_atomic_helper.c | 12 + drivers/gpu/drm/drm_atomic_state_helper.c | 5 + drivers/gpu/drm/drm_atomic_uapi.c | 161 drivers/gpu/drm/drm_colorop.c | 292 +++ drivers/gpu/drm/drm_ioctl.c | 7 + drivers/gpu/drm/drm_mode_config.c | 7 + drivers/gpu/drm/tests/Makefile| 4 +- drivers/gpu/drm/tests/drm_fixp_test.c | 69 ++ drivers/gpu/drm/vkms/Kconfig | 5 + drivers/gpu/drm/vkms/Makefile | 4 +- drivers/gpu/drm/vkms/tests/.kunitconfig | 4 + drivers/gpu/drm/vkms/tests/vkms_color_tests.c | 355 drivers/gpu/drm/vkms/vkms_colorop.c | 115 +++ drivers/gpu/drm/vkms/vkms_composer.c | 117 ++- drivers/gpu/drm/vkms/vkms_drv.h | 8 + drivers/gpu/drm/vkms/vkms_luts.c | 802 ++ drivers/gpu/drm/vkms/vkms_luts.h | 12 + drivers/gpu/drm/vkms/vkms_plane.c | 2 + include/drm/drm_atomic.h | 84 ++ include/drm/drm_atomic_uapi.h | 3 + include/drm/drm_colorop.h | 258 ++ include/drm/drm_file.h| 7 + include/drm/drm_fixed.h | 18 + include/drm/drm_mode_config.h | 18 + include/drm/drm_plane.h | 10 + include/uapi/drm/drm.h| 18 + include/uapi/drm/drm_mode.h | 6 + 30 files changed, 2899 insertions(+), 4 deletions(-) create mode 100644 Documentation/gpu/rfc/color_pipeline.rst create mode 100644 drivers/gpu/drm/drm_colorop.c create mode 100644 drivers/gpu/drm/tests/drm_fixp_test.c create mode 100644 drivers/gpu/drm/vkms/tests/.kunitconfig create mode 100644 drivers/gpu/drm/vkms/tests/vkms_color_tests.c create mode 100644 drivers/gpu/drm/vkms/vkms_colorop.c create mode 100644 drivers/gpu/drm/vkms/vkms_luts.c create mode 100644 drivers/gpu/drm/vkms/vkms_luts.h create mode 100644 include/drm/drm_colorop.h diff --git a/Documentation/gpu/rfc/color_pipeline.rst b/Documentation/gpu/rfc/color_pipeline.rst new file mode 100644 index ..efc70570a592 --- /dev/null +++ b/Documentation/gpu/rfc/color_pipeline.rst @@ -0,0 +1,352 @@ + +Linux Color Pipeline API + + +What problem are we solving? + + +We would like to support pre-, and post-blending complex color +transformations in display controller hardware in order to allow for +HW-supported HDR use-cases, as well as to provide support to +color-managed applications, such as video or image editors. + +It is possible to support an HDR output on HW supporting the Colorspace +and HDR Metadata drm_connector properties, but that requires the +compositor or application to render and compose the content into one +final buffer intended for display. Doing so is costly. + +Most modern display HW offers various 1D LUTs, 3D LUTs, matrices, and other +operations to support color transformations. These operations are often +implemented in fixed-function HW and therefore much more power efficient than +performing similar operations via shaders or CPU. + +We would like to make use of this HW functionality to support complex color +transformations with no, or minimal CPU or shader load. + + +How are other OSes solving this problem? + + +The most widely supported use-cases regard HDR content, whether video or +gaming. + +Most OSes will specify the source content format (color gamut, encoding transfer +function, and other metadata, such as max and average light levels) to a driver. +Drivers will then program their fixed-function HW accordingly to map from a +source content buffer's space to a display's space. + +When fixed-function HW is not available the compositor will assemble a shader to +ask the GPU to perform the transformation from the source content format to the +display's format. + +A compositor's mapping function and a driver's mapping function are usually +entirely separate concepts. On OSes where a HW vendor has no insight
[PATCH 00/28] Plane Color Pipeline support for Intel platforms
This series intends to add support for Plane Color Management for Intel platforms. This is based on the design which has been agreed upon by the community. Series implementing the design for generic DRM core has been sent out by Harry Wentland and is under review below: https://patchwork.freedesktop.org/series/123446/ The base work of above series is squashed under 1 patch and support for Intel platform is added on top of it. Any reviews on the original core design is expected to be done in Harry's series to avoid any forking of the discussion. We have added some changes/fixes to the Harry's core DRM changes, being put up as separate patches on top of squashed patch. These are expected to get included in the main series from Harry once agreed upon. Changes added on core design: 1. Below patches implement some fixes on original series drm: Add missing function declarations drm: handle NULL next colorop in drm_colorop_set_next_property drm: Fix error logging in set Color Pipeline 2. Implemented a HW capability property to expose segmented luts. drm: Add Color lut range attributes drm: Add Color ops capability property drm: Define helper to create color ops capability property drm: Define helper for adding capability property for 1D LUT This helps in generically defining the hardware lut capabilities, lut distribution, precision, segmented or PWL LUTS. 3. Added support for enhanced prescision, 3x3 matrix and 1d LUT: drm: Add Enhanced LUT precision structure drm: Add support for 3x3 CTM drm: Add 1D LUT color op On top of this base work for DRM core plane color pipeline design, implementation is done for Intel hardware platforms. Below patches include the same: drm/i915: Add identifiers for intel color blocks drm/i915: Add intel_color_op drm/i915/color: Add helper to allocate intel colorop drm/i915/color: Add helper to create intel colorop drm/i915/color: Create a transfer function color pipeline drm/i915/color: Add and attach COLORPIPELINE plane property drm/i915/color: Add framework to set colorop drm/i915/color: Add callbacks to set plane CTM drm/i915/color: Add framework to program PRE/POST CSC LUT FIXME: force disable legacy plane color properties for TGL and beyond drm/i915/color: Enable Plane Color Pipelines drm/i915: Define segmented Lut and add capabilities to colorop drm/i915/color: Add plane CTM callback for TGL and beyond drm/i915: Add register definitions for Plane Degamma drm/i915: Add register definitions for Plane Post CSC drm/i915/color: Program Pre-CSC registers drm/i915/xelpd: Program Plane Post CSC Registers Bhanu from Intel will be sending out the igt changes to help test the color pipeline implementation based on the current igt changes sent out by Harry. https://patchwork.freedesktop.org/series/123448/ Planned Next Steps: 1. Work with Harry and community and get DRM core changes for color pipeline merged. 2. Implement pipe color management (post blending) based on the current color pipeline design. 3. Work with compositor maintainers to get color processing implemented using display hardware, thereby avoid any GL or GPU shaders. Thanks to all the community maintainers and contributors who have helped to get this support in upstream Linux. Looking forward to collaborate, work together and get this merged. Cc: Ville Syrjala Cc: Pekka Paalanen Cc: Simon Ser Cc: Harry Wentland Cc: Melissa Wen Cc: Jonas Ådahl Cc: Sebastian Wick Cc: Shashank Sharma Cc: Alexander Goins Cc: Joshua Ashton Cc: Michel Dänzer Cc: Aleix Pol Cc: Xaver Hugl Cc: Victoria Brekenfeld Cc: Sima Cc: Naseer Ahmed Cc: Christopher Braga Cc: Abhinav Kumar Cc: Arthur Grillo Cc: Hector Martin Cc: Liviu Dudau Cc: Sasha McIntosh Cc: Chaitanya Kumar Borah Chaitanya Kumar Borah (16): drm: Add missing function declarations drm: handle NULL next colorop in drm_colorop_set_next_property drm: Fix error logging in set Color Pipeline drm: Add support for 3x3 CTM drm: Add 1D LUT color op drm/i915: Add identifiers for intel color blocks drm/i915: Add intel_color_op drm/i915/color: Add helper to allocate intel colorop drm/i915/color: Add helper to create intel colorop drm/i915/color: Create a transfer function color pipeline drm/i915/color: Add and attach COLORPIPELINE plane property drm/i915/color: Add framework to set colorop drm/i915/color: Add callbacks to set plane CTM drm/i915/color: Add framework to program PRE/POST CSC LUT FIXME: force disable legacy plane color properties for TGL and beyond drm/i915/color: Enable Plane Color Pipelines Harry Wentland (1): [NOT FOR REVIEW] drm: color pipeline base work Uma Shankar (11): drm: Add Enhanced LUT precision structure drm: Add Color lut range attributes drm: Add Color ops capability property drm: Define helper to create color ops capability property drm: Define helper for adding capability property for 1D LUT drm/i915: Define segmented Lut and add capabilities to colorop drm/i915/color: Add plane CTM
[RFC 29/33] drm/i915/xelpd: Program Plane Post CSC Registers
Extract the LUT and program plane post csc registers. Co-developed-by: Chaitanya Kumar Borah Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 95 +- 1 file changed, 94 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 56bcf750b047..ff996b9ee77d 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -1963,16 +1963,109 @@ static void xelpd_program_plane_pre_csc_lut(const struct drm_plane_state *state, } } +static void xelpd_program_plane_post_csc_lut(const struct drm_plane_state *state, +struct drm_color_lut_ext *post_csc_lut, +u32 offset) +{ + struct drm_i915_private *dev_priv = to_i915(state->plane->dev); + enum pipe pipe = to_intel_plane(state->plane)->pipe; + enum plane_id plane = to_intel_plane(state->plane)->id; + u32 i, lut_size; + + if (icl_is_hdr_plane(dev_priv, plane)) { + intel_de_write_fw(dev_priv, PLANE_POST_CSC_GAMC_INDEX_ENH(pipe, plane, 0), + offset | PLANE_PAL_PREC_AUTO_INCREMENT); + if (post_csc_lut) { + lut_size = 32; + for (i = 0; i < lut_size; i++) { + u64 word = drm_color_lut_extract_ext(post_csc_lut[i].green, 24); + u32 lut_val = (word & 0xff); + + intel_de_write_fw(dev_priv, + PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, 0), + lut_val); + } + + do { + /* Program the max register to clamp values > 1.0. */ + intel_de_write_fw(dev_priv, + PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, 0), + post_csc_lut[i].green); + } while (i++ < 34); + } else { + lut_size = 32; + for (i = 0; i < lut_size; i++) { + u32 v = (i * ((1 << 24) - 1)) / (lut_size - 1); + + intel_de_write_fw(dev_priv, + PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, 0), v); + } + + do { + intel_de_write_fw(dev_priv, + PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, 0), + 1 << 24); + } while (i++ < 34); + } + + intel_de_write_fw(dev_priv, PLANE_POST_CSC_GAMC_INDEX_ENH(pipe, plane, 0), 0); + } else { + lut_size = 32; + /* +* First 3 planes are HDR, so reduce by 3 to get to the right +* SDR plane offset +*/ + plane = plane - 3; + + intel_de_write_fw(dev_priv, PLANE_POST_CSC_GAMC_INDEX(pipe, plane, 0), + offset | PLANE_PAL_PREC_AUTO_INCREMENT); + + if (post_csc_lut) { + for (i = 0; i < lut_size; i++) + intel_de_write_fw(dev_priv, + PLANE_POST_CSC_GAMC_DATA(pipe, plane, 0), + post_csc_lut[i].green & 0x); + /* Program the max register to clamp values > 1.0. */ + while (i < 35) + intel_de_write_fw(dev_priv, + PLANE_POST_CSC_GAMC_DATA(pipe, plane, 0), + post_csc_lut[i++].green & 0x3); + } else { + for (i = 0; i < lut_size; i++) { + u32 v = (i * ((1 << 16) - 1)) / (lut_size - 1); + + intel_de_write_fw(dev_priv, + PLANE_POST_CSC_GAMC_DATA(pipe, plane, 0), v); + } + + do { + intel_de_write_fw(dev_priv, + PLANE_POST_CSC_GAMC_DATA(pipe, plane, 0), + (1 << 16)); + } while (i++ < 34); + } + + intel_de_write_fw(dev_priv, PLANE_POST_CSC_GAMC_INDEX(pipe, plane, 0), 0); + } +} + static vo
[RFC 26/33] drm/i915/color: Add color functions for ADL
Register color callbacks for ADL and beyond. While we have to register new callbacks for pre-blending color operations, re-use callbacks for post-blend operations. Co-developed-by: Chaitanya Kumar Borah Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 14 +- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index df2fc8f98dc9..3f3c1ac10330 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -3704,6 +3704,16 @@ static const struct intel_color_funcs i9xx_color_funcs = { .get_config = i9xx_get_config, }; +static const struct intel_color_funcs xelpd_color_funcs = { + .color_check = icl_color_check, + .color_commit_noarm = icl_color_commit_noarm, + .color_commit_arm = icl_color_commit_arm, + .load_luts = icl_load_luts, + .read_luts = icl_read_luts, + .lut_equal = icl_lut_equal, + .read_csc = icl_read_csc, +}; + static const struct intel_color_funcs tgl_color_funcs = { .color_check = icl_color_check, .color_commit_noarm = icl_color_commit_noarm, @@ -4141,7 +4151,9 @@ void intel_color_init_hooks(struct drm_i915_private *i915) else i915->display.funcs.color = _color_funcs; } else { - if (DISPLAY_VER(i915) >= 12) + if (DISPLAY_VER(i915) >= 13) + i915->display.funcs.color = _color_funcs; + else if (DISPLAY_VER(i915) == 12) i915->display.funcs.color = _color_funcs; else if (DISPLAY_VER(i915) == 11) i915->display.funcs.color = _color_funcs; -- 2.38.1
[RFC 32/33] drm/i915/color: Add a dummy pipeline with 3D LUT
From: Chaitanya Kumar Borah This patch is to demonstrate how a pipeline can be added. Co-developed-by: Uma Shankar Signed-off-by: Uma Shankar Signed-off-by: Chaitanya Kumar Borah --- drivers/gpu/drm/drm_atomic_state_helper.c | 3 ++ drivers/gpu/drm/drm_atomic_uapi.c | 15 + drivers/gpu/drm/i915/display/intel_color.c | 37 -- include/drm/drm_plane.h| 6 4 files changed, 59 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c index a554e04c2ce3..9c389d97b344 100644 --- a/drivers/gpu/drm/drm_atomic_state_helper.c +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -349,6 +349,8 @@ void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane, drm_property_blob_get(state->color.post_csc_lut); if (state->color.private_color_op_data) drm_property_blob_get(state->color.private_color_op_data); + if (state->color.lut_3d) + drm_property_blob_get(state->color.lut_3d); state->color_mgmt_changed = false; } @@ -402,6 +404,7 @@ void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state) drm_property_blob_put(state->color.ctm); drm_property_blob_put(state->color.post_csc_lut); drm_property_blob_put(state->color.private_color_op_data); + drm_property_blob_put(state->color.lut_3d); } EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state); diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 9e0fb36d1f47..5629db763fd1 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -482,6 +482,15 @@ int drm_plane_reset_color_op_blobs(struct drm_plane *plane, _replaced); temp_replaced |= blob_replaced; + if (ret) + goto out; + + ret = drm_atomic_replace_property_blob_from_id(dev, + >color.lut_3d, + 0, -1, -1, + _replaced); + temp_replaced |= blob_replaced; + if (ret) goto out; out: @@ -551,6 +560,12 @@ int drm_plane_replace_color_op_blobs(struct drm_plane *plane, color_op[i].blob_id, -1, -1, _replaced); + } else if (color_op[i].name == DRM_CB_3D_LUT) { + ret = drm_atomic_replace_property_blob_from_id(dev, + >color.lut_3d, + color_op[i].blob_id, + -1, sizeof(struct drm_color_lut_ext), + _replaced); } else { ret = -EINVAL; goto copy_fail; diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 4e5c82c88bd4..2352ddb4a96a 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -4265,6 +4265,19 @@ static const struct drm_color_lut_range xelpd_post_csc_hdr[] = { }, }; +static const struct drm_color_lut_range dummy_3d_lut_range[] = { + { + .flags = (DRM_MODE_LUT_POST_CSC | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_NON_DECREASING), + .count = 32, + .input_bpc = 24, .output_bpc = 16, + .start = 0, .end = (1 << 24) - 1, + .min = 0, .max = (1 << 24) - 1, + }, +}; + struct drm_color_op color_pipeline_sdr[] = { { .name = DRM_CB_PRE_CSC, @@ -4300,10 +4313,17 @@ struct drm_color_op color_pipeline_hdr[] = { }, }; +struct drm_color_op color_pipeline_3dlut[] = { + { + .name = DRM_CB_3D_LUT, + .type = CURVE_3D, + }, +}; + static int intel_prepare_plane_color_pipeline(struct drm_plane *plane) { struct drm_i915_private *i915 = to_i915(plane->dev); - struct drm_property_blob *blob[2] = {NULL}; + struct drm_property_blob *blob[3] = {NULL}; int ret = 0, i = 0; if (icl_is_hdr_plane(i915, to_intel_plane(plane)->id)) { @@ -4350,6 +4370,17 @@ static int intel_prepare_plane_color_pipeline(struct drm_plane *plane) color_pipeline_sdr[1].blob_id = blob[i++]->base.id; } + blob[i] = drm_property_create_blob(plane->dev, +
[RFC 33/33] drm/i915/color: Add example implementation for vendor specific color operation
From: Chaitanya Kumar Borah This is an example of how vendor specific color operation could be supported by the uapi Co-developed-by: Uma Shankar Signed-off-by: Uma Shankar Signed-off-by: Chaitanya Kumar Borah --- drivers/gpu/drm/i915/display/intel_color.c| 42 --- drivers/gpu/drm/i915/display/intel_color.h| 1 + .../drm/i915/display/skl_universal_plane.c| 1 + include/uapi/drm/i915_drm.h | 25 +++ 4 files changed, 64 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 2352ddb4a96a..5acc89b0cbf7 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -21,6 +21,7 @@ * DEALINGS IN THE SOFTWARE. * */ +#include #include "i915_reg.h" #include "intel_color.h" @@ -87,6 +88,7 @@ struct intel_color_funcs { */ void (*load_plane_csc_matrix)(const struct drm_plane_state *plane_state); void (*load_plane_luts)(const struct drm_plane_state *plane_state); + void (*load_private)(const struct drm_plane_state *plane_state); }; #define CTM_COEFF_SIGN (1ULL << 63) @@ -2145,6 +2147,25 @@ static void xelpd_load_plane_csc_matrix(const struct drm_plane_state *state) intel_de_write_fw(dev_priv, PLANE_CSC_POSTOFF(pipe, plane, 2), postoff); } +static void xelpd_load_private(const struct drm_plane_state *state) +{ + struct drm_i915_private *i915 = to_i915(state->plane->dev); + struct i915_color_op_data *op_data; + enum plane_id plane = to_intel_plane(state->plane)->id; + int i, num; + + if (icl_is_hdr_plane(i915, plane) || !state->color.private_color_op_data) + return; + + op_data = state->color.private_color_op_data->data; + num = state->color.private_color_op_data->length / sizeof(struct i915_color_op_data); + + for (i = 0; i < num; i++) { + if (op_data[i].flag == I915_COLOR_OP_FIXED_FUNC_CSC) + DRM_DEBUG_KMS("CSC OP [%d]", op_data[i].csc_type); + } +} + void intel_color_load_luts(const struct intel_crtc_state *crtc_state) { struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); @@ -2168,6 +2189,14 @@ void intel_color_load_plane_csc_matrix(const struct drm_plane_state *plane_state i915->display.funcs.color->load_plane_csc_matrix(plane_state); } +void intel_color_load_private(const struct drm_plane_state *plane_state) +{ + struct drm_i915_private *i915 = to_i915(plane_state->plane->dev); + + if (i915->display.funcs.color->load_private) + i915->display.funcs.color->load_private(plane_state); +} + void intel_color_commit_noarm(const struct intel_crtc_state *crtc_state) { struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); @@ -4011,6 +4040,7 @@ static const struct intel_color_funcs xelpd_color_funcs = { .read_csc = icl_read_csc, .load_plane_luts = xelpd_plane_load_luts, .load_plane_csc_matrix = xelpd_load_plane_csc_matrix, + .load_private = xelpd_load_private, }; static const struct intel_color_funcs tgl_color_funcs = { @@ -4284,10 +4314,12 @@ struct drm_color_op color_pipeline_sdr[] = { .type = CURVE_1D, .blob_id = 0, /* To be updated during plane initialization */ }, - /* -* SDR planes have fixed function CSC capabilities. -* TODO: Add support for it -*/ + { + .name = DRM_CB_PRIVATE, + .type = FIXED_FUNCTION, + .blob_id = 0, + .private_flags = I915_COLOR_OP_FIXED_FUNC_CSC, + }, { .name = DRM_CB_POST_CSC, .type = CURVE_1D, @@ -4367,7 +4399,7 @@ static int intel_prepare_plane_color_pipeline(struct drm_plane *plane) * LUT ranges for SDR planes are similar for pre and post-csc blocks */ color_pipeline_sdr[0].blob_id = - color_pipeline_sdr[1].blob_id = blob[i++]->base.id; + color_pipeline_sdr[2].blob_id = blob[i++]->base.id; } blob[i] = drm_property_create_blob(plane->dev, diff --git a/drivers/gpu/drm/i915/display/intel_color.h b/drivers/gpu/drm/i915/display/intel_color.h index a513c88d3bfc..aa8841f1d1ef 100644 --- a/drivers/gpu/drm/i915/display/intel_color.h +++ b/drivers/gpu/drm/i915/display/intel_color.h @@ -34,4 +34,5 @@ void intel_color_assert_luts(const struct intel_crtc_state *crtc_state); void intel_color_plane_init(struct drm_plane *plane); void intel_color_load_plane_luts(const struct drm_plane_state *plane_state); void intel_color_load_plane_csc_matrix(const struct drm_plane_state *plane_state); +void intel_color_load_private(const
[RFC 31/33] drm/i915/color: Enable plane color features
From: Chaitanya Kumar Borah Initialize and expose all plane color features. Co-developed-by: Uma Shankar Signed-off-by: Uma Shankar Signed-off-by: Chaitanya Kumar Borah --- drivers/gpu/drm/i915/display/intel_color.c | 1 - drivers/gpu/drm/i915/display/skl_universal_plane.c | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 956080fb7fcd..4e5c82c88bd4 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -4361,7 +4361,6 @@ static int intel_prepare_plane_color_pipeline(struct drm_plane *plane) return ret; }; -__maybe_unused void intel_color_plane_init(struct drm_plane *plane) { struct drm_i915_private *i915 = to_i915(plane->dev); diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index c85548d3210a..2e4ca55fdbb2 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -2389,6 +2389,7 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR)); intel_plane_helper_add(plane); + intel_color_plane_init(>base); return plane; -- 2.38.1
[RFC 28/33] drm/i915/xelpd: Add register definitions for Plane Post CSC
Add macros to define Plane Post CSC registers Co-developed-by: Chaitanya Kumar Borah Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/i915_reg.h | 73 + 1 file changed, 73 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index d26d6294d231..5e4271e7b735 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6226,6 +6226,79 @@ enum skl_power_gate { #define _MMIO_PLANE_GAMC(plane, i, a, b) _MMIO(_PIPE(plane, a, b) + (i) * 4) +/* Display13 Plane Gamma Reg */ +#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1_A0x70160 +#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1_B0x71160 +#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2_A0x70260 +#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2_B0x71260 +#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1(pipe)_PIPE(pipe, _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1_A, \ + _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1_B) +#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2(pipe)_PIPE(pipe, _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2_A, \ + _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2_B) +#define PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1(pipe), \ + _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2(pipe)) + +#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1_A 0x70164 +#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1_B 0x71164 +#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2_A 0x70264 +#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2_B 0x71264 +#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1_A, \ + _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1_B) +#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2_A, \ + _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2_B) +#define PLANE_POST_CSC_GAMC_SEG0_DATA_ENH(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1(pipe), \ + _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2(pipe)) + +#define _PLANE_POST_CSC_GAMC_INDEX_ENH_1_A 0x701d8 +#define _PLANE_POST_CSC_GAMC_INDEX_ENH_1_B 0x711d8 +#define _PLANE_POST_CSC_GAMC_INDEX_ENH_2_A 0x702d8 +#define _PLANE_POST_CSC_GAMC_INDEX_ENH_2_B 0x712d8 +#define _PLANE_POST_CSC_GAMC_INDEX_ENH_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_INDEX_ENH_1_A, \ + _PLANE_POST_CSC_GAMC_INDEX_ENH_1_B) +#define _PLANE_POST_CSC_GAMC_INDEX_ENH_2(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_INDEX_ENH_2_A, \ + _PLANE_POST_CSC_GAMC_INDEX_ENH_2_B) +#define PLANE_POST_CSC_GAMC_INDEX_ENH(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_INDEX_ENH_1(pipe), \ + _PLANE_POST_CSC_GAMC_INDEX_ENH_2(pipe)) + +#define _PLANE_POST_CSC_GAMC_DATA_ENH_1_A 0x701dc +#define _PLANE_POST_CSC_GAMC_DATA_ENH_1_B 0x711dc +#define _PLANE_POST_CSC_GAMC_DATA_ENH_2_A 0x702dc +#define _PLANE_POST_CSC_GAMC_DATA_ENH_2_B 0x712dc +#define _PLANE_POST_CSC_GAMC_DATA_ENH_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_DATA_ENH_1_A, \ + _PLANE_POST_CSC_GAMC_DATA_ENH_1_B) +#define _PLANE_POST_CSC_GAMC_DATA_ENH_2(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_DATA_ENH_2_A, \ + _PLANE_POST_CSC_GAMC_DATA_ENH_2_B) +#define PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_DATA_ENH_1(pipe), \ + _PLANE_POST_CSC_GAMC_DATA_ENH_2(pipe)) + +#define _PLANE_POST_CSC_GAMC_INDEX_1_A 0x704d8 +#define _PLANE_POST_CSC_GAMC_INDEX_1_B 0x714d8 +#define _PLANE_POST_CSC_GAMC_INDEX_2_A 0x705d8 +#define _PLANE_POST_CSC_GAMC_INDEX_2_B 0x715d8 +#define _PLANE_POST_CSC_GAMC_INDEX_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_INDEX_1_A, \ + _PLANE_POST_CSC_GAMC_INDEX_1_B) +#define _PLANE_POST_CSC_GAMC_INDEX_2(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_INDEX_2_A, \ + _PLANE_POST_CSC_GAMC_INDEX_2_B) +#define PLANE_POST_CSC_GAMC_INDEX(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_INDEX_1(pipe), \ + _PLANE_POST_CSC_GAMC_INDEX_2(pipe)) + +#define _PLANE_POST_CSC_GAMC_DATA_1_A 0x704dc +#define _PLANE_POST_CSC_GAMC_DATA_1_B 0x714dc +#define _PLANE_POST_CSC_GAMC_DATA_2_A 0x705dc +#define _PLANE_POST_CSC_GAMC_DATA_2_B 0x715dc +#define _PLANE_POST_CSC_GAMC_DATA_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_DATA_1_A
[RFC 30/33] drm/i915/color: Enable Plane CSC
Implement plane CSC for Xe_LPD. Co-developed-by: Chaitanya Kumar Borah Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c| 86 +++ drivers/gpu/drm/i915/display/intel_color.h| 1 + .../drm/i915/display/skl_universal_plane.c| 4 +- 3 files changed, 90 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index ff996b9ee77d..956080fb7fcd 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -2068,6 +2068,83 @@ static void xelpd_plane_load_luts(const struct drm_plane_state *plane_state) } } +static void xelpd_load_plane_csc_matrix(const struct drm_plane_state *state) +{ + struct drm_i915_private *dev_priv = to_i915(state->plane->dev); + enum pipe pipe = to_intel_plane(state->plane)->pipe; + enum plane_id plane = to_intel_plane(state->plane)->id; + struct drm_color_ctm *ctm; + const u64 *input; + u16 coeffs[9] = {}; + u16 postoff = 0; + int i; + + if (!icl_is_hdr_plane(dev_priv, plane) || !state->color.ctm) + return; + + ctm = state->color.ctm->data; + input = ctm->matrix; + + /* +* Convert fixed point S31.32 input to format supported by the +* hardware. +*/ + for (i = 0; i < ARRAY_SIZE(coeffs); i++) { + u64 abs_coeff = ((1ULL << 63) - 1) & input[i]; + + /* +* Clamp input value to min/max supported by +* hardware. +*/ + abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_4_0 - 1); + + /* sign bit */ + if (CTM_COEFF_NEGATIVE(input[i])) + coeffs[i] |= 1 << 15; + + if (abs_coeff < CTM_COEFF_0_125) + coeffs[i] |= (3 << 12) | + ILK_CSC_COEFF_FP(abs_coeff, 12); + else if (abs_coeff < CTM_COEFF_0_25) + coeffs[i] |= (2 << 12) | + ILK_CSC_COEFF_FP(abs_coeff, 11); + else if (abs_coeff < CTM_COEFF_0_5) + coeffs[i] |= (1 << 12) | + ILK_CSC_COEFF_FP(abs_coeff, 10); + else if (abs_coeff < CTM_COEFF_1_0) + coeffs[i] |= ILK_CSC_COEFF_FP(abs_coeff, 9); + else if (abs_coeff < CTM_COEFF_2_0) + coeffs[i] |= (7 << 12) | + ILK_CSC_COEFF_FP(abs_coeff, 8); + else + coeffs[i] |= (6 << 12) | + ILK_CSC_COEFF_FP(abs_coeff, 7); + } + + intel_de_write_fw(dev_priv, PLANE_CSC_COEFF(pipe, plane, 0), + coeffs[0] << 16 | coeffs[1]); + intel_de_write_fw(dev_priv, PLANE_CSC_COEFF(pipe, plane, 1), + coeffs[2] << 16); + + intel_de_write_fw(dev_priv, PLANE_CSC_COEFF(pipe, plane, 2), + coeffs[3] << 16 | coeffs[4]); + intel_de_write_fw(dev_priv, PLANE_CSC_COEFF(pipe, plane, 3), + coeffs[5] << 16); + + intel_de_write_fw(dev_priv, PLANE_CSC_COEFF(pipe, plane, 4), + coeffs[6] << 16 | coeffs[7]); + intel_de_write_fw(dev_priv, PLANE_CSC_COEFF(pipe, plane, 5), + coeffs[8] << 16); + + intel_de_write_fw(dev_priv, PLANE_CSC_PREOFF(pipe, plane, 0), 0); + intel_de_write_fw(dev_priv, PLANE_CSC_PREOFF(pipe, plane, 1), 0); + intel_de_write_fw(dev_priv, PLANE_CSC_PREOFF(pipe, plane, 2), 0); + + intel_de_write_fw(dev_priv, PLANE_CSC_POSTOFF(pipe, plane, 0), postoff); + intel_de_write_fw(dev_priv, PLANE_CSC_POSTOFF(pipe, plane, 1), postoff); + intel_de_write_fw(dev_priv, PLANE_CSC_POSTOFF(pipe, plane, 2), postoff); +} + void intel_color_load_luts(const struct intel_crtc_state *crtc_state) { struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); @@ -2083,6 +2160,14 @@ void intel_color_load_plane_luts(const struct drm_plane_state *plane_state) i915->display.funcs.color->load_plane_luts(plane_state); } +void intel_color_load_plane_csc_matrix(const struct drm_plane_state *plane_state) +{ + struct drm_i915_private *i915 = to_i915(plane_state->plane->dev); + + if (i915->display.funcs.color->load_plane_csc_matrix) + i915->display.funcs.color->load_plane_csc_matrix(plane_state); +} + void intel_color_commit_noarm(const struct intel_crtc_state *crtc_state) { struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); @@ -3925,6 +4010,7 @@ static const
[RFC 27/33] drm/i915/color: Program Plane Pre-CSC Registers
Extract the LUT and program plane pre-csc registers. Co-developed-by: Chaitanya Kumar Borah Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 120 + drivers/gpu/drm/i915/i915_reg.h| 1 + 2 files changed, 121 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 3f3c1ac10330..56bcf750b047 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -185,6 +185,29 @@ static bool lut_is_legacy(const struct drm_property_blob *lut) return lut && drm_color_lut_size(lut) == LEGACY_LUT_LENGTH; } +/* + * Added to accommodate enhanced LUT precision. + * Max LUT precision is 32 bits. + */ +static u64 drm_color_lut_extract_ext(u64 user_input, u32 bit_precision) +{ + u64 val = user_input & 0x; + u32 max; + + if (bit_precision > 32) + return 0; + + max = 0x >> (32 - bit_precision); + /* Round only if we're not using full precision. */ + if (bit_precision < 32) { + val += 1UL << (32 - bit_precision - 1); + val >>= 32 - bit_precision; + } + + return ((user_input & 0x) | + clamp_val(val, 0, max)); +} + /* * When using limited range, multiply the matrix given by userspace by * the matrix that we would use for the limited range. @@ -1856,6 +1879,102 @@ static void chv_load_luts(const struct intel_crtc_state *crtc_state) crtc_state->cgm_mode); } +static void xelpd_program_plane_pre_csc_lut(const struct drm_plane_state *state, + struct drm_color_lut_ext *pre_csc_lut, + u32 offset) +{ + struct drm_i915_private *dev_priv = to_i915(state->plane->dev); + enum pipe pipe = to_intel_plane(state->plane)->pipe; + enum plane_id plane = to_intel_plane(state->plane)->id; + u32 i, lut_size; + + if (icl_is_hdr_plane(dev_priv, plane)) { + lut_size = 128; + + intel_de_write_fw(dev_priv, PLANE_PRE_CSC_GAMC_INDEX_ENH(pipe, plane, 0), + PLANE_PAL_PREC_AUTO_INCREMENT); + + if (pre_csc_lut) { + for (i = 0; i < lut_size; i++) { + u64 word = drm_color_lut_extract_ext(pre_csc_lut[i].green, 24); + u32 lut_val = (word & 0xff); + + intel_de_write_fw(dev_priv, + PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0), + lut_val); + } + + /* Program the max register to clamp values > 1.0. */ + while (i < 131) + intel_de_write_fw(dev_priv, + PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0), + pre_csc_lut[i++].green); + } else { + for (i = 0; i < lut_size; i++) { + u32 v = (i * ((1 << 24) - 1)) / (lut_size - 1); + + intel_de_write_fw(dev_priv, + PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0), v); + } + + do { + intel_de_write_fw(dev_priv, + PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0), + 1 << 24); + } while (i++ < 130); + } + + intel_de_write_fw(dev_priv, PLANE_PRE_CSC_GAMC_INDEX_ENH(pipe, plane, 0), 0); + } else { + lut_size = 32; + + /* +* First 3 planes are HDR, so reduce by 3 to get to the right +* SDR plane offset +*/ + plane = plane - 3; + + intel_de_write_fw(dev_priv, PLANE_PRE_CSC_GAMC_INDEX(pipe, plane, 0), + PLANE_PAL_PREC_AUTO_INCREMENT); + + if (pre_csc_lut) { + for (i = 0; i < lut_size; i++) + intel_de_write_fw(dev_priv, PLANE_PRE_CSC_GAMC_DATA(pipe, plane, 0), + pre_csc_lut[i].green); + /* Program the max register to clamp values > 1.0. */ + while (i < 35) + intel_de_write_fw(dev_priv, PLANE_PRE_CSC_GAMC_DATA(pipe, plane, 0), +
[RFC 25/33] drm/i915/xelpd: Add register definitions for Plane Degamma
Add macros to define Plane Degamma registers Co-developed-by: Chaitanya Kumar Borah Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/i915_reg.h | 49 + 1 file changed, 49 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index d50bfe1000d3..5fa7461066ab 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6226,6 +6226,55 @@ enum skl_power_gate { #define _MMIO_PLANE_GAMC(plane, i, a, b) _MMIO(_PIPE(plane, a, b) + (i) * 4) +/* Display13 Plane Degmma Reg */ +#define _PLANE_PRE_CSC_GAMC_INDEX_ENH_1_A 0x701d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_ENH_1_B 0x711d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_ENH_2_A 0x702d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_ENH_2_B 0x712d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_ENH_1(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_INDEX_ENH_1_A, \ + _PLANE_PRE_CSC_GAMC_INDEX_ENH_1_B) +#define _PLANE_PRE_CSC_GAMC_INDEX_ENH_2(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_INDEX_ENH_2_A, \ + _PLANE_PRE_CSC_GAMC_INDEX_ENH_2_B) +#define PLANE_PRE_CSC_GAMC_INDEX_ENH(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_PRE_CSC_GAMC_INDEX_ENH_1(pipe), \ + _PLANE_PRE_CSC_GAMC_INDEX_ENH_2(pipe)) + +#define _PLANE_PRE_CSC_GAMC_DATA_ENH_1_A 0x701d4 +#define _PLANE_PRE_CSC_GAMC_DATA_ENH_1_B 0x711d4 +#define _PLANE_PRE_CSC_GAMC_DATA_ENH_2_A 0x702d4 +#define _PLANE_PRE_CSC_GAMC_DATA_ENH_2_B 0x712d4 +#define _PLANE_PRE_CSC_GAMC_DATA_ENH_1(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_DATA_ENH_1_A, \ + _PLANE_PRE_CSC_GAMC_DATA_ENH_1_B) +#define _PLANE_PRE_CSC_GAMC_DATA_ENH_2(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_DATA_ENH_2_A, \ + _PLANE_PRE_CSC_GAMC_DATA_ENH_2_B) +#define PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, i)\ + _MMIO_PLANE_GAMC(plane, i, _PLANE_PRE_CSC_GAMC_DATA_ENH_1(pipe), \ + _PLANE_PRE_CSC_GAMC_DATA_ENH_2(pipe)) + +#define _PLANE_PRE_CSC_GAMC_INDEX_1_A 0x704d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_1_B 0x714d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_2_A 0x705d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_2_B 0x715d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_1(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_INDEX_1_A, \ + _PLANE_PRE_CSC_GAMC_INDEX_1_B) +#define _PLANE_PRE_CSC_GAMC_INDEX_2(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_INDEX_2_A, \ + _PLANE_PRE_CSC_GAMC_INDEX_2_B) +#define PLANE_PRE_CSC_GAMC_INDEX(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_PRE_CSC_GAMC_INDEX_1(pipe), \ + _PLANE_PRE_CSC_GAMC_INDEX_2(pipe)) + +#define _PLANE_PRE_CSC_GAMC_DATA_1_A 0x704d4 +#define _PLANE_PRE_CSC_GAMC_DATA_1_B 0x714d4 +#define _PLANE_PRE_CSC_GAMC_DATA_2_A 0x705d4 +#define _PLANE_PRE_CSC_GAMC_DATA_2_B 0x715d4 +#define _PLANE_PRE_CSC_GAMC_DATA_1(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_DATA_1_A, \ + _PLANE_PRE_CSC_GAMC_DATA_1_B) +#define _PLANE_PRE_CSC_GAMC_DATA_2(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_DATA_2_A, \ + _PLANE_PRE_CSC_GAMC_DATA_2_B) +#define PLANE_PRE_CSC_GAMC_DATA(pipe, plane, i)\ + _MMIO_PLANE_GAMC(plane, i, _PLANE_PRE_CSC_GAMC_DATA_1(pipe), \ + _PLANE_PRE_CSC_GAMC_DATA_2(pipe)) + /* Plane CSC Registers */ #define _PLANE_CSC_RY_GY_1_A 0x70210 #define _PLANE_CSC_RY_GY_2_A 0x70310 -- 2.38.1
[RFC 23/33] drm/i915/color: Load plane color luts from atomic flip
Load plane color luts as part of atomic plane updates. This will be done only if the plane color luts are changed. Co-developed-by: Chaitanya Kumar Borah Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 8 drivers/gpu/drm/i915/display/intel_color.h | 2 ++ drivers/gpu/drm/i915/display/skl_universal_plane.c | 4 3 files changed, 14 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index faf16107d339..df2fc8f98dc9 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -1863,6 +1863,14 @@ void intel_color_load_luts(const struct intel_crtc_state *crtc_state) i915->display.funcs.color->load_luts(crtc_state); } +void intel_color_load_plane_luts(const struct drm_plane_state *plane_state) +{ + struct drm_i915_private *i915 = to_i915(plane_state->plane->dev); + + if (i915->display.funcs.color->load_plane_luts) + i915->display.funcs.color->load_plane_luts(plane_state); +} + void intel_color_commit_noarm(const struct intel_crtc_state *crtc_state) { struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); diff --git a/drivers/gpu/drm/i915/display/intel_color.h b/drivers/gpu/drm/i915/display/intel_color.h index aa649d13c6fa..93382df101d9 100644 --- a/drivers/gpu/drm/i915/display/intel_color.h +++ b/drivers/gpu/drm/i915/display/intel_color.h @@ -13,6 +13,7 @@ struct intel_crtc; struct drm_plane; struct drm_i915_private; struct drm_property_blob; +struct drm_plane_state; void intel_color_init_hooks(struct drm_i915_private *i915); int intel_color_init(struct drm_i915_private *i915); @@ -31,4 +32,5 @@ bool intel_color_lut_equal(const struct intel_crtc_state *crtc_state, bool is_pre_csc_lut); void intel_color_assert_luts(const struct intel_crtc_state *crtc_state); void intel_color_plane_init(struct drm_plane *plane); +void intel_color_load_plane_luts(const struct drm_plane_state *plane_state); #endif /* __INTEL_COLOR_H__ */ diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 4566c95da1ca..ce7c367fe2da 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -11,6 +11,7 @@ #include "i915_drv.h" #include "i915_reg.h" #include "intel_atomic_plane.h" +#include "intel_color.h" #include "intel_de.h" #include "intel_display_irq.h" #include "intel_display_types.h" @@ -1268,6 +1269,9 @@ icl_plane_update_noarm(struct intel_plane *plane, if (plane_state->force_black) icl_plane_csc_load_black(plane); + if (plane_state->uapi.color_mgmt_changed) + intel_color_load_plane_luts(_state->uapi); + intel_psr2_program_plane_sel_fetch_noarm(plane, crtc_state, plane_state, color_plane); } -- 2.38.1
[RFC 24/33] drm/i915/xelpd: Add plane color check to glk_plane_color_ctl
Extended glk_plane_color_ctl to have plane color checks. This helps enabling the csc, degamma or gamma block based on user inputs. Co-developed-by: Chaitanya Kumar Borah Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/skl_universal_plane.c | 13 - drivers/gpu/drm/i915/i915_reg.h| 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index ce7c367fe2da..c08875fa965e 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -965,7 +965,18 @@ static u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state, struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); u32 plane_color_ctl = 0; - plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE; + /* FIXME needs hw.gamma_lut */ + if (!plane_state->uapi.color.pre_csc_lut) + plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE; + + /* FIXME needs hw.degamma_lut */ + if (plane_state->uapi.color.post_csc_lut) + plane_color_ctl |= PLANE_COLOR_PRE_CSC_GAMMA_ENABLE; + + /* FIXME needs hw.ctm */ + if (plane_state->uapi.color.ctm) + plane_color_ctl |= PLANE_COLOR_PLANE_CSC_ENABLE; + plane_color_ctl |= glk_plane_color_ctl_alpha(plane_state); if (fb->format->is_yuv && !icl_is_hdr_plane(dev_priv, plane->id)) { diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index e00e4d569ba9..d50bfe1000d3 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3730,6 +3730,7 @@ #define PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709 REG_FIELD_PREP(PLANE_COLOR_CSC_MODE_MASK, 2) #define PLANE_COLOR_CSC_MODE_YUV2020_TO_RGB2020 REG_FIELD_PREP(PLANE_COLOR_CSC_MODE_MASK, 3) #define PLANE_COLOR_CSC_MODE_RGB709_TO_RGB2020 REG_FIELD_PREP(PLANE_COLOR_CSC_MODE_MASK, 4) +#define PLANE_COLOR_PRE_CSC_GAMMA_ENABLE REG_BIT(14) #define PLANE_COLOR_PLANE_GAMMA_DISABLE REG_BIT(13) #define PLANE_COLOR_ALPHA_MASK REG_GENMASK(5, 4) #define PLANE_COLOR_ALPHA_DISABLE REG_FIELD_PREP(PLANE_COLOR_ALPHA_MASK, 0) -- 2.38.1
[RFC 22/33] drm/i915/color: Add plane color callbacks
Add callbacks for color plane operations. load_plane_luts: used to load pre/post csc luts load_plane_csc_matrix: used to load csc matrix Co-developed-by: Chaitanya Kumar Borah Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index feff8ac45f47..faf16107d339 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -81,6 +81,12 @@ struct intel_color_funcs { * Read config other than LUTs and CSCs, before them. Optional. */ void (*get_config)(struct intel_crtc_state *crtc_state); + + /* +* Plane color callbacks +*/ + void (*load_plane_csc_matrix)(const struct drm_plane_state *plane_state); + void (*load_plane_luts)(const struct drm_plane_state *plane_state); }; #define CTM_COEFF_SIGN (1ULL << 63) -- 2.38.1
[RFC 21/33] drm/i915/color: Create and attach set color pipeline property
From: Chaitanya Kumar Borah Create and attach "SET_COLOR_PIPELINE" property to planes. Co-developed-by: Uma Shankar Signed-off-by: Uma Shankar Signed-off-by: Chaitanya Kumar Borah --- drivers/gpu/drm/i915/display/intel_color.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 9f5d2cd0f97a..feff8ac45f47 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -4066,6 +4066,9 @@ void intel_color_plane_init(struct drm_plane *plane) sizeof(color_pipeline_sdr)); drm_plane_attach_get_color_pipeline_property(plane); + + drm_plane_create_set_color_pipeline_property(plane->dev, plane); + drm_plane_attach_set_color_pipeline_property(plane); } void intel_color_crtc_init(struct intel_crtc *crtc) -- 2.38.1
[RFC 20/33] drm/i915/color: Add color pipelines to plane
From: Chaitanya Kumar Borah Add supported plane color pipelines. To represent all hardware blocks in their inactive state, we introduce a pipeline called "no color pipeline" which is the default pipeline. Add respective color pipelines for SDR and HDR planes. Create and attach plane enum property "GET_COLOR_PIPELINE" to expose these pipelines to userspace. Co-developed-by: Uma Shankar Signed-off-by: Uma Shankar Signed-off-by: Chaitanya Kumar Borah --- drivers/gpu/drm/i915/display/intel_color.c | 31 +- drivers/gpu/drm/i915/display/intel_color.h | 3 ++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index a8c6be70c859..9f5d2cd0f97a 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -3977,7 +3977,6 @@ struct drm_color_op color_pipeline_hdr[] = { }, }; -__maybe_unused static int intel_prepare_plane_color_pipeline(struct drm_plane *plane) { struct drm_i915_private *i915 = to_i915(plane->dev); @@ -4039,6 +4038,36 @@ static int intel_prepare_plane_color_pipeline(struct drm_plane *plane) return ret; }; +__maybe_unused +void intel_color_plane_init(struct drm_plane *plane) +{ + struct drm_i915_private *i915 = to_i915(plane->dev); + + if (DISPLAY_VER(i915) < 13) + return; + + drm_plane_create_get_color_pipeline_property(plane->dev, plane, 2); + + intel_prepare_plane_color_pipeline(plane); + + /* +* default pipeline is set as 0 or "no color pipeline". All color h/w +* blocks are disabled at this stage. +*/ + drm_plane_add_color_pipeline(plane, "no color pipeline", NULL, 0); + + if (icl_is_hdr_plane(i915, to_intel_plane(plane)->id)) + drm_plane_add_color_pipeline(plane, "color pipeline hdr", +color_pipeline_hdr, +sizeof(color_pipeline_hdr)); + else + drm_plane_add_color_pipeline(plane, "color pipeline sdr", +color_pipeline_sdr, +sizeof(color_pipeline_sdr)); + + drm_plane_attach_get_color_pipeline_property(plane); +} + void intel_color_crtc_init(struct intel_crtc *crtc) { struct drm_i915_private *i915 = to_i915(crtc->base.dev); diff --git a/drivers/gpu/drm/i915/display/intel_color.h b/drivers/gpu/drm/i915/display/intel_color.h index 8002492be709..aa649d13c6fa 100644 --- a/drivers/gpu/drm/i915/display/intel_color.h +++ b/drivers/gpu/drm/i915/display/intel_color.h @@ -10,6 +10,7 @@ struct intel_crtc_state; struct intel_crtc; +struct drm_plane; struct drm_i915_private; struct drm_property_blob; @@ -29,5 +30,5 @@ bool intel_color_lut_equal(const struct intel_crtc_state *crtc_state, const struct drm_property_blob *blob2, bool is_pre_csc_lut); void intel_color_assert_luts(const struct intel_crtc_state *crtc_state); - +void intel_color_plane_init(struct drm_plane *plane); #endif /* __INTEL_COLOR_H__ */ -- 2.38.1
[RFC 15/33] drm/i915/color: Add lut range for HDR planes
Add lut range information for HDR planes. This is used to hint the userspace what kind of LUT values are needed by the hardware block. Pre-CSC and Post-CSC blocks have different lut ranges for HDR planes. Co-developed-by: Chaitanya Kumar Borah Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 108 + 1 file changed, 108 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 3900e3748a0e..58b6d70043ca 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -3833,6 +3833,114 @@ static const struct drm_color_lut_range xelpd_pre_post_csc_sdr[] = { }, }; +/* FIXME input bpc? */ +static const struct drm_color_lut_range xelpd_pre_csc_hdr[] = { + /* segment 1 */ + { + .flags = (DRM_MODE_LUT_PRE_CSC | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_NON_DECREASING), + .count = 128, + .input_bpc = 24, .output_bpc = 16, + .start = 0, .end = (1 << 24) - 1, + .min = 0, .max = (1 << 24) - 1, + }, + /* segment 2 */ + { + .flags = (DRM_MODE_LUT_PRE_CSC | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 24, .output_bpc = 16, + .start = (1 << 24) - 1, .end = 1 << 24, + .min = 0, .max = (1 << 27) - 1, + }, + /* Segment 3 */ + { + .flags = (DRM_MODE_LUT_PRE_CSC | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 24, .output_bpc = 16, + .start = 1 << 24, .end = 3 << 24, + .min = 0, .max = (1 << 27) - 1, + }, + /* Segment 4 */ + { + .flags = (DRM_MODE_LUT_PRE_CSC | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 24, .output_bpc = 16, + .start = 3 << 24, .end = 7 << 24, + .min = 0, .max = (1 << 27) - 1, + }, +}; + +/* FIXME input bpc? */ +static const struct drm_color_lut_range xelpd_post_csc_hdr[] = { + /* +* ToDo: Add Segment 1 +* There is an optional fine segment added with 9 lut values +* Will be added later +*/ + + /* segment 2 */ + { + .flags = (DRM_MODE_LUT_POST_CSC | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_NON_DECREASING), + .count = 32, + .input_bpc = 24, .output_bpc = 16, + .start = 0, .end = (1 << 24) - 1, + .min = 0, .max = (1 << 24) - 1, + }, + /* segment 3 */ + { + .flags = (DRM_MODE_LUT_POST_CSC | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 24, .output_bpc = 16, + .start = (1 << 24) - 1, .end = 1 << 24, + .min = 0, .max = 1 << 24, + }, + /* Segment 4 */ + { + .flags = (DRM_MODE_LUT_POST_CSC | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 24, .output_bpc = 16, + .start = 1 << 24, .end = 3 << 24, + .min = 0, .max = (3 << 24), + }, + /* Segment 5 */ + { + .flags = (DRM_MODE_LUT_POST_CSC | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 24, .output_bpc = 16, + .start = 3 << 24, .end = 7
[RFC 18/33] drm/i915/color: Add HDR plane LUT range data to color pipeline
From: Chaitanya Kumar Borah Create a helper function to add details about LUT ranges that HDR planes can support. Userspace can parse through this information to generate proper LUT data for respective hardware blocks. It will be exposed to the user space by the color pipeline. Co-developed-by: Uma Shankar Signed-off-by: Uma Shankar Signed-off-by: Chaitanya Kumar Borah --- drivers/gpu/drm/i915/display/intel_color.c | 47 ++ 1 file changed, 47 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 09e50659befd..99ae3f4fca05 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -28,6 +28,7 @@ #include "intel_de.h" #include "intel_display_types.h" #include "intel_dsb.h" +#include "skl_universal_plane.h" struct intel_color_funcs { int (*color_check)(struct intel_crtc_state *crtc_state); @@ -3976,6 +3977,52 @@ struct drm_color_op color_pipeline_hdr[] = { }, }; +__maybe_unused +static int intel_prepare_plane_color_pipeline(struct drm_plane *plane) +{ + struct drm_i915_private *i915 = to_i915(plane->dev); + struct drm_property_blob *blob[2] = {NULL}; + int ret = 0, i = 0; + + if (icl_is_hdr_plane(i915, to_intel_plane(plane)->id)) { + blob[i] = drm_property_create_blob(plane->dev, + sizeof(xelpd_pre_csc_hdr), + xelpd_pre_csc_hdr); + if (IS_ERR(blob[i])) { + ret = PTR_ERR(blob[i]); + goto out; + } + + /* +* In HDR color pipeline PRE-CSC and POST-CSC are positioned +* at 0th and 2nd index/position +*/ + color_pipeline_hdr[0].blob_id = + blob[i++]->base.id; + + blob[i] = drm_property_create_blob(plane->dev, + sizeof(xelpd_post_csc_hdr), + xelpd_post_csc_hdr); + if (IS_ERR(blob[i])) { + ret = PTR_ERR(blob[i]); + goto out; + } + + color_pipeline_hdr[2].blob_id = + blob[i++]->base.id; + } + +out: + if (ret) { + for (int j = 0; j < i; j++) { + if (blob[j]) + drm_property_blob_put(blob[j]); + } + } + + return ret; +}; + void intel_color_crtc_init(struct intel_crtc *crtc) { struct drm_i915_private *i915 = to_i915(crtc->base.dev); -- 2.38.1
[RFC 17/33] drm/i915/color: Add color pipeline for SDR planes
SDR planes provides programmable color hardware blocks for Pre-CSC and Post-CSC operations. Add a color pipeline to expose these capabilities. Co-developed-by: Chaitanya Kumar Borah Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 17 + 1 file changed, 17 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 8c2a858fc452..09e50659befd 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -3941,6 +3941,23 @@ static const struct drm_color_lut_range xelpd_post_csc_hdr[] = { }, }; +struct drm_color_op color_pipeline_sdr[] = { + { + .name = DRM_CB_PRE_CSC, + .type = CURVE_1D, + .blob_id = 0, /* To be updated during plane initialization */ + }, + /* +* SDR planes have fixed function CSC capabilities. +* TODO: Add support for it +*/ + { + .name = DRM_CB_POST_CSC, + .type = CURVE_1D, + .blob_id = 0, + }, +}; + struct drm_color_op color_pipeline_hdr[] = { { .name = DRM_CB_PRE_CSC, -- 2.38.1
[RFC 16/33] drm/i915/color: Add color pipeline for HDR planes
Add color pipeline for HDR planes. It consists of the following hardware blocks. * Pre-CSC : This block can used to linearize the input frame buffer data. The linear data then can be further acted on by the following color hardware blocks in the display hardware pipeline * CSC/CTM: Used to program color transformation matrix, this block is used to perform color space conversions like BT2020 to BT709 or BT601 etc. This block acts on the linearized data coming from the Pre-CSC HW block. * Post-CSC: This HW block can be used to non-linearize frame buffer data to match the sink. Another use case of it could be to perform Tone mapping for HDR use-cases. Co-developed-by: Chaitanya Kumar Borah Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 18 ++ 1 file changed, 18 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 58b6d70043ca..8c2a858fc452 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -3941,6 +3941,24 @@ static const struct drm_color_lut_range xelpd_post_csc_hdr[] = { }, }; +struct drm_color_op color_pipeline_hdr[] = { + { + .name = DRM_CB_PRE_CSC, + .type = CURVE_1D, + .blob_id = 0, /* To be updated during plane initialization */ + }, + { + .name = DRM_CB_CSC, + .type = MATRIX, + .blob_id = 0, + }, + { + .name = DRM_CB_POST_CSC, + .type = CURVE_1D, + .blob_id = 0, + }, +}; + void intel_color_crtc_init(struct intel_crtc *crtc) { struct drm_i915_private *i915 = to_i915(crtc->base.dev); -- 2.38.1
[RFC 19/33] drm/i915/color: Add SDR plane LUT range data to color pipeline
From: Chaitanya Kumar Borah Add LUT ranges for color blocks in SDR planes. Userspace can parse through this information to generate proper LUT data for respective hardware blocks. It will be exposed to the user space by the color pipeline. Co-developed-by: Uma Shankar Signed-off-by: Uma Shankar Signed-off-by: Chaitanya Kumar Borah --- drivers/gpu/drm/i915/display/intel_color.c | 16 1 file changed, 16 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 99ae3f4fca05..a8c6be70c859 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -4010,6 +4010,22 @@ static int intel_prepare_plane_color_pipeline(struct drm_plane *plane) color_pipeline_hdr[2].blob_id = blob[i++]->base.id; + } else { + blob[i] = drm_property_create_blob(plane->dev, + sizeof(xelpd_pre_post_csc_sdr), + xelpd_pre_post_csc_sdr); + if (IS_ERR(blob[i])) { + ret = PTR_ERR(blob[i]); + goto out; + } + + /* +* In SDR color pipeline PRE-CSC and POST-CSC blocks are positioned +* at 0th and 1st index/postion. +* LUT ranges for SDR planes are similar for pre and post-csc blocks +*/ + color_pipeline_sdr[0].blob_id = + color_pipeline_sdr[1].blob_id = blob[i++]->base.id; } out: -- 2.38.1
[RFC 10/33] drm: Manage color blob states
From: Chaitanya Kumar Borah This patch manages the references for color blobs. Co-developed-by: Uma Shankar Signed-off-by: Uma Shankar Signed-off-by: Chaitanya Kumar Borah --- drivers/gpu/drm/drm_atomic_state_helper.c | 18 ++ 1 file changed, 18 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c index 784e63d70a42..a554e04c2ce3 100644 --- a/drivers/gpu/drm/drm_atomic_state_helper.c +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -338,6 +338,19 @@ void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane, state->fence = NULL; state->commit = NULL; state->fb_damage_clips = NULL; + + if (state->set_color_pipeline_data) + drm_property_blob_get(state->set_color_pipeline_data); + if (state->color.pre_csc_lut) + drm_property_blob_get(state->color.pre_csc_lut); + if (state->color.ctm) + drm_property_blob_get(state->color.ctm); + if (state->color.post_csc_lut) + drm_property_blob_get(state->color.post_csc_lut); + if (state->color.private_color_op_data) + drm_property_blob_get(state->color.private_color_op_data); + + state->color_mgmt_changed = false; } EXPORT_SYMBOL(__drm_atomic_helper_plane_duplicate_state); @@ -384,6 +397,11 @@ void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state) drm_crtc_commit_put(state->commit); drm_property_blob_put(state->fb_damage_clips); + drm_property_blob_put(state->set_color_pipeline_data); + drm_property_blob_put(state->color.pre_csc_lut); + drm_property_blob_put(state->color.ctm); + drm_property_blob_put(state->color.post_csc_lut); + drm_property_blob_put(state->color.private_color_op_data); } EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state); -- 2.38.1
[RFC 14/33] drm/i915/color: Add lut range for SDR planes
Add lut range information for SDR planes. This is used to hint the userspace what kind of LUT values are needed by the hardware block. Pre-CSC and Post-CSC blocks have similar lut range for HDR planes. Co-developed-by: Chaitanya Kumar Borah Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 55 ++ 1 file changed, 55 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 5918e2e9bcdd..3900e3748a0e 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -3778,6 +3778,61 @@ static const struct intel_color_funcs ilk_color_funcs = { .get_config = ilk_get_config, }; +/* FIXME input bpc? */ +static const struct drm_color_lut_range xelpd_pre_post_csc_sdr[] = { + /* segment 1 */ + { + .flags = (DRM_MODE_LUT_POST_CSC | + DRM_MODE_LUT_PRE_CSC | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_NON_DECREASING), + .count = 32, + .input_bpc = 16, .output_bpc = 16, + .start = 0, .end = (1 << 16) - (1 << 16) / 33, + .min = 0, .max = (1 << 16) - 1, + }, + /* segment 2 */ + { + .flags = (DRM_MODE_LUT_POST_CSC | + DRM_MODE_LUT_PRE_CSC | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 16, .output_bpc = 16, + .start = (1 << 16) - (1 << 16) / 33, .end = 1 << 16, + .min = 0, .max = 1 << 16, + }, + /* Segment 3 */ + { + .flags = (DRM_MODE_LUT_POST_CSC | + DRM_MODE_LUT_PRE_CSC | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 16, .output_bpc = 16, + .start = 1 << 16, .end = 3 << 16, + .min = 0, .max = (8 << 16) - 1, + }, + /* Segment 4 */ + { + .flags = (DRM_MODE_LUT_POST_CSC | + DRM_MODE_LUT_PRE_CSC | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 16, .output_bpc = 16, + .start = 3 << 16, .end = 7 << 16, + .min = 0, .max = (8 << 16) - 1, + }, +}; + void intel_color_crtc_init(struct intel_crtc *crtc) { struct drm_i915_private *i915 = to_i915(crtc->base.dev); -- 2.38.1
[RFC 13/33] drm: Reset plane color state on pipeline switch request
From: Chaitanya Kumar Borah When a pipeline switch is requested by user, driver resets blobs for all the hardware blocks to get to clean state. These are then populated with the new blob id's as programmed by user. For the already enabled hardware blocks, if the user does not add entry in the new switch request, the blob id's will remain NULL eventually resulting in disabling of that hardware block. Co-developed-by: Uma Shankar Signed-off-by: Uma Shankar Signed-off-by: Chaitanya Kumar Borah --- drivers/gpu/drm/drm_atomic_uapi.c | 52 --- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 259cd4f5f520..9e0fb36d1f47 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -362,6 +362,38 @@ static s32 __user *get_out_fence_for_connector(struct drm_atomic_state *state, return fence_ptr; } +static +bool color_pipeline_change_requested(struct drm_device *dev, +struct drm_property_blob *plane_cp_set_blob, +uint64_t blob_id) +{ + bool is_change_requested = false; + struct drm_property_blob *new_blob = NULL; + struct drm_color_pipeline *old_cp, *new_cp; + + /* +* User is setting the pipeline for the first time +*/ + if (!plane_cp_set_blob) + goto out; + + old_cp = plane_cp_set_blob->data; + + if (blob_id != 0) { + new_blob = drm_property_lookup_blob(dev, blob_id); + if (!new_blob) + goto out; + + new_cp = new_blob->data; + + if (old_cp->num != new_cp->num) + is_change_requested = true; + } + drm_property_blob_put(new_blob); +out: + return is_change_requested; +} + static int drm_atomic_replace_property_blob_from_id(struct drm_device *dev, struct drm_property_blob **blob, @@ -727,6 +759,12 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane, } else if (property == plane->scaling_filter_property) { state->scaling_filter = val; } else if (property == plane->set_color_pipeline_prop) { + bool cp_change_requested; + + cp_change_requested = color_pipeline_change_requested(dev, + state->set_color_pipeline_data, + val); + ret = drm_atomic_replace_property_blob_from_id(dev, >set_color_pipeline_data, val, @@ -736,12 +774,18 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane, if (replaced) { /* Consider actual color parameter change only when * individual color blobs are replaced. Hence, reset -* the replaced boolean. +* the replaced boolean but first reset all color +* blobs if color pipeline change is requested. */ + if (val && cp_change_requested) + ret = drm_plane_reset_color_op_blobs(plane, + state, ); replaced = false; - ret = drm_plane_replace_color_op_blobs(plane, state, - val, - ); + if (!ret) { + ret = drm_plane_replace_color_op_blobs(plane, state, + val, + ); + } } state->color_mgmt_changed |= replaced; -- 2.38.1
[RFC 11/33] drm: Replace individual color blobs
From: Chaitanya Kumar Borah Replace the color operation blobs depending on the values sent by userspace. Co-developed-by: Uma Shankar Signed-off-by: Uma Shankar Signed-off-by: Chaitanya Kumar Borah --- drivers/gpu/drm/drm_atomic_uapi.c | 97 +++ 1 file changed, 97 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index a2d3393d21a2..20f9366865ca 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -404,6 +404,92 @@ drm_atomic_replace_property_blob_from_id(struct drm_device *dev, return 0; } +/* + * Helper to replace individual color blobs for a plane. The function + * changes all the color blobs sent by userspace agnostic of the color + * pipeline chosen. Since, the information about color pipeline is + * available at driver level, the driver should check for + * the sanity of the userspace data. + */ +static +int drm_plane_replace_color_op_blobs(struct drm_plane *plane, +struct drm_plane_state *state, +uint64_t color_pipeline_blob_id, +bool *replaced) +{ + struct drm_device *dev = plane->dev; + struct drm_property_blob *new_blob; + struct drm_color_pipeline *color_pipeline; + struct drm_color_op_data *color_op; + int ret = 0, i; + bool blob_replaced = false; + bool temp_replaced = false; + + new_blob = drm_property_lookup_blob(dev, color_pipeline_blob_id); + + if (!new_blob) { + ret = -EINVAL; + goto out; + } + + color_pipeline = new_blob->data; + color_op = kzalloc(color_pipeline->size, GFP_KERNEL); + if (!color_op) { + ret = -ENOMEM; + goto mem_fail; + } + + if (copy_from_user(color_op, color_pipeline->data, color_pipeline->size)) { + ret = -EFAULT; + goto copy_fail; + } + + for (i = 0; i < color_pipeline->size / sizeof(struct drm_color_op_data); i++) { + if (color_op[i].name == DRM_CB_CSC) { + ret = drm_atomic_replace_property_blob_from_id(dev, + >color.ctm, + color_op[i].blob_id, + -1, sizeof(struct drm_color_ctm), + _replaced); + } else if (color_op[i].name == DRM_CB_PRE_CSC) { + ret = drm_atomic_replace_property_blob_from_id(dev, + >color.pre_csc_lut, + color_op[i].blob_id, + -1, sizeof(struct drm_color_lut_ext), + _replaced); + } else if (color_op[i].name == DRM_CB_POST_CSC) { + ret = drm_atomic_replace_property_blob_from_id(dev, + >color.post_csc_lut, + color_op[i].blob_id, + -1, sizeof(struct drm_color_lut_ext), + _replaced); + } else if (color_op[i].name == DRM_CB_PRIVATE) { + ret = drm_atomic_replace_property_blob_from_id(dev, + >color.private_color_op_data, + color_op[i].blob_id, + -1, -1, + _replaced); + } else { + ret = -EINVAL; + goto copy_fail; + } + + if (ret) + goto copy_fail; + + temp_replaced |= blob_replaced; + } + +copy_fail: + kfree(color_op); +mem_fail: + drm_property_blob_put(new_blob); +out: + if (!ret) + *replaced |= temp_replaced; + return ret; +} + static int drm_atomic_crtc_set_property(struct drm_crtc *crtc, struct drm_crtc_state *state, struct drm_property *property, uint64_t val) @@ -597,6 +683,17 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane, -1, sizeof(struct drm_color_pipeline), ); + if (replaced) { + /* Consider actual color parameter change only when +* individual color blobs are replaced. Hence, reset +
[RFC 12/33] drm: Reset pipeline when user sends NULL blob
From: Chaitanya Kumar Borah User can disable the color pipeline entirely, thereby disabling all the color hardware blocks in the pipeline. User should set NULL as the blob id and invoke SET_COLOR_PIPELINE property. Driver will disable all the color hardware blocks by updating respective blob id's as NULL. Co-developed-by: Uma Shankar Signed-off-by: Uma Shankar Signed-off-by: Chaitanya Kumar Borah --- drivers/gpu/drm/drm_atomic_uapi.c | 50 +++ 1 file changed, 50 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 20f9366865ca..259cd4f5f520 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -411,6 +411,53 @@ drm_atomic_replace_property_blob_from_id(struct drm_device *dev, * available at driver level, the driver should check for * the sanity of the userspace data. */ +static +int drm_plane_reset_color_op_blobs(struct drm_plane *plane, + struct drm_plane_state *state, + bool *replaced) +{ + struct drm_device *dev = plane->dev; + int ret; + bool blob_replaced = false; + bool temp_replaced = false; + + ret = drm_atomic_replace_property_blob_from_id(dev, + >color.ctm, + 0, -1, -1, + _replaced); + temp_replaced |= blob_replaced; + if (ret) + goto out; + + ret = drm_atomic_replace_property_blob_from_id(dev, + >color.pre_csc_lut, + 0, -1, -1, + _replaced); + temp_replaced |= blob_replaced; + + if (ret) + goto out; + + ret = drm_atomic_replace_property_blob_from_id(dev, + >color.post_csc_lut, + 0, -1, -1, + _replaced); + temp_replaced |= blob_replaced; + + ret = drm_atomic_replace_property_blob_from_id(dev, + >color.private_color_op_data, + 0, -1, -1, + _replaced); + temp_replaced |= blob_replaced; + + if (ret) + goto out; +out: + if (!ret) + *replaced |= temp_replaced; + return ret; +} + static int drm_plane_replace_color_op_blobs(struct drm_plane *plane, struct drm_plane_state *state, @@ -425,6 +472,9 @@ int drm_plane_replace_color_op_blobs(struct drm_plane *plane, bool blob_replaced = false; bool temp_replaced = false; + if (!color_pipeline_blob_id) + return drm_plane_reset_color_op_blobs(plane, state, replaced); + new_blob = drm_property_lookup_blob(dev, color_pipeline_blob_id); if (!new_blob) { -- 2.38.1
[RFC 09/33] drm: Add color information to plane state
Add a new structure drm_plane_color to plane state. It consists of blobs with data needed for respective color HW blocks. Currently defining below blobs pre-csc: can be used to linearize the input frame buffer data. csc: used for color space conversion. post-csc: can be used non-linearize frame buffer data or to perform Tone mapping for HDR use-cases private: can be used for vendor specific fixed function operations This can be extended to include other color operations as well. Co-developed-by: Chaitanya Kumar Borah Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- include/drm/drm_plane.h | 41 + 1 file changed, 41 insertions(+) diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index fcd589cb38f2..601b01e47a93 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -245,6 +245,47 @@ struct drm_plane_state { */ struct drm_property_blob *set_color_pipeline_data; + /** +* @drm_plane_color: +* +* Encapsulates all color states. +*/ + struct drm_plane_color { + /** +* @pre_csc_lut: +* +* Lookup table for converting framebuffer pixel data before apply the +* color conversion matrix @ctm. See drm_plane_enable_color_mgmt(). The +* blob (if not NULL) is an array of drm_color_lut_ext. +*/ + struct drm_property_blob *pre_csc_lut; + + /** +* @ctm: +* +* Color transformation matrix. See drm_plane_enable_color_mgmt(). The +* blob (if not NULL) is a drm_color_ctm. +*/ + struct drm_property_blob *ctm; + + /** +* @post_csc_lut: +* +* Lookup table for converting framebuffer pixel data after applying the +* color conversion matrix @ctm. See drm_plane_enable_color_mgmt(). The +* blob (if not NULL) is an array of drm_color_lut_ext. +*/ + struct drm_property_blob *post_csc_lut; + + /** +* @private_color_op_data: +* +* This blob is intended for drivers to implement driver private color operations. +* For example: Parameterized/non-parameterized fixed function operations +*/ + struct drm_property_blob *private_color_op_data; + } color; + /** * @color_mgmt_changed: Plane color pipeline state has changed * Used by the atomic helpers and -- 2.38.1
[RFC 08/33] drm: Add color lut range structure
Add color lut range structure which is to be used to advertize the capabilities of pre-csc/post-csc color operation blocks. Co-developed-by: Chaitanya Kumar Borah Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- include/uapi/drm/drm_mode.h | 77 + 1 file changed, 77 insertions(+) diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 1cd656b0e994..6ce7bd0926e0 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -1091,6 +1091,83 @@ struct drm_color_pipeline { DRM_MODE_PAGE_FLIP_ASYNC | \ DRM_MODE_PAGE_FLIP_TARGET) +/** + * DRM_MODE_LUT_POST_CSC + * + * LUT is for post csc (after CTM) + */ +#define DRM_MODE_LUT_POST_CSC BIT(0) + +/** + * DRM_MODE_LUT_PRE_CSC + * + * LUT is for pre csc (before CTM) + */ +#define DRM_MODE_LUT_PRE_CSC BIT(1) + +/** + * DRM_MODE_LUT_INTERPOLATE + * + * linearly interpolate between the points + */ +#define DRM_MODE_LUT_INTERPOLATE BIT(2) + +/** + * DRM_MODE_LUT_REUSE_LAST + * + * the last value of the previous range is the + * first value of the current range. + */ +#define DRM_MODE_LUT_REUSE_LAST BIT(3) + +/** + * DRM_MODE_LUT_NON_DECREASING + * + * the curve must be non-decreasing + */ +#define DRM_MODE_LUT_NON_DECREASING BIT(4) + +/** + * DRM_MODE_LUT_REFLECT_NEGATIVE + * + * the curve is reflected across origin for negative inputs + */ +#define DRM_MODE_LUT_REFLECT_NEGATIVE BIT(5) + +/** + * DRM_MODE_LUT_SINGLE_CHANNEL + * + * the same curve (red) is used for blue and green channels as well + */ +#define DRM_MODE_LUT_SINGLE_CHANNEL BIT(6) + +/** + * struct drm_color_lut_range + * + * structure to advertise capability of a color hardware + * block that accepts LUT values. It can represent LUTs with + * varied number of entries and distributions + * (Multi segmented, Logarithmic etc). + */ + +struct drm_color_lut_range { + /* DRM_MODE_LUT_* */ + __u32 flags; + /* number of points on the curve */ + __u16 count; + /* input/output bits per component */ + __u8 input_bpc, output_bpc; + /* input start/end values */ + __s32 start, end; + /* output min/max values */ + __s32 min, max; +}; + +enum lut_type { + LUT_TYPE_PRE_CSC = 0, + LUT_TYPE_POST_CSC = 1, +}; + /* * Request a page flip on the specified crtc. * -- 2.38.1
[RFC 07/33] drm: Add Enhanced Gamma LUT precision structure
Existing LUT precision structure is having only 16 bit precision. This is not enough for upcoming enhanced hardwares and advance usecases like HDR processing. Hence added a new structure with 32 bit precision values. Co-developed-by: Chaitanya Kumar Borah Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- include/uapi/drm/drm_mode.h | 17 + 1 file changed, 17 insertions(+) diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index a21825ee93e2..1cd656b0e994 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -943,6 +943,23 @@ struct hdr_output_metadata { }; }; +/** + * struct drm_color_lut_ext - Represents high precision lut values + * + * Creating 64 bit palette entries for better data + * precision. This will be required for HDR and + * similar color processing usecases. + */ +struct drm_color_lut_ext { + /* +* Data is U32.32 fixed point format. +*/ + __u64 red; + __u64 green; + __u64 blue; + __u64 reserved; +}; + /** * enum color_op_block * -- 2.38.1
[RFC 05/33] drm: Add structures for setting color pipeline
Add structures using which user space can set a color pipeline it desires. The patch introduces two structures struct drm_color_op_data represents data to be passed onto individual color hardware blocks. struct drm_color_pipeline represents the aggregate of drm_color_op_data structures to program the respective color hardware blocks of the pipeline. It also contains the pipeline number to be set. Co-developed-by: Chaitanya Kumar Borah Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- include/uapi/drm/drm_mode.h | 30 ++ 1 file changed, 30 insertions(+) diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 882479f41745..a21825ee93e2 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -1015,6 +1015,36 @@ struct drm_color_op { __u32 private_flags; }; +/** + * struct drm_color_op_data + * + * Structure for userspace to send data to a particular color operation + * block. + * + * @name: Name of the color block for which the data is being sent + * @blob_id: Id pointing to blob with data for the color operation block + */ +struct drm_color_op_data { + enum color_op_block name; + __u32 blob_id; +}; + +/** + * struct drm_color_pipeline + * + * This structure represents the aggregate pipeline to be set + * + * @num: pipeline number to be selected + * @size: size of the data to be passed onto the driver + * @data: array of struct drm_color_op_data with data for the + * hardware block/s that user space wants to set values for + */ +struct drm_color_pipeline { + int num; + int size; + struct drm_color_op_data *data; +}; + /** * DRM_MODE_PAGE_FLIP_EVENT * -- 2.38.1
[RFC 06/33] drm: Add set colorpipeline property
Add a new plane blob property "SET_COLOR_PIPELINE" using which the user can select a color pipeline and send data for corresponding hardware blocks. Once the user space decides on a color pipeline, it can set the pipeline and corresponding data for the hardware blocks within the pipeline. Co-developed-by: Chaitanya Kumar Borah Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- drivers/gpu/drm/drm_atomic_uapi.c | 12 + drivers/gpu/drm/drm_color_mgmt.c | 42 +++ include/drm/drm_plane.h | 22 3 files changed, 76 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 98d3b10c08ae..a2d3393d21a2 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -590,6 +590,15 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane, return ret; } else if (property == plane->scaling_filter_property) { state->scaling_filter = val; + } else if (property == plane->set_color_pipeline_prop) { + ret = drm_atomic_replace_property_blob_from_id(dev, + >set_color_pipeline_data, + val, + -1, + sizeof(struct drm_color_pipeline), + ); + state->color_mgmt_changed |= replaced; + return ret; } else if (plane->funcs->atomic_set_property) { return plane->funcs->atomic_set_property(plane, state, property, val); @@ -651,6 +660,9 @@ drm_atomic_plane_get_property(struct drm_plane *plane, state->fb_damage_clips->base.id : 0; } else if (property == plane->scaling_filter_property) { *val = state->scaling_filter; + } else if (property == plane->set_color_pipeline_prop) { + *val = (state->set_color_pipeline_data) ? + state->set_color_pipeline_data->base.id : 0; } else if (plane->funcs->atomic_get_property) { return plane->funcs->atomic_get_property(plane, state, property, val); } else { diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index 43d0187faa98..3ef58da94556 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -634,6 +634,48 @@ void drm_plane_attach_get_color_pipeline_property(struct drm_plane *plane) } EXPORT_SYMBOL(drm_plane_attach_get_color_pipeline_property); +/** + * drm_plane_create_set_color_pipeline_property - create property to set color pipeline + * @dev: DRM device + * @plane: plane object + * + * create blob property using which the user space can set up a plane color pipeline. + * Userspace can send data for one or multiple hardware blocks in the pipeline. + */ +int drm_plane_create_set_color_pipeline_property(struct drm_device *dev, +struct drm_plane *plane) +{ + struct drm_property *prop; + + prop = drm_property_create(dev, DRM_MODE_PROP_BLOB, + "SET_COLOR_PIPELINE", 0); + if (!prop) + return -ENOMEM; + + plane->set_color_pipeline_prop = prop; + + return 0; +} +EXPORT_SYMBOL(drm_plane_create_set_color_pipeline_property); + +/** + * drm_plane_attach_set_color_pipeline_property - attach set color pipeline property to a plane + * @plane: plane object + * + * Attach "SET_COLOR_PIPELINE" property to a plane. The property will be visible to + * the userspace once we attach the property. The default value is set to 0 indicating + * no colorpipeline which essentially disables all the color HW blocks in the pipeline. + */ +void drm_plane_attach_set_color_pipeline_property(struct drm_plane *plane) +{ + if (!plane->set_color_pipeline_prop) + return; + + drm_object_attach_property(>base, + plane->set_color_pipeline_prop, 0); +} +EXPORT_SYMBOL(drm_plane_attach_set_color_pipeline_property); + /** * drm_plane_add_color_pipeline - helper to add a color pipeline * @plane: plane object diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index ffd7887c2acf..fcd589cb38f2 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -237,6 +237,20 @@ struct drm_plane_state { /** @state: backpointer to global drm_atomic_state */ struct drm_atomic_state *state; + + /** +* @set_color_pipeline_data: +* +* Stores information about the current selected color pipeline +*/ + struct drm_property_blob *set_color_pipeline_data; + + /** +* @color_mgmt_changed: Pla
[RFC 03/33] drm: Add plane get color pipeline property
From: Chaitanya Kumar Borah Each hardware plane can consist of multiple color hardware blocks. These hardware blocks are defined by a color pipeline. In case, hardware blocks can be re-arranged/muxed a distinct pipeline can be defined to represent the same. Introduce a new enum plane property "GET_COLOR_PIPELINE" to expose the color pipelines that a particular plane supports. This enum property has blob id's as values. With each blob id representing a distinct color pipeline based on underlying HW capabilities and their respective combinations. Add helpers to create and attach the property to a plane. Co-developed-by: Uma Shankar Signed-off-by: Uma Shankar Signed-off-by: Chaitanya Kumar Borah --- drivers/gpu/drm/drm_color_mgmt.c | 46 include/drm/drm_plane.h | 10 +++ 2 files changed, 56 insertions(+) diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index d021497841b8..026d057d1f1f 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -588,6 +588,52 @@ int drm_plane_create_color_properties(struct drm_plane *plane, } EXPORT_SYMBOL(drm_plane_create_color_properties); +/** + * drm_plane_create_get_color_pipeline_property - create property to expose color pipelines + * @dev: DRM device + * @plane: plane object + * @num_val: number of color pipelines supported + * + * create enum property to expose color pipelines to userspace. This enum + * property has blob id's as values. With each blob id representing + * a distinct color pipeline based on underlying HW capabilities and + * their respective combinations. + */ +int drm_plane_create_get_color_pipeline_property(struct drm_device *dev, +struct drm_plane *plane, +int num_val) +{ + struct drm_property *prop; + + prop = drm_property_create(dev, DRM_MODE_PROP_ENUM | + DRM_MODE_PROP_IMMUTABLE, + "GET_COLOR_PIPELINE", num_val); + if (!prop) + return -ENOMEM; + + plane->get_color_pipeline_prop = prop; + + return 0; +} +EXPORT_SYMBOL(drm_plane_create_get_color_pipeline_property); + +/** + * drm_plane_attach_get_color_pipeline_property - attach get color pipeline property to a plane + * @plane: plane object + * + * Attach "GET_COLOR_PIPELINE" property to a plane. The property will be visible to + * the userspace once we attach the property. + */ +void drm_plane_attach_get_color_pipeline_property(struct drm_plane *plane) +{ + if (!plane->get_color_pipeline_prop) + return; + + drm_object_attach_property(>base, + plane->get_color_pipeline_prop, 0); +} +EXPORT_SYMBOL(drm_plane_attach_get_color_pipeline_property); + /** * drm_color_lut_check - check validity of lookup table * @lut: property blob containing LUT to check diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index 79d62856defb..256c97ead698 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -748,6 +748,12 @@ struct drm_plane { * scaling. */ struct drm_property *scaling_filter_property; + + /** +* @get_color_pipeline_prop: Optional Plane property to get the color pipelines +* that the plane supports +*/ + struct drm_property *get_color_pipeline_prop; }; #define obj_to_plane(x) container_of(x, struct drm_plane, base) @@ -945,5 +951,9 @@ drm_plane_get_damage_clips(const struct drm_plane_state *state); int drm_plane_create_scaling_filter_property(struct drm_plane *plane, unsigned int supported_filters); +int drm_plane_create_get_color_pipeline_property(struct drm_device *dev, +struct drm_plane *plane, +int num_val); +void drm_plane_attach_get_color_pipeline_property(struct drm_plane *plane); #endif -- 2.38.1
[RFC 02/33] drm: Add color operation structure
From: Chaitanya Kumar Borah Each Color Hardware block will be represented uniquely in the color pipeline. Define the structure to represent the same. These color operations will form the building blocks of a color pipeline which best represents the underlying Hardware. Color operations can be re-arranged, substracted or added to create distinct color pipelines to accurately describe the Hardware blocks present in the display engine. Co-developed-by: Uma Shankar Signed-off-by: Uma Shankar Signed-off-by: Chaitanya Kumar Borah --- include/uapi/drm/drm_mode.h | 72 + 1 file changed, 72 insertions(+) diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index ea1b639bcb28..882479f41745 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -943,6 +943,78 @@ struct hdr_output_metadata { }; }; +/** + * enum color_op_block + * + * Enums to identify hardware color blocks. + * + * @DRM_CB_PRE_CSC: LUT before the CTM unit + * @DRM_CB_CSC: CTM hardware supporting 3x3 matrix + * @DRM_CB_POST_CSC: LUT after the CTM unit + * @DRM_CB_3D_LUT: LUT hardware with coefficients for all + * color components + * @DRM_CB_PRIVATE: Vendor specific hardware unit. Vendor + * can expose a custom hardware by defining a + * color operation block with this name as + * identifier + */ +enum color_op_block { + DRM_CB_INVAL = -1, + + DRM_CB_PRE_CSC = 0, + DRM_CB_CSC, + DRM_CB_POST_CSC, + DRM_CB_3D_LUT, + + /* Any new generic hardware block can be updated here */ + + /* +* PRIVATE is kept at 255 to make it future proof and leave +* scope for any new addition +*/ + DRM_CB_PRIVATE = 255, + DRM_CB_MAX = DRM_CB_PRIVATE, +}; + +/** + * enum color_op_type + * + * These enums are to identify the mathematical operation that + * a hardware block is capable of. + * @CURVE_1D: It represents a one dimensional lookup table + * @CURVE_3D: Represents lut value for each color component for 3d lut capable hardware + * @MATRIX: It represents co-efficients for a CSC/CTM matrix hardware + * @FIXED_FUNCTION: To enable and program any custom fixed function hardware unit + */ +enum color_op_type { + CURVE_1D, + CURVE_3D, + MATRIX, + FIXED_FUNCTION, +}; + +/** + * @struct drm_color_op + * + * This structure is used to represent the capability of + * individual color hardware blocks. + * + * @name: a standardized enum to identify the color hardware block + * @type: The type of mathematical operation it can perform + * @blob_id: Id pointing to a blob containing information about + * the hardware block which advertizes its capabilities + * to the userspace. It can be an optional field depending + * on the members "name" and "type". + * @private_flags: This can be used to provide vendor specific hints + * to user space + */ +struct drm_color_op { + enum color_op_block name; + enum color_op_type type; + __u32 blob_id; + __u32 private_flags; +}; + /** * DRM_MODE_PAGE_FLIP_EVENT * -- 2.38.1
[RFC 04/33] drm: Add helper to add color pipeline
From: Chaitanya Kumar Borah Create a helper function to add a color pipeline for a plane. Color pipeline is an array of struct drm_color_op which represent a possible logical combination of color operations. Color operations can be re-arranged, substracted or added to create distinct color pipelines to accurately describe the Hardware blocks present in the display engine. Co-developed-by: Uma Shankar Signed-off-by: Uma Shankar Signed-off-by: Chaitanya Kumar Borah --- drivers/gpu/drm/drm_color_mgmt.c | 42 include/drm/drm_plane.h | 3 +++ 2 files changed, 45 insertions(+) diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index 026d057d1f1f..43d0187faa98 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -634,6 +634,48 @@ void drm_plane_attach_get_color_pipeline_property(struct drm_plane *plane) } EXPORT_SYMBOL(drm_plane_attach_get_color_pipeline_property); +/** + * drm_plane_add_color_pipeline - helper to add a color pipeline + * @plane: plane object + * @name: name of the color pipeline + * @color_pipeline: an array of 'struct drm_color_op' to represent a color pipeline + * @len: size of the color pipeline + * + * This helper can be used to add a distinct color pipeline to a plane. A driver + * can provide a meaningful name to the pipeline as it desires. + */ +int drm_plane_add_color_pipeline(struct drm_plane *plane, char *name, +struct drm_color_op *color_pipeline, +size_t len) +{ + int ret; + struct drm_property *prop; + struct drm_property_blob *blob; + u32 id = 0; + + prop = plane->get_color_pipeline_prop; + + if (color_pipeline && !len) + return -EINVAL; + + if (color_pipeline) { + blob = drm_property_create_blob(plane->dev, len, color_pipeline); + if (IS_ERR(blob)) + return PTR_ERR(blob); + + id = blob->base.id; + }; + + ret = drm_property_add_enum(prop, id, name); + if (ret) { + if (blob) + drm_property_blob_put(blob); + return ret; + } + return 0; +} +EXPORT_SYMBOL(drm_plane_add_color_pipeline); + /** * drm_color_lut_check - check validity of lookup table * @lut: property blob containing LUT to check diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index 256c97ead698..ffd7887c2acf 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -955,5 +955,8 @@ int drm_plane_create_get_color_pipeline_property(struct drm_device *dev, struct drm_plane *plane, int num_val); void drm_plane_attach_get_color_pipeline_property(struct drm_plane *plane); +int drm_plane_add_color_pipeline(struct drm_plane *plane, char *name, +struct drm_color_op *color_pipeline, +size_t len); #endif -- 2.38.1
[RFC 01/33] drm/doc/rfc: Add RFC document for proposed Plane Color Pipeline
Add the documentation for the new proposed Plane Color Pipeline. Co-developed-by: Chaitanya Kumar Borah Signed-off-by: Chaitanya Kumar Borah Signed-off-by: Uma Shankar --- .../gpu/rfc/plane_color_pipeline.rst | 394 ++ 1 file changed, 394 insertions(+) create mode 100644 Documentation/gpu/rfc/plane_color_pipeline.rst diff --git a/Documentation/gpu/rfc/plane_color_pipeline.rst b/Documentation/gpu/rfc/plane_color_pipeline.rst new file mode 100644 index ..60ce515b6ea7 --- /dev/null +++ b/Documentation/gpu/rfc/plane_color_pipeline.rst @@ -0,0 +1,394 @@ +=== + Plane Color Pipeline: A UAPI proposal +=== + +To build the proposal on, lets take the premise of a color pipeline as shown +below. + + +---+ + |RAM| + | +--++-++-+ | + | | FB 1 || FB 2 || FB N| | + | +--++-++-+ | + +---+ + | Plane Color Hardware Block | + ++ + | +---v-+ +---v---+ +---v--+ | + | | Plane A | | Plane B | | Plane N | | + | | Pre-CSC | | Pre-CSC | | Pre-CSC | | + | +---+-+ +---+---+ +---+--+ | + | | | || + | +---v-+ +---v---+ +---v--+ | + | |Plane A | | Plane B | | Plane N | | + | |CSC/CTM | | CSC/CTM | | CSC/CTM | | + | +---+-+ ++--+ ++-+ | + | | | | | + | +---v-+ +v--+ +v-+ | + | | Plane A | | Plane B | | Plane N | | + | |Post-CSC | | Post-CSC | | Post-CSC | | + | +---+-+ ++--+ ++-+ | + | | | | | + ++ ++--v--v---v---| +|| || +|| Pipe Blender|| ++++ +||| +|+---v--+ | +|| Pipe Pre-CSC| | +|| | | +|+---+--+ | +||Pipe Color | +|+---v--+ Hardware| +|| Pipe CSC/CTM| | +|| | | +|+---+--+ | +||| +|+---v--+ | +|| Pipe Post-CSC | | +|| | | +|+---+--+ | +||| ++-+ + | + v +Pipe Output + +Each plane consists of the following color blocks + * Pre-CSC : This block can used to linearize the input frame buffer data. + The linear data then can be further acted on by the following + color hardware blocks in the display hardware pipeline + + * CSC/CTM: Used to program color transformation matrix, this block is used +to perform color space conversions like BT2020 to BT709 or BT601 +etc. This block acts on the linearized data coming from the +Pre-CSC HW block. + + * Post-CSC: This HW block can be used to non-linearize frame buffer data to + match the sink. Another use case of it could be to perform Tone + mapping for HDR use-cases. + +Data from multiple planes will then be fed to pipe/crtc where it will get blended. +There is a similar set of HW blocks available at pipe/crtc level which acts on +this blended data. + +Below is a sample usecase fo video playback with sub-titles and playback +controls + +┌┐┌─┐ ┌─┐┌─┐ +│FB1 ││PRE-CSC │ │ CTM Matrix ││ POST-CSC│ +│├───►│Linearize├►│ BT709 to├───►│ SDR to HDR │ +│BT709 SDR ││ │ │ BT2020 ││ Tone Mapping├─┐ +└┘└─┘ └─┘└─┘ │ +(subtitles) │ + │ +┌┐┌─┐ ┌─┐┌─┐ │ +│FB2 ││PRE-CSC │ │ CTM Matrix ││ POST-CSC│ │ +│├───►│Linearize├►│ BT601 to├───►│ SDR to HDR ├───┐ │ +│BT601 SDR ││ │ │ BT2020 ││ Tone Mapping
[RFC 00/33] Add Support for Plane Color Pipeline
ocumentation/gpu/rfc/plane_color_pipeline.rst added in the patch IGT and test details A set of IGT tests is written to demonstrate the usage of the proposed UAPIs along with some sanity validation. Details of the IGT test can be found here: https://patchwork.freedesktop.org/series/123018/ Opens = a. To come up with a list of common HW blocks which can be defined generically by the DRM core in agreement with all the stakeholders b. To enhance/finalize the data structure to define segmented LUTs generically. Out of Scope a. The coefficients for CTM and LUT value calculations are out of scope of the proposal. b. The onus of programming the HW blocks and their values is on user-space. Driver will just provide the interface for the same. c. In order to compute LUT values and coefficients, a helper library can be created in user-space. However, it is out of scope for the current proposal. Acknowledgements and credits There are multiple contributors who have helped us to reach to this proposal. Special mention to Ville Syrjala, Pekka Paalanen, Simon Ser, Harry Wentland, Melissa Wen, Jonas, Sebastian Wick, Bhanu and Shashank. Also, thanks to Carlos and the Redhat team for organizing the HDR hackfest. UAPI dependency and Usermode development The current KMS implementation requires a user space consumer for it to be accepted upstream. Work is ongoing in weston and mutter community to get color management and HDR support implemented in the respective stacks. = We have tried to take care of all the scenarios and use-cases which possibly could exists in the current proposal. Thanks to everyone who has contributed in all color management discussions so far. Let's work together to improve the current proposal and get this thing implemented in upstream linux. All the feedback and suggestions to enhance the design are welcome. Regards, Uma Shankar Chaitanya Kumar Borah Cc: Ville Syrjala Cc: Pekka Paalanen Cc: Simon Ser Cc: Harry Wentland Cc: Melissa Wen Cc: Jonas Ådahl Cc: Sebastian Wick Cc: Shashank Sharma Cc: Alexander Goins Chaitanya Kumar Borah (14): drm: Add color operation structure drm: Add plane get color pipeline property drm: Add helper to add color pipeline drm: Manage color blob states drm: Replace individual color blobs drm: Reset pipeline when user sends NULL blob drm: Reset plane color state on pipeline switch request drm/i915/color: Add HDR plane LUT range data to color pipeline drm/i915/color: Add SDR plane LUT range data to color pipeline drm/i915/color: Add color pipelines to plane drm/i915/color: Create and attach set color pipeline property drm/i915/color: Enable plane color features drm/i915/color: Add a dummy pipeline with 3D LUT drm/i915/color: Add example implementation for vendor specific color operation Uma Shankar (19): drm/doc/rfc: Add RFC document for proposed Plane Color Pipeline drm: Add structures for setting color pipeline drm: Add set colorpipeline property drm: Add Enhanced Gamma LUT precision structure drm: Add color lut range structure drm: Add color information to plane state drm/i915/color: Add lut range for SDR planes drm/i915/color: Add lut range for HDR planes drm/i915/color: Add color pipeline for HDR planes drm/i915/color: Add color pipeline for SDR planes drm/i915/color: Add plane color callbacks drm/i915/color: Load plane color luts from atomic flip drm/i915/xelpd: Add plane color check to glk_plane_color_ctl drm/i915/xelpd: Add register definitions for Plane Degamma drm/i915/color: Add color functions for ADL drm/i915/color: Program Plane Pre-CSC Registers drm/i915/xelpd: Add register definitions for Plane Post CSC drm/i915/xelpd: Program Plane Post CSC Registers drm/i915/color: Enable Plane CSC .../gpu/rfc/plane_color_pipeline.rst | 394 ++ drivers/gpu/drm/drm_atomic_state_helper.c | 21 + drivers/gpu/drm/drm_atomic_uapi.c | 218 ++ drivers/gpu/drm/drm_color_mgmt.c | 130 drivers/gpu/drm/i915/display/intel_color.c| 684 +- drivers/gpu/drm/i915/display/intel_color.h| 7 +- .../drm/i915/display/skl_universal_plane.c| 21 +- drivers/gpu/drm/i915/i915_reg.h | 124 include/drm/drm_plane.h | 82 +++ include/uapi/drm/drm_mode.h | 196 + include/uapi/drm/i915_drm.h | 25 + 11 files changed, 1899 insertions(+), 3 deletions(-) create mode 100644 Documentation/gpu/rfc/plane_color_pipeline.rst -- 2.38.1
[RFC v2 22/22] drm/i915/xelpd: Enable plane gamma
Enable plane gamma feature in check callbacks. Decide based on the user input. Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/skl_universal_plane.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 61eff22a3503..139863d4e3a7 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -959,7 +959,9 @@ static u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state, struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); u32 plane_color_ctl = 0; - plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE; + /* FIXME needs hw.gamma_lut */ + if (!plane_state->uapi.gamma_lut) + plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE; /* FIXME needs hw.degamma_lut */ if (plane_state->uapi.degamma_lut) -- 2.26.2
[RFC v2 21/22] drm/i915/xelpd: Program Plane Gamma Registers
Extract the LUT and program plane gamma registers. Enabled multi segmented lut as well. Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 89 ++ drivers/gpu/drm/i915/i915_reg.h| 9 ++- 2 files changed, 94 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index b4cad5c92c85..e5f168a32932 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -27,6 +27,9 @@ #include "intel_de.h" #include "intel_display_types.h" #include "intel_sprite.h" + +#include "skl_universal_plane.h" + #include #define CTM_COEFF_SIGN (1ULL << 63) @@ -2433,16 +2436,102 @@ static void d13_program_plane_degamma_lut(const struct drm_plane_state *state, } } +static void d13_program_plane_gamma_lut(const struct drm_plane_state *state, + struct drm_color_lut_ext *gamma_lut, + u32 offset) +{ + struct drm_i915_private *dev_priv = to_i915(state->plane->dev); + enum pipe pipe = to_intel_plane(state->plane)->pipe; + enum plane_id plane = to_intel_plane(state->plane)->id; + u32 i, lut_size; + + if (icl_is_hdr_plane(dev_priv, plane)) { + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_INDEX_ENH(pipe, plane, 0), + offset | PLANE_PAL_PREC_AUTO_INCREMENT); + if (gamma_lut) { + lut_size = 32; + for (i = 0; i < lut_size; i++) { + u64 word = drm_color_lut_extract_ext(gamma_lut[i].green, 24); + u32 lut_val = (word & 0xff); + + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, 0), + lut_val); + } + + do { + /* Program the max register to clamp values > 1.0. */ + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, 0), + gamma_lut[i].green); + } while (i++ < 34); + } else { + lut_size = 32; + for (i = 0; i < lut_size; i++) { + u32 v = (i * ((1 << 24) - 1)) / (lut_size - 1); + + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, 0), v); + } + + do { + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, 0), + 1 << 24); + } while (i++ < 34); + } + + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_INDEX_ENH(pipe, plane, 0), 0); + } else { + lut_size = 32; + /* +* First 3 planes are HDR, so reduce by 3 to get to the right +* SDR plane offset +*/ + plane = plane - 3; + + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_INDEX(pipe, plane, 0), + offset | PLANE_PAL_PREC_AUTO_INCREMENT); + + if (gamma_lut) { + for (i = 0; i < lut_size; i++) + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_DATA(pipe, plane, 0), + gamma_lut[i].green & 0x); + /* Program the max register to clamp values > 1.0. */ + while (i < 35) + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_DATA(pipe, plane, 0), + gamma_lut[i++].green & 0x3); + } else { + for (i = 0; i < lut_size; i++) { + u32 v = (i * ((1 << 16) - 1)) / (lut_size - 1); + + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_DATA(pipe, plane, 0), v); + } + + do { + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_DATA(pipe, plane, 0), + (1 << 16)); + } while (i++ < 34); + } + + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_INDEX(pipe, plane, 0), 0); + } +} + static void d13_plane_load_luts(const struct drm_plane_state *plane_state) { const struct drm_property_blob *degamma_lut_blob = plane_state->degamma_lut; + const struct drm_property_blob *gamma_lut_blob =
[RFC v2 20/22] drm/i915/xelpd: Add register definitions for Plane Gamma
Add macros to define Plane Gamma registers Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/i915_reg.h | 73 + 1 file changed, 73 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index ceee500e64d7..fc4f8b430518 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -11464,6 +11464,79 @@ enum skl_power_gate { _MMIO_PLANE_GAMC(plane, i, _PLANE_PRE_CSC_GAMC_DATA_1(pipe), \ _PLANE_PRE_CSC_GAMC_DATA_2(pipe)) +/* Display13 Plane Gamma Reg */ +#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1_A0x70160 +#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1_B0x71160 +#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2_A0x70260 +#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2_B0x71260 +#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1(pipe)_PIPE(pipe, _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1_A, \ + _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1_B) +#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2(pipe)_PIPE(pipe, _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2_A, \ + _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2_B) +#define PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1(pipe), \ + _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2(pipe)) + +#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1_A 0x70164 +#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1_B 0x71164 +#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2_A 0x70264 +#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2_B 0x71264 +#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1_A, \ + _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1_B) +#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2_A, \ + _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2_B) +#define PLANE_POST_CSC_GAMC_SEG0_DATA_ENH(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1(pipe), \ + _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2(pipe)) + +#define _PLANE_POST_CSC_GAMC_INDEX_ENH_1_A 0x701d8 +#define _PLANE_POST_CSC_GAMC_INDEX_ENH_1_B 0x711d8 +#define _PLANE_POST_CSC_GAMC_INDEX_ENH_2_A 0x702d8 +#define _PLANE_POST_CSC_GAMC_INDEX_ENH_2_B 0x712d8 +#define _PLANE_POST_CSC_GAMC_INDEX_ENH_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_INDEX_ENH_1_A, \ + _PLANE_POST_CSC_GAMC_INDEX_ENH_1_B) +#define _PLANE_POST_CSC_GAMC_INDEX_ENH_2(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_INDEX_ENH_2_A, \ + _PLANE_POST_CSC_GAMC_INDEX_ENH_2_B) +#define PLANE_POST_CSC_GAMC_INDEX_ENH(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_INDEX_ENH_1(pipe), \ + _PLANE_POST_CSC_GAMC_INDEX_ENH_2(pipe)) + +#define _PLANE_POST_CSC_GAMC_DATA_ENH_1_A 0x701dc +#define _PLANE_POST_CSC_GAMC_DATA_ENH_1_B 0x711dc +#define _PLANE_POST_CSC_GAMC_DATA_ENH_2_A 0x702dc +#define _PLANE_POST_CSC_GAMC_DATA_ENH_2_B 0x712dc +#define _PLANE_POST_CSC_GAMC_DATA_ENH_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_DATA_ENH_1_A, \ + _PLANE_POST_CSC_GAMC_DATA_ENH_1_B) +#define _PLANE_POST_CSC_GAMC_DATA_ENH_2(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_DATA_ENH_2_A, \ + _PLANE_POST_CSC_GAMC_DATA_ENH_2_B) +#define PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_DATA_ENH_1(pipe), \ + _PLANE_POST_CSC_GAMC_DATA_ENH_2(pipe)) + +#define _PLANE_POST_CSC_GAMC_INDEX_1_A 0x704d8 +#define _PLANE_POST_CSC_GAMC_INDEX_1_B 0x714d8 +#define _PLANE_POST_CSC_GAMC_INDEX_2_A 0x705d8 +#define _PLANE_POST_CSC_GAMC_INDEX_2_B 0x715d8 +#define _PLANE_POST_CSC_GAMC_INDEX_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_INDEX_1_A, \ + _PLANE_POST_CSC_GAMC_INDEX_1_B) +#define _PLANE_POST_CSC_GAMC_INDEX_2(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_INDEX_2_A, \ + _PLANE_POST_CSC_GAMC_INDEX_2_B) +#define PLANE_POST_CSC_GAMC_INDEX(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_INDEX_1(pipe), \ + _PLANE_POST_CSC_GAMC_INDEX_2(pipe)) + +#define _PLANE_POST_CSC_GAMC_DATA_1_A 0x704dc +#define _PLANE_POST_CSC_GAMC_DATA_1_B 0x714dc +#define _PLANE_POST_CSC_GAMC_DATA_2_A 0x705dc +#define _PLANE_POST_CSC_GAMC_DATA_2_B 0x715dc +#define _PLANE_POST_CSC_GAMC_DATA_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_DATA_1_A
[RFC v2 18/22] drm: Add Plane Gamma Lut property
Add Plane Gamma Lut as a blob property. Signed-off-by: Uma Shankar --- drivers/gpu/drm/drm_atomic_state_helper.c | 3 +++ drivers/gpu/drm/drm_atomic_uapi.c | 10 ++ drivers/gpu/drm/drm_color_mgmt.c | 18 ++ include/drm/drm_plane.h | 14 ++ 4 files changed, 45 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c index fafb8af1c9cb..7ddf6e4b956b 100644 --- a/drivers/gpu/drm/drm_atomic_state_helper.c +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -316,6 +316,8 @@ void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane, drm_property_blob_get(state->degamma_lut); if (state->ctm) drm_property_blob_get(state->ctm); + if (state->gamma_lut) + drm_property_blob_get(state->gamma_lut); state->color_mgmt_changed = false; } @@ -366,6 +368,7 @@ void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state) drm_property_blob_put(state->fb_damage_clips); drm_property_blob_put(state->degamma_lut); drm_property_blob_put(state->ctm); + drm_property_blob_put(state->gamma_lut); } EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state); diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index b5abf03c5d51..a32557a4e0d3 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -615,6 +615,13 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane, return ret; } else if (property == plane->gamma_mode_property) { state->gamma_mode = val; + } else if (property == plane->gamma_lut_property) { + ret = drm_atomic_replace_property_blob_from_id(dev, + >gamma_lut, + val, -1, sizeof(struct drm_color_lut_ext), + ); + state->color_mgmt_changed |= replaced; + return ret; } else if (property == config->prop_fb_damage_clips) { ret = drm_atomic_replace_property_blob_from_id(dev, >fb_damage_clips, @@ -690,6 +697,9 @@ drm_atomic_plane_get_property(struct drm_plane *plane, *val = (state->ctm) ? state->ctm->base.id : 0; } else if (property == plane->gamma_mode_property) { *val = state->gamma_mode; + } else if (property == plane->gamma_lut_property) { + *val = (state->gamma_lut) ? + state->gamma_lut->base.id : 0; } else if (property == config->prop_fb_damage_clips) { *val = (state->fb_damage_clips) ? state->fb_damage_clips->base.id : 0; diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index 02367e691cf3..b5b3ff7f654d 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -613,6 +613,11 @@ EXPORT_SYMBOL(drm_plane_create_color_properties); * to query and get the plane gamma color caps and choose the * appropriate gamma mode and create lut values accordingly * + * gamma_lut_property: + * Blob property which allows a userspace to provide LUT values + * to apply gamma curve using the h/w plane degamma processing + * engine, thereby making the content as non-linear. + * */ int drm_plane_create_color_mgmt_properties(struct drm_device *dev, struct drm_plane *plane, @@ -648,6 +653,13 @@ int drm_plane_create_color_mgmt_properties(struct drm_device *dev, plane->gamma_mode_property = prop; + prop = drm_property_create(dev, DRM_MODE_PROP_BLOB, + "PLANE_GAMMA_LUT", 0); + if (!prop) + return -ENOMEM; + + plane->gamma_lut_property = prop; + return 0; } EXPORT_SYMBOL(drm_plane_create_color_mgmt_properties); @@ -685,6 +697,12 @@ void drm_plane_attach_gamma_properties(struct drm_plane *plane) drm_object_attach_property(>base, plane->gamma_mode_property, 0); + + if (!plane->gamma_lut_property) + return; + + drm_object_attach_property(>base, + plane->gamma_lut_property, 0); } EXPORT_SYMBOL(drm_plane_attach_gamma_properties); diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index 9081867ecbd1..8b1f506bc5d3 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -270,6 +270,14 @@ struct drm_plane_state { */ u32 gamma_mode; + /* @gamma_lut: +* +* Lookup table for converting framebuffer pixel data after applying the
[RFC v2 19/22] drm/i915/xelpd: Define and Initialize Plane Gamma Lut range
Define the structure with XE_LPD gamma lut ranges. HDR and SDR planes have different capabilities, implemented respective structure for the HDR planes. Degamma and GAMMA has same Lut caps for SDR planes, extended the same. Initialize the mode range caps as well. Signed-off-by: Uma Shankar Signed-off-by: Bhanuprakash Modem --- drivers/gpu/drm/i915/display/intel_color.c | 112 ++--- 1 file changed, 99 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index e9c80ed41466..b4cad5c92c85 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -2247,7 +2247,7 @@ static const struct drm_color_lut_range d13_degamma_hdr[] = { }; /* FIXME input bpc? */ -static const struct drm_color_lut_range d13_degamma_sdr[] = { +static const struct drm_color_lut_range d13_gamma_degamma_sdr[] = { /* segment 1 */ { .flags = (DRM_MODE_LUT_GAMMA | @@ -2297,6 +2297,63 @@ static const struct drm_color_lut_range d13_degamma_sdr[] = { }, }; + /* FIXME input bpc? */ +static const struct drm_color_lut_range d13_gamma_hdr[] = { + /* +* ToDo: Add Segment 1 +* There is an optional fine segment added with 9 lut values +* Will be added later +*/ + + /* segment 2 */ + { + .flags = (DRM_MODE_LUT_GAMMA | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_NON_DECREASING), + .count = 32, + .input_bpc = 24, .output_bpc = 16, + .start = 0, .end = (1 << 24) - 1, + .min = 0, .max = (1 << 24) - 1, + }, + /* segment 3 */ + { + .flags = (DRM_MODE_LUT_GAMMA | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 24, .output_bpc = 16, + .start = (1 << 24) - 1, .end = 1 << 24, + .min = 0, .max = 1 << 24, + }, + /* Segment 4 */ + { + .flags = (DRM_MODE_LUT_GAMMA | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 24, .output_bpc = 16, + .start = 1 << 24, .end = 3 << 24, + .min = 0, .max = (3 << 24), + }, + /* Segment 5 */ + { + .flags = (DRM_MODE_LUT_GAMMA | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 24, .output_bpc = 16, + .start = 3 << 24, .end = 7 << 24, + .min = 0, .max = (7 << 24), + }, +}; + static void d13_program_plane_degamma_lut(const struct drm_plane_state *state, struct drm_color_lut_ext *degamma_lut, u32 offset) @@ -2406,26 +2463,55 @@ int intel_plane_color_init(struct drm_plane *plane) ret = drm_plane_color_add_gamma_degamma_mode_range(plane, "no degamma", NULL, 0, LUT_TYPE_DEGAMMA); - if (icl_is_hdr_plane(dev_priv, to_intel_plane(plane)->id)) + if (ret) + return ret; + + ret = drm_plane_color_add_gamma_degamma_mode_range(plane, "no gamma", + NULL, 0, + LUT_TYPE_GAMMA); + if (ret) + return ret; + + if (icl_is_hdr_plane(dev_priv, to_intel_plane(plane)->id)) { ret = drm_plane_color_add_gamma_degamma_mode_range(plane, "plane degamma", d13_degamma_hdr, sizeof(d13_degamma_hdr), LUT_TYPE_DEGAMMA); - else - ret = drm_plane_color_add_gamma_degamma_mode_r
[RFC v2 17/22] drm: Add Plane Gamma Mode property
Add Plane Gamma Mode as a blob property. This is an enum property with values as blob_id's and exposes the various gamma modes supported and the lut ranges. Getting the blob id in userspace, user can get the mode supported and also the range of gamma mode supported with number of lut coefficients. It can then set one of the modes using this enum property. Lut values will be sent through a separate GAMMA_LUT blob property. Signed-off-by: Uma Shankar Signed-off-by: Bhanuprakash Modem --- drivers/gpu/drm/drm_atomic_uapi.c | 4 drivers/gpu/drm/drm_color_mgmt.c | 26 ++ include/drm/drm_plane.h | 14 ++ 3 files changed, 44 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index e736fd7c1d5b..b5abf03c5d51 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -613,6 +613,8 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane, ); state->color_mgmt_changed |= replaced; return ret; + } else if (property == plane->gamma_mode_property) { + state->gamma_mode = val; } else if (property == config->prop_fb_damage_clips) { ret = drm_atomic_replace_property_blob_from_id(dev, >fb_damage_clips, @@ -686,6 +688,8 @@ drm_atomic_plane_get_property(struct drm_plane *plane, state->degamma_lut->base.id : 0; } else if (property == plane->ctm_property) { *val = (state->ctm) ? state->ctm->base.id : 0; + } else if (property == plane->gamma_mode_property) { + *val = state->gamma_mode; } else if (property == config->prop_fb_damage_clips) { *val = (state->fb_damage_clips) ? state->fb_damage_clips->base.id : 0; diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index 5c3138497b9c..02367e691cf3 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -606,6 +606,13 @@ EXPORT_SYMBOL(drm_plane_create_color_properties); * Blob property which allows a userspace to provide CTM coefficients * to do color space conversion or any other enhancement by doing a * matrix multiplication using the h/w CTM processing engine + * + * gamma_mode_property: + * Blob property which advertizes the possible gamma modes and + * lut ranges supported by the platform. This allows userspace + * to query and get the plane gamma color caps and choose the + * appropriate gamma mode and create lut values accordingly + * */ int drm_plane_create_color_mgmt_properties(struct drm_device *dev, struct drm_plane *plane, @@ -634,6 +641,13 @@ int drm_plane_create_color_mgmt_properties(struct drm_device *dev, plane->ctm_property = prop; + prop = drm_property_create(dev, DRM_MODE_PROP_ENUM, + "PLANE_GAMMA_MODE", num_values); + if (!prop) + return -ENOMEM; + + plane->gamma_mode_property = prop; + return 0; } EXPORT_SYMBOL(drm_plane_create_color_mgmt_properties); @@ -664,6 +678,16 @@ void drm_plane_attach_ctm_property(struct drm_plane *plane) } EXPORT_SYMBOL(drm_plane_attach_ctm_property); +void drm_plane_attach_gamma_properties(struct drm_plane *plane) +{ + if (!plane->gamma_mode_property) + return; + + drm_object_attach_property(>base, + plane->gamma_mode_property, 0); +} +EXPORT_SYMBOL(drm_plane_attach_gamma_properties); + int drm_plane_color_add_gamma_degamma_mode_range(struct drm_plane *plane, const char *name, const struct drm_color_lut_range *ranges, @@ -676,6 +700,8 @@ int drm_plane_color_add_gamma_degamma_mode_range(struct drm_plane *plane, if (type == LUT_TYPE_DEGAMMA) prop = plane->degamma_mode_property; + else + prop = plane->gamma_mode_property; if (!prop) return -EINVAL; diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index 3d329f71d287..9081867ecbd1 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -263,6 +263,13 @@ struct drm_plane_state { */ struct drm_property_blob *ctm; + /** +* @gamma_mode: This is a blob_id and exposes the platform capabilities +* wrt to various gamma modes and the respective lut ranges. This also +* helps user select a gamma mode amongst the supported ones. +*/ + u32 gamma_mode; + u8 color_mgmt_changed : 1; }; @@ -794,6 +801,12 @@ struct drm_pla
[RFC v2 16/22] drm/i915/xelpd: Enable Plane CSC
Implement plane CSC for ICL+ Signed-off-by: Uma Shankar --- .../gpu/drm/i915/display/intel_atomic_plane.c | 5 +- drivers/gpu/drm/i915/display/intel_color.c| 82 +++ .../drm/i915/display/skl_universal_plane.c| 4 + drivers/gpu/drm/i915/i915_reg.h | 1 + 4 files changed, 91 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index 8796fc86b2e5..1637f7890f42 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -499,6 +499,7 @@ void skl_update_planes_on_crtc(struct intel_atomic_state *state, intel_atomic_get_new_crtc_state(state, crtc); struct skl_ddb_entry entries_y[I915_MAX_PLANES]; struct skl_ddb_entry entries_uv[I915_MAX_PLANES]; + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 update_mask = new_crtc_state->update_planes; struct intel_plane *plane; @@ -513,8 +514,10 @@ void skl_update_planes_on_crtc(struct intel_atomic_state *state, struct intel_plane_state *new_plane_state = intel_atomic_get_new_plane_state(state, plane); - if (new_plane_state->uapi.color_mgmt_changed) + if (new_plane_state->uapi.color_mgmt_changed) { intel_color_load_plane_luts(_plane_state->uapi); + dev_priv->display.load_plane_csc_matrix(_plane_state->uapi); + } if (new_plane_state->uapi.visible || new_plane_state->planar_slave) { diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index f5a9af858d1b..e9c80ed41466 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -2118,6 +2118,83 @@ static void icl_read_luts(struct intel_crtc_state *crtc_state) } } +static void icl_load_plane_csc_matrix(const struct drm_plane_state *state) +{ + struct drm_i915_private *dev_priv = to_i915(state->plane->dev); + enum pipe pipe = to_intel_plane(state->plane)->pipe; + enum plane_id plane = to_intel_plane(state->plane)->id; + struct drm_color_ctm *ctm; + const u64 *input; + u16 coeffs[9] = {}; + u16 postoff = 0; + int i; + + if (!icl_is_hdr_plane(dev_priv, plane) || !state->ctm) + return; + + ctm = state->ctm->data; + input = ctm->matrix; + + /* +* Convert fixed point S31.32 input to format supported by the +* hardware. +*/ + for (i = 0; i < ARRAY_SIZE(coeffs); i++) { + u64 abs_coeff = ((1ULL << 63) - 1) & input[i]; + + /* +* Clamp input value to min/max supported by +* hardware. +*/ + abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_4_0 - 1); + + /* sign bit */ + if (CTM_COEFF_NEGATIVE(input[i])) + coeffs[i] |= 1 << 15; + + if (abs_coeff < CTM_COEFF_0_125) + coeffs[i] |= (3 << 12) | + ILK_CSC_COEFF_FP(abs_coeff, 12); + else if (abs_coeff < CTM_COEFF_0_25) + coeffs[i] |= (2 << 12) | + ILK_CSC_COEFF_FP(abs_coeff, 11); + else if (abs_coeff < CTM_COEFF_0_5) + coeffs[i] |= (1 << 12) | + ILK_CSC_COEFF_FP(abs_coeff, 10); + else if (abs_coeff < CTM_COEFF_1_0) + coeffs[i] |= ILK_CSC_COEFF_FP(abs_coeff, 9); + else if (abs_coeff < CTM_COEFF_2_0) + coeffs[i] |= (7 << 12) | + ILK_CSC_COEFF_FP(abs_coeff, 8); + else + coeffs[i] |= (6 << 12) | + ILK_CSC_COEFF_FP(abs_coeff, 7); + } + + intel_de_write(dev_priv, PLANE_CSC_COEFF(pipe, plane, 0), + coeffs[0] << 16 | coeffs[1]); + intel_de_write(dev_priv, PLANE_CSC_COEFF(pipe, plane, 1), + coeffs[2] << 16); + + intel_de_write(dev_priv, PLANE_CSC_COEFF(pipe, plane, 2), + coeffs[3] << 16 | coeffs[4]); + intel_de_write(dev_priv, PLANE_CSC_COEFF(pipe, plane, 3), + coeffs[5] << 16); + + intel_de_write(dev_priv, PLANE_CSC_COEFF(pipe, plane, 4), + coeffs[6] << 16 | coeffs[7]); + intel_de_write(dev_priv, PLANE_CSC_COEFF(pipe, plane, 5), + coeffs[8] << 16); + + intel_de_write(dev_priv, PLANE_CSC_PREOFF(pipe, plane, 0), 0); + intel_de_w
[RFC v2 15/22] drm/i915/xelpd: Define Plane CSC Registers
Define Register macros for plane CSC. Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/i915_reg.h | 43 + 1 file changed, 43 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 0c36a330734f..20c1b8ddded8 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7440,6 +7440,49 @@ enum { #define PLANE_COLOR_CTL(pipe, plane) \ _MMIO_PLANE(plane, _PLANE_COLOR_CTL_1(pipe), _PLANE_COLOR_CTL_2(pipe)) +/* Plane CSC Registers */ +#define _PLANE_CSC_RY_GY_1_A 0x70210 +#define _PLANE_CSC_RY_GY_2_A 0x70310 + +#define _PLANE_CSC_RY_GY_1_B 0x71210 +#define _PLANE_CSC_RY_GY_2_B 0x71310 + +#define _PLANE_CSC_RY_GY_1(pipe) _PIPE(pipe, _PLANE_CSC_RY_GY_1_A, \ + _PLANE_CSC_RY_GY_1_B) +#define _PLANE_CSC_RY_GY_2(pipe) _PIPE(pipe, _PLANE_INPUT_CSC_RY_GY_2_A, \ + _PLANE_INPUT_CSC_RY_GY_2_B) +#define PLANE_CSC_COEFF(pipe, plane, index)_MMIO_PLANE(plane, \ + _PLANE_CSC_RY_GY_1(pipe) + (index) * 4, \ + _PLANE_CSC_RY_GY_2(pipe) + (index) * 4) + +#define _PLANE_CSC_PREOFF_HI_1_A 0x70228 +#define _PLANE_CSC_PREOFF_HI_2_A 0x70328 + +#define _PLANE_CSC_PREOFF_HI_1_B 0x71228 +#define _PLANE_CSC_PREOFF_HI_2_B 0x71328 + +#define _PLANE_CSC_PREOFF_HI_1(pipe) _PIPE(pipe, _PLANE_CSC_PREOFF_HI_1_A, \ + _PLANE_CSC_PREOFF_HI_1_B) +#define _PLANE_CSC_PREOFF_HI_2(pipe) _PIPE(pipe, _PLANE_CSC_PREOFF_HI_2_A, \ + _PLANE_CSC_PREOFF_HI_2_B) +#define PLANE_CSC_PREOFF(pipe, plane, index) _MMIO_PLANE(plane, _PLANE_CSC_PREOFF_HI_1(pipe) + \ + (index) * 4, _PLANE_CSC_PREOFF_HI_2(pipe) + \ + (index) * 4) + +#define _PLANE_CSC_POSTOFF_HI_1_A 0x70234 +#define _PLANE_CSC_POSTOFF_HI_2_A 0x70334 + +#define _PLANE_CSC_POSTOFF_HI_1_B 0x71234 +#define _PLANE_CSC_POSTOFF_HI_2_B 0x71334 + +#define _PLANE_CSC_POSTOFF_HI_1(pipe) _PIPE(pipe, _PLANE_CSC_POSTOFF_HI_1_A, \ + _PLANE_CSC_POSTOFF_HI_1_B) +#define _PLANE_CSC_POSTOFF_HI_2(pipe) _PIPE(pipe, _PLANE_CSC_POSTOFF_HI_2_A, \ + _PLANE_CSC_POSTOFF_HI_2_B) +#define PLANE_CSC_POSTOFF(pipe, plane, index) _MMIO_PLANE(plane, _PLANE_CSC_POSTOFF_HI_1(pipe) + \ + (index) * 4, _PLANE_CSC_POSTOFF_HI_2(pipe) + \ + (index) * 4) + #define _SEL_FETCH_PLANE_BASE_1_A 0x70890 #define _SEL_FETCH_PLANE_BASE_2_A 0x708B0 #define _SEL_FETCH_PLANE_BASE_3_A 0x708D0 -- 2.26.2
[RFC v2 14/22] drm: Add helper to attach Plane ctm property
Add a DRM helper to attach ctm property. Signed-off-by: Uma Shankar --- drivers/gpu/drm/drm_color_mgmt.c | 10 ++ include/drm/drm_plane.h | 1 + 2 files changed, 11 insertions(+) diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index 83832adf3adf..5c3138497b9c 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -654,6 +654,16 @@ void drm_plane_attach_degamma_properties(struct drm_plane *plane) } EXPORT_SYMBOL(drm_plane_attach_degamma_properties); +void drm_plane_attach_ctm_property(struct drm_plane *plane) +{ + if (!plane->ctm_property) + return; + + drm_object_attach_property(>base, + plane->ctm_property, 0); +} +EXPORT_SYMBOL(drm_plane_attach_ctm_property); + int drm_plane_color_add_gamma_degamma_mode_range(struct drm_plane *plane, const char *name, const struct drm_color_lut_range *ranges, diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index c4ed1799ecaf..3d329f71d287 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -889,6 +889,7 @@ int drm_plane_create_color_mgmt_properties(struct drm_device *dev, struct drm_plane *plane, int num_values); void drm_plane_attach_degamma_properties(struct drm_plane *plane); +void drm_plane_attach_ctm_property(struct drm_plane *plane); int drm_plane_color_add_gamma_degamma_mode_range(struct drm_plane *plane, const char *name, const struct drm_color_lut_range *ranges, -- 2.26.2
[RFC v2 13/22] drm: Add Plane CTM property
Add a blob property for plane CSC usage. Signed-off-by: Uma Shankar --- drivers/gpu/drm/drm_atomic_state_helper.c | 3 +++ drivers/gpu/drm/drm_atomic_uapi.c | 10 ++ drivers/gpu/drm/drm_color_mgmt.c | 11 +++ include/drm/drm_plane.h | 15 +++ 4 files changed, 39 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c index 6e358067cb7a..fafb8af1c9cb 100644 --- a/drivers/gpu/drm/drm_atomic_state_helper.c +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -314,6 +314,8 @@ void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane, if (state->degamma_lut) drm_property_blob_get(state->degamma_lut); + if (state->ctm) + drm_property_blob_get(state->ctm); state->color_mgmt_changed = false; } @@ -363,6 +365,7 @@ void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state) drm_property_blob_put(state->fb_damage_clips); drm_property_blob_put(state->degamma_lut); + drm_property_blob_put(state->ctm); } EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state); diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 904291b96ba9..e736fd7c1d5b 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -605,6 +605,14 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane, ); state->color_mgmt_changed |= replaced; return ret; + } else if (property == plane->ctm_property) { + ret = drm_atomic_replace_property_blob_from_id(dev, + >ctm, + val, + sizeof(struct drm_color_ctm), -1, + ); + state->color_mgmt_changed |= replaced; + return ret; } else if (property == config->prop_fb_damage_clips) { ret = drm_atomic_replace_property_blob_from_id(dev, >fb_damage_clips, @@ -676,6 +684,8 @@ drm_atomic_plane_get_property(struct drm_plane *plane, } else if (property == plane->degamma_lut_property) { *val = (state->degamma_lut) ? state->degamma_lut->base.id : 0; + } else if (property == plane->ctm_property) { + *val = (state->ctm) ? state->ctm->base.id : 0; } else if (property == config->prop_fb_damage_clips) { *val = (state->fb_damage_clips) ? state->fb_damage_clips->base.id : 0; diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index 29d0fc1e52b5..83832adf3adf 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -602,6 +602,10 @@ EXPORT_SYMBOL(drm_plane_create_color_properties); * engine, thereby making the content as linear for further color * processing. * + * ctm_property: + * Blob property which allows a userspace to provide CTM coefficients + * to do color space conversion or any other enhancement by doing a + * matrix multiplication using the h/w CTM processing engine */ int drm_plane_create_color_mgmt_properties(struct drm_device *dev, struct drm_plane *plane, @@ -623,6 +627,13 @@ int drm_plane_create_color_mgmt_properties(struct drm_device *dev, plane->degamma_lut_property = prop; + prop = drm_property_create(dev, DRM_MODE_PROP_BLOB, + "PLANE_CTM", 0); + if (!prop) + return -ENOMEM; + + plane->ctm_property = prop; + return 0; } EXPORT_SYMBOL(drm_plane_create_color_mgmt_properties); diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index fbfada0b990d..c4ed1799ecaf 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -255,6 +255,14 @@ struct drm_plane_state { */ struct drm_property_blob *degamma_lut; + /** +* @ctm: +* +* Color transformation matrix. See drm_plane_enable_color_mgmt(). The +* blob (if not NULL) is a drm_color_ctm. +*/ + struct drm_property_blob *ctm; + u8 color_mgmt_changed : 1; }; @@ -779,6 +787,13 @@ struct drm_plane { * used to convert the framebuffer's colors to linear gamma. */ struct drm_property *degamma_lut_property; + + /** +* @plane_ctm_property: Optional Plane property to set the +* matrix used to convert colors after the lookup in the +* degamma LUT. +*/ + struct drm_property *ctm_property; }; #define obj_to_plane(x) container_of(x, struct drm_plane, base) -- 2.26.2
[RFC v2 12/22] drm/i915/xelpd: Load plane color luts from atomic flip
Load plane color luts as part of atomic plane updates. This will be done only if the plane color luts are changed. Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_atomic_plane.c | 3 +++ drivers/gpu/drm/i915/display/intel_atomic_plane.h | 1 + drivers/gpu/drm/i915/display/intel_color.c| 9 + 3 files changed, 13 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index 47234d898549..8796fc86b2e5 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -513,6 +513,9 @@ void skl_update_planes_on_crtc(struct intel_atomic_state *state, struct intel_plane_state *new_plane_state = intel_atomic_get_new_plane_state(state, plane); + if (new_plane_state->uapi.color_mgmt_changed) + intel_color_load_plane_luts(_plane_state->uapi); + if (new_plane_state->uapi.visible || new_plane_state->planar_slave) { intel_update_plane(plane, new_crtc_state, new_plane_state); diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.h b/drivers/gpu/drm/i915/display/intel_atomic_plane.h index 854f37b49681..3001f4d69b4d 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.h +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.h @@ -65,5 +65,6 @@ void intel_plane_set_invisible(struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state); void intel_plane_helper_add(struct intel_plane *plane); int intel_plane_color_init(struct drm_plane *plane); +void intel_color_load_plane_luts(const struct drm_plane_state *plane_state); #endif /* __INTEL_ATOMIC_PLANE_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 62df5122309a..f5a9af858d1b 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -22,6 +22,7 @@ * */ +#include "intel_atomic_plane.h" #include "intel_color.h" #include "intel_de.h" #include "intel_display_types.h" @@ -2310,6 +2311,14 @@ static void d13_plane_load_luts(const struct drm_plane_state *plane_state) } } +void intel_color_load_plane_luts(const struct drm_plane_state *plane_state) +{ + struct drm_device *dev = plane_state->plane->dev; + struct drm_i915_private *dev_priv = to_i915(dev); + + dev_priv->display.load_plane_luts(plane_state); +} + int intel_plane_color_init(struct drm_plane *plane) { struct drm_i915_private *dev_priv = to_i915(plane->dev); -- 2.26.2
[RFC v2 11/22] drm/i915/xelpd: Initialize plane color features
Initialize plane color features for XE_LPD. Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_atomic_plane.h | 1 + drivers/gpu/drm/i915/display/skl_universal_plane.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.h b/drivers/gpu/drm/i915/display/intel_atomic_plane.h index 62e5a2a77fd4..854f37b49681 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.h +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.h @@ -64,5 +64,6 @@ int intel_atomic_plane_check_clipping(struct intel_plane_state *plane_state, void intel_plane_set_invisible(struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state); void intel_plane_helper_add(struct intel_plane *plane); +int intel_plane_color_init(struct drm_plane *plane); #endif /* __INTEL_ATOMIC_PLANE_H__ */ diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 4187a670e840..c4e01ae4343c 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -2184,6 +2184,8 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, BIT(DRM_SCALING_FILTER_DEFAULT) | BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR)); + intel_plane_color_init(>base); + intel_plane_helper_add(plane); return plane; -- 2.26.2
[RFC v2 10/22] drm/i915/xelpd: Add plane color check to glk_plane_color_ctl
Extended glk_plane_color_ctl to have plane color checks. This helps enabling the degamma or gamma block based on user inputs. Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/skl_universal_plane.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 724e7b04f3b6..4187a670e840 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -960,6 +960,11 @@ static u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state, u32 plane_color_ctl = 0; plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE; + + /* FIXME needs hw.degamma_lut */ + if (plane_state->uapi.degamma_lut) + plane_color_ctl |= PLANE_PRE_CSC_GAMMA_ENABLE; + plane_color_ctl |= glk_plane_color_ctl_alpha(plane_state); if (fb->format->is_yuv && !icl_is_hdr_plane(dev_priv, plane->id)) { -- 2.26.2
[RFC v2 09/22] drm/i915/xelpd: Program Plane Degamma Registers
Extract the LUT and program plane degamma registers. Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 116 + drivers/gpu/drm/i915/i915_reg.h| 2 + 2 files changed, 118 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index fd0bfdf85703..62df5122309a 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -126,6 +126,29 @@ static bool crtc_state_is_legacy_gamma(const struct intel_crtc_state *crtc_state lut_is_legacy(crtc_state->hw.gamma_lut); } +/* + * Added to accommodate enhanced LUT precision. + * Max LUT precision is 32 bits. + */ +static u64 drm_color_lut_extract_ext(u64 user_input, u32 bit_precision) +{ + u64 val = user_input & 0x; + u32 max; + + if (bit_precision > 32) + return 0; + + max = 0x >> (32 - bit_precision); + /* Round only if we're not using full precision. */ + if (bit_precision < 32) { + val += 1UL << (32 - bit_precision - 1); + val >>= 32 - bit_precision; + } + + return ((user_input & 0x) | + clamp_val(val, 0, max)); +} + /* * When using limited range, multiply the matrix given by userspace by * the matrix that we would use for the limited range. @@ -2196,6 +2219,97 @@ static const struct drm_color_lut_range d13_degamma_sdr[] = { }, }; +static void d13_program_plane_degamma_lut(const struct drm_plane_state *state, + struct drm_color_lut_ext *degamma_lut, + u32 offset) +{ + struct drm_i915_private *dev_priv = to_i915(state->plane->dev); + enum pipe pipe = to_intel_plane(state->plane)->pipe; + enum plane_id plane = to_intel_plane(state->plane)->id; + u32 i, lut_size; + + if (icl_is_hdr_plane(dev_priv, plane)) { + lut_size = 128; + + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_INDEX_ENH(pipe, plane, 0), + PLANE_PAL_PREC_AUTO_INCREMENT); + + if (degamma_lut) { + for (i = 0; i < lut_size; i++) { + u64 word = drm_color_lut_extract_ext(degamma_lut[i].green, 24); + u32 lut_val = (word & 0xff); + + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0), + lut_val); + } + + /* Program the max register to clamp values > 1.0. */ + while (i < 131) + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0), + degamma_lut[i++].green); + } else { + for (i = 0; i < lut_size; i++) { + u32 v = (i * ((1 << 24) - 1)) / (lut_size - 1); + + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0), v); + } + + do { + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0), + 1 << 24); + } while (i++ < 130); + } + + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_INDEX_ENH(pipe, plane, 0), 0); + } else { + lut_size = 32; + + /* +* First 3 planes are HDR, so reduce by 3 to get to the right +* SDR plane offset +*/ + plane = plane - 3; + + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_INDEX(pipe, plane, 0), + PLANE_PAL_PREC_AUTO_INCREMENT); + + if (degamma_lut) { + for (i = 0; i < lut_size; i++) + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_DATA(pipe, plane, 0), + degamma_lut[i].green); + /* Program the max register to clamp values > 1.0. */ + while (i < 35) + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_DATA(pipe, plane, 0), + degamma_lut[i++].green); + } else { + for (i = 0; i < lut_size; i++) { + u32 v = (i * ((1 << 16) - 1)) / (lut_size - 1); + + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_DATA(pipe, plane, 0), v); + } + + do { + intel_de_writ
[RFC v2 07/22] drm/i915/xelpd: Enable plane color features
Enable and initialize plane color features. Also initialize the color features of HDR planes. Signed-off-by: Uma Shankar Signed-off-by: Bhanuprakash Modem --- drivers/gpu/drm/i915/display/intel_color.c | 22 +- drivers/gpu/drm/i915/display/intel_color.h | 2 ++ drivers/gpu/drm/i915/i915_drv.h| 3 +++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 6403bd74324b..2307a2e4d73d 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -25,6 +25,7 @@ #include "intel_color.h" #include "intel_de.h" #include "intel_display_types.h" +#include #define CTM_COEFF_SIGN (1ULL << 63) @@ -2093,7 +2094,6 @@ static void icl_read_luts(struct intel_crtc_state *crtc_state) } /* FIXME input bpc? */ -__maybe_unused static const struct drm_color_lut_range d13_degamma_hdr[] = { /* segment 1 */ { @@ -2144,6 +2144,26 @@ static const struct drm_color_lut_range d13_degamma_hdr[] = { }, }; +int intel_plane_color_init(struct drm_plane *plane) +{ + struct drm_i915_private *dev_priv = to_i915(plane->dev); + int ret = 0; + + if (DISPLAY_VER(dev_priv) >= 13) { + drm_plane_create_color_mgmt_properties(plane->dev, plane, 2); + ret = drm_plane_color_add_gamma_degamma_mode_range(plane, "no degamma", + NULL, 0, + LUT_TYPE_DEGAMMA); + ret = drm_plane_color_add_gamma_degamma_mode_range(plane, "plane degamma", + d13_degamma_hdr, + sizeof(d13_degamma_hdr), + LUT_TYPE_DEGAMMA); + drm_plane_attach_degamma_properties(plane); + } + + return ret; +} + void intel_color_init(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); diff --git a/drivers/gpu/drm/i915/display/intel_color.h b/drivers/gpu/drm/i915/display/intel_color.h index 173727aaa24d..b8850bb1b0c9 100644 --- a/drivers/gpu/drm/i915/display/intel_color.h +++ b/drivers/gpu/drm/i915/display/intel_color.h @@ -10,6 +10,7 @@ struct intel_crtc_state; struct intel_crtc; +struct drm_plane; struct drm_property_blob; void intel_color_init(struct intel_crtc *crtc); @@ -21,5 +22,6 @@ int intel_color_get_gamma_bit_precision(const struct intel_crtc_state *crtc_stat bool intel_color_lut_equal(struct drm_property_blob *blob1, struct drm_property_blob *blob2, u32 gamma_mode, u32 bit_precision); +int intel_plane_color_init(struct drm_plane *plane); #endif /* __INTEL_COLOR_H__ */ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index be2392bbcecc..a937a20e4c49 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -391,6 +391,9 @@ struct drm_i915_display_funcs { */ void (*load_luts)(const struct intel_crtc_state *crtc_state); void (*read_luts)(struct intel_crtc_state *crtc_state); + /* Add Plane Color callbacks */ + void (*load_plane_csc_matrix)(const struct drm_plane_state *plane_state); + void (*load_plane_luts)(const struct drm_plane_state *plane_state); }; -- 2.26.2
[RFC v2 08/22] drm/i915/xelpd: Add color capabilities of SDR planes
Add the Color capabilities of SDR planes. Signed-off-by: Uma Shankar Signed-off-by: Bhanuprakash Modem --- drivers/gpu/drm/i915/display/intel_color.c | 67 -- 1 file changed, 63 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 2307a2e4d73d..fd0bfdf85703 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -25,6 +25,7 @@ #include "intel_color.h" #include "intel_de.h" #include "intel_display_types.h" +#include "intel_sprite.h" #include #define CTM_COEFF_SIGN (1ULL << 63) @@ -2144,6 +2145,57 @@ static const struct drm_color_lut_range d13_degamma_hdr[] = { }, }; + /* FIXME input bpc? */ +static const struct drm_color_lut_range d13_degamma_sdr[] = { + /* segment 1 */ + { + .flags = (DRM_MODE_LUT_GAMMA | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_NON_DECREASING), + .count = 32, + .input_bpc = 16, .output_bpc = 16, + .start = 0, .end = (1 << 16) - (1 << 16) / 33, + .min = 0, .max = (1 << 16) - 1, + }, + /* segment 2 */ + { + .flags = (DRM_MODE_LUT_GAMMA | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 16, .output_bpc = 16, + .start = (1 << 16) - (1 << 16) / 33, .end = 1 << 16, + .min = 0, .max = 1 << 16, + }, + /* Segment 3 */ + { + .flags = (DRM_MODE_LUT_GAMMA | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 16, .output_bpc = 16, + .start = 1 << 16, .end = 3 << 16, + .min = 0, .max = (8 << 16) - 1, + }, + /* Segment 4 */ + { + .flags = (DRM_MODE_LUT_GAMMA | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 16, .output_bpc = 16, + .start = 3 << 16, .end = 7 << 16, + .min = 0, .max = (8 << 16) - 1, + }, +}; + int intel_plane_color_init(struct drm_plane *plane) { struct drm_i915_private *dev_priv = to_i915(plane->dev); @@ -2154,10 +2206,17 @@ int intel_plane_color_init(struct drm_plane *plane) ret = drm_plane_color_add_gamma_degamma_mode_range(plane, "no degamma", NULL, 0, LUT_TYPE_DEGAMMA); - ret = drm_plane_color_add_gamma_degamma_mode_range(plane, "plane degamma", - d13_degamma_hdr, - sizeof(d13_degamma_hdr), - LUT_TYPE_DEGAMMA); + if (icl_is_hdr_plane(dev_priv, to_intel_plane(plane)->id)) + ret = drm_plane_color_add_gamma_degamma_mode_range(plane, "plane degamma", + d13_degamma_hdr, + sizeof(d13_degamma_hdr), + LUT_TYPE_DEGAMMA); + else + ret = drm_plane_color_add_gamma_degamma_mode_range(plane, + "plane degamma", + d13_degamma_sdr, + sizeof(d13_degamma_sdr), + LUT_TYPE_DEGAMMA); drm_plane_attach_degamma_properties(plane); } -- 2.26.2
[RFC v2 05/22] drm/i915/xelpd: Define Degamma Lut range struct for HDR planes
Define the structure with XE_LPD degamma lut ranges. HDR and SDR planes have different capabilities, implemented respective structure for the HDR planes. Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 52 ++ 1 file changed, 52 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index afcb4bf3826c..6403bd74324b 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -2092,6 +2092,58 @@ static void icl_read_luts(struct intel_crtc_state *crtc_state) } } + /* FIXME input bpc? */ +__maybe_unused +static const struct drm_color_lut_range d13_degamma_hdr[] = { + /* segment 1 */ + { + .flags = (DRM_MODE_LUT_GAMMA | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_NON_DECREASING), + .count = 128, + .input_bpc = 24, .output_bpc = 16, + .start = 0, .end = (1 << 24) - 1, + .min = 0, .max = (1 << 24) - 1, + }, + /* segment 2 */ + { + .flags = (DRM_MODE_LUT_GAMMA | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 24, .output_bpc = 16, + .start = (1 << 24) - 1, .end = 1 << 24, + .min = 0, .max = (1 << 27) - 1, + }, + /* Segment 3 */ + { + .flags = (DRM_MODE_LUT_GAMMA | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 24, .output_bpc = 16, + .start = 1 << 24, .end = 3 << 24, + .min = 0, .max = (1 << 27) - 1, + }, + /* Segment 4 */ + { + .flags = (DRM_MODE_LUT_GAMMA | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 24, .output_bpc = 16, + .start = 3 << 24, .end = 7 << 24, + .min = 0, .max = (1 << 27) - 1, + }, +}; + void intel_color_init(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); -- 2.26.2
[RFC v2 06/22] drm/i915/xelpd: Add register definitions for Plane Degamma
Add macros to define Plane Degamma registers Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/i915_reg.h | 52 + 1 file changed, 52 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 313432ed6196..919982c878ac 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -262,6 +262,9 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) INTEL_INFO(dev_priv)->cursor_offsets[PIPE_A] + (reg) + \ DISPLAY_MMIO_BASE(dev_priv)) +/* Plane Gamma Registers */ +#define _MMIO_PLANE_GAMC(plane, i, a, b) _MMIO(_PIPE(plane, a, b) + (i) * 4) + #define __MASKED_FIELD(mask, value) ((mask) << 16 | (value)) #define _MASKED_FIELD(mask, value) ({ \ if (__builtin_constant_p(mask))\ @@ -11366,6 +11369,55 @@ enum skl_power_gate { _PAL_PREC_MULTI_SEG_DATA_A, \ _PAL_PREC_MULTI_SEG_DATA_B) +/* Display13 Plane Degmma Reg */ +#define _PLANE_PRE_CSC_GAMC_INDEX_ENH_1_A 0x701d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_ENH_1_B 0x711d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_ENH_2_A 0x702d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_ENH_2_B 0x712d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_ENH_1(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_INDEX_ENH_1_A, \ + _PLANE_PRE_CSC_GAMC_INDEX_ENH_1_B) +#define _PLANE_PRE_CSC_GAMC_INDEX_ENH_2(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_INDEX_ENH_2_A, \ + _PLANE_PRE_CSC_GAMC_INDEX_ENH_2_B) +#define PLANE_PRE_CSC_GAMC_INDEX_ENH(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_PRE_CSC_GAMC_INDEX_ENH_1(pipe), \ + _PLANE_PRE_CSC_GAMC_INDEX_ENH_2(pipe)) + +#define _PLANE_PRE_CSC_GAMC_DATA_ENH_1_A 0x701d4 +#define _PLANE_PRE_CSC_GAMC_DATA_ENH_1_B 0x711d4 +#define _PLANE_PRE_CSC_GAMC_DATA_ENH_2_A 0x702d4 +#define _PLANE_PRE_CSC_GAMC_DATA_ENH_2_B 0x712d4 +#define _PLANE_PRE_CSC_GAMC_DATA_ENH_1(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_DATA_ENH_1_A, \ + _PLANE_PRE_CSC_GAMC_DATA_ENH_1_B) +#define _PLANE_PRE_CSC_GAMC_DATA_ENH_2(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_DATA_ENH_2_A, \ + _PLANE_PRE_CSC_GAMC_DATA_ENH_2_B) +#define PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, i)\ + _MMIO_PLANE_GAMC(plane, i, _PLANE_PRE_CSC_GAMC_DATA_ENH_1(pipe), \ + _PLANE_PRE_CSC_GAMC_DATA_ENH_2(pipe)) + +#define _PLANE_PRE_CSC_GAMC_INDEX_1_A 0x704d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_1_B 0x714d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_2_A 0x705d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_2_B 0x715d0 +#define _PLANE_PRE_CSC_GAMC_INDEX_1(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_INDEX_1_A, \ + _PLANE_PRE_CSC_GAMC_INDEX_1_B) +#define _PLANE_PRE_CSC_GAMC_INDEX_2(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_INDEX_2_A, \ + _PLANE_PRE_CSC_GAMC_INDEX_2_B) +#define PLANE_PRE_CSC_GAMC_INDEX(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_PRE_CSC_GAMC_INDEX_1(pipe), \ + _PLANE_PRE_CSC_GAMC_INDEX_2(pipe)) + +#define _PLANE_PRE_CSC_GAMC_DATA_1_A 0x704d4 +#define _PLANE_PRE_CSC_GAMC_DATA_1_B 0x714d4 +#define _PLANE_PRE_CSC_GAMC_DATA_2_A 0x705d4 +#define _PLANE_PRE_CSC_GAMC_DATA_2_B 0x715d4 +#define _PLANE_PRE_CSC_GAMC_DATA_1(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_DATA_1_A, \ + _PLANE_PRE_CSC_GAMC_DATA_1_B) +#define _PLANE_PRE_CSC_GAMC_DATA_2(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_DATA_2_A, \ + _PLANE_PRE_CSC_GAMC_DATA_2_B) +#define PLANE_PRE_CSC_GAMC_DATA(pipe, plane, i)\ + _MMIO_PLANE_GAMC(plane, i, _PLANE_PRE_CSC_GAMC_DATA_1(pipe), \ + _PLANE_PRE_CSC_GAMC_DATA_2(pipe)) + /* pipe CSC & degamma/gamma LUTs on CHV */ #define _CGM_PIPE_A_CSC_COEFF01(VLV_DISPLAY_BASE + 0x67900) #define _CGM_PIPE_A_CSC_COEFF23(VLV_DISPLAY_BASE + 0x67904) -- 2.26.2
[RFC v2 04/22] drm: Add Plane Degamma Lut property
Add Plane Degamma Lut as a blob property. User will calculate the lut values, create the blob and send it to driver using this property. Lut calculation will be based on the gamma mode chosen out of the gamma mode exposed. Signed-off-by: Uma Shankar --- drivers/gpu/drm/drm_atomic_state_helper.c | 4 drivers/gpu/drm/drm_atomic_uapi.c | 10 ++ drivers/gpu/drm/drm_color_mgmt.c | 19 +++ include/drm/drm_plane.h | 14 ++ 4 files changed, 47 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c index f26b03853711..6e358067cb7a 100644 --- a/drivers/gpu/drm/drm_atomic_state_helper.c +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -312,6 +312,9 @@ void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane, state->commit = NULL; state->fb_damage_clips = NULL; + if (state->degamma_lut) + drm_property_blob_get(state->degamma_lut); + state->color_mgmt_changed = false; } EXPORT_SYMBOL(__drm_atomic_helper_plane_duplicate_state); @@ -359,6 +362,7 @@ void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state) drm_crtc_commit_put(state->commit); drm_property_blob_put(state->fb_damage_clips); + drm_property_blob_put(state->degamma_lut); } EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state); diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 3c952123f747..904291b96ba9 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -598,6 +598,13 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane, state->color_range = val; } else if (property == plane->degamma_mode_property) { state->degamma_mode = val; + } else if (property == plane->degamma_lut_property) { + ret = drm_atomic_replace_property_blob_from_id(dev, + >degamma_lut, + val, -1, sizeof(struct drm_color_lut_ext), + ); + state->color_mgmt_changed |= replaced; + return ret; } else if (property == config->prop_fb_damage_clips) { ret = drm_atomic_replace_property_blob_from_id(dev, >fb_damage_clips, @@ -666,6 +673,9 @@ drm_atomic_plane_get_property(struct drm_plane *plane, *val = state->color_range; } else if (property == plane->degamma_mode_property) { *val = state->degamma_mode; + } else if (property == plane->degamma_lut_property) { + *val = (state->degamma_lut) ? + state->degamma_lut->base.id : 0; } else if (property == config->prop_fb_damage_clips) { *val = (state->fb_damage_clips) ? state->fb_damage_clips->base.id : 0; diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index 085ed0d0db00..29d0fc1e52b5 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -596,6 +596,12 @@ EXPORT_SYMBOL(drm_plane_create_color_properties); * to query and get the plane degamma color caps and choose the * appropriate degamma mode and create lut values accordingly * + * degamma_lut_property: + * Blob property which allows a userspace to provide LUT values + * to apply degamma curve using the h/w plane degamma processing + * engine, thereby making the content as linear for further color + * processing. + * */ int drm_plane_create_color_mgmt_properties(struct drm_device *dev, struct drm_plane *plane, @@ -610,6 +616,13 @@ int drm_plane_create_color_mgmt_properties(struct drm_device *dev, plane->degamma_mode_property = prop; + prop = drm_property_create(dev, DRM_MODE_PROP_BLOB, + "PLANE_DEGAMMA_LUT", 0); + if (!prop) + return -ENOMEM; + + plane->degamma_lut_property = prop; + return 0; } EXPORT_SYMBOL(drm_plane_create_color_mgmt_properties); @@ -621,6 +634,12 @@ void drm_plane_attach_degamma_properties(struct drm_plane *plane) drm_object_attach_property(>base, plane->degamma_mode_property, 0); + + if (!plane->degamma_lut_property) + return; + + drm_object_attach_property(>base, + plane->degamma_lut_property, 0); } EXPORT_SYMBOL(drm_plane_attach_degamma_properties); diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index b9064101db2b..fbfada0b990d 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane
[RFC v2 03/22] drm: Add Plane Degamma Mode property
Add Plane Degamma Mode as an enum property. Create a helper function for all plane color management features. This is an enum property with values as blob_id's and exposes the various gamma modes supported and the lut ranges. Getting the blob id in userspace, user can get the mode supported and also the range of gamma mode supported with number of lut coefficients. It can then set one of the modes using this enum property. Lut values will be sent through separate GAMMA_LUT blob property. Signed-off-by: Uma Shankar --- Documentation/gpu/drm-kms.rst | 90 ++ drivers/gpu/drm/drm_atomic.c | 1 + drivers/gpu/drm/drm_atomic_state_helper.c | 2 + drivers/gpu/drm/drm_atomic_uapi.c | 4 + drivers/gpu/drm/drm_color_mgmt.c | 93 ++- include/drm/drm_mode_object.h | 2 +- include/drm/drm_plane.h | 23 ++ 7 files changed, 212 insertions(+), 3 deletions(-) diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst index 1ef7951ded5e..f4658417bf20 100644 --- a/Documentation/gpu/drm-kms.rst +++ b/Documentation/gpu/drm-kms.rst @@ -545,9 +545,99 @@ Damage Tracking Properties Color Management Properties --- +Below is how a typical hardware pipeline for color +will look like: + +.. kernel-render:: DOT + :alt: Display Color Pipeline + :caption: Display Color Pipeline Overview + + digraph "KMS" { + node [shape=box] + + subgraph cluster_static { + style=dashed + label="Display Color Hardware Blocks" + + node [bgcolor=grey style=filled] + "Plane Degamma A" -> "Plane CSC/CTM A" + "Plane CSC/CTM A" -> "Plane Gamma A" + "Pipe Blender" [color=lightblue,style=filled, width=5.25, height=0.75]; + "Plane Gamma A" -> "Pipe Blender" + "Pipe Blender" -> "Pipe DeGamma" + "Pipe DeGamma" -> "Pipe CSC/CTM" + "Pipe CSC/CTM" -> "Pipe Gamma" + "Pipe Gamma" -> "Pipe Output" + } + + subgraph cluster_static { + style=dashed + + node [shape=box] + "Plane Degamma B" -> "Plane CSC/CTM B" + "Plane CSC/CTM B" -> "Plane Gamma B" + "Plane Gamma B" -> "Pipe Blender" + } + + subgraph cluster_static { + style=dashed + + node [shape=box] + "Plane Degamma C" -> "Plane CSC/CTM C" + "Plane CSC/CTM C" -> "Plane Gamma C" + "Plane Gamma C" -> "Pipe Blender" + } + + subgraph cluster_fb { + style=dashed + label="RAM" + + node [shape=box width=1.7 height=0.2] + + "FB 1" -> "Plane Degamma A" + "FB 2" -> "Plane Degamma B" + "FB 3" -> "Plane Degamma C" + } + } + +In real world usecases, + +1. Plane Degamma can be used to linearize a non linear gamma +encoded framebuffer. This is needed to do any linear math like +color space conversion. For ex, linearize frames encoded in SRGB +or by HDR curve. + +2. Later Plane CTM block can convert the content to some different +colorspace. For ex, SRGB to BT2020 etc. + +3. Plane Gamma block can be used later to re-apply the non-linear +curve. This can also be used to apply Tone Mapping for HDR usecases. + +All the layers or framebuffers need to be converted to same color +space and format before blending. The plane color hardware blocks +can help with this. Once the Data is blended, similar color processing +can be done on blended output using pipe color hardware blocks. + +DRM Properties have been created to define and expose all these +hardware blocks to userspace. A userspace application (compositor +or any color app) can use these interfaces and define policies to +efficiently use the display hardware for such color operations. + +Pipe Color Management Properties +- + .. kernel-doc:: drivers/gpu/drm/drm_color_mgmt.c :doc: overview +Plane Color Management Properties +- + +.. kernel-doc:: drivers/gpu/drm/drm_color_mgmt.c + :doc: Plane Color Properties + +.. kernel-doc:: drivers/gpu/drm/drm_color_mgmt.c + :doc: export + Tile Group Property --- diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index ff1416cd609a..fddf9df15cd5 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -709,6 +709,7 @@ static void drm_atomic_plane_print_state(struct drm_printer *p, drm_get_color_encoding_name(state->color_encoding));
[RFC v2 02/22] drm: Add Enhanced Gamma and color lut range attributes
Existing LUT precision structure is having only 16 bit precision. This is not enough for upcoming enhanced hardwares and advance usecases like HDR processing. Hence added a new structure with 32 bit precision values. This also defines a new structure to define color lut ranges, along with related macro definitions and enums. This will help describe multi segmented lut ranges in the hardware. Signed-off-by: Uma Shankar --- include/uapi/drm/drm_mode.h | 58 + 1 file changed, 58 insertions(+) diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 90c55383f1ee..1079794c86c3 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -903,6 +903,64 @@ struct hdr_output_metadata { }; }; +/* + * DRM_MODE_LUT_GAMMA|DRM_MODE_LUT_DEGAMMA is legal and means the LUT + * can be used for either purpose, but not simultaneously. To expose + * modes that support gamma and degamma simultaneously the gamma mode + * must declare distinct DRM_MODE_LUT_GAMMA and DRM_MODE_LUT_DEGAMMA + * ranges. + */ +/* LUT is for gamma (after CTM) */ +#define DRM_MODE_LUT_GAMMA BIT(0) +/* LUT is for degamma (before CTM) */ +#define DRM_MODE_LUT_DEGAMMA BIT(1) +/* linearly interpolate between the points */ +#define DRM_MODE_LUT_INTERPOLATE BIT(2) +/* + * the last value of the previous range is the + * first value of the current range. + */ +#define DRM_MODE_LUT_REUSE_LAST BIT(3) +/* the curve must be non-decreasing */ +#define DRM_MODE_LUT_NON_DECREASING BIT(4) +/* the curve is reflected across origin for negative inputs */ +#define DRM_MODE_LUT_REFLECT_NEGATIVE BIT(5) +/* the same curve (red) is used for blue and green channels as well */ +#define DRM_MODE_LUT_SINGLE_CHANNEL BIT(6) + +struct drm_color_lut_range { + /* DRM_MODE_LUT_* */ + __u32 flags; + /* number of points on the curve */ + __u16 count; + /* input/output bits per component */ + __u8 input_bpc, output_bpc; + /* input start/end values */ + __s32 start, end; + /* output min/max values */ + __s32 min, max; +}; + +enum lut_type { + LUT_TYPE_DEGAMMA = 0, + LUT_TYPE_GAMMA = 1, +}; + +/* + * Creating 64 bit palette entries for better data + * precision. This will be required for HDR and + * similar color processing usecases. + */ +struct drm_color_lut_ext { + /* +* Data is U32.32 fixed point format. +*/ + __u64 red; + __u64 green; + __u64 blue; + __u64 reserved; +}; + #define DRM_MODE_PAGE_FLIP_EVENT 0x01 #define DRM_MODE_PAGE_FLIP_ASYNC 0x02 #define DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE 0x4 -- 2.26.2
[RFC v2 00/22] Add Support for Plane Color Lut and CSC features
This is how a typical display color hardware pipeline looks like: +---+ |RAM| | +--++-++-+ | | | FB 1 || FB 2 || FB N| | | +--++-++-+ | +---+ | Plane Color Hardware Block | ++ | +---v-+ +---v---+ +---v--+ | | | Plane A | | Plane B | | Plane N | | | | DeGamma | | Degamma | | Degamma | | | +---+-+ +---+---+ +---+--+ | | | | || | +---v-+ +---v---+ +---v--+ | | |Plane A | | Plane B | | Plane N | | | |CSC/CTM | | CSC/CTM | | CSC/CTM | | | +---+-+ ++--+ ++-+ | | | | | | | +---v-+ +v--+ +v-+ | | | Plane A | | Plane B | | Plane N | | | | Gamma | | Gamma | | Gamma| | | +---+-+ ++--+ ++-+ | | | | | | ++ +--v--v---v---| || || || Pipe Blender|| +++ ||| |+---v--+ | || Pipe DeGamma| | || | | |+---+--+ | ||Pipe Color | |+---v--+ Hardware| || Pipe CSC/CTM| | || | | |+---+--+ | ||| |+---v--+ | || Pipe Gamma | | || | | |+---+--+ | ||| +-+ | v Pipe Output This patch series adds properties for plane color features. It adds properties for degamma used to linearize data and CSC used for gamut conversion. It also includes Gamma support used to again non-linearize data as per panel supported color space. These can be utilize by user space to convert planes from one format to another, one color space to another etc. Userspace can take smart blending decisions and utilize these hardware supported plane color features to get accurate color profile. The same can help in consistent color quality from source to panel taking advantage of advanced color features in hardware. These patches add the property interfaces and enable helper functions. This series adds Intel's XE_LPD hw specific plane gamma feature. We can build up and add other platform/hardware specific implementation on top of this series. Credits: Special mention and credits to Ville Syrjala for coming up with a design for this feature and inputs. This series is based on his original design and idea. Note: Userspace support for this new UAPI will be done on Chrome in alignment with weston and general opensource community. Discussion ongoing with Harry Wentland, Pekka and community on color pipeline and UAPI design. Harry's RFC below: https://patchwork.freedesktop.org/series/89506/ We need to converge on a common UAPI interface which caters to all the modern color hardware pipelines. ToDo: State readout for this feature will be added next. v2: Added UAPI description and added change in the rfc section of kernel Documentation folder Uma Shankar (22): drm: RFC for Plane Color Hardware Pipeline drm: Add Enhanced Gamma and color lut range attributes drm: Add Plane Degamma Mode property drm: Add Plane Degamma Lut property drm/i915/xelpd: Define Degamma Lut range struct for HDR planes drm/i915/xelpd: Add register definitions for Plane Degamma drm/i915/xelpd: Enable plane color features drm/i915/xelpd: Add color capabilities of SDR planes drm/i915/xelpd: Program Plane Degamma Registers drm/i915/xelpd: Add plane color check to glk_plane_color_ctl drm/i915/xelpd: Initialize plane color features drm/i915/xelpd: Load plane color luts from atomic flip drm: Add Plane CTM property drm: Add helper to attach Plane ctm property drm/i915/xelpd: Define Plane CSC Registers drm/i915/xelpd: Enable Plane CSC drm: Add Plane Gamma Mode property drm: Add Plane Gamma Lut property drm/i915/xelpd: Define and Initialize Plane Gamma Lut range drm/i915/xelpd: Add register definitions for Plane Gamma drm/i915/xelpd: Program Plane Gamma Registers drm/i915/xelpd: Enable plane gamma Documentation/gpu/drm-kms.rst | 90
[RFC v2 01/22] drm: RFC for Plane Color Hardware Pipeline
This is a RFC proposal for plane color hardware blocks. It exposes the property interface to userspace and calls out the details or interfaces created and the intended purpose. Credits: Ville Syrjälä Signed-off-by: Uma Shankar --- Documentation/gpu/rfc/drm_color_pipeline.rst | 167 +++ 1 file changed, 167 insertions(+) create mode 100644 Documentation/gpu/rfc/drm_color_pipeline.rst diff --git a/Documentation/gpu/rfc/drm_color_pipeline.rst b/Documentation/gpu/rfc/drm_color_pipeline.rst new file mode 100644 index ..0d1ca858783b --- /dev/null +++ b/Documentation/gpu/rfc/drm_color_pipeline.rst @@ -0,0 +1,167 @@ +== +Display Color Pipeline: Proposed DRM Properties +== + +This is how a typical display color hardware pipeline looks like: + +---+ + |RAM| + | +--++-++-+ | + | | FB 1 || FB 2 || FB N| | + | +--++-++-+ | + +---+ + | Plane Color Hardware Block | + ++ + | +---v-+ +---v---+ +---v--+ | + | | Plane A | | Plane B | | Plane N | | + | | DeGamma | | Degamma | | Degamma | | + | +---+-+ +---+---+ +---+--+ | + | | | || + | +---v-+ +---v---+ +---v--+ | + | |Plane A | | Plane B | | Plane N | | + | |CSC/CTM | | CSC/CTM | | CSC/CTM | | + | +---+-+ ++--+ ++-+ | + | | | | | + | +---v-+ +v--+ +v-+ | + | | Plane A | | Plane B | | Plane N | | + | | Gamma | | Gamma | | Gamma| | + | +---+-+ ++--+ ++-+ | + | | | | | + ++ ++--v--v---v---| +|| || +|| Pipe Blender|| ++++ +||| +|+---v--+ | +|| Pipe DeGamma| | +|| | | +|+---+--+ | +||Pipe Color | +|+---v--+ Hardware| +|| Pipe CSC/CTM| | +|| | | +|+---+--+ | +||| +|+---v--+ | +|| Pipe Gamma | | +|| | | +|+---+--+ | +||| ++-+ + | + v + Pipe Output + +Proposal is to have below properties for a plane: + +* Plane Degamma or Pre-Curve: + * This will be used to linearize the input framebuffer data. + * It will apply the reverse of the color transfer function. + * It can be a degamma curve or OETF for HDR. + * This linear data can be further acted on by the following + * color hardware blocks in the display hardware pipeline + +UAPI Name: PLANE_DEGAMMA_MODE +Description: Enum property with values as blob_id's which advertizes the + possible degamma modes and lut ranges supported by the platform. + This allows userspace to query and get the plane degamma color + caps and choose the appropriate degamma mode and create lut values + accordingly. + +UAPI Name: PLANE_DEGAMMA_LUT +Description: Blob property which allows a userspace to provide LUT values +to apply degamma curve using the h/w plane degamma processing +engine, thereby making the content as linear for further color +processing. Userspace gets the size of LUT and precision etc +from PLANE_DEGAMA_MODE_PROPERTY + +* Plane CTM + * This is a Property to program the color transformation matrix. + * This can be used to perform a color space conversion like + * BT2020 to BT709 or BT601 etc. + * This block is generally kept after the degamma unit so that + * linear data can be fed to it for conversion. + +UAPI Name: PLANE_CTM +Description: Blob property which allows a userspace to provide CTM coefficients +to do color space conversion or any other enhancement by doing a +matrix multiplication using the h/w CTM processing engine + +* Plane Gamma or Post-Curve + * This can be used to perform 2 operations: + * non-lineralize
[PATCH 21/21] drm/i915/xelpd: Enable plane gamma
Enable plane gamma feature in check callbacks. Decide based on the user input. Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/skl_universal_plane.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 6ba670b6a5c9..5d527d12ec45 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -959,7 +959,9 @@ static u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state, struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); u32 plane_color_ctl = 0; - plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE; + /* FIXME needs hw.gamma_lut */ + if (!plane_state->uapi.gamma_lut) + plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE; /* FIXME needs hw.degamma_lut */ if (plane_state->uapi.degamma_lut) -- 2.26.2
[PATCH 20/21] drm/i915/xelpd: Program Plane Gamma Registers
Extract the LUT and program plane gamma registers. Enabled multi segmented lut as well. Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 89 ++ drivers/gpu/drm/i915/i915_reg.h| 9 ++- 2 files changed, 94 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 7f091dd0bb19..daf2148fb2df 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -27,6 +27,9 @@ #include "intel_de.h" #include "intel_display_types.h" #include "intel_sprite.h" + +#include "skl_universal_plane.h" + #include #define CTM_COEFF_SIGN (1ULL << 63) @@ -2434,16 +2437,102 @@ static void d13_program_plane_degamma_lut(const struct drm_plane_state *state, } } +static void d13_program_plane_gamma_lut(const struct drm_plane_state *state, + struct drm_color_lut_ext *gamma_lut, + u32 offset) +{ + struct drm_i915_private *dev_priv = to_i915(state->plane->dev); + enum pipe pipe = to_intel_plane(state->plane)->pipe; + enum plane_id plane = to_intel_plane(state->plane)->id; + u32 i, lut_size; + + if (icl_is_hdr_plane(dev_priv, plane)) { + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_INDEX_ENH(pipe, plane, 0), + offset | PLANE_PAL_PREC_AUTO_INCREMENT); + if (gamma_lut) { + lut_size = 32; + for (i = 0; i < lut_size; i++) { + u64 word = drm_color_lut_extract_ext(gamma_lut[i].green, 24); + u32 lut_val = (word & 0xff); + + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, 0), + lut_val); + } + + do { + /* Program the max register to clamp values > 1.0. */ + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, 0), + gamma_lut[i].green); + } while (i++ < 34); + } else { + lut_size = 32; + for (i = 0; i < lut_size; i++) { + u32 v = (i * ((1 << 24) - 1)) / (lut_size - 1); + + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, 0), v); + } + + do { + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, 0), + 1 << 24); + } while (i++ < 34); + } + + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_INDEX_ENH(pipe, plane, 0), 0); + } else { + lut_size = 32; + /* +* First 3 planes are HDR, so reduce by 3 to get to the right +* SDR plane offset +*/ + plane = plane - 3; + + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_INDEX(pipe, plane, 0), + offset | PLANE_PAL_PREC_AUTO_INCREMENT); + + if (gamma_lut) { + for (i = 0; i < lut_size; i++) + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_DATA(pipe, plane, 0), + gamma_lut[i].green & 0x); + /* Program the max register to clamp values > 1.0. */ + while (i < 35) + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_DATA(pipe, plane, 0), + gamma_lut[i++].green & 0x3); + } else { + for (i = 0; i < lut_size; i++) { + u32 v = (i * ((1 << 16) - 1)) / (lut_size - 1); + + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_DATA(pipe, plane, 0), v); + } + + do { + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_DATA(pipe, plane, 0), + (1 << 16)); + } while (i++ < 34); + } + + intel_de_write(dev_priv, PLANE_POST_CSC_GAMC_INDEX(pipe, plane, 0), 0); + } +} + static void d13_plane_load_luts(const struct drm_plane_state *plane_state) { const struct drm_property_blob *degamma_lut_blob = plane_state->degamma_lut; + const struct drm_property_blob *gamma_lut_blob =
[PATCH 19/21] drm/i915/xelpd: Add register definitions for Plane Gamma
Add macros to define Plane Gamma registers Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/i915_reg.h | 73 + 1 file changed, 73 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index a8e35357aea0..2ebc92104f64 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -11398,6 +11398,79 @@ enum skl_power_gate { _MMIO_PLANE_GAMC(plane, i, _PLANE_PRE_CSC_GAMC_DATA_1(pipe), \ _PLANE_PRE_CSC_GAMC_DATA_2(pipe)) +/* Display13 Plane Gamma Reg */ +#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1_A0x70160 +#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1_B0x71160 +#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2_A0x70260 +#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2_B0x71260 +#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1(pipe)_PIPE(pipe, _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1_A, \ + _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1_B) +#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2(pipe)_PIPE(pipe, _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2_A, \ + _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2_B) +#define PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1(pipe), \ + _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2(pipe)) + +#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1_A 0x70164 +#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1_B 0x71164 +#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2_A 0x70264 +#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2_B 0x71264 +#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1_A, \ + _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1_B) +#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2_A, \ + _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2_B) +#define PLANE_POST_CSC_GAMC_SEG0_DATA_ENH(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1(pipe), \ + _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2(pipe)) + +#define _PLANE_POST_CSC_GAMC_INDEX_ENH_1_A 0x701d8 +#define _PLANE_POST_CSC_GAMC_INDEX_ENH_1_B 0x711d8 +#define _PLANE_POST_CSC_GAMC_INDEX_ENH_2_A 0x702d8 +#define _PLANE_POST_CSC_GAMC_INDEX_ENH_2_B 0x712d8 +#define _PLANE_POST_CSC_GAMC_INDEX_ENH_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_INDEX_ENH_1_A, \ + _PLANE_POST_CSC_GAMC_INDEX_ENH_1_B) +#define _PLANE_POST_CSC_GAMC_INDEX_ENH_2(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_INDEX_ENH_2_A, \ + _PLANE_POST_CSC_GAMC_INDEX_ENH_2_B) +#define PLANE_POST_CSC_GAMC_INDEX_ENH(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_INDEX_ENH_1(pipe), \ + _PLANE_POST_CSC_GAMC_INDEX_ENH_2(pipe)) + +#define _PLANE_POST_CSC_GAMC_DATA_ENH_1_A 0x701dc +#define _PLANE_POST_CSC_GAMC_DATA_ENH_1_B 0x711dc +#define _PLANE_POST_CSC_GAMC_DATA_ENH_2_A 0x702dc +#define _PLANE_POST_CSC_GAMC_DATA_ENH_2_B 0x712dc +#define _PLANE_POST_CSC_GAMC_DATA_ENH_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_DATA_ENH_1_A, \ + _PLANE_POST_CSC_GAMC_DATA_ENH_1_B) +#define _PLANE_POST_CSC_GAMC_DATA_ENH_2(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_DATA_ENH_2_A, \ + _PLANE_POST_CSC_GAMC_DATA_ENH_2_B) +#define PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_DATA_ENH_1(pipe), \ + _PLANE_POST_CSC_GAMC_DATA_ENH_2(pipe)) + +#define _PLANE_POST_CSC_GAMC_INDEX_1_A 0x704d8 +#define _PLANE_POST_CSC_GAMC_INDEX_1_B 0x714d8 +#define _PLANE_POST_CSC_GAMC_INDEX_2_A 0x705d8 +#define _PLANE_POST_CSC_GAMC_INDEX_2_B 0x715d8 +#define _PLANE_POST_CSC_GAMC_INDEX_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_INDEX_1_A, \ + _PLANE_POST_CSC_GAMC_INDEX_1_B) +#define _PLANE_POST_CSC_GAMC_INDEX_2(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_INDEX_2_A, \ + _PLANE_POST_CSC_GAMC_INDEX_2_B) +#define PLANE_POST_CSC_GAMC_INDEX(pipe, plane, i) \ + _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_INDEX_1(pipe), \ + _PLANE_POST_CSC_GAMC_INDEX_2(pipe)) + +#define _PLANE_POST_CSC_GAMC_DATA_1_A 0x704dc +#define _PLANE_POST_CSC_GAMC_DATA_1_B 0x714dc +#define _PLANE_POST_CSC_GAMC_DATA_2_A 0x705dc +#define _PLANE_POST_CSC_GAMC_DATA_2_B 0x715dc +#define _PLANE_POST_CSC_GAMC_DATA_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_DATA_1_A
[PATCH 18/21] drm/i915/xelpd: Define and Initialize Plane Gamma Lut range
Define the structure with XE_LPD gamma lut ranges. HDR and SDR planes have different capabilities, implemented respective structure for the HDR planes. Degamma and GAMMA has same Lut caps for SDR planes, extended the same. Initialize the mode range caps as well. Signed-off-by: Uma Shankar Signed-off-by: Bhanuprakash Modem --- drivers/gpu/drm/i915/display/intel_color.c | 112 ++--- 1 file changed, 99 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 8b4f653b213d..7f091dd0bb19 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -2248,7 +2248,7 @@ static const struct drm_color_lut_range d13_degamma_hdr[] = { }; /* FIXME input bpc? */ -static const struct drm_color_lut_range d13_degamma_sdr[] = { +static const struct drm_color_lut_range d13_gamma_degamma_sdr[] = { /* segment 1 */ { .flags = (DRM_MODE_LUT_GAMMA | @@ -2298,6 +2298,63 @@ static const struct drm_color_lut_range d13_degamma_sdr[] = { }, }; + /* FIXME input bpc? */ +static const struct drm_color_lut_range d13_gamma_hdr[] = { + /* +* ToDo: Add Segment 1 +* There is an optional fine segment added with 9 lut values +* Will be added later +*/ + + /* segment 2 */ + { + .flags = (DRM_MODE_LUT_GAMMA | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_NON_DECREASING), + .count = 32, + .input_bpc = 24, .output_bpc = 16, + .start = 0, .end = (1 << 24) - 1, + .min = 0, .max = (1 << 24) - 1, + }, + /* segment 3 */ + { + .flags = (DRM_MODE_LUT_GAMMA | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 24, .output_bpc = 16, + .start = (1 << 24) - 1, .end = 1 << 24, + .min = 0, .max = 1 << 24, + }, + /* Segment 4 */ + { + .flags = (DRM_MODE_LUT_GAMMA | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 24, .output_bpc = 16, + .start = 1 << 24, .end = 3 << 24, + .min = 0, .max = (3 << 24), + }, + /* Segment 5 */ + { + .flags = (DRM_MODE_LUT_GAMMA | + DRM_MODE_LUT_REFLECT_NEGATIVE | + DRM_MODE_LUT_INTERPOLATE | + DRM_MODE_LUT_REUSE_LAST | + DRM_MODE_LUT_NON_DECREASING), + .count = 1, + .input_bpc = 24, .output_bpc = 16, + .start = 3 << 24, .end = 7 << 24, + .min = 0, .max = (7 << 24), + }, +}; + static void d13_program_plane_degamma_lut(const struct drm_plane_state *state, struct drm_color_lut_ext *degamma_lut, u32 offset) @@ -2407,26 +2464,55 @@ int intel_plane_color_init(struct drm_plane *plane) ret = drm_plane_color_add_gamma_degamma_mode_range(plane, "no degamma", NULL, 0, LUT_TYPE_DEGAMMA); - if (icl_is_hdr_plane(dev_priv, to_intel_plane(plane)->id)) + if (ret) + return ret; + + ret = drm_plane_color_add_gamma_degamma_mode_range(plane, "no gamma", + NULL, 0, + LUT_TYPE_GAMMA); + if (ret) + return ret; + + if (icl_is_hdr_plane(dev_priv, to_intel_plane(plane)->id)) { ret = drm_plane_color_add_gamma_degamma_mode_range(plane, "plane degamma", d13_degamma_hdr, sizeof(d13_degamma_hdr), LUT_TYPE_DEGAMMA); - else - ret = drm_plane_color_add_gamma_degamma_mode_r
[PATCH 17/21] drm: Add Plane Gamma Lut property
Add Plane Gamma Lut as a blob property. Signed-off-by: Uma Shankar --- drivers/gpu/drm/drm_atomic_state_helper.c | 3 +++ drivers/gpu/drm/drm_atomic_uapi.c | 10 ++ drivers/gpu/drm/drm_color_mgmt.c | 18 ++ include/drm/drm_plane.h | 14 ++ 4 files changed, 45 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c index fafb8af1c9cb..7ddf6e4b956b 100644 --- a/drivers/gpu/drm/drm_atomic_state_helper.c +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -316,6 +316,8 @@ void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane, drm_property_blob_get(state->degamma_lut); if (state->ctm) drm_property_blob_get(state->ctm); + if (state->gamma_lut) + drm_property_blob_get(state->gamma_lut); state->color_mgmt_changed = false; } @@ -366,6 +368,7 @@ void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state) drm_property_blob_put(state->fb_damage_clips); drm_property_blob_put(state->degamma_lut); drm_property_blob_put(state->ctm); + drm_property_blob_put(state->gamma_lut); } EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state); diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 6e3958491d10..4f5b7f76208d 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -614,6 +614,13 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane, return ret; } else if (property == plane->gamma_mode_property) { state->gamma_mode = val; + } else if (property == plane->gamma_lut_property) { + ret = drm_atomic_replace_property_blob_from_id(dev, + >gamma_lut, + val, -1, sizeof(struct drm_color_lut_ext), + ); + state->color_mgmt_changed |= replaced; + return ret; } else if (property == config->prop_fb_damage_clips) { ret = drm_atomic_replace_property_blob_from_id(dev, >fb_damage_clips, @@ -689,6 +696,9 @@ drm_atomic_plane_get_property(struct drm_plane *plane, *val = (state->ctm) ? state->ctm->base.id : 0; } else if (property == plane->gamma_mode_property) { *val = state->gamma_mode; + } else if (property == plane->gamma_lut_property) { + *val = (state->gamma_lut) ? + state->gamma_lut->base.id : 0; } else if (property == config->prop_fb_damage_clips) { *val = (state->fb_damage_clips) ? state->fb_damage_clips->base.id : 0; diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index 02367e691cf3..b5b3ff7f654d 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -613,6 +613,11 @@ EXPORT_SYMBOL(drm_plane_create_color_properties); * to query and get the plane gamma color caps and choose the * appropriate gamma mode and create lut values accordingly * + * gamma_lut_property: + * Blob property which allows a userspace to provide LUT values + * to apply gamma curve using the h/w plane degamma processing + * engine, thereby making the content as non-linear. + * */ int drm_plane_create_color_mgmt_properties(struct drm_device *dev, struct drm_plane *plane, @@ -648,6 +653,13 @@ int drm_plane_create_color_mgmt_properties(struct drm_device *dev, plane->gamma_mode_property = prop; + prop = drm_property_create(dev, DRM_MODE_PROP_BLOB, + "PLANE_GAMMA_LUT", 0); + if (!prop) + return -ENOMEM; + + plane->gamma_lut_property = prop; + return 0; } EXPORT_SYMBOL(drm_plane_create_color_mgmt_properties); @@ -685,6 +697,12 @@ void drm_plane_attach_gamma_properties(struct drm_plane *plane) drm_object_attach_property(>base, plane->gamma_mode_property, 0); + + if (!plane->gamma_lut_property) + return; + + drm_object_attach_property(>base, + plane->gamma_lut_property, 0); } EXPORT_SYMBOL(drm_plane_attach_gamma_properties); diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index a7b7c8599702..8989bb1aa46c 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -267,6 +267,14 @@ struct drm_plane_state { */ u32 gamma_mode; + /* @gamma_lut: +* +* Lookup table for converting framebuffer pixel data after applying the
[PATCH 16/21] drm: Add Plane Gamma Mode property
Add Plane Gamma Mode as a blob property. This is an enum property with values as blob_id's and exposes the various gamma modes supported and the lut ranges. Getting the blob id in userspace, user can get the mode supported and also the range of gamma mode supported with number of lut coefficients. It can then set one of the modes using this enum property. Lut values will be sent through a separate GAMMA_LUT blob property. Signed-off-by: Uma Shankar Signed-off-by: Bhanuprakash Modem --- drivers/gpu/drm/drm_atomic_uapi.c | 4 drivers/gpu/drm/drm_color_mgmt.c | 26 ++ include/drm/drm_plane.h | 14 ++ 3 files changed, 44 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 6af2afe362ff..6e3958491d10 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -612,6 +612,8 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane, ); state->color_mgmt_changed |= replaced; return ret; + } else if (property == plane->gamma_mode_property) { + state->gamma_mode = val; } else if (property == config->prop_fb_damage_clips) { ret = drm_atomic_replace_property_blob_from_id(dev, >fb_damage_clips, @@ -685,6 +687,8 @@ drm_atomic_plane_get_property(struct drm_plane *plane, state->degamma_lut->base.id : 0; } else if (property == plane->ctm_property) { *val = (state->ctm) ? state->ctm->base.id : 0; + } else if (property == plane->gamma_mode_property) { + *val = state->gamma_mode; } else if (property == config->prop_fb_damage_clips) { *val = (state->fb_damage_clips) ? state->fb_damage_clips->base.id : 0; diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index 5c3138497b9c..02367e691cf3 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -606,6 +606,13 @@ EXPORT_SYMBOL(drm_plane_create_color_properties); * Blob property which allows a userspace to provide CTM coefficients * to do color space conversion or any other enhancement by doing a * matrix multiplication using the h/w CTM processing engine + * + * gamma_mode_property: + * Blob property which advertizes the possible gamma modes and + * lut ranges supported by the platform. This allows userspace + * to query and get the plane gamma color caps and choose the + * appropriate gamma mode and create lut values accordingly + * */ int drm_plane_create_color_mgmt_properties(struct drm_device *dev, struct drm_plane *plane, @@ -634,6 +641,13 @@ int drm_plane_create_color_mgmt_properties(struct drm_device *dev, plane->ctm_property = prop; + prop = drm_property_create(dev, DRM_MODE_PROP_ENUM, + "PLANE_GAMMA_MODE", num_values); + if (!prop) + return -ENOMEM; + + plane->gamma_mode_property = prop; + return 0; } EXPORT_SYMBOL(drm_plane_create_color_mgmt_properties); @@ -664,6 +678,16 @@ void drm_plane_attach_ctm_property(struct drm_plane *plane) } EXPORT_SYMBOL(drm_plane_attach_ctm_property); +void drm_plane_attach_gamma_properties(struct drm_plane *plane) +{ + if (!plane->gamma_mode_property) + return; + + drm_object_attach_property(>base, + plane->gamma_mode_property, 0); +} +EXPORT_SYMBOL(drm_plane_attach_gamma_properties); + int drm_plane_color_add_gamma_degamma_mode_range(struct drm_plane *plane, const char *name, const struct drm_color_lut_range *ranges, @@ -676,6 +700,8 @@ int drm_plane_color_add_gamma_degamma_mode_range(struct drm_plane *plane, if (type == LUT_TYPE_DEGAMMA) prop = plane->degamma_mode_property; + else + prop = plane->gamma_mode_property; if (!prop) return -EINVAL; diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index 4557f59cf3cf..a7b7c8599702 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -260,6 +260,13 @@ struct drm_plane_state { */ struct drm_property_blob *ctm; + /** +* @gamma_mode: This is a blob_id and exposes the platform capabilities +* wrt to various gamma modes and the respective lut ranges. This also +* helps user select a gamma mode amongst the supported ones. +*/ + u32 gamma_mode; + u8 color_mgmt_changed : 1; }; @@ -791,6 +798,12 @@ struct drm_pla
[PATCH 15/21] drm/i915/xelpd: Enable Plane CSC
Implement plane CSC for ICL+ Signed-off-by: Uma Shankar --- .../gpu/drm/i915/display/intel_atomic_plane.c | 5 +- drivers/gpu/drm/i915/display/intel_color.c| 82 +++ .../drm/i915/display/skl_universal_plane.c| 4 + drivers/gpu/drm/i915/i915_reg.h | 1 + 4 files changed, 91 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index 5de9c98beaf6..ec7646790892 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -499,6 +499,7 @@ void skl_update_planes_on_crtc(struct intel_atomic_state *state, intel_atomic_get_new_crtc_state(state, crtc); struct skl_ddb_entry entries_y[I915_MAX_PLANES]; struct skl_ddb_entry entries_uv[I915_MAX_PLANES]; + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 update_mask = new_crtc_state->update_planes; struct intel_plane *plane; @@ -513,8 +514,10 @@ void skl_update_planes_on_crtc(struct intel_atomic_state *state, struct intel_plane_state *new_plane_state = intel_atomic_get_new_plane_state(state, plane); - if (new_plane_state->uapi.color_mgmt_changed) + if (new_plane_state->uapi.color_mgmt_changed) { intel_color_load_plane_luts(_plane_state->uapi); + dev_priv->display.load_plane_csc_matrix(_plane_state->uapi); + } if (new_plane_state->uapi.visible || new_plane_state->planar_slave) { diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 6d57a47d8a60..8b4f653b213d 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -2119,6 +2119,83 @@ static void icl_read_luts(struct intel_crtc_state *crtc_state) } } +static void icl_load_plane_csc_matrix(const struct drm_plane_state *state) +{ + struct drm_i915_private *dev_priv = to_i915(state->plane->dev); + enum pipe pipe = to_intel_plane(state->plane)->pipe; + enum plane_id plane = to_intel_plane(state->plane)->id; + struct drm_color_ctm *ctm; + const u64 *input; + u16 coeffs[9] = {}; + u16 postoff = 0; + int i; + + if (!icl_is_hdr_plane(dev_priv, plane) || !state->ctm) + return; + + ctm = state->ctm->data; + input = ctm->matrix; + + /* +* Convert fixed point S31.32 input to format supported by the +* hardware. +*/ + for (i = 0; i < ARRAY_SIZE(coeffs); i++) { + u64 abs_coeff = ((1ULL << 63) - 1) & input[i]; + + /* +* Clamp input value to min/max supported by +* hardware. +*/ + abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_4_0 - 1); + + /* sign bit */ + if (CTM_COEFF_NEGATIVE(input[i])) + coeffs[i] |= 1 << 15; + + if (abs_coeff < CTM_COEFF_0_125) + coeffs[i] |= (3 << 12) | + ILK_CSC_COEFF_FP(abs_coeff, 12); + else if (abs_coeff < CTM_COEFF_0_25) + coeffs[i] |= (2 << 12) | + ILK_CSC_COEFF_FP(abs_coeff, 11); + else if (abs_coeff < CTM_COEFF_0_5) + coeffs[i] |= (1 << 12) | + ILK_CSC_COEFF_FP(abs_coeff, 10); + else if (abs_coeff < CTM_COEFF_1_0) + coeffs[i] |= ILK_CSC_COEFF_FP(abs_coeff, 9); + else if (abs_coeff < CTM_COEFF_2_0) + coeffs[i] |= (7 << 12) | + ILK_CSC_COEFF_FP(abs_coeff, 8); + else + coeffs[i] |= (6 << 12) | + ILK_CSC_COEFF_FP(abs_coeff, 7); + } + + intel_de_write(dev_priv, PLANE_CSC_COEFF(pipe, plane, 0), + coeffs[0] << 16 | coeffs[1]); + intel_de_write(dev_priv, PLANE_CSC_COEFF(pipe, plane, 1), + coeffs[2] << 16); + + intel_de_write(dev_priv, PLANE_CSC_COEFF(pipe, plane, 2), + coeffs[3] << 16 | coeffs[4]); + intel_de_write(dev_priv, PLANE_CSC_COEFF(pipe, plane, 3), + coeffs[5] << 16); + + intel_de_write(dev_priv, PLANE_CSC_COEFF(pipe, plane, 4), + coeffs[6] << 16 | coeffs[7]); + intel_de_write(dev_priv, PLANE_CSC_COEFF(pipe, plane, 5), + coeffs[8] << 16); + + intel_de_write(dev_priv, PLANE_CSC_PREOFF(pipe, plane, 0), 0); + intel_de_w
[PATCH 14/21] drm/i915/xelpd: Define Plane CSC Registers
Define Register macros for plane CSC. Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/i915_reg.h | 43 + 1 file changed, 43 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index ede7dca440e2..df8500a86e9d 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7397,6 +7397,49 @@ enum { #define PLANE_COLOR_CTL(pipe, plane) \ _MMIO_PLANE(plane, _PLANE_COLOR_CTL_1(pipe), _PLANE_COLOR_CTL_2(pipe)) +/* Plane CSC Registers */ +#define _PLANE_CSC_RY_GY_1_A 0x70210 +#define _PLANE_CSC_RY_GY_2_A 0x70310 + +#define _PLANE_CSC_RY_GY_1_B 0x71210 +#define _PLANE_CSC_RY_GY_2_B 0x71310 + +#define _PLANE_CSC_RY_GY_1(pipe) _PIPE(pipe, _PLANE_CSC_RY_GY_1_A, \ + _PLANE_CSC_RY_GY_1_B) +#define _PLANE_CSC_RY_GY_2(pipe) _PIPE(pipe, _PLANE_INPUT_CSC_RY_GY_2_A, \ + _PLANE_INPUT_CSC_RY_GY_2_B) +#define PLANE_CSC_COEFF(pipe, plane, index)_MMIO_PLANE(plane, \ + _PLANE_CSC_RY_GY_1(pipe) + (index) * 4, \ + _PLANE_CSC_RY_GY_2(pipe) + (index) * 4) + +#define _PLANE_CSC_PREOFF_HI_1_A 0x70228 +#define _PLANE_CSC_PREOFF_HI_2_A 0x70328 + +#define _PLANE_CSC_PREOFF_HI_1_B 0x71228 +#define _PLANE_CSC_PREOFF_HI_2_B 0x71328 + +#define _PLANE_CSC_PREOFF_HI_1(pipe) _PIPE(pipe, _PLANE_CSC_PREOFF_HI_1_A, \ + _PLANE_CSC_PREOFF_HI_1_B) +#define _PLANE_CSC_PREOFF_HI_2(pipe) _PIPE(pipe, _PLANE_CSC_PREOFF_HI_2_A, \ + _PLANE_CSC_PREOFF_HI_2_B) +#define PLANE_CSC_PREOFF(pipe, plane, index) _MMIO_PLANE(plane, _PLANE_CSC_PREOFF_HI_1(pipe) + \ + (index) * 4, _PLANE_CSC_PREOFF_HI_2(pipe) + \ + (index) * 4) + +#define _PLANE_CSC_POSTOFF_HI_1_A 0x70234 +#define _PLANE_CSC_POSTOFF_HI_2_A 0x70334 + +#define _PLANE_CSC_POSTOFF_HI_1_B 0x71234 +#define _PLANE_CSC_POSTOFF_HI_2_B 0x71334 + +#define _PLANE_CSC_POSTOFF_HI_1(pipe) _PIPE(pipe, _PLANE_CSC_POSTOFF_HI_1_A, \ + _PLANE_CSC_POSTOFF_HI_1_B) +#define _PLANE_CSC_POSTOFF_HI_2(pipe) _PIPE(pipe, _PLANE_CSC_POSTOFF_HI_2_A, \ + _PLANE_CSC_POSTOFF_HI_2_B) +#define PLANE_CSC_POSTOFF(pipe, plane, index) _MMIO_PLANE(plane, _PLANE_CSC_POSTOFF_HI_1(pipe) + \ + (index) * 4, _PLANE_CSC_POSTOFF_HI_2(pipe) + \ + (index) * 4) + #define _SEL_FETCH_PLANE_BASE_1_A 0x70890 #define _SEL_FETCH_PLANE_BASE_2_A 0x708B0 #define _SEL_FETCH_PLANE_BASE_3_A 0x708D0 -- 2.26.2
[PATCH 13/21] drm: Add helper to attach Plane ctm property
Add a DRM helper to attach ctm property. Signed-off-by: Uma Shankar --- drivers/gpu/drm/drm_color_mgmt.c | 10 ++ include/drm/drm_plane.h | 1 + 2 files changed, 11 insertions(+) diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index 83832adf3adf..5c3138497b9c 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -654,6 +654,16 @@ void drm_plane_attach_degamma_properties(struct drm_plane *plane) } EXPORT_SYMBOL(drm_plane_attach_degamma_properties); +void drm_plane_attach_ctm_property(struct drm_plane *plane) +{ + if (!plane->ctm_property) + return; + + drm_object_attach_property(>base, + plane->ctm_property, 0); +} +EXPORT_SYMBOL(drm_plane_attach_ctm_property); + int drm_plane_color_add_gamma_degamma_mode_range(struct drm_plane *plane, const char *name, const struct drm_color_lut_range *ranges, diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index 83d11918333b..4557f59cf3cf 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -886,6 +886,7 @@ int drm_plane_create_color_mgmt_properties(struct drm_device *dev, struct drm_plane *plane, int num_values); void drm_plane_attach_degamma_properties(struct drm_plane *plane); +void drm_plane_attach_ctm_property(struct drm_plane *plane); int drm_plane_color_add_gamma_degamma_mode_range(struct drm_plane *plane, const char *name, const struct drm_color_lut_range *ranges, -- 2.26.2
[PATCH 12/21] drm: Add Plane CTM property
Add a blob property for plane CSC usage. Signed-off-by: Uma Shankar --- drivers/gpu/drm/drm_atomic_state_helper.c | 3 +++ drivers/gpu/drm/drm_atomic_uapi.c | 10 ++ drivers/gpu/drm/drm_color_mgmt.c | 11 +++ include/drm/drm_plane.h | 15 +++ 4 files changed, 39 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c index 6e358067cb7a..fafb8af1c9cb 100644 --- a/drivers/gpu/drm/drm_atomic_state_helper.c +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -314,6 +314,8 @@ void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane, if (state->degamma_lut) drm_property_blob_get(state->degamma_lut); + if (state->ctm) + drm_property_blob_get(state->ctm); state->color_mgmt_changed = false; } @@ -363,6 +365,7 @@ void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state) drm_property_blob_put(state->fb_damage_clips); drm_property_blob_put(state->degamma_lut); + drm_property_blob_put(state->ctm); } EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state); diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index ce3cb65d415e..6af2afe362ff 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -604,6 +604,14 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane, ); state->color_mgmt_changed |= replaced; return ret; + } else if (property == plane->ctm_property) { + ret = drm_atomic_replace_property_blob_from_id(dev, + >ctm, + val, + sizeof(struct drm_color_ctm), -1, + ); + state->color_mgmt_changed |= replaced; + return ret; } else if (property == config->prop_fb_damage_clips) { ret = drm_atomic_replace_property_blob_from_id(dev, >fb_damage_clips, @@ -675,6 +683,8 @@ drm_atomic_plane_get_property(struct drm_plane *plane, } else if (property == plane->degamma_lut_property) { *val = (state->degamma_lut) ? state->degamma_lut->base.id : 0; + } else if (property == plane->ctm_property) { + *val = (state->ctm) ? state->ctm->base.id : 0; } else if (property == config->prop_fb_damage_clips) { *val = (state->fb_damage_clips) ? state->fb_damage_clips->base.id : 0; diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index 29d0fc1e52b5..83832adf3adf 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -602,6 +602,10 @@ EXPORT_SYMBOL(drm_plane_create_color_properties); * engine, thereby making the content as linear for further color * processing. * + * ctm_property: + * Blob property which allows a userspace to provide CTM coefficients + * to do color space conversion or any other enhancement by doing a + * matrix multiplication using the h/w CTM processing engine */ int drm_plane_create_color_mgmt_properties(struct drm_device *dev, struct drm_plane *plane, @@ -623,6 +627,13 @@ int drm_plane_create_color_mgmt_properties(struct drm_device *dev, plane->degamma_lut_property = prop; + prop = drm_property_create(dev, DRM_MODE_PROP_BLOB, + "PLANE_CTM", 0); + if (!prop) + return -ENOMEM; + + plane->ctm_property = prop; + return 0; } EXPORT_SYMBOL(drm_plane_create_color_mgmt_properties); diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index bbd0033ed1d2..83d11918333b 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -252,6 +252,14 @@ struct drm_plane_state { */ struct drm_property_blob *degamma_lut; + /** +* @ctm: +* +* Color transformation matrix. See drm_plane_enable_color_mgmt(). The +* blob (if not NULL) is a drm_color_ctm. +*/ + struct drm_property_blob *ctm; + u8 color_mgmt_changed : 1; }; @@ -776,6 +784,13 @@ struct drm_plane { * used to convert the framebuffer's colors to linear gamma. */ struct drm_property *degamma_lut_property; + + /** +* @plane_ctm_property: Optional Plane property to set the +* matrix used to convert colors after the lookup in the +* degamma LUT. +*/ + struct drm_property *ctm_property; }; #define obj_to_plane(x) container_of(x, struct drm_plane, base) -- 2.26.2
[PATCH 11/21] drm/i915/xelpd: Load plane color luts from atomic flip
Load plane color luts as part of atomic plane updates. This will be done only if the plane color luts are changed. Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_atomic_plane.c | 3 +++ drivers/gpu/drm/i915/display/intel_atomic_plane.h | 1 + drivers/gpu/drm/i915/display/intel_color.c| 9 + 3 files changed, 13 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index 36f52a1d7552..5de9c98beaf6 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -513,6 +513,9 @@ void skl_update_planes_on_crtc(struct intel_atomic_state *state, struct intel_plane_state *new_plane_state = intel_atomic_get_new_plane_state(state, plane); + if (new_plane_state->uapi.color_mgmt_changed) + intel_color_load_plane_luts(_plane_state->uapi); + if (new_plane_state->uapi.visible || new_plane_state->planar_slave) { intel_update_plane(plane, new_crtc_state, new_plane_state); diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.h b/drivers/gpu/drm/i915/display/intel_atomic_plane.h index c809f522a710..1ba3b524cee2 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.h +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.h @@ -66,5 +66,6 @@ int intel_atomic_plane_check_clipping(struct intel_plane_state *plane_state, void intel_plane_set_invisible(struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state); int intel_plane_color_init(struct drm_plane *plane); +void intel_color_load_plane_luts(const struct drm_plane_state *plane_state); #endif /* __INTEL_ATOMIC_PLANE_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 4e5733573fd8..6d57a47d8a60 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -22,6 +22,7 @@ * */ +#include "intel_atomic_plane.h" #include "intel_color.h" #include "intel_de.h" #include "intel_display_types.h" @@ -2311,6 +2312,14 @@ static void d13_plane_load_luts(const struct drm_plane_state *plane_state) } } +void intel_color_load_plane_luts(const struct drm_plane_state *plane_state) +{ + struct drm_device *dev = plane_state->plane->dev; + struct drm_i915_private *dev_priv = to_i915(dev); + + dev_priv->display.load_plane_luts(plane_state); +} + int intel_plane_color_init(struct drm_plane *plane) { struct drm_i915_private *dev_priv = to_i915(plane->dev); -- 2.26.2
[PATCH 10/21] drm/i915/xelpd: Initialize plane color features
Initialize plane color features for XE_LPD. Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_atomic_plane.h | 1 + drivers/gpu/drm/i915/display/skl_universal_plane.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.h b/drivers/gpu/drm/i915/display/intel_atomic_plane.h index dc4d05e75e1c..c809f522a710 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.h +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.h @@ -65,5 +65,6 @@ int intel_atomic_plane_check_clipping(struct intel_plane_state *plane_state, bool can_position); void intel_plane_set_invisible(struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state); +int intel_plane_color_init(struct drm_plane *plane); #endif /* __INTEL_ATOMIC_PLANE_H__ */ diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index ae439dca4b3c..aadb984fdf77 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -2184,6 +2184,8 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, BIT(DRM_SCALING_FILTER_DEFAULT) | BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR)); + intel_plane_color_init(>base); + drm_plane_helper_add(>base, _plane_helper_funcs); return plane; -- 2.26.2
[PATCH 09/21] drm/i915/xelpd: Add plane color check to glk_plane_color_ctl
Extended glk_plane_color_ctl to have plane color checks. This helps enabling the degamma or gamma block based on user inputs. Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/skl_universal_plane.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 92a4fd508e92..ae439dca4b3c 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -960,6 +960,11 @@ static u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state, u32 plane_color_ctl = 0; plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE; + + /* FIXME needs hw.degamma_lut */ + if (plane_state->uapi.degamma_lut) + plane_color_ctl |= PLANE_PRE_CSC_GAMMA_ENABLE; + plane_color_ctl |= glk_plane_color_ctl_alpha(plane_state); if (fb->format->is_yuv && !icl_is_hdr_plane(dev_priv, plane->id)) { -- 2.26.2
[PATCH 08/21] drm/i915/xelpd: Program Plane Degamma Registers
Extract the LUT and program plane degamma registers. Signed-off-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 116 + drivers/gpu/drm/i915/i915_reg.h| 2 + 2 files changed, 118 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 4908e825f3cc..4e5733573fd8 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -126,6 +126,29 @@ static bool crtc_state_is_legacy_gamma(const struct intel_crtc_state *crtc_state lut_is_legacy(crtc_state->hw.gamma_lut); } +/* + * Added to accommodate enhanced LUT precision. + * Max LUT precision is 32 bits. + */ +static u64 drm_color_lut_extract_ext(u64 user_input, u32 bit_precision) +{ + u64 val = user_input & 0x; + u32 max; + + if (bit_precision > 32) + return 0; + + max = 0x >> (32 - bit_precision); + /* Round only if we're not using full precision. */ + if (bit_precision < 32) { + val += 1UL << (32 - bit_precision - 1); + val >>= 32 - bit_precision; + } + + return ((user_input & 0x) | + clamp_val(val, 0, max)); +} + /* * When using limited range, multiply the matrix given by userspace by * the matrix that we would use for the limited range. @@ -2197,6 +2220,97 @@ static const struct drm_color_lut_range d13_degamma_sdr[] = { }, }; +static void d13_program_plane_degamma_lut(const struct drm_plane_state *state, + struct drm_color_lut_ext *degamma_lut, + u32 offset) +{ + struct drm_i915_private *dev_priv = to_i915(state->plane->dev); + enum pipe pipe = to_intel_plane(state->plane)->pipe; + enum plane_id plane = to_intel_plane(state->plane)->id; + u32 i, lut_size; + + if (icl_is_hdr_plane(dev_priv, plane)) { + lut_size = 128; + + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_INDEX_ENH(pipe, plane, 0), + PLANE_PAL_PREC_AUTO_INCREMENT); + + if (degamma_lut) { + for (i = 0; i < lut_size; i++) { + u64 word = drm_color_lut_extract_ext(degamma_lut[i].green, 24); + u32 lut_val = (word & 0xff); + + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0), + lut_val); + } + + /* Program the max register to clamp values > 1.0. */ + while (i < 131) + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0), + degamma_lut[i++].green); + } else { + for (i = 0; i < lut_size; i++) { + u32 v = (i * ((1 << 24) - 1)) / (lut_size - 1); + + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0), v); + } + + do { + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0), + 1 << 24); + } while (i++ < 130); + } + + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_INDEX_ENH(pipe, plane, 0), 0); + } else { + lut_size = 32; + + /* +* First 3 planes are HDR, so reduce by 3 to get to the right +* SDR plane offset +*/ + plane = plane - 3; + + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_INDEX(pipe, plane, 0), + PLANE_PAL_PREC_AUTO_INCREMENT); + + if (degamma_lut) { + for (i = 0; i < lut_size; i++) + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_DATA(pipe, plane, 0), + degamma_lut[i].green); + /* Program the max register to clamp values > 1.0. */ + while (i < 35) + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_DATA(pipe, plane, 0), + degamma_lut[i++].green); + } else { + for (i = 0; i < lut_size; i++) { + u32 v = (i * ((1 << 16) - 1)) / (lut_size - 1); + + intel_de_write(dev_priv, PLANE_PRE_CSC_GAMC_DATA(pipe, plane, 0), v); + } + + do { + intel_de_writ