]> Git Repo - linux.git/blob - drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
Merge tag 'drm-misc-next-2023-08-03' of git://anongit.freedesktop.org/drm/drm-misc...
[linux.git] / drivers / gpu / drm / amd / amdgpu / amdgpu_atpx_handler.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2010 Red Hat Inc.
4  * Author : Dave Airlie <[email protected]>
5  *
6  * ATPX support for both Intel/ATI
7  */
8 #include <linux/vga_switcheroo.h>
9 #include <linux/slab.h>
10 #include <linux/acpi.h>
11 #include <linux/pci.h>
12 #include <linux/delay.h>
13
14 #include "amdgpu.h"
15 #include "amd_acpi.h"
16
17 #define AMDGPU_PX_QUIRK_FORCE_ATPX  (1 << 0)
18
19 struct amdgpu_px_quirk {
20         u32 chip_vendor;
21         u32 chip_device;
22         u32 subsys_vendor;
23         u32 subsys_device;
24         u32 px_quirk_flags;
25 };
26
27 struct amdgpu_atpx_functions {
28         bool px_params;
29         bool power_cntl;
30         bool disp_mux_cntl;
31         bool i2c_mux_cntl;
32         bool switch_start;
33         bool switch_end;
34         bool disp_connectors_mapping;
35         bool disp_detection_ports;
36 };
37
38 struct amdgpu_atpx {
39         acpi_handle handle;
40         struct amdgpu_atpx_functions functions;
41         bool is_hybrid;
42         bool dgpu_req_power_for_displays;
43 };
44
45 static struct amdgpu_atpx_priv {
46         bool atpx_detected;
47         bool bridge_pm_usable;
48         unsigned int quirks;
49         /* handle for device - and atpx */
50         acpi_handle dhandle;
51         acpi_handle other_handle;
52         struct amdgpu_atpx atpx;
53 } amdgpu_atpx_priv;
54
55 struct atpx_verify_interface {
56         u16 size;               /* structure size in bytes (includes size field) */
57         u16 version;            /* version */
58         u32 function_bits;      /* supported functions bit vector */
59 } __packed;
60
61 struct atpx_px_params {
62         u16 size;               /* structure size in bytes (includes size field) */
63         u32 valid_flags;        /* which flags are valid */
64         u32 flags;              /* flags */
65 } __packed;
66
67 struct atpx_power_control {
68         u16 size;
69         u8 dgpu_state;
70 } __packed;
71
72 struct atpx_mux {
73         u16 size;
74         u16 mux;
75 } __packed;
76
77 bool amdgpu_has_atpx(void)
78 {
79         return amdgpu_atpx_priv.atpx_detected;
80 }
81
82 bool amdgpu_has_atpx_dgpu_power_cntl(void)
83 {
84         return amdgpu_atpx_priv.atpx.functions.power_cntl;
85 }
86
87 bool amdgpu_is_atpx_hybrid(void)
88 {
89         return amdgpu_atpx_priv.atpx.is_hybrid;
90 }
91
92 bool amdgpu_atpx_dgpu_req_power_for_displays(void)
93 {
94         return amdgpu_atpx_priv.atpx.dgpu_req_power_for_displays;
95 }
96
97 #if defined(CONFIG_ACPI)
98 void *amdgpu_atpx_get_dhandle(void)
99 {
100         return amdgpu_atpx_priv.dhandle;
101 }
102 #endif
103
104 /**
105  * amdgpu_atpx_call - call an ATPX method
106  *
107  * @handle: acpi handle
108  * @function: the ATPX function to execute
109  * @params: ATPX function params
110  *
111  * Executes the requested ATPX function (all asics).
112  * Returns a pointer to the acpi output buffer.
113  */
114 static union acpi_object *amdgpu_atpx_call(acpi_handle handle, int function,
115                                            struct acpi_buffer *params)
116 {
117         acpi_status status;
118         union acpi_object atpx_arg_elements[2];
119         struct acpi_object_list atpx_arg;
120         struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
121         struct acpi_device *adev = container_of(handle, struct acpi_device, handle);
122         struct device *dev = &adev->dev;
123
124         atpx_arg.count = 2;
125         atpx_arg.pointer = &atpx_arg_elements[0];
126
127         atpx_arg_elements[0].type = ACPI_TYPE_INTEGER;
128         atpx_arg_elements[0].integer.value = function;
129
130         if (params) {
131                 atpx_arg_elements[1].type = ACPI_TYPE_BUFFER;
132                 atpx_arg_elements[1].buffer.length = params->length;
133                 atpx_arg_elements[1].buffer.pointer = params->pointer;
134         } else {
135                 /* We need a second fake parameter */
136                 atpx_arg_elements[1].type = ACPI_TYPE_INTEGER;
137                 atpx_arg_elements[1].integer.value = 0;
138         }
139
140         status = acpi_evaluate_object(handle, NULL, &atpx_arg, &buffer);
141
142         /* Fail only if calling the method fails and ATPX is supported */
143         if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
144                 dev_err(dev, "failed to evaluate ATPX got %s\n",
145                         acpi_format_exception(status));
146                 kfree(buffer.pointer);
147                 return NULL;
148         }
149
150         return buffer.pointer;
151 }
152
153 /**
154  * amdgpu_atpx_parse_functions - parse supported functions
155  *
156  * @f: supported functions struct
157  * @mask: supported functions mask from ATPX
158  *
159  * Use the supported functions mask from ATPX function
160  * ATPX_FUNCTION_VERIFY_INTERFACE to determine what functions
161  * are supported (all asics).
162  */
163 static void amdgpu_atpx_parse_functions(struct amdgpu_atpx_functions *f, u32 mask)
164 {
165         f->px_params = mask & ATPX_GET_PX_PARAMETERS_SUPPORTED;
166         f->power_cntl = mask & ATPX_POWER_CONTROL_SUPPORTED;
167         f->disp_mux_cntl = mask & ATPX_DISPLAY_MUX_CONTROL_SUPPORTED;
168         f->i2c_mux_cntl = mask & ATPX_I2C_MUX_CONTROL_SUPPORTED;
169         f->switch_start = mask & ATPX_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION_SUPPORTED;
170         f->switch_end = mask & ATPX_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION_SUPPORTED;
171         f->disp_connectors_mapping = mask & ATPX_GET_DISPLAY_CONNECTORS_MAPPING_SUPPORTED;
172         f->disp_detection_ports = mask & ATPX_GET_DISPLAY_DETECTION_PORTS_SUPPORTED;
173 }
174
175 /**
176  * amdgpu_atpx_validate - validate ATPX functions
177  *
178  * @atpx: amdgpu atpx struct
179  *
180  * Validate that required functions are enabled (all asics).
181  * returns 0 on success, error on failure.
182  */
183 static int amdgpu_atpx_validate(struct amdgpu_atpx *atpx)
184 {
185         u32 valid_bits = 0;
186         struct acpi_device *adev = container_of(atpx->handle, struct acpi_device, handle);
187         struct device *dev = &adev->dev;
188
189         if (atpx->functions.px_params) {
190                 union acpi_object *info;
191                 struct atpx_px_params output;
192                 size_t size;
193
194                 info = amdgpu_atpx_call(atpx->handle, ATPX_FUNCTION_GET_PX_PARAMETERS, NULL);
195                 if (!info)
196                         return -EIO;
197
198                 memset(&output, 0, sizeof(output));
199
200                 size = *(u16 *) info->buffer.pointer;
201                 if (size < 10) {
202                         dev_err(dev, "ATPX buffer is too small: %zu\n", size);
203                         kfree(info);
204                         return -EINVAL;
205                 }
206                 size = min(sizeof(output), size);
207
208                 memcpy(&output, info->buffer.pointer, size);
209
210                 valid_bits = output.flags & output.valid_flags;
211
212                 kfree(info);
213         }
214
215         /* if separate mux flag is set, mux controls are required */
216         if (valid_bits & ATPX_SEPARATE_MUX_FOR_I2C) {
217                 atpx->functions.i2c_mux_cntl = true;
218                 atpx->functions.disp_mux_cntl = true;
219         }
220         /* if any outputs are muxed, mux controls are required */
221         if (valid_bits & (ATPX_CRT1_RGB_SIGNAL_MUXED |
222                           ATPX_TV_SIGNAL_MUXED |
223                           ATPX_DFP_SIGNAL_MUXED))
224                 atpx->functions.disp_mux_cntl = true;
225
226
227         /* some bioses set these bits rather than flagging power_cntl as supported */
228         if (valid_bits & (ATPX_DYNAMIC_PX_SUPPORTED |
229                           ATPX_DYNAMIC_DGPU_POWER_OFF_SUPPORTED))
230                 atpx->functions.power_cntl = true;
231
232         atpx->is_hybrid = false;
233         if (valid_bits & ATPX_MS_HYBRID_GFX_SUPPORTED) {
234                 if (amdgpu_atpx_priv.quirks & AMDGPU_PX_QUIRK_FORCE_ATPX) {
235                         dev_info(dev, "ATPX Hybrid Graphics, forcing to ATPX\n");
236                         atpx->functions.power_cntl = true;
237                         atpx->is_hybrid = false;
238                 } else {
239                         dev_info(dev, "ATPX Hybrid Graphics\n");
240                         /*
241                          * Disable legacy PM methods only when pcie port PM is usable,
242                          * otherwise the device might fail to power off or power on.
243                          */
244                         atpx->functions.power_cntl = !amdgpu_atpx_priv.bridge_pm_usable;
245                         atpx->is_hybrid = true;
246                 }
247         }
248
249         atpx->dgpu_req_power_for_displays = false;
250         if (valid_bits & ATPX_DGPU_REQ_POWER_FOR_DISPLAYS)
251                 atpx->dgpu_req_power_for_displays = true;
252
253         return 0;
254 }
255
256 /**
257  * amdgpu_atpx_verify_interface - verify ATPX
258  *
259  * @atpx: amdgpu atpx struct
260  *
261  * Execute the ATPX_FUNCTION_VERIFY_INTERFACE ATPX function
262  * to initialize ATPX and determine what features are supported
263  * (all asics).
264  * returns 0 on success, error on failure.
265  */
266 static int amdgpu_atpx_verify_interface(struct amdgpu_atpx *atpx)
267 {
268         union acpi_object *info;
269         struct atpx_verify_interface output;
270         size_t size;
271         int err = 0;
272         struct acpi_device *adev = container_of(atpx->handle, struct acpi_device, handle);
273         struct device *dev = &adev->dev;
274
275         info = amdgpu_atpx_call(atpx->handle, ATPX_FUNCTION_VERIFY_INTERFACE, NULL);
276         if (!info)
277                 return -EIO;
278
279         memset(&output, 0, sizeof(output));
280
281         size = *(u16 *) info->buffer.pointer;
282         if (size < 8) {
283                 printk("ATPX buffer is too small: %zu\n", size);
284                 err = -EINVAL;
285                 goto out;
286         }
287         size = min(sizeof(output), size);
288
289         memcpy(&output, info->buffer.pointer, size);
290
291         /* TODO: check version? */
292         dev_info(dev, "ATPX version %u, functions 0x%08x\n",
293                  output.version, output.function_bits);
294
295         amdgpu_atpx_parse_functions(&atpx->functions, output.function_bits);
296
297 out:
298         kfree(info);
299         return err;
300 }
301
302 /**
303  * amdgpu_atpx_set_discrete_state - power up/down discrete GPU
304  *
305  * @atpx: atpx info struct
306  * @state: discrete GPU state (0 = power down, 1 = power up)
307  *
308  * Execute the ATPX_FUNCTION_POWER_CONTROL ATPX function to
309  * power down/up the discrete GPU (all asics).
310  * Returns 0 on success, error on failure.
311  */
312 static int amdgpu_atpx_set_discrete_state(struct amdgpu_atpx *atpx, u8 state)
313 {
314         struct acpi_buffer params;
315         union acpi_object *info;
316         struct atpx_power_control input;
317
318         if (atpx->functions.power_cntl) {
319                 input.size = 3;
320                 input.dgpu_state = state;
321                 params.length = input.size;
322                 params.pointer = &input;
323                 info = amdgpu_atpx_call(atpx->handle,
324                                         ATPX_FUNCTION_POWER_CONTROL,
325                                         &params);
326                 if (!info)
327                         return -EIO;
328                 kfree(info);
329
330                 /* 200ms delay is required after off */
331                 if (state == 0)
332                         msleep(200);
333         }
334         return 0;
335 }
336
337 /**
338  * amdgpu_atpx_switch_disp_mux - switch display mux
339  *
340  * @atpx: atpx info struct
341  * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU)
342  *
343  * Execute the ATPX_FUNCTION_DISPLAY_MUX_CONTROL ATPX function to
344  * switch the display mux between the discrete GPU and integrated GPU
345  * (all asics).
346  * Returns 0 on success, error on failure.
347  */
348 static int amdgpu_atpx_switch_disp_mux(struct amdgpu_atpx *atpx, u16 mux_id)
349 {
350         struct acpi_buffer params;
351         union acpi_object *info;
352         struct atpx_mux input;
353
354         if (atpx->functions.disp_mux_cntl) {
355                 input.size = 4;
356                 input.mux = mux_id;
357                 params.length = input.size;
358                 params.pointer = &input;
359                 info = amdgpu_atpx_call(atpx->handle,
360                                         ATPX_FUNCTION_DISPLAY_MUX_CONTROL,
361                                         &params);
362                 if (!info)
363                         return -EIO;
364                 kfree(info);
365         }
366         return 0;
367 }
368
369 /**
370  * amdgpu_atpx_switch_i2c_mux - switch i2c/hpd mux
371  *
372  * @atpx: atpx info struct
373  * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU)
374  *
375  * Execute the ATPX_FUNCTION_I2C_MUX_CONTROL ATPX function to
376  * switch the i2c/hpd mux between the discrete GPU and integrated GPU
377  * (all asics).
378  * Returns 0 on success, error on failure.
379  */
380 static int amdgpu_atpx_switch_i2c_mux(struct amdgpu_atpx *atpx, u16 mux_id)
381 {
382         struct acpi_buffer params;
383         union acpi_object *info;
384         struct atpx_mux input;
385
386         if (atpx->functions.i2c_mux_cntl) {
387                 input.size = 4;
388                 input.mux = mux_id;
389                 params.length = input.size;
390                 params.pointer = &input;
391                 info = amdgpu_atpx_call(atpx->handle,
392                                         ATPX_FUNCTION_I2C_MUX_CONTROL,
393                                         &params);
394                 if (!info)
395                         return -EIO;
396                 kfree(info);
397         }
398         return 0;
399 }
400
401 /**
402  * amdgpu_atpx_switch_start - notify the sbios of a GPU switch
403  *
404  * @atpx: atpx info struct
405  * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU)
406  *
407  * Execute the ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION ATPX
408  * function to notify the sbios that a switch between the discrete GPU and
409  * integrated GPU has begun (all asics).
410  * Returns 0 on success, error on failure.
411  */
412 static int amdgpu_atpx_switch_start(struct amdgpu_atpx *atpx, u16 mux_id)
413 {
414         struct acpi_buffer params;
415         union acpi_object *info;
416         struct atpx_mux input;
417
418         if (atpx->functions.switch_start) {
419                 input.size = 4;
420                 input.mux = mux_id;
421                 params.length = input.size;
422                 params.pointer = &input;
423                 info = amdgpu_atpx_call(atpx->handle,
424                                         ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION,
425                                         &params);
426                 if (!info)
427                         return -EIO;
428                 kfree(info);
429         }
430         return 0;
431 }
432
433 /**
434  * amdgpu_atpx_switch_end - notify the sbios of a GPU switch
435  *
436  * @atpx: atpx info struct
437  * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU)
438  *
439  * Execute the ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION ATPX
440  * function to notify the sbios that a switch between the discrete GPU and
441  * integrated GPU has ended (all asics).
442  * Returns 0 on success, error on failure.
443  */
444 static int amdgpu_atpx_switch_end(struct amdgpu_atpx *atpx, u16 mux_id)
445 {
446         struct acpi_buffer params;
447         union acpi_object *info;
448         struct atpx_mux input;
449
450         if (atpx->functions.switch_end) {
451                 input.size = 4;
452                 input.mux = mux_id;
453                 params.length = input.size;
454                 params.pointer = &input;
455                 info = amdgpu_atpx_call(atpx->handle,
456                                         ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION,
457                                         &params);
458                 if (!info)
459                         return -EIO;
460                 kfree(info);
461         }
462         return 0;
463 }
464
465 /**
466  * amdgpu_atpx_switchto - switch to the requested GPU
467  *
468  * @id: GPU to switch to
469  *
470  * Execute the necessary ATPX functions to switch between the discrete GPU and
471  * integrated GPU (all asics).
472  * Returns 0 on success, error on failure.
473  */
474 static int amdgpu_atpx_switchto(enum vga_switcheroo_client_id id)
475 {
476         u16 gpu_id;
477
478         if (id == VGA_SWITCHEROO_IGD)
479                 gpu_id = ATPX_INTEGRATED_GPU;
480         else
481                 gpu_id = ATPX_DISCRETE_GPU;
482
483         amdgpu_atpx_switch_start(&amdgpu_atpx_priv.atpx, gpu_id);
484         amdgpu_atpx_switch_disp_mux(&amdgpu_atpx_priv.atpx, gpu_id);
485         amdgpu_atpx_switch_i2c_mux(&amdgpu_atpx_priv.atpx, gpu_id);
486         amdgpu_atpx_switch_end(&amdgpu_atpx_priv.atpx, gpu_id);
487
488         return 0;
489 }
490
491 /**
492  * amdgpu_atpx_power_state - power down/up the requested GPU
493  *
494  * @id: GPU to power down/up
495  * @state: requested power state (0 = off, 1 = on)
496  *
497  * Execute the necessary ATPX function to power down/up the discrete GPU
498  * (all asics).
499  * Returns 0 on success, error on failure.
500  */
501 static int amdgpu_atpx_power_state(enum vga_switcheroo_client_id id,
502                                    enum vga_switcheroo_state state)
503 {
504         /* on w500 ACPI can't change intel gpu state */
505         if (id == VGA_SWITCHEROO_IGD)
506                 return 0;
507
508         amdgpu_atpx_set_discrete_state(&amdgpu_atpx_priv.atpx, state);
509         return 0;
510 }
511
512 /**
513  * amdgpu_atpx_pci_probe_handle - look up the ATPX handle
514  *
515  * @pdev: pci device
516  *
517  * Look up the ATPX handles (all asics).
518  * Returns true if the handles are found, false if not.
519  */
520 static bool amdgpu_atpx_pci_probe_handle(struct pci_dev *pdev)
521 {
522         acpi_handle dhandle, atpx_handle;
523         acpi_status status;
524
525         dhandle = ACPI_HANDLE(&pdev->dev);
526         if (!dhandle)
527                 return false;
528
529         status = acpi_get_handle(dhandle, "ATPX", &atpx_handle);
530         if (ACPI_FAILURE(status)) {
531                 amdgpu_atpx_priv.other_handle = dhandle;
532                 return false;
533         }
534         amdgpu_atpx_priv.dhandle = dhandle;
535         amdgpu_atpx_priv.atpx.handle = atpx_handle;
536         return true;
537 }
538
539 /**
540  * amdgpu_atpx_init - verify the ATPX interface
541  *
542  * Verify the ATPX interface (all asics).
543  * Returns 0 on success, error on failure.
544  */
545 static int amdgpu_atpx_init(void)
546 {
547         int r;
548
549         /* set up the ATPX handle */
550         r = amdgpu_atpx_verify_interface(&amdgpu_atpx_priv.atpx);
551         if (r)
552                 return r;
553
554         /* validate the atpx setup */
555         r = amdgpu_atpx_validate(&amdgpu_atpx_priv.atpx);
556         if (r)
557                 return r;
558
559         return 0;
560 }
561
562 /**
563  * amdgpu_atpx_get_client_id - get the client id
564  *
565  * @pdev: pci device
566  *
567  * look up whether we are the integrated or discrete GPU (all asics).
568  * Returns the client id.
569  */
570 static enum vga_switcheroo_client_id amdgpu_atpx_get_client_id(struct pci_dev *pdev)
571 {
572         if (amdgpu_atpx_priv.dhandle == ACPI_HANDLE(&pdev->dev))
573                 return VGA_SWITCHEROO_IGD;
574         else
575                 return VGA_SWITCHEROO_DIS;
576 }
577
578 static const struct vga_switcheroo_handler amdgpu_atpx_handler = {
579         .switchto = amdgpu_atpx_switchto,
580         .power_state = amdgpu_atpx_power_state,
581         .get_client_id = amdgpu_atpx_get_client_id,
582 };
583
584 static const struct amdgpu_px_quirk amdgpu_px_quirk_list[] = {
585         /* HG _PR3 doesn't seem to work on this A+A weston board */
586         { 0x1002, 0x6900, 0x1002, 0x0124, AMDGPU_PX_QUIRK_FORCE_ATPX },
587         { 0x1002, 0x6900, 0x1028, 0x0812, AMDGPU_PX_QUIRK_FORCE_ATPX },
588         { 0x1002, 0x6900, 0x1028, 0x0813, AMDGPU_PX_QUIRK_FORCE_ATPX },
589         { 0x1002, 0x699f, 0x1028, 0x0814, AMDGPU_PX_QUIRK_FORCE_ATPX },
590         { 0x1002, 0x6900, 0x1025, 0x125A, AMDGPU_PX_QUIRK_FORCE_ATPX },
591         { 0x1002, 0x6900, 0x17AA, 0x3806, AMDGPU_PX_QUIRK_FORCE_ATPX },
592         { 0, 0, 0, 0, 0 },
593 };
594
595 static void amdgpu_atpx_get_quirks(struct pci_dev *pdev)
596 {
597         const struct amdgpu_px_quirk *p = amdgpu_px_quirk_list;
598
599         /* Apply PX quirks */
600         while (p && p->chip_device != 0) {
601                 if (pdev->vendor == p->chip_vendor &&
602                     pdev->device == p->chip_device &&
603                     pdev->subsystem_vendor == p->subsys_vendor &&
604                     pdev->subsystem_device == p->subsys_device) {
605                         amdgpu_atpx_priv.quirks |= p->px_quirk_flags;
606                         break;
607                 }
608                 ++p;
609         }
610 }
611
612 /**
613  * amdgpu_atpx_detect - detect whether we have PX
614  *
615  * Check if we have a PX system (all asics).
616  * Returns true if we have a PX system, false if not.
617  */
618 static bool amdgpu_atpx_detect(void)
619 {
620         char acpi_method_name[255] = { 0 };
621         struct acpi_buffer buffer = {sizeof(acpi_method_name), acpi_method_name};
622         struct pci_dev *pdev = NULL;
623         bool has_atpx = false;
624         int vga_count = 0;
625         bool d3_supported = false;
626         struct pci_dev *parent_pdev;
627
628         while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
629                 vga_count++;
630
631                 has_atpx |= amdgpu_atpx_pci_probe_handle(pdev);
632
633                 parent_pdev = pci_upstream_bridge(pdev);
634                 d3_supported |= parent_pdev && parent_pdev->bridge_d3;
635                 amdgpu_atpx_get_quirks(pdev);
636         }
637
638         while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) {
639                 vga_count++;
640
641                 has_atpx |= amdgpu_atpx_pci_probe_handle(pdev);
642
643                 parent_pdev = pci_upstream_bridge(pdev);
644                 d3_supported |= parent_pdev && parent_pdev->bridge_d3;
645                 amdgpu_atpx_get_quirks(pdev);
646         }
647
648         if (has_atpx && vga_count == 2) {
649                 acpi_get_name(amdgpu_atpx_priv.atpx.handle, ACPI_FULL_PATHNAME, &buffer);
650                 pr_info("vga_switcheroo: detected switching method %s handle\n",
651                         acpi_method_name);
652                 amdgpu_atpx_priv.atpx_detected = true;
653                 amdgpu_atpx_priv.bridge_pm_usable = d3_supported;
654                 amdgpu_atpx_init();
655                 return true;
656         }
657         return false;
658 }
659
660 /**
661  * amdgpu_register_atpx_handler - register with vga_switcheroo
662  *
663  * Register the PX callbacks with vga_switcheroo (all asics).
664  */
665 void amdgpu_register_atpx_handler(void)
666 {
667         bool r;
668         enum vga_switcheroo_handler_flags_t handler_flags = 0;
669
670         /* detect if we have any ATPX + 2 VGA in the system */
671         r = amdgpu_atpx_detect();
672         if (!r)
673                 return;
674
675         vga_switcheroo_register_handler(&amdgpu_atpx_handler, handler_flags);
676 }
677
678 /**
679  * amdgpu_unregister_atpx_handler - unregister with vga_switcheroo
680  *
681  * Unregister the PX callbacks with vga_switcheroo (all asics).
682  */
683 void amdgpu_unregister_atpx_handler(void)
684 {
685         vga_switcheroo_unregister_handler();
686 }
This page took 0.077786 seconds and 4 git commands to generate.