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 <acpi/acpi.h> 12 #include <acpi/acpi_bus.h> 13 #include <linux/pci.h> 14 15 #include "radeon_acpi.h" 16 17 struct radeon_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 radeon_atpx { 29 acpi_handle handle; 30 struct radeon_atpx_functions functions; 31 }; 32 33 static struct radeon_atpx_priv { 34 bool atpx_detected; 35 /* handle for device - and atpx */ 36 acpi_handle dhandle; 37 struct radeon_atpx atpx; 38 } radeon_atpx_priv; 39 40 struct atpx_verify_interface { 41 u16 size; /* structure size in bytes (includes size field) */ 42 u16 version; /* version */ 43 u32 function_bits; /* supported functions bit vector */ 44 } __packed; 45 46 struct atpx_power_control { 47 u16 size; 48 u8 dgpu_state; 49 } __packed; 50 51 struct atpx_mux { 52 u16 size; 53 u16 mux; 54 } __packed; 55 56 /** 57 * radeon_atpx_call - call an ATPX method 58 * 59 * @handle: acpi handle 60 * @function: the ATPX function to execute 61 * @params: ATPX function params 62 * 63 * Executes the requested ATPX function (all asics). 64 * Returns a pointer to the acpi output buffer. 65 */ 66 static union acpi_object *radeon_atpx_call(acpi_handle handle, int function, 67 struct acpi_buffer *params) 68 { 69 acpi_status status; 70 union acpi_object atpx_arg_elements[2]; 71 struct acpi_object_list atpx_arg; 72 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 73 74 atpx_arg.count = 2; 75 atpx_arg.pointer = &atpx_arg_elements[0]; 76 77 atpx_arg_elements[0].type = ACPI_TYPE_INTEGER; 78 atpx_arg_elements[0].integer.value = function; 79 80 if (params) { 81 atpx_arg_elements[1].type = ACPI_TYPE_BUFFER; 82 atpx_arg_elements[1].buffer.length = params->length; 83 atpx_arg_elements[1].buffer.pointer = params->pointer; 84 } else { 85 /* We need a second fake parameter */ 86 atpx_arg_elements[1].type = ACPI_TYPE_INTEGER; 87 atpx_arg_elements[1].integer.value = 0; 88 } 89 90 status = acpi_evaluate_object(handle, NULL, &atpx_arg, &buffer); 91 92 /* Fail only if calling the method fails and ATPX is supported */ 93 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 94 printk("failed to evaluate ATPX got %s\n", 95 acpi_format_exception(status)); 96 kfree(buffer.pointer); 97 return NULL; 98 } 99 100 return buffer.pointer; 101 } 102 103 /** 104 * radeon_atpx_parse_functions - parse supported functions 105 * 106 * @f: supported functions struct 107 * @mask: supported functions mask from ATPX 108 * 109 * Use the supported functions mask from ATPX function 110 * ATPX_FUNCTION_VERIFY_INTERFACE to determine what functions 111 * are supported (all asics). 112 */ 113 static void radeon_atpx_parse_functions(struct radeon_atpx_functions *f, u32 mask) 114 { 115 f->px_params = mask & ATPX_GET_PX_PARAMETERS_SUPPORTED; 116 f->power_cntl = mask & ATPX_POWER_CONTROL_SUPPORTED; 117 f->disp_mux_cntl = mask & ATPX_DISPLAY_MUX_CONTROL_SUPPORTED; 118 f->i2c_mux_cntl = mask & ATPX_I2C_MUX_CONTROL_SUPPORTED; 119 f->switch_start = mask & ATPX_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION_SUPPORTED; 120 f->switch_end = mask & ATPX_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION_SUPPORTED; 121 f->disp_connectors_mapping = mask & ATPX_GET_DISPLAY_CONNECTORS_MAPPING_SUPPORTED; 122 f->disp_detetion_ports = mask & ATPX_GET_DISPLAY_DETECTION_PORTS_SUPPORTED; 123 } 124 125 /** 126 * radeon_atpx_verify_interface - verify ATPX 127 * 128 * @handle: acpi handle 129 * @atpx: radeon atpx struct 130 * 131 * Execute the ATPX_FUNCTION_VERIFY_INTERFACE ATPX function 132 * to initialize ATPX and determine what features are supported 133 * (all asics). 134 * returns 0 on success, error on failure. 135 */ 136 static int radeon_atpx_verify_interface(struct radeon_atpx *atpx) 137 { 138 union acpi_object *info; 139 struct atpx_verify_interface output; 140 size_t size; 141 int err = 0; 142 143 info = radeon_atpx_call(atpx->handle, ATPX_FUNCTION_VERIFY_INTERFACE, NULL); 144 if (!info) 145 return -EIO; 146 147 memset(&output, 0, sizeof(output)); 148 149 size = *(u16 *) info->buffer.pointer; 150 if (size < 8) { 151 printk("ATPX buffer is too small: %zu\n", size); 152 err = -EINVAL; 153 goto out; 154 } 155 size = min(sizeof(output), size); 156 157 memcpy(&output, info->buffer.pointer, size); 158 159 /* TODO: check version? */ 160 printk("ATPX version %u\n", output.version); 161 162 radeon_atpx_parse_functions(&atpx->functions, output.function_bits); 163 164 out: 165 kfree(info); 166 return err; 167 } 168 169 /** 170 * radeon_atpx_set_discrete_state - power up/down discrete GPU 171 * 172 * @atpx: atpx info struct 173 * @state: discrete GPU state (0 = power down, 1 = power up) 174 * 175 * Execute the ATPX_FUNCTION_POWER_CONTROL ATPX function to 176 * power down/up the discrete GPU (all asics). 177 * Returns 0 on success, error on failure. 178 */ 179 static int radeon_atpx_set_discrete_state(struct radeon_atpx *atpx, u8 state) 180 { 181 struct acpi_buffer params; 182 union acpi_object *info; 183 struct atpx_power_control input; 184 185 if (atpx->functions.power_cntl) { 186 input.size = 3; 187 input.dgpu_state = state; 188 params.length = input.size; 189 params.pointer = &input; 190 info = radeon_atpx_call(atpx->handle, 191 ATPX_FUNCTION_POWER_CONTROL, 192 ¶ms); 193 if (!info) 194 return -EIO; 195 kfree(info); 196 } 197 return 0; 198 } 199 200 /** 201 * radeon_atpx_switch_disp_mux - switch display mux 202 * 203 * @atpx: atpx info struct 204 * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU) 205 * 206 * Execute the ATPX_FUNCTION_DISPLAY_MUX_CONTROL ATPX function to 207 * switch the display mux between the discrete GPU and integrated GPU 208 * (all asics). 209 * Returns 0 on success, error on failure. 210 */ 211 static int radeon_atpx_switch_disp_mux(struct radeon_atpx *atpx, u16 mux_id) 212 { 213 struct acpi_buffer params; 214 union acpi_object *info; 215 struct atpx_mux input; 216 217 if (atpx->functions.disp_mux_cntl) { 218 input.size = 4; 219 input.mux = mux_id; 220 params.length = input.size; 221 params.pointer = &input; 222 info = radeon_atpx_call(atpx->handle, 223 ATPX_FUNCTION_DISPLAY_MUX_CONTROL, 224 ¶ms); 225 if (!info) 226 return -EIO; 227 kfree(info); 228 } 229 return 0; 230 } 231 232 /** 233 * radeon_atpx_switch_i2c_mux - switch i2c/hpd mux 234 * 235 * @atpx: atpx info struct 236 * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU) 237 * 238 * Execute the ATPX_FUNCTION_I2C_MUX_CONTROL ATPX function to 239 * switch the i2c/hpd mux between the discrete GPU and integrated GPU 240 * (all asics). 241 * Returns 0 on success, error on failure. 242 */ 243 static int radeon_atpx_switch_i2c_mux(struct radeon_atpx *atpx, u16 mux_id) 244 { 245 struct acpi_buffer params; 246 union acpi_object *info; 247 struct atpx_mux input; 248 249 if (atpx->functions.i2c_mux_cntl) { 250 input.size = 4; 251 input.mux = mux_id; 252 params.length = input.size; 253 params.pointer = &input; 254 info = radeon_atpx_call(atpx->handle, 255 ATPX_FUNCTION_I2C_MUX_CONTROL, 256 ¶ms); 257 if (!info) 258 return -EIO; 259 kfree(info); 260 } 261 return 0; 262 } 263 264 /** 265 * radeon_atpx_switch_start - notify the sbios of a GPU switch 266 * 267 * @atpx: atpx info struct 268 * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU) 269 * 270 * Execute the ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION ATPX 271 * function to notify the sbios that a switch between the discrete GPU and 272 * integrated GPU has begun (all asics). 273 * Returns 0 on success, error on failure. 274 */ 275 static int radeon_atpx_switch_start(struct radeon_atpx *atpx, u16 mux_id) 276 { 277 struct acpi_buffer params; 278 union acpi_object *info; 279 struct atpx_mux input; 280 281 if (atpx->functions.switch_start) { 282 input.size = 4; 283 input.mux = mux_id; 284 params.length = input.size; 285 params.pointer = &input; 286 info = radeon_atpx_call(atpx->handle, 287 ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION, 288 ¶ms); 289 if (!info) 290 return -EIO; 291 kfree(info); 292 } 293 return 0; 294 } 295 296 /** 297 * radeon_atpx_switch_end - notify the sbios of a GPU switch 298 * 299 * @atpx: atpx info struct 300 * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU) 301 * 302 * Execute the ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION ATPX 303 * function to notify the sbios that a switch between the discrete GPU and 304 * integrated GPU has ended (all asics). 305 * Returns 0 on success, error on failure. 306 */ 307 static int radeon_atpx_switch_end(struct radeon_atpx *atpx, u16 mux_id) 308 { 309 struct acpi_buffer params; 310 union acpi_object *info; 311 struct atpx_mux input; 312 313 if (atpx->functions.switch_end) { 314 input.size = 4; 315 input.mux = mux_id; 316 params.length = input.size; 317 params.pointer = &input; 318 info = radeon_atpx_call(atpx->handle, 319 ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION, 320 ¶ms); 321 if (!info) 322 return -EIO; 323 kfree(info); 324 } 325 return 0; 326 } 327 328 /** 329 * radeon_atpx_switchto - switch to the requested GPU 330 * 331 * @id: GPU to switch to 332 * 333 * Execute the necessary ATPX functions to switch between the discrete GPU and 334 * integrated GPU (all asics). 335 * Returns 0 on success, error on failure. 336 */ 337 static int radeon_atpx_switchto(enum vga_switcheroo_client_id id) 338 { 339 u16 gpu_id; 340 341 if (id == VGA_SWITCHEROO_IGD) 342 gpu_id = ATPX_INTEGRATED_GPU; 343 else 344 gpu_id = ATPX_DISCRETE_GPU; 345 346 radeon_atpx_switch_start(&radeon_atpx_priv.atpx, gpu_id); 347 radeon_atpx_switch_disp_mux(&radeon_atpx_priv.atpx, gpu_id); 348 radeon_atpx_switch_i2c_mux(&radeon_atpx_priv.atpx, gpu_id); 349 radeon_atpx_switch_end(&radeon_atpx_priv.atpx, gpu_id); 350 351 return 0; 352 } 353 354 /** 355 * radeon_atpx_power_state - power down/up the requested GPU 356 * 357 * @id: GPU to power down/up 358 * @state: requested power state (0 = off, 1 = on) 359 * 360 * Execute the necessary ATPX function to power down/up the discrete GPU 361 * (all asics). 362 * Returns 0 on success, error on failure. 363 */ 364 static int radeon_atpx_power_state(enum vga_switcheroo_client_id id, 365 enum vga_switcheroo_state state) 366 { 367 /* on w500 ACPI can't change intel gpu state */ 368 if (id == VGA_SWITCHEROO_IGD) 369 return 0; 370 371 radeon_atpx_set_discrete_state(&radeon_atpx_priv.atpx, state); 372 return 0; 373 } 374 375 /** 376 * radeon_atpx_pci_probe_handle - look up the ATPX handle 377 * 378 * @pdev: pci device 379 * 380 * Look up the ATPX handles (all asics). 381 * Returns true if the handles are found, false if not. 382 */ 383 static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev) 384 { 385 acpi_handle dhandle, atpx_handle; 386 acpi_status status; 387 388 dhandle = DEVICE_ACPI_HANDLE(&pdev->dev); 389 if (!dhandle) 390 return false; 391 392 status = acpi_get_handle(dhandle, "ATPX", &atpx_handle); 393 if (ACPI_FAILURE(status)) 394 return false; 395 396 radeon_atpx_priv.dhandle = dhandle; 397 radeon_atpx_priv.atpx.handle = atpx_handle; 398 return true; 399 } 400 401 /** 402 * radeon_atpx_init - verify the ATPX interface 403 * 404 * Verify the ATPX interface (all asics). 405 * Returns 0 on success, error on failure. 406 */ 407 static int radeon_atpx_init(void) 408 { 409 /* set up the ATPX handle */ 410 return radeon_atpx_verify_interface(&radeon_atpx_priv.atpx); 411 } 412 413 /** 414 * radeon_atpx_get_client_id - get the client id 415 * 416 * @pdev: pci device 417 * 418 * look up whether we are the integrated or discrete GPU (all asics). 419 * Returns the client id. 420 */ 421 static int radeon_atpx_get_client_id(struct pci_dev *pdev) 422 { 423 if (radeon_atpx_priv.dhandle == DEVICE_ACPI_HANDLE(&pdev->dev)) 424 return VGA_SWITCHEROO_IGD; 425 else 426 return VGA_SWITCHEROO_DIS; 427 } 428 429 static struct vga_switcheroo_handler radeon_atpx_handler = { 430 .switchto = radeon_atpx_switchto, 431 .power_state = radeon_atpx_power_state, 432 .init = radeon_atpx_init, 433 .get_client_id = radeon_atpx_get_client_id, 434 }; 435 436 /** 437 * radeon_atpx_detect - detect whether we have PX 438 * 439 * Check if we have a PX system (all asics). 440 * Returns true if we have a PX system, false if not. 441 */ 442 static bool radeon_atpx_detect(void) 443 { 444 char acpi_method_name[255] = { 0 }; 445 struct acpi_buffer buffer = {sizeof(acpi_method_name), acpi_method_name}; 446 struct pci_dev *pdev = NULL; 447 bool has_atpx = false; 448 int vga_count = 0; 449 450 while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) { 451 vga_count++; 452 453 has_atpx |= (radeon_atpx_pci_probe_handle(pdev) == true); 454 } 455 456 if (has_atpx && vga_count == 2) { 457 acpi_get_name(radeon_atpx_priv.atpx.handle, ACPI_FULL_PATHNAME, &buffer); 458 printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n", 459 acpi_method_name); 460 radeon_atpx_priv.atpx_detected = true; 461 return true; 462 } 463 return false; 464 } 465 466 /** 467 * radeon_register_atpx_handler - register with vga_switcheroo 468 * 469 * Register the PX callbacks with vga_switcheroo (all asics). 470 */ 471 void radeon_register_atpx_handler(void) 472 { 473 bool r; 474 475 /* detect if we have any ATPX + 2 VGA in the system */ 476 r = radeon_atpx_detect(); 477 if (!r) 478 return; 479 480 vga_switcheroo_register_handler(&radeon_atpx_handler); 481 } 482 483 /** 484 * radeon_unregister_atpx_handler - unregister with vga_switcheroo 485 * 486 * Unregister the PX callbacks with vga_switcheroo (all asics). 487 */ 488 void radeon_unregister_atpx_handler(void) 489 { 490 vga_switcheroo_unregister_handler(); 491 } 492