Commit 0ef47454 authored by Joshua Ashton's avatar Joshua Ashton Committed by Alex Deucher

drm/amd/display: add plane blend LUT and TF driver-specific properties

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: default avatarHarry Wentland <harry.wentland@amd.com>
Signed-off-by: default avatarJoshua Ashton <joshua@froggi.es>
Signed-off-by: default avatarMelissa Wen <mwen@igalia.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent f545d824
......@@ -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
......
......@@ -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 {
......
......@@ -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
......
......@@ -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;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment