diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2012-08-16 14:01:57 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2012-09-20 13:10:37 -0400 |
commit | 48fa412b7451530322cdbe969e404b798c6e204e (patch) | |
tree | 00344807e75541ed49f6dc4b1e1cffe7486470e9 | |
parent | c3c651600bd83de5e1cbb5d9ec34a88efd2856e8 (diff) |
drm/radeon: update ATPX verify interface handling (v2)
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>
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_atpx_handler.c | 141 |
1 files changed, 124 insertions, 17 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index 950a1ac95d6a..c1f2671a7b0b 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c | |||
@@ -14,17 +14,50 @@ | |||
14 | 14 | ||
15 | #include "radeon_acpi.h" | 15 | #include "radeon_acpi.h" |
16 | 16 | ||
17 | struct radeon_atpx_functions { | ||
18 | bool px_params; | ||
19 | bool power_cntl; | ||
20 | bool disp_mux_cntl; | ||
21 | bool i2c_mux_cntl; | ||
22 | bool switch_start; | ||
23 | bool switch_end; | ||
24 | bool disp_connectors_mapping; | ||
25 | bool disp_detetion_ports; | ||
26 | }; | ||
27 | |||
28 | struct radeon_atpx { | ||
29 | struct radeon_atpx_functions functions; | ||
30 | }; | ||
31 | |||
17 | static struct radeon_atpx_priv { | 32 | static struct radeon_atpx_priv { |
18 | bool atpx_detected; | 33 | bool atpx_detected; |
19 | /* handle for device - and atpx */ | 34 | /* handle for device - and atpx */ |
20 | acpi_handle dhandle; | 35 | acpi_handle dhandle; |
21 | acpi_handle atpx_handle; | 36 | acpi_handle atpx_handle; |
37 | struct radeon_atpx atpx; | ||
22 | } radeon_atpx_priv; | 38 | } radeon_atpx_priv; |
23 | 39 | ||
24 | static int radeon_atpx_get_version(acpi_handle handle) | 40 | struct atpx_verify_interface { |
41 | u16 size; /* structure size in bytes (includes size field) */ | ||
42 | u16 version; /* version */ | ||
43 | u32 function_bits; /* supported functions bit vector */ | ||
44 | } __packed; | ||
45 | |||
46 | /** | ||
47 | * radeon_atpx_call - call an ATPX method | ||
48 | * | ||
49 | * @handle: acpi handle | ||
50 | * @function: the ATPX function to execute | ||
51 | * @params: ATPX function params | ||
52 | * | ||
53 | * Executes the requested ATPX function (all asics). | ||
54 | * Returns a pointer to the acpi output buffer. | ||
55 | */ | ||
56 | static union acpi_object *radeon_atpx_call(acpi_handle handle, int function, | ||
57 | struct acpi_buffer *params) | ||
25 | { | 58 | { |
26 | acpi_status status; | 59 | acpi_status status; |
27 | union acpi_object atpx_arg_elements[2], *obj; | 60 | union acpi_object atpx_arg_elements[2]; |
28 | struct acpi_object_list atpx_arg; | 61 | struct acpi_object_list atpx_arg; |
29 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 62 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
30 | 63 | ||
@@ -32,21 +65,96 @@ static int radeon_atpx_get_version(acpi_handle handle) | |||
32 | atpx_arg.pointer = &atpx_arg_elements[0]; | 65 | atpx_arg.pointer = &atpx_arg_elements[0]; |
33 | 66 | ||
34 | atpx_arg_elements[0].type = ACPI_TYPE_INTEGER; | 67 | atpx_arg_elements[0].type = ACPI_TYPE_INTEGER; |
35 | atpx_arg_elements[0].integer.value = ATPX_FUNCTION_VERIFY_INTERFACE; | 68 | atpx_arg_elements[0].integer.value = function; |
69 | |||
70 | if (params) { | ||
71 | atpx_arg_elements[1].type = ACPI_TYPE_BUFFER; | ||
72 | atpx_arg_elements[1].buffer.length = params->length; | ||
73 | atpx_arg_elements[1].buffer.pointer = params->pointer; | ||
74 | } else { | ||
75 | /* We need a second fake parameter */ | ||
76 | atpx_arg_elements[1].type = ACPI_TYPE_INTEGER; | ||
77 | atpx_arg_elements[1].integer.value = 0; | ||
78 | } | ||
36 | 79 | ||
37 | atpx_arg_elements[1].type = ACPI_TYPE_INTEGER; | 80 | status = acpi_evaluate_object(handle, "ATPX", &atpx_arg, &buffer); |
38 | atpx_arg_elements[1].integer.value = 0; | ||
39 | 81 | ||
40 | status = acpi_evaluate_object(handle, NULL, &atpx_arg, &buffer); | 82 | /* Fail only if calling the method fails and ATPX is supported */ |
41 | if (ACPI_FAILURE(status)) { | 83 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { |
42 | printk("%s: failed to call ATPX: %s\n", __func__, acpi_format_exception(status)); | 84 | printk("failed to evaluate ATPX got %s\n", |
43 | return -ENOSYS; | 85 | acpi_format_exception(status)); |
86 | kfree(buffer.pointer); | ||
87 | return NULL; | ||
44 | } | 88 | } |
45 | obj = (union acpi_object *)buffer.pointer; | 89 | |
46 | if (obj && (obj->type == ACPI_TYPE_BUFFER)) | 90 | return buffer.pointer; |
47 | printk(KERN_INFO "radeon atpx: version is %d\n", *((u8 *)(obj->buffer.pointer) + 2)); | 91 | } |
48 | kfree(buffer.pointer); | 92 | |
49 | return 0; | 93 | /** |
94 | * radeon_atpx_parse_functions - parse supported functions | ||
95 | * | ||
96 | * @f: supported functions struct | ||
97 | * @mask: supported functions mask from ATPX | ||
98 | * | ||
99 | * Use the supported functions mask from ATPX function | ||
100 | * ATPX_FUNCTION_VERIFY_INTERFACE to determine what functions | ||
101 | * are supported (all asics). | ||
102 | */ | ||
103 | static void radeon_atpx_parse_functions(struct radeon_atpx_functions *f, u32 mask) | ||
104 | { | ||
105 | f->px_params = mask & ATPX_GET_PX_PARAMETERS_SUPPORTED; | ||
106 | f->power_cntl = mask & ATPX_POWER_CONTROL_SUPPORTED; | ||
107 | f->disp_mux_cntl = mask & ATPX_DISPLAY_MUX_CONTROL_SUPPORTED; | ||
108 | f->i2c_mux_cntl = mask & ATPX_I2C_MUX_CONTROL_SUPPORTED; | ||
109 | f->switch_start = mask & ATPX_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION_SUPPORTED; | ||
110 | f->switch_end = mask & ATPX_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION_SUPPORTED; | ||
111 | f->disp_connectors_mapping = mask & ATPX_GET_DISPLAY_CONNECTORS_MAPPING_SUPPORTED; | ||
112 | f->disp_detetion_ports = mask & ATPX_GET_DISPLAY_DETECTION_PORTS_SUPPORTED; | ||
113 | } | ||
114 | |||
115 | /** | ||
116 | * radeon_atpx_verify_interface - verify ATPX | ||
117 | * | ||
118 | * @handle: acpi handle | ||
119 | * @atpx: radeon atpx struct | ||
120 | * | ||
121 | * Execute the ATPX_FUNCTION_VERIFY_INTERFACE ATPX function | ||
122 | * to initialize ATPX and determine what features are supported | ||
123 | * (all asics). | ||
124 | * returns 0 on success, error on failure. | ||
125 | */ | ||
126 | static int radeon_atpx_verify_interface(acpi_handle handle, | ||
127 | struct radeon_atpx *atpx) | ||
128 | { | ||
129 | union acpi_object *info; | ||
130 | struct atpx_verify_interface output; | ||
131 | size_t size; | ||
132 | int err = 0; | ||
133 | |||
134 | info = radeon_atpx_call(handle, ATPX_FUNCTION_VERIFY_INTERFACE, NULL); | ||
135 | if (!info) | ||
136 | return -EIO; | ||
137 | |||
138 | memset(&output, 0, sizeof(output)); | ||
139 | |||
140 | size = *(u16 *) info->buffer.pointer; | ||
141 | if (size < 8) { | ||
142 | printk("ATPX buffer is too small: %lu\n", size); | ||
143 | err = -EINVAL; | ||
144 | goto out; | ||
145 | } | ||
146 | size = min(sizeof(output), size); | ||
147 | |||
148 | memcpy(&output, info->buffer.pointer, size); | ||
149 | |||
150 | /* TODO: check version? */ | ||
151 | printk("ATPX version %u\n", output.version); | ||
152 | |||
153 | radeon_atpx_parse_functions(&atpx->functions, output.function_bits); | ||
154 | |||
155 | out: | ||
156 | kfree(info); | ||
157 | return err; | ||
50 | } | 158 | } |
51 | 159 | ||
52 | static int radeon_atpx_execute(acpi_handle handle, int cmd_id, u16 value) | 160 | static int radeon_atpx_execute(acpi_handle handle, int cmd_id, u16 value) |
@@ -161,9 +269,8 @@ static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev) | |||
161 | static int radeon_atpx_init(void) | 269 | static int radeon_atpx_init(void) |
162 | { | 270 | { |
163 | /* set up the ATPX handle */ | 271 | /* set up the ATPX handle */ |
164 | 272 | return radeon_atpx_verify_interface(radeon_atpx_priv.atpx_handle, | |
165 | radeon_atpx_get_version(radeon_atpx_priv.atpx_handle); | 273 | &radeon_atpx_priv.atpx); |
166 | return 0; | ||
167 | } | 274 | } |
168 | 275 | ||
169 | static int radeon_atpx_get_client_id(struct pci_dev *pdev) | 276 | static int radeon_atpx_get_client_id(struct pci_dev *pdev) |