diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2012-08-16 14:07:37 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2012-09-20 13:10:37 -0400 |
commit | 492b49a2f21a7ce6cb0abce36017daa06036a626 (patch) | |
tree | cfd30f8739e6991aca373174f354ae42a1a5a66b /drivers/gpu/drm/radeon/radeon_atpx_handler.c | |
parent | 48fa412b7451530322cdbe969e404b798c6e204e (diff) |
drm/radeon: reorganize ATPX support (v2)
- rework the acpi execute code
- User proper parameters for ATPX functions
v2: rebase fixes
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_atpx_handler.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_atpx_handler.c | 170 |
1 files changed, 110 insertions, 60 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index c1f2671a7b0b..331db7a95f09 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c | |||
@@ -26,6 +26,7 @@ struct radeon_atpx_functions { | |||
26 | }; | 26 | }; |
27 | 27 | ||
28 | struct radeon_atpx { | 28 | struct radeon_atpx { |
29 | acpi_handle handle; | ||
29 | struct radeon_atpx_functions functions; | 30 | struct radeon_atpx_functions functions; |
30 | }; | 31 | }; |
31 | 32 | ||
@@ -33,7 +34,6 @@ static struct radeon_atpx_priv { | |||
33 | bool atpx_detected; | 34 | bool atpx_detected; |
34 | /* handle for device - and atpx */ | 35 | /* handle for device - and atpx */ |
35 | acpi_handle dhandle; | 36 | acpi_handle dhandle; |
36 | acpi_handle atpx_handle; | ||
37 | struct radeon_atpx atpx; | 37 | struct radeon_atpx atpx; |
38 | } radeon_atpx_priv; | 38 | } radeon_atpx_priv; |
39 | 39 | ||
@@ -43,6 +43,16 @@ struct atpx_verify_interface { | |||
43 | u32 function_bits; /* supported functions bit vector */ | 43 | u32 function_bits; /* supported functions bit vector */ |
44 | } __packed; | 44 | } __packed; |
45 | 45 | ||
46 | struct atpx_power_control { | ||
47 | u16 size; | ||
48 | u8 dgpu_state; | ||
49 | } __packed; | ||
50 | |||
51 | struct atpx_mux { | ||
52 | u16 size; | ||
53 | u16 mux; | ||
54 | } __packed; | ||
55 | |||
46 | /** | 56 | /** |
47 | * radeon_atpx_call - call an ATPX method | 57 | * radeon_atpx_call - call an ATPX method |
48 | * | 58 | * |
@@ -123,15 +133,14 @@ static void radeon_atpx_parse_functions(struct radeon_atpx_functions *f, u32 mas | |||
123 | * (all asics). | 133 | * (all asics). |
124 | * returns 0 on success, error on failure. | 134 | * returns 0 on success, error on failure. |
125 | */ | 135 | */ |
126 | static int radeon_atpx_verify_interface(acpi_handle handle, | 136 | static int radeon_atpx_verify_interface(struct radeon_atpx *atpx) |
127 | struct radeon_atpx *atpx) | ||
128 | { | 137 | { |
129 | union acpi_object *info; | 138 | union acpi_object *info; |
130 | struct atpx_verify_interface output; | 139 | struct atpx_verify_interface output; |
131 | size_t size; | 140 | size_t size; |
132 | int err = 0; | 141 | int err = 0; |
133 | 142 | ||
134 | info = radeon_atpx_call(handle, ATPX_FUNCTION_VERIFY_INTERFACE, NULL); | 143 | info = radeon_atpx_call(atpx->handle, ATPX_FUNCTION_VERIFY_INTERFACE, NULL); |
135 | if (!info) | 144 | if (!info) |
136 | return -EIO; | 145 | return -EIO; |
137 | 146 | ||
@@ -157,82 +166,124 @@ out: | |||
157 | return err; | 166 | return err; |
158 | } | 167 | } |
159 | 168 | ||
160 | static int radeon_atpx_execute(acpi_handle handle, int cmd_id, u16 value) | 169 | static int radeon_atpx_set_discrete_state(struct radeon_atpx *atpx, u8 state) |
161 | { | 170 | { |
162 | acpi_status status; | 171 | struct acpi_buffer params; |
163 | union acpi_object atpx_arg_elements[2]; | 172 | union acpi_object *info; |
164 | struct acpi_object_list atpx_arg; | 173 | struct atpx_power_control input; |
165 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 174 | |
166 | uint8_t buf[4] = {0}; | 175 | if (atpx->functions.power_cntl) { |
167 | 176 | input.size = 3; | |
168 | if (!handle) | 177 | input.dgpu_state = state; |
169 | return -EINVAL; | 178 | params.length = input.size; |
170 | 179 | params.pointer = &input; | |
171 | atpx_arg.count = 2; | 180 | info = radeon_atpx_call(atpx->handle, |
172 | atpx_arg.pointer = &atpx_arg_elements[0]; | 181 | ATPX_FUNCTION_POWER_CONTROL, |
173 | 182 | ¶ms); | |
174 | atpx_arg_elements[0].type = ACPI_TYPE_INTEGER; | 183 | if (!info) |
175 | atpx_arg_elements[0].integer.value = cmd_id; | 184 | return -EIO; |
176 | 185 | kfree(info); | |
177 | buf[2] = value & 0xff; | ||
178 | buf[3] = (value >> 8) & 0xff; | ||
179 | |||
180 | atpx_arg_elements[1].type = ACPI_TYPE_BUFFER; | ||
181 | atpx_arg_elements[1].buffer.length = 4; | ||
182 | atpx_arg_elements[1].buffer.pointer = buf; | ||
183 | |||
184 | status = acpi_evaluate_object(handle, NULL, &atpx_arg, &buffer); | ||
185 | if (ACPI_FAILURE(status)) { | ||
186 | printk("%s: failed to call ATPX: %s\n", __func__, acpi_format_exception(status)); | ||
187 | return -ENOSYS; | ||
188 | } | 186 | } |
189 | kfree(buffer.pointer); | ||
190 | |||
191 | return 0; | 187 | return 0; |
192 | } | 188 | } |
193 | 189 | ||
194 | static int radeon_atpx_set_discrete_state(acpi_handle handle, int state) | 190 | static int radeon_atpx_switch_disp_mux(struct radeon_atpx *atpx, u16 mux_id) |
195 | { | ||
196 | return radeon_atpx_execute(handle, ATPX_FUNCTION_POWER_CONTROL, state); | ||
197 | } | ||
198 | |||
199 | static int radeon_atpx_switch_mux(acpi_handle handle, int mux_id) | ||
200 | { | 191 | { |
201 | return radeon_atpx_execute(handle, ATPX_FUNCTION_DISPLAY_MUX_CONTROL, mux_id); | 192 | struct acpi_buffer params; |
193 | union acpi_object *info; | ||
194 | struct atpx_mux input; | ||
195 | |||
196 | if (atpx->functions.disp_mux_cntl) { | ||
197 | input.size = 4; | ||
198 | input.mux = mux_id; | ||
199 | params.length = input.size; | ||
200 | params.pointer = &input; | ||
201 | info = radeon_atpx_call(atpx->handle, | ||
202 | ATPX_FUNCTION_DISPLAY_MUX_CONTROL, | ||
203 | ¶ms); | ||
204 | if (!info) | ||
205 | return -EIO; | ||
206 | kfree(info); | ||
207 | } | ||
208 | return 0; | ||
202 | } | 209 | } |
203 | 210 | ||
204 | static int radeon_atpx_switch_i2c_mux(acpi_handle handle, int mux_id) | 211 | static int radeon_atpx_switch_i2c_mux(struct radeon_atpx *atpx, u16 mux_id) |
205 | { | 212 | { |
206 | return radeon_atpx_execute(handle, ATPX_FUNCTION_I2C_MUX_CONTROL, mux_id); | 213 | struct acpi_buffer params; |
214 | union acpi_object *info; | ||
215 | struct atpx_mux input; | ||
216 | |||
217 | if (atpx->functions.i2c_mux_cntl) { | ||
218 | input.size = 4; | ||
219 | input.mux = mux_id; | ||
220 | params.length = input.size; | ||
221 | params.pointer = &input; | ||
222 | info = radeon_atpx_call(atpx->handle, | ||
223 | ATPX_FUNCTION_I2C_MUX_CONTROL, | ||
224 | ¶ms); | ||
225 | if (!info) | ||
226 | return -EIO; | ||
227 | kfree(info); | ||
228 | } | ||
229 | return 0; | ||
207 | } | 230 | } |
208 | 231 | ||
209 | static int radeon_atpx_switch_start(acpi_handle handle, int gpu_id) | 232 | static int radeon_atpx_switch_start(struct radeon_atpx *atpx, u16 mux_id) |
210 | { | 233 | { |
211 | return radeon_atpx_execute(handle, | 234 | struct acpi_buffer params; |
212 | ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION, | 235 | union acpi_object *info; |
213 | gpu_id); | 236 | struct atpx_mux input; |
237 | |||
238 | if (atpx->functions.switch_start) { | ||
239 | input.size = 4; | ||
240 | input.mux = mux_id; | ||
241 | params.length = input.size; | ||
242 | params.pointer = &input; | ||
243 | info = radeon_atpx_call(atpx->handle, | ||
244 | ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION, | ||
245 | ¶ms); | ||
246 | if (!info) | ||
247 | return -EIO; | ||
248 | kfree(info); | ||
249 | } | ||
250 | return 0; | ||
214 | } | 251 | } |
215 | 252 | ||
216 | static int radeon_atpx_switch_end(acpi_handle handle, int gpu_id) | 253 | static int radeon_atpx_switch_end(struct radeon_atpx *atpx, u16 mux_id) |
217 | { | 254 | { |
218 | return radeon_atpx_execute(handle, | 255 | struct acpi_buffer params; |
219 | ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION, | 256 | union acpi_object *info; |
220 | gpu_id); | 257 | struct atpx_mux input; |
258 | |||
259 | if (atpx->functions.switch_end) { | ||
260 | input.size = 4; | ||
261 | input.mux = mux_id; | ||
262 | params.length = input.size; | ||
263 | params.pointer = &input; | ||
264 | info = radeon_atpx_call(atpx->handle, | ||
265 | ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION, | ||
266 | ¶ms); | ||
267 | if (!info) | ||
268 | return -EIO; | ||
269 | kfree(info); | ||
270 | } | ||
271 | return 0; | ||
221 | } | 272 | } |
222 | 273 | ||
223 | static int radeon_atpx_switchto(enum vga_switcheroo_client_id id) | 274 | static int radeon_atpx_switchto(enum vga_switcheroo_client_id id) |
224 | { | 275 | { |
225 | int gpu_id; | 276 | u16 gpu_id; |
226 | 277 | ||
227 | if (id == VGA_SWITCHEROO_IGD) | 278 | if (id == VGA_SWITCHEROO_IGD) |
228 | gpu_id = ATPX_INTEGRATED_GPU; | 279 | gpu_id = ATPX_INTEGRATED_GPU; |
229 | else | 280 | else |
230 | gpu_id = ATPX_DISCRETE_GPU; | 281 | gpu_id = ATPX_DISCRETE_GPU; |
231 | 282 | ||
232 | radeon_atpx_switch_start(radeon_atpx_priv.atpx_handle, gpu_id); | 283 | radeon_atpx_switch_start(&radeon_atpx_priv.atpx, gpu_id); |
233 | radeon_atpx_switch_mux(radeon_atpx_priv.atpx_handle, gpu_id); | 284 | radeon_atpx_switch_disp_mux(&radeon_atpx_priv.atpx, gpu_id); |
234 | radeon_atpx_switch_i2c_mux(radeon_atpx_priv.atpx_handle, gpu_id); | 285 | radeon_atpx_switch_i2c_mux(&radeon_atpx_priv.atpx, gpu_id); |
235 | radeon_atpx_switch_end(radeon_atpx_priv.atpx_handle, gpu_id); | 286 | radeon_atpx_switch_end(&radeon_atpx_priv.atpx, gpu_id); |
236 | 287 | ||
237 | return 0; | 288 | return 0; |
238 | } | 289 | } |
@@ -244,7 +295,7 @@ static int radeon_atpx_power_state(enum vga_switcheroo_client_id id, | |||
244 | if (id == VGA_SWITCHEROO_IGD) | 295 | if (id == VGA_SWITCHEROO_IGD) |
245 | return 0; | 296 | return 0; |
246 | 297 | ||
247 | radeon_atpx_set_discrete_state(radeon_atpx_priv.atpx_handle, state); | 298 | radeon_atpx_set_discrete_state(&radeon_atpx_priv.atpx, state); |
248 | return 0; | 299 | return 0; |
249 | } | 300 | } |
250 | 301 | ||
@@ -262,15 +313,14 @@ static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev) | |||
262 | return false; | 313 | return false; |
263 | 314 | ||
264 | radeon_atpx_priv.dhandle = dhandle; | 315 | radeon_atpx_priv.dhandle = dhandle; |
265 | radeon_atpx_priv.atpx_handle = atpx_handle; | 316 | radeon_atpx_priv.atpx.handle = atpx_handle; |
266 | return true; | 317 | return true; |
267 | } | 318 | } |
268 | 319 | ||
269 | static int radeon_atpx_init(void) | 320 | static int radeon_atpx_init(void) |
270 | { | 321 | { |
271 | /* set up the ATPX handle */ | 322 | /* set up the ATPX handle */ |
272 | return radeon_atpx_verify_interface(radeon_atpx_priv.atpx_handle, | 323 | return radeon_atpx_verify_interface(&radeon_atpx_priv.atpx); |
273 | &radeon_atpx_priv.atpx); | ||
274 | } | 324 | } |
275 | 325 | ||
276 | static int radeon_atpx_get_client_id(struct pci_dev *pdev) | 326 | static int radeon_atpx_get_client_id(struct pci_dev *pdev) |
@@ -303,7 +353,7 @@ static bool radeon_atpx_detect(void) | |||
303 | } | 353 | } |
304 | 354 | ||
305 | if (has_atpx && vga_count == 2) { | 355 | if (has_atpx && vga_count == 2) { |
306 | acpi_get_name(radeon_atpx_priv.atpx_handle, ACPI_FULL_PATHNAME, &buffer); | 356 | acpi_get_name(radeon_atpx_priv.atpx.handle, ACPI_FULL_PATHNAME, &buffer); |
307 | printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n", | 357 | printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n", |
308 | acpi_method_name); | 358 | acpi_method_name); |
309 | radeon_atpx_priv.atpx_detected = true; | 359 | radeon_atpx_priv.atpx_detected = true; |