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