Add 3D LUT property for plane gamma correction using a 3D lookup table.
3D LUT is more effective when applying in non-linear space, therefore,
userpace may need one 1D LUT (shaper) before it to delinearize content
and another 1D LUT after 3D LUT (blend) to linearize content again for
blending. The next patches add these 1D LUTs to the plane color mgmt
pipeline.
Signed-off-by: Melissa Wen <mwen@igalia.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 14 +++++++++++
drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 10 ++++++++
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 5 ++++
.../amd/display/amdgpu_dm/amdgpu_dm_plane.c | 24 +++++++++++++++++++
4 files changed, 53 insertions(+)
@@ -1332,6 +1332,20 @@ amdgpu_display_create_color_properties(struct amdgpu_device *adev)
return -ENOMEM;
adev->mode_info.plane_hdr_mult_property = prop;
+ prop = drm_property_create(adev_to_drm(adev),
+ DRM_MODE_PROP_BLOB,
+ "AMD_PLANE_LUT3D", 0);
+ if (!prop)
+ return -ENOMEM;
+ adev->mode_info.plane_lut3d_property = prop;
+
+ prop = drm_property_create_range(adev_to_drm(adev),
+ DRM_MODE_PROP_IMMUTABLE,
+ "AMD_PLANE_LUT3D_SIZE", 0, UINT_MAX);
+ if (!prop)
+ return -ENOMEM;
+ adev->mode_info.plane_lut3d_size_property = prop;
+
return 0;
}
#endif
@@ -391,6 +391,16 @@ struct amdgpu_mode_info {
* @plane_hdr_mult_property:
*/
struct drm_property *plane_hdr_mult_property;
+ /**
+ * @plane_lut3d_property: Plane property for gamma correction using a
+ * 3D LUT (pre-blending).
+ */
+ struct drm_property *plane_lut3d_property;
+ /**
+ * @plane_degamma_lut_size_property: Plane property to define the max
+ * size of 3D LUT as supported by the driver (read-only).
+ */
+ struct drm_property *plane_lut3d_size_property;
#endif
};
@@ -748,6 +748,11 @@ struct dm_plane_state {
* S31.32 sign-magnitude.
*/
__u64 hdr_mult;
+ /**
+ * @lut3d: 3D lookup table blob. The blob (if not NULL) is an array of
+ * &struct drm_color_lut.
+ */
+ struct drm_property_blob *lut3d;
#endif
};
@@ -1347,7 +1347,10 @@ dm_drm_plane_duplicate_state(struct drm_plane *plane)
#ifdef CONFIG_STEAM_DECK
if (dm_plane_state->degamma_lut)
drm_property_blob_get(dm_plane_state->degamma_lut);
+ if (dm_plane_state->lut3d)
+ drm_property_blob_get(dm_plane_state->lut3d);
#endif
+
return &dm_plane_state->base;
}
@@ -1416,7 +1419,9 @@ static void dm_drm_plane_destroy_state(struct drm_plane *plane,
struct dm_plane_state *dm_plane_state = to_dm_plane_state(state);
#ifdef CONFIG_STEAM_DECK
drm_property_blob_put(dm_plane_state->degamma_lut);
+ drm_property_blob_put(dm_plane_state->lut3d);
#endif
+
if (dm_plane_state->dc_state)
dc_plane_state_release(dm_plane_state->dc_state);
@@ -1488,6 +1493,14 @@ dm_plane_attach_color_mgmt_properties(struct amdgpu_display_manager *dm,
drm_object_attach_property(&plane->base,
dm->adev->mode_info.plane_hdr_mult_property,
AMDGPU_HDR_MULT_DEFAULT);
+
+ if (dm->dc->caps.color.dpp.hw_3d_lut) {
+ drm_object_attach_property(&plane->base,
+ dm->adev->mode_info.plane_lut3d_property, 0);
+ drm_object_attach_property(&plane->base,
+ dm->adev->mode_info.plane_lut3d_size_property,
+ MAX_COLOR_3DLUT_ENTRIES);
+ }
}
static int
@@ -1518,6 +1531,14 @@ dm_atomic_plane_set_property(struct drm_plane *plane,
dm_plane_state->hdr_mult = val;
dm_plane_state->base.color_mgmt_changed = 1;
}
+ } else if (property == adev->mode_info.plane_lut3d_property) {
+ ret = amdgpu_dm_replace_property_blob_from_id(plane->dev,
+ &dm_plane_state->lut3d,
+ val,
+ -1, sizeof(struct drm_color_lut),
+ &replaced);
+ dm_plane_state->base.color_mgmt_changed |= replaced;
+ return ret;
} else {
drm_dbg_atomic(plane->dev,
"[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n",
@@ -1546,6 +1567,9 @@ dm_atomic_plane_get_property(struct drm_plane *plane,
*val = dm_plane_state->degamma_tf;
} else if (property == adev->mode_info.plane_hdr_mult_property) {
*val = dm_plane_state->hdr_mult;
+ } else if (property == adev->mode_info.plane_lut3d_property) {
+ *val = (dm_plane_state->lut3d) ?
+ dm_plane_state->lut3d->base.id : 0;
} else {
return -EINVAL;
}