[RFC 00/33] Add Support for Plane Color Pipeline

2023-08-29 Thread Uma Shankar
E".

Refer to Documentation/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 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 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 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(&plane->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 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 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,
+   &state->set_color_pipeline_data,
+   val,
+   -1,
+   sizeof(struct drm_color_pipeline),
+   &replaced);
+   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(&plane->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;
+
+  

[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 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 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 &struct 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 &struct 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 &struct 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 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 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,
+  &state->color.ctm,
+  0, -1, -1,
+  &blob_replaced);
+   temp_replaced |= blob_replaced;
+   if (ret)
+   goto out;
+
+   ret = drm_atomic_replace_property_blob_from_id(dev,
+  
&state->color.pre_csc_lut,
+  0, -1, -1,
+  &blob_replaced);
+   temp_replaced |= blob_replaced;
+
+   if (ret)
+   goto out;
+
+   ret = drm_atomic_replace_property_blob_from_id(dev,
+  
&state->color.post_csc_lut,
+  0, -1, -1,
+  &blob_replaced);
+   temp_replaced |= blob_replaced;
+
+   ret = drm_atomic_replace_property_blob_from_id(dev,
+  
&state->color.private_color_op_data,
+  0, -1, -1,
+  &blob_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 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,
&state->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);
replaced = false;
-   ret = drm_plane_replace_color_op_blobs(plane, state,
-  val,
-  &replaced);
+   if (!ret) {
+   ret = drm_plane_replace_color_op_blobs(plane, 
state,
+  val,
+  
&replaced);
+   }
}
 
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,
+   &state->color.ctm,
+   color_op[i].blob_id,
+   -1, sizeof(struct 
drm_color_ctm),
+   &blob_replaced);
+   } else if (color_op[i].name ==  DRM_CB_PRE_CSC) {
+   ret = drm_atomic_replace_property_blob_from_id(dev,
+   
&state->color.pre_csc_lut,
+   color_op[i].blob_id,
+   -1, sizeof(struct 
drm_color_lut_ext),
+   &blob_replaced);
+   } else if (color_op[i].name == DRM_CB_POST_CSC) {
+   ret = drm_atomic_replace_property_blob_from_id(dev,
+   
&state->color.post_csc_lut,
+   color_op[i].blob_id,
+   -1, sizeof(struct 
drm_color_lut_ext),
+   &blob_replaced);
+   } else if (color_op[i].name == DRM_CB_PRIVATE) {
+   ret = drm_atomic_replace_property_blob_from_id(dev,
+   
&state->color.private_color_op_data,
+   color_op[i].blob_id,
+   -1, -1,
+   &blob_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),
&replaced);
+   if (replaced) {
+   /* Consider actual color parameter change only when

[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 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 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 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 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 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 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 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 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(&plane_state->uapi);
+
intel_psr2_program_plane_sel_fetch_noarm(plane, crtc_state, 
plane_state, color_plane);
 }
 
-- 
2.38.1



[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 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 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 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 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 = &i9xx_color_funcs;
} else {
-   if (DISPLAY_VER(i915) >= 12)
+   if (DISPLAY_VER(i915) >= 13)
+   i915->display.funcs.color = &xelpd_color_funcs;
+   else if (DISPLAY_VER(i915) == 12)
i915->display.funcs.color = &tgl_color_funcs;
else if (DISPLAY_VER(i915) == 11)
i915->display.funcs.color = &icl_color_funcs;
-- 
2.38.1



[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 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 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 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 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,
   &blob_replaced);
temp_replaced |= blob_replaced;
 
+   if (ret)
+   goto out;
+
+   ret = drm_atomic_replace_property_blob_from_id(dev,
+  &state->color.lut_3d,
+  0, -1, -1,
+  &blob_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,
&blob_replaced);
+   } else if (color_op[i].name == DRM_CB_3D_LUT) {
+   ret = drm_atomic_replace_property_blob_from_id(dev,
+   &state->color.lut_3d,
+   color_op[i].blob_id,
+   -1, sizeof(struct 
drm_color_lut_ext),
+   &blob_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_p

[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(&plane->base);
 
return plane;
 
-- 
2.38.1