Skip to content

Commit

Permalink
drm/radeon: add initial support for ATCS ACPI methods
Browse files Browse the repository at this point in the history
Just verify the interface and track what functions are
supported.  Not actually used yet.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
  • Loading branch information
Alex Deucher committed Sep 20, 2012
1 parent 82e0293 commit e3a1592
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 1 deletion.
12 changes: 12 additions & 0 deletions drivers/gpu/drm/radeon/radeon.h
Original file line number Diff line number Diff line change
Expand Up @@ -1464,6 +1464,17 @@ struct radeon_atif {
struct radeon_encoder *backlight_ctl;
};

struct radeon_atcs_functions {
bool get_ext_state;
bool pcie_perf_req;
bool pcie_dev_rdy;
bool pcie_bus_width;
};

struct radeon_atcs {
struct radeon_atcs_functions functions;
};

/*
* Core structure, functions and helpers.
*/
Expand Down Expand Up @@ -1557,6 +1568,7 @@ struct radeon_device {
struct mutex gpu_clock_mutex;
/* ACPI interface */
struct radeon_atif atif;
struct radeon_atcs atcs;
};

int radeon_device_init(struct radeon_device *rdev,
Expand Down
127 changes: 126 additions & 1 deletion drivers/gpu/drm/radeon/radeon_acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ struct atif_sbios_requests {
#define ATIF_NOTIFY_81 1
#define ATIF_NOTIFY_N 2

struct atcs_verify_interface {
u16 size; /* structure size in bytes (includes size field) */
u16 version; /* version */
u32 function_bits; /* supported functions bit vector */
} __packed;

/* Call the ATIF method
*/
/**
Expand Down Expand Up @@ -383,6 +389,118 @@ int radeon_atif_handler(struct radeon_device *rdev,
return NOTIFY_BAD;
}

/* Call the ATCS method
*/
/**
* radeon_atcs_call - call an ATCS method
*
* @handle: acpi handle
* @function: the ATCS function to execute
* @params: ATCS function params
*
* Executes the requested ATCS function (all asics).
* Returns a pointer to the acpi output buffer.
*/
static union acpi_object *radeon_atcs_call(acpi_handle handle, int function,
struct acpi_buffer *params)
{
acpi_status status;
union acpi_object atcs_arg_elements[2];
struct acpi_object_list atcs_arg;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };

atcs_arg.count = 2;
atcs_arg.pointer = &atcs_arg_elements[0];

atcs_arg_elements[0].type = ACPI_TYPE_INTEGER;
atcs_arg_elements[0].integer.value = function;

if (params) {
atcs_arg_elements[1].type = ACPI_TYPE_BUFFER;
atcs_arg_elements[1].buffer.length = params->length;
atcs_arg_elements[1].buffer.pointer = params->pointer;
} else {
/* We need a second fake parameter */
atcs_arg_elements[1].type = ACPI_TYPE_INTEGER;
atcs_arg_elements[1].integer.value = 0;
}

status = acpi_evaluate_object(handle, "ATCS", &atcs_arg, &buffer);

/* Fail only if calling the method fails and ATIF is supported */
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
DRM_DEBUG_DRIVER("failed to evaluate ATCS got %s\n",
acpi_format_exception(status));
kfree(buffer.pointer);
return NULL;
}

return buffer.pointer;
}

/**
* radeon_atcs_parse_functions - parse supported functions
*
* @f: supported functions struct
* @mask: supported functions mask from ATCS
*
* Use the supported functions mask from ATCS function
* ATCS_FUNCTION_VERIFY_INTERFACE to determine what functions
* are supported (all asics).
*/
static void radeon_atcs_parse_functions(struct radeon_atcs_functions *f, u32 mask)
{
f->get_ext_state = mask & ATCS_GET_EXTERNAL_STATE_SUPPORTED;
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;
}

/**
* radeon_atcs_verify_interface - verify ATCS
*
* @handle: acpi handle
* @atcs: radeon atcs struct
*
* Execute the ATCS_FUNCTION_VERIFY_INTERFACE ATCS function
* to initialize ATCS and determine what features are supported
* (all asics).
* returns 0 on success, error on failure.
*/
static int radeon_atcs_verify_interface(acpi_handle handle,
struct radeon_atcs *atcs)
{
union acpi_object *info;
struct atcs_verify_interface output;
size_t size;
int err = 0;

info = radeon_atcs_call(handle, ATCS_FUNCTION_VERIFY_INTERFACE, NULL);
if (!info)
return -EIO;

memset(&output, 0, sizeof(output));

size = *(u16 *) info->buffer.pointer;
if (size < 8) {
DRM_INFO("ATCS buffer is too small: %lu\n", size);
err = -EINVAL;
goto out;
}
size = min(sizeof(output), size);

memcpy(&output, info->buffer.pointer, size);

/* TODO: check version? */
DRM_DEBUG_DRIVER("ATCS version %u\n", output.version);

radeon_atcs_parse_functions(&atcs->functions, output.function_bits);

out:
kfree(info);
return err;
}

/**
* radeon_acpi_event - handle notify events
*
Expand Down Expand Up @@ -428,6 +546,7 @@ int radeon_acpi_init(struct radeon_device *rdev)
{
acpi_handle handle;
struct radeon_atif *atif = &rdev->atif;
struct radeon_atcs *atcs = &rdev->atcs;
int ret;

/* Get the device handle */
Expand All @@ -437,10 +556,16 @@ int radeon_acpi_init(struct radeon_device *rdev)
if (!ASIC_IS_AVIVO(rdev) || !rdev->bios || !handle)
return 0;

/* Call the ATCS method */
ret = radeon_atcs_verify_interface(handle, atcs);
if (ret) {
DRM_DEBUG_DRIVER("Call to ATCS verify_interface failed: %d\n", ret);
}

/* Call the ATIF method */
ret = radeon_atif_verify_interface(handle, atif);
if (ret) {
DRM_DEBUG_DRIVER("Call to verify_interface failed: %d\n", ret);
DRM_DEBUG_DRIVER("Call to ATIF verify_interface failed: %d\n", ret);
goto out;
}

Expand Down

0 comments on commit e3a1592

Please sign in to comment.