aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/files/0037-drm-amdgpu-implement-new-cgs-interface-for-acpi-func.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/files/0037-drm-amdgpu-implement-new-cgs-interface-for-acpi-func.patch')
-rw-r--r--common/recipes-kernel/linux/files/0037-drm-amdgpu-implement-new-cgs-interface-for-acpi-func.patch349
1 files changed, 349 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/files/0037-drm-amdgpu-implement-new-cgs-interface-for-acpi-func.patch b/common/recipes-kernel/linux/files/0037-drm-amdgpu-implement-new-cgs-interface-for-acpi-func.patch
new file mode 100644
index 00000000..f71e744e
--- /dev/null
+++ b/common/recipes-kernel/linux/files/0037-drm-amdgpu-implement-new-cgs-interface-for-acpi-func.patch
@@ -0,0 +1,349 @@
+From 80cec685ee980cb171f2f73d1df702afbbc0bbb8 Mon Sep 17 00:00:00 2001
+From: Rex Zhu <Rex.Zhu@amd.com>
+Date: Tue, 15 Sep 2015 14:44:44 +0800
+Subject: [PATCH 0037/1110] drm/amdgpu: implement new cgs interface for acpi
+ function
+
+Add a new driver internal interface for accessing ACPI
+methods. These will be used by various new components
+including powerplay.
+
+Signed-off-by: Rex Zhu <Rex.Zhu@amd.com>
+Reviewed-by: Jammy Zhou <Jammy.Zhou@amd.com>
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c | 220 ++++++++++++++++++++++++++++++-
+ drivers/gpu/drm/amd/include/cgs_common.h | 45 ++++++-
+ 2 files changed, 262 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
+index 8e99514..f901cdc 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
+@@ -24,6 +24,7 @@
+ #include <linux/list.h>
+ #include <linux/slab.h>
+ #include <linux/pci.h>
++#include <linux/acpi.h>
+ #include <drm/drmP.h>
+ #include <linux/firmware.h>
+ #include <drm/amdgpu_drm.h>
+@@ -32,7 +33,6 @@
+ #include "atom.h"
+ #include "amdgpu_ucode.h"
+
+-
+ struct amdgpu_cgs_device {
+ struct cgs_device base;
+ struct amdgpu_device *adev;
+@@ -736,6 +736,221 @@ static int amdgpu_cgs_get_firmware_info(void *cgs_device,
+ return 0;
+ }
+
++/** \brief evaluate acpi namespace object, handle or pathname must be valid
++ * \param cgs_device
++ * \param info input/output arguments for the control method
++ * \return status
++ */
++
++#if defined(CONFIG_ACPI)
++static int amdgpu_cgs_acpi_eval_object(void *cgs_device,
++ struct cgs_acpi_method_info *info)
++{
++ CGS_FUNC_ADEV;
++ acpi_handle handle;
++ struct acpi_object_list input;
++ struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
++ union acpi_object *params = NULL;
++ union acpi_object *obj = NULL;
++ uint8_t name[5] = {'\0'};
++ struct cgs_acpi_method_argument *argument = NULL;
++ uint32_t i, count;
++ acpi_status status;
++ int result;
++ uint32_t func_no = 0xFFFFFFFF;
++
++ handle = ACPI_HANDLE(&adev->pdev->dev);
++ if (!handle)
++ return -ENODEV;
++
++ memset(&input, 0, sizeof(struct acpi_object_list));
++
++ /* validate input info */
++ if (info->size != sizeof(struct cgs_acpi_method_info))
++ return -EINVAL;
++
++ input.count = info->input_count;
++ if (info->input_count > 0) {
++ if (info->pinput_argument == NULL)
++ return -EINVAL;
++ argument = info->pinput_argument;
++ func_no = argument->value;
++ for (i = 0; i < info->input_count; i++) {
++ if (((argument->type == ACPI_TYPE_STRING) ||
++ (argument->type == ACPI_TYPE_BUFFER))
++ && (argument->pointer == NULL))
++ return -EINVAL;
++ argument++;
++ }
++ }
++
++ if (info->output_count > 0) {
++ if (info->poutput_argument == NULL)
++ return -EINVAL;
++ argument = info->poutput_argument;
++ for (i = 0; i < info->output_count; i++) {
++ if (((argument->type == ACPI_TYPE_STRING) ||
++ (argument->type == ACPI_TYPE_BUFFER))
++ && (argument->pointer == NULL))
++ return -EINVAL;
++ argument++;
++ }
++ }
++
++ /* The path name passed to acpi_evaluate_object should be null terminated */
++ if ((info->field & CGS_ACPI_FIELD_METHOD_NAME) != 0) {
++ strncpy(name, (char *)&(info->name), sizeof(uint32_t));
++ name[4] = '\0';
++ }
++
++ /* parse input parameters */
++ if (input.count > 0) {
++ input.pointer = params =
++ kzalloc(sizeof(union acpi_object) * input.count, GFP_KERNEL);
++ if (params == NULL)
++ return -EINVAL;
++
++ argument = info->pinput_argument;
++
++ for (i = 0; i < input.count; i++) {
++ params->type = argument->type;
++ switch (params->type) {
++ case ACPI_TYPE_INTEGER:
++ params->integer.value = argument->value;
++ break;
++ case ACPI_TYPE_STRING:
++ params->string.length = argument->method_length;
++ params->string.pointer = argument->pointer;
++ break;
++ case ACPI_TYPE_BUFFER:
++ params->buffer.length = argument->method_length;
++ params->buffer.pointer = argument->pointer;
++ break;
++ default:
++ break;
++ }
++ params++;
++ argument++;
++ }
++ }
++
++ /* parse output info */
++ count = info->output_count;
++ argument = info->poutput_argument;
++
++ /* evaluate the acpi method */
++ status = acpi_evaluate_object(handle, name, &input, &output);
++
++ if (ACPI_FAILURE(status)) {
++ result = -EIO;
++ goto error;
++ }
++
++ /* return the output info */
++ obj = output.pointer;
++
++ if (count > 1) {
++ if ((obj->type != ACPI_TYPE_PACKAGE) ||
++ (obj->package.count != count)) {
++ result = -EIO;
++ goto error;
++ }
++ params = obj->package.elements;
++ } else
++ params = obj;
++
++ if (params == NULL) {
++ result = -EIO;
++ goto error;
++ }
++
++ for (i = 0; i < count; i++) {
++ if (argument->type != params->type) {
++ result = -EIO;
++ goto error;
++ }
++ switch (params->type) {
++ case ACPI_TYPE_INTEGER:
++ argument->value = params->integer.value;
++ break;
++ case ACPI_TYPE_STRING:
++ if ((params->string.length != argument->data_length) ||
++ (params->string.pointer == NULL)) {
++ result = -EIO;
++ goto error;
++ }
++ strncpy(argument->pointer,
++ params->string.pointer,
++ params->string.length);
++ break;
++ case ACPI_TYPE_BUFFER:
++ if (params->buffer.pointer == NULL) {
++ result = -EIO;
++ goto error;
++ }
++ memcpy(argument->pointer,
++ params->buffer.pointer,
++ argument->data_length);
++ break;
++ default:
++ break;
++ }
++ argument++;
++ params++;
++ }
++
++error:
++ if (obj != NULL)
++ kfree(obj);
++ kfree((void *)input.pointer);
++ return result;
++}
++#else
++static int amdgpu_cgs_acpi_eval_object(void *cgs_device,
++ struct cgs_acpi_method_info *info)
++{
++ return -EIO;
++}
++#endif
++
++int amdgpu_cgs_call_acpi_method(void *cgs_device,
++ uint32_t acpi_method,
++ uint32_t acpi_function,
++ void *pinput, void *poutput,
++ uint32_t output_count,
++ uint32_t input_size,
++ uint32_t output_size)
++{
++ struct cgs_acpi_method_argument acpi_input[2] = { {0}, {0} };
++ struct cgs_acpi_method_argument acpi_output = {0};
++ struct cgs_acpi_method_info info = {0};
++
++ acpi_input[0].type = CGS_ACPI_TYPE_INTEGER;
++ acpi_input[0].method_length = sizeof(uint32_t);
++ acpi_input[0].data_length = sizeof(uint32_t);
++ acpi_input[0].value = acpi_function;
++
++ acpi_input[1].type = CGS_ACPI_TYPE_BUFFER;
++ acpi_input[1].method_length = CGS_ACPI_MAX_BUFFER_SIZE;
++ acpi_input[1].data_length = input_size;
++ acpi_input[1].pointer = pinput;
++
++ acpi_output.type = CGS_ACPI_TYPE_BUFFER;
++ acpi_output.method_length = CGS_ACPI_MAX_BUFFER_SIZE;
++ acpi_output.data_length = output_size;
++ acpi_output.pointer = poutput;
++
++ info.size = sizeof(struct cgs_acpi_method_info);
++ info.field = CGS_ACPI_FIELD_METHOD_NAME | CGS_ACPI_FIELD_INPUT_ARGUMENT_COUNT;
++ info.input_count = 2;
++ info.name = acpi_method;
++ info.pinput_argument = acpi_input;
++ info.output_count = output_count;
++ info.poutput_argument = &acpi_output;
++
++ return amdgpu_cgs_acpi_eval_object(cgs_device, &info);
++}
++
+ static const struct cgs_ops amdgpu_cgs_ops = {
+ amdgpu_cgs_gpu_mem_info,
+ amdgpu_cgs_gmap_kmem,
+@@ -768,7 +983,8 @@ static const struct cgs_ops amdgpu_cgs_ops = {
+ amdgpu_cgs_set_camera_voltages,
+ amdgpu_cgs_get_firmware_info,
+ amdgpu_cgs_set_powergating_state,
+- amdgpu_cgs_set_clockgating_state
++ amdgpu_cgs_set_clockgating_state,
++ amdgpu_cgs_call_acpi_method,
+ };
+
+ static const struct cgs_os_ops amdgpu_cgs_os_ops = {
+diff --git a/drivers/gpu/drm/amd/include/cgs_common.h b/drivers/gpu/drm/amd/include/cgs_common.h
+index 992dcd8..8bf6ee5 100644
+--- a/drivers/gpu/drm/amd/include/cgs_common.h
++++ b/drivers/gpu/drm/amd/include/cgs_common.h
+@@ -129,6 +129,39 @@ struct cgs_firmware_info {
+
+ typedef unsigned long cgs_handle_t;
+
++#define CGS_ACPI_METHOD_ATCS 0x53435441
++#define CGS_ACPI_METHOD_ATIF 0x46495441
++#define CGS_ACPI_METHOD_ATPX 0x58505441
++#define CGS_ACPI_FIELD_METHOD_NAME 0x00000001
++#define CGS_ACPI_FIELD_INPUT_ARGUMENT_COUNT 0x00000002
++#define CGS_ACPI_MAX_BUFFER_SIZE 256
++#define CGS_ACPI_TYPE_ANY 0x00
++#define CGS_ACPI_TYPE_INTEGER 0x01
++#define CGS_ACPI_TYPE_STRING 0x02
++#define CGS_ACPI_TYPE_BUFFER 0x03
++#define CGS_ACPI_TYPE_PACKAGE 0x04
++
++struct cgs_acpi_method_argument {
++ uint32_t type;
++ uint32_t method_length;
++ uint32_t data_length;
++ union{
++ uint32_t value;
++ void *pointer;
++ };
++};
++
++struct cgs_acpi_method_info {
++ uint32_t size;
++ uint32_t field;
++ uint32_t input_count;
++ uint32_t name;
++ struct cgs_acpi_method_argument *pinput_argument;
++ uint32_t output_count;
++ struct cgs_acpi_method_argument *poutput_argument;
++ uint32_t padding[9];
++};
++
+ /**
+ * cgs_gpu_mem_info() - Return information about memory heaps
+ * @cgs_device: opaque device handle
+@@ -493,6 +526,13 @@ typedef int(*cgs_set_clockgating_state)(void *cgs_device,
+ enum amd_ip_block_type block_type,
+ enum amd_clockgating_state state);
+
++typedef int (*cgs_call_acpi_method)(void *cgs_device,
++ uint32_t acpi_method,
++ uint32_t acpi_function,
++ void *pinput, void *poutput,
++ uint32_t output_count,
++ uint32_t input_size,
++ uint32_t output_size);
+ struct cgs_ops {
+ /* memory management calls (similar to KFD interface) */
+ cgs_gpu_mem_info_t gpu_mem_info;
+@@ -533,7 +573,8 @@ struct cgs_ops {
+ /* cg pg interface*/
+ cgs_set_powergating_state set_powergating_state;
+ cgs_set_clockgating_state set_clockgating_state;
+- /* ACPI (TODO) */
++ /* ACPI */
++ cgs_call_acpi_method call_acpi_method;
+ };
+
+ struct cgs_os_ops; /* To be define in OS-specific CGS header */
+@@ -620,5 +661,7 @@ struct cgs_device
+ CGS_CALL(set_powergating_state, dev, block_type, state)
+ #define cgs_set_clockgating_state(dev, block_type, state) \
+ CGS_CALL(set_clockgating_state, dev, block_type, state)
++#define cgs_call_acpi_method(dev, acpi_method, acpi_function, pintput, poutput, output_count, input_size, output_size) \
++ CGS_CALL(call_acpi_method, dev, acpi_method, acpi_function, pintput, poutput, output_count, input_size, output_size)
+
+ #endif /* _CGS_COMMON_H */
+--
+2.7.4
+