Commit 16eb48c6 authored by Sathishkumar S's avatar Sathishkumar S Committed by Alex Deucher
Browse files

drm/amdgpu: support atcs method powershift (v4)



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: default avatarSathishkumar S <sathishkumar.sundararaju@amd.com>
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Reviewed-by: default avatarLijo Lazar <lijo.lazar@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 8a81028b
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -1340,8 +1340,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);
@@ -1352,6 +1355,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,
+55 −0
Original line number Diff line number Diff line
@@ -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, &params);
	if (!info) {
		DRM_ERROR("ATCS PSC update failed\n");
		return -EIO;
	}

	return 0;
}

/**
 * amdgpu_acpi_event - handle notify events
 *
+18 −0
Original line number Diff line number Diff line
@@ -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