add support to handle ATCS method for power shift control. used to communicate dGPU device state to SBIOS. V2: use defined acpi func for checking psc support (Lijo) fix alignment (Shashank) V3: rebased on unified ATCS handling (Alex) V4: rebased on ATPX/ATCS structures global (Alex) Signed-off-by: Sathishkumar S <sathishkumar.sundararaju@xxxxxxx> Reviewed-by: Alex Deucher <alexander.deucher@xxxxxxx> Reviewed-by: Lijo Lazar <lijo.lazar@xxxxxxx> --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 6 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c | 55 ++++++++++++++++++++++++ drivers/gpu/drm/amd/include/amd_acpi.h | 18 ++++++++ 3 files changed, 79 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 7b794957515f..0ea2ed3a55f1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1343,8 +1343,11 @@ struct amdgpu_afmt_acr amdgpu_afmt_acr(uint32_t clock); int amdgpu_acpi_init(struct amdgpu_device *adev); void amdgpu_acpi_fini(struct amdgpu_device *adev); bool amdgpu_acpi_is_pcie_performance_request_supported(struct amdgpu_device *adev); +bool amdgpu_acpi_is_power_shift_control_supported(void); int amdgpu_acpi_pcie_performance_request(struct amdgpu_device *adev, u8 perf_req, bool advertise); +int amdgpu_acpi_power_shift_control(struct amdgpu_device *adev, + u8 dev_state, bool drv_state); int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev); void amdgpu_acpi_get_backlight_caps(struct amdgpu_dm_backlight_caps *caps); @@ -1355,6 +1358,9 @@ static inline int amdgpu_acpi_init(struct amdgpu_device *adev) { return 0; } static inline void amdgpu_acpi_fini(struct amdgpu_device *adev) { } static inline bool amdgpu_acpi_is_s0ix_supported(struct amdgpu_device *adev) { return false; } static inline void amdgpu_acpi_detect(void) { } +static inline bool amdgpu_acpi_is_power_shift_control_supported(void) { return false; } +static inline int amdgpu_acpi_power_shift_control(struct amdgpu_device *adev, + u8 dev_state, bool drv_state) { return 0; } #endif int amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c index bbff6c06f943..b631316bfe5b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c @@ -76,6 +76,7 @@ struct amdgpu_atcs_functions { bool pcie_perf_req; bool pcie_dev_rdy; bool pcie_bus_width; + bool power_shift_control; }; struct amdgpu_atcs { @@ -534,6 +535,7 @@ static void amdgpu_atcs_parse_functions(struct amdgpu_atcs_functions *f, u32 mas f->pcie_perf_req = mask & ATCS_PCIE_PERFORMANCE_REQUEST_SUPPORTED; f->pcie_dev_rdy = mask & ATCS_PCIE_DEVICE_READY_NOTIFICATION_SUPPORTED; f->pcie_bus_width = mask & ATCS_SET_PCIE_BUS_WIDTH_SUPPORTED; + f->power_shift_control = mask & ATCS_SET_POWER_SHIFT_CONTROL_SUPPORTED; } /** @@ -598,6 +600,18 @@ bool amdgpu_acpi_is_pcie_performance_request_supported(struct amdgpu_device *ade return false; } +/** + * amdgpu_acpi_is_power_shift_control_supported + * + * Check if the ATCS power shift control method + * is supported. + * returns true if supported, false if not. + */ +bool amdgpu_acpi_is_power_shift_control_supported(void) +{ + return amdgpu_acpi_priv.atcs.functions.power_shift_control; +} + /** * amdgpu_acpi_pcie_notify_device_ready * @@ -699,6 +713,47 @@ int amdgpu_acpi_pcie_performance_request(struct amdgpu_device *adev, return 0; } +/** + * amdgpu_acpi_power_shift_control + * + * @adev: amdgpu_device pointer + * @dev_state: device acpi state + * @drv_state: driver state + * + * Executes the POWER_SHIFT_CONTROL method to + * communicate current dGPU device state and + * driver state to APU/SBIOS. + * returns 0 on success, error on failure. + */ +int amdgpu_acpi_power_shift_control(struct amdgpu_device *adev, + u8 dev_state, bool drv_state) +{ + union acpi_object *info; + struct amdgpu_atcs *atcs = &amdgpu_acpi_priv.atcs; + struct atcs_pwr_shift_input atcs_input; + struct acpi_buffer params; + + if (!amdgpu_acpi_is_power_shift_control_supported()) + return -EINVAL; + + atcs_input.size = sizeof(struct atcs_pwr_shift_input); + /* dGPU id (bit 2-0: func num, 7-3: dev num, 15-8: bus num) */ + atcs_input.dgpu_id = adev->pdev->devfn | (adev->pdev->bus->number << 8); + atcs_input.dev_acpi_state = dev_state; + atcs_input.drv_state = drv_state; + + params.length = sizeof(struct atcs_pwr_shift_input); + params.pointer = &atcs_input; + + info = amdgpu_atcs_call(atcs, ATCS_FUNCTION_POWER_SHIFT_CONTROL, ¶ms); + if (!info) { + DRM_ERROR("ATCS PSC update failed\n"); + return -EIO; + } + + return 0; +} + /** * amdgpu_acpi_event - handle notify events * diff --git a/drivers/gpu/drm/amd/include/amd_acpi.h b/drivers/gpu/drm/amd/include/amd_acpi.h index c72cbfe8f684..2d089d30518f 100644 --- a/drivers/gpu/drm/amd/include/amd_acpi.h +++ b/drivers/gpu/drm/amd/include/amd_acpi.h @@ -103,6 +103,13 @@ struct atcs_pref_req_output { u8 ret_val; /* return value */ } __packed; +struct atcs_pwr_shift_input { + u16 size; /* structure size in bytes (includes size field) */ + u16 dgpu_id; /* client id (bit 2-0: func num, 7-3: dev num, 15-8: bus num) */ + u8 dev_acpi_state; /* D0 = 0, D3 hot = 3 */ + u8 drv_state; /* 0 = operational, 1 = not operational */ +} __packed; + /* AMD hw uses four ACPI control methods: * 1. ATIF * ARG0: (ACPI_INTEGER) function code @@ -418,6 +425,7 @@ struct atcs_pref_req_output { # define ATCS_PCIE_PERFORMANCE_REQUEST_SUPPORTED (1 << 1) # define ATCS_PCIE_DEVICE_READY_NOTIFICATION_SUPPORTED (1 << 2) # define ATCS_SET_PCIE_BUS_WIDTH_SUPPORTED (1 << 3) +# define ATCS_SET_POWER_SHIFT_CONTROL_SUPPORTED (1 << 7) #define ATCS_FUNCTION_GET_EXTERNAL_STATE 0x1 /* ARG0: ATCS_FUNCTION_GET_EXTERNAL_STATE * ARG1: none @@ -472,4 +480,14 @@ struct atcs_pref_req_output { * BYTE - number of active lanes */ +#define ATCS_FUNCTION_POWER_SHIFT_CONTROL 0x8 +/* ARG0: ATCS_FUNCTION_POWER_SHIFT_CONTROL + * ARG1: + * WORD - structure size in bytes (includes size field) + * WORD - dGPU id (bit 2-0: func num, 7-3: dev num, 15-8: bus num) + * BYTE - Device ACPI state + * BYTE - Driver state + * OUTPUT: none + */ + #endif -- 2.17.1 _______________________________________________ amd-gfx mailing list amd-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/amd-gfx