All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH v2 0/6] A drm_plane API to support HDR planes
@ 2021-05-14 21:07 ` Harry Wentland
  0 siblings, 0 replies; 18+ messages in thread
From: Harry Wentland @ 2021-05-14 21:07 UTC (permalink / raw)
  To: amd-gfx, dri-devel, ppaalanen, sebastian, mcasas
  Cc: Deepak.Sharma, Krunoslav.Kovac, Shashank.Sharma, Shirish.S,
	hersenxs.wu, Vitaly.Prosyak, laurentiu.palcu, Bhawanpreet.Lakha,
	Nicholas.Kazlauskas

We are looking to enable HDR support for a couple of single-plane and
multi-plane scenarios. To do this effectively we recommend new interfaces
to drm_plane. The first patch gives a bit of background on HDR and why we
propose these interfaces.

v2:
 * Moved RFC from cover letter to kernel doc (Daniel Vetter)
 * Created new color space property instead of abusing
   color_encoding property (Ville)
 * Elaborated on need for named transfer functions
 * Expanded on reason for SDR luminance definition
 * Dropped 'color' from transfer function naming
 * Added output_transfer_function on crtc

Bhawanpreet Lakha (3):
  drm/color: Add transfer functions for HDR/SDR on drm_plane
  drm/color: Add sdr boost property
  drm/color: Add color space plane property

Harry Wentland (3):
  drm/doc: Color Management and HDR10 RFC
  drm/color: Add output transfer function to crtc
  drm/amd/display: reformat YCbCr-RGB conversion matrix

 Documentation/gpu/rfc/hdr-wide-gamut.rst      | 416 ++++++++++++++++++
 Documentation/gpu/rfc/index.rst               |   4 +
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  17 +-
 drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h   |  28 +-
 .../gpu/drm/arm/display/komeda/komeda_crtc.c  |   7 +-
 .../gpu/drm/arm/display/komeda/komeda_plane.c |   6 +-
 drivers/gpu/drm/arm/malidp_crtc.c             |   7 +-
 drivers/gpu/drm/arm/malidp_planes.c           |   6 +-
 drivers/gpu/drm/armada/armada_crtc.c          |   5 +-
 drivers/gpu/drm/armada/armada_overlay.c       |   6 +-
 .../gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c    |   7 +-
 drivers/gpu/drm/drm_atomic_uapi.c             |   8 +
 drivers/gpu/drm/drm_color_mgmt.c              | 177 +++++++-
 drivers/gpu/drm/i915/display/intel_color.c    |  11 +-
 drivers/gpu/drm/i915/display/intel_color.h    |   2 +-
 drivers/gpu/drm/i915/display/intel_crtc.c     |   4 +-
 drivers/gpu/drm/i915/display/intel_sprite.c   |   6 +-
 .../drm/i915/display/skl_universal_plane.c    |   6 +-
 drivers/gpu/drm/ingenic/ingenic-drm-drv.c     |   9 +-
 drivers/gpu/drm/mediatek/mtk_drm_crtc.c       |   8 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c      |   9 +-
 drivers/gpu/drm/nouveau/dispnv04/overlay.c    |   6 +-
 drivers/gpu/drm/nouveau/dispnv50/head.c       |  13 +-
 drivers/gpu/drm/omapdrm/omap_crtc.c           |  10 +-
 drivers/gpu/drm/omapdrm/omap_plane.c          |   6 +-
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c        |   7 +-
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c   |   5 +-
 drivers/gpu/drm/stm/ltdc.c                    |   8 +-
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c        |  10 +-
 drivers/gpu/drm/tidss/tidss_crtc.c            |   9 +-
 drivers/gpu/drm/tidss/tidss_plane.c           |  10 +-
 drivers/gpu/drm/vc4/vc4_crtc.c                |  16 +-
 include/drm/drm_color_mgmt.h                  |  49 ++-
 include/drm/drm_crtc.h                        |  20 +
 include/drm/drm_plane.h                       |  47 +-
 35 files changed, 905 insertions(+), 60 deletions(-)
 create mode 100644 Documentation/gpu/rfc/hdr-wide-gamut.rst

-- 
2.31.1


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [RFC PATCH v2 0/6] A drm_plane API to support HDR planes
@ 2021-05-14 21:07 ` Harry Wentland
  0 siblings, 0 replies; 18+ messages in thread
From: Harry Wentland @ 2021-05-14 21:07 UTC (permalink / raw)
  To: amd-gfx, dri-devel, ppaalanen, sebastian, mcasas
  Cc: Deepak.Sharma, aric.cyr, Krunoslav.Kovac, Shashank.Sharma,
	Harry Wentland, Shirish.S, hersenxs.wu, Vitaly.Prosyak,
	laurentiu.palcu, Bhawanpreet.Lakha, Nicholas.Kazlauskas,
	ville.syrjala

We are looking to enable HDR support for a couple of single-plane and
multi-plane scenarios. To do this effectively we recommend new interfaces
to drm_plane. The first patch gives a bit of background on HDR and why we
propose these interfaces.

v2:
 * Moved RFC from cover letter to kernel doc (Daniel Vetter)
 * Created new color space property instead of abusing
   color_encoding property (Ville)
 * Elaborated on need for named transfer functions
 * Expanded on reason for SDR luminance definition
 * Dropped 'color' from transfer function naming
 * Added output_transfer_function on crtc

Bhawanpreet Lakha (3):
  drm/color: Add transfer functions for HDR/SDR on drm_plane
  drm/color: Add sdr boost property
  drm/color: Add color space plane property

Harry Wentland (3):
  drm/doc: Color Management and HDR10 RFC
  drm/color: Add output transfer function to crtc
  drm/amd/display: reformat YCbCr-RGB conversion matrix

 Documentation/gpu/rfc/hdr-wide-gamut.rst      | 416 ++++++++++++++++++
 Documentation/gpu/rfc/index.rst               |   4 +
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  17 +-
 drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h   |  28 +-
 .../gpu/drm/arm/display/komeda/komeda_crtc.c  |   7 +-
 .../gpu/drm/arm/display/komeda/komeda_plane.c |   6 +-
 drivers/gpu/drm/arm/malidp_crtc.c             |   7 +-
 drivers/gpu/drm/arm/malidp_planes.c           |   6 +-
 drivers/gpu/drm/armada/armada_crtc.c          |   5 +-
 drivers/gpu/drm/armada/armada_overlay.c       |   6 +-
 .../gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c    |   7 +-
 drivers/gpu/drm/drm_atomic_uapi.c             |   8 +
 drivers/gpu/drm/drm_color_mgmt.c              | 177 +++++++-
 drivers/gpu/drm/i915/display/intel_color.c    |  11 +-
 drivers/gpu/drm/i915/display/intel_color.h    |   2 +-
 drivers/gpu/drm/i915/display/intel_crtc.c     |   4 +-
 drivers/gpu/drm/i915/display/intel_sprite.c   |   6 +-
 .../drm/i915/display/skl_universal_plane.c    |   6 +-
 drivers/gpu/drm/ingenic/ingenic-drm-drv.c     |   9 +-
 drivers/gpu/drm/mediatek/mtk_drm_crtc.c       |   8 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c      |   9 +-
 drivers/gpu/drm/nouveau/dispnv04/overlay.c    |   6 +-
 drivers/gpu/drm/nouveau/dispnv50/head.c       |  13 +-
 drivers/gpu/drm/omapdrm/omap_crtc.c           |  10 +-
 drivers/gpu/drm/omapdrm/omap_plane.c          |   6 +-
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c        |   7 +-
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c   |   5 +-
 drivers/gpu/drm/stm/ltdc.c                    |   8 +-
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c        |  10 +-
 drivers/gpu/drm/tidss/tidss_crtc.c            |   9 +-
 drivers/gpu/drm/tidss/tidss_plane.c           |  10 +-
 drivers/gpu/drm/vc4/vc4_crtc.c                |  16 +-
 include/drm/drm_color_mgmt.h                  |  49 ++-
 include/drm/drm_crtc.h                        |  20 +
 include/drm/drm_plane.h                       |  47 +-
 35 files changed, 905 insertions(+), 60 deletions(-)
 create mode 100644 Documentation/gpu/rfc/hdr-wide-gamut.rst

-- 
2.31.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [RFC PATCH v2 1/6] drm/doc: Color Management and HDR10 RFC
  2021-05-14 21:07 ` Harry Wentland
@ 2021-05-14 21:07   ` Harry Wentland
  -1 siblings, 0 replies; 18+ messages in thread
From: Harry Wentland @ 2021-05-14 21:07 UTC (permalink / raw)
  To: amd-gfx, dri-devel, ppaalanen, sebastian, mcasas
  Cc: Deepak.Sharma, Krunoslav.Kovac, Shashank.Sharma, Shirish.S,
	hersenxs.wu, Vitaly.Prosyak, laurentiu.palcu, Bhawanpreet.Lakha,
	Nicholas.Kazlauskas

Use the new DRM RFC doc section to capture the RFC previously only
described in the cover letter at
https://patchwork.freedesktop.org/series/89506/

Update the RFC based on feedback received:
 * don't use color_encoding property to define color space
 * expand on reason for SDR luminance definition
 * define input/output transfer functions for luminance space transforms,
   rather than defining the luminance space of an input directly

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
 Documentation/gpu/rfc/hdr-wide-gamut.rst | 416 +++++++++++++++++++++++
 Documentation/gpu/rfc/index.rst          |   4 +
 2 files changed, 420 insertions(+)
 create mode 100644 Documentation/gpu/rfc/hdr-wide-gamut.rst

diff --git a/Documentation/gpu/rfc/hdr-wide-gamut.rst b/Documentation/gpu/rfc/hdr-wide-gamut.rst
new file mode 100644
index 000000000000..132898668eac
--- /dev/null
+++ b/Documentation/gpu/rfc/hdr-wide-gamut.rst
@@ -0,0 +1,416 @@
+==============================
+HDR & Wide Color Gamut Support
+==============================
+
+.. role:: wy-text-strike
+
+ToDo
+====
+
+* :wy-text-strike:`Reformat as RST kerneldoc` - done
+* :wy-text-strike:`Don't use color_encoding for color_space definitions` - done
+* :wy-text-strike:`Update SDR luminance description and reasoning` - done
+* :wy-text-strike:`Clarify 3D LUT required for some color space transformations` - done
+* :wy-text-strike:`Highlight need for named color space and EOTF definitions` - done
+* :wy-text-strike:`Define transfer function API` - done
+* :wy-text-strike:`Draft upstream plan` - done
+* Reference to wayland and/or Chrome plans
+* Sketch view of HW pipeline for couple of HW implementations
+
+
+Upstream Plan
+=============
+
+* Reach consensus on DRM/KMS API
+* Implement support in amdgpu
+* Implement IGT tests
+* Add API support to Weston, ChromiumOS, or other canonical open-source project interested in HDR
+* Merge user-space
+* Merge kernel patches
+
+
+Introduction
+============
+
+We are looking to enable HDR support for a couple of single-plane and
+multi-plane scenarios. To do this effectively we recommend new interfaces
+to drm_plane. Below I'll give a bit of background on HDR and why we
+propose these interfaces.
+
+
+Overview and background
+=======================
+
+Defining a pixel's luminance
+----------------------------
+
+The luminance space of pixels in a framebuffer/plane presented to the
+display is not well defined in the DRM/KMS APIs. It is usually assumed to
+be in a 2.2 or 2.4 gamma space and has no mapping to an absolute luminance
+value; it is interpreted in relative terms.
+
+Luminance can be measured and described in absolute terms as candela
+per meter squared, or cd/m2, or nits. Even though a pixel value can be
+mapped to luminance in a linear fashion to do so without losing a lot of
+detail requires 16-bpc color depth. The reason for this is that human
+perception can distinguish roughly between a 0.5-1% luminance delta. A
+linear representation is suboptimal, wasting precision in the highlights
+and losing precision in the shadows.
+
+A gamma curve is a decent approximation to a human's perception of
+luminance, but the PQ (perceptual quantizer) function [1] improves on
+it. It also defines the luminance values in absolute terms, with the
+highest value being 10,000 nits and the lowest 0.0005 nits.
+
+Using a content that's defined in PQ space we can approximate the real
+world in a much better way.
+
+Here are some examples of real-life objects and their approximate
+luminance values:
+
+.. flat-table::
+   :header-rows: 1
+
+   * - Object
+     - Luminance in nits
+   
+   *  - Fluorescent light
+      - 10,000
+  
+   *  - Highlights
+      - 1,000 - sunlight
+ 
+   *  - White Objects
+      - 250 - 1,000
+   
+   *  - Typical Objects
+      - 1 - 250
+   
+   *  - Shadows
+      - 0.01 - 1
+   
+   *  - Ultra Blacks
+      - 0 - 0.0005
+
+Transfer functions
+------------------
+
+Traditionally we used the terms gamma and de-gamma to describe the
+encoding of a pixel's luminance value and the operation to transfer from
+a linear luminance space to the non-linear space used to encode the
+pixels. Since some newer encodings don't use a gamma curve I suggest
+we refer to non-linear encodings using the terms EOTF, and OETF[2], or
+simply as transfer function in general.
+
+The EOTF (Electro-Optical Transfer Function) describes how to transfer
+from an electrical signal to an optical signal. This was traditionally
+done by the de-gamma function.
+
+The OETF (Opto Electronic Transfer Function) describes how to transfer
+from an optical signal to an electronic signal. This was traditionally
+done by the gamma function.
+
+More generally we can name the transfer function describing the transform
+between scanout and blending space as the **input transfer function**, and
+the transfer function describing the transform from blending space to the
+output space as **output transfer function**.
+
+
+Mastering Luminances
+--------------------
+
+Even though we are able to describe the absolute luminance of a pixel
+using the PQ 2084 EOTF we are presented with physical limitations of the
+display technologies on the market today. Here are a few examples of
+luminance ranges of displays.
+
+.. flat-table::
+   :header-rows: 1
+
+   * - Display
+     - Luminance range in nits
+   
+   *  - Typical PC display
+      - 0.3 - 200
+  
+   *  - Excellent LCD HDTV
+      - 0.3 - 400
+ 
+   *  - HDR LCD w/ local dimming
+      - 0.05 - 1,500
+   
+Since no display can currently show the full 0.0005 to 10,000 nits
+luminance range of PQ the display will need to tone-map the HDR content,
+i.e to fit the content within a display's capabilities. To assist
+with tone-mapping HDR content is usually accompanied by a metadata
+that describes (among other things) the minimum and maximum mastering
+luminance, i.e. the maximum and minimum luminance of the display that
+was used to master the HDR content.
+
+The HDR metadata is currently defined on the drm_connector via the
+hdr_output_metadata blob property.
+
+It might be useful to define per-plane hdr metadata, as different planes
+might have been mastered differently.
+
+
+SDR Luminance
+-------------
+
+Traditional SDR content's maximum white luminance is not well defined.
+Some like to define it at 80 nits, others at 200 nits. It also depends
+to a large extent on the environmental viewing conditions. In practice
+this means that we need to define the maximum SDR white luminance, either
+in nits, or as a ratio.
+
+One Windows API defines it as a ratio against 80 nits:
+https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/dispmprt/ns-dispmprt-_dxgkarg_settargetadjustedcolorimetry2
+
+Another Windows API defines it as a nits value:
+https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/dispmprt/ns-dispmprt-_dxgkarg_settargetadjustedcolorimetry2
+
+The Wayland color management proposal uses Apple's definition of EDR as a
+ratio of the HDR range vs SDR range: 
+https://gitlab.freedesktop.org/swick/wayland-protocols/-/blob/color/unstable/color-management/color.rst#id8
+
+If a display's maximum HDR white level is correctly reported it is trivial
+to convert between all of the above representations of SDR white level. If
+it is not, defining SDR luminance as a nits value, or a ratio vs a fixed
+nits value is preferred, assuming we are blending in linear space.
+
+It is our experience that many HDR displays do not report maximum white
+level correctly
+
+
+Let There Be Color
+------------------
+
+So far we've only talked about luminance, ignoring colors altogether. Just
+like in the luminance space, traditionally the color space of display
+outputs has not been well defined. Similar to how an EOTF defines a
+mapping of pixel data to an absolute luminance value, the color space
+maps color information for each pixel onto the CIE 1931 chromaticity
+space. This can be thought of as a mapping to an absolute, real-life,
+color value.
+
+A color space is defined by its primaries and white point. The primaries
+and white point are expressed as coordinates in the CIE 1931 color
+space. Think of the red primary as the reddest red that can be displayed
+within the color space. Same for green and blue.
+
+Examples of color spaces are:
+
+.. flat-table::
+   :header-rows: 1
+
+   * - Color Space
+     - Description
+   
+   *  - BT 601
+      - similar to BT 709
+  
+   *  - BT 709
+      - used by sRGB content; ~53% of BT 2020
+ 
+   *  - DCI-P3
+      - used by most HDR displays; ~72% of BT 2020
+
+   *  - BT 2020
+      - standard for most HDR content
+
+
+
+Color Primaries and White Point
+-------------------------------
+
+Just like displays can currently not represent the entire 0.0005 -
+10,000 nits HDR range of the PQ 2084 EOTF, they are currently not capable
+of representing the entire BT.2020 color Gamut. For this reason video
+content will often specify the color primaries and white point used to
+master the video, in order to allow displays to be able to map the image
+as best as possible onto the display's gamut.
+
+
+Displays and Tonemapping
+------------------------
+
+External displays are able to do their own tone and color mapping, based
+on the mastering luminance, color primaries, and white space defined in
+the HDR metadata.
+
+Some internal panels might not include the complex HW to do tone and color
+mapping on their own and will require the display driver to perform
+appropriate mapping.
+
+
+How are we solving the problem?
+===============================
+
+Input and Output Transfer functions
+-----------------------------------
+
+We define an input transfer function on drm_plane to describe the
+transform from framebuffer to blending space.
+
+We define an output transfer function on drm_crtc to describe the
+transform from blending space to display space.
+
+The transfer function can be a pre-defined function, such as PQ EOTF, or
+a custom LUT. A driver will be able to specify support for specific
+transfer functions, including custom ones.
+
+Defining the transfer function in this way allows us to support in on HW
+that uses ROMs to support these transforms, as well as on HW that use
+LUT definitions that are complex and don't map easily onto a standard LUT
+definition.
+
+We will not define per-plane LUTs in this patchset as the scope of our
+current work only deals with pre-defined transfer functions. This API has
+the flexibility to add custom 1D or 3D LUTs at a later date.
+
+In order to support the existing 1D de-gamma and gamma LUTs on the drm_crtc
+we will include a "custom 1D" enum value to indicate that the custom gamma and
+de-gamma 1D LUTs should be used.
+
+Possible transfer functions:
+
+.. flat-table::
+   :header-rows: 1
+
+   * - Transfer Function
+     - Description
+   
+   *  - Gamma 2.2
+      - a simple 2.2 gamma function
+  
+   *  - sRGB
+      - 2.4 gamma with small initial linear section
+ 
+   *  - PQ 2084
+      - SMPTE ST 2084; used for HDR video and allows for up to 10,000 nit support
+
+   *  - Linear
+      - Linear relationship between pixel value and luminance value
+
+   *  - Custom 1D
+      - Custom 1D de-gamma and gamma LUTs; one LUT per color
+
+   *  - Custom 3D
+      - Custom 3D LUT (to be defined)
+
+
+Describing SDR Luminance
+------------------------------
+
+Since many displays do no correctly advertise the HDR white level we
+propose to define the SDR white level in nits.
+
+We define a new drm_plane property to specify the white level of an SDR
+plane.
+
+
+Defining the color space
+------------------------
+
+We propose to add a new color space property to drm_plane to define a
+plane's color space.
+
+While some color space conversions can be performed with a simple color
+transformation matrix (CTM) others require a 3D LUT.
+
+
+Defining mastering color space and luminance
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ToDo
+
+
+
+Pixel Formats
+~~~~~~~~~~~~~
+
+The pixel formats, such as ARGB8888, ARGB2101010, P010, or FP16 are
+unrelated to color space and EOTF definitions. HDR pixels can be formatted
+in different ways but in order to not lose precision HDR content requires
+at least 10 bpc precision. For this reason ARGB2101010, P010, and FP16 are
+the obvious candidates for HDR. ARGB2101010 and P010 have the advantage
+of requiring only half the bandwidth as FP16, while FP16 has the advantage
+of enough precision to operate in a linear space, i.e. without EOTF.
+
+
+
+Use Cases
+=========
+
+RGB10 HDR plane - composited HDR video & desktop
+------------------------------------------------
+
+A single, composited plane of HDR content. The use-case is a video player
+on a desktop with the compositor owning the composition of SDR and HDR
+content. The content shall be PQ BT.2020 formatted. The drm_connector's
+hdr_output_metadata shall be set.
+
+
+P010 HDR video plane + RGB8 SDR desktop plane
+---------------------------------------------
+A normal 8bpc desktop plane, with a P010 HDR video plane underlayed. The
+HDR plane shall be PQ BT.2020 formatted. The desktop plane shall specify
+an SDR boost value. The drm_connector's hdr_output_metadata shall be set.
+
+
+One XRGB8888 SDR Plane - HDR output
+-----------------------------------
+
+In order to support a smooth transition we recommend an OS that supports
+HDR output to provide the hdr_output_metadata on the drm_connector to
+configure the output for HDR, even when the content is only SDR. This will
+allow for a smooth transition between SDR-only and HDR content. In this
+use-case the SDR max luminance value should be provided on the drm_plane.
+
+In DCN we will de-PQ or de-Gamma all input in order to blend in linear
+space. For SDR content we will also apply any desired boost before
+blending. After blending we will then re-apply the PQ EOTF and do RGB
+to YCbCr conversion if needed.
+
+FP16 HDR linear planes
+----------------------
+
+ToDo
+
+
+User Space
+==========
+
+Wayland
+-------
+
+ToDo
+
+
+ChromeOS Ozone
+--------------
+
+ToDo
+
+
+HW support
+==========
+
+ToDo, describe pipeline on a couple different HW platforms
+
+
+References
+==========
+
+* [1] https://en.wikipedia.org/wiki/High-dynamic-range_video#Perceptual_Quantizer
+* [2] https://en.wikipedia.org/wiki/Transfer_functions_in_imaging
+
+
+Further Reading
+===============
+
+* https://gitlab.freedesktop.org/swick/wayland-protocols/-/blob/color/unstable/color-management/color.rst
+* http://downloads.bbc.co.uk/rd/pubs/whp/whp-pdf-files/WHP309.pdf
+* https://app.spectracal.com/Documents/White%20Papers/HDR_Demystified.pdf
+
+
diff --git a/Documentation/gpu/rfc/index.rst b/Documentation/gpu/rfc/index.rst
index a8621f7dab8b..5c8eaf8bf587 100644
--- a/Documentation/gpu/rfc/index.rst
+++ b/Documentation/gpu/rfc/index.rst
@@ -15,3 +15,7 @@ host such documentation:
 
 * Once the code has landed move all the documentation to the right places in
   the main core, helper or driver sections.
+
+  .. toctree::
+
+  hdr-wide-gamut.rst
\ No newline at end of file
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [RFC PATCH v2 1/6] drm/doc: Color Management and HDR10 RFC
@ 2021-05-14 21:07   ` Harry Wentland
  0 siblings, 0 replies; 18+ messages in thread
From: Harry Wentland @ 2021-05-14 21:07 UTC (permalink / raw)
  To: amd-gfx, dri-devel, ppaalanen, sebastian, mcasas
  Cc: Deepak.Sharma, aric.cyr, Krunoslav.Kovac, Shashank.Sharma,
	Harry Wentland, Shirish.S, hersenxs.wu, Vitaly.Prosyak,
	laurentiu.palcu, Bhawanpreet.Lakha, Nicholas.Kazlauskas,
	ville.syrjala

Use the new DRM RFC doc section to capture the RFC previously only
described in the cover letter at
https://patchwork.freedesktop.org/series/89506/

Update the RFC based on feedback received:
 * don't use color_encoding property to define color space
 * expand on reason for SDR luminance definition
 * define input/output transfer functions for luminance space transforms,
   rather than defining the luminance space of an input directly

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
 Documentation/gpu/rfc/hdr-wide-gamut.rst | 416 +++++++++++++++++++++++
 Documentation/gpu/rfc/index.rst          |   4 +
 2 files changed, 420 insertions(+)
 create mode 100644 Documentation/gpu/rfc/hdr-wide-gamut.rst

diff --git a/Documentation/gpu/rfc/hdr-wide-gamut.rst b/Documentation/gpu/rfc/hdr-wide-gamut.rst
new file mode 100644
index 000000000000..132898668eac
--- /dev/null
+++ b/Documentation/gpu/rfc/hdr-wide-gamut.rst
@@ -0,0 +1,416 @@
+==============================
+HDR & Wide Color Gamut Support
+==============================
+
+.. role:: wy-text-strike
+
+ToDo
+====
+
+* :wy-text-strike:`Reformat as RST kerneldoc` - done
+* :wy-text-strike:`Don't use color_encoding for color_space definitions` - done
+* :wy-text-strike:`Update SDR luminance description and reasoning` - done
+* :wy-text-strike:`Clarify 3D LUT required for some color space transformations` - done
+* :wy-text-strike:`Highlight need for named color space and EOTF definitions` - done
+* :wy-text-strike:`Define transfer function API` - done
+* :wy-text-strike:`Draft upstream plan` - done
+* Reference to wayland and/or Chrome plans
+* Sketch view of HW pipeline for couple of HW implementations
+
+
+Upstream Plan
+=============
+
+* Reach consensus on DRM/KMS API
+* Implement support in amdgpu
+* Implement IGT tests
+* Add API support to Weston, ChromiumOS, or other canonical open-source project interested in HDR
+* Merge user-space
+* Merge kernel patches
+
+
+Introduction
+============
+
+We are looking to enable HDR support for a couple of single-plane and
+multi-plane scenarios. To do this effectively we recommend new interfaces
+to drm_plane. Below I'll give a bit of background on HDR and why we
+propose these interfaces.
+
+
+Overview and background
+=======================
+
+Defining a pixel's luminance
+----------------------------
+
+The luminance space of pixels in a framebuffer/plane presented to the
+display is not well defined in the DRM/KMS APIs. It is usually assumed to
+be in a 2.2 or 2.4 gamma space and has no mapping to an absolute luminance
+value; it is interpreted in relative terms.
+
+Luminance can be measured and described in absolute terms as candela
+per meter squared, or cd/m2, or nits. Even though a pixel value can be
+mapped to luminance in a linear fashion to do so without losing a lot of
+detail requires 16-bpc color depth. The reason for this is that human
+perception can distinguish roughly between a 0.5-1% luminance delta. A
+linear representation is suboptimal, wasting precision in the highlights
+and losing precision in the shadows.
+
+A gamma curve is a decent approximation to a human's perception of
+luminance, but the PQ (perceptual quantizer) function [1] improves on
+it. It also defines the luminance values in absolute terms, with the
+highest value being 10,000 nits and the lowest 0.0005 nits.
+
+Using a content that's defined in PQ space we can approximate the real
+world in a much better way.
+
+Here are some examples of real-life objects and their approximate
+luminance values:
+
+.. flat-table::
+   :header-rows: 1
+
+   * - Object
+     - Luminance in nits
+   
+   *  - Fluorescent light
+      - 10,000
+  
+   *  - Highlights
+      - 1,000 - sunlight
+ 
+   *  - White Objects
+      - 250 - 1,000
+   
+   *  - Typical Objects
+      - 1 - 250
+   
+   *  - Shadows
+      - 0.01 - 1
+   
+   *  - Ultra Blacks
+      - 0 - 0.0005
+
+Transfer functions
+------------------
+
+Traditionally we used the terms gamma and de-gamma to describe the
+encoding of a pixel's luminance value and the operation to transfer from
+a linear luminance space to the non-linear space used to encode the
+pixels. Since some newer encodings don't use a gamma curve I suggest
+we refer to non-linear encodings using the terms EOTF, and OETF[2], or
+simply as transfer function in general.
+
+The EOTF (Electro-Optical Transfer Function) describes how to transfer
+from an electrical signal to an optical signal. This was traditionally
+done by the de-gamma function.
+
+The OETF (Opto Electronic Transfer Function) describes how to transfer
+from an optical signal to an electronic signal. This was traditionally
+done by the gamma function.
+
+More generally we can name the transfer function describing the transform
+between scanout and blending space as the **input transfer function**, and
+the transfer function describing the transform from blending space to the
+output space as **output transfer function**.
+
+
+Mastering Luminances
+--------------------
+
+Even though we are able to describe the absolute luminance of a pixel
+using the PQ 2084 EOTF we are presented with physical limitations of the
+display technologies on the market today. Here are a few examples of
+luminance ranges of displays.
+
+.. flat-table::
+   :header-rows: 1
+
+   * - Display
+     - Luminance range in nits
+   
+   *  - Typical PC display
+      - 0.3 - 200
+  
+   *  - Excellent LCD HDTV
+      - 0.3 - 400
+ 
+   *  - HDR LCD w/ local dimming
+      - 0.05 - 1,500
+   
+Since no display can currently show the full 0.0005 to 10,000 nits
+luminance range of PQ the display will need to tone-map the HDR content,
+i.e to fit the content within a display's capabilities. To assist
+with tone-mapping HDR content is usually accompanied by a metadata
+that describes (among other things) the minimum and maximum mastering
+luminance, i.e. the maximum and minimum luminance of the display that
+was used to master the HDR content.
+
+The HDR metadata is currently defined on the drm_connector via the
+hdr_output_metadata blob property.
+
+It might be useful to define per-plane hdr metadata, as different planes
+might have been mastered differently.
+
+
+SDR Luminance
+-------------
+
+Traditional SDR content's maximum white luminance is not well defined.
+Some like to define it at 80 nits, others at 200 nits. It also depends
+to a large extent on the environmental viewing conditions. In practice
+this means that we need to define the maximum SDR white luminance, either
+in nits, or as a ratio.
+
+One Windows API defines it as a ratio against 80 nits:
+https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/dispmprt/ns-dispmprt-_dxgkarg_settargetadjustedcolorimetry2
+
+Another Windows API defines it as a nits value:
+https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/dispmprt/ns-dispmprt-_dxgkarg_settargetadjustedcolorimetry2
+
+The Wayland color management proposal uses Apple's definition of EDR as a
+ratio of the HDR range vs SDR range: 
+https://gitlab.freedesktop.org/swick/wayland-protocols/-/blob/color/unstable/color-management/color.rst#id8
+
+If a display's maximum HDR white level is correctly reported it is trivial
+to convert between all of the above representations of SDR white level. If
+it is not, defining SDR luminance as a nits value, or a ratio vs a fixed
+nits value is preferred, assuming we are blending in linear space.
+
+It is our experience that many HDR displays do not report maximum white
+level correctly
+
+
+Let There Be Color
+------------------
+
+So far we've only talked about luminance, ignoring colors altogether. Just
+like in the luminance space, traditionally the color space of display
+outputs has not been well defined. Similar to how an EOTF defines a
+mapping of pixel data to an absolute luminance value, the color space
+maps color information for each pixel onto the CIE 1931 chromaticity
+space. This can be thought of as a mapping to an absolute, real-life,
+color value.
+
+A color space is defined by its primaries and white point. The primaries
+and white point are expressed as coordinates in the CIE 1931 color
+space. Think of the red primary as the reddest red that can be displayed
+within the color space. Same for green and blue.
+
+Examples of color spaces are:
+
+.. flat-table::
+   :header-rows: 1
+
+   * - Color Space
+     - Description
+   
+   *  - BT 601
+      - similar to BT 709
+  
+   *  - BT 709
+      - used by sRGB content; ~53% of BT 2020
+ 
+   *  - DCI-P3
+      - used by most HDR displays; ~72% of BT 2020
+
+   *  - BT 2020
+      - standard for most HDR content
+
+
+
+Color Primaries and White Point
+-------------------------------
+
+Just like displays can currently not represent the entire 0.0005 -
+10,000 nits HDR range of the PQ 2084 EOTF, they are currently not capable
+of representing the entire BT.2020 color Gamut. For this reason video
+content will often specify the color primaries and white point used to
+master the video, in order to allow displays to be able to map the image
+as best as possible onto the display's gamut.
+
+
+Displays and Tonemapping
+------------------------
+
+External displays are able to do their own tone and color mapping, based
+on the mastering luminance, color primaries, and white space defined in
+the HDR metadata.
+
+Some internal panels might not include the complex HW to do tone and color
+mapping on their own and will require the display driver to perform
+appropriate mapping.
+
+
+How are we solving the problem?
+===============================
+
+Input and Output Transfer functions
+-----------------------------------
+
+We define an input transfer function on drm_plane to describe the
+transform from framebuffer to blending space.
+
+We define an output transfer function on drm_crtc to describe the
+transform from blending space to display space.
+
+The transfer function can be a pre-defined function, such as PQ EOTF, or
+a custom LUT. A driver will be able to specify support for specific
+transfer functions, including custom ones.
+
+Defining the transfer function in this way allows us to support in on HW
+that uses ROMs to support these transforms, as well as on HW that use
+LUT definitions that are complex and don't map easily onto a standard LUT
+definition.
+
+We will not define per-plane LUTs in this patchset as the scope of our
+current work only deals with pre-defined transfer functions. This API has
+the flexibility to add custom 1D or 3D LUTs at a later date.
+
+In order to support the existing 1D de-gamma and gamma LUTs on the drm_crtc
+we will include a "custom 1D" enum value to indicate that the custom gamma and
+de-gamma 1D LUTs should be used.
+
+Possible transfer functions:
+
+.. flat-table::
+   :header-rows: 1
+
+   * - Transfer Function
+     - Description
+   
+   *  - Gamma 2.2
+      - a simple 2.2 gamma function
+  
+   *  - sRGB
+      - 2.4 gamma with small initial linear section
+ 
+   *  - PQ 2084
+      - SMPTE ST 2084; used for HDR video and allows for up to 10,000 nit support
+
+   *  - Linear
+      - Linear relationship between pixel value and luminance value
+
+   *  - Custom 1D
+      - Custom 1D de-gamma and gamma LUTs; one LUT per color
+
+   *  - Custom 3D
+      - Custom 3D LUT (to be defined)
+
+
+Describing SDR Luminance
+------------------------------
+
+Since many displays do no correctly advertise the HDR white level we
+propose to define the SDR white level in nits.
+
+We define a new drm_plane property to specify the white level of an SDR
+plane.
+
+
+Defining the color space
+------------------------
+
+We propose to add a new color space property to drm_plane to define a
+plane's color space.
+
+While some color space conversions can be performed with a simple color
+transformation matrix (CTM) others require a 3D LUT.
+
+
+Defining mastering color space and luminance
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ToDo
+
+
+
+Pixel Formats
+~~~~~~~~~~~~~
+
+The pixel formats, such as ARGB8888, ARGB2101010, P010, or FP16 are
+unrelated to color space and EOTF definitions. HDR pixels can be formatted
+in different ways but in order to not lose precision HDR content requires
+at least 10 bpc precision. For this reason ARGB2101010, P010, and FP16 are
+the obvious candidates for HDR. ARGB2101010 and P010 have the advantage
+of requiring only half the bandwidth as FP16, while FP16 has the advantage
+of enough precision to operate in a linear space, i.e. without EOTF.
+
+
+
+Use Cases
+=========
+
+RGB10 HDR plane - composited HDR video & desktop
+------------------------------------------------
+
+A single, composited plane of HDR content. The use-case is a video player
+on a desktop with the compositor owning the composition of SDR and HDR
+content. The content shall be PQ BT.2020 formatted. The drm_connector's
+hdr_output_metadata shall be set.
+
+
+P010 HDR video plane + RGB8 SDR desktop plane
+---------------------------------------------
+A normal 8bpc desktop plane, with a P010 HDR video plane underlayed. The
+HDR plane shall be PQ BT.2020 formatted. The desktop plane shall specify
+an SDR boost value. The drm_connector's hdr_output_metadata shall be set.
+
+
+One XRGB8888 SDR Plane - HDR output
+-----------------------------------
+
+In order to support a smooth transition we recommend an OS that supports
+HDR output to provide the hdr_output_metadata on the drm_connector to
+configure the output for HDR, even when the content is only SDR. This will
+allow for a smooth transition between SDR-only and HDR content. In this
+use-case the SDR max luminance value should be provided on the drm_plane.
+
+In DCN we will de-PQ or de-Gamma all input in order to blend in linear
+space. For SDR content we will also apply any desired boost before
+blending. After blending we will then re-apply the PQ EOTF and do RGB
+to YCbCr conversion if needed.
+
+FP16 HDR linear planes
+----------------------
+
+ToDo
+
+
+User Space
+==========
+
+Wayland
+-------
+
+ToDo
+
+
+ChromeOS Ozone
+--------------
+
+ToDo
+
+
+HW support
+==========
+
+ToDo, describe pipeline on a couple different HW platforms
+
+
+References
+==========
+
+* [1] https://en.wikipedia.org/wiki/High-dynamic-range_video#Perceptual_Quantizer
+* [2] https://en.wikipedia.org/wiki/Transfer_functions_in_imaging
+
+
+Further Reading
+===============
+
+* https://gitlab.freedesktop.org/swick/wayland-protocols/-/blob/color/unstable/color-management/color.rst
+* http://downloads.bbc.co.uk/rd/pubs/whp/whp-pdf-files/WHP309.pdf
+* https://app.spectracal.com/Documents/White%20Papers/HDR_Demystified.pdf
+
+
diff --git a/Documentation/gpu/rfc/index.rst b/Documentation/gpu/rfc/index.rst
index a8621f7dab8b..5c8eaf8bf587 100644
--- a/Documentation/gpu/rfc/index.rst
+++ b/Documentation/gpu/rfc/index.rst
@@ -15,3 +15,7 @@ host such documentation:
 
 * Once the code has landed move all the documentation to the right places in
   the main core, helper or driver sections.
+
+  .. toctree::
+
+  hdr-wide-gamut.rst
\ No newline at end of file
-- 
2.31.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [RFC PATCH v2 2/6] drm/color: Add transfer functions for HDR/SDR on drm_plane
  2021-05-14 21:07 ` Harry Wentland
@ 2021-05-14 21:07   ` Harry Wentland
  -1 siblings, 0 replies; 18+ messages in thread
From: Harry Wentland @ 2021-05-14 21:07 UTC (permalink / raw)
  To: amd-gfx, dri-devel, ppaalanen, sebastian, mcasas
  Cc: Deepak.Sharma, Krunoslav.Kovac, Shashank.Sharma, Shirish.S,
	hersenxs.wu, Vitaly.Prosyak, laurentiu.palcu, Bhawanpreet.Lakha,
	Nicholas.Kazlauskas

From: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>

Due to the way displays and human vision work it is most effective to
encode luminance information in a non-linear space.

For SDR this non-linear mapping is assumed to roughly use a gamma 2.2 curve.
This was due to the way CRTs worked and was fine for SDR content with a
low luminance range.

The large luminance range (0-10,000 nits) for HDR exposes some
short-comings of a simple gamma curve that have been addressed
through various Electro-Optical Transfer Functions (EOTFs).

Rather than assuming how framebuffer content is encoded we want to
make sure userspace presenting HDR content is explicit about the
EOTF of the content, so a driver can decide whether the content
can be supported or not.

This Patch adds common transfer functions for SDR/HDR. These can
be used to communicate with the driver regarding the transformation to
use for a given plane.

enums added:
	DRM_TF_UNDEFINED
		the legacy case where the TF in/out of blending space is
		undefined
	DRM_TF_SRGB
		roughly 2.4 gamma with initial linear section
	DRM_TF_BT709
		Similar to Gamma 2.2-2.8
	DRM_TF_PQ2084
		most common tf used for HDR video (HDR10/Dolby). Can support up
		to 10,000 nits

The usage is similar to color_encoding and color_range where the driver
can specify the default and supported tfs and pass it into
drm_plane_create_color_properties().

v2:
 - drop "color" from transfer function name (Harry)
 - add DRM_TF_UNDEFINED enum as legacy default (Harry)

Signed-off-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  4 +-
 .../gpu/drm/arm/display/komeda/komeda_plane.c |  4 +-
 drivers/gpu/drm/arm/malidp_planes.c           |  4 +-
 drivers/gpu/drm/armada/armada_overlay.c       |  4 +-
 drivers/gpu/drm/drm_atomic_uapi.c             |  4 ++
 drivers/gpu/drm/drm_color_mgmt.c              | 64 +++++++++++++++++--
 drivers/gpu/drm/i915/display/intel_sprite.c   |  4 +-
 .../drm/i915/display/skl_universal_plane.c    |  4 +-
 drivers/gpu/drm/nouveau/dispnv04/overlay.c    |  4 +-
 drivers/gpu/drm/omapdrm/omap_plane.c          |  4 +-
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c        |  4 +-
 drivers/gpu/drm/tidss/tidss_plane.c           |  6 +-
 include/drm/drm_color_mgmt.h                  | 18 +++++-
 include/drm/drm_plane.h                       | 16 +++++
 14 files changed, 128 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 389eff96fcf6..041576945a0d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -7072,7 +7072,9 @@ static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
 			BIT(DRM_COLOR_YCBCR_BT2020),
 			BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
 			BIT(DRM_COLOR_YCBCR_FULL_RANGE),
-			DRM_COLOR_YCBCR_BT709, DRM_COLOR_YCBCR_LIMITED_RANGE);
+			BIT(DRM_TF_SRGB),
+			DRM_COLOR_YCBCR_BT709, DRM_COLOR_YCBCR_LIMITED_RANGE,
+			DRM_TF_SRGB);
 	}
 
 	supported_rotations =
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
index d63d83800a8a..811f79ab6d32 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
@@ -302,8 +302,10 @@ static int komeda_plane_add(struct komeda_kms_dev *kms,
 			BIT(DRM_COLOR_YCBCR_BT2020),
 			BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
 			BIT(DRM_COLOR_YCBCR_FULL_RANGE),
+			BIT(DRM_TF_UNDEFINED),
 			DRM_COLOR_YCBCR_BT601,
-			DRM_COLOR_YCBCR_LIMITED_RANGE);
+			DRM_COLOR_YCBCR_LIMITED_RANGE,
+			DRM_TF_UNDEFINED);
 	if (err)
 		goto cleanup;
 
diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
index ddbba67f0283..8be0d40db2e5 100644
--- a/drivers/gpu/drm/arm/malidp_planes.c
+++ b/drivers/gpu/drm/arm/malidp_planes.c
@@ -1025,7 +1025,9 @@ int malidp_de_planes_init(struct drm_device *drm)
 					BIT(DRM_COLOR_YCBCR_BT2020),
 					BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | \
 					BIT(DRM_COLOR_YCBCR_FULL_RANGE),
-					enc, range);
+					BIT(DRM_TF_UNDEFINED),
+					enc, range,
+					DRM_TF_UNDEFINED);
 			if (!ret)
 				/* program the HW registers */
 				malidp_de_set_color_encoding(plane, enc, range);
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c
index d3e3e5fdc390..f7792444cb73 100644
--- a/drivers/gpu/drm/armada/armada_overlay.c
+++ b/drivers/gpu/drm/armada/armada_overlay.c
@@ -596,8 +596,10 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs)
 						BIT(DRM_COLOR_YCBCR_BT601) |
 						BIT(DRM_COLOR_YCBCR_BT709),
 						BIT(DRM_COLOR_YCBCR_LIMITED_RANGE),
+						BIT(DRM_TF_UNDEFINED),
 						DEFAULT_ENCODING,
-						DRM_COLOR_YCBCR_LIMITED_RANGE);
+						DRM_COLOR_YCBCR_LIMITED_RANGE,
+						DRM_TF_UNDEFINED);
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index 268bb69c2e2f..42f8fd577d36 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -595,6 +595,8 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane,
 		state->color_encoding = val;
 	} else if (property == plane->color_range_property) {
 		state->color_range = val;
+	} else if (property == plane->transfer_function_property) {
+		state->transfer_function = val;
 	} else if (property == config->prop_fb_damage_clips) {
 		ret = drm_atomic_replace_property_blob_from_id(dev,
 					&state->fb_damage_clips,
@@ -661,6 +663,8 @@ drm_atomic_plane_get_property(struct drm_plane *plane,
 		*val = state->color_encoding;
 	} else if (property == plane->color_range_property) {
 		*val = state->color_range;
+	} else if (property == plane->transfer_function_property) {
+		*val = state->transfer_function;
 	} else if (property == config->prop_fb_damage_clips) {
 		*val = (state->fb_damage_clips) ?
 			state->fb_damage_clips->base.id : 0;
diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c
index bb14f488c8f6..daf62fb090a6 100644
--- a/drivers/gpu/drm/drm_color_mgmt.c
+++ b/drivers/gpu/drm/drm_color_mgmt.c
@@ -106,6 +106,11 @@
  * 	Optional plane enum property to support different non RGB
  * 	color parameter ranges. The driver can provide a subset of
  * 	standard enum values supported by the DRM plane.
+ *
+ * "COLOR_TRANFER_FUNCTION":
+ * 	Optional plane enum property to support different
+ * 	color luminance mappings. The driver can provide a subset of
+ * 	standard enum values supported by the DRM plane.
  */
 
 /**
@@ -476,6 +481,11 @@ static const char * const color_range_name[] = {
 	[DRM_COLOR_YCBCR_LIMITED_RANGE] = "YCbCr limited range",
 };
 
+static const char * const tf_name[] = {
+	[DRM_TF_UNDEFINED] = "undefined",
+	[DRM_TF_SRGB] = "sRGB",
+	[DRM_TF_PQ2084] = "PQ2084",
+};
 /**
  * drm_get_color_encoding_name - return a string for color encoding
  * @encoding: color encoding to compute name of
@@ -506,30 +516,49 @@ const char *drm_get_color_range_name(enum drm_color_range range)
 	return color_range_name[range];
 }
 
+/**
+ * drm_get_transfer_function - return a string for transfer function
+ * @tf: transfer function to compute name of
+ *
+ * In contrast to the other drm_get_*_name functions this one here returns a
+ * const pointer and hence is threadsafe.
+ */
+const char *drm_get_transfer_function_name(enum drm_transfer_function tf)
+{
+	if (WARN_ON(tf >= ARRAY_SIZE(tf_name)))
+		return "unknown";
+
+	return tf_name[tf];
+}
 /**
  * drm_plane_create_color_properties - color encoding related plane properties
  * @plane: plane object
  * @supported_encodings: bitfield indicating supported color encodings
  * @supported_ranges: bitfileld indicating supported color ranges
+ * @supported_tfs: bitfield indicating supported transfer functions
  * @default_encoding: default color encoding
  * @default_range: default color range
+ * @default_tf: default color transfer function
  *
- * Create and attach plane specific COLOR_ENCODING and COLOR_RANGE
- * properties to @plane. The supported encodings and ranges should
- * be provided in supported_encodings and supported_ranges bitmasks.
+ * Create and attach plane specific COLOR_ENCODING, COLOR_RANGE and TRANSFER_FUNCTION
+ * properties to @plane. The supported encodings, ranges  and tfs should
+ * be provided in supported_encodings, supported_ranges and supported_tfs bitmasks.
  * Each bit set in the bitmask indicates that its number as enum
  * value is supported.
  */
 int drm_plane_create_color_properties(struct drm_plane *plane,
 				      u32 supported_encodings,
 				      u32 supported_ranges,
+				      u32 supported_tfs,
 				      enum drm_color_encoding default_encoding,
-				      enum drm_color_range default_range)
+				      enum drm_color_range default_range,
+				      enum drm_transfer_function default_tf)
 {
 	struct drm_device *dev = plane->dev;
 	struct drm_property *prop;
 	struct drm_prop_enum_list enum_list[max_t(int, DRM_COLOR_ENCODING_MAX,
-						       DRM_COLOR_RANGE_MAX)];
+						       max_t(int, DRM_COLOR_RANGE_MAX,
+							     DRM_TF_MAX))];
 	int i, len;
 
 	if (WARN_ON(supported_encodings == 0 ||
@@ -542,6 +571,11 @@ int drm_plane_create_color_properties(struct drm_plane *plane,
 		    (supported_ranges & BIT(default_range)) == 0))
 		return -EINVAL;
 
+	if (WARN_ON(supported_tfs == 0 ||
+		    (supported_tfs & -BIT(DRM_TF_MAX)) != 0 ||
+		    (supported_tfs & BIT(default_tf)) == 0))
+		return -EINVAL;
+
 	len = 0;
 	for (i = 0; i < DRM_COLOR_ENCODING_MAX; i++) {
 		if ((supported_encodings & BIT(i)) == 0)
@@ -580,6 +614,26 @@ int drm_plane_create_color_properties(struct drm_plane *plane,
 	if (plane->state)
 		plane->state->color_range = default_range;
 
+
+	len = 0;
+	for (i = 0; i < DRM_TF_MAX; i++) {
+		if ((supported_tfs & BIT(i)) == 0)
+			continue;
+
+		enum_list[len].type = i;
+		enum_list[len].name = tf_name[i];
+		len++;
+	}
+
+	prop = drm_property_create_enum(dev, 0, "TRANSFER_FUNCTION",
+					enum_list, len);
+	if (!prop)
+		return -ENOMEM;
+	plane->transfer_function_property = prop;
+	drm_object_attach_property(&plane->base, prop, default_tf);
+	if (plane->state)
+		plane->state->transfer_function = default_tf;
+
 	return 0;
 }
 EXPORT_SYMBOL(drm_plane_create_color_properties);
diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c
index acbf4e63b245..85b7efc43a8b 100644
--- a/drivers/gpu/drm/i915/display/intel_sprite.c
+++ b/drivers/gpu/drm/i915/display/intel_sprite.c
@@ -1849,8 +1849,10 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 					  BIT(DRM_COLOR_YCBCR_BT709),
 					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
 					  BIT(DRM_COLOR_YCBCR_FULL_RANGE),
+					  BIT(DRM_TF_UNDEFINED),
 					  DRM_COLOR_YCBCR_BT709,
-					  DRM_COLOR_YCBCR_LIMITED_RANGE);
+					  DRM_COLOR_YCBCR_LIMITED_RANGE,
+					  DRM_TF_UNDEFINED);
 
 	zpos = sprite + 1;
 	drm_plane_create_zpos_immutable_property(&plane->base, zpos);
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c
index 7ffd7b570b54..f1abf74cef48 100644
--- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
+++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
@@ -2044,8 +2044,10 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv,
 					  supported_csc,
 					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
 					  BIT(DRM_COLOR_YCBCR_FULL_RANGE),
+					  BIT(DRM_TF_UNDEFINED),
 					  DRM_COLOR_YCBCR_BT709,
-					  DRM_COLOR_YCBCR_LIMITED_RANGE);
+					  DRM_COLOR_YCBCR_LIMITED_RANGE,
+					  DRM_TF_UNDEFINED);
 
 	drm_plane_create_alpha_property(&plane->base);
 	drm_plane_create_blend_mode_property(&plane->base,
diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
index 37e63e98cd08..64e1793212b4 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/overlay.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
@@ -345,8 +345,10 @@ nv10_overlay_init(struct drm_device *device)
 					  BIT(DRM_COLOR_YCBCR_BT601) |
 					  BIT(DRM_COLOR_YCBCR_BT709),
 					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE),
+					  BIT(DRM_TF_UNDEFINED),
 					  DRM_COLOR_YCBCR_BT601,
-					  DRM_COLOR_YCBCR_LIMITED_RANGE);
+					  DRM_COLOR_YCBCR_LIMITED_RANGE,
+					  DRM_TF_UNDEFINED);
 
 	plane->set_params = nv10_set_params;
 	nv10_set_params(plane);
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c
index 801da917507d..ca7559824dcd 100644
--- a/drivers/gpu/drm/omapdrm/omap_plane.c
+++ b/drivers/gpu/drm/omapdrm/omap_plane.c
@@ -325,8 +325,10 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
 						  BIT(DRM_COLOR_YCBCR_BT709),
 						  BIT(DRM_COLOR_YCBCR_FULL_RANGE) |
 						  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE),
+						  BIT(DRM_TF_UNDEFINED),
 						  DRM_COLOR_YCBCR_BT601,
-						  DRM_COLOR_YCBCR_FULL_RANGE);
+						  DRM_COLOR_YCBCR_FULL_RANGE,
+						  DRM_TF_UNDEFINED);
 
 	return plane;
 
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index 46420780db59..e0dd7132b920 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -594,8 +594,10 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
 	ret = drm_plane_create_color_properties(&layer->plane,
 						supported_encodings,
 						supported_ranges,
+						BIT(DRM_TF_UNDEFINED),
 						DRM_COLOR_YCBCR_BT709,
-						DRM_COLOR_YCBCR_LIMITED_RANGE);
+						DRM_COLOR_YCBCR_LIMITED_RANGE,
+						DRM_TF_UNDEFINED);
 	if (ret) {
 		dev_err(drm->dev, "Couldn't add encoding and range properties!\n");
 		return ERR_PTR(ret);
diff --git a/drivers/gpu/drm/tidss/tidss_plane.c b/drivers/gpu/drm/tidss/tidss_plane.c
index 1acd15aa4193..a1336ecd5fd5 100644
--- a/drivers/gpu/drm/tidss/tidss_plane.c
+++ b/drivers/gpu/drm/tidss/tidss_plane.c
@@ -186,8 +186,10 @@ struct tidss_plane *tidss_plane_create(struct tidss_device *tidss,
 			       BIT(DRM_COLOR_YCBCR_BT709));
 	u32 color_ranges = (BIT(DRM_COLOR_YCBCR_FULL_RANGE) |
 			    BIT(DRM_COLOR_YCBCR_LIMITED_RANGE));
+	u32 transfer_functions = BIT(DRM_TF_UNDEFINED;
 	u32 default_encoding = DRM_COLOR_YCBCR_BT601;
 	u32 default_range = DRM_COLOR_YCBCR_FULL_RANGE;
+	u32 default_tf = DRM_TF_UNDEFINED;;
 	u32 blend_modes = (BIT(DRM_MODE_BLEND_PREMULTI) |
 			   BIT(DRM_MODE_BLEND_COVERAGE));
 	int ret;
@@ -217,8 +219,10 @@ struct tidss_plane *tidss_plane_create(struct tidss_device *tidss,
 	ret = drm_plane_create_color_properties(&tplane->plane,
 						color_encodings,
 						color_ranges,
+						transfer_functions,
 						default_encoding,
-						default_range);
+						default_range,
+						default_tf);
 	if (ret)
 		goto err;
 
diff --git a/include/drm/drm_color_mgmt.h b/include/drm/drm_color_mgmt.h
index 81c298488b0c..370bbc55b744 100644
--- a/include/drm/drm_color_mgmt.h
+++ b/include/drm/drm_color_mgmt.h
@@ -87,11 +87,27 @@ enum drm_color_range {
 	DRM_COLOR_RANGE_MAX,
 };
 
+/**
+ * enum drm_transfer_function - common transfer function used for sdr/hdr formats
+ *
+ * DRM_TF_UNDEFINED - The legacy case where a TF in and out of the blending
+ *                    space is undefined
+ * DRM_TF_SRGB - Based on gamma curve and is used for printer/monitors/web
+ * DRM_TF_PQ2084 - Used for HDR and allows for up to 10,000 nit support.
+*/
+enum drm_transfer_function {
+	DRM_TF_UNDEFINED,
+	DRM_TF_SRGB,
+	DRM_TF_PQ2084,
+	DRM_TF_MAX,
+};
 int drm_plane_create_color_properties(struct drm_plane *plane,
 				      u32 supported_encodings,
 				      u32 supported_ranges,
+				      u32 supported_tf,
 				      enum drm_color_encoding default_encoding,
-				      enum drm_color_range default_range);
+				      enum drm_color_range default_range,
+				      enum drm_transfer_function default_tf);
 
 /**
  * enum drm_color_lut_tests - hw-specific LUT tests to perform
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
index 1294610e84f4..cff56994513f 100644
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -179,6 +179,14 @@ struct drm_plane_state {
 	 */
 	enum drm_color_range color_range;
 
+	/**
+	 * @transfer_function:
+	 *
+	 * Transfer function for HDR color/luminance mapping. This will allow the
+	 * driver to know what transfer function should be used to for the current
+	 * format for a proper HDR color/luminance output.
+	 */
+	enum drm_transfer_function transfer_function;
 	/**
 	 * @fb_damage_clips:
 	 *
@@ -741,6 +749,14 @@ struct drm_plane {
 	 * See drm_plane_create_color_properties().
 	 */
 	struct drm_property *color_range_property;
+	/**
+	 * @transfer_function_property:
+	 *
+	 * Optional "TRANSFER_FUNCTION" enum property for specifying
+	 * color transfer function for non RGB formats, mostly used for HDR.
+	 * See drm_plane_create_color_properties().
+	 */
+	struct drm_property *transfer_function_property;
 
 	/**
 	 * @scaling_filter_property: property to apply a particular filter while
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [RFC PATCH v2 2/6] drm/color: Add transfer functions for HDR/SDR on drm_plane
@ 2021-05-14 21:07   ` Harry Wentland
  0 siblings, 0 replies; 18+ messages in thread
From: Harry Wentland @ 2021-05-14 21:07 UTC (permalink / raw)
  To: amd-gfx, dri-devel, ppaalanen, sebastian, mcasas
  Cc: Deepak.Sharma, aric.cyr, Krunoslav.Kovac, Shashank.Sharma,
	Harry Wentland, Shirish.S, hersenxs.wu, Vitaly.Prosyak,
	laurentiu.palcu, Bhawanpreet.Lakha, Nicholas.Kazlauskas,
	ville.syrjala

From: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>

Due to the way displays and human vision work it is most effective to
encode luminance information in a non-linear space.

For SDR this non-linear mapping is assumed to roughly use a gamma 2.2 curve.
This was due to the way CRTs worked and was fine for SDR content with a
low luminance range.

The large luminance range (0-10,000 nits) for HDR exposes some
short-comings of a simple gamma curve that have been addressed
through various Electro-Optical Transfer Functions (EOTFs).

Rather than assuming how framebuffer content is encoded we want to
make sure userspace presenting HDR content is explicit about the
EOTF of the content, so a driver can decide whether the content
can be supported or not.

This Patch adds common transfer functions for SDR/HDR. These can
be used to communicate with the driver regarding the transformation to
use for a given plane.

enums added:
	DRM_TF_UNDEFINED
		the legacy case where the TF in/out of blending space is
		undefined
	DRM_TF_SRGB
		roughly 2.4 gamma with initial linear section
	DRM_TF_BT709
		Similar to Gamma 2.2-2.8
	DRM_TF_PQ2084
		most common tf used for HDR video (HDR10/Dolby). Can support up
		to 10,000 nits

The usage is similar to color_encoding and color_range where the driver
can specify the default and supported tfs and pass it into
drm_plane_create_color_properties().

v2:
 - drop "color" from transfer function name (Harry)
 - add DRM_TF_UNDEFINED enum as legacy default (Harry)

Signed-off-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  4 +-
 .../gpu/drm/arm/display/komeda/komeda_plane.c |  4 +-
 drivers/gpu/drm/arm/malidp_planes.c           |  4 +-
 drivers/gpu/drm/armada/armada_overlay.c       |  4 +-
 drivers/gpu/drm/drm_atomic_uapi.c             |  4 ++
 drivers/gpu/drm/drm_color_mgmt.c              | 64 +++++++++++++++++--
 drivers/gpu/drm/i915/display/intel_sprite.c   |  4 +-
 .../drm/i915/display/skl_universal_plane.c    |  4 +-
 drivers/gpu/drm/nouveau/dispnv04/overlay.c    |  4 +-
 drivers/gpu/drm/omapdrm/omap_plane.c          |  4 +-
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c        |  4 +-
 drivers/gpu/drm/tidss/tidss_plane.c           |  6 +-
 include/drm/drm_color_mgmt.h                  | 18 +++++-
 include/drm/drm_plane.h                       | 16 +++++
 14 files changed, 128 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 389eff96fcf6..041576945a0d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -7072,7 +7072,9 @@ static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
 			BIT(DRM_COLOR_YCBCR_BT2020),
 			BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
 			BIT(DRM_COLOR_YCBCR_FULL_RANGE),
-			DRM_COLOR_YCBCR_BT709, DRM_COLOR_YCBCR_LIMITED_RANGE);
+			BIT(DRM_TF_SRGB),
+			DRM_COLOR_YCBCR_BT709, DRM_COLOR_YCBCR_LIMITED_RANGE,
+			DRM_TF_SRGB);
 	}
 
 	supported_rotations =
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
index d63d83800a8a..811f79ab6d32 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
@@ -302,8 +302,10 @@ static int komeda_plane_add(struct komeda_kms_dev *kms,
 			BIT(DRM_COLOR_YCBCR_BT2020),
 			BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
 			BIT(DRM_COLOR_YCBCR_FULL_RANGE),
+			BIT(DRM_TF_UNDEFINED),
 			DRM_COLOR_YCBCR_BT601,
-			DRM_COLOR_YCBCR_LIMITED_RANGE);
+			DRM_COLOR_YCBCR_LIMITED_RANGE,
+			DRM_TF_UNDEFINED);
 	if (err)
 		goto cleanup;
 
diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
index ddbba67f0283..8be0d40db2e5 100644
--- a/drivers/gpu/drm/arm/malidp_planes.c
+++ b/drivers/gpu/drm/arm/malidp_planes.c
@@ -1025,7 +1025,9 @@ int malidp_de_planes_init(struct drm_device *drm)
 					BIT(DRM_COLOR_YCBCR_BT2020),
 					BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | \
 					BIT(DRM_COLOR_YCBCR_FULL_RANGE),
-					enc, range);
+					BIT(DRM_TF_UNDEFINED),
+					enc, range,
+					DRM_TF_UNDEFINED);
 			if (!ret)
 				/* program the HW registers */
 				malidp_de_set_color_encoding(plane, enc, range);
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c
index d3e3e5fdc390..f7792444cb73 100644
--- a/drivers/gpu/drm/armada/armada_overlay.c
+++ b/drivers/gpu/drm/armada/armada_overlay.c
@@ -596,8 +596,10 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs)
 						BIT(DRM_COLOR_YCBCR_BT601) |
 						BIT(DRM_COLOR_YCBCR_BT709),
 						BIT(DRM_COLOR_YCBCR_LIMITED_RANGE),
+						BIT(DRM_TF_UNDEFINED),
 						DEFAULT_ENCODING,
-						DRM_COLOR_YCBCR_LIMITED_RANGE);
+						DRM_COLOR_YCBCR_LIMITED_RANGE,
+						DRM_TF_UNDEFINED);
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index 268bb69c2e2f..42f8fd577d36 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -595,6 +595,8 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane,
 		state->color_encoding = val;
 	} else if (property == plane->color_range_property) {
 		state->color_range = val;
+	} else if (property == plane->transfer_function_property) {
+		state->transfer_function = val;
 	} else if (property == config->prop_fb_damage_clips) {
 		ret = drm_atomic_replace_property_blob_from_id(dev,
 					&state->fb_damage_clips,
@@ -661,6 +663,8 @@ drm_atomic_plane_get_property(struct drm_plane *plane,
 		*val = state->color_encoding;
 	} else if (property == plane->color_range_property) {
 		*val = state->color_range;
+	} else if (property == plane->transfer_function_property) {
+		*val = state->transfer_function;
 	} else if (property == config->prop_fb_damage_clips) {
 		*val = (state->fb_damage_clips) ?
 			state->fb_damage_clips->base.id : 0;
diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c
index bb14f488c8f6..daf62fb090a6 100644
--- a/drivers/gpu/drm/drm_color_mgmt.c
+++ b/drivers/gpu/drm/drm_color_mgmt.c
@@ -106,6 +106,11 @@
  * 	Optional plane enum property to support different non RGB
  * 	color parameter ranges. The driver can provide a subset of
  * 	standard enum values supported by the DRM plane.
+ *
+ * "COLOR_TRANFER_FUNCTION":
+ * 	Optional plane enum property to support different
+ * 	color luminance mappings. The driver can provide a subset of
+ * 	standard enum values supported by the DRM plane.
  */
 
 /**
@@ -476,6 +481,11 @@ static const char * const color_range_name[] = {
 	[DRM_COLOR_YCBCR_LIMITED_RANGE] = "YCbCr limited range",
 };
 
+static const char * const tf_name[] = {
+	[DRM_TF_UNDEFINED] = "undefined",
+	[DRM_TF_SRGB] = "sRGB",
+	[DRM_TF_PQ2084] = "PQ2084",
+};
 /**
  * drm_get_color_encoding_name - return a string for color encoding
  * @encoding: color encoding to compute name of
@@ -506,30 +516,49 @@ const char *drm_get_color_range_name(enum drm_color_range range)
 	return color_range_name[range];
 }
 
+/**
+ * drm_get_transfer_function - return a string for transfer function
+ * @tf: transfer function to compute name of
+ *
+ * In contrast to the other drm_get_*_name functions this one here returns a
+ * const pointer and hence is threadsafe.
+ */
+const char *drm_get_transfer_function_name(enum drm_transfer_function tf)
+{
+	if (WARN_ON(tf >= ARRAY_SIZE(tf_name)))
+		return "unknown";
+
+	return tf_name[tf];
+}
 /**
  * drm_plane_create_color_properties - color encoding related plane properties
  * @plane: plane object
  * @supported_encodings: bitfield indicating supported color encodings
  * @supported_ranges: bitfileld indicating supported color ranges
+ * @supported_tfs: bitfield indicating supported transfer functions
  * @default_encoding: default color encoding
  * @default_range: default color range
+ * @default_tf: default color transfer function
  *
- * Create and attach plane specific COLOR_ENCODING and COLOR_RANGE
- * properties to @plane. The supported encodings and ranges should
- * be provided in supported_encodings and supported_ranges bitmasks.
+ * Create and attach plane specific COLOR_ENCODING, COLOR_RANGE and TRANSFER_FUNCTION
+ * properties to @plane. The supported encodings, ranges  and tfs should
+ * be provided in supported_encodings, supported_ranges and supported_tfs bitmasks.
  * Each bit set in the bitmask indicates that its number as enum
  * value is supported.
  */
 int drm_plane_create_color_properties(struct drm_plane *plane,
 				      u32 supported_encodings,
 				      u32 supported_ranges,
+				      u32 supported_tfs,
 				      enum drm_color_encoding default_encoding,
-				      enum drm_color_range default_range)
+				      enum drm_color_range default_range,
+				      enum drm_transfer_function default_tf)
 {
 	struct drm_device *dev = plane->dev;
 	struct drm_property *prop;
 	struct drm_prop_enum_list enum_list[max_t(int, DRM_COLOR_ENCODING_MAX,
-						       DRM_COLOR_RANGE_MAX)];
+						       max_t(int, DRM_COLOR_RANGE_MAX,
+							     DRM_TF_MAX))];
 	int i, len;
 
 	if (WARN_ON(supported_encodings == 0 ||
@@ -542,6 +571,11 @@ int drm_plane_create_color_properties(struct drm_plane *plane,
 		    (supported_ranges & BIT(default_range)) == 0))
 		return -EINVAL;
 
+	if (WARN_ON(supported_tfs == 0 ||
+		    (supported_tfs & -BIT(DRM_TF_MAX)) != 0 ||
+		    (supported_tfs & BIT(default_tf)) == 0))
+		return -EINVAL;
+
 	len = 0;
 	for (i = 0; i < DRM_COLOR_ENCODING_MAX; i++) {
 		if ((supported_encodings & BIT(i)) == 0)
@@ -580,6 +614,26 @@ int drm_plane_create_color_properties(struct drm_plane *plane,
 	if (plane->state)
 		plane->state->color_range = default_range;
 
+
+	len = 0;
+	for (i = 0; i < DRM_TF_MAX; i++) {
+		if ((supported_tfs & BIT(i)) == 0)
+			continue;
+
+		enum_list[len].type = i;
+		enum_list[len].name = tf_name[i];
+		len++;
+	}
+
+	prop = drm_property_create_enum(dev, 0, "TRANSFER_FUNCTION",
+					enum_list, len);
+	if (!prop)
+		return -ENOMEM;
+	plane->transfer_function_property = prop;
+	drm_object_attach_property(&plane->base, prop, default_tf);
+	if (plane->state)
+		plane->state->transfer_function = default_tf;
+
 	return 0;
 }
 EXPORT_SYMBOL(drm_plane_create_color_properties);
diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c
index acbf4e63b245..85b7efc43a8b 100644
--- a/drivers/gpu/drm/i915/display/intel_sprite.c
+++ b/drivers/gpu/drm/i915/display/intel_sprite.c
@@ -1849,8 +1849,10 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 					  BIT(DRM_COLOR_YCBCR_BT709),
 					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
 					  BIT(DRM_COLOR_YCBCR_FULL_RANGE),
+					  BIT(DRM_TF_UNDEFINED),
 					  DRM_COLOR_YCBCR_BT709,
-					  DRM_COLOR_YCBCR_LIMITED_RANGE);
+					  DRM_COLOR_YCBCR_LIMITED_RANGE,
+					  DRM_TF_UNDEFINED);
 
 	zpos = sprite + 1;
 	drm_plane_create_zpos_immutable_property(&plane->base, zpos);
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c
index 7ffd7b570b54..f1abf74cef48 100644
--- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
+++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
@@ -2044,8 +2044,10 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv,
 					  supported_csc,
 					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
 					  BIT(DRM_COLOR_YCBCR_FULL_RANGE),
+					  BIT(DRM_TF_UNDEFINED),
 					  DRM_COLOR_YCBCR_BT709,
-					  DRM_COLOR_YCBCR_LIMITED_RANGE);
+					  DRM_COLOR_YCBCR_LIMITED_RANGE,
+					  DRM_TF_UNDEFINED);
 
 	drm_plane_create_alpha_property(&plane->base);
 	drm_plane_create_blend_mode_property(&plane->base,
diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
index 37e63e98cd08..64e1793212b4 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/overlay.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
@@ -345,8 +345,10 @@ nv10_overlay_init(struct drm_device *device)
 					  BIT(DRM_COLOR_YCBCR_BT601) |
 					  BIT(DRM_COLOR_YCBCR_BT709),
 					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE),
+					  BIT(DRM_TF_UNDEFINED),
 					  DRM_COLOR_YCBCR_BT601,
-					  DRM_COLOR_YCBCR_LIMITED_RANGE);
+					  DRM_COLOR_YCBCR_LIMITED_RANGE,
+					  DRM_TF_UNDEFINED);
 
 	plane->set_params = nv10_set_params;
 	nv10_set_params(plane);
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c
index 801da917507d..ca7559824dcd 100644
--- a/drivers/gpu/drm/omapdrm/omap_plane.c
+++ b/drivers/gpu/drm/omapdrm/omap_plane.c
@@ -325,8 +325,10 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
 						  BIT(DRM_COLOR_YCBCR_BT709),
 						  BIT(DRM_COLOR_YCBCR_FULL_RANGE) |
 						  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE),
+						  BIT(DRM_TF_UNDEFINED),
 						  DRM_COLOR_YCBCR_BT601,
-						  DRM_COLOR_YCBCR_FULL_RANGE);
+						  DRM_COLOR_YCBCR_FULL_RANGE,
+						  DRM_TF_UNDEFINED);
 
 	return plane;
 
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index 46420780db59..e0dd7132b920 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -594,8 +594,10 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
 	ret = drm_plane_create_color_properties(&layer->plane,
 						supported_encodings,
 						supported_ranges,
+						BIT(DRM_TF_UNDEFINED),
 						DRM_COLOR_YCBCR_BT709,
-						DRM_COLOR_YCBCR_LIMITED_RANGE);
+						DRM_COLOR_YCBCR_LIMITED_RANGE,
+						DRM_TF_UNDEFINED);
 	if (ret) {
 		dev_err(drm->dev, "Couldn't add encoding and range properties!\n");
 		return ERR_PTR(ret);
diff --git a/drivers/gpu/drm/tidss/tidss_plane.c b/drivers/gpu/drm/tidss/tidss_plane.c
index 1acd15aa4193..a1336ecd5fd5 100644
--- a/drivers/gpu/drm/tidss/tidss_plane.c
+++ b/drivers/gpu/drm/tidss/tidss_plane.c
@@ -186,8 +186,10 @@ struct tidss_plane *tidss_plane_create(struct tidss_device *tidss,
 			       BIT(DRM_COLOR_YCBCR_BT709));
 	u32 color_ranges = (BIT(DRM_COLOR_YCBCR_FULL_RANGE) |
 			    BIT(DRM_COLOR_YCBCR_LIMITED_RANGE));
+	u32 transfer_functions = BIT(DRM_TF_UNDEFINED;
 	u32 default_encoding = DRM_COLOR_YCBCR_BT601;
 	u32 default_range = DRM_COLOR_YCBCR_FULL_RANGE;
+	u32 default_tf = DRM_TF_UNDEFINED;;
 	u32 blend_modes = (BIT(DRM_MODE_BLEND_PREMULTI) |
 			   BIT(DRM_MODE_BLEND_COVERAGE));
 	int ret;
@@ -217,8 +219,10 @@ struct tidss_plane *tidss_plane_create(struct tidss_device *tidss,
 	ret = drm_plane_create_color_properties(&tplane->plane,
 						color_encodings,
 						color_ranges,
+						transfer_functions,
 						default_encoding,
-						default_range);
+						default_range,
+						default_tf);
 	if (ret)
 		goto err;
 
diff --git a/include/drm/drm_color_mgmt.h b/include/drm/drm_color_mgmt.h
index 81c298488b0c..370bbc55b744 100644
--- a/include/drm/drm_color_mgmt.h
+++ b/include/drm/drm_color_mgmt.h
@@ -87,11 +87,27 @@ enum drm_color_range {
 	DRM_COLOR_RANGE_MAX,
 };
 
+/**
+ * enum drm_transfer_function - common transfer function used for sdr/hdr formats
+ *
+ * DRM_TF_UNDEFINED - The legacy case where a TF in and out of the blending
+ *                    space is undefined
+ * DRM_TF_SRGB - Based on gamma curve and is used for printer/monitors/web
+ * DRM_TF_PQ2084 - Used for HDR and allows for up to 10,000 nit support.
+*/
+enum drm_transfer_function {
+	DRM_TF_UNDEFINED,
+	DRM_TF_SRGB,
+	DRM_TF_PQ2084,
+	DRM_TF_MAX,
+};
 int drm_plane_create_color_properties(struct drm_plane *plane,
 				      u32 supported_encodings,
 				      u32 supported_ranges,
+				      u32 supported_tf,
 				      enum drm_color_encoding default_encoding,
-				      enum drm_color_range default_range);
+				      enum drm_color_range default_range,
+				      enum drm_transfer_function default_tf);
 
 /**
  * enum drm_color_lut_tests - hw-specific LUT tests to perform
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
index 1294610e84f4..cff56994513f 100644
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -179,6 +179,14 @@ struct drm_plane_state {
 	 */
 	enum drm_color_range color_range;
 
+	/**
+	 * @transfer_function:
+	 *
+	 * Transfer function for HDR color/luminance mapping. This will allow the
+	 * driver to know what transfer function should be used to for the current
+	 * format for a proper HDR color/luminance output.
+	 */
+	enum drm_transfer_function transfer_function;
 	/**
 	 * @fb_damage_clips:
 	 *
@@ -741,6 +749,14 @@ struct drm_plane {
 	 * See drm_plane_create_color_properties().
 	 */
 	struct drm_property *color_range_property;
+	/**
+	 * @transfer_function_property:
+	 *
+	 * Optional "TRANSFER_FUNCTION" enum property for specifying
+	 * color transfer function for non RGB formats, mostly used for HDR.
+	 * See drm_plane_create_color_properties().
+	 */
+	struct drm_property *transfer_function_property;
 
 	/**
 	 * @scaling_filter_property: property to apply a particular filter while
-- 
2.31.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [RFC PATCH v2 3/6] drm/color: Add output transfer function to crtc
  2021-05-14 21:07 ` Harry Wentland
@ 2021-05-14 21:07   ` Harry Wentland
  -1 siblings, 0 replies; 18+ messages in thread
From: Harry Wentland @ 2021-05-14 21:07 UTC (permalink / raw)
  To: amd-gfx, dri-devel, ppaalanen, sebastian, mcasas
  Cc: Deepak.Sharma, Krunoslav.Kovac, Shashank.Sharma, Shirish.S,
	hersenxs.wu, Vitaly.Prosyak, laurentiu.palcu, Bhawanpreet.Lakha,
	Nicholas.Kazlauskas

We currently have 1D LUTs to define output transfer function but using a
1D LUT is not always the best way to define a transfer function for HW
that has ROMs for certain transfer functions, or for HW that has complex
PWL definition for accurate LUT definitions.

For this reason we're introducing named transfer functions. The original
LUT behavior is preserved with the default "1D LUT" transfer function.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 11 +++-
 .../gpu/drm/arm/display/komeda/komeda_crtc.c  |  7 ++-
 drivers/gpu/drm/arm/malidp_crtc.c             |  7 ++-
 drivers/gpu/drm/armada/armada_crtc.c          |  5 +-
 .../gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c    |  7 ++-
 drivers/gpu/drm/drm_color_mgmt.c              | 54 ++++++++++++++++---
 drivers/gpu/drm/i915/display/intel_color.c    | 11 ++--
 drivers/gpu/drm/i915/display/intel_color.h    |  2 +-
 drivers/gpu/drm/i915/display/intel_crtc.c     |  4 +-
 drivers/gpu/drm/ingenic/ingenic-drm-drv.c     |  9 +++-
 drivers/gpu/drm/mediatek/mtk_drm_crtc.c       |  8 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c      |  9 +++-
 drivers/gpu/drm/nouveau/dispnv50/head.c       | 13 +++--
 drivers/gpu/drm/omapdrm/omap_crtc.c           | 10 +++-
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c        |  7 ++-
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c   |  5 +-
 drivers/gpu/drm/stm/ltdc.c                    |  8 ++-
 drivers/gpu/drm/tidss/tidss_crtc.c            |  9 +++-
 drivers/gpu/drm/vc4/vc4_crtc.c                | 16 +++++-
 include/drm/drm_color_mgmt.h                  | 37 +++++++------
 include/drm/drm_crtc.h                        | 20 +++++++
 21 files changed, 208 insertions(+), 51 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 041576945a0d..59d277c31864 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -7139,8 +7139,15 @@ static int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
 	acrtc->otg_inst = -1;
 
 	dm->adev->mode_info.crtcs[crtc_index] = acrtc;
-	drm_crtc_enable_color_mgmt(&acrtc->base, MAX_COLOR_LUT_ENTRIES,
-				   true, MAX_COLOR_LUT_ENTRIES);
+
+	res = drm_crtc_enable_color_mgmt(&acrtc->base, MAX_COLOR_LUT_ENTRIES,
+					 true, MAX_COLOR_LUT_ENTRIES,
+					 BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
+	if (res) {
+		drm_crtc_cleanup(&acrtc->base);
+		goto fail;
+	}
+
 	drm_mode_crtc_set_gamma_size(&acrtc->base, MAX_COLOR_LEGACY_LUT_ENTRIES);
 
 	return 0;
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
index 59172acb9738..f364d37232b5 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
@@ -626,7 +626,12 @@ static int komeda_crtc_add(struct komeda_kms_dev *kms,
 
 	crtc->port = kcrtc->master->of_output_port;
 
-	drm_crtc_enable_color_mgmt(crtc, 0, true, KOMEDA_COLOR_LUT_SIZE);
+	err = drm_crtc_enable_color_mgmt(crtc, 0, true, KOMEDA_COLOR_LUT_SIZE,
+					 BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
+	if (err) {
+		drm_crtc_cleanup(crtc);
+		return err;
+	}
 
 	return err;
 }
diff --git a/drivers/gpu/drm/arm/malidp_crtc.c b/drivers/gpu/drm/arm/malidp_crtc.c
index 494075ddbef6..7af87002c375 100644
--- a/drivers/gpu/drm/arm/malidp_crtc.c
+++ b/drivers/gpu/drm/arm/malidp_crtc.c
@@ -552,7 +552,12 @@ int malidp_crtc_init(struct drm_device *drm)
 	drm_crtc_helper_add(&malidp->crtc, &malidp_crtc_helper_funcs);
 	drm_mode_crtc_set_gamma_size(&malidp->crtc, MALIDP_GAMMA_LUT_SIZE);
 	/* No inverse-gamma: it is per-plane. */
-	drm_crtc_enable_color_mgmt(&malidp->crtc, 0, true, MALIDP_GAMMA_LUT_SIZE);
+	ret = drm_crtc_enable_color_mgmt(&malidp->crtc, 0, true, MALIDP_GAMMA_LUT_SIZE,
+					 BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
+	if (ret) {
+		drm_crtc_cleanup(&malidp->crtc);
+		return ret;
+	}
 
 	malidp_se_set_enh_coeffs(malidp->dev);
 
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index b7bb90ae787f..d44a1d4fa475 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -992,7 +992,10 @@ static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev,
 	if (ret)
 		return ret;
 
-	drm_crtc_enable_color_mgmt(&dcrtc->crtc, 0, false, 256);
+	ret = drm_crtc_enable_color_mgmt(&dcrtc->crtc, 0, false, ,
+					 BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
+	if (ret)
+		return ret;
 
 	return armada_overlay_plane_create(drm, 1 << dcrtc->num);
 
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
index 05ad75d155e8..e5911826d002 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
@@ -528,8 +528,11 @@ int atmel_hlcdc_crtc_create(struct drm_device *dev)
 	drm_crtc_helper_add(&crtc->base, &lcdc_crtc_helper_funcs);
 
 	drm_mode_crtc_set_gamma_size(&crtc->base, ATMEL_HLCDC_CLUT_SIZE);
-	drm_crtc_enable_color_mgmt(&crtc->base, 0, false,
-				   ATMEL_HLCDC_CLUT_SIZE);
+	ret = drm_crtc_enable_color_mgmt(&crtc->base, 0, false,
+					 ATMEL_HLCDC_CLUT_SIZE,
+					 BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
+	if (ret)
+		goto fail;
 
 	dc->crtc = &crtc->base;
 
diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c
index daf62fb090a6..196544951ab7 100644
--- a/drivers/gpu/drm/drm_color_mgmt.c
+++ b/drivers/gpu/drm/drm_color_mgmt.c
@@ -147,12 +147,21 @@ u64 drm_color_ctm_s31_32_to_qm_n(u64 user_input, u32 m, u32 n)
 }
 EXPORT_SYMBOL(drm_color_ctm_s31_32_to_qm_n);
 
+static const char * const tf_name[] = {
+	[DRM_TF_UNDEFINED] = "undefined",
+	[DRM_TF_SRGB] = "sRGB",
+	[DRM_TF_PQ2084] = "PQ2084",
+	[DRM_TF_1D_LUT] = "1D LUT",
+};
+
 /**
  * drm_crtc_enable_color_mgmt - enable color management properties
  * @crtc: DRM CRTC
  * @degamma_lut_size: the size of the degamma lut (before CSC)
  * @has_ctm: whether to attach ctm_property for CSC matrix
  * @gamma_lut_size: the size of the gamma lut (after CSC)
+ * @supported_tfs: bitfield indicating supported transfer functions
+ * @default_tf: default output transfer function
  *
  * This function lets the driver enable the color correction
  * properties on a CRTC. This includes 3 degamma, csc and gamma
@@ -162,13 +171,27 @@ EXPORT_SYMBOL(drm_color_ctm_s31_32_to_qm_n);
  * their size is not 0 and ctm_property is only attached if has_ctm is
  * true.
  */
-void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
+bool drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
 				uint degamma_lut_size,
 				bool has_ctm,
-				uint gamma_lut_size)
+				uint gamma_lut_size,
+				u32 supported_tfs,
+				enum drm_transfer_function default_tf)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_mode_config *config = &dev->mode_config;
+	struct drm_property *prop;
+	struct drm_prop_enum_list enum_list[DRM_TF_MAX];
+	int i, len;
+
+	if (WARN_ON(supported_tfs == 0 ||
+		    (supported_tfs & -BIT(DRM_TF_MAX)) != 0 ||
+		    (supported_tfs & BIT(default_tf)) == 0))
+		return -EINVAL;
+
+	if (!!(supported_tfs & BIT(DRM_TF_1D_LUT)) !=
+	    !!(degamma_lut_size || gamma_lut_size))
+		return -EINVAL;
 
 	if (degamma_lut_size) {
 		drm_object_attach_property(&crtc->base,
@@ -189,6 +212,28 @@ void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
 					   config->gamma_lut_size_property,
 					   gamma_lut_size);
 	}
+
+	len = 0;
+	for (i = 0; i < DRM_TF_MAX; i++) {
+		if ((supported_tfs & BIT(i)) == 0)
+			continue;
+
+		enum_list[len].type = i;
+		enum_list[len].name = tf_name[i];
+		len++;
+	}
+
+	prop = drm_property_create_enum(dev, 0, "OUT TRANSFER_FUNCTION",
+					enum_list, len);
+	if (!prop)
+		return -ENOMEM;
+	crtc->out_transfer_function_property = prop;
+	drm_object_attach_property(&crtc->base, prop, default_tf);
+	if (crtc->state)
+		crtc->state->out_transfer_function = default_tf;
+	
+	return 0;
+
 }
 EXPORT_SYMBOL(drm_crtc_enable_color_mgmt);
 
@@ -481,11 +526,6 @@ static const char * const color_range_name[] = {
 	[DRM_COLOR_YCBCR_LIMITED_RANGE] = "YCbCr limited range",
 };
 
-static const char * const tf_name[] = {
-	[DRM_TF_UNDEFINED] = "undefined",
-	[DRM_TF_SRGB] = "sRGB",
-	[DRM_TF_PQ2084] = "PQ2084",
-};
 /**
  * drm_get_color_encoding_name - return a string for color encoding
  * @encoding: color encoding to compute name of
diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c
index c75d7124d57a..1d4b2824dcf1 100644
--- a/drivers/gpu/drm/i915/display/intel_color.c
+++ b/drivers/gpu/drm/i915/display/intel_color.c
@@ -2092,7 +2092,7 @@ static void icl_read_luts(struct intel_crtc_state *crtc_state)
 	}
 }
 
-void intel_color_init(struct intel_crtc *crtc)
+bool intel_color_init(struct intel_crtc *crtc)
 {
 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 	bool has_ctm = INTEL_INFO(dev_priv)->color.degamma_lut_size != 0;
@@ -2149,8 +2149,9 @@ void intel_color_init(struct intel_crtc *crtc)
 		}
 	}
 
-	drm_crtc_enable_color_mgmt(&crtc->base,
-				   INTEL_INFO(dev_priv)->color.degamma_lut_size,
-				   has_ctm,
-				   INTEL_INFO(dev_priv)->color.gamma_lut_size);
+	return drm_crtc_enable_color_mgmt(&crtc->base,
+					  INTEL_INFO(dev_priv)->color.degamma_lut_size,
+					  has_ctm,
+					  INTEL_INFO(dev_priv)->color.gamma_lut_size,
+					  BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
 }
diff --git a/drivers/gpu/drm/i915/display/intel_color.h b/drivers/gpu/drm/i915/display/intel_color.h
index 173727aaa24d..a8e015acc60c 100644
--- a/drivers/gpu/drm/i915/display/intel_color.h
+++ b/drivers/gpu/drm/i915/display/intel_color.h
@@ -12,7 +12,7 @@ struct intel_crtc_state;
 struct intel_crtc;
 struct drm_property_blob;
 
-void intel_color_init(struct intel_crtc *crtc);
+bool intel_color_init(struct intel_crtc *crtc);
 int intel_color_check(struct intel_crtc_state *crtc_state);
 void intel_color_commit(const struct intel_crtc_state *crtc_state);
 void intel_color_load_luts(const struct intel_crtc_state *crtc_state);
diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c
index 39358076c05b..c0bdad412032 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc.c
+++ b/drivers/gpu/drm/i915/display/intel_crtc.c
@@ -340,7 +340,9 @@ int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
 						BIT(DRM_SCALING_FILTER_DEFAULT) |
 						BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
 
-	intel_color_init(crtc);
+	ret = intel_color_init(crtc);
+	if (ret)
+		goto fail;
 
 	intel_crtc_crc_init(crtc);
 
diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
index 29742ec5ab95..9aabaf499065 100644
--- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
+++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
@@ -971,8 +971,13 @@ static int ingenic_drm_bind(struct device *dev, bool has_components)
 		return ret;
 	}
 
-	drm_crtc_enable_color_mgmt(&priv->crtc, 0, false,
-				   ARRAY_SIZE(priv->dma_hwdescs->palette));
+	ret = drm_crtc_enable_color_mgmt(&priv->crtc, 0, false,
+					 ARRAY_SIZE(priv->dma_hwdescs->palette),
+					 BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
+	if (ret) {
+		dev_err(dev, "Failed to init color management: %i\n", ret);
+		return ret;
+	}
 
 	if (soc_info->has_osd) {
 		drm_plane_helper_add(&priv->f0,
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
index 40df2c823187..943ba13ff55e 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
@@ -827,7 +827,13 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
 
 	if (gamma_lut_size)
 		drm_mode_crtc_set_gamma_size(&mtk_crtc->base, gamma_lut_size);
-	drm_crtc_enable_color_mgmt(&mtk_crtc->base, 0, has_ctm, gamma_lut_size);
+	ret = drm_crtc_enable_color_mgmt(&mtk_crtc->base, 0, has_ctm, gamma_lut_size,
+					BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
+	if (ret) {
+		drm_crtc_cleanup(mtk_crtc->base);
+		kfree(mtk_crtc);
+		return ret;
+
 	priv->num_pipes++;
 	mutex_init(&mtk_crtc->hw_lock);
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 18bc76b7f1a3..4b01196fc093 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -1340,6 +1340,7 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane,
 	struct drm_crtc *crtc = NULL;
 	struct dpu_crtc *dpu_crtc = NULL;
 	int i;
+	int ret = 0;
 
 	dpu_crtc = kzalloc(sizeof(*dpu_crtc), GFP_KERNEL);
 	if (!dpu_crtc)
@@ -1368,7 +1369,13 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane,
 
 	drm_crtc_helper_add(crtc, &dpu_crtc_helper_funcs);
 
-	drm_crtc_enable_color_mgmt(crtc, 0, true, 0);
+	ret = drm_crtc_enable_color_mgmt(crtc, 0, true, 0,
+					 BIT(DRM_TF_UNDEFINED), DRM_TF_UNDEFINED);
+	if (ret) {
+		drm_crtc_cleanup(crtc);
+		kfree(dpu_crtc);
+		return ERR_PTR(ret);
+	}
 
 	/* save user friendly CRTC name for later */
 	snprintf(dpu_crtc->name, DPU_CRTC_NAME_SIZE, "crtc%u", crtc->base.id);
diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.c b/drivers/gpu/drm/nouveau/dispnv50/head.c
index ec361d17e900..f97b3f70152b 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/head.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/head.c
@@ -589,9 +589,16 @@ nv50_head_create(struct drm_device *dev, int index)
 	drm_crtc_helper_add(crtc, &nv50_head_help);
 	/* Keep the legacy gamma size at 256 to avoid compatibility issues */
 	drm_mode_crtc_set_gamma_size(crtc, 256);
-	drm_crtc_enable_color_mgmt(crtc, base->func->ilut_size,
-				   disp->disp->object.oclass >= GF110_DISP,
-				   head->func->olut_size);
+	ret = drm_crtc_enable_color_mgmt(crtc, base->func->ilut_size,
+					 disp->disp->object.oclass >= GF110_DISP,
+					 head->func->olut_size,
+					 BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
+	if (ret) {
+		drm_crtc_cleanup(crtc);
+		kfree(head);
+		return ERR_PTR(ret);
+	}
+
 
 	if (head->func->olut_set) {
 		ret = nv50_lut_init(disp, &drm->client.mmu, &head->olut);
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 06a719c104f4..a618b3338c38 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -839,7 +839,15 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
 	if (dispc_mgr_gamma_size(priv->dispc, channel)) {
 		unsigned int gamma_lut_size = 256;
 
-		drm_crtc_enable_color_mgmt(crtc, gamma_lut_size, true, 0);
+		ret = drm_crtc_enable_color_mgmt(crtc, gamma_lut_size, true, 0,
+						 BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
+		if (ret) {
+			dev_err(dev->dev, "$s(): could not init color management for: %s\n",
+				__func__, pipe->output->name);
+			drm_crtc_cleanup(crtc);
+			kfree(omap_crtc);
+			return ERR_PTR(ret);
+		}
 		drm_mode_crtc_set_gamma_size(crtc, gamma_lut_size);
 	}
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index ea7e39d03545..02d8737e6603 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -1263,7 +1263,12 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int swindex,
 		rgrp->cmms_mask |= BIT(hwindex % 2);
 
 		drm_mode_crtc_set_gamma_size(crtc, CM2_LUT_SIZE);
-		drm_crtc_enable_color_mgmt(crtc, 0, false, CM2_LUT_SIZE);
+		ret = drm_crtc_enable_color_mgmt(crtc, 0, false, CM2_LUT_SIZE,
+						 BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
+		if (ret) {
+			drm_crtc_cleanup(crtc);
+			return ret;
+		}
 	}
 
 	drm_crtc_helper_add(crtc, &crtc_helper_funcs);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 64469439ddf2..e303c06f9913 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -1816,7 +1816,10 @@ static int vop_create_crtc(struct vop *vop)
 	drm_crtc_helper_add(crtc, &vop_crtc_helper_funcs);
 	if (vop->lut_regs) {
 		drm_mode_crtc_set_gamma_size(crtc, vop_data->lut_size);
-		drm_crtc_enable_color_mgmt(crtc, 0, false, vop_data->lut_size);
+		ret = drm_crtc_enable_color_mgmt(crtc, 0, false, vop_data->lut_size,
+						 BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
+		if (ret)
+			goto err_cleanup_crtc;
 	}
 
 	/*
diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c
index 65c3c79ad1d5..861e79873f09 100644
--- a/drivers/gpu/drm/stm/ltdc.c
+++ b/drivers/gpu/drm/stm/ltdc.c
@@ -1034,7 +1034,13 @@ static int ltdc_crtc_init(struct drm_device *ddev, struct drm_crtc *crtc)
 	drm_crtc_helper_add(crtc, &ltdc_crtc_helper_funcs);
 
 	drm_mode_crtc_set_gamma_size(crtc, CLUT_SIZE);
-	drm_crtc_enable_color_mgmt(crtc, 0, false, CLUT_SIZE);
+	ret = drm_crtc_enable_color_mgmt(crtc, 0, false, CLUT_SIZE,
+					 BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
+	if (ret) {
+		DRM_ERROR("Can not initialize color management\n");
+		drm_crtc_cleanup(crtc);
+		goto cleanup;
+	}
 
 	DRM_DEBUG_DRIVER("CRTC:%d created\n", crtc->base.id);
 
diff --git a/drivers/gpu/drm/tidss/tidss_crtc.c b/drivers/gpu/drm/tidss/tidss_crtc.c
index 2218da3b3ca3..34ed098887bc 100644
--- a/drivers/gpu/drm/tidss/tidss_crtc.c
+++ b/drivers/gpu/drm/tidss/tidss_crtc.c
@@ -439,7 +439,14 @@ struct tidss_crtc *tidss_crtc_create(struct tidss_device *tidss,
 	if (tidss->feat->vp_feat.color.gamma_size)
 		gamma_lut_size = 256;
 
-	drm_crtc_enable_color_mgmt(crtc, 0, has_ctm, gamma_lut_size);
+	ret = drm_crtc_enable_color_mgmt(crtc, 0, has_ctm, gamma_lut_size,
+					 BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
+	if (ret) {
+		drm_crtc_cleanup(crtc);
+		kfree(tcrtc);
+		return ERR_PTR(ret);
+	}
+
 	if (gamma_lut_size)
 		drm_mode_crtc_set_gamma_size(crtc, gamma_lut_size);
 
diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 76657dcdf9b0..f0919a6e999f 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -1074,12 +1074,24 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
 	if (!vc4->hvs->hvs5) {
 		drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r));
 
-		drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size);
+		ret = drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size,
+						 BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
+		if (ret) {
+			dev_err(drm->dev, "failed to enable color management\n");
+			drm_crtc_cleanup(crtc);
+			return ret;
+		}
 
 		/* We support CTM, but only for one CRTC at a time. It's therefore
 		 * implemented as private driver state in vc4_kms, not here.
 		 */
-		drm_crtc_enable_color_mgmt(crtc, 0, true, crtc->gamma_size);
+		ret = drm_crtc_enable_color_mgmt(crtc, 0, true, crtc->gamma_size,
+						 BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
+		if (ret) {
+			dev_err(drm->dev, "failed to enable color management\n");
+			drm_crtc_cleanup(crtc);
+			return ret;
+		}
 	}
 
 	for (i = 0; i < crtc->gamma_size; i++) {
diff --git a/include/drm/drm_color_mgmt.h b/include/drm/drm_color_mgmt.h
index 370bbc55b744..408561acdb3d 100644
--- a/include/drm/drm_color_mgmt.h
+++ b/include/drm/drm_color_mgmt.h
@@ -54,10 +54,29 @@ static inline u32 drm_color_lut_extract(u32 user_input, int bit_precision)
 
 u64 drm_color_ctm_s31_32_to_qm_n(u64 user_input, u32 m, u32 n);
 
-void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
+/**
+ * enum drm_transfer_function - common transfer function used for sdr/hdr formats
+ *
+ * DRM_TF_UNDEFINED - The legacy case where a TF in and out of the blending
+ *                    space is undefined
+ * DRM_TF_SRGB - Based on gamma curve and is used for printer/monitors/web
+ * DRM_TF_PQ2084 - Used for HDR and allows for up to 10,000 nit support.
+ * DRM_TF_1D_LUT - Use 1D gamma/degamma LUTs (currently only defined on crtc)
+*/
+enum drm_transfer_function {
+	DRM_TF_UNDEFINED,
+	DRM_TF_SRGB,
+	DRM_TF_PQ2084,
+	DRM_TF_1D_LUT,
+	DRM_TF_MAX,
+};
+
+bool drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
 				uint degamma_lut_size,
 				bool has_ctm,
-				uint gamma_lut_size);
+				uint gamma_lut_size,
+				u32 supported_tfs,
+				enum drm_transfer_function default_tf);
 
 int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
 				 int gamma_size);
@@ -87,20 +106,6 @@ enum drm_color_range {
 	DRM_COLOR_RANGE_MAX,
 };
 
-/**
- * enum drm_transfer_function - common transfer function used for sdr/hdr formats
- *
- * DRM_TF_UNDEFINED - The legacy case where a TF in and out of the blending
- *                    space is undefined
- * DRM_TF_SRGB - Based on gamma curve and is used for printer/monitors/web
- * DRM_TF_PQ2084 - Used for HDR and allows for up to 10,000 nit support.
-*/
-enum drm_transfer_function {
-	DRM_TF_UNDEFINED,
-	DRM_TF_SRGB,
-	DRM_TF_PQ2084,
-	DRM_TF_MAX,
-};
 int drm_plane_create_color_properties(struct drm_plane *plane,
 				      u32 supported_encodings,
 				      u32 supported_ranges,
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 13eeba2a750a..35580dd36294 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -288,6 +288,15 @@ struct drm_crtc_state {
 	 */
 	struct drm_property_blob *gamma_lut;
 
+	/**
+	 * @out_transfer_function:
+	 *
+	 * Transfer function for conversion from blending space to
+	 * display space. DRM_TF_1D_LUT can be specified to use the
+	 * gamma/degamma LUTs from mode_config instead.
+	 */
+	enum drm_transfer_function out_transfer_function;
+
 	/**
 	 * @target_vblank:
 	 *
@@ -1096,6 +1105,17 @@ struct drm_crtc {
 	 */
 	struct drm_property *scaling_filter_property;
 
+	/**
+	 * @out_transfer_function_property:
+	 *
+	 * Optional "OUT TRANSFER FUNCTION" enum property for specifying
+	 * an output transfer function, i.e. a TF to convert from
+	 * blending space to luminance space. Use DRM_TF_1D_LUT to
+	 * indicate using the 1D gamma/degamma LUTs instead of a
+	 * named transfer function.
+	 */
+	struct drm_property *out_transfer_function_property;
+
 	/**
 	 * @state:
 	 *
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [RFC PATCH v2 3/6] drm/color: Add output transfer function to crtc
@ 2021-05-14 21:07   ` Harry Wentland
  0 siblings, 0 replies; 18+ messages in thread
From: Harry Wentland @ 2021-05-14 21:07 UTC (permalink / raw)
  To: amd-gfx, dri-devel, ppaalanen, sebastian, mcasas
  Cc: Deepak.Sharma, aric.cyr, Krunoslav.Kovac, Shashank.Sharma,
	Harry Wentland, Shirish.S, hersenxs.wu, Vitaly.Prosyak,
	laurentiu.palcu, Bhawanpreet.Lakha, Nicholas.Kazlauskas,
	ville.syrjala

We currently have 1D LUTs to define output transfer function but using a
1D LUT is not always the best way to define a transfer function for HW
that has ROMs for certain transfer functions, or for HW that has complex
PWL definition for accurate LUT definitions.

For this reason we're introducing named transfer functions. The original
LUT behavior is preserved with the default "1D LUT" transfer function.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 11 +++-
 .../gpu/drm/arm/display/komeda/komeda_crtc.c  |  7 ++-
 drivers/gpu/drm/arm/malidp_crtc.c             |  7 ++-
 drivers/gpu/drm/armada/armada_crtc.c          |  5 +-
 .../gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c    |  7 ++-
 drivers/gpu/drm/drm_color_mgmt.c              | 54 ++++++++++++++++---
 drivers/gpu/drm/i915/display/intel_color.c    | 11 ++--
 drivers/gpu/drm/i915/display/intel_color.h    |  2 +-
 drivers/gpu/drm/i915/display/intel_crtc.c     |  4 +-
 drivers/gpu/drm/ingenic/ingenic-drm-drv.c     |  9 +++-
 drivers/gpu/drm/mediatek/mtk_drm_crtc.c       |  8 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c      |  9 +++-
 drivers/gpu/drm/nouveau/dispnv50/head.c       | 13 +++--
 drivers/gpu/drm/omapdrm/omap_crtc.c           | 10 +++-
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c        |  7 ++-
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c   |  5 +-
 drivers/gpu/drm/stm/ltdc.c                    |  8 ++-
 drivers/gpu/drm/tidss/tidss_crtc.c            |  9 +++-
 drivers/gpu/drm/vc4/vc4_crtc.c                | 16 +++++-
 include/drm/drm_color_mgmt.h                  | 37 +++++++------
 include/drm/drm_crtc.h                        | 20 +++++++
 21 files changed, 208 insertions(+), 51 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 041576945a0d..59d277c31864 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -7139,8 +7139,15 @@ static int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
 	acrtc->otg_inst = -1;
 
 	dm->adev->mode_info.crtcs[crtc_index] = acrtc;
-	drm_crtc_enable_color_mgmt(&acrtc->base, MAX_COLOR_LUT_ENTRIES,
-				   true, MAX_COLOR_LUT_ENTRIES);
+
+	res = drm_crtc_enable_color_mgmt(&acrtc->base, MAX_COLOR_LUT_ENTRIES,
+					 true, MAX_COLOR_LUT_ENTRIES,
+					 BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
+	if (res) {
+		drm_crtc_cleanup(&acrtc->base);
+		goto fail;
+	}
+
 	drm_mode_crtc_set_gamma_size(&acrtc->base, MAX_COLOR_LEGACY_LUT_ENTRIES);
 
 	return 0;
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
index 59172acb9738..f364d37232b5 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
@@ -626,7 +626,12 @@ static int komeda_crtc_add(struct komeda_kms_dev *kms,
 
 	crtc->port = kcrtc->master->of_output_port;
 
-	drm_crtc_enable_color_mgmt(crtc, 0, true, KOMEDA_COLOR_LUT_SIZE);
+	err = drm_crtc_enable_color_mgmt(crtc, 0, true, KOMEDA_COLOR_LUT_SIZE,
+					 BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
+	if (err) {
+		drm_crtc_cleanup(crtc);
+		return err;
+	}
 
 	return err;
 }
diff --git a/drivers/gpu/drm/arm/malidp_crtc.c b/drivers/gpu/drm/arm/malidp_crtc.c
index 494075ddbef6..7af87002c375 100644
--- a/drivers/gpu/drm/arm/malidp_crtc.c
+++ b/drivers/gpu/drm/arm/malidp_crtc.c
@@ -552,7 +552,12 @@ int malidp_crtc_init(struct drm_device *drm)
 	drm_crtc_helper_add(&malidp->crtc, &malidp_crtc_helper_funcs);
 	drm_mode_crtc_set_gamma_size(&malidp->crtc, MALIDP_GAMMA_LUT_SIZE);
 	/* No inverse-gamma: it is per-plane. */
-	drm_crtc_enable_color_mgmt(&malidp->crtc, 0, true, MALIDP_GAMMA_LUT_SIZE);
+	ret = drm_crtc_enable_color_mgmt(&malidp->crtc, 0, true, MALIDP_GAMMA_LUT_SIZE,
+					 BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
+	if (ret) {
+		drm_crtc_cleanup(&malidp->crtc);
+		return ret;
+	}
 
 	malidp_se_set_enh_coeffs(malidp->dev);
 
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index b7bb90ae787f..d44a1d4fa475 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -992,7 +992,10 @@ static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev,
 	if (ret)
 		return ret;
 
-	drm_crtc_enable_color_mgmt(&dcrtc->crtc, 0, false, 256);
+	ret = drm_crtc_enable_color_mgmt(&dcrtc->crtc, 0, false, ,
+					 BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
+	if (ret)
+		return ret;
 
 	return armada_overlay_plane_create(drm, 1 << dcrtc->num);
 
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
index 05ad75d155e8..e5911826d002 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
@@ -528,8 +528,11 @@ int atmel_hlcdc_crtc_create(struct drm_device *dev)
 	drm_crtc_helper_add(&crtc->base, &lcdc_crtc_helper_funcs);
 
 	drm_mode_crtc_set_gamma_size(&crtc->base, ATMEL_HLCDC_CLUT_SIZE);
-	drm_crtc_enable_color_mgmt(&crtc->base, 0, false,
-				   ATMEL_HLCDC_CLUT_SIZE);
+	ret = drm_crtc_enable_color_mgmt(&crtc->base, 0, false,
+					 ATMEL_HLCDC_CLUT_SIZE,
+					 BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
+	if (ret)
+		goto fail;
 
 	dc->crtc = &crtc->base;
 
diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c
index daf62fb090a6..196544951ab7 100644
--- a/drivers/gpu/drm/drm_color_mgmt.c
+++ b/drivers/gpu/drm/drm_color_mgmt.c
@@ -147,12 +147,21 @@ u64 drm_color_ctm_s31_32_to_qm_n(u64 user_input, u32 m, u32 n)
 }
 EXPORT_SYMBOL(drm_color_ctm_s31_32_to_qm_n);
 
+static const char * const tf_name[] = {
+	[DRM_TF_UNDEFINED] = "undefined",
+	[DRM_TF_SRGB] = "sRGB",
+	[DRM_TF_PQ2084] = "PQ2084",
+	[DRM_TF_1D_LUT] = "1D LUT",
+};
+
 /**
  * drm_crtc_enable_color_mgmt - enable color management properties
  * @crtc: DRM CRTC
  * @degamma_lut_size: the size of the degamma lut (before CSC)
  * @has_ctm: whether to attach ctm_property for CSC matrix
  * @gamma_lut_size: the size of the gamma lut (after CSC)
+ * @supported_tfs: bitfield indicating supported transfer functions
+ * @default_tf: default output transfer function
  *
  * This function lets the driver enable the color correction
  * properties on a CRTC. This includes 3 degamma, csc and gamma
@@ -162,13 +171,27 @@ EXPORT_SYMBOL(drm_color_ctm_s31_32_to_qm_n);
  * their size is not 0 and ctm_property is only attached if has_ctm is
  * true.
  */
-void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
+bool drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
 				uint degamma_lut_size,
 				bool has_ctm,
-				uint gamma_lut_size)
+				uint gamma_lut_size,
+				u32 supported_tfs,
+				enum drm_transfer_function default_tf)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_mode_config *config = &dev->mode_config;
+	struct drm_property *prop;
+	struct drm_prop_enum_list enum_list[DRM_TF_MAX];
+	int i, len;
+
+	if (WARN_ON(supported_tfs == 0 ||
+		    (supported_tfs & -BIT(DRM_TF_MAX)) != 0 ||
+		    (supported_tfs & BIT(default_tf)) == 0))
+		return -EINVAL;
+
+	if (!!(supported_tfs & BIT(DRM_TF_1D_LUT)) !=
+	    !!(degamma_lut_size || gamma_lut_size))
+		return -EINVAL;
 
 	if (degamma_lut_size) {
 		drm_object_attach_property(&crtc->base,
@@ -189,6 +212,28 @@ void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
 					   config->gamma_lut_size_property,
 					   gamma_lut_size);
 	}
+
+	len = 0;
+	for (i = 0; i < DRM_TF_MAX; i++) {
+		if ((supported_tfs & BIT(i)) == 0)
+			continue;
+
+		enum_list[len].type = i;
+		enum_list[len].name = tf_name[i];
+		len++;
+	}
+
+	prop = drm_property_create_enum(dev, 0, "OUT TRANSFER_FUNCTION",
+					enum_list, len);
+	if (!prop)
+		return -ENOMEM;
+	crtc->out_transfer_function_property = prop;
+	drm_object_attach_property(&crtc->base, prop, default_tf);
+	if (crtc->state)
+		crtc->state->out_transfer_function = default_tf;
+	
+	return 0;
+
 }
 EXPORT_SYMBOL(drm_crtc_enable_color_mgmt);
 
@@ -481,11 +526,6 @@ static const char * const color_range_name[] = {
 	[DRM_COLOR_YCBCR_LIMITED_RANGE] = "YCbCr limited range",
 };
 
-static const char * const tf_name[] = {
-	[DRM_TF_UNDEFINED] = "undefined",
-	[DRM_TF_SRGB] = "sRGB",
-	[DRM_TF_PQ2084] = "PQ2084",
-};
 /**
  * drm_get_color_encoding_name - return a string for color encoding
  * @encoding: color encoding to compute name of
diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c
index c75d7124d57a..1d4b2824dcf1 100644
--- a/drivers/gpu/drm/i915/display/intel_color.c
+++ b/drivers/gpu/drm/i915/display/intel_color.c
@@ -2092,7 +2092,7 @@ static void icl_read_luts(struct intel_crtc_state *crtc_state)
 	}
 }
 
-void intel_color_init(struct intel_crtc *crtc)
+bool intel_color_init(struct intel_crtc *crtc)
 {
 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 	bool has_ctm = INTEL_INFO(dev_priv)->color.degamma_lut_size != 0;
@@ -2149,8 +2149,9 @@ void intel_color_init(struct intel_crtc *crtc)
 		}
 	}
 
-	drm_crtc_enable_color_mgmt(&crtc->base,
-				   INTEL_INFO(dev_priv)->color.degamma_lut_size,
-				   has_ctm,
-				   INTEL_INFO(dev_priv)->color.gamma_lut_size);
+	return drm_crtc_enable_color_mgmt(&crtc->base,
+					  INTEL_INFO(dev_priv)->color.degamma_lut_size,
+					  has_ctm,
+					  INTEL_INFO(dev_priv)->color.gamma_lut_size,
+					  BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
 }
diff --git a/drivers/gpu/drm/i915/display/intel_color.h b/drivers/gpu/drm/i915/display/intel_color.h
index 173727aaa24d..a8e015acc60c 100644
--- a/drivers/gpu/drm/i915/display/intel_color.h
+++ b/drivers/gpu/drm/i915/display/intel_color.h
@@ -12,7 +12,7 @@ struct intel_crtc_state;
 struct intel_crtc;
 struct drm_property_blob;
 
-void intel_color_init(struct intel_crtc *crtc);
+bool intel_color_init(struct intel_crtc *crtc);
 int intel_color_check(struct intel_crtc_state *crtc_state);
 void intel_color_commit(const struct intel_crtc_state *crtc_state);
 void intel_color_load_luts(const struct intel_crtc_state *crtc_state);
diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c
index 39358076c05b..c0bdad412032 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc.c
+++ b/drivers/gpu/drm/i915/display/intel_crtc.c
@@ -340,7 +340,9 @@ int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
 						BIT(DRM_SCALING_FILTER_DEFAULT) |
 						BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
 
-	intel_color_init(crtc);
+	ret = intel_color_init(crtc);
+	if (ret)
+		goto fail;
 
 	intel_crtc_crc_init(crtc);
 
diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
index 29742ec5ab95..9aabaf499065 100644
--- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
+++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
@@ -971,8 +971,13 @@ static int ingenic_drm_bind(struct device *dev, bool has_components)
 		return ret;
 	}
 
-	drm_crtc_enable_color_mgmt(&priv->crtc, 0, false,
-				   ARRAY_SIZE(priv->dma_hwdescs->palette));
+	ret = drm_crtc_enable_color_mgmt(&priv->crtc, 0, false,
+					 ARRAY_SIZE(priv->dma_hwdescs->palette),
+					 BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
+	if (ret) {
+		dev_err(dev, "Failed to init color management: %i\n", ret);
+		return ret;
+	}
 
 	if (soc_info->has_osd) {
 		drm_plane_helper_add(&priv->f0,
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
index 40df2c823187..943ba13ff55e 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
@@ -827,7 +827,13 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
 
 	if (gamma_lut_size)
 		drm_mode_crtc_set_gamma_size(&mtk_crtc->base, gamma_lut_size);
-	drm_crtc_enable_color_mgmt(&mtk_crtc->base, 0, has_ctm, gamma_lut_size);
+	ret = drm_crtc_enable_color_mgmt(&mtk_crtc->base, 0, has_ctm, gamma_lut_size,
+					BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
+	if (ret) {
+		drm_crtc_cleanup(mtk_crtc->base);
+		kfree(mtk_crtc);
+		return ret;
+
 	priv->num_pipes++;
 	mutex_init(&mtk_crtc->hw_lock);
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 18bc76b7f1a3..4b01196fc093 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -1340,6 +1340,7 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane,
 	struct drm_crtc *crtc = NULL;
 	struct dpu_crtc *dpu_crtc = NULL;
 	int i;
+	int ret = 0;
 
 	dpu_crtc = kzalloc(sizeof(*dpu_crtc), GFP_KERNEL);
 	if (!dpu_crtc)
@@ -1368,7 +1369,13 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane,
 
 	drm_crtc_helper_add(crtc, &dpu_crtc_helper_funcs);
 
-	drm_crtc_enable_color_mgmt(crtc, 0, true, 0);
+	ret = drm_crtc_enable_color_mgmt(crtc, 0, true, 0,
+					 BIT(DRM_TF_UNDEFINED), DRM_TF_UNDEFINED);
+	if (ret) {
+		drm_crtc_cleanup(crtc);
+		kfree(dpu_crtc);
+		return ERR_PTR(ret);
+	}
 
 	/* save user friendly CRTC name for later */
 	snprintf(dpu_crtc->name, DPU_CRTC_NAME_SIZE, "crtc%u", crtc->base.id);
diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.c b/drivers/gpu/drm/nouveau/dispnv50/head.c
index ec361d17e900..f97b3f70152b 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/head.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/head.c
@@ -589,9 +589,16 @@ nv50_head_create(struct drm_device *dev, int index)
 	drm_crtc_helper_add(crtc, &nv50_head_help);
 	/* Keep the legacy gamma size at 256 to avoid compatibility issues */
 	drm_mode_crtc_set_gamma_size(crtc, 256);
-	drm_crtc_enable_color_mgmt(crtc, base->func->ilut_size,
-				   disp->disp->object.oclass >= GF110_DISP,
-				   head->func->olut_size);
+	ret = drm_crtc_enable_color_mgmt(crtc, base->func->ilut_size,
+					 disp->disp->object.oclass >= GF110_DISP,
+					 head->func->olut_size,
+					 BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
+	if (ret) {
+		drm_crtc_cleanup(crtc);
+		kfree(head);
+		return ERR_PTR(ret);
+	}
+
 
 	if (head->func->olut_set) {
 		ret = nv50_lut_init(disp, &drm->client.mmu, &head->olut);
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 06a719c104f4..a618b3338c38 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -839,7 +839,15 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
 	if (dispc_mgr_gamma_size(priv->dispc, channel)) {
 		unsigned int gamma_lut_size = 256;
 
-		drm_crtc_enable_color_mgmt(crtc, gamma_lut_size, true, 0);
+		ret = drm_crtc_enable_color_mgmt(crtc, gamma_lut_size, true, 0,
+						 BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
+		if (ret) {
+			dev_err(dev->dev, "$s(): could not init color management for: %s\n",
+				__func__, pipe->output->name);
+			drm_crtc_cleanup(crtc);
+			kfree(omap_crtc);
+			return ERR_PTR(ret);
+		}
 		drm_mode_crtc_set_gamma_size(crtc, gamma_lut_size);
 	}
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index ea7e39d03545..02d8737e6603 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -1263,7 +1263,12 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int swindex,
 		rgrp->cmms_mask |= BIT(hwindex % 2);
 
 		drm_mode_crtc_set_gamma_size(crtc, CM2_LUT_SIZE);
-		drm_crtc_enable_color_mgmt(crtc, 0, false, CM2_LUT_SIZE);
+		ret = drm_crtc_enable_color_mgmt(crtc, 0, false, CM2_LUT_SIZE,
+						 BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
+		if (ret) {
+			drm_crtc_cleanup(crtc);
+			return ret;
+		}
 	}
 
 	drm_crtc_helper_add(crtc, &crtc_helper_funcs);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 64469439ddf2..e303c06f9913 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -1816,7 +1816,10 @@ static int vop_create_crtc(struct vop *vop)
 	drm_crtc_helper_add(crtc, &vop_crtc_helper_funcs);
 	if (vop->lut_regs) {
 		drm_mode_crtc_set_gamma_size(crtc, vop_data->lut_size);
-		drm_crtc_enable_color_mgmt(crtc, 0, false, vop_data->lut_size);
+		ret = drm_crtc_enable_color_mgmt(crtc, 0, false, vop_data->lut_size,
+						 BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
+		if (ret)
+			goto err_cleanup_crtc;
 	}
 
 	/*
diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c
index 65c3c79ad1d5..861e79873f09 100644
--- a/drivers/gpu/drm/stm/ltdc.c
+++ b/drivers/gpu/drm/stm/ltdc.c
@@ -1034,7 +1034,13 @@ static int ltdc_crtc_init(struct drm_device *ddev, struct drm_crtc *crtc)
 	drm_crtc_helper_add(crtc, &ltdc_crtc_helper_funcs);
 
 	drm_mode_crtc_set_gamma_size(crtc, CLUT_SIZE);
-	drm_crtc_enable_color_mgmt(crtc, 0, false, CLUT_SIZE);
+	ret = drm_crtc_enable_color_mgmt(crtc, 0, false, CLUT_SIZE,
+					 BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
+	if (ret) {
+		DRM_ERROR("Can not initialize color management\n");
+		drm_crtc_cleanup(crtc);
+		goto cleanup;
+	}
 
 	DRM_DEBUG_DRIVER("CRTC:%d created\n", crtc->base.id);
 
diff --git a/drivers/gpu/drm/tidss/tidss_crtc.c b/drivers/gpu/drm/tidss/tidss_crtc.c
index 2218da3b3ca3..34ed098887bc 100644
--- a/drivers/gpu/drm/tidss/tidss_crtc.c
+++ b/drivers/gpu/drm/tidss/tidss_crtc.c
@@ -439,7 +439,14 @@ struct tidss_crtc *tidss_crtc_create(struct tidss_device *tidss,
 	if (tidss->feat->vp_feat.color.gamma_size)
 		gamma_lut_size = 256;
 
-	drm_crtc_enable_color_mgmt(crtc, 0, has_ctm, gamma_lut_size);
+	ret = drm_crtc_enable_color_mgmt(crtc, 0, has_ctm, gamma_lut_size,
+					 BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
+	if (ret) {
+		drm_crtc_cleanup(crtc);
+		kfree(tcrtc);
+		return ERR_PTR(ret);
+	}
+
 	if (gamma_lut_size)
 		drm_mode_crtc_set_gamma_size(crtc, gamma_lut_size);
 
diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 76657dcdf9b0..f0919a6e999f 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -1074,12 +1074,24 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
 	if (!vc4->hvs->hvs5) {
 		drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r));
 
-		drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size);
+		ret = drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size,
+						 BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
+		if (ret) {
+			dev_err(drm->dev, "failed to enable color management\n");
+			drm_crtc_cleanup(crtc);
+			return ret;
+		}
 
 		/* We support CTM, but only for one CRTC at a time. It's therefore
 		 * implemented as private driver state in vc4_kms, not here.
 		 */
-		drm_crtc_enable_color_mgmt(crtc, 0, true, crtc->gamma_size);
+		ret = drm_crtc_enable_color_mgmt(crtc, 0, true, crtc->gamma_size,
+						 BIT(DRM_TF_1D_LUT), DRM_TF_1D_LUT);
+		if (ret) {
+			dev_err(drm->dev, "failed to enable color management\n");
+			drm_crtc_cleanup(crtc);
+			return ret;
+		}
 	}
 
 	for (i = 0; i < crtc->gamma_size; i++) {
diff --git a/include/drm/drm_color_mgmt.h b/include/drm/drm_color_mgmt.h
index 370bbc55b744..408561acdb3d 100644
--- a/include/drm/drm_color_mgmt.h
+++ b/include/drm/drm_color_mgmt.h
@@ -54,10 +54,29 @@ static inline u32 drm_color_lut_extract(u32 user_input, int bit_precision)
 
 u64 drm_color_ctm_s31_32_to_qm_n(u64 user_input, u32 m, u32 n);
 
-void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
+/**
+ * enum drm_transfer_function - common transfer function used for sdr/hdr formats
+ *
+ * DRM_TF_UNDEFINED - The legacy case where a TF in and out of the blending
+ *                    space is undefined
+ * DRM_TF_SRGB - Based on gamma curve and is used for printer/monitors/web
+ * DRM_TF_PQ2084 - Used for HDR and allows for up to 10,000 nit support.
+ * DRM_TF_1D_LUT - Use 1D gamma/degamma LUTs (currently only defined on crtc)
+*/
+enum drm_transfer_function {
+	DRM_TF_UNDEFINED,
+	DRM_TF_SRGB,
+	DRM_TF_PQ2084,
+	DRM_TF_1D_LUT,
+	DRM_TF_MAX,
+};
+
+bool drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
 				uint degamma_lut_size,
 				bool has_ctm,
-				uint gamma_lut_size);
+				uint gamma_lut_size,
+				u32 supported_tfs,
+				enum drm_transfer_function default_tf);
 
 int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
 				 int gamma_size);
@@ -87,20 +106,6 @@ enum drm_color_range {
 	DRM_COLOR_RANGE_MAX,
 };
 
-/**
- * enum drm_transfer_function - common transfer function used for sdr/hdr formats
- *
- * DRM_TF_UNDEFINED - The legacy case where a TF in and out of the blending
- *                    space is undefined
- * DRM_TF_SRGB - Based on gamma curve and is used for printer/monitors/web
- * DRM_TF_PQ2084 - Used for HDR and allows for up to 10,000 nit support.
-*/
-enum drm_transfer_function {
-	DRM_TF_UNDEFINED,
-	DRM_TF_SRGB,
-	DRM_TF_PQ2084,
-	DRM_TF_MAX,
-};
 int drm_plane_create_color_properties(struct drm_plane *plane,
 				      u32 supported_encodings,
 				      u32 supported_ranges,
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 13eeba2a750a..35580dd36294 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -288,6 +288,15 @@ struct drm_crtc_state {
 	 */
 	struct drm_property_blob *gamma_lut;
 
+	/**
+	 * @out_transfer_function:
+	 *
+	 * Transfer function for conversion from blending space to
+	 * display space. DRM_TF_1D_LUT can be specified to use the
+	 * gamma/degamma LUTs from mode_config instead.
+	 */
+	enum drm_transfer_function out_transfer_function;
+
 	/**
 	 * @target_vblank:
 	 *
@@ -1096,6 +1105,17 @@ struct drm_crtc {
 	 */
 	struct drm_property *scaling_filter_property;
 
+	/**
+	 * @out_transfer_function_property:
+	 *
+	 * Optional "OUT TRANSFER FUNCTION" enum property for specifying
+	 * an output transfer function, i.e. a TF to convert from
+	 * blending space to luminance space. Use DRM_TF_1D_LUT to
+	 * indicate using the 1D gamma/degamma LUTs instead of a
+	 * named transfer function.
+	 */
+	struct drm_property *out_transfer_function_property;
+
 	/**
 	 * @state:
 	 *
-- 
2.31.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [RFC PATCH v2 4/6] drm/color: Add sdr boost property
  2021-05-14 21:07 ` Harry Wentland
@ 2021-05-14 21:07   ` Harry Wentland
  -1 siblings, 0 replies; 18+ messages in thread
From: Harry Wentland @ 2021-05-14 21:07 UTC (permalink / raw)
  To: amd-gfx, dri-devel, ppaalanen, sebastian, mcasas
  Cc: Deepak.Sharma, Krunoslav.Kovac, Shashank.Sharma, Shirish.S,
	hersenxs.wu, Vitaly.Prosyak, laurentiu.palcu, Bhawanpreet.Lakha,
	Nicholas.Kazlauskas

From: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>

SDR is typically mastered at 200 nits and HDR is mastered at up to 10,000
nits. Due to this luminance range difference if we blend a SDR and
HDR plane together, we can run into problems where the HDR plane is too
bright or the SDR plane is too dim

A common solution to this problem is to boost the SDR plane so that its
not too dim.

This patch introduces a "sdr_white_level" property, this property can be
used by the userspace to boost the SDR content luminance. The boost
value is an explicit luminance value in nits. This allows the userspace
to set the maximum white level for the SDR plane.

v2:
 - fix type in description

Signed-off-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
 drivers/gpu/drm/drm_atomic_uapi.c |  4 ++++
 drivers/gpu/drm/drm_color_mgmt.c  | 17 +++++++++++++++++
 include/drm/drm_color_mgmt.h      |  6 ++++++
 include/drm/drm_plane.h           | 15 ++++++++++++++-
 4 files changed, 41 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index 42f8fd577d36..863d6ee3bd3d 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -597,6 +597,8 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane,
 		state->color_range = val;
 	} else if (property == plane->transfer_function_property) {
 		state->transfer_function = val;
+	} else if (property == plane->sdr_white_level_property) {
+		state->sdr_white_level = val;
 	} else if (property == config->prop_fb_damage_clips) {
 		ret = drm_atomic_replace_property_blob_from_id(dev,
 					&state->fb_damage_clips,
@@ -665,6 +667,8 @@ drm_atomic_plane_get_property(struct drm_plane *plane,
 		*val = state->color_range;
 	} else if (property == plane->transfer_function_property) {
 		*val = state->transfer_function;
+	} else if (property == plane->sdr_white_level_property) {
+		*val = state->sdr_white_level;
 	} else if (property == config->prop_fb_damage_clips) {
 		*val = (state->fb_damage_clips) ?
 			state->fb_damage_clips->base.id : 0;
diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c
index 196544951ab7..44842ba0454d 100644
--- a/drivers/gpu/drm/drm_color_mgmt.c
+++ b/drivers/gpu/drm/drm_color_mgmt.c
@@ -556,6 +556,23 @@ const char *drm_get_color_range_name(enum drm_color_range range)
 	return color_range_name[range];
 }
 
+int drm_plane_create_sdr_white_level_property(struct drm_plane *plane){
+
+	struct drm_property *prop;
+
+	prop = drm_property_create_range(plane->dev, 0, "SDR_WHITE_LEVEL", 0, UINT_MAX);
+
+	if (!prop)
+		return -ENOMEM;
+
+	plane->sdr_white_level_property = prop;
+	drm_object_attach_property(&plane->base, prop, DRM_DEFAULT_SDR_WHITE_LEVEL);
+
+	if (plane->state)
+		plane->state->sdr_white_level = DRM_DEFAULT_SDR_WHITE_LEVEL;
+
+	return 0;
+}
 /**
  * drm_get_transfer_function - return a string for transfer function
  * @tf: transfer function to compute name of
diff --git a/include/drm/drm_color_mgmt.h b/include/drm/drm_color_mgmt.h
index 408561acdb3d..2a356a9601df 100644
--- a/include/drm/drm_color_mgmt.h
+++ b/include/drm/drm_color_mgmt.h
@@ -26,6 +26,12 @@
 #include <linux/ctype.h>
 #include <drm/drm_property.h>
 
+/**
+ * Default SDR white level in nits. Although there is no standard SDR nit level, 200
+ * is chosen as the default since that is the generally accepted value.
+ */
+#define DRM_DEFAULT_SDR_WHITE_LEVEL 200
+
 struct drm_crtc;
 struct drm_plane;
 
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
index cff56994513f..93ee308a46af 100644
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -187,6 +187,11 @@ struct drm_plane_state {
 	 * format for a proper HDR color/luminance output.
 	 */
 	enum drm_transfer_function transfer_function;
+	/**
+	 * @sdr_white_level:
+	 * SDR white level boost for HDR+SDR multi plane usecases. max white level in nits
+	 */
+	unsigned int sdr_white_level;
 	/**
 	 * @fb_damage_clips:
 	 *
@@ -757,7 +762,15 @@ struct drm_plane {
 	 * See drm_plane_create_color_properties().
 	 */
 	struct drm_property *transfer_function_property;
-
+	/**
+	 * @sdr_white_level:
+	 *
+	 * Optional sdr_white_level. When HDR and SDR are combined in multi plane
+	 * overlay cases, the sdr plane will be very dim. This property allows
+	 * the driver to boost the sdr plane's white level. The value should be
+	 * max white level in nits.
+	 */
+	struct drm_property *sdr_white_level_property;
 	/**
 	 * @scaling_filter_property: property to apply a particular filter while
 	 * scaling.
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [RFC PATCH v2 4/6] drm/color: Add sdr boost property
@ 2021-05-14 21:07   ` Harry Wentland
  0 siblings, 0 replies; 18+ messages in thread
From: Harry Wentland @ 2021-05-14 21:07 UTC (permalink / raw)
  To: amd-gfx, dri-devel, ppaalanen, sebastian, mcasas
  Cc: Deepak.Sharma, aric.cyr, Krunoslav.Kovac, Shashank.Sharma,
	Harry Wentland, Shirish.S, hersenxs.wu, Vitaly.Prosyak,
	laurentiu.palcu, Bhawanpreet.Lakha, Nicholas.Kazlauskas,
	ville.syrjala

From: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>

SDR is typically mastered at 200 nits and HDR is mastered at up to 10,000
nits. Due to this luminance range difference if we blend a SDR and
HDR plane together, we can run into problems where the HDR plane is too
bright or the SDR plane is too dim

A common solution to this problem is to boost the SDR plane so that its
not too dim.

This patch introduces a "sdr_white_level" property, this property can be
used by the userspace to boost the SDR content luminance. The boost
value is an explicit luminance value in nits. This allows the userspace
to set the maximum white level for the SDR plane.

v2:
 - fix type in description

Signed-off-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
 drivers/gpu/drm/drm_atomic_uapi.c |  4 ++++
 drivers/gpu/drm/drm_color_mgmt.c  | 17 +++++++++++++++++
 include/drm/drm_color_mgmt.h      |  6 ++++++
 include/drm/drm_plane.h           | 15 ++++++++++++++-
 4 files changed, 41 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index 42f8fd577d36..863d6ee3bd3d 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -597,6 +597,8 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane,
 		state->color_range = val;
 	} else if (property == plane->transfer_function_property) {
 		state->transfer_function = val;
+	} else if (property == plane->sdr_white_level_property) {
+		state->sdr_white_level = val;
 	} else if (property == config->prop_fb_damage_clips) {
 		ret = drm_atomic_replace_property_blob_from_id(dev,
 					&state->fb_damage_clips,
@@ -665,6 +667,8 @@ drm_atomic_plane_get_property(struct drm_plane *plane,
 		*val = state->color_range;
 	} else if (property == plane->transfer_function_property) {
 		*val = state->transfer_function;
+	} else if (property == plane->sdr_white_level_property) {
+		*val = state->sdr_white_level;
 	} else if (property == config->prop_fb_damage_clips) {
 		*val = (state->fb_damage_clips) ?
 			state->fb_damage_clips->base.id : 0;
diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c
index 196544951ab7..44842ba0454d 100644
--- a/drivers/gpu/drm/drm_color_mgmt.c
+++ b/drivers/gpu/drm/drm_color_mgmt.c
@@ -556,6 +556,23 @@ const char *drm_get_color_range_name(enum drm_color_range range)
 	return color_range_name[range];
 }
 
+int drm_plane_create_sdr_white_level_property(struct drm_plane *plane){
+
+	struct drm_property *prop;
+
+	prop = drm_property_create_range(plane->dev, 0, "SDR_WHITE_LEVEL", 0, UINT_MAX);
+
+	if (!prop)
+		return -ENOMEM;
+
+	plane->sdr_white_level_property = prop;
+	drm_object_attach_property(&plane->base, prop, DRM_DEFAULT_SDR_WHITE_LEVEL);
+
+	if (plane->state)
+		plane->state->sdr_white_level = DRM_DEFAULT_SDR_WHITE_LEVEL;
+
+	return 0;
+}
 /**
  * drm_get_transfer_function - return a string for transfer function
  * @tf: transfer function to compute name of
diff --git a/include/drm/drm_color_mgmt.h b/include/drm/drm_color_mgmt.h
index 408561acdb3d..2a356a9601df 100644
--- a/include/drm/drm_color_mgmt.h
+++ b/include/drm/drm_color_mgmt.h
@@ -26,6 +26,12 @@
 #include <linux/ctype.h>
 #include <drm/drm_property.h>
 
+/**
+ * Default SDR white level in nits. Although there is no standard SDR nit level, 200
+ * is chosen as the default since that is the generally accepted value.
+ */
+#define DRM_DEFAULT_SDR_WHITE_LEVEL 200
+
 struct drm_crtc;
 struct drm_plane;
 
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
index cff56994513f..93ee308a46af 100644
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -187,6 +187,11 @@ struct drm_plane_state {
 	 * format for a proper HDR color/luminance output.
 	 */
 	enum drm_transfer_function transfer_function;
+	/**
+	 * @sdr_white_level:
+	 * SDR white level boost for HDR+SDR multi plane usecases. max white level in nits
+	 */
+	unsigned int sdr_white_level;
 	/**
 	 * @fb_damage_clips:
 	 *
@@ -757,7 +762,15 @@ struct drm_plane {
 	 * See drm_plane_create_color_properties().
 	 */
 	struct drm_property *transfer_function_property;
-
+	/**
+	 * @sdr_white_level:
+	 *
+	 * Optional sdr_white_level. When HDR and SDR are combined in multi plane
+	 * overlay cases, the sdr plane will be very dim. This property allows
+	 * the driver to boost the sdr plane's white level. The value should be
+	 * max white level in nits.
+	 */
+	struct drm_property *sdr_white_level_property;
 	/**
 	 * @scaling_filter_property: property to apply a particular filter while
 	 * scaling.
-- 
2.31.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [RFC PATCH v2 5/6] drm/color: Add color space plane property
  2021-05-14 21:07 ` Harry Wentland
@ 2021-05-14 21:07   ` Harry Wentland
  -1 siblings, 0 replies; 18+ messages in thread
From: Harry Wentland @ 2021-05-14 21:07 UTC (permalink / raw)
  To: amd-gfx, dri-devel, ppaalanen, sebastian, mcasas
  Cc: Deepak.Sharma, Krunoslav.Kovac, Shashank.Sharma, Shirish.S,
	hersenxs.wu, Vitaly.Prosyak, laurentiu.palcu, Bhawanpreet.Lakha,
	Nicholas.Kazlauskas

From: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>

Add color space definitions for BT601, BT709, BT2020, and DCI-P3.

Default to BT709, the sRGB color space.

Signed-off-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  2 +
 .../gpu/drm/arm/display/komeda/komeda_plane.c |  2 +
 drivers/gpu/drm/arm/malidp_planes.c           |  4 +-
 drivers/gpu/drm/armada/armada_overlay.c       |  2 +
 drivers/gpu/drm/drm_color_mgmt.c              | 58 ++++++++++++++++++-
 drivers/gpu/drm/i915/display/intel_sprite.c   |  2 +
 .../drm/i915/display/skl_universal_plane.c    |  2 +
 drivers/gpu/drm/nouveau/dispnv04/overlay.c    |  2 +
 drivers/gpu/drm/omapdrm/omap_plane.c          |  2 +
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c        |  6 +-
 drivers/gpu/drm/tidss/tidss_plane.c           |  4 ++
 include/drm/drm_color_mgmt.h                  | 16 +++++
 include/drm/drm_plane.h                       | 16 +++++
 13 files changed, 113 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 59d277c31864..14e5260a298f 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -7072,8 +7072,10 @@ static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
 			BIT(DRM_COLOR_YCBCR_BT2020),
 			BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
 			BIT(DRM_COLOR_YCBCR_FULL_RANGE),
+			BIT(DRM_COLOR_SPACE_BT709),
 			BIT(DRM_TF_SRGB),
 			DRM_COLOR_YCBCR_BT709, DRM_COLOR_YCBCR_LIMITED_RANGE,
+			DRM_COLOR_SPACE_BT709,
 			DRM_TF_SRGB);
 	}
 
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
index 811f79ab6d32..4fb3ad4c691e 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
@@ -302,9 +302,11 @@ static int komeda_plane_add(struct komeda_kms_dev *kms,
 			BIT(DRM_COLOR_YCBCR_BT2020),
 			BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
 			BIT(DRM_COLOR_YCBCR_FULL_RANGE),
+			BIT(DRM_COLOR_SPACE_BT709),
 			BIT(DRM_TF_UNDEFINED),
 			DRM_COLOR_YCBCR_BT601,
 			DRM_COLOR_YCBCR_LIMITED_RANGE,
+			DRM_COLOR_SPACE_BT709,
 			DRM_TF_UNDEFINED);
 	if (err)
 		goto cleanup;
diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
index 8be0d40db2e5..6478b5b1bcf6 100644
--- a/drivers/gpu/drm/arm/malidp_planes.c
+++ b/drivers/gpu/drm/arm/malidp_planes.c
@@ -1018,6 +1018,7 @@ int malidp_de_planes_init(struct drm_device *drm)
 			/* default encoding for YUV->RGB is BT601 NARROW */
 			enum drm_color_encoding enc = DRM_COLOR_YCBCR_BT601;
 			enum drm_color_range range = DRM_COLOR_YCBCR_LIMITED_RANGE;
+			enum drm_color_space space = DRM_COLOR_SPACE_BT709;
 
 			ret = drm_plane_create_color_properties(&plane->base,
 					BIT(DRM_COLOR_YCBCR_BT601) | \
@@ -1025,8 +1026,9 @@ int malidp_de_planes_init(struct drm_device *drm)
 					BIT(DRM_COLOR_YCBCR_BT2020),
 					BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | \
 					BIT(DRM_COLOR_YCBCR_FULL_RANGE),
+					BIT(DRM_COLOR_SPACE_BT709),
 					BIT(DRM_TF_UNDEFINED),
-					enc, range,
+					enc, range, space,
 					DRM_TF_UNDEFINED);
 			if (!ret)
 				/* program the HW registers */
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c
index f7792444cb73..e66f2fa72830 100644
--- a/drivers/gpu/drm/armada/armada_overlay.c
+++ b/drivers/gpu/drm/armada/armada_overlay.c
@@ -596,9 +596,11 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs)
 						BIT(DRM_COLOR_YCBCR_BT601) |
 						BIT(DRM_COLOR_YCBCR_BT709),
 						BIT(DRM_COLOR_YCBCR_LIMITED_RANGE),
+						BIT(DRM_COLOR_SPACE_BT709),
 						BIT(DRM_TF_UNDEFINED),
 						DEFAULT_ENCODING,
 						DRM_COLOR_YCBCR_LIMITED_RANGE,
+						DRM_COLOR_SPACE_BT709,
 						DRM_TF_UNDEFINED);
 
 	return ret;
diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c
index 44842ba0454d..75e6dbbd0081 100644
--- a/drivers/gpu/drm/drm_color_mgmt.c
+++ b/drivers/gpu/drm/drm_color_mgmt.c
@@ -526,6 +526,13 @@ static const char * const color_range_name[] = {
 	[DRM_COLOR_YCBCR_LIMITED_RANGE] = "YCbCr limited range",
 };
 
+static const char * const color_space_name[] = {
+	[DRM_COLOR_SPACE_BT601] = "ITU-R BT.601 RGB",
+	[DRM_COLOR_SPACE_BT709] = "ITU-R BT.709 RGB",
+	[DRM_COLOR_SPACE_BT2020] = "ITU-R BT.2020 RGB",
+	[DRM_COLOR_SPACE_P3] = "DCI-P3",
+};
+
 /**
  * drm_get_color_encoding_name - return a string for color encoding
  * @encoding: color encoding to compute name of
@@ -556,6 +563,21 @@ const char *drm_get_color_range_name(enum drm_color_range range)
 	return color_range_name[range];
 }
 
+/**
+ * drm_get_color_space_name - return a string for color space
+ * @space: color space to compute name of
+ *
+ * In contrast to the other drm_get_*_name functions this one here returns a
+ * const pointer and hence is threadsafe.
+ */
+const char *drm_get_color_space_name(enum drm_color_space space)
+{
+	if (WARN_ON(space >= ARRAY_SIZE(color_space_name)))
+		return "unknown";
+
+	return color_space_name[space];
+}
+
 int drm_plane_create_sdr_white_level_property(struct drm_plane *plane){
 
 	struct drm_property *prop;
@@ -592,23 +614,28 @@ const char *drm_get_transfer_function_name(enum drm_transfer_function tf)
  * @plane: plane object
  * @supported_encodings: bitfield indicating supported color encodings
  * @supported_ranges: bitfileld indicating supported color ranges
+ * @supported_spaces: bitfield indicating supported color spaces
  * @supported_tfs: bitfield indicating supported transfer functions
  * @default_encoding: default color encoding
  * @default_range: default color range
+ * @default_space: default color space
  * @default_tf: default color transfer function
  *
- * Create and attach plane specific COLOR_ENCODING, COLOR_RANGE and TRANSFER_FUNCTION
- * properties to @plane. The supported encodings, ranges  and tfs should
- * be provided in supported_encodings, supported_ranges and supported_tfs bitmasks.
+ * Create and attach plane specific COLOR_ENCODING, COLOR_RANGE, COLOR_SPACE,
+ * and TRANSFER_FUNCTION properties to @plane. The supported encodings, ranges,
+ * spaces, and tfs should be provided in supported_encodings, supported_ranges,
+ * supported_spaces, and supported_tfs bitmasks.
  * Each bit set in the bitmask indicates that its number as enum
  * value is supported.
  */
 int drm_plane_create_color_properties(struct drm_plane *plane,
 				      u32 supported_encodings,
 				      u32 supported_ranges,
+				      u32 supported_spaces,
 				      u32 supported_tfs,
 				      enum drm_color_encoding default_encoding,
 				      enum drm_color_range default_range,
+				      enum drm_color_space default_space,
 				      enum drm_transfer_function default_tf)
 {
 	struct drm_device *dev = plane->dev;
@@ -628,6 +655,11 @@ int drm_plane_create_color_properties(struct drm_plane *plane,
 		    (supported_ranges & BIT(default_range)) == 0))
 		return -EINVAL;
 
+	if (WARN_ON(supported_spaces == 0 ||
+		    (supported_spaces & -BIT(DRM_COLOR_SPACE_MAX)) != 0 ||
+		    (supported_spaces & BIT(default_space)) == 0))
+		return -EINVAL;
+
 	if (WARN_ON(supported_tfs == 0 ||
 		    (supported_tfs & -BIT(DRM_TF_MAX)) != 0 ||
 		    (supported_tfs & BIT(default_tf)) == 0))
@@ -672,6 +704,26 @@ int drm_plane_create_color_properties(struct drm_plane *plane,
 		plane->state->color_range = default_range;
 
 
+	len = 0;
+	for (i = 0; i < DRM_COLOR_SPACE_MAX; i++) {
+		if ((supported_spaces & BIT(i)) == 0)
+			continue;
+
+		enum_list[len].type = i;
+		enum_list[len].name = color_space_name[i];
+		len++;
+	}
+
+	prop = drm_property_create_enum(dev, 0,	"COLOR_SPACE",
+					enum_list, len);
+	if (!prop)
+		return -ENOMEM;
+	plane->color_space_property = prop;
+	drm_object_attach_property(&plane->base, prop, default_space);
+	if (plane->state)
+		plane->state->color_space = default_space;
+
+
 	len = 0;
 	for (i = 0; i < DRM_TF_MAX; i++) {
 		if ((supported_tfs & BIT(i)) == 0)
diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c
index 85b7efc43a8b..2878d5918c89 100644
--- a/drivers/gpu/drm/i915/display/intel_sprite.c
+++ b/drivers/gpu/drm/i915/display/intel_sprite.c
@@ -1849,9 +1849,11 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 					  BIT(DRM_COLOR_YCBCR_BT709),
 					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
 					  BIT(DRM_COLOR_YCBCR_FULL_RANGE),
+					  BIT(DRM_COLOR_SPACE_BT709),
 					  BIT(DRM_TF_UNDEFINED),
 					  DRM_COLOR_YCBCR_BT709,
 					  DRM_COLOR_YCBCR_LIMITED_RANGE,
+					  DRM_COLOR_SPACE_BT709,
 					  DRM_TF_UNDEFINED);
 
 	zpos = sprite + 1;
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c
index f1abf74cef48..eeb30198bb4f 100644
--- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
+++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
@@ -2044,9 +2044,11 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv,
 					  supported_csc,
 					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
 					  BIT(DRM_COLOR_YCBCR_FULL_RANGE),
+					  BIT(DRM_COLOR_SPACE_BT709),
 					  BIT(DRM_TF_UNDEFINED),
 					  DRM_COLOR_YCBCR_BT709,
 					  DRM_COLOR_YCBCR_LIMITED_RANGE,
+					  DRM_COLOR_SPACE_BT709,
 					  DRM_TF_UNDEFINED);
 
 	drm_plane_create_alpha_property(&plane->base);
diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
index 64e1793212b4..dc350245c98b 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/overlay.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
@@ -345,9 +345,11 @@ nv10_overlay_init(struct drm_device *device)
 					  BIT(DRM_COLOR_YCBCR_BT601) |
 					  BIT(DRM_COLOR_YCBCR_BT709),
 					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE),
+					  BIT(DRM_COLOR_SPACE_BT709),
 					  BIT(DRM_TF_UNDEFINED),
 					  DRM_COLOR_YCBCR_BT601,
 					  DRM_COLOR_YCBCR_LIMITED_RANGE,
+					  DRM_COLOR_SPACE_BT709,
 					  DRM_TF_UNDEFINED);
 
 	plane->set_params = nv10_set_params;
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c
index ca7559824dcd..3eb52e78e08d 100644
--- a/drivers/gpu/drm/omapdrm/omap_plane.c
+++ b/drivers/gpu/drm/omapdrm/omap_plane.c
@@ -325,9 +325,11 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
 						  BIT(DRM_COLOR_YCBCR_BT709),
 						  BIT(DRM_COLOR_YCBCR_FULL_RANGE) |
 						  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE),
+						  BIT(DRM_COLOR_SPACE_BT709),
 						  BIT(DRM_TF_UNDEFINED),
 						  DRM_COLOR_YCBCR_BT601,
 						  DRM_COLOR_YCBCR_FULL_RANGE,
+						  DRM_COLOR_SPACE_BT709,
 						  DRM_TF_UNDEFINED);
 
 	return plane;
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index e0dd7132b920..3da68e4e880f 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -538,7 +538,7 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
 					       struct sun8i_mixer *mixer,
 					       int index)
 {
-	u32 supported_encodings, supported_ranges;
+	u32 supported_encodings, supported_ranges, supported_spaces;
 	unsigned int plane_cnt, format_count;
 	struct sun8i_vi_layer *layer;
 	const u32 *formats;
@@ -591,12 +591,16 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
 	supported_ranges = BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
 			   BIT(DRM_COLOR_YCBCR_FULL_RANGE);
 
+	supported_spaces = BIT(DRM_COLOR_SPACE_BT709);
+
 	ret = drm_plane_create_color_properties(&layer->plane,
 						supported_encodings,
 						supported_ranges,
+						supported_spaces,
 						BIT(DRM_TF_UNDEFINED),
 						DRM_COLOR_YCBCR_BT709,
 						DRM_COLOR_YCBCR_LIMITED_RANGE,
+						DRM_COLOR_SPACE_BT709,
 						DRM_TF_UNDEFINED);
 	if (ret) {
 		dev_err(drm->dev, "Couldn't add encoding and range properties!\n");
diff --git a/drivers/gpu/drm/tidss/tidss_plane.c b/drivers/gpu/drm/tidss/tidss_plane.c
index a1336ecd5fd5..367a14616756 100644
--- a/drivers/gpu/drm/tidss/tidss_plane.c
+++ b/drivers/gpu/drm/tidss/tidss_plane.c
@@ -186,9 +186,11 @@ struct tidss_plane *tidss_plane_create(struct tidss_device *tidss,
 			       BIT(DRM_COLOR_YCBCR_BT709));
 	u32 color_ranges = (BIT(DRM_COLOR_YCBCR_FULL_RANGE) |
 			    BIT(DRM_COLOR_YCBCR_LIMITED_RANGE));
+	u32 color_spaces = BIT(DRM_COLOR_SPACE_BY709);
 	u32 transfer_functions = BIT(DRM_TF_UNDEFINED;
 	u32 default_encoding = DRM_COLOR_YCBCR_BT601;
 	u32 default_range = DRM_COLOR_YCBCR_FULL_RANGE;
+	u32 default_space = DRM_COLOR_SPACE_BT709;
 	u32 default_tf = DRM_TF_UNDEFINED;;
 	u32 blend_modes = (BIT(DRM_MODE_BLEND_PREMULTI) |
 			   BIT(DRM_MODE_BLEND_COVERAGE));
@@ -219,9 +221,11 @@ struct tidss_plane *tidss_plane_create(struct tidss_device *tidss,
 	ret = drm_plane_create_color_properties(&tplane->plane,
 						color_encodings,
 						color_ranges,
+						color_spaces,
 						transfer_functions,
 						default_encoding,
 						default_range,
+						default_space,
 						default_tf);
 	if (ret)
 		goto err;
diff --git a/include/drm/drm_color_mgmt.h b/include/drm/drm_color_mgmt.h
index 2a356a9601df..575427650542 100644
--- a/include/drm/drm_color_mgmt.h
+++ b/include/drm/drm_color_mgmt.h
@@ -99,6 +99,9 @@ static inline int drm_color_lut_size(const struct drm_property_blob *blob)
 	return blob->length / sizeof(struct drm_color_lut);
 }
 
+/**
+ * drm_color_encoding - describes the coefficient for YCbCr-RGB conversion
+ */
 enum drm_color_encoding {
 	DRM_COLOR_YCBCR_BT601,
 	DRM_COLOR_YCBCR_BT709,
@@ -112,12 +115,25 @@ enum drm_color_range {
 	DRM_COLOR_RANGE_MAX,
 };
 
+/**
+ * drm_color_space - describes the color space (primaries & white point)
+ */
+enum drm_color_space {
+	DRM_COLOR_SPACE_BT601,
+	DRM_COLOR_SPACE_BT709,
+	DRM_COLOR_SPACE_BT2020,
+	DRM_COLOR_SPACE_P3,
+	DRM_COLOR_SPACE_MAX,
+};
+
 int drm_plane_create_color_properties(struct drm_plane *plane,
 				      u32 supported_encodings,
 				      u32 supported_ranges,
+				      u32 supported_spaces,
 				      u32 supported_tf,
 				      enum drm_color_encoding default_encoding,
 				      enum drm_color_range default_range,
+				      enum drm_color_space default_space,
 				      enum drm_transfer_function default_tf);
 
 /**
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
index 93ee308a46af..8c9fe6350ead 100644
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -179,6 +179,13 @@ struct drm_plane_state {
 	 */
 	enum drm_color_range color_range;
 
+	/**
+	 * @color_space
+	 *
+	 * Color space (primaries & white point) of the plane
+	 */
+	enum drm_color_space color_space;
+
 	/**
 	 * @transfer_function:
 	 *
@@ -754,6 +761,15 @@ struct drm_plane {
 	 * See drm_plane_create_color_properties().
 	 */
 	struct drm_property *color_range_property;
+	/**
+	 * @color_space_property:
+	 *
+	 * Optional "COLOR_SPACE" enum property for specifying
+	 * the color space (i.e. primaries and white point) of
+	 * the plane.
+	 * See drm_plane_create_color_properties().
+	 */
+	struct drm_property *color_space_property;
 	/**
 	 * @transfer_function_property:
 	 *
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [RFC PATCH v2 5/6] drm/color: Add color space plane property
@ 2021-05-14 21:07   ` Harry Wentland
  0 siblings, 0 replies; 18+ messages in thread
From: Harry Wentland @ 2021-05-14 21:07 UTC (permalink / raw)
  To: amd-gfx, dri-devel, ppaalanen, sebastian, mcasas
  Cc: Deepak.Sharma, aric.cyr, Krunoslav.Kovac, Shashank.Sharma,
	Harry Wentland, Shirish.S, hersenxs.wu, Vitaly.Prosyak,
	laurentiu.palcu, Bhawanpreet.Lakha, Nicholas.Kazlauskas,
	ville.syrjala

From: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>

Add color space definitions for BT601, BT709, BT2020, and DCI-P3.

Default to BT709, the sRGB color space.

Signed-off-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  2 +
 .../gpu/drm/arm/display/komeda/komeda_plane.c |  2 +
 drivers/gpu/drm/arm/malidp_planes.c           |  4 +-
 drivers/gpu/drm/armada/armada_overlay.c       |  2 +
 drivers/gpu/drm/drm_color_mgmt.c              | 58 ++++++++++++++++++-
 drivers/gpu/drm/i915/display/intel_sprite.c   |  2 +
 .../drm/i915/display/skl_universal_plane.c    |  2 +
 drivers/gpu/drm/nouveau/dispnv04/overlay.c    |  2 +
 drivers/gpu/drm/omapdrm/omap_plane.c          |  2 +
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c        |  6 +-
 drivers/gpu/drm/tidss/tidss_plane.c           |  4 ++
 include/drm/drm_color_mgmt.h                  | 16 +++++
 include/drm/drm_plane.h                       | 16 +++++
 13 files changed, 113 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 59d277c31864..14e5260a298f 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -7072,8 +7072,10 @@ static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
 			BIT(DRM_COLOR_YCBCR_BT2020),
 			BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
 			BIT(DRM_COLOR_YCBCR_FULL_RANGE),
+			BIT(DRM_COLOR_SPACE_BT709),
 			BIT(DRM_TF_SRGB),
 			DRM_COLOR_YCBCR_BT709, DRM_COLOR_YCBCR_LIMITED_RANGE,
+			DRM_COLOR_SPACE_BT709,
 			DRM_TF_SRGB);
 	}
 
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
index 811f79ab6d32..4fb3ad4c691e 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
@@ -302,9 +302,11 @@ static int komeda_plane_add(struct komeda_kms_dev *kms,
 			BIT(DRM_COLOR_YCBCR_BT2020),
 			BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
 			BIT(DRM_COLOR_YCBCR_FULL_RANGE),
+			BIT(DRM_COLOR_SPACE_BT709),
 			BIT(DRM_TF_UNDEFINED),
 			DRM_COLOR_YCBCR_BT601,
 			DRM_COLOR_YCBCR_LIMITED_RANGE,
+			DRM_COLOR_SPACE_BT709,
 			DRM_TF_UNDEFINED);
 	if (err)
 		goto cleanup;
diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
index 8be0d40db2e5..6478b5b1bcf6 100644
--- a/drivers/gpu/drm/arm/malidp_planes.c
+++ b/drivers/gpu/drm/arm/malidp_planes.c
@@ -1018,6 +1018,7 @@ int malidp_de_planes_init(struct drm_device *drm)
 			/* default encoding for YUV->RGB is BT601 NARROW */
 			enum drm_color_encoding enc = DRM_COLOR_YCBCR_BT601;
 			enum drm_color_range range = DRM_COLOR_YCBCR_LIMITED_RANGE;
+			enum drm_color_space space = DRM_COLOR_SPACE_BT709;
 
 			ret = drm_plane_create_color_properties(&plane->base,
 					BIT(DRM_COLOR_YCBCR_BT601) | \
@@ -1025,8 +1026,9 @@ int malidp_de_planes_init(struct drm_device *drm)
 					BIT(DRM_COLOR_YCBCR_BT2020),
 					BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | \
 					BIT(DRM_COLOR_YCBCR_FULL_RANGE),
+					BIT(DRM_COLOR_SPACE_BT709),
 					BIT(DRM_TF_UNDEFINED),
-					enc, range,
+					enc, range, space,
 					DRM_TF_UNDEFINED);
 			if (!ret)
 				/* program the HW registers */
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c
index f7792444cb73..e66f2fa72830 100644
--- a/drivers/gpu/drm/armada/armada_overlay.c
+++ b/drivers/gpu/drm/armada/armada_overlay.c
@@ -596,9 +596,11 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs)
 						BIT(DRM_COLOR_YCBCR_BT601) |
 						BIT(DRM_COLOR_YCBCR_BT709),
 						BIT(DRM_COLOR_YCBCR_LIMITED_RANGE),
+						BIT(DRM_COLOR_SPACE_BT709),
 						BIT(DRM_TF_UNDEFINED),
 						DEFAULT_ENCODING,
 						DRM_COLOR_YCBCR_LIMITED_RANGE,
+						DRM_COLOR_SPACE_BT709,
 						DRM_TF_UNDEFINED);
 
 	return ret;
diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c
index 44842ba0454d..75e6dbbd0081 100644
--- a/drivers/gpu/drm/drm_color_mgmt.c
+++ b/drivers/gpu/drm/drm_color_mgmt.c
@@ -526,6 +526,13 @@ static const char * const color_range_name[] = {
 	[DRM_COLOR_YCBCR_LIMITED_RANGE] = "YCbCr limited range",
 };
 
+static const char * const color_space_name[] = {
+	[DRM_COLOR_SPACE_BT601] = "ITU-R BT.601 RGB",
+	[DRM_COLOR_SPACE_BT709] = "ITU-R BT.709 RGB",
+	[DRM_COLOR_SPACE_BT2020] = "ITU-R BT.2020 RGB",
+	[DRM_COLOR_SPACE_P3] = "DCI-P3",
+};
+
 /**
  * drm_get_color_encoding_name - return a string for color encoding
  * @encoding: color encoding to compute name of
@@ -556,6 +563,21 @@ const char *drm_get_color_range_name(enum drm_color_range range)
 	return color_range_name[range];
 }
 
+/**
+ * drm_get_color_space_name - return a string for color space
+ * @space: color space to compute name of
+ *
+ * In contrast to the other drm_get_*_name functions this one here returns a
+ * const pointer and hence is threadsafe.
+ */
+const char *drm_get_color_space_name(enum drm_color_space space)
+{
+	if (WARN_ON(space >= ARRAY_SIZE(color_space_name)))
+		return "unknown";
+
+	return color_space_name[space];
+}
+
 int drm_plane_create_sdr_white_level_property(struct drm_plane *plane){
 
 	struct drm_property *prop;
@@ -592,23 +614,28 @@ const char *drm_get_transfer_function_name(enum drm_transfer_function tf)
  * @plane: plane object
  * @supported_encodings: bitfield indicating supported color encodings
  * @supported_ranges: bitfileld indicating supported color ranges
+ * @supported_spaces: bitfield indicating supported color spaces
  * @supported_tfs: bitfield indicating supported transfer functions
  * @default_encoding: default color encoding
  * @default_range: default color range
+ * @default_space: default color space
  * @default_tf: default color transfer function
  *
- * Create and attach plane specific COLOR_ENCODING, COLOR_RANGE and TRANSFER_FUNCTION
- * properties to @plane. The supported encodings, ranges  and tfs should
- * be provided in supported_encodings, supported_ranges and supported_tfs bitmasks.
+ * Create and attach plane specific COLOR_ENCODING, COLOR_RANGE, COLOR_SPACE,
+ * and TRANSFER_FUNCTION properties to @plane. The supported encodings, ranges,
+ * spaces, and tfs should be provided in supported_encodings, supported_ranges,
+ * supported_spaces, and supported_tfs bitmasks.
  * Each bit set in the bitmask indicates that its number as enum
  * value is supported.
  */
 int drm_plane_create_color_properties(struct drm_plane *plane,
 				      u32 supported_encodings,
 				      u32 supported_ranges,
+				      u32 supported_spaces,
 				      u32 supported_tfs,
 				      enum drm_color_encoding default_encoding,
 				      enum drm_color_range default_range,
+				      enum drm_color_space default_space,
 				      enum drm_transfer_function default_tf)
 {
 	struct drm_device *dev = plane->dev;
@@ -628,6 +655,11 @@ int drm_plane_create_color_properties(struct drm_plane *plane,
 		    (supported_ranges & BIT(default_range)) == 0))
 		return -EINVAL;
 
+	if (WARN_ON(supported_spaces == 0 ||
+		    (supported_spaces & -BIT(DRM_COLOR_SPACE_MAX)) != 0 ||
+		    (supported_spaces & BIT(default_space)) == 0))
+		return -EINVAL;
+
 	if (WARN_ON(supported_tfs == 0 ||
 		    (supported_tfs & -BIT(DRM_TF_MAX)) != 0 ||
 		    (supported_tfs & BIT(default_tf)) == 0))
@@ -672,6 +704,26 @@ int drm_plane_create_color_properties(struct drm_plane *plane,
 		plane->state->color_range = default_range;
 
 
+	len = 0;
+	for (i = 0; i < DRM_COLOR_SPACE_MAX; i++) {
+		if ((supported_spaces & BIT(i)) == 0)
+			continue;
+
+		enum_list[len].type = i;
+		enum_list[len].name = color_space_name[i];
+		len++;
+	}
+
+	prop = drm_property_create_enum(dev, 0,	"COLOR_SPACE",
+					enum_list, len);
+	if (!prop)
+		return -ENOMEM;
+	plane->color_space_property = prop;
+	drm_object_attach_property(&plane->base, prop, default_space);
+	if (plane->state)
+		plane->state->color_space = default_space;
+
+
 	len = 0;
 	for (i = 0; i < DRM_TF_MAX; i++) {
 		if ((supported_tfs & BIT(i)) == 0)
diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c
index 85b7efc43a8b..2878d5918c89 100644
--- a/drivers/gpu/drm/i915/display/intel_sprite.c
+++ b/drivers/gpu/drm/i915/display/intel_sprite.c
@@ -1849,9 +1849,11 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 					  BIT(DRM_COLOR_YCBCR_BT709),
 					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
 					  BIT(DRM_COLOR_YCBCR_FULL_RANGE),
+					  BIT(DRM_COLOR_SPACE_BT709),
 					  BIT(DRM_TF_UNDEFINED),
 					  DRM_COLOR_YCBCR_BT709,
 					  DRM_COLOR_YCBCR_LIMITED_RANGE,
+					  DRM_COLOR_SPACE_BT709,
 					  DRM_TF_UNDEFINED);
 
 	zpos = sprite + 1;
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c
index f1abf74cef48..eeb30198bb4f 100644
--- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
+++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
@@ -2044,9 +2044,11 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv,
 					  supported_csc,
 					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
 					  BIT(DRM_COLOR_YCBCR_FULL_RANGE),
+					  BIT(DRM_COLOR_SPACE_BT709),
 					  BIT(DRM_TF_UNDEFINED),
 					  DRM_COLOR_YCBCR_BT709,
 					  DRM_COLOR_YCBCR_LIMITED_RANGE,
+					  DRM_COLOR_SPACE_BT709,
 					  DRM_TF_UNDEFINED);
 
 	drm_plane_create_alpha_property(&plane->base);
diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
index 64e1793212b4..dc350245c98b 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/overlay.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
@@ -345,9 +345,11 @@ nv10_overlay_init(struct drm_device *device)
 					  BIT(DRM_COLOR_YCBCR_BT601) |
 					  BIT(DRM_COLOR_YCBCR_BT709),
 					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE),
+					  BIT(DRM_COLOR_SPACE_BT709),
 					  BIT(DRM_TF_UNDEFINED),
 					  DRM_COLOR_YCBCR_BT601,
 					  DRM_COLOR_YCBCR_LIMITED_RANGE,
+					  DRM_COLOR_SPACE_BT709,
 					  DRM_TF_UNDEFINED);
 
 	plane->set_params = nv10_set_params;
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c
index ca7559824dcd..3eb52e78e08d 100644
--- a/drivers/gpu/drm/omapdrm/omap_plane.c
+++ b/drivers/gpu/drm/omapdrm/omap_plane.c
@@ -325,9 +325,11 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
 						  BIT(DRM_COLOR_YCBCR_BT709),
 						  BIT(DRM_COLOR_YCBCR_FULL_RANGE) |
 						  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE),
+						  BIT(DRM_COLOR_SPACE_BT709),
 						  BIT(DRM_TF_UNDEFINED),
 						  DRM_COLOR_YCBCR_BT601,
 						  DRM_COLOR_YCBCR_FULL_RANGE,
+						  DRM_COLOR_SPACE_BT709,
 						  DRM_TF_UNDEFINED);
 
 	return plane;
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index e0dd7132b920..3da68e4e880f 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -538,7 +538,7 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
 					       struct sun8i_mixer *mixer,
 					       int index)
 {
-	u32 supported_encodings, supported_ranges;
+	u32 supported_encodings, supported_ranges, supported_spaces;
 	unsigned int plane_cnt, format_count;
 	struct sun8i_vi_layer *layer;
 	const u32 *formats;
@@ -591,12 +591,16 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
 	supported_ranges = BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
 			   BIT(DRM_COLOR_YCBCR_FULL_RANGE);
 
+	supported_spaces = BIT(DRM_COLOR_SPACE_BT709);
+
 	ret = drm_plane_create_color_properties(&layer->plane,
 						supported_encodings,
 						supported_ranges,
+						supported_spaces,
 						BIT(DRM_TF_UNDEFINED),
 						DRM_COLOR_YCBCR_BT709,
 						DRM_COLOR_YCBCR_LIMITED_RANGE,
+						DRM_COLOR_SPACE_BT709,
 						DRM_TF_UNDEFINED);
 	if (ret) {
 		dev_err(drm->dev, "Couldn't add encoding and range properties!\n");
diff --git a/drivers/gpu/drm/tidss/tidss_plane.c b/drivers/gpu/drm/tidss/tidss_plane.c
index a1336ecd5fd5..367a14616756 100644
--- a/drivers/gpu/drm/tidss/tidss_plane.c
+++ b/drivers/gpu/drm/tidss/tidss_plane.c
@@ -186,9 +186,11 @@ struct tidss_plane *tidss_plane_create(struct tidss_device *tidss,
 			       BIT(DRM_COLOR_YCBCR_BT709));
 	u32 color_ranges = (BIT(DRM_COLOR_YCBCR_FULL_RANGE) |
 			    BIT(DRM_COLOR_YCBCR_LIMITED_RANGE));
+	u32 color_spaces = BIT(DRM_COLOR_SPACE_BY709);
 	u32 transfer_functions = BIT(DRM_TF_UNDEFINED;
 	u32 default_encoding = DRM_COLOR_YCBCR_BT601;
 	u32 default_range = DRM_COLOR_YCBCR_FULL_RANGE;
+	u32 default_space = DRM_COLOR_SPACE_BT709;
 	u32 default_tf = DRM_TF_UNDEFINED;;
 	u32 blend_modes = (BIT(DRM_MODE_BLEND_PREMULTI) |
 			   BIT(DRM_MODE_BLEND_COVERAGE));
@@ -219,9 +221,11 @@ struct tidss_plane *tidss_plane_create(struct tidss_device *tidss,
 	ret = drm_plane_create_color_properties(&tplane->plane,
 						color_encodings,
 						color_ranges,
+						color_spaces,
 						transfer_functions,
 						default_encoding,
 						default_range,
+						default_space,
 						default_tf);
 	if (ret)
 		goto err;
diff --git a/include/drm/drm_color_mgmt.h b/include/drm/drm_color_mgmt.h
index 2a356a9601df..575427650542 100644
--- a/include/drm/drm_color_mgmt.h
+++ b/include/drm/drm_color_mgmt.h
@@ -99,6 +99,9 @@ static inline int drm_color_lut_size(const struct drm_property_blob *blob)
 	return blob->length / sizeof(struct drm_color_lut);
 }
 
+/**
+ * drm_color_encoding - describes the coefficient for YCbCr-RGB conversion
+ */
 enum drm_color_encoding {
 	DRM_COLOR_YCBCR_BT601,
 	DRM_COLOR_YCBCR_BT709,
@@ -112,12 +115,25 @@ enum drm_color_range {
 	DRM_COLOR_RANGE_MAX,
 };
 
+/**
+ * drm_color_space - describes the color space (primaries & white point)
+ */
+enum drm_color_space {
+	DRM_COLOR_SPACE_BT601,
+	DRM_COLOR_SPACE_BT709,
+	DRM_COLOR_SPACE_BT2020,
+	DRM_COLOR_SPACE_P3,
+	DRM_COLOR_SPACE_MAX,
+};
+
 int drm_plane_create_color_properties(struct drm_plane *plane,
 				      u32 supported_encodings,
 				      u32 supported_ranges,
+				      u32 supported_spaces,
 				      u32 supported_tf,
 				      enum drm_color_encoding default_encoding,
 				      enum drm_color_range default_range,
+				      enum drm_color_space default_space,
 				      enum drm_transfer_function default_tf);
 
 /**
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
index 93ee308a46af..8c9fe6350ead 100644
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -179,6 +179,13 @@ struct drm_plane_state {
 	 */
 	enum drm_color_range color_range;
 
+	/**
+	 * @color_space
+	 *
+	 * Color space (primaries & white point) of the plane
+	 */
+	enum drm_color_space color_space;
+
 	/**
 	 * @transfer_function:
 	 *
@@ -754,6 +761,15 @@ struct drm_plane {
 	 * See drm_plane_create_color_properties().
 	 */
 	struct drm_property *color_range_property;
+	/**
+	 * @color_space_property:
+	 *
+	 * Optional "COLOR_SPACE" enum property for specifying
+	 * the color space (i.e. primaries and white point) of
+	 * the plane.
+	 * See drm_plane_create_color_properties().
+	 */
+	struct drm_property *color_space_property;
 	/**
 	 * @transfer_function_property:
 	 *
-- 
2.31.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [RFC PATCH v2 6/6] drm/amd/display: reformat YCbCr-RGB conversion matrix
  2021-05-14 21:07 ` Harry Wentland
@ 2021-05-14 21:07   ` Harry Wentland
  -1 siblings, 0 replies; 18+ messages in thread
From: Harry Wentland @ 2021-05-14 21:07 UTC (permalink / raw)
  To: amd-gfx, dri-devel, ppaalanen, sebastian, mcasas
  Cc: Deepak.Sharma, Krunoslav.Kovac, Shashank.Sharma, Shirish.S,
	hersenxs.wu, Vitaly.Prosyak, laurentiu.palcu, Bhawanpreet.Lakha,
	Nicholas.Kazlauskas

Show the CSC matrixes in a 4x3 format.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
 drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h | 28 +++++++++++++--------
 1 file changed, 18 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
index ddbe4bb52724..e91dd899ba65 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
@@ -49,22 +49,30 @@ struct dpp_input_csc_matrix {
 
 static const struct dpp_input_csc_matrix __maybe_unused dpp_input_csc_matrix[] = {
 	{COLOR_SPACE_SRGB,
-		{0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
+		{0x2000,      0,      0,      0,
+		      0, 0x2000,      0,      0,
+		      0,      0, 0x2000,      0} },
 	{COLOR_SPACE_SRGB_LIMITED,
-		{0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
+		{0x2000,      0,      0,      0,
+		      0, 0x2000,      0,      0,
+		      0,      0, 0x2000,      0} },
 	{COLOR_SPACE_YCBCR601,
-		{0x2cdd, 0x2000, 0, 0xe991, 0xe926, 0x2000, 0xf4fd, 0x10ef,
-						0, 0x2000, 0x38b4, 0xe3a6} },
+		{0x2cdd, 0x2000,      0, 0xe991,
+		 0xe926, 0x2000, 0xf4fd, 0x10ef,
+		      0, 0x2000, 0x38b4, 0xe3a6} },
 	{COLOR_SPACE_YCBCR601_LIMITED,
-		{0x3353, 0x2568, 0, 0xe400, 0xe5dc, 0x2568, 0xf367, 0x1108,
-						0, 0x2568, 0x40de, 0xdd3a} },
+		{0x3353, 0x2568,      0, 0xe400,
+		 0xe5dc, 0x2568, 0xf367, 0x1108,
+		      0, 0x2568, 0x40de, 0xdd3a} },
 	{COLOR_SPACE_YCBCR709,
-		{0x3265, 0x2000, 0, 0xe6ce, 0xf105, 0x2000, 0xfa01, 0xa7d, 0,
-						0x2000, 0x3b61, 0xe24f} },
+		{0x3265, 0x2000,      0, 0xe6ce,
+		 0xf105, 0x2000, 0xfa01, 0xa7d,
+		      0, 0x2000, 0x3b61, 0xe24f} },
 
 	{COLOR_SPACE_YCBCR709_LIMITED,
-		{0x39a6, 0x2568, 0, 0xe0d6, 0xeedd, 0x2568, 0xf925, 0x9a8, 0,
-						0x2568, 0x43ee, 0xdbb2} }
+		{0x39a6, 0x2568,      0, 0xe0d6,
+		 0xeedd, 0x2568, 0xf925, 0x9a8,
+		      0, 0x2568, 0x43ee, 0xdbb2} }
 };
 
 struct dpp_grph_csc_adjustment {
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [RFC PATCH v2 6/6] drm/amd/display: reformat YCbCr-RGB conversion matrix
@ 2021-05-14 21:07   ` Harry Wentland
  0 siblings, 0 replies; 18+ messages in thread
From: Harry Wentland @ 2021-05-14 21:07 UTC (permalink / raw)
  To: amd-gfx, dri-devel, ppaalanen, sebastian, mcasas
  Cc: Deepak.Sharma, aric.cyr, Krunoslav.Kovac, Shashank.Sharma,
	Harry Wentland, Shirish.S, hersenxs.wu, Vitaly.Prosyak,
	laurentiu.palcu, Bhawanpreet.Lakha, Nicholas.Kazlauskas,
	ville.syrjala

Show the CSC matrixes in a 4x3 format.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
 drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h | 28 +++++++++++++--------
 1 file changed, 18 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
index ddbe4bb52724..e91dd899ba65 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
@@ -49,22 +49,30 @@ struct dpp_input_csc_matrix {
 
 static const struct dpp_input_csc_matrix __maybe_unused dpp_input_csc_matrix[] = {
 	{COLOR_SPACE_SRGB,
-		{0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
+		{0x2000,      0,      0,      0,
+		      0, 0x2000,      0,      0,
+		      0,      0, 0x2000,      0} },
 	{COLOR_SPACE_SRGB_LIMITED,
-		{0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
+		{0x2000,      0,      0,      0,
+		      0, 0x2000,      0,      0,
+		      0,      0, 0x2000,      0} },
 	{COLOR_SPACE_YCBCR601,
-		{0x2cdd, 0x2000, 0, 0xe991, 0xe926, 0x2000, 0xf4fd, 0x10ef,
-						0, 0x2000, 0x38b4, 0xe3a6} },
+		{0x2cdd, 0x2000,      0, 0xe991,
+		 0xe926, 0x2000, 0xf4fd, 0x10ef,
+		      0, 0x2000, 0x38b4, 0xe3a6} },
 	{COLOR_SPACE_YCBCR601_LIMITED,
-		{0x3353, 0x2568, 0, 0xe400, 0xe5dc, 0x2568, 0xf367, 0x1108,
-						0, 0x2568, 0x40de, 0xdd3a} },
+		{0x3353, 0x2568,      0, 0xe400,
+		 0xe5dc, 0x2568, 0xf367, 0x1108,
+		      0, 0x2568, 0x40de, 0xdd3a} },
 	{COLOR_SPACE_YCBCR709,
-		{0x3265, 0x2000, 0, 0xe6ce, 0xf105, 0x2000, 0xfa01, 0xa7d, 0,
-						0x2000, 0x3b61, 0xe24f} },
+		{0x3265, 0x2000,      0, 0xe6ce,
+		 0xf105, 0x2000, 0xfa01, 0xa7d,
+		      0, 0x2000, 0x3b61, 0xe24f} },
 
 	{COLOR_SPACE_YCBCR709_LIMITED,
-		{0x39a6, 0x2568, 0, 0xe0d6, 0xeedd, 0x2568, 0xf925, 0x9a8, 0,
-						0x2568, 0x43ee, 0xdbb2} }
+		{0x39a6, 0x2568,      0, 0xe0d6,
+		 0xeedd, 0x2568, 0xf925, 0x9a8,
+		      0, 0x2568, 0x43ee, 0xdbb2} }
 };
 
 struct dpp_grph_csc_adjustment {
-- 
2.31.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [RFC PATCH v2 1/6] drm/doc: Color Management and HDR10 RFC
  2021-05-14 21:07   ` Harry Wentland
@ 2021-05-17 17:30     ` Sebastian Wick
  -1 siblings, 0 replies; 18+ messages in thread
From: Sebastian Wick @ 2021-05-17 17:30 UTC (permalink / raw)
  To: Harry Wentland
  Cc: Deepak.Sharma, Krunoslav.Kovac, mcasas, Shashank.Sharma,
	dri-devel, Shirish.S, hersenxs.wu, amd-gfx, laurentiu.palcu,
	Bhawanpreet.Lakha, Nicholas.Kazlauskas, Vitaly.Prosyak

On 2021-05-14 23:07, Harry Wentland wrote:
> Use the new DRM RFC doc section to capture the RFC previously only
> described in the cover letter at
> https://patchwork.freedesktop.org/series/89506/
> 
> Update the RFC based on feedback received:
>  * don't use color_encoding property to define color space
>  * expand on reason for SDR luminance definition
>  * define input/output transfer functions for luminance space 
> transforms,
>    rather than defining the luminance space of an input directly
> 
> Signed-off-by: Harry Wentland <harry.wentland@amd.com>
> ---
>  Documentation/gpu/rfc/hdr-wide-gamut.rst | 416 +++++++++++++++++++++++
>  Documentation/gpu/rfc/index.rst          |   4 +
>  2 files changed, 420 insertions(+)
>  create mode 100644 Documentation/gpu/rfc/hdr-wide-gamut.rst
> 
> diff --git a/Documentation/gpu/rfc/hdr-wide-gamut.rst
> b/Documentation/gpu/rfc/hdr-wide-gamut.rst
> new file mode 100644
> index 000000000000..132898668eac
> --- /dev/null
> +++ b/Documentation/gpu/rfc/hdr-wide-gamut.rst
> @@ -0,0 +1,416 @@
> +==============================
> +HDR & Wide Color Gamut Support
> +==============================
> +
> +.. role:: wy-text-strike
> +
> +ToDo
> +====
> +
> +* :wy-text-strike:`Reformat as RST kerneldoc` - done
> +* :wy-text-strike:`Don't use color_encoding for color_space 
> definitions` - done
> +* :wy-text-strike:`Update SDR luminance description and reasoning` - 
> done
> +* :wy-text-strike:`Clarify 3D LUT required for some color space
> transformations` - done
> +* :wy-text-strike:`Highlight need for named color space and EOTF
> definitions` - done
> +* :wy-text-strike:`Define transfer function API` - done
> +* :wy-text-strike:`Draft upstream plan` - done
> +* Reference to wayland and/or Chrome plans
> +* Sketch view of HW pipeline for couple of HW implementations
> +
> +
> +Upstream Plan
> +=============
> +
> +* Reach consensus on DRM/KMS API
> +* Implement support in amdgpu
> +* Implement IGT tests
> +* Add API support to Weston, ChromiumOS, or other canonical
> open-source project interested in HDR
> +* Merge user-space
> +* Merge kernel patches
> +
> +
> +Introduction
> +============
> +
> +We are looking to enable HDR support for a couple of single-plane and
> +multi-plane scenarios. To do this effectively we recommend new 
> interfaces
> +to drm_plane. Below I'll give a bit of background on HDR and why we
> +propose these interfaces.
> +
> +
> +Overview and background
> +=======================
> +
> +Defining a pixel's luminance
> +----------------------------
> +
> +The luminance space of pixels in a framebuffer/plane presented to the
> +display is not well defined in the DRM/KMS APIs. It is usually assumed 
> to
> +be in a 2.2 or 2.4 gamma space and has no mapping to an absolute 
> luminance
> +value; it is interpreted in relative terms.
> +
> +Luminance can be measured and described in absolute terms as candela
> +per meter squared, or cd/m2, or nits. Even though a pixel value can be
> +mapped to luminance in a linear fashion to do so without losing a lot 
> of
> +detail requires 16-bpc color depth. The reason for this is that human
> +perception can distinguish roughly between a 0.5-1% luminance delta. A
> +linear representation is suboptimal, wasting precision in the 
> highlights
> +and losing precision in the shadows.
> +
> +A gamma curve is a decent approximation to a human's perception of
> +luminance, but the PQ (perceptual quantizer) function [1] improves on
> +it. It also defines the luminance values in absolute terms, with the
> +highest value being 10,000 nits and the lowest 0.0005 nits.
> +
> +Using a content that's defined in PQ space we can approximate the real
> +world in a much better way.
> +
> +Here are some examples of real-life objects and their approximate
> +luminance values:
> +
> +.. flat-table::
> +   :header-rows: 1
> +
> +   * - Object
> +     - Luminance in nits
> +
> +   *  - Fluorescent light
> +      - 10,000
> +
> +   *  - Highlights
> +      - 1,000 - sunlight
> +
> +   *  - White Objects
> +      - 250 - 1,000
> +
> +   *  - Typical Objects
> +      - 1 - 250
> +
> +   *  - Shadows
> +      - 0.01 - 1
> +
> +   *  - Ultra Blacks
> +      - 0 - 0.0005
> +
> +Transfer functions
> +------------------
> +
> +Traditionally we used the terms gamma and de-gamma to describe the
> +encoding of a pixel's luminance value and the operation to transfer 
> from
> +a linear luminance space to the non-linear space used to encode the
> +pixels. Since some newer encodings don't use a gamma curve I suggest
> +we refer to non-linear encodings using the terms EOTF, and OETF[2], or
> +simply as transfer function in general.
> +
> +The EOTF (Electro-Optical Transfer Function) describes how to transfer
> +from an electrical signal to an optical signal. This was traditionally
> +done by the de-gamma function.
> +
> +The OETF (Opto Electronic Transfer Function) describes how to transfer
> +from an optical signal to an electronic signal. This was traditionally
> +done by the gamma function.
> +
> +More generally we can name the transfer function describing the 
> transform
> +between scanout and blending space as the **input transfer function**, 
> and
> +the transfer function describing the transform from blending space to 
> the
> +output space as **output transfer function**.
> +
> +
> +Mastering Luminances
> +--------------------
> +
> +Even though we are able to describe the absolute luminance of a pixel
> +using the PQ 2084 EOTF we are presented with physical limitations of 
> the
> +display technologies on the market today. Here are a few examples of
> +luminance ranges of displays.
> +
> +.. flat-table::
> +   :header-rows: 1
> +
> +   * - Display
> +     - Luminance range in nits
> +
> +   *  - Typical PC display
> +      - 0.3 - 200
> +
> +   *  - Excellent LCD HDTV
> +      - 0.3 - 400
> +
> +   *  - HDR LCD w/ local dimming
> +      - 0.05 - 1,500
> +
> +Since no display can currently show the full 0.0005 to 10,000 nits
> +luminance range of PQ the display will need to tone-map the HDR 
> content,
> +i.e to fit the content within a display's capabilities. To assist
> +with tone-mapping HDR content is usually accompanied by a metadata
> +that describes (among other things) the minimum and maximum mastering
> +luminance, i.e. the maximum and minimum luminance of the display that
> +was used to master the HDR content.
> +
> +The HDR metadata is currently defined on the drm_connector via the
> +hdr_output_metadata blob property.
> +
> +It might be useful to define per-plane hdr metadata, as different 
> planes
> +might have been mastered differently.

There really is not reason to have the HDR metadata anywhere but the
connector. If you drive the display in PQ mode and you just map content
into the PQ space you won't do any color or gamut mapping which is the
only reason why you'd want access to the HDR metadata.

User space can generate suitable connector metadata from the clients
metadata.

> +
> +
> +SDR Luminance
> +-------------
> +
> +Traditional SDR content's maximum white luminance is not well defined.
> +Some like to define it at 80 nits, others at 200 nits. It also depends
> +to a large extent on the environmental viewing conditions. In practice
> +this means that we need to define the maximum SDR white luminance, 
> either
> +in nits, or as a ratio.
> +
> +One Windows API defines it as a ratio against 80 nits:
> +https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/dispmprt/ns-dispmprt-_dxgkarg_settargetadjustedcolorimetry2
> +
> +Another Windows API defines it as a nits value:
> +https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/dispmprt/ns-dispmprt-_dxgkarg_settargetadjustedcolorimetry2
> +
> +The Wayland color management proposal uses Apple's definition of EDR 
> as a
> +ratio of the HDR range vs SDR range:
> +https://gitlab.freedesktop.org/swick/wayland-protocols/-/blob/color/unstable/color-management/color.rst#id8

If you're interested: the concept expanded to black levels
https://gitlab.freedesktop.org/swick/wayland-protocols/-/merge_requests/15

> +
> +If a display's maximum HDR white level is correctly reported it is 
> trivial
> +to convert between all of the above representations of SDR white 
> level. If
> +it is not, defining SDR luminance as a nits value, or a ratio vs a 
> fixed
> +nits value is preferred, assuming we are blending in linear space.
> +
> +It is our experience that many HDR displays do not report maximum 
> white
> +level correctly
> +
> +
> +Let There Be Color
> +------------------
> +
> +So far we've only talked about luminance, ignoring colors altogether. 
> Just
> +like in the luminance space, traditionally the color space of display
> +outputs has not been well defined. Similar to how an EOTF defines a
> +mapping of pixel data to an absolute luminance value, the color space
> +maps color information for each pixel onto the CIE 1931 chromaticity
> +space. This can be thought of as a mapping to an absolute, real-life,
> +color value.
> +
> +A color space is defined by its primaries and white point. The 
> primaries
> +and white point are expressed as coordinates in the CIE 1931 color
> +space. Think of the red primary as the reddest red that can be 
> displayed
> +within the color space. Same for green and blue.
> +
> +Examples of color spaces are:
> +
> +.. flat-table::
> +   :header-rows: 1
> +
> +   * - Color Space
> +     - Description
> +
> +   *  - BT 601
> +      - similar to BT 709
> +
> +   *  - BT 709
> +      - used by sRGB content; ~53% of BT 2020
> +
> +   *  - DCI-P3
> +      - used by most HDR displays; ~72% of BT 2020
> +
> +   *  - BT 2020
> +      - standard for most HDR content
> +
> +
> +
> +Color Primaries and White Point
> +-------------------------------
> +
> +Just like displays can currently not represent the entire 0.0005 -
> +10,000 nits HDR range of the PQ 2084 EOTF, they are currently not 
> capable
> +of representing the entire BT.2020 color Gamut. For this reason video
> +content will often specify the color primaries and white point used to
> +master the video, in order to allow displays to be able to map the 
> image
> +as best as possible onto the display's gamut.
> +
> +
> +Displays and Tonemapping
> +------------------------
> +
> +External displays are able to do their own tone and color mapping, 
> based
> +on the mastering luminance, color primaries, and white space defined 
> in
> +the HDR metadata.
> +
> +Some internal panels might not include the complex HW to do tone and 
> color
> +mapping on their own and will require the display driver to perform
> +appropriate mapping.
> +
> +
> +How are we solving the problem?
> +===============================
> +
> +Input and Output Transfer functions
> +-----------------------------------
> +
> +We define an input transfer function on drm_plane to describe the
> +transform from framebuffer to blending space.
> +
> +We define an output transfer function on drm_crtc to describe the
> +transform from blending space to display space.
> +
> +The transfer function can be a pre-defined function, such as PQ EOTF, 
> or
> +a custom LUT. A driver will be able to specify support for specific
> +transfer functions, including custom ones.
> +
> +Defining the transfer function in this way allows us to support in on 
> HW
> +that uses ROMs to support these transforms, as well as on HW that use
> +LUT definitions that are complex and don't map easily onto a standard 
> LUT
> +definition.
> +
> +We will not define per-plane LUTs in this patchset as the scope of our
> +current work only deals with pre-defined transfer functions. This API 
> has
> +the flexibility to add custom 1D or 3D LUTs at a later date.
> +
> +In order to support the existing 1D de-gamma and gamma LUTs on the 
> drm_crtc
> +we will include a "custom 1D" enum value to indicate that the custom 
> gamma and
> +de-gamma 1D LUTs should be used.
> +
> +Possible transfer functions:
> +
> +.. flat-table::
> +   :header-rows: 1
> +
> +   * - Transfer Function
> +     - Description
> +
> +   *  - Gamma 2.2
> +      - a simple 2.2 gamma function
> +
> +   *  - sRGB
> +      - 2.4 gamma with small initial linear section
> +
> +   *  - PQ 2084
> +      - SMPTE ST 2084; used for HDR video and allows for up to 10,000
> nit support
> +
> +   *  - Linear
> +      - Linear relationship between pixel value and luminance value
> +
> +   *  - Custom 1D
> +      - Custom 1D de-gamma and gamma LUTs; one LUT per color
> +
> +   *  - Custom 3D
> +      - Custom 3D LUT (to be defined)

If there actually is hardware which would benefit from the named TF then
this isn't a bad idea. However, it should be made clear where in the
pipeline this is (i.e. that it replaces the 1d lut) and each entry
should have a reference to the exact formula used.

This would not be useful for a generic wayland compositor so you might
want to get the opinion of the Kodi devs.

> +
> +
> +Describing SDR Luminance
> +------------------------------
> +
> +Since many displays do no correctly advertise the HDR white level we
> +propose to define the SDR white level in nits.
> +
> +We define a new drm_plane property to specify the white level of an 
> SDR
> +plane.

Basically the same situation as with named TFs. If this includes some
proprietary tone mapping stuff it should definitely not be generic KMS
API and if hardware between vendors have just slightly different
formulas it shouldn't be either.

> +
> +
> +Defining the color space
> +------------------------
> +
> +We propose to add a new color space property to drm_plane to define a
> +plane's color space.
> +
> +While some color space conversions can be performed with a simple 
> color
> +transformation matrix (CTM) others require a 3D LUT.

Every well-known color space can be converted to other well-known color
spaces with a CTM so this property is just a worse CTM (am I missing
something?).

On the other hand if the hardware *has* a 3D LUT we absolutely want to
be able to use it from user space!

> +
> +
> +Defining mastering color space and luminance
> +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +ToDo
> +
> +
> +
> +Pixel Formats
> +~~~~~~~~~~~~~
> +
> +The pixel formats, such as ARGB8888, ARGB2101010, P010, or FP16 are
> +unrelated to color space and EOTF definitions. HDR pixels can be 
> formatted
> +in different ways but in order to not lose precision HDR content 
> requires
> +at least 10 bpc precision. For this reason ARGB2101010, P010, and FP16 
> are
> +the obvious candidates for HDR. ARGB2101010 and P010 have the 
> advantage
> +of requiring only half the bandwidth as FP16, while FP16 has the 
> advantage
> +of enough precision to operate in a linear space, i.e. without EOTF.
> +
> +
> +
> +Use Cases
> +=========
> +
> +RGB10 HDR plane - composited HDR video & desktop
> +------------------------------------------------
> +
> +A single, composited plane of HDR content. The use-case is a video 
> player
> +on a desktop with the compositor owning the composition of SDR and HDR
> +content. The content shall be PQ BT.2020 formatted. The 
> drm_connector's
> +hdr_output_metadata shall be set.
> +
> +
> +P010 HDR video plane + RGB8 SDR desktop plane
> +---------------------------------------------
> +A normal 8bpc desktop plane, with a P010 HDR video plane underlayed. 
> The
> +HDR plane shall be PQ BT.2020 formatted. The desktop plane shall 
> specify
> +an SDR boost value. The drm_connector's hdr_output_metadata shall be 
> set.
> +
> +
> +One XRGB8888 SDR Plane - HDR output
> +-----------------------------------
> +
> +In order to support a smooth transition we recommend an OS that 
> supports
> +HDR output to provide the hdr_output_metadata on the drm_connector to
> +configure the output for HDR, even when the content is only SDR. This 
> will
> +allow for a smooth transition between SDR-only and HDR content. In 
> this
> +use-case the SDR max luminance value should be provided on the 
> drm_plane.
> +
> +In DCN we will de-PQ or de-Gamma all input in order to blend in linear
> +space. For SDR content we will also apply any desired boost before
> +blending. After blending we will then re-apply the PQ EOTF and do RGB
> +to YCbCr conversion if needed.
> +
> +FP16 HDR linear planes
> +----------------------
> +
> +ToDo
> +
> +
> +User Space
> +==========
> +
> +Wayland
> +-------
> +
> +ToDo
> +
> +
> +ChromeOS Ozone
> +--------------
> +
> +ToDo
> +
> +
> +HW support
> +==========
> +
> +ToDo, describe pipeline on a couple different HW platforms
> +
> +
> +References
> +==========
> +
> +* [1]
> https://en.wikipedia.org/wiki/High-dynamic-range_video#Perceptual_Quantizer
> +* [2] https://en.wikipedia.org/wiki/Transfer_functions_in_imaging
> +
> +
> +Further Reading
> +===============
> +
> +*
> https://gitlab.freedesktop.org/swick/wayland-protocols/-/blob/color/unstable/color-management/color.rst
> +* http://downloads.bbc.co.uk/rd/pubs/whp/whp-pdf-files/WHP309.pdf
> +* 
> https://app.spectracal.com/Documents/White%20Papers/HDR_Demystified.pdf
> +
> +
> diff --git a/Documentation/gpu/rfc/index.rst 
> b/Documentation/gpu/rfc/index.rst
> index a8621f7dab8b..5c8eaf8bf587 100644
> --- a/Documentation/gpu/rfc/index.rst
> +++ b/Documentation/gpu/rfc/index.rst
> @@ -15,3 +15,7 @@ host such documentation:
> 
>  * Once the code has landed move all the documentation to the right 
> places in
>    the main core, helper or driver sections.
> +
> +  .. toctree::
> +
> +  hdr-wide-gamut.rst
> \ No newline at end of file

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC PATCH v2 1/6] drm/doc: Color Management and HDR10 RFC
@ 2021-05-17 17:30     ` Sebastian Wick
  0 siblings, 0 replies; 18+ messages in thread
From: Sebastian Wick @ 2021-05-17 17:30 UTC (permalink / raw)
  To: Harry Wentland
  Cc: Deepak.Sharma, aric.cyr, Krunoslav.Kovac, mcasas,
	Shashank.Sharma, dri-devel, Shirish.S, ppaalanen, hersenxs.wu,
	amd-gfx, laurentiu.palcu, Bhawanpreet.Lakha, Nicholas.Kazlauskas,
	ville.syrjala, Vitaly.Prosyak

On 2021-05-14 23:07, Harry Wentland wrote:
> Use the new DRM RFC doc section to capture the RFC previously only
> described in the cover letter at
> https://patchwork.freedesktop.org/series/89506/
> 
> Update the RFC based on feedback received:
>  * don't use color_encoding property to define color space
>  * expand on reason for SDR luminance definition
>  * define input/output transfer functions for luminance space 
> transforms,
>    rather than defining the luminance space of an input directly
> 
> Signed-off-by: Harry Wentland <harry.wentland@amd.com>
> ---
>  Documentation/gpu/rfc/hdr-wide-gamut.rst | 416 +++++++++++++++++++++++
>  Documentation/gpu/rfc/index.rst          |   4 +
>  2 files changed, 420 insertions(+)
>  create mode 100644 Documentation/gpu/rfc/hdr-wide-gamut.rst
> 
> diff --git a/Documentation/gpu/rfc/hdr-wide-gamut.rst
> b/Documentation/gpu/rfc/hdr-wide-gamut.rst
> new file mode 100644
> index 000000000000..132898668eac
> --- /dev/null
> +++ b/Documentation/gpu/rfc/hdr-wide-gamut.rst
> @@ -0,0 +1,416 @@
> +==============================
> +HDR & Wide Color Gamut Support
> +==============================
> +
> +.. role:: wy-text-strike
> +
> +ToDo
> +====
> +
> +* :wy-text-strike:`Reformat as RST kerneldoc` - done
> +* :wy-text-strike:`Don't use color_encoding for color_space 
> definitions` - done
> +* :wy-text-strike:`Update SDR luminance description and reasoning` - 
> done
> +* :wy-text-strike:`Clarify 3D LUT required for some color space
> transformations` - done
> +* :wy-text-strike:`Highlight need for named color space and EOTF
> definitions` - done
> +* :wy-text-strike:`Define transfer function API` - done
> +* :wy-text-strike:`Draft upstream plan` - done
> +* Reference to wayland and/or Chrome plans
> +* Sketch view of HW pipeline for couple of HW implementations
> +
> +
> +Upstream Plan
> +=============
> +
> +* Reach consensus on DRM/KMS API
> +* Implement support in amdgpu
> +* Implement IGT tests
> +* Add API support to Weston, ChromiumOS, or other canonical
> open-source project interested in HDR
> +* Merge user-space
> +* Merge kernel patches
> +
> +
> +Introduction
> +============
> +
> +We are looking to enable HDR support for a couple of single-plane and
> +multi-plane scenarios. To do this effectively we recommend new 
> interfaces
> +to drm_plane. Below I'll give a bit of background on HDR and why we
> +propose these interfaces.
> +
> +
> +Overview and background
> +=======================
> +
> +Defining a pixel's luminance
> +----------------------------
> +
> +The luminance space of pixels in a framebuffer/plane presented to the
> +display is not well defined in the DRM/KMS APIs. It is usually assumed 
> to
> +be in a 2.2 or 2.4 gamma space and has no mapping to an absolute 
> luminance
> +value; it is interpreted in relative terms.
> +
> +Luminance can be measured and described in absolute terms as candela
> +per meter squared, or cd/m2, or nits. Even though a pixel value can be
> +mapped to luminance in a linear fashion to do so without losing a lot 
> of
> +detail requires 16-bpc color depth. The reason for this is that human
> +perception can distinguish roughly between a 0.5-1% luminance delta. A
> +linear representation is suboptimal, wasting precision in the 
> highlights
> +and losing precision in the shadows.
> +
> +A gamma curve is a decent approximation to a human's perception of
> +luminance, but the PQ (perceptual quantizer) function [1] improves on
> +it. It also defines the luminance values in absolute terms, with the
> +highest value being 10,000 nits and the lowest 0.0005 nits.
> +
> +Using a content that's defined in PQ space we can approximate the real
> +world in a much better way.
> +
> +Here are some examples of real-life objects and their approximate
> +luminance values:
> +
> +.. flat-table::
> +   :header-rows: 1
> +
> +   * - Object
> +     - Luminance in nits
> +
> +   *  - Fluorescent light
> +      - 10,000
> +
> +   *  - Highlights
> +      - 1,000 - sunlight
> +
> +   *  - White Objects
> +      - 250 - 1,000
> +
> +   *  - Typical Objects
> +      - 1 - 250
> +
> +   *  - Shadows
> +      - 0.01 - 1
> +
> +   *  - Ultra Blacks
> +      - 0 - 0.0005
> +
> +Transfer functions
> +------------------
> +
> +Traditionally we used the terms gamma and de-gamma to describe the
> +encoding of a pixel's luminance value and the operation to transfer 
> from
> +a linear luminance space to the non-linear space used to encode the
> +pixels. Since some newer encodings don't use a gamma curve I suggest
> +we refer to non-linear encodings using the terms EOTF, and OETF[2], or
> +simply as transfer function in general.
> +
> +The EOTF (Electro-Optical Transfer Function) describes how to transfer
> +from an electrical signal to an optical signal. This was traditionally
> +done by the de-gamma function.
> +
> +The OETF (Opto Electronic Transfer Function) describes how to transfer
> +from an optical signal to an electronic signal. This was traditionally
> +done by the gamma function.
> +
> +More generally we can name the transfer function describing the 
> transform
> +between scanout and blending space as the **input transfer function**, 
> and
> +the transfer function describing the transform from blending space to 
> the
> +output space as **output transfer function**.
> +
> +
> +Mastering Luminances
> +--------------------
> +
> +Even though we are able to describe the absolute luminance of a pixel
> +using the PQ 2084 EOTF we are presented with physical limitations of 
> the
> +display technologies on the market today. Here are a few examples of
> +luminance ranges of displays.
> +
> +.. flat-table::
> +   :header-rows: 1
> +
> +   * - Display
> +     - Luminance range in nits
> +
> +   *  - Typical PC display
> +      - 0.3 - 200
> +
> +   *  - Excellent LCD HDTV
> +      - 0.3 - 400
> +
> +   *  - HDR LCD w/ local dimming
> +      - 0.05 - 1,500
> +
> +Since no display can currently show the full 0.0005 to 10,000 nits
> +luminance range of PQ the display will need to tone-map the HDR 
> content,
> +i.e to fit the content within a display's capabilities. To assist
> +with tone-mapping HDR content is usually accompanied by a metadata
> +that describes (among other things) the minimum and maximum mastering
> +luminance, i.e. the maximum and minimum luminance of the display that
> +was used to master the HDR content.
> +
> +The HDR metadata is currently defined on the drm_connector via the
> +hdr_output_metadata blob property.
> +
> +It might be useful to define per-plane hdr metadata, as different 
> planes
> +might have been mastered differently.

There really is not reason to have the HDR metadata anywhere but the
connector. If you drive the display in PQ mode and you just map content
into the PQ space you won't do any color or gamut mapping which is the
only reason why you'd want access to the HDR metadata.

User space can generate suitable connector metadata from the clients
metadata.

> +
> +
> +SDR Luminance
> +-------------
> +
> +Traditional SDR content's maximum white luminance is not well defined.
> +Some like to define it at 80 nits, others at 200 nits. It also depends
> +to a large extent on the environmental viewing conditions. In practice
> +this means that we need to define the maximum SDR white luminance, 
> either
> +in nits, or as a ratio.
> +
> +One Windows API defines it as a ratio against 80 nits:
> +https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/dispmprt/ns-dispmprt-_dxgkarg_settargetadjustedcolorimetry2
> +
> +Another Windows API defines it as a nits value:
> +https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/dispmprt/ns-dispmprt-_dxgkarg_settargetadjustedcolorimetry2
> +
> +The Wayland color management proposal uses Apple's definition of EDR 
> as a
> +ratio of the HDR range vs SDR range:
> +https://gitlab.freedesktop.org/swick/wayland-protocols/-/blob/color/unstable/color-management/color.rst#id8

If you're interested: the concept expanded to black levels
https://gitlab.freedesktop.org/swick/wayland-protocols/-/merge_requests/15

> +
> +If a display's maximum HDR white level is correctly reported it is 
> trivial
> +to convert between all of the above representations of SDR white 
> level. If
> +it is not, defining SDR luminance as a nits value, or a ratio vs a 
> fixed
> +nits value is preferred, assuming we are blending in linear space.
> +
> +It is our experience that many HDR displays do not report maximum 
> white
> +level correctly
> +
> +
> +Let There Be Color
> +------------------
> +
> +So far we've only talked about luminance, ignoring colors altogether. 
> Just
> +like in the luminance space, traditionally the color space of display
> +outputs has not been well defined. Similar to how an EOTF defines a
> +mapping of pixel data to an absolute luminance value, the color space
> +maps color information for each pixel onto the CIE 1931 chromaticity
> +space. This can be thought of as a mapping to an absolute, real-life,
> +color value.
> +
> +A color space is defined by its primaries and white point. The 
> primaries
> +and white point are expressed as coordinates in the CIE 1931 color
> +space. Think of the red primary as the reddest red that can be 
> displayed
> +within the color space. Same for green and blue.
> +
> +Examples of color spaces are:
> +
> +.. flat-table::
> +   :header-rows: 1
> +
> +   * - Color Space
> +     - Description
> +
> +   *  - BT 601
> +      - similar to BT 709
> +
> +   *  - BT 709
> +      - used by sRGB content; ~53% of BT 2020
> +
> +   *  - DCI-P3
> +      - used by most HDR displays; ~72% of BT 2020
> +
> +   *  - BT 2020
> +      - standard for most HDR content
> +
> +
> +
> +Color Primaries and White Point
> +-------------------------------
> +
> +Just like displays can currently not represent the entire 0.0005 -
> +10,000 nits HDR range of the PQ 2084 EOTF, they are currently not 
> capable
> +of representing the entire BT.2020 color Gamut. For this reason video
> +content will often specify the color primaries and white point used to
> +master the video, in order to allow displays to be able to map the 
> image
> +as best as possible onto the display's gamut.
> +
> +
> +Displays and Tonemapping
> +------------------------
> +
> +External displays are able to do their own tone and color mapping, 
> based
> +on the mastering luminance, color primaries, and white space defined 
> in
> +the HDR metadata.
> +
> +Some internal panels might not include the complex HW to do tone and 
> color
> +mapping on their own and will require the display driver to perform
> +appropriate mapping.
> +
> +
> +How are we solving the problem?
> +===============================
> +
> +Input and Output Transfer functions
> +-----------------------------------
> +
> +We define an input transfer function on drm_plane to describe the
> +transform from framebuffer to blending space.
> +
> +We define an output transfer function on drm_crtc to describe the
> +transform from blending space to display space.
> +
> +The transfer function can be a pre-defined function, such as PQ EOTF, 
> or
> +a custom LUT. A driver will be able to specify support for specific
> +transfer functions, including custom ones.
> +
> +Defining the transfer function in this way allows us to support in on 
> HW
> +that uses ROMs to support these transforms, as well as on HW that use
> +LUT definitions that are complex and don't map easily onto a standard 
> LUT
> +definition.
> +
> +We will not define per-plane LUTs in this patchset as the scope of our
> +current work only deals with pre-defined transfer functions. This API 
> has
> +the flexibility to add custom 1D or 3D LUTs at a later date.
> +
> +In order to support the existing 1D de-gamma and gamma LUTs on the 
> drm_crtc
> +we will include a "custom 1D" enum value to indicate that the custom 
> gamma and
> +de-gamma 1D LUTs should be used.
> +
> +Possible transfer functions:
> +
> +.. flat-table::
> +   :header-rows: 1
> +
> +   * - Transfer Function
> +     - Description
> +
> +   *  - Gamma 2.2
> +      - a simple 2.2 gamma function
> +
> +   *  - sRGB
> +      - 2.4 gamma with small initial linear section
> +
> +   *  - PQ 2084
> +      - SMPTE ST 2084; used for HDR video and allows for up to 10,000
> nit support
> +
> +   *  - Linear
> +      - Linear relationship between pixel value and luminance value
> +
> +   *  - Custom 1D
> +      - Custom 1D de-gamma and gamma LUTs; one LUT per color
> +
> +   *  - Custom 3D
> +      - Custom 3D LUT (to be defined)

If there actually is hardware which would benefit from the named TF then
this isn't a bad idea. However, it should be made clear where in the
pipeline this is (i.e. that it replaces the 1d lut) and each entry
should have a reference to the exact formula used.

This would not be useful for a generic wayland compositor so you might
want to get the opinion of the Kodi devs.

> +
> +
> +Describing SDR Luminance
> +------------------------------
> +
> +Since many displays do no correctly advertise the HDR white level we
> +propose to define the SDR white level in nits.
> +
> +We define a new drm_plane property to specify the white level of an 
> SDR
> +plane.

Basically the same situation as with named TFs. If this includes some
proprietary tone mapping stuff it should definitely not be generic KMS
API and if hardware between vendors have just slightly different
formulas it shouldn't be either.

> +
> +
> +Defining the color space
> +------------------------
> +
> +We propose to add a new color space property to drm_plane to define a
> +plane's color space.
> +
> +While some color space conversions can be performed with a simple 
> color
> +transformation matrix (CTM) others require a 3D LUT.

Every well-known color space can be converted to other well-known color
spaces with a CTM so this property is just a worse CTM (am I missing
something?).

On the other hand if the hardware *has* a 3D LUT we absolutely want to
be able to use it from user space!

> +
> +
> +Defining mastering color space and luminance
> +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +ToDo
> +
> +
> +
> +Pixel Formats
> +~~~~~~~~~~~~~
> +
> +The pixel formats, such as ARGB8888, ARGB2101010, P010, or FP16 are
> +unrelated to color space and EOTF definitions. HDR pixels can be 
> formatted
> +in different ways but in order to not lose precision HDR content 
> requires
> +at least 10 bpc precision. For this reason ARGB2101010, P010, and FP16 
> are
> +the obvious candidates for HDR. ARGB2101010 and P010 have the 
> advantage
> +of requiring only half the bandwidth as FP16, while FP16 has the 
> advantage
> +of enough precision to operate in a linear space, i.e. without EOTF.
> +
> +
> +
> +Use Cases
> +=========
> +
> +RGB10 HDR plane - composited HDR video & desktop
> +------------------------------------------------
> +
> +A single, composited plane of HDR content. The use-case is a video 
> player
> +on a desktop with the compositor owning the composition of SDR and HDR
> +content. The content shall be PQ BT.2020 formatted. The 
> drm_connector's
> +hdr_output_metadata shall be set.
> +
> +
> +P010 HDR video plane + RGB8 SDR desktop plane
> +---------------------------------------------
> +A normal 8bpc desktop plane, with a P010 HDR video plane underlayed. 
> The
> +HDR plane shall be PQ BT.2020 formatted. The desktop plane shall 
> specify
> +an SDR boost value. The drm_connector's hdr_output_metadata shall be 
> set.
> +
> +
> +One XRGB8888 SDR Plane - HDR output
> +-----------------------------------
> +
> +In order to support a smooth transition we recommend an OS that 
> supports
> +HDR output to provide the hdr_output_metadata on the drm_connector to
> +configure the output for HDR, even when the content is only SDR. This 
> will
> +allow for a smooth transition between SDR-only and HDR content. In 
> this
> +use-case the SDR max luminance value should be provided on the 
> drm_plane.
> +
> +In DCN we will de-PQ or de-Gamma all input in order to blend in linear
> +space. For SDR content we will also apply any desired boost before
> +blending. After blending we will then re-apply the PQ EOTF and do RGB
> +to YCbCr conversion if needed.
> +
> +FP16 HDR linear planes
> +----------------------
> +
> +ToDo
> +
> +
> +User Space
> +==========
> +
> +Wayland
> +-------
> +
> +ToDo
> +
> +
> +ChromeOS Ozone
> +--------------
> +
> +ToDo
> +
> +
> +HW support
> +==========
> +
> +ToDo, describe pipeline on a couple different HW platforms
> +
> +
> +References
> +==========
> +
> +* [1]
> https://en.wikipedia.org/wiki/High-dynamic-range_video#Perceptual_Quantizer
> +* [2] https://en.wikipedia.org/wiki/Transfer_functions_in_imaging
> +
> +
> +Further Reading
> +===============
> +
> +*
> https://gitlab.freedesktop.org/swick/wayland-protocols/-/blob/color/unstable/color-management/color.rst
> +* http://downloads.bbc.co.uk/rd/pubs/whp/whp-pdf-files/WHP309.pdf
> +* 
> https://app.spectracal.com/Documents/White%20Papers/HDR_Demystified.pdf
> +
> +
> diff --git a/Documentation/gpu/rfc/index.rst 
> b/Documentation/gpu/rfc/index.rst
> index a8621f7dab8b..5c8eaf8bf587 100644
> --- a/Documentation/gpu/rfc/index.rst
> +++ b/Documentation/gpu/rfc/index.rst
> @@ -15,3 +15,7 @@ host such documentation:
> 
>  * Once the code has landed move all the documentation to the right 
> places in
>    the main core, helper or driver sections.
> +
> +  .. toctree::
> +
> +  hdr-wide-gamut.rst
> \ No newline at end of file
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC PATCH v2 0/6] A drm_plane API to support HDR planes
  2021-05-14 21:07 ` Harry Wentland
@ 2021-05-18  7:58   ` Pekka Paalanen
  -1 siblings, 0 replies; 18+ messages in thread
From: Pekka Paalanen @ 2021-05-18  7:58 UTC (permalink / raw)
  To: Harry Wentland
  Cc: Deepak.Sharma, Krunoslav.Kovac, mcasas, Shashank.Sharma,
	dri-devel, Shirish.S, sebastian, hersenxs.wu, amd-gfx,
	laurentiu.palcu, Bhawanpreet.Lakha, Nicholas.Kazlauskas,
	Vitaly.Prosyak

[-- Attachment #1: Type: text/plain, Size: 462 bytes --]

On Fri, 14 May 2021 17:07:14 -0400
Harry Wentland <harry.wentland@amd.com> wrote:

> We are looking to enable HDR support for a couple of single-plane and
> multi-plane scenarios. To do this effectively we recommend new interfaces
> to drm_plane. The first patch gives a bit of background on HDR and why we
> propose these interfaces.
> 
> v2:

For everyone's information, the discussion is still on-going in the
first email thread.


Thanks,
pq

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC PATCH v2 0/6] A drm_plane API to support HDR planes
@ 2021-05-18  7:58   ` Pekka Paalanen
  0 siblings, 0 replies; 18+ messages in thread
From: Pekka Paalanen @ 2021-05-18  7:58 UTC (permalink / raw)
  To: Harry Wentland
  Cc: Deepak.Sharma, aric.cyr, Krunoslav.Kovac, mcasas,
	Shashank.Sharma, dri-devel, Shirish.S, sebastian, hersenxs.wu,
	amd-gfx, laurentiu.palcu, Bhawanpreet.Lakha, Nicholas.Kazlauskas,
	ville.syrjala, Vitaly.Prosyak


[-- Attachment #1.1: Type: text/plain, Size: 462 bytes --]

On Fri, 14 May 2021 17:07:14 -0400
Harry Wentland <harry.wentland@amd.com> wrote:

> We are looking to enable HDR support for a couple of single-plane and
> multi-plane scenarios. To do this effectively we recommend new interfaces
> to drm_plane. The first patch gives a bit of background on HDR and why we
> propose these interfaces.
> 
> v2:

For everyone's information, the discussion is still on-going in the
first email thread.


Thanks,
pq

[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

[-- Attachment #2: Type: text/plain, Size: 154 bytes --]

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2021-05-18  7:58 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-14 21:07 [RFC PATCH v2 0/6] A drm_plane API to support HDR planes Harry Wentland
2021-05-14 21:07 ` Harry Wentland
2021-05-14 21:07 ` [RFC PATCH v2 1/6] drm/doc: Color Management and HDR10 RFC Harry Wentland
2021-05-14 21:07   ` Harry Wentland
2021-05-17 17:30   ` Sebastian Wick
2021-05-17 17:30     ` Sebastian Wick
2021-05-14 21:07 ` [RFC PATCH v2 2/6] drm/color: Add transfer functions for HDR/SDR on drm_plane Harry Wentland
2021-05-14 21:07   ` Harry Wentland
2021-05-14 21:07 ` [RFC PATCH v2 3/6] drm/color: Add output transfer function to crtc Harry Wentland
2021-05-14 21:07   ` Harry Wentland
2021-05-14 21:07 ` [RFC PATCH v2 4/6] drm/color: Add sdr boost property Harry Wentland
2021-05-14 21:07   ` Harry Wentland
2021-05-14 21:07 ` [RFC PATCH v2 5/6] drm/color: Add color space plane property Harry Wentland
2021-05-14 21:07   ` Harry Wentland
2021-05-14 21:07 ` [RFC PATCH v2 6/6] drm/amd/display: reformat YCbCr-RGB conversion matrix Harry Wentland
2021-05-14 21:07   ` Harry Wentland
2021-05-18  7:58 ` [RFC PATCH v2 0/6] A drm_plane API to support HDR planes Pekka Paalanen
2021-05-18  7:58   ` Pekka Paalanen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.