drm/radeon: clean up atpx power control handling
[cascardo/linux.git] / drivers / gpu / drm / radeon / radeon_atpx_handler.c
1 /*
2  * Copyright (c) 2010 Red Hat Inc.
3  * Author : Dave Airlie <airlied@redhat.com>
4  *
5  * Licensed under GPLv2
6  *
7  * ATPX support for both Intel/ATI
8  */
9 #include <linux/vga_switcheroo.h>
10 #include <linux/slab.h>
11 #include <linux/acpi.h>
12 #include <linux/pci.h>
13
14 #include "radeon_acpi.h"
15
16 struct radeon_atpx_functions {
17         bool px_params;
18         bool power_cntl;
19         bool disp_mux_cntl;
20         bool i2c_mux_cntl;
21         bool switch_start;
22         bool switch_end;
23         bool disp_connectors_mapping;
24         bool disp_detetion_ports;
25 };
26
27 struct radeon_atpx {
28         acpi_handle handle;
29         struct radeon_atpx_functions functions;
30 };
31
32 static struct radeon_atpx_priv {
33         bool atpx_detected;
34         /* handle for device - and atpx */
35         acpi_handle dhandle;
36         struct radeon_atpx atpx;
37 } radeon_atpx_priv;
38
39 struct atpx_verify_interface {
40         u16 size;               /* structure size in bytes (includes size field) */
41         u16 version;            /* version */
42         u32 function_bits;      /* supported functions bit vector */
43 } __packed;
44
45 struct atpx_px_params {
46         u16 size;               /* structure size in bytes (includes size field) */
47         u32 valid_flags;        /* which flags are valid */
48         u32 flags;              /* flags */
49 } __packed;
50
51 struct atpx_power_control {
52         u16 size;
53         u8 dgpu_state;
54 } __packed;
55
56 struct atpx_mux {
57         u16 size;
58         u16 mux;
59 } __packed;
60
61 bool radeon_has_atpx(void) {
62         return radeon_atpx_priv.atpx_detected;
63 }
64
65 /**
66  * radeon_atpx_call - call an ATPX method
67  *
68  * @handle: acpi handle
69  * @function: the ATPX function to execute
70  * @params: ATPX function params
71  *
72  * Executes the requested ATPX function (all asics).
73  * Returns a pointer to the acpi output buffer.
74  */
75 static union acpi_object *radeon_atpx_call(acpi_handle handle, int function,
76                                            struct acpi_buffer *params)
77 {
78         acpi_status status;
79         union acpi_object atpx_arg_elements[2];
80         struct acpi_object_list atpx_arg;
81         struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
82
83         atpx_arg.count = 2;
84         atpx_arg.pointer = &atpx_arg_elements[0];
85
86         atpx_arg_elements[0].type = ACPI_TYPE_INTEGER;
87         atpx_arg_elements[0].integer.value = function;
88
89         if (params) {
90                 atpx_arg_elements[1].type = ACPI_TYPE_BUFFER;
91                 atpx_arg_elements[1].buffer.length = params->length;
92                 atpx_arg_elements[1].buffer.pointer = params->pointer;
93         } else {
94                 /* We need a second fake parameter */
95                 atpx_arg_elements[1].type = ACPI_TYPE_INTEGER;
96                 atpx_arg_elements[1].integer.value = 0;
97         }
98
99         status = acpi_evaluate_object(handle, NULL, &atpx_arg, &buffer);
100
101         /* Fail only if calling the method fails and ATPX is supported */
102         if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
103                 printk("failed to evaluate ATPX got %s\n",
104                        acpi_format_exception(status));
105                 kfree(buffer.pointer);
106                 return NULL;
107         }
108
109         return buffer.pointer;
110 }
111
112 /**
113  * radeon_atpx_parse_functions - parse supported functions
114  *
115  * @f: supported functions struct
116  * @mask: supported functions mask from ATPX
117  *
118  * Use the supported functions mask from ATPX function
119  * ATPX_FUNCTION_VERIFY_INTERFACE to determine what functions
120  * are supported (all asics).
121  */
122 static void radeon_atpx_parse_functions(struct radeon_atpx_functions *f, u32 mask)
123 {
124         f->px_params = mask & ATPX_GET_PX_PARAMETERS_SUPPORTED;
125         f->power_cntl = mask & ATPX_POWER_CONTROL_SUPPORTED;
126         f->disp_mux_cntl = mask & ATPX_DISPLAY_MUX_CONTROL_SUPPORTED;
127         f->i2c_mux_cntl = mask & ATPX_I2C_MUX_CONTROL_SUPPORTED;
128         f->switch_start = mask & ATPX_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION_SUPPORTED;
129         f->switch_end = mask & ATPX_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION_SUPPORTED;
130         f->disp_connectors_mapping = mask & ATPX_GET_DISPLAY_CONNECTORS_MAPPING_SUPPORTED;
131         f->disp_detetion_ports = mask & ATPX_GET_DISPLAY_DETECTION_PORTS_SUPPORTED;
132 }
133
134 /**
135  * radeon_atpx_validate_functions - validate ATPX functions
136  *
137  * @atpx: radeon atpx struct
138  *
139  * Validate that required functions are enabled (all asics).
140  * returns 0 on success, error on failure.
141  */
142 static int radeon_atpx_validate(struct radeon_atpx *atpx)
143 {
144         u32 valid_bits = 0;
145
146         if (atpx->functions.px_params) {
147                 union acpi_object *info;
148                 struct atpx_px_params output;
149                 size_t size;
150
151                 info = radeon_atpx_call(atpx->handle, ATPX_FUNCTION_GET_PX_PARAMETERS, NULL);
152                 if (!info)
153                         return -EIO;
154
155                 memset(&output, 0, sizeof(output));
156
157                 size = *(u16 *) info->buffer.pointer;
158                 if (size < 10) {
159                         printk("ATPX buffer is too small: %zu\n", size);
160                         kfree(info);
161                         return -EINVAL;
162                 }
163                 size = min(sizeof(output), size);
164
165                 memcpy(&output, info->buffer.pointer, size);
166
167                 valid_bits = output.flags & output.valid_flags;
168
169                 kfree(info);
170         }
171
172         /* if separate mux flag is set, mux controls are required */
173         if (valid_bits & ATPX_SEPARATE_MUX_FOR_I2C) {
174                 atpx->functions.i2c_mux_cntl = true;
175                 atpx->functions.disp_mux_cntl = true;
176         }
177         /* if any outputs are muxed, mux controls are required */
178         if (valid_bits & (ATPX_CRT1_RGB_SIGNAL_MUXED |
179                           ATPX_TV_SIGNAL_MUXED |
180                           ATPX_DFP_SIGNAL_MUXED))
181                 atpx->functions.disp_mux_cntl = true;
182
183         /* some bioses set these bits rather than flagging power_cntl as supported */
184         if (valid_bits & (ATPX_DYNAMIC_PX_SUPPORTED |
185                           ATPX_DYNAMIC_DGPU_POWER_OFF_SUPPORTED))
186                 atpx->functions.power_cntl = true;
187
188         if (valid_bits & ATPX_MS_HYBRID_GFX_SUPPORTED) {
189                 printk("Hybrid Graphics, ATPX dGPU power cntl disabled\n");
190                 atpx->functions.power_cntl = false;
191         } else if (atpx->functions.power_cntl == false) {
192                 /* make sure required functions are enabled */
193                 /* dGPU power control is required */
194                 printk("ATPX dGPU power cntl not present, forcing\n");
195                 atpx->functions.power_cntl = true;
196         }
197
198         return 0;
199 }
200
201 /**
202  * radeon_atpx_verify_interface - verify ATPX
203  *
204  * @atpx: radeon atpx struct
205  *
206  * Execute the ATPX_FUNCTION_VERIFY_INTERFACE ATPX function
207  * to initialize ATPX and determine what features are supported
208  * (all asics).
209  * returns 0 on success, error on failure.
210  */
211 static int radeon_atpx_verify_interface(struct radeon_atpx *atpx)
212 {
213         union acpi_object *info;
214         struct atpx_verify_interface output;
215         size_t size;
216         int err = 0;
217
218         info = radeon_atpx_call(atpx->handle, ATPX_FUNCTION_VERIFY_INTERFACE, NULL);
219         if (!info)
220                 return -EIO;
221
222         memset(&output, 0, sizeof(output));
223
224         size = *(u16 *) info->buffer.pointer;
225         if (size < 8) {
226                 printk("ATPX buffer is too small: %zu\n", size);
227                 err = -EINVAL;
228                 goto out;
229         }
230         size = min(sizeof(output), size);
231
232         memcpy(&output, info->buffer.pointer, size);
233
234         /* TODO: check version? */
235         printk("ATPX version %u, functions 0x%08x\n",
236                output.version, output.function_bits);
237
238         radeon_atpx_parse_functions(&atpx->functions, output.function_bits);
239
240 out:
241         kfree(info);
242         return err;
243 }
244
245 /**
246  * radeon_atpx_set_discrete_state - power up/down discrete GPU
247  *
248  * @atpx: atpx info struct
249  * @state: discrete GPU state (0 = power down, 1 = power up)
250  *
251  * Execute the ATPX_FUNCTION_POWER_CONTROL ATPX function to
252  * power down/up the discrete GPU (all asics).
253  * Returns 0 on success, error on failure.
254  */
255 static int radeon_atpx_set_discrete_state(struct radeon_atpx *atpx, u8 state)
256 {
257         struct acpi_buffer params;
258         union acpi_object *info;
259         struct atpx_power_control input;
260
261         if (atpx->functions.power_cntl) {
262                 input.size = 3;
263                 input.dgpu_state = state;
264                 params.length = input.size;
265                 params.pointer = &input;
266                 info = radeon_atpx_call(atpx->handle,
267                                         ATPX_FUNCTION_POWER_CONTROL,
268                                         &params);
269                 if (!info)
270                         return -EIO;
271                 kfree(info);
272         }
273         return 0;
274 }
275
276 /**
277  * radeon_atpx_switch_disp_mux - switch display mux
278  *
279  * @atpx: atpx info struct
280  * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU)
281  *
282  * Execute the ATPX_FUNCTION_DISPLAY_MUX_CONTROL ATPX function to
283  * switch the display mux between the discrete GPU and integrated GPU
284  * (all asics).
285  * Returns 0 on success, error on failure.
286  */
287 static int radeon_atpx_switch_disp_mux(struct radeon_atpx *atpx, u16 mux_id)
288 {
289         struct acpi_buffer params;
290         union acpi_object *info;
291         struct atpx_mux input;
292
293         if (atpx->functions.disp_mux_cntl) {
294                 input.size = 4;
295                 input.mux = mux_id;
296                 params.length = input.size;
297                 params.pointer = &input;
298                 info = radeon_atpx_call(atpx->handle,
299                                         ATPX_FUNCTION_DISPLAY_MUX_CONTROL,
300                                         &params);
301                 if (!info)
302                         return -EIO;
303                 kfree(info);
304         }
305         return 0;
306 }
307
308 /**
309  * radeon_atpx_switch_i2c_mux - switch i2c/hpd mux
310  *
311  * @atpx: atpx info struct
312  * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU)
313  *
314  * Execute the ATPX_FUNCTION_I2C_MUX_CONTROL ATPX function to
315  * switch the i2c/hpd mux between the discrete GPU and integrated GPU
316  * (all asics).
317  * Returns 0 on success, error on failure.
318  */
319 static int radeon_atpx_switch_i2c_mux(struct radeon_atpx *atpx, u16 mux_id)
320 {
321         struct acpi_buffer params;
322         union acpi_object *info;
323         struct atpx_mux input;
324
325         if (atpx->functions.i2c_mux_cntl) {
326                 input.size = 4;
327                 input.mux = mux_id;
328                 params.length = input.size;
329                 params.pointer = &input;
330                 info = radeon_atpx_call(atpx->handle,
331                                         ATPX_FUNCTION_I2C_MUX_CONTROL,
332                                         &params);
333                 if (!info)
334                         return -EIO;
335                 kfree(info);
336         }
337         return 0;
338 }
339
340 /**
341  * radeon_atpx_switch_start - notify the sbios of a GPU switch
342  *
343  * @atpx: atpx info struct
344  * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU)
345  *
346  * Execute the ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION ATPX
347  * function to notify the sbios that a switch between the discrete GPU and
348  * integrated GPU has begun (all asics).
349  * Returns 0 on success, error on failure.
350  */
351 static int radeon_atpx_switch_start(struct radeon_atpx *atpx, u16 mux_id)
352 {
353         struct acpi_buffer params;
354         union acpi_object *info;
355         struct atpx_mux input;
356
357         if (atpx->functions.switch_start) {
358                 input.size = 4;
359                 input.mux = mux_id;
360                 params.length = input.size;
361                 params.pointer = &input;
362                 info = radeon_atpx_call(atpx->handle,
363                                         ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION,
364                                         &params);
365                 if (!info)
366                         return -EIO;
367                 kfree(info);
368         }
369         return 0;
370 }
371
372 /**
373  * radeon_atpx_switch_end - notify the sbios of a GPU switch
374  *
375  * @atpx: atpx info struct
376  * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU)
377  *
378  * Execute the ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION ATPX
379  * function to notify the sbios that a switch between the discrete GPU and
380  * integrated GPU has ended (all asics).
381  * Returns 0 on success, error on failure.
382  */
383 static int radeon_atpx_switch_end(struct radeon_atpx *atpx, u16 mux_id)
384 {
385         struct acpi_buffer params;
386         union acpi_object *info;
387         struct atpx_mux input;
388
389         if (atpx->functions.switch_end) {
390                 input.size = 4;
391                 input.mux = mux_id;
392                 params.length = input.size;
393                 params.pointer = &input;
394                 info = radeon_atpx_call(atpx->handle,
395                                         ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION,
396                                         &params);
397                 if (!info)
398                         return -EIO;
399                 kfree(info);
400         }
401         return 0;
402 }
403
404 /**
405  * radeon_atpx_switchto - switch to the requested GPU
406  *
407  * @id: GPU to switch to
408  *
409  * Execute the necessary ATPX functions to switch between the discrete GPU and
410  * integrated GPU (all asics).
411  * Returns 0 on success, error on failure.
412  */
413 static int radeon_atpx_switchto(enum vga_switcheroo_client_id id)
414 {
415         u16 gpu_id;
416
417         if (id == VGA_SWITCHEROO_IGD)
418                 gpu_id = ATPX_INTEGRATED_GPU;
419         else
420                 gpu_id = ATPX_DISCRETE_GPU;
421
422         radeon_atpx_switch_start(&radeon_atpx_priv.atpx, gpu_id);
423         radeon_atpx_switch_disp_mux(&radeon_atpx_priv.atpx, gpu_id);
424         radeon_atpx_switch_i2c_mux(&radeon_atpx_priv.atpx, gpu_id);
425         radeon_atpx_switch_end(&radeon_atpx_priv.atpx, gpu_id);
426
427         return 0;
428 }
429
430 /**
431  * radeon_atpx_power_state - power down/up the requested GPU
432  *
433  * @id: GPU to power down/up
434  * @state: requested power state (0 = off, 1 = on)
435  *
436  * Execute the necessary ATPX function to power down/up the discrete GPU
437  * (all asics).
438  * Returns 0 on success, error on failure.
439  */
440 static int radeon_atpx_power_state(enum vga_switcheroo_client_id id,
441                                    enum vga_switcheroo_state state)
442 {
443         /* on w500 ACPI can't change intel gpu state */
444         if (id == VGA_SWITCHEROO_IGD)
445                 return 0;
446
447         radeon_atpx_set_discrete_state(&radeon_atpx_priv.atpx, state);
448         return 0;
449 }
450
451 /**
452  * radeon_atpx_pci_probe_handle - look up the ATPX handle
453  *
454  * @pdev: pci device
455  *
456  * Look up the ATPX handles (all asics).
457  * Returns true if the handles are found, false if not.
458  */
459 static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev)
460 {
461         acpi_handle dhandle, atpx_handle;
462         acpi_status status;
463
464         dhandle = ACPI_HANDLE(&pdev->dev);
465         if (!dhandle)
466                 return false;
467
468         status = acpi_get_handle(dhandle, "ATPX", &atpx_handle);
469         if (ACPI_FAILURE(status))
470                 return false;
471
472         radeon_atpx_priv.dhandle = dhandle;
473         radeon_atpx_priv.atpx.handle = atpx_handle;
474         return true;
475 }
476
477 /**
478  * radeon_atpx_init - verify the ATPX interface
479  *
480  * Verify the ATPX interface (all asics).
481  * Returns 0 on success, error on failure.
482  */
483 static int radeon_atpx_init(void)
484 {
485         int r;
486
487         /* set up the ATPX handle */
488         r = radeon_atpx_verify_interface(&radeon_atpx_priv.atpx);
489         if (r)
490                 return r;
491
492         /* validate the atpx setup */
493         r = radeon_atpx_validate(&radeon_atpx_priv.atpx);
494         if (r)
495                 return r;
496
497         return 0;
498 }
499
500 /**
501  * radeon_atpx_get_client_id - get the client id
502  *
503  * @pdev: pci device
504  *
505  * look up whether we are the integrated or discrete GPU (all asics).
506  * Returns the client id.
507  */
508 static int radeon_atpx_get_client_id(struct pci_dev *pdev)
509 {
510         if (radeon_atpx_priv.dhandle == ACPI_HANDLE(&pdev->dev))
511                 return VGA_SWITCHEROO_IGD;
512         else
513                 return VGA_SWITCHEROO_DIS;
514 }
515
516 static const struct vga_switcheroo_handler radeon_atpx_handler = {
517         .switchto = radeon_atpx_switchto,
518         .power_state = radeon_atpx_power_state,
519         .init = radeon_atpx_init,
520         .get_client_id = radeon_atpx_get_client_id,
521 };
522
523 /**
524  * radeon_atpx_detect - detect whether we have PX
525  *
526  * Check if we have a PX system (all asics).
527  * Returns true if we have a PX system, false if not.
528  */
529 static bool radeon_atpx_detect(void)
530 {
531         char acpi_method_name[255] = { 0 };
532         struct acpi_buffer buffer = {sizeof(acpi_method_name), acpi_method_name};
533         struct pci_dev *pdev = NULL;
534         bool has_atpx = false;
535         int vga_count = 0;
536
537         while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
538                 vga_count++;
539
540                 has_atpx |= (radeon_atpx_pci_probe_handle(pdev) == true);
541         }
542
543         /* some newer PX laptops mark the dGPU as a non-VGA display device */
544         while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) {
545                 vga_count++;
546
547                 has_atpx |= (radeon_atpx_pci_probe_handle(pdev) == true);
548         }
549
550         if (has_atpx && vga_count == 2) {
551                 acpi_get_name(radeon_atpx_priv.atpx.handle, ACPI_FULL_PATHNAME, &buffer);
552                 printk(KERN_INFO "vga_switcheroo: detected switching method %s handle\n",
553                        acpi_method_name);
554                 radeon_atpx_priv.atpx_detected = true;
555                 return true;
556         }
557         return false;
558 }
559
560 /**
561  * radeon_register_atpx_handler - register with vga_switcheroo
562  *
563  * Register the PX callbacks with vga_switcheroo (all asics).
564  */
565 void radeon_register_atpx_handler(void)
566 {
567         bool r;
568         enum vga_switcheroo_handler_flags_t handler_flags = 0;
569
570         /* detect if we have any ATPX + 2 VGA in the system */
571         r = radeon_atpx_detect();
572         if (!r)
573                 return;
574
575         vga_switcheroo_register_handler(&radeon_atpx_handler, handler_flags);
576 }
577
578 /**
579  * radeon_unregister_atpx_handler - unregister with vga_switcheroo
580  *
581  * Unregister the PX callbacks with vga_switcheroo (all asics).
582  */
583 void radeon_unregister_atpx_handler(void)
584 {
585         vga_switcheroo_unregister_handler();
586 }