[PATCH v4 11/32] drm/amd/display: add plane blend LUT and TF driver-specific properties

Harry Wentland harry.wentland at amd.com
Wed Nov 15 18:27:22 UTC 2023



On 2023-10-05 13:15, Melissa Wen wrote:
> From: Joshua Ashton <joshua at froggi.es>
> 
> 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)
> 
> Signed-off-by: Joshua Ashton <joshua at froggi.es>
> Signed-off-by: Melissa Wen <mwen at igalia.com>

Reviewed-by: Harry Wentland <harry.wentland at amd.com>

Harry

> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h      | 22 ++++++++++++
>  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 12 +++++++
>  .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 21 +++++++++++
>  .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   | 36 +++++++++++++++++++
>  4 files changed, 91 insertions(+)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> index af70db4f6b4b..dee35d208493 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> @@ -402,6 +402,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
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> index 0e2a04a3caf3..1b96c742d747 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> @@ -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 {
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
> index d3c7f9a13a61..82c554662faa 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
> @@ -273,6 +273,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
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> index a381b3558bd1..f1070ca7076a 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> @@ -1339,6 +1339,7 @@ static void dm_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 *
> @@ -1364,10 +1365,13 @@ dm_drm_plane_duplicate_state(struct drm_plane *plane)
>  		drm_property_blob_get(dm_plane_state->shaper_lut);
>  	if (dm_plane_state->lut3d)
>  		drm_property_blob_get(dm_plane_state->lut3d);
> +	if (dm_plane_state->blend_lut)
> +		drm_property_blob_get(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;
>  }
> @@ -1442,6 +1446,8 @@ static void dm_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);
> @@ -1488,6 +1494,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
> @@ -1540,6 +1557,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",
> @@ -1575,6 +1605,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;
>  	}



More information about the amd-gfx mailing list