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