root/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. amdgpu_has_atpx
  2. amdgpu_has_atpx_dgpu_power_cntl
  3. amdgpu_is_atpx_hybrid
  4. amdgpu_atpx_dgpu_req_power_for_displays
  5. amdgpu_atpx_get_dhandle
  6. amdgpu_atpx_call
  7. amdgpu_atpx_parse_functions
  8. amdgpu_atpx_validate
  9. amdgpu_atpx_verify_interface
  10. amdgpu_atpx_set_discrete_state
  11. amdgpu_atpx_switch_disp_mux
  12. amdgpu_atpx_switch_i2c_mux
  13. amdgpu_atpx_switch_start
  14. amdgpu_atpx_switch_end
  15. amdgpu_atpx_switchto
  16. amdgpu_atpx_power_state
  17. amdgpu_atpx_pci_probe_handle
  18. amdgpu_atpx_init
  19. amdgpu_atpx_get_client_id
  20. amdgpu_atpx_get_quirks
  21. amdgpu_atpx_detect
  22. amdgpu_register_atpx_handler
  23. amdgpu_unregister_atpx_handler

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

/* [<][>][^][v][top][bottom][index][help] */