Re: [PATCH RFC v6 01/10] drm: Introduce pixel_source DRM plane property

2023-08-29 Thread Pekka Paalanen
On Mon, 28 Aug 2023 17:05:07 -0700
Jessica Zhang  wrote:

> Add support for pixel_source property to drm_plane and related
> documentation. In addition, force pixel_source to
> DRM_PLANE_PIXEL_SOURCE_FB in DRM_IOCTL_MODE_SETPLANE as to not break
> legacy userspace.
> 
> This enum property will allow user to specify a pixel source for the
> plane. Possible pixel sources will be defined in the
> drm_plane_pixel_source enum.
> 
> Currently, the only pixel sources are DRM_PLANE_PIXEL_SOURCE_FB (the
> default value) and DRM_PLANE_PIXEL_SOURCE_NONE.
> 
> Signed-off-by: Jessica Zhang 
> ---
>  drivers/gpu/drm/drm_atomic_state_helper.c |  1 +
>  drivers/gpu/drm/drm_atomic_uapi.c |  4 ++
>  drivers/gpu/drm/drm_blend.c   | 90 
> +++
>  drivers/gpu/drm/drm_plane.c   | 19 +--
>  include/drm/drm_blend.h   |  2 +
>  include/drm/drm_plane.h   | 21 
>  6 files changed, 133 insertions(+), 4 deletions(-)

...

> diff --git a/drivers/gpu/drm/drm_blend.c b/drivers/gpu/drm/drm_blend.c
> index 6e74de833466..c3c57bae06b7 100644
> --- a/drivers/gpu/drm/drm_blend.c
> +++ b/drivers/gpu/drm/drm_blend.c
> @@ -185,6 +185,21 @@
>   *plane does not expose the "alpha" property, then this is
>   *assumed to be 1.0
>   *
> + * pixel_source:
> + *   pixel_source is set up with drm_plane_create_pixel_source_property().
> + *   It is used to toggle the active source of pixel data for the plane.
> + *   The plane will only display data from the set pixel_source -- any
> + *   data from other sources will be ignored.
> + *
> + *   Possible values:
> + *
> + *   "NONE":
> + *   No active pixel source.
> + *   Committing with a NONE pixel source will disable the plane.
> + *
> + *   "FB":
> + *   Framebuffer source set by the "FB_ID" property.
> + *
>   * Note that all the property extensions described here apply either to the
>   * plane or the CRTC (e.g. for the background color, which currently is not
>   * exposed and assumed to be black).

This UAPI:
Acked-by: Pekka Paalanen 


Thanks,
pq


pgp2TIIFMWlG1.pgp
Description: OpenPGP digital signature


Re: [PATCH RFC v6 02/10] drm: Introduce solid fill DRM plane property

2023-08-29 Thread Pekka Paalanen
On Mon, 28 Aug 2023 17:05:08 -0700
Jessica Zhang  wrote:

> Document and add support for solid_fill property to drm_plane. In
> addition, add support for setting and getting the values for solid_fill.
> 
> To enable solid fill planes, userspace must assign a property blob to
> the "solid_fill" plane property containing the following information:
> 
> struct drm_mode_solid_fill {
>   u32 r, g, b;
> };
> 
> Signed-off-by: Jessica Zhang 
> ---
>  drivers/gpu/drm/drm_atomic_state_helper.c |  9 
>  drivers/gpu/drm/drm_atomic_uapi.c | 26 ++
>  drivers/gpu/drm/drm_blend.c   | 30 ++
>  include/drm/drm_blend.h   |  1 +
>  include/drm/drm_plane.h   | 36 
> +++
>  include/uapi/drm/drm_mode.h   | 24 +
>  6 files changed, 126 insertions(+)

...

> diff --git a/drivers/gpu/drm/drm_blend.c b/drivers/gpu/drm/drm_blend.c
> index c3c57bae06b7..273021cc21c8 100644
> --- a/drivers/gpu/drm/drm_blend.c
> +++ b/drivers/gpu/drm/drm_blend.c
> @@ -200,6 +200,10 @@
>   *   "FB":
>   *   Framebuffer source set by the "FB_ID" property.
>   *
> + * solid_fill:
> + *   solid_fill is set up with drm_plane_create_solid_fill_property(). It
> + *   contains pixel data that drivers can use to fill a plane.
> + *
>   * Note that all the property extensions described here apply either to the
>   * plane or the CRTC (e.g. for the background color, which currently is not
>   * exposed and assumed to be black).

...

> diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
> index 43691058d28f..1fd92886d66c 100644
> --- a/include/uapi/drm/drm_mode.h
> +++ b/include/uapi/drm/drm_mode.h
> @@ -259,6 +259,30 @@ struct drm_mode_modeinfo {
>   char name[DRM_DISPLAY_MODE_LEN];
>  };
>  
> +/**
> + * struct drm_mode_solid_fill - User info for solid fill planes
> + *
> + * This is the userspace API solid fill information structure.
> + *
> + * Userspace can enable solid fill planes by assigning the plane "solid_fill"
> + * property to a blob containing a single drm_mode_solid_fill struct 
> populated with an RGB323232
> + * color and setting the pixel source to "SOLID_FILL".
> + *
> + * For information on the plane property, see 
> drm_plane_create_solid_fill_property()
> + *
> + * @r: Red color value of single pixel
> + * @g: Green color value of single pixel
> + * @b: Blue color value of single pixel
> + * @pad: padding

Document that padding must be zero, and ensure userspace obeys that. If
there is ever need to re-purpose the pad field, requiring it to be zero
today makes re-purposing possible.

Alternatively, if it is likely that it might be used as alpha if
alpha-ful format is added, then it would make more sense to require it
to be 0x instead of zero. Then the kernel could internally
interpret it as alpha always without special-casing zero. Or, it could
be straight out called "alpha" to begin with, but document and verify
that it must be set to 0x which means opaque.

> + */
> +struct drm_mode_solid_fill {
> + __u32 r;
> + __u32 g;
> + __u32 b;
> + __u32 pad;
> +};
> +
> +
>  struct drm_mode_card_res {
>   __u64 fb_id_ptr;
>   __u64 crtc_id_ptr;
> 

Looking good.


Thanks,
pq


pgpPsF6HPVCrt.pgp
Description: OpenPGP digital signature


Re: [PATCH RFC v6 03/10] drm: Add solid fill pixel source

2023-08-29 Thread Pekka Paalanen
On Mon, 28 Aug 2023 17:05:09 -0700
Jessica Zhang  wrote:

> Add "SOLID_FILL" as a valid pixel source. If the pixel_source property is
> set to "SOLID_FILL", it will display data from the drm_plane "solid_fill"
> blob property.
> 
> Reviewed-by: Dmitry Baryshkov 
> Signed-off-by: Jessica Zhang 
> ---
>  drivers/gpu/drm/drm_blend.c | 10 +-
>  include/drm/drm_plane.h |  1 +
>  2 files changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/drm_blend.c b/drivers/gpu/drm/drm_blend.c
> index 273021cc21c8..1016a206ca0c 100644
> --- a/drivers/gpu/drm/drm_blend.c
> +++ b/drivers/gpu/drm/drm_blend.c
> @@ -200,6 +200,9 @@
>   *   "FB":
>   *   Framebuffer source set by the "FB_ID" property.
>   *
> + *   "SOLID_FILL":
> + *   Solid fill color source set by the "solid_fill" property.
> + *
>   * solid_fill:
>   *   solid_fill is set up with drm_plane_create_solid_fill_property(). It
>   *   contains pixel data that drivers can use to fill a plane.
> @@ -638,6 +641,7 @@ EXPORT_SYMBOL(drm_plane_create_blend_mode_property);
>  static const struct drm_prop_enum_list drm_pixel_source_enum_list[] = {
>   { DRM_PLANE_PIXEL_SOURCE_NONE, "NONE" },
>   { DRM_PLANE_PIXEL_SOURCE_FB, "FB" },
> + { DRM_PLANE_PIXEL_SOURCE_SOLID_FILL, "SOLID_FILL" },
>  };
>  
>  /**
> @@ -662,6 +666,9 @@ static const struct drm_prop_enum_list 
> drm_pixel_source_enum_list[] = {
>   * "FB":
>   *   Framebuffer pixel source
>   *
> + * "SOLID_FILL":
> + *   Solid fill color pixel source
> + *
>   * Returns:
>   * Zero on success, negative errno on failure.
>   */
> @@ -671,7 +678,8 @@ int drm_plane_create_pixel_source_property(struct 
> drm_plane *plane,
>   struct drm_device *dev = plane->dev;
>   struct drm_property *prop;
>   static const unsigned int valid_source_mask = 
> BIT(DRM_PLANE_PIXEL_SOURCE_FB) |
> -   
> BIT(DRM_PLANE_PIXEL_SOURCE_NONE);
> +   
> BIT(DRM_PLANE_PIXEL_SOURCE_NONE) |
> +   
> BIT(DRM_PLANE_PIXEL_SOURCE_SOLID_FILL);
>   int i;
>  
>   /* FB is supported by default */
> diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
> index a38e18bfb43e..49995c4be2ab 100644
> --- a/include/drm/drm_plane.h
> +++ b/include/drm/drm_plane.h
> @@ -43,6 +43,7 @@ enum drm_scaling_filter {
>  enum drm_plane_pixel_source {
>   DRM_PLANE_PIXEL_SOURCE_NONE,
>   DRM_PLANE_PIXEL_SOURCE_FB,
> + DRM_PLANE_PIXEL_SOURCE_SOLID_FILL,
>   DRM_PLANE_PIXEL_SOURCE_MAX
>  };
>  
> 

This UAPI:
Acked-by: Pekka Paalanen 


Thanks,
pq


pgpiGlZwworr_.pgp
Description: OpenPGP digital signature


Re: [PATCH RFC v6 05/10] drm/atomic: Add solid fill data to plane state dump

2023-08-29 Thread Pekka Paalanen
On Mon, 28 Aug 2023 17:05:11 -0700
Jessica Zhang  wrote:

> Add solid_fill property data to the atomic plane state dump.
> 
> Signed-off-by: Jessica Zhang 
> ---
>  drivers/gpu/drm/drm_atomic.c | 4 
>  drivers/gpu/drm/drm_plane.c  | 8 
>  include/drm/drm_plane.h  | 3 +++
>  3 files changed, 15 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
> index bcecb64ccfad..3cb599b3304a 100644
> --- a/drivers/gpu/drm/drm_atomic.c
> +++ b/drivers/gpu/drm/drm_atomic.c
> @@ -717,6 +717,10 @@ static void drm_atomic_plane_print_state(struct 
> drm_printer *p,
>   drm_printf(p, "\tfb=%u\n", state->fb ? state->fb->base.id : 0);
>   if (state->fb)
>   drm_framebuffer_print_info(p, 2, state->fb);
> + drm_printf(p, "\tsolid_fill=%u\n",
> + state->solid_fill_blob ? 
> state->solid_fill_blob->base.id : 0);
> + if (state->solid_fill_blob)
> + drm_plane_solid_fill_print_info(p, 2, state);
>   drm_printf(p, "\tcrtc-pos=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&dest));
>   drm_printf(p, "\tsrc-pos=" DRM_RECT_FP_FMT "\n", DRM_RECT_FP_ARG(&src));
>   drm_printf(p, "\trotation=%x\n", state->rotation);
> diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
> index 559d101162ba..6244b622a21a 100644
> --- a/drivers/gpu/drm/drm_plane.c
> +++ b/drivers/gpu/drm/drm_plane.c
> @@ -1495,6 +1495,14 @@ __drm_plane_get_damage_clips(const struct 
> drm_plane_state *state)
>   state->fb_damage_clips->data : NULL);
>  }
>  
> +void drm_plane_solid_fill_print_info(struct drm_printer *p, unsigned int 
> indent,
> +  const struct drm_plane_state *state)
> +{
> + drm_printf_indent(p, indent, "r=0x%x\n", state->solid_fill.r);
> + drm_printf_indent(p, indent, "g=0x%x\n", state->solid_fill.g);
> + drm_printf_indent(p, indent, "b=0x%x\n", state->solid_fill.b);

I'd recommend %08x format, so that leading zeroes are explicit. That
makes it easier to see the difference between e.g. 0x and
0x0fff.


Thanks,
pq

> +}
> +
>  /**
>   * drm_plane_get_damage_clips - Returns damage clips.
>   * @state: Plane state.
> diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
> index 49995c4be2ab..a58f84b6bd5e 100644
> --- a/include/drm/drm_plane.h
> +++ b/include/drm/drm_plane.h
> @@ -1001,6 +1001,9 @@ drm_plane_get_damage_clips_count(const struct 
> drm_plane_state *state);
>  struct drm_mode_rect *
>  drm_plane_get_damage_clips(const struct drm_plane_state *state);
>  
> +void drm_plane_solid_fill_print_info(struct drm_printer *p, unsigned int 
> indent,
> +  const struct drm_plane_state *state);
> +
>  int drm_plane_create_scaling_filter_property(struct drm_plane *plane,
>unsigned int supported_filters);
>  
> 



pgpwd_eAngZBu.pgp
Description: OpenPGP digital signature


Re: [PATCH RFC v6 07/10] drm/atomic: Loosen FB atomic checks

2023-08-29 Thread Pekka Paalanen
On Mon, 28 Aug 2023 17:05:13 -0700
Jessica Zhang  wrote:

> Loosen the requirements for atomic and legacy commit so that, in cases
> where pixel_source != FB, the commit can still go through.
> 
> This includes adding framebuffer NULL checks in other areas to account for
> FB being NULL when non-FB pixel sources are enabled.
> 
> To disable a plane, the pixel_source must be NONE or the FB must be NULL
> if pixel_source == FB.
> 
> Signed-off-by: Jessica Zhang 
> ---
>  drivers/gpu/drm/drm_atomic.c| 20 +++-
>  drivers/gpu/drm/drm_atomic_helper.c | 36 
>  include/drm/drm_atomic_helper.h |  4 ++--
>  include/drm/drm_plane.h | 29 +
>  4 files changed, 62 insertions(+), 27 deletions(-)

...

> diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
> index a58f84b6bd5e..4c5b7bcdb25c 100644
> --- a/include/drm/drm_plane.h
> +++ b/include/drm/drm_plane.h
> @@ -992,6 +992,35 @@ static inline struct drm_plane *drm_plane_find(struct 
> drm_device *dev,
>  #define drm_for_each_plane(plane, dev) \
>   list_for_each_entry(plane, &(dev)->mode_config.plane_list, head)
>  
> +/**
> + * drm_plane_solid_fill_enabled - Check if solid fill is enabled on plane
> + * @state: plane state
> + *
> + * Returns:
> + * Whether the plane has been assigned a solid_fill_blob
> + */
> +static inline bool drm_plane_solid_fill_enabled(struct drm_plane_state 
> *state)
> +{
> + if (!state)
> + return false;
> + return state->pixel_source == DRM_PLANE_PIXEL_SOURCE_SOLID_FILL && 
> state->solid_fill_blob;
> +}
> +
> +static inline bool drm_plane_has_visible_data(const struct drm_plane_state 
> *state)
> +{
> + switch (state->pixel_source) {
> + case DRM_PLANE_PIXEL_SOURCE_NONE:
> + return false;
> + case DRM_PLANE_PIXEL_SOURCE_SOLID_FILL:
> + return state->solid_fill_blob != NULL;

This reminds me, new UAPI docs did not say what the requirements are for
choosing solid fill pixel source. Is the atomic commit rejected if
pixel source is solid fill, but solid_fill property has no blob?

This should be doc'd.


Thanks,
pq

> + case DRM_PLANE_PIXEL_SOURCE_FB:
> + default:
> + WARN_ON(state->pixel_source != DRM_PLANE_PIXEL_SOURCE_FB);
> + }
> +
> + return state->fb != NULL;
> +}
> +
>  bool drm_any_plane_has_format(struct drm_device *dev,
> u32 format, u64 modifier);
>  
> 



pgpFudiMpyD69.pgp
Description: OpenPGP digital signature


Re: [PATCH RFC v6 02/10] drm: Introduce solid fill DRM plane property

2023-08-29 Thread Sebastian Wick
On Mon, Aug 28, 2023 at 05:05:08PM -0700, Jessica Zhang wrote:
> Document and add support for solid_fill property to drm_plane. In
> addition, add support for setting and getting the values for solid_fill.
> 
> To enable solid fill planes, userspace must assign a property blob to
> the "solid_fill" plane property containing the following information:
> 
> struct drm_mode_solid_fill {
>   u32 r, g, b;
> };
> 
> Signed-off-by: Jessica Zhang 
> ---
>  drivers/gpu/drm/drm_atomic_state_helper.c |  9 
>  drivers/gpu/drm/drm_atomic_uapi.c | 26 ++
>  drivers/gpu/drm/drm_blend.c   | 30 ++
>  include/drm/drm_blend.h   |  1 +
>  include/drm/drm_plane.h   | 36 
> +++
>  include/uapi/drm/drm_mode.h   | 24 +
>  6 files changed, 126 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c 
> b/drivers/gpu/drm/drm_atomic_state_helper.c
> index 01638c51ce0a..86fb876efbe6 100644
> --- a/drivers/gpu/drm/drm_atomic_state_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_state_helper.c
> @@ -254,6 +254,11 @@ void __drm_atomic_helper_plane_state_reset(struct 
> drm_plane_state *plane_state,
>   plane_state->pixel_blend_mode = DRM_MODE_BLEND_PREMULTI;
>   plane_state->pixel_source = DRM_PLANE_PIXEL_SOURCE_FB;
>  
> + if (plane_state->solid_fill_blob) {
> + drm_property_blob_put(plane_state->solid_fill_blob);
> + plane_state->solid_fill_blob = NULL;
> + }
> +
>   if (plane->color_encoding_property) {
>   if (!drm_object_property_get_default_value(&plane->base,
>  
> plane->color_encoding_property,
> @@ -336,6 +341,9 @@ void __drm_atomic_helper_plane_duplicate_state(struct 
> drm_plane *plane,
>   if (state->fb)
>   drm_framebuffer_get(state->fb);
>  
> + if (state->solid_fill_blob)
> + drm_property_blob_get(state->solid_fill_blob);
> +
>   state->fence = NULL;
>   state->commit = NULL;
>   state->fb_damage_clips = NULL;
> @@ -385,6 +393,7 @@ void __drm_atomic_helper_plane_destroy_state(struct 
> drm_plane_state *state)
>   drm_crtc_commit_put(state->commit);
>  
>   drm_property_blob_put(state->fb_damage_clips);
> + drm_property_blob_put(state->solid_fill_blob);
>  }
>  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 454f980e16c9..1cae596ab693 100644
> --- a/drivers/gpu/drm/drm_atomic_uapi.c
> +++ b/drivers/gpu/drm/drm_atomic_uapi.c
> @@ -316,6 +316,20 @@ drm_atomic_set_crtc_for_connector(struct 
> drm_connector_state *conn_state,
>  }
>  EXPORT_SYMBOL(drm_atomic_set_crtc_for_connector);
>  
> +static void drm_atomic_set_solid_fill_prop(struct drm_plane_state *state)
> +{
> + struct drm_mode_solid_fill *user_info;
> +
> + if (!state->solid_fill_blob)
> + return;
> +
> + user_info = (struct drm_mode_solid_fill *)state->solid_fill_blob->data;
> +
> + state->solid_fill.r = user_info->r;
> + state->solid_fill.g = user_info->g;
> + state->solid_fill.b = user_info->b;
> +}
> +
>  static void set_out_fence_for_crtc(struct drm_atomic_state *state,
>  struct drm_crtc *crtc, s32 __user *fence_ptr)
>  {
> @@ -546,6 +560,15 @@ static int drm_atomic_plane_set_property(struct 
> drm_plane *plane,
>   state->src_h = val;
>   } else if (property == plane->pixel_source_property) {
>   state->pixel_source = val;
> + } else if (property == plane->solid_fill_property) {
> + ret = drm_atomic_replace_property_blob_from_id(dev,
> + &state->solid_fill_blob,
> + val, sizeof(struct drm_mode_solid_fill),
> + -1, &replaced);
> + if (ret)
> + return ret;
> +
> + drm_atomic_set_solid_fill_prop(state);
>   } else if (property == plane->alpha_property) {
>   state->alpha = val;
>   } else if (property == plane->blend_mode_property) {
> @@ -620,6 +643,9 @@ drm_atomic_plane_get_property(struct drm_plane *plane,
>   *val = state->src_h;
>   } else if (property == plane->pixel_source_property) {
>   *val = state->pixel_source;
> + } else if (property == plane->solid_fill_property) {
> + *val = state->solid_fill_blob ?
> + state->solid_fill_blob->base.id : 0;
>   } else if (property == plane->alpha_property) {
>   *val = state->alpha;
>   } else if (property == plane->blend_mode_property) {
> diff --git a/drivers/gpu/drm/drm_blend.c b/drivers/gpu/drm/drm_blend.c
> index c3c57bae06b7..273021cc21c8 100644
> --- a/drivers/gpu/drm/drm_blend.c
> +++ b/drivers/gpu/drm/drm_blend.c

Re: [PATCH RFC v6 00/10] Support for Solid Fill Planes

2023-08-29 Thread Sebastian Wick
On Mon, Aug 28, 2023 at 05:05:06PM -0700, Jessica Zhang wrote:
> Some drivers support hardware that have optimizations for solid fill
> planes. This series aims to expose these capabilities to userspace as
> some compositors have a solid fill flag (ex. SOLID_COLOR in the Android
> hardware composer HAL) that can be set by apps like the Android Gears
> app.
> 
> In order to expose this capability to userspace, this series will:
> 
> - Introduce solid_fill and pixel_source properties to allow userspace to
>   toggle between FB and solid fill sources
> - Loosen NULL FB checks within the DRM atomic commit callstack to allow
>   for NULL FB when solid fill is enabled.
> - Add NULL FB checks in methods where FB was previously assumed to be
>   non-NULL
> - Have MSM DPU driver use drm_plane_state.solid_fill instead of
>   dpu_plane_state.color_fill
> 
> Note: The solid fill planes feature depends on both the solid_fill *and*
> pixel_source properties.
> 
> To use this feature, userspace can set the solid_fill property to a blob
> containing the appropriate version number and solid fill color (in
> RGB323232 format) and and setting the pixel_source property to
> DRM_PLANE_PIXEL_SOURCE_COLOR. This will disable memory fetch and the
> resulting plane will display the color specified by the solid_fill blob.
> 
> Currently, there's only one version of the solid_fill blob property.
> However if other drivers want to support a similar feature, but require
> more than just the solid fill color, they can extend this feature by
> creating additional versions of the drm_solid_fill struct.
> 
> This 2 property approach was chosen because passing in a special 1x1 FB
> with the necessary color information would have unecessary overhead that
> does not reflect the behavior of the solid fill feature. In addition,
> assigning the solid fill blob to FB_ID would require loosening some core
> drm_property checks that might cause unwanted side effects elsewhere.

The cover letter is a bit outdated by now. Anyway, with Pekkas issues
addressed the core drm parts are

Acked-by: Sebastian Wick 
 
> ---
> Changes in v6:
> - Have _dpu_plane_color_fill() take in a single ABGR color instead
>   of having separate alpha and BGR color parameters (Dmitry)
> - Drop plane->state->pixel_source != DRM_PLANE_PIXEL_SOURCE_FB check
>   in SetPlane ioctl (Dmitry)
> - Add DRM_PLANE_PIXEL_SOURCE_NONE as a default pixel source (Sebastian)
> - Dropped versioning from solid fill property blob (Dmitry)
> - Use DRM_ENUM_NAME_FN (Dmitry)
> - Use drm_atomic_replace_property_blob_from_id() (Dmitry)
> - drm_atomic_check_fb -> drm_atomic_plane_check_fb (Dmitry)
> - Group redundant NULL FB checks (Dmitry)
> - Squashed drm_plane_needs_disable() implementation with 
>   DRM_PLANE_PIXEL_SOURCE_NONE declaration (Sebastian)
> - Add comment to support RGBA solid fill color in the future (Dmitry)
> - Link to v5: 
> https://lore.kernel.org/r/20230728-solid-fill-v5-0-053dbefa9...@quicinc.com
> 
> Changes in v5:
> - Added support for PIXEL_SOURCE_NONE (Sebastian)
> - Added WARN_ON() in drm_plane_has_visible_data() if pixel_source isn't
>   set (Dmitry)
> - Added debugfs support for both properties (Dmitry)
> - Corrected u32 to u8 conversion (Pekka)
> - Moved drm_solid_fill_info struct and related documentation to
>   include/uapi (Pekka)
> - Changed drm_solid_fill_info.version to __u32 for data alignment (Pekka)
> - Added more detailed UAPI and kernel documentation (Pekka)
> - Reordered patch series so that the pixel_source property is introduced
>   before solid_fill (Dmitry)
> - Fixed inconsistent ABGR/RGBA format declaration (Pekka)
> - Reset pixel_source to FB in drm_mode_setplane() (Dmitry)
> - Rename supported_sources to extra_sources (Dmitry)
> - Only destroy old solid_fill blob state if new state is valid (Pekka)
> - Link to v4: 
> https://lore.kernel.org/r/20230404-solid-fill-v4-0-f4ec0caa7...@quicinc.com
> 
> Changes in v4:
> - Rebased onto latest kernel
> - Reworded cover letter for clarity (Dmitry)
> - Reworded commit messages for clarity
> - Split existing changes into smaller commits
> - Added pixel_source enum property (Dmitry, Pekka, Ville)
> - Updated drm-kms comment docs with pixel_source and solid_fill
>   properties (Dmitry)
> - Inlined drm_atomic_convert_solid_fill_info() (Dmitry)
> - Passed in plane state alpha value to _dpu_plane_color_fill_pipe()
> - Link to v3: 
> https://lore.kernel.org/r/20230104234036.636-1-quic_jessz...@quicinc.com
> 
> Changes in v3:
> - Fixed some logic errors in atomic checks (Dmitry)
> - Introduced drm_plane_has_visible_data() and drm_atomic_check_fb() helper
>   methods (Dmitry)
> - Fixed typo in drm_solid_fill struct documentation
> - Created drm_plane_has_visible_data() helper and corrected CRTC and FB
>   NULL-check logic (Dmitry)
> - Merged `if (fb)` blocks in drm_atomic_plane_check() and abstracted
>   them into helper method (Dmitry)
> - Inverted `if (solid_fill_enabled) else if (fb)` check order (Dmitry)
> 

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

2023-08-29 Thread Uma Shankar
Introduction


Modern hardwares have various color processing capabilities both
at pre-blending and post-blending phases in the color pipeline.
The current drm implementation exposes only the post-blending
color hardware blocks. Support for pre-blending hardware is missing.
There are multiple use cases where pre-blending color hardware will
be useful:
a) Linearization of input buffers encoded in various transfer
   functions.
b) Color Space conversion
c) Tone mapping
d) Frame buffer format conversion
e) Non-linearization of buffer(apply transfer function)
f) 3D Luts

and other miscellaneous color operations.

Hence, there is a need to expose the color capabilities of the hardware
to user-space. This will help userspace/middleware to use display
hardware for color processing and blending instead of doing it through
GPU shaders.


Work done so far and relevant references


Some implementation is done by Intel and AMD/Igalia to address the same.
Broad consensus is there that we need a generic API at drm core to suffice
the use case of various HW vendors. Below are the links capturing the
discussion so far.

Intel's Plane Color Implementation: 
https://patchwork.freedesktop.org/series/90825/
AMD's Plane Color Implementation: 
https://patchwork.freedesktop.org/series/116862/


Hackfest conclusions


HDR/Color Hackfest was organised by Redhat to bring all the industry 
stakeholders
together and converge on a common uapi expectations. Participants from Intel, 
AMD,
Nvidia, Collabora, Redhat, Igalia and other prominent user-space developers and
maintainers.

Discussions happened on the uapi expectations, opens, nature of hardware of 
multiple
hardware vendors, challenges in generalizing the same and the path forward. 
Consensus
was made that drm core should implement descriptive APIs and not go with 
prescriptive
APIs. DRM core should just expose the hardware capabilities; enabling, 
customizing and
programming the same should be done by the user-space. Driver should just honor
the user space request without doing any operations internally.

Thanks to Simon Ser, for nicely documenting the design consensus and an UAPI RFC
which can be referred to here:

https://lore.kernel.org/dri-devel/QMers3awXvNCQlyhWdTtsPwkp5ie9bze_hD5nAccFW7a_RXlWjYB7MoUW_8CKLT2bSQwIXVi5H6VULYIxCdgvryZoAoJnC5lZgyK1QWn488=@emersion.fr/


Design considerations
=

Following are the important aspects taken into account while designing the 
current RFC
proposal:

1. Individual HW blocks can be muxed. (e.g. out of two HW blocks only 
one can be used)
2. Position of the HW block in the pipeline can be programmable
3. LUTs can be one dimentional or three dimentional
4. Number of LUT entries can vary across platforms
5. Precision of LUT entries can vary across platforms
6. Distribution of LUT entries may vary. e.g Mutli-segmented, 
Logarithmic,
   Piece-Wise Linear(PWL) etc
7. There can be parameterized/non-parameterized fixed function HW 
blocks.
   e.g. Just a hardware bit, to convert from one color space to another.
8. Custom non-standard HW implementation.
9. Leaving scope for some vendor defined pescriptive implementation if 
required.
10.Scope to handle any modification in hardware as technology evolves

The current proposal takes into account the above considerations while keeping 
the implementation
as generic as possible leaving scope for future additions or modifications.
 
This proposal is also in line to the details mentioned by Simon's RFC covering 
all
the aspects discussed in hackfest.


Outline of the implementation


Each Color Hardware block will be represented by a data structure drm_color_op.
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.

In this proposal, a color pipeline is represented as an array of
struct drm_color_op. For individual color operation, we add blobs to advertise
the capability of the particular Hardware block.

This color pipeline is then packaged within a blob for the user space to
retrieve it.

To advertise the available color pipelines, an immutable ENUM property
"GET_COLOR_PIPELINE" is introduced. 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.

Once the user space decides on a color pipeline, it can set the pipeline and
the corresponding data for the hardware blocks within the pipeline with
the BLOB property "SET_COLOR_PIPELINE".

Refer to Documentation/gpu/rfc/plane_color_pipe

[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;
+
+   /**
+* @color_mgmt_changed: Plane color pipeline state has changed
+* Used by the atomic helpers and
+* dri

[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
+* individual color blobs are replaced. Hence, reset

[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 << 24,
+   .min = 0, .max = (7 << 24),
+   },
+};
+
 void intel_color_crtc_init(struct intel_crtc *crtc)
 {

[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 void xelpd_plane_load_luts(const struct drm_plane_state *plane_state)
 {
const st

[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),
+ pre_csc_lut[i++].green);
+   } else {
+   for (i = 0; i < lut_size; i++) {
+ 

[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 struct drm_plane_state *plane_state);
 #endif /* __INTEL_COLOR_H__ */
diff --git a/drivers/gpu/drm/i915/display/skl_u

[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 struct intel_color_funcs xelpd_color_funcs = 
{
.lut_equal = icl_lut_equal,
.read_csc = icl_read_csc,
.load_plane_luts = xelpd_plane_load_luts,
+   .load_pla

[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_property_create_blob(plane->dev,
+  sizeof(dummy_3d_lut_ra

[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



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

2023-08-29 Thread Harry Wentland

+CC Naseer and Chris, FYI

See https://patchwork.freedesktop.org/series/123024/ for whole series.

On 2023-08-29 12:03, Uma Shankar wrote:

Introduction


Modern hardwares have various color processing capabilities both
at pre-blending and post-blending phases in the color pipeline.
The current drm implementation exposes only the post-blending
color hardware blocks. Support for pre-blending hardware is missing.
There are multiple use cases where pre-blending color hardware will
be useful:
a) Linearization of input buffers encoded in various transfer
   functions.
b) Color Space conversion
c) Tone mapping
d) Frame buffer format conversion
e) Non-linearization of buffer(apply transfer function)
f) 3D Luts

and other miscellaneous color operations.

Hence, there is a need to expose the color capabilities of the hardware
to user-space. This will help userspace/middleware to use display
hardware for color processing and blending instead of doing it through
GPU shaders.



Thanks, Uma, for sending this. I've been working on something similar
but you beat me to it. :)



Work done so far and relevant references


Some implementation is done by Intel and AMD/Igalia to address the same.
Broad consensus is there that we need a generic API at drm core to suffice
the use case of various HW vendors. Below are the links capturing the
discussion so far.

Intel's Plane Color Implementation: 
https://patchwork.freedesktop.org/series/90825/
AMD's Plane Color Implementation: 
https://patchwork.freedesktop.org/series/116862/


Hackfest conclusions


HDR/Color Hackfest was organised by Redhat to bring all the industry 
stakeholders
together and converge on a common uapi expectations. Participants from Intel, 
AMD,
Nvidia, Collabora, Redhat, Igalia and other prominent user-space developers and
maintainers.

Discussions happened on the uapi expectations, opens, nature of hardware of 
multiple
hardware vendors, challenges in generalizing the same and the path forward. 
Consensus
was made that drm core should implement descriptive APIs and not go with 
prescriptive
APIs. DRM core should just expose the hardware capabilities; enabling, 
customizing and
programming the same should be done by the user-space. Driver should just honor
the user space request without doing any operations internally.

Thanks to Simon Ser, for nicely documenting the design consensus and an UAPI RFC
which can be referred to here:

https://lore.kernel.org/dri-devel/QMers3awXvNCQlyhWdTtsPwkp5ie9bze_hD5nAccFW7a_RXlWjYB7MoUW_8CKLT2bSQwIXVi5H6VULYIxCdgvryZoAoJnC5lZgyK1QWn488=@emersion.fr/


Design considerations
=

Following are the important aspects taken into account while designing the 
current RFC
proposal:

1. Individual HW blocks can be muxed. (e.g. out of two HW blocks only 
one can be used)
2. Position of the HW block in the pipeline can be programmable
3. LUTs can be one dimentional or three dimentional
4. Number of LUT entries can vary across platforms
5. Precision of LUT entries can vary across platforms
6. Distribution of LUT entries may vary. e.g Mutli-segmented, 
Logarithmic,
   Piece-Wise Linear(PWL) etc
7. There can be parameterized/non-parameterized fixed function HW 
blocks.
   e.g. Just a hardware bit, to convert from one color space to another.
8. Custom non-standard HW implementation.
9. Leaving scope for some vendor defined pescriptive implementation if 
required.
10.Scope to handle any modification in hardware as technology evolves

The current proposal takes into account the above considerations while keeping 
the implementation
as generic as possible leaving scope for future additions or modifications.
  
This proposal is also in line to the details mentioned by Simon's RFC covering all

the aspects discussed in hackfest.


Outline of the implementation


Each Color Hardware block will be represented by a data structure drm_color_op.
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.


Who is doing the arranging of color operations? IMO a driver should 
define one or more respective pipelines that can be selected by 
userspace. This seems to be what you're talking about after (I haven't 
reviewed the whole thing yet). Might be best to drop this sentence or to 
add clarifications in order to avoid confusion.




In this proposal, a color pipeline is represented as an array of
struct drm_color_op. For individual color operation, we add blobs to advertise
the capability of the particular Hardware block.

This color pipeline is then p

Re: [RFC 01/33] drm/doc/rfc: Add RFC document for proposed Plane Color Pipeline

2023-08-29 Thread Harry Wentland




On 2023-08-29 12:03, Uma Shankar wrote:

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│   │ │
+