Skip to content

Commit

Permalink
drm/radeon: update ATPX verify interface handling (v2)
Browse files Browse the repository at this point in the history
Verify the ATPX interface and track what ATPX functions
are available for future use.

v2: rework due to tree changes

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
  • Loading branch information
Alex Deucher committed Sep 20, 2012
1 parent c3c6516 commit 48fa412
Showing 1 changed file with 124 additions and 17 deletions.
141 changes: 124 additions & 17 deletions drivers/gpu/drm/radeon/radeon_atpx_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,39 +14,147 @@

#include "radeon_acpi.h"

struct radeon_atpx_functions {
bool px_params;
bool power_cntl;
bool disp_mux_cntl;
bool i2c_mux_cntl;
bool switch_start;
bool switch_end;
bool disp_connectors_mapping;
bool disp_detetion_ports;
};

struct radeon_atpx {
struct radeon_atpx_functions functions;
};

static struct radeon_atpx_priv {
bool atpx_detected;
/* handle for device - and atpx */
acpi_handle dhandle;
acpi_handle atpx_handle;
struct radeon_atpx atpx;
} radeon_atpx_priv;

static int radeon_atpx_get_version(acpi_handle handle)
struct atpx_verify_interface {
u16 size; /* structure size in bytes (includes size field) */
u16 version; /* version */
u32 function_bits; /* supported functions bit vector */
} __packed;

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

atpx_arg.count = 2;
atpx_arg.pointer = &atpx_arg_elements[0];

atpx_arg_elements[0].type = ACPI_TYPE_INTEGER;
atpx_arg_elements[0].integer.value = ATPX_FUNCTION_VERIFY_INTERFACE;
atpx_arg_elements[0].integer.value = function;

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

atpx_arg_elements[1].type = ACPI_TYPE_INTEGER;
atpx_arg_elements[1].integer.value = 0;
status = acpi_evaluate_object(handle, "ATPX", &atpx_arg, &buffer);

status = acpi_evaluate_object(handle, NULL, &atpx_arg, &buffer);
if (ACPI_FAILURE(status)) {
printk("%s: failed to call ATPX: %s\n", __func__, acpi_format_exception(status));
return -ENOSYS;
/* Fail only if calling the method fails and ATPX is supported */
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
printk("failed to evaluate ATPX got %s\n",
acpi_format_exception(status));
kfree(buffer.pointer);
return NULL;
}
obj = (union acpi_object *)buffer.pointer;
if (obj && (obj->type == ACPI_TYPE_BUFFER))
printk(KERN_INFO "radeon atpx: version is %d\n", *((u8 *)(obj->buffer.pointer) + 2));
kfree(buffer.pointer);
return 0;

return buffer.pointer;
}

/**
* radeon_atpx_parse_functions - parse supported functions
*
* @f: supported functions struct
* @mask: supported functions mask from ATPX
*
* Use the supported functions mask from ATPX function
* ATPX_FUNCTION_VERIFY_INTERFACE to determine what functions
* are supported (all asics).
*/
static void radeon_atpx_parse_functions(struct radeon_atpx_functions *f, u32 mask)
{
f->px_params = mask & ATPX_GET_PX_PARAMETERS_SUPPORTED;
f->power_cntl = mask & ATPX_POWER_CONTROL_SUPPORTED;
f->disp_mux_cntl = mask & ATPX_DISPLAY_MUX_CONTROL_SUPPORTED;
f->i2c_mux_cntl = mask & ATPX_I2C_MUX_CONTROL_SUPPORTED;
f->switch_start = mask & ATPX_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION_SUPPORTED;
f->switch_end = mask & ATPX_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION_SUPPORTED;
f->disp_connectors_mapping = mask & ATPX_GET_DISPLAY_CONNECTORS_MAPPING_SUPPORTED;
f->disp_detetion_ports = mask & ATPX_GET_DISPLAY_DETECTION_PORTS_SUPPORTED;
}

/**
* radeon_atpx_verify_interface - verify ATPX
*
* @handle: acpi handle
* @atpx: radeon atpx struct
*
* Execute the ATPX_FUNCTION_VERIFY_INTERFACE ATPX function
* to initialize ATPX and determine what features are supported
* (all asics).
* returns 0 on success, error on failure.
*/
static int radeon_atpx_verify_interface(acpi_handle handle,
struct radeon_atpx *atpx)
{
union acpi_object *info;
struct atpx_verify_interface output;
size_t size;
int err = 0;

info = radeon_atpx_call(handle, ATPX_FUNCTION_VERIFY_INTERFACE, NULL);
if (!info)
return -EIO;

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

size = *(u16 *) info->buffer.pointer;
if (size < 8) {
printk("ATPX 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? */
printk("ATPX version %u\n", output.version);

radeon_atpx_parse_functions(&atpx->functions, output.function_bits);

out:
kfree(info);
return err;
}

static int radeon_atpx_execute(acpi_handle handle, int cmd_id, u16 value)
Expand Down Expand Up @@ -161,9 +269,8 @@ static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev)
static int radeon_atpx_init(void)
{
/* set up the ATPX handle */

radeon_atpx_get_version(radeon_atpx_priv.atpx_handle);
return 0;
return radeon_atpx_verify_interface(radeon_atpx_priv.atpx_handle,
&radeon_atpx_priv.atpx);
}

static int radeon_atpx_get_client_id(struct pci_dev *pdev)
Expand Down

0 comments on commit 48fa412

Please sign in to comment.