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@xxxxxxx> Reviewed-by: Harry Wentland <harry.wentland@xxxxxxx> 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, > + ¶ms); > + 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 > _______________________________________________ amd-gfx mailing list amd-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/amd-gfx