diff options
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.patch | 349 |
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 + |