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 /* make sure required functions are enabled */ 145 /* dGPU power control is required */ 146 if (atpx->functions.power_cntl == false) { 147 printk("ATPX dGPU power cntl not present, forcing\n"); 148 atpx->functions.power_cntl = true; 149 } 150 151 if (atpx->functions.px_params) { 152 union acpi_object *info; 153 struct atpx_px_params output; 154 size_t size; 155 u32 valid_bits; 156 157 info = radeon_atpx_call(atpx->handle, ATPX_FUNCTION_GET_PX_PARAMETERS, NULL); 158 if (!info) 159 return -EIO; 160 161 memset(&output, 0, sizeof(output)); 162 163 size = *(u16 *) info->buffer.pointer; 164 if (size < 10) { 165 printk("ATPX buffer is too small: %zu\n", size); 166 kfree(info); 167 return -EINVAL; 168 } 169 size = min(sizeof(output), size); 170 171 memcpy(&output, info->buffer.pointer, size); 172 173 valid_bits = output.flags & output.valid_flags; 174 /* if separate mux flag is set, mux controls are required */ 175 if (valid_bits & ATPX_SEPARATE_MUX_FOR_I2C) { 176 atpx->functions.i2c_mux_cntl = true; 177 atpx->functions.disp_mux_cntl = true; 178 } 179 /* if any outputs are muxed, mux controls are required */ 180 if (valid_bits & (ATPX_CRT1_RGB_SIGNAL_MUXED | 181 ATPX_TV_SIGNAL_MUXED | 182 ATPX_DFP_SIGNAL_MUXED)) 183 atpx->functions.disp_mux_cntl = true; 184 185 kfree(info); 186 } 187 return 0; 188 } 189 190 /** 191 * radeon_atpx_verify_interface - verify ATPX 192 * 193 * @atpx: radeon atpx struct 194 * 195 * Execute the ATPX_FUNCTION_VERIFY_INTERFACE ATPX function 196 * to initialize ATPX and determine what features are supported 197 * (all asics). 198 * returns 0 on success, error on failure. 199 */ 200 static int radeon_atpx_verify_interface(struct radeon_atpx *atpx) 201 { 202 union acpi_object *info; 203 struct atpx_verify_interface output; 204 size_t size; 205 int err = 0; 206 207 info = radeon_atpx_call(atpx->handle, ATPX_FUNCTION_VERIFY_INTERFACE, NULL); 208 if (!info) 209 return -EIO; 210 211 memset(&output, 0, sizeof(output)); 212 213 size = *(u16 *) info->buffer.pointer; 214 if (size < 8) { 215 printk("ATPX buffer is too small: %zu\n", size); 216 err = -EINVAL; 217 goto out; 218 } 219 size = min(sizeof(output), size); 220 221 memcpy(&output, info->buffer.pointer, size); 222 223 /* TODO: check version? */ 224 printk("ATPX version %u, functions 0x%08x\n", 225 output.version, output.function_bits); 226 227 radeon_atpx_parse_functions(&atpx->functions, output.function_bits); 228 229 out: 230 kfree(info); 231 return err; 232 } 233 234 /** 235 * radeon_atpx_set_discrete_state - power up/down discrete GPU 236 * 237 * @atpx: atpx info struct 238 * @state: discrete GPU state (0 = power down, 1 = power up) 239 * 240 * Execute the ATPX_FUNCTION_POWER_CONTROL ATPX function to 241 * power down/up the discrete GPU (all asics). 242 * Returns 0 on success, error on failure. 243 */ 244 static int radeon_atpx_set_discrete_state(struct radeon_atpx *atpx, u8 state) 245 { 246 struct acpi_buffer params; 247 union acpi_object *info; 248 struct atpx_power_control input; 249 250 if (atpx->functions.power_cntl) { 251 input.size = 3; 252 input.dgpu_state = state; 253 params.length = input.size; 254 params.pointer = &input; 255 info = radeon_atpx_call(atpx->handle, 256 ATPX_FUNCTION_POWER_CONTROL, 257 ¶ms); 258 if (!info) 259 return -EIO; 260 kfree(info); 261 } 262 return 0; 263 } 264 265 /** 266 * radeon_atpx_switch_disp_mux - switch display mux 267 * 268 * @atpx: atpx info struct 269 * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU) 270 * 271 * Execute the ATPX_FUNCTION_DISPLAY_MUX_CONTROL ATPX function to 272 * switch the display mux between the discrete GPU and integrated GPU 273 * (all asics). 274 * Returns 0 on success, error on failure. 275 */ 276 static int radeon_atpx_switch_disp_mux(struct radeon_atpx *atpx, u16 mux_id) 277 { 278 struct acpi_buffer params; 279 union acpi_object *info; 280 struct atpx_mux input; 281 282 if (atpx->functions.disp_mux_cntl) { 283 input.size = 4; 284 input.mux = mux_id; 285 params.length = input.size; 286 params.pointer = &input; 287 info = radeon_atpx_call(atpx->handle, 288 ATPX_FUNCTION_DISPLAY_MUX_CONTROL, 289 ¶ms); 290 if (!info) 291 return -EIO; 292 kfree(info); 293 } 294 return 0; 295 } 296 297 /** 298 * radeon_atpx_switch_i2c_mux - switch i2c/hpd mux 299 * 300 * @atpx: atpx info struct 301 * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU) 302 * 303 * Execute the ATPX_FUNCTION_I2C_MUX_CONTROL ATPX function to 304 * switch the i2c/hpd mux between the discrete GPU and integrated GPU 305 * (all asics). 306 * Returns 0 on success, error on failure. 307 */ 308 static int radeon_atpx_switch_i2c_mux(struct radeon_atpx *atpx, u16 mux_id) 309 { 310 struct acpi_buffer params; 311 union acpi_object *info; 312 struct atpx_mux input; 313 314 if (atpx->functions.i2c_mux_cntl) { 315 input.size = 4; 316 input.mux = mux_id; 317 params.length = input.size; 318 params.pointer = &input; 319 info = radeon_atpx_call(atpx->handle, 320 ATPX_FUNCTION_I2C_MUX_CONTROL, 321 ¶ms); 322 if (!info) 323 return -EIO; 324 kfree(info); 325 } 326 return 0; 327 } 328 329 /** 330 * radeon_atpx_switch_start - notify the sbios of a GPU switch 331 * 332 * @atpx: atpx info struct 333 * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU) 334 * 335 * Execute the ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION ATPX 336 * function to notify the sbios that a switch between the discrete GPU and 337 * integrated GPU has begun (all asics). 338 * Returns 0 on success, error on failure. 339 */ 340 static int radeon_atpx_switch_start(struct radeon_atpx *atpx, u16 mux_id) 341 { 342 struct acpi_buffer params; 343 union acpi_object *info; 344 struct atpx_mux input; 345 346 if (atpx->functions.switch_start) { 347 input.size = 4; 348 input.mux = mux_id; 349 params.length = input.size; 350 params.pointer = &input; 351 info = radeon_atpx_call(atpx->handle, 352 ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION, 353 ¶ms); 354 if (!info) 355 return -EIO; 356 kfree(info); 357 } 358 return 0; 359 } 360 361 /** 362 * radeon_atpx_switch_end - notify the sbios of a GPU switch 363 * 364 * @atpx: atpx info struct 365 * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU) 366 * 367 * Execute the ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION ATPX 368 * function to notify the sbios that a switch between the discrete GPU and 369 * integrated GPU has ended (all asics). 370 * Returns 0 on success, error on failure. 371 */ 372 static int radeon_atpx_switch_end(struct radeon_atpx *atpx, u16 mux_id) 373 { 374 struct acpi_buffer params; 375 union acpi_object *info; 376 struct atpx_mux input; 377 378 if (atpx->functions.switch_end) { 379 input.size = 4; 380 input.mux = mux_id; 381 params.length = input.size; 382 params.pointer = &input; 383 info = radeon_atpx_call(atpx->handle, 384 ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION, 385 ¶ms); 386 if (!info) 387 return -EIO; 388 kfree(info); 389 } 390 return 0; 391 } 392 393 /** 394 * radeon_atpx_switchto - switch to the requested GPU 395 * 396 * @id: GPU to switch to 397 * 398 * Execute the necessary ATPX functions to switch between the discrete GPU and 399 * integrated GPU (all asics). 400 * Returns 0 on success, error on failure. 401 */ 402 static int radeon_atpx_switchto(enum vga_switcheroo_client_id id) 403 { 404 u16 gpu_id; 405 406 if (id == VGA_SWITCHEROO_IGD) 407 gpu_id = ATPX_INTEGRATED_GPU; 408 else 409 gpu_id = ATPX_DISCRETE_GPU; 410 411 radeon_atpx_switch_start(&radeon_atpx_priv.atpx, gpu_id); 412 radeon_atpx_switch_disp_mux(&radeon_atpx_priv.atpx, gpu_id); 413 radeon_atpx_switch_i2c_mux(&radeon_atpx_priv.atpx, gpu_id); 414 radeon_atpx_switch_end(&radeon_atpx_priv.atpx, gpu_id); 415 416 return 0; 417 } 418 419 /** 420 * radeon_atpx_power_state - power down/up the requested GPU 421 * 422 * @id: GPU to power down/up 423 * @state: requested power state (0 = off, 1 = on) 424 * 425 * Execute the necessary ATPX function to power down/up the discrete GPU 426 * (all asics). 427 * Returns 0 on success, error on failure. 428 */ 429 static int radeon_atpx_power_state(enum vga_switcheroo_client_id id, 430 enum vga_switcheroo_state state) 431 { 432 /* on w500 ACPI can't change intel gpu state */ 433 if (id == VGA_SWITCHEROO_IGD) 434 return 0; 435 436 radeon_atpx_set_discrete_state(&radeon_atpx_priv.atpx, state); 437 return 0; 438 } 439 440 /** 441 * radeon_atpx_pci_probe_handle - look up the ATPX handle 442 * 443 * @pdev: pci device 444 * 445 * Look up the ATPX handles (all asics). 446 * Returns true if the handles are found, false if not. 447 */ 448 static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev) 449 { 450 acpi_handle dhandle, atpx_handle; 451 acpi_status status; 452 453 dhandle = ACPI_HANDLE(&pdev->dev); 454 if (!dhandle) 455 return false; 456 457 status = acpi_get_handle(dhandle, "ATPX", &atpx_handle); 458 if (ACPI_FAILURE(status)) 459 return false; 460 461 radeon_atpx_priv.dhandle = dhandle; 462 radeon_atpx_priv.atpx.handle = atpx_handle; 463 return true; 464 } 465 466 /** 467 * radeon_atpx_init - verify the ATPX interface 468 * 469 * Verify the ATPX interface (all asics). 470 * Returns 0 on success, error on failure. 471 */ 472 static int radeon_atpx_init(void) 473 { 474 int r; 475 476 /* set up the ATPX handle */ 477 r = radeon_atpx_verify_interface(&radeon_atpx_priv.atpx); 478 if (r) 479 return r; 480 481 /* validate the atpx setup */ 482 r = radeon_atpx_validate(&radeon_atpx_priv.atpx); 483 if (r) 484 return r; 485 486 return 0; 487 } 488 489 /** 490 * radeon_atpx_get_client_id - get the client id 491 * 492 * @pdev: pci device 493 * 494 * look up whether we are the integrated or discrete GPU (all asics). 495 * Returns the client id. 496 */ 497 static int radeon_atpx_get_client_id(struct pci_dev *pdev) 498 { 499 if (radeon_atpx_priv.dhandle == ACPI_HANDLE(&pdev->dev)) 500 return VGA_SWITCHEROO_IGD; 501 else 502 return VGA_SWITCHEROO_DIS; 503 } 504 505 static const struct vga_switcheroo_handler radeon_atpx_handler = { 506 .switchto = radeon_atpx_switchto, 507 .power_state = radeon_atpx_power_state, 508 .init = radeon_atpx_init, 509 .get_client_id = radeon_atpx_get_client_id, 510 }; 511 512 /** 513 * radeon_atpx_detect - detect whether we have PX 514 * 515 * Check if we have a PX system (all asics). 516 * Returns true if we have a PX system, false if not. 517 */ 518 static bool radeon_atpx_detect(void) 519 { 520 char acpi_method_name[255] = { 0 }; 521 struct acpi_buffer buffer = {sizeof(acpi_method_name), acpi_method_name}; 522 struct pci_dev *pdev = NULL; 523 bool has_atpx = false; 524 int vga_count = 0; 525 526 while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) { 527 vga_count++; 528 529 has_atpx |= (radeon_atpx_pci_probe_handle(pdev) == true); 530 } 531 532 /* some newer PX laptops mark the dGPU as a non-VGA display device */ 533 while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) { 534 vga_count++; 535 536 has_atpx |= (radeon_atpx_pci_probe_handle(pdev) == true); 537 } 538 539 if (has_atpx && vga_count == 2) { 540 acpi_get_name(radeon_atpx_priv.atpx.handle, ACPI_FULL_PATHNAME, &buffer); 541 printk(KERN_INFO "vga_switcheroo: detected switching method %s handle\n", 542 acpi_method_name); 543 radeon_atpx_priv.atpx_detected = true; 544 return true; 545 } 546 return false; 547 } 548 549 /** 550 * radeon_register_atpx_handler - register with vga_switcheroo 551 * 552 * Register the PX callbacks with vga_switcheroo (all asics). 553 */ 554 void radeon_register_atpx_handler(void) 555 { 556 bool r; 557 enum vga_switcheroo_handler_flags_t handler_flags = 0; 558 559 /* detect if we have any ATPX + 2 VGA in the system */ 560 r = radeon_atpx_detect(); 561 if (!r) 562 return; 563 564 vga_switcheroo_register_handler(&radeon_atpx_handler, handler_flags); 565 } 566 567 /** 568 * radeon_unregister_atpx_handler - unregister with vga_switcheroo 569 * 570 * Unregister the PX callbacks with vga_switcheroo (all asics). 571 */ 572 void radeon_unregister_atpx_handler(void) 573 { 574 vga_switcheroo_unregister_handler(); 575 } 576