Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2010 Red Hat Inc.
0004  * Author : Dave Airlie <airlied@redhat.com>
0005  *
0006  * ATPX support for both Intel/ATI
0007  */
0008 #include <linux/vga_switcheroo.h>
0009 #include <linux/slab.h>
0010 #include <linux/acpi.h>
0011 #include <linux/pci.h>
0012 #include <linux/delay.h>
0013 
0014 #include "amdgpu.h"
0015 #include "amd_acpi.h"
0016 
0017 #define AMDGPU_PX_QUIRK_FORCE_ATPX  (1 << 0)
0018 
0019 struct amdgpu_px_quirk {
0020     u32 chip_vendor;
0021     u32 chip_device;
0022     u32 subsys_vendor;
0023     u32 subsys_device;
0024     u32 px_quirk_flags;
0025 };
0026 
0027 struct amdgpu_atpx_functions {
0028     bool px_params;
0029     bool power_cntl;
0030     bool disp_mux_cntl;
0031     bool i2c_mux_cntl;
0032     bool switch_start;
0033     bool switch_end;
0034     bool disp_connectors_mapping;
0035     bool disp_detection_ports;
0036 };
0037 
0038 struct amdgpu_atpx {
0039     acpi_handle handle;
0040     struct amdgpu_atpx_functions functions;
0041     bool is_hybrid;
0042     bool dgpu_req_power_for_displays;
0043 };
0044 
0045 static struct amdgpu_atpx_priv {
0046     bool atpx_detected;
0047     bool bridge_pm_usable;
0048     unsigned int quirks;
0049     /* handle for device - and atpx */
0050     acpi_handle dhandle;
0051     acpi_handle other_handle;
0052     struct amdgpu_atpx atpx;
0053 } amdgpu_atpx_priv;
0054 
0055 struct atpx_verify_interface {
0056     u16 size;       /* structure size in bytes (includes size field) */
0057     u16 version;        /* version */
0058     u32 function_bits;  /* supported functions bit vector */
0059 } __packed;
0060 
0061 struct atpx_px_params {
0062     u16 size;       /* structure size in bytes (includes size field) */
0063     u32 valid_flags;    /* which flags are valid */
0064     u32 flags;      /* flags */
0065 } __packed;
0066 
0067 struct atpx_power_control {
0068     u16 size;
0069     u8 dgpu_state;
0070 } __packed;
0071 
0072 struct atpx_mux {
0073     u16 size;
0074     u16 mux;
0075 } __packed;
0076 
0077 bool amdgpu_has_atpx(void) {
0078     return amdgpu_atpx_priv.atpx_detected;
0079 }
0080 
0081 bool amdgpu_has_atpx_dgpu_power_cntl(void) {
0082     return amdgpu_atpx_priv.atpx.functions.power_cntl;
0083 }
0084 
0085 bool amdgpu_is_atpx_hybrid(void) {
0086     return amdgpu_atpx_priv.atpx.is_hybrid;
0087 }
0088 
0089 bool amdgpu_atpx_dgpu_req_power_for_displays(void) {
0090     return amdgpu_atpx_priv.atpx.dgpu_req_power_for_displays;
0091 }
0092 
0093 #if defined(CONFIG_ACPI)
0094 void *amdgpu_atpx_get_dhandle(void) {
0095     return amdgpu_atpx_priv.dhandle;
0096 }
0097 #endif
0098 
0099 /**
0100  * amdgpu_atpx_call - call an ATPX method
0101  *
0102  * @handle: acpi handle
0103  * @function: the ATPX function to execute
0104  * @params: ATPX function params
0105  *
0106  * Executes the requested ATPX function (all asics).
0107  * Returns a pointer to the acpi output buffer.
0108  */
0109 static union acpi_object *amdgpu_atpx_call(acpi_handle handle, int function,
0110                        struct acpi_buffer *params)
0111 {
0112     acpi_status status;
0113     union acpi_object atpx_arg_elements[2];
0114     struct acpi_object_list atpx_arg;
0115     struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
0116 
0117     atpx_arg.count = 2;
0118     atpx_arg.pointer = &atpx_arg_elements[0];
0119 
0120     atpx_arg_elements[0].type = ACPI_TYPE_INTEGER;
0121     atpx_arg_elements[0].integer.value = function;
0122 
0123     if (params) {
0124         atpx_arg_elements[1].type = ACPI_TYPE_BUFFER;
0125         atpx_arg_elements[1].buffer.length = params->length;
0126         atpx_arg_elements[1].buffer.pointer = params->pointer;
0127     } else {
0128         /* We need a second fake parameter */
0129         atpx_arg_elements[1].type = ACPI_TYPE_INTEGER;
0130         atpx_arg_elements[1].integer.value = 0;
0131     }
0132 
0133     status = acpi_evaluate_object(handle, NULL, &atpx_arg, &buffer);
0134 
0135     /* Fail only if calling the method fails and ATPX is supported */
0136     if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
0137         printk("failed to evaluate ATPX got %s\n",
0138                acpi_format_exception(status));
0139         kfree(buffer.pointer);
0140         return NULL;
0141     }
0142 
0143     return buffer.pointer;
0144 }
0145 
0146 /**
0147  * amdgpu_atpx_parse_functions - parse supported functions
0148  *
0149  * @f: supported functions struct
0150  * @mask: supported functions mask from ATPX
0151  *
0152  * Use the supported functions mask from ATPX function
0153  * ATPX_FUNCTION_VERIFY_INTERFACE to determine what functions
0154  * are supported (all asics).
0155  */
0156 static void amdgpu_atpx_parse_functions(struct amdgpu_atpx_functions *f, u32 mask)
0157 {
0158     f->px_params = mask & ATPX_GET_PX_PARAMETERS_SUPPORTED;
0159     f->power_cntl = mask & ATPX_POWER_CONTROL_SUPPORTED;
0160     f->disp_mux_cntl = mask & ATPX_DISPLAY_MUX_CONTROL_SUPPORTED;
0161     f->i2c_mux_cntl = mask & ATPX_I2C_MUX_CONTROL_SUPPORTED;
0162     f->switch_start = mask & ATPX_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION_SUPPORTED;
0163     f->switch_end = mask & ATPX_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION_SUPPORTED;
0164     f->disp_connectors_mapping = mask & ATPX_GET_DISPLAY_CONNECTORS_MAPPING_SUPPORTED;
0165     f->disp_detection_ports = mask & ATPX_GET_DISPLAY_DETECTION_PORTS_SUPPORTED;
0166 }
0167 
0168 /**
0169  * amdgpu_atpx_validate - validate ATPX functions
0170  *
0171  * @atpx: amdgpu atpx struct
0172  *
0173  * Validate that required functions are enabled (all asics).
0174  * returns 0 on success, error on failure.
0175  */
0176 static int amdgpu_atpx_validate(struct amdgpu_atpx *atpx)
0177 {
0178     u32 valid_bits = 0;
0179 
0180     if (atpx->functions.px_params) {
0181         union acpi_object *info;
0182         struct atpx_px_params output;
0183         size_t size;
0184 
0185         info = amdgpu_atpx_call(atpx->handle, ATPX_FUNCTION_GET_PX_PARAMETERS, NULL);
0186         if (!info)
0187             return -EIO;
0188 
0189         memset(&output, 0, sizeof(output));
0190 
0191         size = *(u16 *) info->buffer.pointer;
0192         if (size < 10) {
0193             printk("ATPX buffer is too small: %zu\n", size);
0194             kfree(info);
0195             return -EINVAL;
0196         }
0197         size = min(sizeof(output), size);
0198 
0199         memcpy(&output, info->buffer.pointer, size);
0200 
0201         valid_bits = output.flags & output.valid_flags;
0202 
0203         kfree(info);
0204     }
0205 
0206     /* if separate mux flag is set, mux controls are required */
0207     if (valid_bits & ATPX_SEPARATE_MUX_FOR_I2C) {
0208         atpx->functions.i2c_mux_cntl = true;
0209         atpx->functions.disp_mux_cntl = true;
0210     }
0211     /* if any outputs are muxed, mux controls are required */
0212     if (valid_bits & (ATPX_CRT1_RGB_SIGNAL_MUXED |
0213               ATPX_TV_SIGNAL_MUXED |
0214               ATPX_DFP_SIGNAL_MUXED))
0215         atpx->functions.disp_mux_cntl = true;
0216 
0217 
0218     /* some bioses set these bits rather than flagging power_cntl as supported */
0219     if (valid_bits & (ATPX_DYNAMIC_PX_SUPPORTED |
0220               ATPX_DYNAMIC_DGPU_POWER_OFF_SUPPORTED))
0221         atpx->functions.power_cntl = true;
0222 
0223     atpx->is_hybrid = false;
0224     if (valid_bits & ATPX_MS_HYBRID_GFX_SUPPORTED) {
0225         if (amdgpu_atpx_priv.quirks & AMDGPU_PX_QUIRK_FORCE_ATPX) {
0226             printk("ATPX Hybrid Graphics, forcing to ATPX\n");
0227             atpx->functions.power_cntl = true;
0228             atpx->is_hybrid = false;
0229         } else {
0230             printk("ATPX Hybrid Graphics\n");
0231             /*
0232              * Disable legacy PM methods only when pcie port PM is usable,
0233              * otherwise the device might fail to power off or power on.
0234              */
0235             atpx->functions.power_cntl = !amdgpu_atpx_priv.bridge_pm_usable;
0236             atpx->is_hybrid = true;
0237         }
0238     }
0239 
0240     atpx->dgpu_req_power_for_displays = false;
0241     if (valid_bits & ATPX_DGPU_REQ_POWER_FOR_DISPLAYS)
0242         atpx->dgpu_req_power_for_displays = true;
0243 
0244     return 0;
0245 }
0246 
0247 /**
0248  * amdgpu_atpx_verify_interface - verify ATPX
0249  *
0250  * @atpx: amdgpu atpx struct
0251  *
0252  * Execute the ATPX_FUNCTION_VERIFY_INTERFACE ATPX function
0253  * to initialize ATPX and determine what features are supported
0254  * (all asics).
0255  * returns 0 on success, error on failure.
0256  */
0257 static int amdgpu_atpx_verify_interface(struct amdgpu_atpx *atpx)
0258 {
0259     union acpi_object *info;
0260     struct atpx_verify_interface output;
0261     size_t size;
0262     int err = 0;
0263 
0264     info = amdgpu_atpx_call(atpx->handle, ATPX_FUNCTION_VERIFY_INTERFACE, NULL);
0265     if (!info)
0266         return -EIO;
0267 
0268     memset(&output, 0, sizeof(output));
0269 
0270     size = *(u16 *) info->buffer.pointer;
0271     if (size < 8) {
0272         printk("ATPX buffer is too small: %zu\n", size);
0273         err = -EINVAL;
0274         goto out;
0275     }
0276     size = min(sizeof(output), size);
0277 
0278     memcpy(&output, info->buffer.pointer, size);
0279 
0280     /* TODO: check version? */
0281     printk("ATPX version %u, functions 0x%08x\n",
0282            output.version, output.function_bits);
0283 
0284     amdgpu_atpx_parse_functions(&atpx->functions, output.function_bits);
0285 
0286 out:
0287     kfree(info);
0288     return err;
0289 }
0290 
0291 /**
0292  * amdgpu_atpx_set_discrete_state - power up/down discrete GPU
0293  *
0294  * @atpx: atpx info struct
0295  * @state: discrete GPU state (0 = power down, 1 = power up)
0296  *
0297  * Execute the ATPX_FUNCTION_POWER_CONTROL ATPX function to
0298  * power down/up the discrete GPU (all asics).
0299  * Returns 0 on success, error on failure.
0300  */
0301 static int amdgpu_atpx_set_discrete_state(struct amdgpu_atpx *atpx, u8 state)
0302 {
0303     struct acpi_buffer params;
0304     union acpi_object *info;
0305     struct atpx_power_control input;
0306 
0307     if (atpx->functions.power_cntl) {
0308         input.size = 3;
0309         input.dgpu_state = state;
0310         params.length = input.size;
0311         params.pointer = &input;
0312         info = amdgpu_atpx_call(atpx->handle,
0313                     ATPX_FUNCTION_POWER_CONTROL,
0314                     &params);
0315         if (!info)
0316             return -EIO;
0317         kfree(info);
0318 
0319         /* 200ms delay is required after off */
0320         if (state == 0)
0321             msleep(200);
0322     }
0323     return 0;
0324 }
0325 
0326 /**
0327  * amdgpu_atpx_switch_disp_mux - switch display mux
0328  *
0329  * @atpx: atpx info struct
0330  * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU)
0331  *
0332  * Execute the ATPX_FUNCTION_DISPLAY_MUX_CONTROL ATPX function to
0333  * switch the display mux between the discrete GPU and integrated GPU
0334  * (all asics).
0335  * Returns 0 on success, error on failure.
0336  */
0337 static int amdgpu_atpx_switch_disp_mux(struct amdgpu_atpx *atpx, u16 mux_id)
0338 {
0339     struct acpi_buffer params;
0340     union acpi_object *info;
0341     struct atpx_mux input;
0342 
0343     if (atpx->functions.disp_mux_cntl) {
0344         input.size = 4;
0345         input.mux = mux_id;
0346         params.length = input.size;
0347         params.pointer = &input;
0348         info = amdgpu_atpx_call(atpx->handle,
0349                     ATPX_FUNCTION_DISPLAY_MUX_CONTROL,
0350                     &params);
0351         if (!info)
0352             return -EIO;
0353         kfree(info);
0354     }
0355     return 0;
0356 }
0357 
0358 /**
0359  * amdgpu_atpx_switch_i2c_mux - switch i2c/hpd mux
0360  *
0361  * @atpx: atpx info struct
0362  * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU)
0363  *
0364  * Execute the ATPX_FUNCTION_I2C_MUX_CONTROL ATPX function to
0365  * switch the i2c/hpd mux between the discrete GPU and integrated GPU
0366  * (all asics).
0367  * Returns 0 on success, error on failure.
0368  */
0369 static int amdgpu_atpx_switch_i2c_mux(struct amdgpu_atpx *atpx, u16 mux_id)
0370 {
0371     struct acpi_buffer params;
0372     union acpi_object *info;
0373     struct atpx_mux input;
0374 
0375     if (atpx->functions.i2c_mux_cntl) {
0376         input.size = 4;
0377         input.mux = mux_id;
0378         params.length = input.size;
0379         params.pointer = &input;
0380         info = amdgpu_atpx_call(atpx->handle,
0381                     ATPX_FUNCTION_I2C_MUX_CONTROL,
0382                     &params);
0383         if (!info)
0384             return -EIO;
0385         kfree(info);
0386     }
0387     return 0;
0388 }
0389 
0390 /**
0391  * amdgpu_atpx_switch_start - notify the sbios of a GPU switch
0392  *
0393  * @atpx: atpx info struct
0394  * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU)
0395  *
0396  * Execute the ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION ATPX
0397  * function to notify the sbios that a switch between the discrete GPU and
0398  * integrated GPU has begun (all asics).
0399  * Returns 0 on success, error on failure.
0400  */
0401 static int amdgpu_atpx_switch_start(struct amdgpu_atpx *atpx, u16 mux_id)
0402 {
0403     struct acpi_buffer params;
0404     union acpi_object *info;
0405     struct atpx_mux input;
0406 
0407     if (atpx->functions.switch_start) {
0408         input.size = 4;
0409         input.mux = mux_id;
0410         params.length = input.size;
0411         params.pointer = &input;
0412         info = amdgpu_atpx_call(atpx->handle,
0413                     ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION,
0414                     &params);
0415         if (!info)
0416             return -EIO;
0417         kfree(info);
0418     }
0419     return 0;
0420 }
0421 
0422 /**
0423  * amdgpu_atpx_switch_end - notify the sbios of a GPU switch
0424  *
0425  * @atpx: atpx info struct
0426  * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU)
0427  *
0428  * Execute the ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION ATPX
0429  * function to notify the sbios that a switch between the discrete GPU and
0430  * integrated GPU has ended (all asics).
0431  * Returns 0 on success, error on failure.
0432  */
0433 static int amdgpu_atpx_switch_end(struct amdgpu_atpx *atpx, u16 mux_id)
0434 {
0435     struct acpi_buffer params;
0436     union acpi_object *info;
0437     struct atpx_mux input;
0438 
0439     if (atpx->functions.switch_end) {
0440         input.size = 4;
0441         input.mux = mux_id;
0442         params.length = input.size;
0443         params.pointer = &input;
0444         info = amdgpu_atpx_call(atpx->handle,
0445                     ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION,
0446                     &params);
0447         if (!info)
0448             return -EIO;
0449         kfree(info);
0450     }
0451     return 0;
0452 }
0453 
0454 /**
0455  * amdgpu_atpx_switchto - switch to the requested GPU
0456  *
0457  * @id: GPU to switch to
0458  *
0459  * Execute the necessary ATPX functions to switch between the discrete GPU and
0460  * integrated GPU (all asics).
0461  * Returns 0 on success, error on failure.
0462  */
0463 static int amdgpu_atpx_switchto(enum vga_switcheroo_client_id id)
0464 {
0465     u16 gpu_id;
0466 
0467     if (id == VGA_SWITCHEROO_IGD)
0468         gpu_id = ATPX_INTEGRATED_GPU;
0469     else
0470         gpu_id = ATPX_DISCRETE_GPU;
0471 
0472     amdgpu_atpx_switch_start(&amdgpu_atpx_priv.atpx, gpu_id);
0473     amdgpu_atpx_switch_disp_mux(&amdgpu_atpx_priv.atpx, gpu_id);
0474     amdgpu_atpx_switch_i2c_mux(&amdgpu_atpx_priv.atpx, gpu_id);
0475     amdgpu_atpx_switch_end(&amdgpu_atpx_priv.atpx, gpu_id);
0476 
0477     return 0;
0478 }
0479 
0480 /**
0481  * amdgpu_atpx_power_state - power down/up the requested GPU
0482  *
0483  * @id: GPU to power down/up
0484  * @state: requested power state (0 = off, 1 = on)
0485  *
0486  * Execute the necessary ATPX function to power down/up the discrete GPU
0487  * (all asics).
0488  * Returns 0 on success, error on failure.
0489  */
0490 static int amdgpu_atpx_power_state(enum vga_switcheroo_client_id id,
0491                    enum vga_switcheroo_state state)
0492 {
0493     /* on w500 ACPI can't change intel gpu state */
0494     if (id == VGA_SWITCHEROO_IGD)
0495         return 0;
0496 
0497     amdgpu_atpx_set_discrete_state(&amdgpu_atpx_priv.atpx, state);
0498     return 0;
0499 }
0500 
0501 /**
0502  * amdgpu_atpx_pci_probe_handle - look up the ATPX handle
0503  *
0504  * @pdev: pci device
0505  *
0506  * Look up the ATPX handles (all asics).
0507  * Returns true if the handles are found, false if not.
0508  */
0509 static bool amdgpu_atpx_pci_probe_handle(struct pci_dev *pdev)
0510 {
0511     acpi_handle dhandle, atpx_handle;
0512     acpi_status status;
0513 
0514     dhandle = ACPI_HANDLE(&pdev->dev);
0515     if (!dhandle)
0516         return false;
0517 
0518     status = acpi_get_handle(dhandle, "ATPX", &atpx_handle);
0519     if (ACPI_FAILURE(status)) {
0520         amdgpu_atpx_priv.other_handle = dhandle;
0521         return false;
0522     }
0523     amdgpu_atpx_priv.dhandle = dhandle;
0524     amdgpu_atpx_priv.atpx.handle = atpx_handle;
0525     return true;
0526 }
0527 
0528 /**
0529  * amdgpu_atpx_init - verify the ATPX interface
0530  *
0531  * Verify the ATPX interface (all asics).
0532  * Returns 0 on success, error on failure.
0533  */
0534 static int amdgpu_atpx_init(void)
0535 {
0536     int r;
0537 
0538     /* set up the ATPX handle */
0539     r = amdgpu_atpx_verify_interface(&amdgpu_atpx_priv.atpx);
0540     if (r)
0541         return r;
0542 
0543     /* validate the atpx setup */
0544     r = amdgpu_atpx_validate(&amdgpu_atpx_priv.atpx);
0545     if (r)
0546         return r;
0547 
0548     return 0;
0549 }
0550 
0551 /**
0552  * amdgpu_atpx_get_client_id - get the client id
0553  *
0554  * @pdev: pci device
0555  *
0556  * look up whether we are the integrated or discrete GPU (all asics).
0557  * Returns the client id.
0558  */
0559 static enum vga_switcheroo_client_id amdgpu_atpx_get_client_id(struct pci_dev *pdev)
0560 {
0561     if (amdgpu_atpx_priv.dhandle == ACPI_HANDLE(&pdev->dev))
0562         return VGA_SWITCHEROO_IGD;
0563     else
0564         return VGA_SWITCHEROO_DIS;
0565 }
0566 
0567 static const struct vga_switcheroo_handler amdgpu_atpx_handler = {
0568     .switchto = amdgpu_atpx_switchto,
0569     .power_state = amdgpu_atpx_power_state,
0570     .get_client_id = amdgpu_atpx_get_client_id,
0571 };
0572 
0573 static const struct amdgpu_px_quirk amdgpu_px_quirk_list[] = {
0574     /* HG _PR3 doesn't seem to work on this A+A weston board */
0575     { 0x1002, 0x6900, 0x1002, 0x0124, AMDGPU_PX_QUIRK_FORCE_ATPX },
0576     { 0x1002, 0x6900, 0x1028, 0x0812, AMDGPU_PX_QUIRK_FORCE_ATPX },
0577     { 0x1002, 0x6900, 0x1028, 0x0813, AMDGPU_PX_QUIRK_FORCE_ATPX },
0578     { 0x1002, 0x699f, 0x1028, 0x0814, AMDGPU_PX_QUIRK_FORCE_ATPX },
0579     { 0x1002, 0x6900, 0x1025, 0x125A, AMDGPU_PX_QUIRK_FORCE_ATPX },
0580     { 0x1002, 0x6900, 0x17AA, 0x3806, AMDGPU_PX_QUIRK_FORCE_ATPX },
0581     { 0, 0, 0, 0, 0 },
0582 };
0583 
0584 static void amdgpu_atpx_get_quirks(struct pci_dev *pdev)
0585 {
0586     const struct amdgpu_px_quirk *p = amdgpu_px_quirk_list;
0587 
0588     /* Apply PX quirks */
0589     while (p && p->chip_device != 0) {
0590         if (pdev->vendor == p->chip_vendor &&
0591             pdev->device == p->chip_device &&
0592             pdev->subsystem_vendor == p->subsys_vendor &&
0593             pdev->subsystem_device == p->subsys_device) {
0594             amdgpu_atpx_priv.quirks |= p->px_quirk_flags;
0595             break;
0596         }
0597         ++p;
0598     }
0599 }
0600 
0601 /**
0602  * amdgpu_atpx_detect - detect whether we have PX
0603  *
0604  * Check if we have a PX system (all asics).
0605  * Returns true if we have a PX system, false if not.
0606  */
0607 static bool amdgpu_atpx_detect(void)
0608 {
0609     char acpi_method_name[255] = { 0 };
0610     struct acpi_buffer buffer = {sizeof(acpi_method_name), acpi_method_name};
0611     struct pci_dev *pdev = NULL;
0612     bool has_atpx = false;
0613     int vga_count = 0;
0614     bool d3_supported = false;
0615     struct pci_dev *parent_pdev;
0616 
0617     while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
0618         vga_count++;
0619 
0620         has_atpx |= amdgpu_atpx_pci_probe_handle(pdev);
0621 
0622         parent_pdev = pci_upstream_bridge(pdev);
0623         d3_supported |= parent_pdev && parent_pdev->bridge_d3;
0624         amdgpu_atpx_get_quirks(pdev);
0625     }
0626 
0627     while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) {
0628         vga_count++;
0629 
0630         has_atpx |= amdgpu_atpx_pci_probe_handle(pdev);
0631 
0632         parent_pdev = pci_upstream_bridge(pdev);
0633         d3_supported |= parent_pdev && parent_pdev->bridge_d3;
0634         amdgpu_atpx_get_quirks(pdev);
0635     }
0636 
0637     if (has_atpx && vga_count == 2) {
0638         acpi_get_name(amdgpu_atpx_priv.atpx.handle, ACPI_FULL_PATHNAME, &buffer);
0639         pr_info("vga_switcheroo: detected switching method %s handle\n",
0640             acpi_method_name);
0641         amdgpu_atpx_priv.atpx_detected = true;
0642         amdgpu_atpx_priv.bridge_pm_usable = d3_supported;
0643         amdgpu_atpx_init();
0644         return true;
0645     }
0646     return false;
0647 }
0648 
0649 /**
0650  * amdgpu_register_atpx_handler - register with vga_switcheroo
0651  *
0652  * Register the PX callbacks with vga_switcheroo (all asics).
0653  */
0654 void amdgpu_register_atpx_handler(void)
0655 {
0656     bool r;
0657     enum vga_switcheroo_handler_flags_t handler_flags = 0;
0658 
0659     /* detect if we have any ATPX + 2 VGA in the system */
0660     r = amdgpu_atpx_detect();
0661     if (!r)
0662         return;
0663 
0664     vga_switcheroo_register_handler(&amdgpu_atpx_handler, handler_flags);
0665 }
0666 
0667 /**
0668  * amdgpu_unregister_atpx_handler - unregister with vga_switcheroo
0669  *
0670  * Unregister the PX callbacks with vga_switcheroo (all asics).
0671  */
0672 void amdgpu_unregister_atpx_handler(void)
0673 {
0674     vga_switcheroo_unregister_handler();
0675 }