[PATCH] drm/amd: Query and use ACPI backlight caps

Wentland, Harry Harry.Wentland at amd.com
Wed Nov 21 21:42:32 UTC 2018


On 2018-11-20 10:16 a.m., David Francis wrote:
> ACPI ATIF has a function called query
> backlight transfer characteristics.  Among the
> information returned by this function is
> the minimum and maximum input signals for the
> backlight
> 
> Call that function on ACPI init.  When DM
> backlight device is updated, copy over the
> backlight caps into DM, but only once.  Use
> the backlight caps in the backlight-to-dc
> calculation.
> 
> Signed-off-by: David Francis <David.Francis at amd.com>

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

Harry

> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu.h           |  3 +
>  drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c      | 83 +++++++++++++++++++
>  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 59 ++++++++++---
>  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 13 +++
>  drivers/gpu/drm/amd/include/amd_acpi.h        | 24 ++++++
>  5 files changed, 170 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> index 2c80453ca350..adbad0e2d4ea 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> @@ -1255,6 +1255,9 @@ bool amdgpu_acpi_is_pcie_performance_request_supported(struct amdgpu_device *ade
>  int amdgpu_acpi_pcie_performance_request(struct amdgpu_device *adev,
>  						u8 perf_req, bool advertise);
>  int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev);
> +
> +void amdgpu_acpi_get_backlight_caps(struct amdgpu_device *adev,
> +		struct amdgpu_dm_backlight_caps *caps);
>  #else
>  static inline int amdgpu_acpi_init(struct amdgpu_device *adev) { return 0; }
>  static inline void amdgpu_acpi_fini(struct amdgpu_device *adev) { }
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
> index 471266901d1b..47db65926d71 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
> @@ -65,6 +65,7 @@ struct amdgpu_atif {
>  	struct amdgpu_atif_functions functions;
>  	struct amdgpu_atif_notification_cfg notification_cfg;
>  	struct amdgpu_encoder *encoder_for_bl;
> +	struct amdgpu_dm_backlight_caps backlight_caps;
>  };
>  
>  /* Call the ATIF method
> @@ -297,6 +298,65 @@ static int amdgpu_atif_get_notification_params(struct amdgpu_atif *atif)
>  	return err;
>  }
>  
> +/**
> + * amdgpu_atif_query_backlight_caps - get min and max backlight input signal
> + *
> + * @handle: acpi handle
> + *
> + * Execute the QUERY_BRIGHTNESS_TRANSFER_CHARACTERISTICS ATIF function
> + * to determine the acceptable range of backlight values
> + *
> + * Backlight_caps.caps_valid will be set to true if the query is successful
> + *
> + * The input signals are in range 0-255
> + *
> + * This function assumes the display with backlight is the first LCD
> + *
> + * Returns 0 on success, error on failure.
> + */
> +static int amdgpu_atif_query_backlight_caps(struct amdgpu_atif *atif)
> +{
> +	union acpi_object *info;
> +	struct atif_qbtc_output characteristics;
> +	struct atif_qbtc_arguments arguments;
> +	struct acpi_buffer params;
> +	size_t size;
> +	int err = 0;
> +
> +	arguments.size = sizeof(arguments);
> +	arguments.requested_display = ATIF_QBTC_REQUEST_LCD1;
> +
> +	params.length = sizeof(arguments);
> +	params.pointer = (void *)&arguments;
> +
> +	info = amdgpu_atif_call(atif,
> +		ATIF_FUNCTION_QUERY_BRIGHTNESS_TRANSFER_CHARACTERISTICS,
> +		&params);
> +	if (!info) {
> +		err = -EIO;
> +		goto out;
> +	}
> +
> +	size = *(u16 *) info->buffer.pointer;
> +	if (size < 10) {
> +		err = -EINVAL;
> +		goto out;
> +	}
> +
> +	memset(&characteristics, 0, sizeof(characteristics));
> +	size = min(sizeof(characteristics), size);
> +	memcpy(&characteristics, info->buffer.pointer, size);
> +
> +	atif->backlight_caps.caps_valid = true;
> +	atif->backlight_caps.min_input_signal =
> +			characteristics.min_input_signal;
> +	atif->backlight_caps.max_input_signal =
> +			characteristics.max_input_signal;
> +out:
> +	kfree(info);
> +	return err;
> +}
> +
>  /**
>   * amdgpu_atif_get_sbios_requests - get requested sbios event
>   *
> @@ -786,6 +846,17 @@ int amdgpu_acpi_init(struct amdgpu_device *adev)
>  		}
>  	}
>  
> +	if (atif->functions.query_backlight_transfer_characteristics) {
> +		ret = amdgpu_atif_query_backlight_caps(atif);
> +		if (ret) {
> +			DRM_DEBUG_DRIVER("Call to QUERY_BACKLIGHT_TRANSFER_CHARACTERISTICS failed: %d\n",
> +					ret);
> +			atif->backlight_caps.caps_valid = false;
> +		}
> +	} else {
> +		atif->backlight_caps.caps_valid = false;
> +	}
> +
>  out:
>  	adev->acpi_nb.notifier_call = amdgpu_acpi_event;
>  	register_acpi_notifier(&adev->acpi_nb);
> @@ -793,6 +864,18 @@ int amdgpu_acpi_init(struct amdgpu_device *adev)
>  	return ret;
>  }
>  
> +void amdgpu_acpi_get_backlight_caps(struct amdgpu_device *adev,
> +		struct amdgpu_dm_backlight_caps *caps)
> +{
> +	if (!adev->atif) {
> +		caps->caps_valid = false;
> +		return;
> +	}
> +	caps->caps_valid = adev->atif->backlight_caps.caps_valid;
> +	caps->min_input_signal = adev->atif->backlight_caps.min_input_signal;
> +	caps->max_input_signal = adev->atif->backlight_caps.max_input_signal;
> +}
> +
>  /**
>   * amdgpu_acpi_fini - tear down driver acpi support
>   *
> 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 090a602f3014..0bccea073f9d 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -1590,27 +1590,60 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev)
>  	return 0;
>  }
>  
> +#define AMDGPU_DM_DEFAULT_MIN_BACKLIGHT 12
> +#define AMDGPU_DM_DEFAULT_MAX_BACKLIGHT 255
> +
>  #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\
>  	defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
>  
> +static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm)
> +{
> +#if defined(CONFIG_ACPI)
> +	struct amdgpu_dm_backlight_caps caps;
> +
> +	if (dm->backlight_caps.caps_valid)
> +		return;
> +
> +	amdgpu_acpi_get_backlight_caps(dm->adev, &caps);
> +	if (caps.caps_valid) {
> +		dm->backlight_caps.min_input_signal = caps.min_input_signal;
> +		dm->backlight_caps.max_input_signal = caps.max_input_signal;
> +		dm->backlight_caps.caps_valid = true;
> +	} else {
> +		dm->backlight_caps.min_input_signal =
> +				AMDGPU_DM_DEFAULT_MIN_BACKLIGHT;
> +		dm->backlight_caps.max_input_signal =
> +				AMDGPU_DM_DEFAULT_MAX_BACKLIGHT;
> +	}
> +#else
> +	dm->backlight_min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT;
> +	dm->backlight_max_input_signal = AMDGPU_DM_DEFAULT_MAX_BACKLIGHT;
> +#endif
> +}
> +
>  static int amdgpu_dm_backlight_update_status(struct backlight_device *bd)
>  {
>  	struct amdgpu_display_manager *dm = bl_get_data(bd);
> +	struct amdgpu_dm_backlight_caps caps;
> +	uint32_t brightness = bd->props.brightness;
>  
> -	/* backlight_pwm_u16_16 parameter is in unsigned 32 bit, 16 bit integer
> -	 * and 16 bit fractional, where 1.0 is max backlight value.
> -	 * bd->props.brightness is 8 bit format and needs to be converted by
> -	 * scaling via copy lower byte to upper byte of 16 bit value.
> -	 */
> -	uint32_t brightness = bd->props.brightness * 0x101;
> -
> +	amdgpu_dm_update_backlight_caps(dm);
> +	caps = dm->backlight_caps;
>  	/*
> -	 * PWM interperts 0 as 100% rather than 0% because of HW
> -	 * limitation for level 0.  So limiting minimum brightness level
> -	 * to 1.
> +	 * The brightness input is in the range 0-255
> +	 * It needs to be rescaled to be between the
> +	 * requested min and max input signal
> +	 *
> +	 * It also needs to be scaled up by 0x101 to
> +	 * match the DC interface which has a range of
> +	 * 0 to 0xffff
>  	 */
> -	if (bd->props.brightness < 1)
> -		brightness = 0x101;
> +	brightness =
> +		brightness
> +		* 0x101
> +		* (caps.max_input_signal - caps.min_input_signal)
> +		/ AMDGPU_MAX_BL_LEVEL
> +		+ caps.min_input_signal * 0x101;
>  
>  	if (dc_link_set_backlight_level(dm->backlight_link,
>  			brightness, 0, 0))
> @@ -1640,6 +1673,8 @@ amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm)
>  	char bl_name[16];
>  	struct backlight_properties props = { 0 };
>  
> +	amdgpu_dm_update_backlight_caps(dm);
> +
>  	props.max_brightness = AMDGPU_MAX_BL_LEVEL;
>  	props.brightness = AMDGPU_MAX_BL_LEVEL;
>  	props.type = BACKLIGHT_RAW;
> 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 3c2fbfac938f..b8e724a5fd6d 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> @@ -83,6 +83,18 @@ struct dm_comressor_info {
>  	uint64_t gpu_addr;
>  };
>  
> +/**
> + * struct amdgpu_dm_backlight_caps - Usable range of backlight values from ACPI
> + * @min_input_signal: minimum possible input in range 0-255
> + * @max_input_signal: maximum possible input in range 0-255
> + * @caps_valid: true if these values are from the ACPI interface
> + */
> +struct amdgpu_dm_backlight_caps {
> +	int min_input_signal;
> +	int max_input_signal;
> +	bool caps_valid;
> +};
> +
>  /**
>   * struct amdgpu_display_manager - Central amdgpu display manager device
>   *
> @@ -158,6 +170,7 @@ struct amdgpu_display_manager {
>  	struct backlight_device *backlight_dev;
>  
>  	const struct dc_link *backlight_link;
> +	struct amdgpu_dm_backlight_caps backlight_caps;
>  
>  	struct mod_freesync *freesync_module;
>  
> diff --git a/drivers/gpu/drm/amd/include/amd_acpi.h b/drivers/gpu/drm/amd/include/amd_acpi.h
> index 8980edfe5fa9..c72cbfe8f684 100644
> --- a/drivers/gpu/drm/amd/include/amd_acpi.h
> +++ b/drivers/gpu/drm/amd/include/amd_acpi.h
> @@ -52,6 +52,30 @@ struct atif_sbios_requests {
>  	u8 backlight_level;	/* panel backlight level (0-255) */
>  } __packed;
>  
> +struct atif_qbtc_arguments {
> +	u16 size;		/* structure size in bytes (includes size field) */
> +	u8 requested_display;	/* which display is requested */
> +} __packed;
> +
> +#define ATIF_QBTC_MAX_DATA_POINTS 99
> +
> +struct atif_qbtc_data_point {
> +	u8 luminance;		/* luminance in percent */
> +	u8 ipnut_signal;	/* input signal in range 0-255 */
> +} __packed;
> +
> +struct atif_qbtc_output {
> +	u16 size;		/* structure size in bytes (includes size field) */
> +	u16 flags;		/* all zeroes */
> +	u8 error_code;		/* error code */
> +	u8 ac_level;		/* default brightness on AC power */
> +	u8 dc_level;		/* default brightness on DC power */
> +	u8 min_input_signal;	/* max input signal in range 0-255 */
> +	u8 max_input_signal;	/* min input signal in range 0-255 */
> +	u8 number_of_points;	/* number of data points */
> +	struct atif_qbtc_data_point data_points[ATIF_QBTC_MAX_DATA_POINTS];
> +} __packed;
> +
>  #define ATIF_NOTIFY_MASK	0x3
>  #define ATIF_NOTIFY_NONE	0
>  #define ATIF_NOTIFY_81		1
> 


More information about the amd-gfx mailing list