]> Git Repo - linux.git/commitdiff
drm/amd/display: add plane blend LUT and TF driver-specific properties
authorJoshua Ashton <[email protected]>
Thu, 16 Nov 2023 19:57:51 +0000 (18:57 -0100)
committerAlex Deucher <[email protected]>
Wed, 13 Dec 2023 21:08:00 +0000 (16:08 -0500)
Blend 1D LUT or a pre-defined transfer function (TF) can be set to
linearize content before blending, so that it's positioned just before
blending planes in the AMD color mgmt pipeline, and after 3D LUT
(non-linear space). Shaper and Blend LUTs are 1D LUTs that sandwich 3D
LUT. Drivers should advertize blend properties according to HW caps.

There is no blend ROM for pre-defined TF. When setting blend TF (!=
Identity) and LUT at the same time, the color module will combine the
pre-defined TF and the custom LUT values into the LUT that's actually
programmed.

v3:
- spell out TF+LUT behavior in the commit and comments (Harry)

v5:
- get blend blob correctly

Reviewed-by: Harry Wentland <[email protected]>
Signed-off-by: Joshua Ashton <[email protected]>
Signed-off-by: Melissa Wen <[email protected]>
Signed-off-by: Alex Deucher <[email protected]>
drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c

index 981a2eb252570032d12b91db86efe32dbebe21a1..6ff37272ccad42ebb6908fbf215670cb6cde9fbd 100644 (file)
@@ -403,6 +403,28 @@ struct amdgpu_mode_info {
         * entries for 3D LUT array is the 3D LUT size cubed;
         */
        struct drm_property *plane_lut3d_size_property;
+       /**
+        * @plane_blend_lut_property: Plane property for output gamma before
+        * blending. Userspace set a blend LUT to convert colors after 3D LUT
+        * conversion. It works as a post-3DLUT 1D LUT. With shaper LUT, they
+        * are sandwiching 3D LUT with two 1D LUT. If plane_blend_tf_property
+        * != Identity TF, AMD color module will combine the user LUT values
+        * with pre-defined TF into the LUT parameters to be programmed.
+        */
+       struct drm_property *plane_blend_lut_property;
+       /**
+        * @plane_blend_lut_size_property: Plane property to define the max
+        * size of blend LUT as supported by the driver (read-only).
+        */
+       struct drm_property *plane_blend_lut_size_property;
+       /**
+        * @plane_blend_tf_property: Plane property to set a predefined
+        * transfer function for pre-blending blend/out_gamma (after applying
+        * 3D LUT) with or without LUT. There is no blend ROM, but we can use
+        * AMD color modules to program LUT parameters from predefined TF (or
+        * from a combination of pre-defined TF and the custom 1D LUT).
+        */
+       struct drm_property *plane_blend_tf_property;
 };
 
 #define AMDGPU_MAX_BL_LEVEL 0xFF
index 9bee60cbc2b5958be0324ffbf09982ff0a5a1176..a9a0bc875b783f40efa1be52f091deffc836f0e5 100644 (file)
@@ -800,6 +800,18 @@ struct dm_plane_state {
         * &struct drm_color_lut.
         */
        struct drm_property_blob *lut3d;
+       /**
+        * @blend_lut: blend lut lookup table blob. The blob (if not NULL) is an
+        * array of &struct drm_color_lut.
+        */
+       struct drm_property_blob *blend_lut;
+       /**
+        * @blend_tf:
+        *
+        * Pre-defined transfer function for converting plane pixel data before
+        * applying blend LUT.
+        */
+       enum amdgpu_transfer_function blend_tf;
 };
 
 struct dm_crtc_state {
index 866c6f1d3d99608601b787e43f2293b98ceeceaa..425676f5afb7c853c657c4be39a960b608b87f41 100644 (file)
@@ -274,6 +274,27 @@ amdgpu_dm_create_color_properties(struct amdgpu_device *adev)
                return -ENOMEM;
        adev->mode_info.plane_lut3d_size_property = prop;
 
+       prop = drm_property_create(adev_to_drm(adev),
+                                  DRM_MODE_PROP_BLOB,
+                                  "AMD_PLANE_BLEND_LUT", 0);
+       if (!prop)
+               return -ENOMEM;
+       adev->mode_info.plane_blend_lut_property = prop;
+
+       prop = drm_property_create_range(adev_to_drm(adev),
+                                        DRM_MODE_PROP_IMMUTABLE,
+                                        "AMD_PLANE_BLEND_LUT_SIZE", 0, UINT_MAX);
+       if (!prop)
+               return -ENOMEM;
+       adev->mode_info.plane_blend_lut_size_property = prop;
+
+       prop = amdgpu_create_tf_property(adev_to_drm(adev),
+                                        "AMD_PLANE_BLEND_TF",
+                                        amdgpu_eotf);
+       if (!prop)
+               return -ENOMEM;
+       adev->mode_info.plane_blend_tf_property = prop;
+
        return 0;
 }
 #endif
index 7f0de29889f0590f1f34d43dbba5f0070a9588a7..35a4732483ba74015a3e7d4fdafc6043263d7757 100644 (file)
@@ -1344,6 +1344,7 @@ static void amdgpu_dm_plane_drm_plane_reset(struct drm_plane *plane)
        amdgpu_state->degamma_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT;
        amdgpu_state->hdr_mult = AMDGPU_HDR_MULT_DEFAULT;
        amdgpu_state->shaper_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT;
+       amdgpu_state->blend_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT;
 }
 
 static struct drm_plane_state *amdgpu_dm_plane_drm_plane_duplicate_state(struct drm_plane *plane)
@@ -1371,10 +1372,14 @@ static struct drm_plane_state *amdgpu_dm_plane_drm_plane_duplicate_state(struct
        if (old_dm_plane_state->lut3d)
                dm_plane_state->lut3d =
                        drm_property_blob_get(old_dm_plane_state->lut3d);
+       if (old_dm_plane_state->blend_lut)
+               dm_plane_state->blend_lut =
+                       drm_property_blob_get(old_dm_plane_state->blend_lut);
 
        dm_plane_state->degamma_tf = old_dm_plane_state->degamma_tf;
        dm_plane_state->hdr_mult = old_dm_plane_state->hdr_mult;
        dm_plane_state->shaper_tf = old_dm_plane_state->shaper_tf;
+       dm_plane_state->blend_tf = old_dm_plane_state->blend_tf;
 
        return &dm_plane_state->base;
 }
@@ -1449,6 +1454,8 @@ static void amdgpu_dm_plane_drm_plane_destroy_state(struct drm_plane *plane,
                drm_property_blob_put(dm_plane_state->lut3d);
        if (dm_plane_state->shaper_lut)
                drm_property_blob_put(dm_plane_state->shaper_lut);
+       if (dm_plane_state->blend_lut)
+               drm_property_blob_put(dm_plane_state->blend_lut);
 
        if (dm_plane_state->dc_state)
                dc_plane_state_release(dm_plane_state->dc_state);
@@ -1498,6 +1505,17 @@ dm_atomic_plane_attach_color_mgmt_properties(struct amdgpu_display_manager *dm,
                                           mode_info.plane_lut3d_size_property,
                                           MAX_COLOR_3DLUT_SIZE);
        }
+
+       if (dpp_color_caps.ogam_ram) {
+               drm_object_attach_property(&plane->base,
+                                          mode_info.plane_blend_lut_property, 0);
+               drm_object_attach_property(&plane->base,
+                                          mode_info.plane_blend_lut_size_property,
+                                          MAX_COLOR_LUT_ENTRIES);
+               drm_object_attach_property(&plane->base,
+                                          mode_info.plane_blend_tf_property,
+                                          AMDGPU_TRANSFER_FUNCTION_DEFAULT);
+       }
 }
 
 static int
@@ -1550,6 +1568,19 @@ dm_atomic_plane_set_property(struct drm_plane *plane,
                                                        &replaced);
                dm_plane_state->base.color_mgmt_changed |= replaced;
                return ret;
+       } else if (property == adev->mode_info.plane_blend_lut_property) {
+               ret = drm_property_replace_blob_from_id(plane->dev,
+                                                       &dm_plane_state->blend_lut,
+                                                       val, -1,
+                                                       sizeof(struct drm_color_lut),
+                                                       &replaced);
+               dm_plane_state->base.color_mgmt_changed |= replaced;
+               return ret;
+       } else if (property == adev->mode_info.plane_blend_tf_property) {
+               if (dm_plane_state->blend_tf != val) {
+                       dm_plane_state->blend_tf = val;
+                       dm_plane_state->base.color_mgmt_changed = 1;
+               }
        } else {
                drm_dbg_atomic(plane->dev,
                               "[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n",
@@ -1585,6 +1616,12 @@ dm_atomic_plane_get_property(struct drm_plane *plane,
        } else  if (property == adev->mode_info.plane_lut3d_property) {
                *val = (dm_plane_state->lut3d) ?
                        dm_plane_state->lut3d->base.id : 0;
+       } else  if (property == adev->mode_info.plane_blend_lut_property) {
+               *val = (dm_plane_state->blend_lut) ?
+                       dm_plane_state->blend_lut->base.id : 0;
+       } else if (property == adev->mode_info.plane_blend_tf_property) {
+               *val = dm_plane_state->blend_tf;
+
        } else {
                return -EINVAL;
        }
This page took 0.069095 seconds and 4 git commands to generate.