diff options
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.19.8/0845-drm-amd-Query-and-use-ACPI-backlight-caps.patch')
-rw-r--r-- | common/recipes-kernel/linux/linux-yocto-4.19.8/0845-drm-amd-Query-and-use-ACPI-backlight-caps.patch | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.19.8/0845-drm-amd-Query-and-use-ACPI-backlight-caps.patch b/common/recipes-kernel/linux/linux-yocto-4.19.8/0845-drm-amd-Query-and-use-ACPI-backlight-caps.patch new file mode 100644 index 00000000..54ece729 --- /dev/null +++ b/common/recipes-kernel/linux/linux-yocto-4.19.8/0845-drm-amd-Query-and-use-ACPI-backlight-caps.patch @@ -0,0 +1,309 @@ +From 05ed87883240b0e86068929a38531cf606d840e6 Mon Sep 17 00:00:00 2001 +From: David Francis <David.Francis@amd.com> +Date: Mon, 26 Nov 2018 11:44:06 -0500 +Subject: [PATCH 0845/2940] drm/amd: Query and use ACPI backlight caps + +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@amd.com> +Reviewed-by: Harry Wentland <harry.wentland@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +--- + 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 | 56 +++++++++++-- + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 13 +++ + drivers/gpu/drm/amd/include/amd_acpi.h | 24 ++++++ + 5 files changed, 172 insertions(+), 7 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h +index ae419c8bdc8d..9671f53d44c3 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h +@@ -1290,6 +1290,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 2d5b0bf695d3..a6e3e4d7e883 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -1588,22 +1588,62 @@ 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. ++ amdgpu_dm_update_backlight_caps(dm); ++ caps = dm->backlight_caps; ++ /* ++ * 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 + */ +- uint32_t brightness = bd->props.brightness * 0x101; + +- 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)) +@@ -1633,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 63ee581b55a0..a84d72120275 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 + * +@@ -155,6 +167,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 +-- +2.17.1 + |