]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
drm/amdgpu: support atcs method powershift (v4)
authorSathishkumar S <sathishkumar.sundararaju@amd.com>
Mon, 10 May 2021 14:00:23 +0000 (19:30 +0530)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 2 Jun 2021 02:36:48 +0000 (22:36 -0400)
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@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
drivers/gpu/drm/amd/include/amd_acpi.h

index 435103e514cdba2b8ac4243854b37eb420bb2bf9..c215690670f2bddec37f60b4d427873dbe32b535 100644 (file)
@@ -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,
index bbff6c06f943dfbdf4fa3d9c1876937e58652328..b631316bfe5b3d1c59c61642e312937bec99d102 100644 (file)
@@ -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
  *
index c72cbfe8f684b926bd149e8a58581c6951d9d18f..2d089d30518f3a2696a998ba9115773cdeecc2eb 100644 (file)
@@ -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