[PATCH 28/28] drm/i915/color: Enable Plane Color Pipelines

2024-02-12 Thread Uma Shankar
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

2024-02-12 Thread Uma Shankar
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

2024-02-12 Thread Uma Shankar
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

2024-02-12 Thread Uma Shankar
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

2024-02-12 Thread Uma Shankar
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

2024-02-12 Thread Uma Shankar
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

2024-02-12 Thread Uma Shankar
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

2024-02-12 Thread Uma Shankar
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

2024-02-12 Thread Uma Shankar
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

2024-02-12 Thread Uma Shankar
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

2024-02-12 Thread Uma Shankar
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

2024-02-12 Thread Uma Shankar
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

2024-02-12 Thread Uma Shankar
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

2024-02-12 Thread Uma Shankar
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

2024-02-12 Thread Uma Shankar
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

2024-02-12 Thread Uma Shankar
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

2024-02-12 Thread Uma Shankar
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

2024-02-12 Thread Uma Shankar
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

2024-02-12 Thread Uma Shankar
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

2024-02-12 Thread Uma Shankar
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

2024-02-12 Thread Uma Shankar
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

2024-02-12 Thread Uma Shankar
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

2024-02-12 Thread Uma Shankar
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

2024-02-12 Thread Uma Shankar
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

2024-02-12 Thread Uma Shankar
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

2024-02-12 Thread Uma Shankar
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

2024-02-12 Thread Uma Shankar
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

2024-02-12 Thread Uma Shankar
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

2024-02-12 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2023-08-29 Thread Uma Shankar
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

2021-09-06 Thread Uma Shankar
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

2021-09-06 Thread Uma Shankar
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

2021-09-06 Thread Uma Shankar
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

2021-09-06 Thread Uma Shankar
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

2021-09-06 Thread Uma Shankar
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

2021-09-06 Thread Uma Shankar
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

2021-09-06 Thread Uma Shankar
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

2021-09-06 Thread Uma Shankar
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

2021-09-06 Thread Uma Shankar
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

2021-09-06 Thread Uma Shankar
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

2021-09-06 Thread Uma Shankar
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

2021-09-06 Thread Uma Shankar
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

2021-09-06 Thread Uma Shankar
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

2021-09-06 Thread Uma Shankar
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

2021-09-06 Thread Uma Shankar
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

2021-09-06 Thread Uma Shankar
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

2021-09-06 Thread Uma Shankar
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

2021-09-06 Thread Uma Shankar
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

2021-09-06 Thread Uma Shankar
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

2021-09-06 Thread Uma Shankar
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

2021-09-06 Thread Uma Shankar
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

2021-09-06 Thread Uma Shankar
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

2021-09-06 Thread Uma Shankar
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

2021-06-01 Thread Uma Shankar
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

2021-06-01 Thread Uma Shankar
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

2021-06-01 Thread Uma Shankar
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

2021-06-01 Thread Uma Shankar
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

2021-06-01 Thread Uma Shankar
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

2021-06-01 Thread Uma Shankar
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

2021-06-01 Thread Uma Shankar
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

2021-06-01 Thread Uma Shankar
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

2021-06-01 Thread Uma Shankar
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

2021-06-01 Thread Uma Shankar
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

2021-06-01 Thread Uma Shankar
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

2021-06-01 Thread Uma Shankar
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

2021-06-01 Thread Uma Shankar
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

2021-06-01 Thread Uma Shankar
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

  1   2   3   4   5   >