1 /* 2 * Gmux driver for Apple laptops 3 * 4 * Copyright (C) Canonical Ltd. <seth.forshee@canonical.com> 5 * Copyright (C) 2010-2012 Andreas Heider <andreas@meetr.de> 6 * Copyright (C) 2015 Lukas Wunner <lukas@wunner.de> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 */ 12 13 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 14 15 #include <linux/module.h> 16 #include <linux/kernel.h> 17 #include <linux/init.h> 18 #include <linux/backlight.h> 19 #include <linux/acpi.h> 20 #include <linux/pnp.h> 21 #include <linux/apple_bl.h> 22 #include <linux/apple-gmux.h> 23 #include <linux/slab.h> 24 #include <linux/delay.h> 25 #include <linux/pci.h> 26 #include <linux/vga_switcheroo.h> 27 #include <linux/vgaarb.h> 28 #include <acpi/video.h> 29 #include <asm/io.h> 30 31 /** 32 * DOC: Overview 33 * 34 * gmux is a microcontroller built into the MacBook Pro to support dual GPUs: 35 * A `Lattice XP2`_ on pre-retinas, a `Renesas R4F2113`_ on retinas. 36 * 37 * (The MacPro6,1 2013 also has a gmux, however it is unclear why since it has 38 * dual GPUs but no built-in display.) 39 * 40 * gmux is connected to the LPC bus of the southbridge. Its I/O ports are 41 * accessed differently depending on the microcontroller: Driver functions 42 * to access a pre-retina gmux are infixed ``_pio_``, those for a retina gmux 43 * are infixed ``_index_``. 44 * 45 * .. _Lattice XP2: 46 * http://www.latticesemi.com/en/Products/FPGAandCPLD/LatticeXP2.aspx 47 * .. _Renesas R4F2113: 48 * http://www.renesas.com/products/mpumcu/h8s/h8s2100/h8s2113/index.jsp 49 */ 50 51 struct apple_gmux_data { 52 unsigned long iostart; 53 unsigned long iolen; 54 bool indexed; 55 struct mutex index_lock; 56 57 struct pci_dev *pdev; 58 struct backlight_device *bdev; 59 60 /* switcheroo data */ 61 acpi_handle dhandle; 62 int gpe; 63 bool external_switchable; 64 enum vga_switcheroo_client_id switch_state_display; 65 enum vga_switcheroo_client_id switch_state_ddc; 66 enum vga_switcheroo_client_id switch_state_external; 67 enum vga_switcheroo_state power_state; 68 struct completion powerchange_done; 69 }; 70 71 static struct apple_gmux_data *apple_gmux_data; 72 73 /* 74 * gmux port offsets. Many of these are not yet used, but may be in the 75 * future, and it's useful to have them documented here anyhow. 76 */ 77 #define GMUX_PORT_VERSION_MAJOR 0x04 78 #define GMUX_PORT_VERSION_MINOR 0x05 79 #define GMUX_PORT_VERSION_RELEASE 0x06 80 #define GMUX_PORT_SWITCH_DISPLAY 0x10 81 #define GMUX_PORT_SWITCH_GET_DISPLAY 0x11 82 #define GMUX_PORT_INTERRUPT_ENABLE 0x14 83 #define GMUX_PORT_INTERRUPT_STATUS 0x16 84 #define GMUX_PORT_SWITCH_DDC 0x28 85 #define GMUX_PORT_SWITCH_EXTERNAL 0x40 86 #define GMUX_PORT_SWITCH_GET_EXTERNAL 0x41 87 #define GMUX_PORT_DISCRETE_POWER 0x50 88 #define GMUX_PORT_MAX_BRIGHTNESS 0x70 89 #define GMUX_PORT_BRIGHTNESS 0x74 90 #define GMUX_PORT_VALUE 0xc2 91 #define GMUX_PORT_READ 0xd0 92 #define GMUX_PORT_WRITE 0xd4 93 94 #define GMUX_MIN_IO_LEN (GMUX_PORT_BRIGHTNESS + 4) 95 96 #define GMUX_INTERRUPT_ENABLE 0xff 97 #define GMUX_INTERRUPT_DISABLE 0x00 98 99 #define GMUX_INTERRUPT_STATUS_ACTIVE 0 100 #define GMUX_INTERRUPT_STATUS_DISPLAY (1 << 0) 101 #define GMUX_INTERRUPT_STATUS_POWER (1 << 2) 102 #define GMUX_INTERRUPT_STATUS_HOTPLUG (1 << 3) 103 104 #define GMUX_BRIGHTNESS_MASK 0x00ffffff 105 #define GMUX_MAX_BRIGHTNESS GMUX_BRIGHTNESS_MASK 106 107 static u8 gmux_pio_read8(struct apple_gmux_data *gmux_data, int port) 108 { 109 return inb(gmux_data->iostart + port); 110 } 111 112 static void gmux_pio_write8(struct apple_gmux_data *gmux_data, int port, 113 u8 val) 114 { 115 outb(val, gmux_data->iostart + port); 116 } 117 118 static u32 gmux_pio_read32(struct apple_gmux_data *gmux_data, int port) 119 { 120 return inl(gmux_data->iostart + port); 121 } 122 123 static void gmux_pio_write32(struct apple_gmux_data *gmux_data, int port, 124 u32 val) 125 { 126 int i; 127 u8 tmpval; 128 129 for (i = 0; i < 4; i++) { 130 tmpval = (val >> (i * 8)) & 0xff; 131 outb(tmpval, gmux_data->iostart + port + i); 132 } 133 } 134 135 static int gmux_index_wait_ready(struct apple_gmux_data *gmux_data) 136 { 137 int i = 200; 138 u8 gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE); 139 140 while (i && (gwr & 0x01)) { 141 inb(gmux_data->iostart + GMUX_PORT_READ); 142 gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE); 143 udelay(100); 144 i--; 145 } 146 147 return !!i; 148 } 149 150 static int gmux_index_wait_complete(struct apple_gmux_data *gmux_data) 151 { 152 int i = 200; 153 u8 gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE); 154 155 while (i && !(gwr & 0x01)) { 156 gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE); 157 udelay(100); 158 i--; 159 } 160 161 if (gwr & 0x01) 162 inb(gmux_data->iostart + GMUX_PORT_READ); 163 164 return !!i; 165 } 166 167 static u8 gmux_index_read8(struct apple_gmux_data *gmux_data, int port) 168 { 169 u8 val; 170 171 mutex_lock(&gmux_data->index_lock); 172 gmux_index_wait_ready(gmux_data); 173 outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ); 174 gmux_index_wait_complete(gmux_data); 175 val = inb(gmux_data->iostart + GMUX_PORT_VALUE); 176 mutex_unlock(&gmux_data->index_lock); 177 178 return val; 179 } 180 181 static void gmux_index_write8(struct apple_gmux_data *gmux_data, int port, 182 u8 val) 183 { 184 mutex_lock(&gmux_data->index_lock); 185 outb(val, gmux_data->iostart + GMUX_PORT_VALUE); 186 gmux_index_wait_ready(gmux_data); 187 outb(port & 0xff, gmux_data->iostart + GMUX_PORT_WRITE); 188 gmux_index_wait_complete(gmux_data); 189 mutex_unlock(&gmux_data->index_lock); 190 } 191 192 static u32 gmux_index_read32(struct apple_gmux_data *gmux_data, int port) 193 { 194 u32 val; 195 196 mutex_lock(&gmux_data->index_lock); 197 gmux_index_wait_ready(gmux_data); 198 outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ); 199 gmux_index_wait_complete(gmux_data); 200 val = inl(gmux_data->iostart + GMUX_PORT_VALUE); 201 mutex_unlock(&gmux_data->index_lock); 202 203 return val; 204 } 205 206 static void gmux_index_write32(struct apple_gmux_data *gmux_data, int port, 207 u32 val) 208 { 209 int i; 210 u8 tmpval; 211 212 mutex_lock(&gmux_data->index_lock); 213 214 for (i = 0; i < 4; i++) { 215 tmpval = (val >> (i * 8)) & 0xff; 216 outb(tmpval, gmux_data->iostart + GMUX_PORT_VALUE + i); 217 } 218 219 gmux_index_wait_ready(gmux_data); 220 outb(port & 0xff, gmux_data->iostart + GMUX_PORT_WRITE); 221 gmux_index_wait_complete(gmux_data); 222 mutex_unlock(&gmux_data->index_lock); 223 } 224 225 static u8 gmux_read8(struct apple_gmux_data *gmux_data, int port) 226 { 227 if (gmux_data->indexed) 228 return gmux_index_read8(gmux_data, port); 229 else 230 return gmux_pio_read8(gmux_data, port); 231 } 232 233 static void gmux_write8(struct apple_gmux_data *gmux_data, int port, u8 val) 234 { 235 if (gmux_data->indexed) 236 gmux_index_write8(gmux_data, port, val); 237 else 238 gmux_pio_write8(gmux_data, port, val); 239 } 240 241 static u32 gmux_read32(struct apple_gmux_data *gmux_data, int port) 242 { 243 if (gmux_data->indexed) 244 return gmux_index_read32(gmux_data, port); 245 else 246 return gmux_pio_read32(gmux_data, port); 247 } 248 249 static void gmux_write32(struct apple_gmux_data *gmux_data, int port, 250 u32 val) 251 { 252 if (gmux_data->indexed) 253 gmux_index_write32(gmux_data, port, val); 254 else 255 gmux_pio_write32(gmux_data, port, val); 256 } 257 258 static bool gmux_is_indexed(struct apple_gmux_data *gmux_data) 259 { 260 u16 val; 261 262 outb(0xaa, gmux_data->iostart + 0xcc); 263 outb(0x55, gmux_data->iostart + 0xcd); 264 outb(0x00, gmux_data->iostart + 0xce); 265 266 val = inb(gmux_data->iostart + 0xcc) | 267 (inb(gmux_data->iostart + 0xcd) << 8); 268 269 if (val == 0x55aa) 270 return true; 271 272 return false; 273 } 274 275 /** 276 * DOC: Backlight control 277 * 278 * On single GPU MacBooks, the PWM signal for the backlight is generated by 279 * the GPU. On dual GPU MacBook Pros by contrast, either GPU may be suspended 280 * to conserve energy. Hence the PWM signal needs to be generated by a separate 281 * backlight driver which is controlled by gmux. The earliest generation 282 * MBP5 2008/09 uses a `TI LP8543`_ backlight driver. All newer models 283 * use a `TI LP8545`_. 284 * 285 * .. _TI LP8543: http://www.ti.com/lit/ds/symlink/lp8543.pdf 286 * .. _TI LP8545: http://www.ti.com/lit/ds/symlink/lp8545.pdf 287 */ 288 289 static int gmux_get_brightness(struct backlight_device *bd) 290 { 291 struct apple_gmux_data *gmux_data = bl_get_data(bd); 292 return gmux_read32(gmux_data, GMUX_PORT_BRIGHTNESS) & 293 GMUX_BRIGHTNESS_MASK; 294 } 295 296 static int gmux_update_status(struct backlight_device *bd) 297 { 298 struct apple_gmux_data *gmux_data = bl_get_data(bd); 299 u32 brightness = bd->props.brightness; 300 301 if (bd->props.state & BL_CORE_SUSPENDED) 302 return 0; 303 304 gmux_write32(gmux_data, GMUX_PORT_BRIGHTNESS, brightness); 305 306 return 0; 307 } 308 309 static const struct backlight_ops gmux_bl_ops = { 310 .options = BL_CORE_SUSPENDRESUME, 311 .get_brightness = gmux_get_brightness, 312 .update_status = gmux_update_status, 313 }; 314 315 /** 316 * DOC: Graphics mux 317 * 318 * On pre-retinas, the LVDS outputs of both GPUs feed into gmux which muxes 319 * either of them to the panel. One of the tricks gmux has up its sleeve is 320 * to lengthen the blanking interval of its output during a switch to 321 * synchronize it with the GPU switched to. This allows for a flicker-free 322 * switch that is imperceptible by the user (`US 8,687,007 B2`_). 323 * 324 * On retinas, muxing is no longer done by gmux itself, but by a separate 325 * chip which is controlled by gmux. The chip is triple sourced, it is 326 * either an `NXP CBTL06142`_, `TI HD3SS212`_ or `Pericom PI3VDP12412`_. 327 * The panel is driven with eDP instead of LVDS since the pixel clock 328 * required for retina resolution exceeds LVDS' limits. 329 * 330 * Pre-retinas are able to switch the panel's DDC pins separately. 331 * This is handled by a `TI SN74LV4066A`_ which is controlled by gmux. 332 * The inactive GPU can thus probe the panel's EDID without switching over 333 * the entire panel. Retinas lack this functionality as the chips used for 334 * eDP muxing are incapable of switching the AUX channel separately (see 335 * the linked data sheets, Pericom would be capable but this is unused). 336 * However the retina panel has the NO_AUX_HANDSHAKE_LINK_TRAINING bit set 337 * in its DPCD, allowing the inactive GPU to skip the AUX handshake and 338 * set up the output with link parameters pre-calibrated by the active GPU. 339 * 340 * The external DP port is only fully switchable on the first two unibody 341 * MacBook Pro generations, MBP5 2008/09 and MBP6 2010. This is done by an 342 * `NXP CBTL06141`_ which is controlled by gmux. It's the predecessor of the 343 * eDP mux on retinas, the difference being support for 2.7 versus 5.4 Gbit/s. 344 * 345 * The following MacBook Pro generations replaced the external DP port with a 346 * combined DP/Thunderbolt port and lost the ability to switch it between GPUs, 347 * connecting it either to the discrete GPU or the Thunderbolt controller. 348 * Oddly enough, while the full port is no longer switchable, AUX and HPD 349 * are still switchable by way of an `NXP CBTL03062`_ (on pre-retinas 350 * MBP8 2011 and MBP9 2012) or two `TI TS3DS10224`_ (on retinas) under the 351 * control of gmux. Since the integrated GPU is missing the main link, 352 * external displays appear to it as phantoms which fail to link-train. 353 * 354 * gmux receives the HPD signal of all display connectors and sends an 355 * interrupt on hotplug. On generations which cannot switch external ports, 356 * the discrete GPU can then be woken to drive the newly connected display. 357 * The ability to switch AUX on these generations could be used to improve 358 * reliability of hotplug detection by having the integrated GPU poll the 359 * ports while the discrete GPU is asleep, but currently we do not make use 360 * of this feature. 361 * 362 * Our switching policy for the external port is that on those generations 363 * which are able to switch it fully, the port is switched together with the 364 * panel when IGD / DIS commands are issued to vga_switcheroo. It is thus 365 * possible to drive e.g. a beamer on battery power with the integrated GPU. 366 * The user may manually switch to the discrete GPU if more performance is 367 * needed. 368 * 369 * On all newer generations, the external port can only be driven by the 370 * discrete GPU. If a display is plugged in while the panel is switched to 371 * the integrated GPU, *both* GPUs will be in use for maximum performance. 372 * To decrease power consumption, the user may manually switch to the 373 * discrete GPU, thereby suspending the integrated GPU. 374 * 375 * gmux' initial switch state on bootup is user configurable via the EFI 376 * variable ``gpu-power-prefs-fa4ce28d-b62f-4c99-9cc3-6815686e30f9`` (5th byte, 377 * 1 = IGD, 0 = DIS). Based on this setting, the EFI firmware tells gmux to 378 * switch the panel and the external DP connector and allocates a framebuffer 379 * for the selected GPU. 380 * 381 * .. _US 8,687,007 B2: http://pimg-fpiw.uspto.gov/fdd/07/870/086/0.pdf 382 * .. _NXP CBTL06141: http://www.nxp.com/documents/data_sheet/CBTL06141.pdf 383 * .. _NXP CBTL06142: http://www.nxp.com/documents/data_sheet/CBTL06141.pdf 384 * .. _TI HD3SS212: http://www.ti.com/lit/ds/symlink/hd3ss212.pdf 385 * .. _Pericom PI3VDP12412: https://www.pericom.com/assets/Datasheets/PI3VDP12412.pdf 386 * .. _TI SN74LV4066A: http://www.ti.com/lit/ds/symlink/sn74lv4066a.pdf 387 * .. _NXP CBTL03062: http://pdf.datasheetarchive.com/indexerfiles/Datasheets-SW16/DSASW00308511.pdf 388 * .. _TI TS3DS10224: http://www.ti.com/lit/ds/symlink/ts3ds10224.pdf 389 */ 390 391 static void gmux_read_switch_state(struct apple_gmux_data *gmux_data) 392 { 393 if (gmux_read8(gmux_data, GMUX_PORT_SWITCH_DDC) == 1) 394 gmux_data->switch_state_ddc = VGA_SWITCHEROO_IGD; 395 else 396 gmux_data->switch_state_ddc = VGA_SWITCHEROO_DIS; 397 398 if (gmux_read8(gmux_data, GMUX_PORT_SWITCH_DISPLAY) == 2) 399 gmux_data->switch_state_display = VGA_SWITCHEROO_IGD; 400 else 401 gmux_data->switch_state_display = VGA_SWITCHEROO_DIS; 402 403 if (gmux_read8(gmux_data, GMUX_PORT_SWITCH_EXTERNAL) == 2) 404 gmux_data->switch_state_external = VGA_SWITCHEROO_IGD; 405 else 406 gmux_data->switch_state_external = VGA_SWITCHEROO_DIS; 407 } 408 409 static void gmux_write_switch_state(struct apple_gmux_data *gmux_data) 410 { 411 if (gmux_data->switch_state_ddc == VGA_SWITCHEROO_IGD) 412 gmux_write8(gmux_data, GMUX_PORT_SWITCH_DDC, 1); 413 else 414 gmux_write8(gmux_data, GMUX_PORT_SWITCH_DDC, 2); 415 416 if (gmux_data->switch_state_display == VGA_SWITCHEROO_IGD) 417 gmux_write8(gmux_data, GMUX_PORT_SWITCH_DISPLAY, 2); 418 else 419 gmux_write8(gmux_data, GMUX_PORT_SWITCH_DISPLAY, 3); 420 421 if (gmux_data->switch_state_external == VGA_SWITCHEROO_IGD) 422 gmux_write8(gmux_data, GMUX_PORT_SWITCH_EXTERNAL, 2); 423 else 424 gmux_write8(gmux_data, GMUX_PORT_SWITCH_EXTERNAL, 3); 425 } 426 427 static int gmux_switchto(enum vga_switcheroo_client_id id) 428 { 429 apple_gmux_data->switch_state_ddc = id; 430 apple_gmux_data->switch_state_display = id; 431 if (apple_gmux_data->external_switchable) 432 apple_gmux_data->switch_state_external = id; 433 434 gmux_write_switch_state(apple_gmux_data); 435 436 return 0; 437 } 438 439 static int gmux_switch_ddc(enum vga_switcheroo_client_id id) 440 { 441 enum vga_switcheroo_client_id old_ddc_owner = 442 apple_gmux_data->switch_state_ddc; 443 444 if (id == old_ddc_owner) 445 return id; 446 447 pr_debug("Switching DDC from %d to %d\n", old_ddc_owner, id); 448 apple_gmux_data->switch_state_ddc = id; 449 450 if (id == VGA_SWITCHEROO_IGD) 451 gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 1); 452 else 453 gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 2); 454 455 return old_ddc_owner; 456 } 457 458 /** 459 * DOC: Power control 460 * 461 * gmux is able to cut power to the discrete GPU. It automatically takes care 462 * of the correct sequence to tear down and bring up the power rails for 463 * core voltage, VRAM and PCIe. 464 */ 465 466 static int gmux_set_discrete_state(struct apple_gmux_data *gmux_data, 467 enum vga_switcheroo_state state) 468 { 469 reinit_completion(&gmux_data->powerchange_done); 470 471 if (state == VGA_SWITCHEROO_ON) { 472 gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 1); 473 gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 3); 474 pr_debug("Discrete card powered up\n"); 475 } else { 476 gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 1); 477 gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 0); 478 pr_debug("Discrete card powered down\n"); 479 } 480 481 gmux_data->power_state = state; 482 483 if (gmux_data->gpe >= 0 && 484 !wait_for_completion_interruptible_timeout(&gmux_data->powerchange_done, 485 msecs_to_jiffies(200))) 486 pr_warn("Timeout waiting for gmux switch to complete\n"); 487 488 return 0; 489 } 490 491 static int gmux_set_power_state(enum vga_switcheroo_client_id id, 492 enum vga_switcheroo_state state) 493 { 494 if (id == VGA_SWITCHEROO_IGD) 495 return 0; 496 497 return gmux_set_discrete_state(apple_gmux_data, state); 498 } 499 500 static int gmux_get_client_id(struct pci_dev *pdev) 501 { 502 /* 503 * Early Macbook Pros with switchable graphics use nvidia 504 * integrated graphics. Hardcode that the 9400M is integrated. 505 */ 506 if (pdev->vendor == PCI_VENDOR_ID_INTEL) 507 return VGA_SWITCHEROO_IGD; 508 else if (pdev->vendor == PCI_VENDOR_ID_NVIDIA && 509 pdev->device == 0x0863) 510 return VGA_SWITCHEROO_IGD; 511 else 512 return VGA_SWITCHEROO_DIS; 513 } 514 515 static const struct vga_switcheroo_handler gmux_handler_indexed = { 516 .switchto = gmux_switchto, 517 .power_state = gmux_set_power_state, 518 .get_client_id = gmux_get_client_id, 519 }; 520 521 static const struct vga_switcheroo_handler gmux_handler_classic = { 522 .switchto = gmux_switchto, 523 .switch_ddc = gmux_switch_ddc, 524 .power_state = gmux_set_power_state, 525 .get_client_id = gmux_get_client_id, 526 }; 527 528 /** 529 * DOC: Interrupt 530 * 531 * gmux is also connected to a GPIO pin of the southbridge and thereby is able 532 * to trigger an ACPI GPE. On the MBP5 2008/09 it's GPIO pin 22 of the Nvidia 533 * MCP79, on all following generations it's GPIO pin 6 of the Intel PCH. 534 * The GPE merely signals that an interrupt occurred, the actual type of event 535 * is identified by reading a gmux register. 536 */ 537 538 static inline void gmux_disable_interrupts(struct apple_gmux_data *gmux_data) 539 { 540 gmux_write8(gmux_data, GMUX_PORT_INTERRUPT_ENABLE, 541 GMUX_INTERRUPT_DISABLE); 542 } 543 544 static inline void gmux_enable_interrupts(struct apple_gmux_data *gmux_data) 545 { 546 gmux_write8(gmux_data, GMUX_PORT_INTERRUPT_ENABLE, 547 GMUX_INTERRUPT_ENABLE); 548 } 549 550 static inline u8 gmux_interrupt_get_status(struct apple_gmux_data *gmux_data) 551 { 552 return gmux_read8(gmux_data, GMUX_PORT_INTERRUPT_STATUS); 553 } 554 555 static void gmux_clear_interrupts(struct apple_gmux_data *gmux_data) 556 { 557 u8 status; 558 559 /* to clear interrupts write back current status */ 560 status = gmux_interrupt_get_status(gmux_data); 561 gmux_write8(gmux_data, GMUX_PORT_INTERRUPT_STATUS, status); 562 } 563 564 static void gmux_notify_handler(acpi_handle device, u32 value, void *context) 565 { 566 u8 status; 567 struct pnp_dev *pnp = (struct pnp_dev *)context; 568 struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp); 569 570 status = gmux_interrupt_get_status(gmux_data); 571 gmux_disable_interrupts(gmux_data); 572 pr_debug("Notify handler called: status %d\n", status); 573 574 gmux_clear_interrupts(gmux_data); 575 gmux_enable_interrupts(gmux_data); 576 577 if (status & GMUX_INTERRUPT_STATUS_POWER) 578 complete(&gmux_data->powerchange_done); 579 } 580 581 static int gmux_suspend(struct device *dev) 582 { 583 struct pnp_dev *pnp = to_pnp_dev(dev); 584 struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp); 585 586 gmux_disable_interrupts(gmux_data); 587 return 0; 588 } 589 590 static int gmux_resume(struct device *dev) 591 { 592 struct pnp_dev *pnp = to_pnp_dev(dev); 593 struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp); 594 595 gmux_enable_interrupts(gmux_data); 596 gmux_write_switch_state(gmux_data); 597 if (gmux_data->power_state == VGA_SWITCHEROO_OFF) 598 gmux_set_discrete_state(gmux_data, gmux_data->power_state); 599 return 0; 600 } 601 602 static struct pci_dev *gmux_get_io_pdev(void) 603 { 604 struct pci_dev *pdev = NULL; 605 606 while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev))) { 607 u16 cmd; 608 609 pci_read_config_word(pdev, PCI_COMMAND, &cmd); 610 if (!(cmd & PCI_COMMAND_IO)) 611 continue; 612 613 return pdev; 614 } 615 616 return NULL; 617 } 618 619 static int is_thunderbolt(struct device *dev, void *data) 620 { 621 return to_pci_dev(dev)->is_thunderbolt; 622 } 623 624 static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) 625 { 626 struct apple_gmux_data *gmux_data; 627 struct resource *res; 628 struct backlight_properties props; 629 struct backlight_device *bdev; 630 u8 ver_major, ver_minor, ver_release; 631 int ret = -ENXIO; 632 acpi_status status; 633 unsigned long long gpe; 634 struct pci_dev *pdev = NULL; 635 636 if (apple_gmux_data) 637 return -EBUSY; 638 639 gmux_data = kzalloc(sizeof(*gmux_data), GFP_KERNEL); 640 if (!gmux_data) 641 return -ENOMEM; 642 pnp_set_drvdata(pnp, gmux_data); 643 644 res = pnp_get_resource(pnp, IORESOURCE_IO, 0); 645 if (!res) { 646 pr_err("Failed to find gmux I/O resource\n"); 647 goto err_free; 648 } 649 650 gmux_data->iostart = res->start; 651 gmux_data->iolen = res->end - res->start; 652 653 if (gmux_data->iolen < GMUX_MIN_IO_LEN) { 654 pr_err("gmux I/O region too small (%lu < %u)\n", 655 gmux_data->iolen, GMUX_MIN_IO_LEN); 656 goto err_free; 657 } 658 659 if (!request_region(gmux_data->iostart, gmux_data->iolen, 660 "Apple gmux")) { 661 pr_err("gmux I/O already in use\n"); 662 goto err_free; 663 } 664 665 /* 666 * Invalid version information may indicate either that the gmux 667 * device isn't present or that it's a new one that uses indexed 668 * io 669 */ 670 671 ver_major = gmux_read8(gmux_data, GMUX_PORT_VERSION_MAJOR); 672 ver_minor = gmux_read8(gmux_data, GMUX_PORT_VERSION_MINOR); 673 ver_release = gmux_read8(gmux_data, GMUX_PORT_VERSION_RELEASE); 674 if (ver_major == 0xff && ver_minor == 0xff && ver_release == 0xff) { 675 if (gmux_is_indexed(gmux_data)) { 676 u32 version; 677 mutex_init(&gmux_data->index_lock); 678 gmux_data->indexed = true; 679 version = gmux_read32(gmux_data, 680 GMUX_PORT_VERSION_MAJOR); 681 ver_major = (version >> 24) & 0xff; 682 ver_minor = (version >> 16) & 0xff; 683 ver_release = (version >> 8) & 0xff; 684 } else { 685 pr_info("gmux device not present or IO disabled\n"); 686 ret = -ENODEV; 687 goto err_release; 688 } 689 } 690 pr_info("Found gmux version %d.%d.%d [%s]\n", ver_major, ver_minor, 691 ver_release, (gmux_data->indexed ? "indexed" : "classic")); 692 693 /* 694 * Apple systems with gmux are EFI based and normally don't use 695 * VGA. In addition changing IO+MEM ownership between IGP and dGPU 696 * disables IO/MEM used for backlight control on some systems. 697 * Lock IO+MEM to GPU with active IO to prevent switch. 698 */ 699 pdev = gmux_get_io_pdev(); 700 if (pdev && vga_tryget(pdev, 701 VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM)) { 702 pr_err("IO+MEM vgaarb-locking for PCI:%s failed\n", 703 pci_name(pdev)); 704 ret = -EBUSY; 705 goto err_release; 706 } else if (pdev) 707 pr_info("locked IO for PCI:%s\n", pci_name(pdev)); 708 gmux_data->pdev = pdev; 709 710 memset(&props, 0, sizeof(props)); 711 props.type = BACKLIGHT_PLATFORM; 712 props.max_brightness = gmux_read32(gmux_data, GMUX_PORT_MAX_BRIGHTNESS); 713 714 /* 715 * Currently it's assumed that the maximum brightness is less than 716 * 2^24 for compatibility with old gmux versions. Cap the max 717 * brightness at this value, but print a warning if the hardware 718 * reports something higher so that it can be fixed. 719 */ 720 if (WARN_ON(props.max_brightness > GMUX_MAX_BRIGHTNESS)) 721 props.max_brightness = GMUX_MAX_BRIGHTNESS; 722 723 bdev = backlight_device_register("gmux_backlight", &pnp->dev, 724 gmux_data, &gmux_bl_ops, &props); 725 if (IS_ERR(bdev)) { 726 ret = PTR_ERR(bdev); 727 goto err_release; 728 } 729 730 gmux_data->bdev = bdev; 731 bdev->props.brightness = gmux_get_brightness(bdev); 732 backlight_update_status(bdev); 733 734 /* 735 * The backlight situation on Macs is complicated. If the gmux is 736 * present it's the best choice, because it always works for 737 * backlight control and supports more levels than other options. 738 * Disable the other backlight choices. 739 */ 740 acpi_video_set_dmi_backlight_type(acpi_backlight_vendor); 741 apple_bl_unregister(); 742 743 gmux_data->power_state = VGA_SWITCHEROO_ON; 744 745 gmux_data->dhandle = ACPI_HANDLE(&pnp->dev); 746 if (!gmux_data->dhandle) { 747 pr_err("Cannot find acpi handle for pnp device %s\n", 748 dev_name(&pnp->dev)); 749 ret = -ENODEV; 750 goto err_notify; 751 } 752 753 status = acpi_evaluate_integer(gmux_data->dhandle, "GMGP", NULL, &gpe); 754 if (ACPI_SUCCESS(status)) { 755 gmux_data->gpe = (int)gpe; 756 757 status = acpi_install_notify_handler(gmux_data->dhandle, 758 ACPI_DEVICE_NOTIFY, 759 &gmux_notify_handler, pnp); 760 if (ACPI_FAILURE(status)) { 761 pr_err("Install notify handler failed: %s\n", 762 acpi_format_exception(status)); 763 ret = -ENODEV; 764 goto err_notify; 765 } 766 767 status = acpi_enable_gpe(NULL, gmux_data->gpe); 768 if (ACPI_FAILURE(status)) { 769 pr_err("Cannot enable gpe: %s\n", 770 acpi_format_exception(status)); 771 goto err_enable_gpe; 772 } 773 } else { 774 pr_warn("No GPE found for gmux\n"); 775 gmux_data->gpe = -1; 776 } 777 778 /* 779 * If Thunderbolt is present, the external DP port is not fully 780 * switchable. Force its AUX channel to the discrete GPU. 781 */ 782 gmux_data->external_switchable = 783 !bus_for_each_dev(&pci_bus_type, NULL, NULL, is_thunderbolt); 784 if (!gmux_data->external_switchable) 785 gmux_write8(gmux_data, GMUX_PORT_SWITCH_EXTERNAL, 3); 786 787 apple_gmux_data = gmux_data; 788 init_completion(&gmux_data->powerchange_done); 789 gmux_enable_interrupts(gmux_data); 790 gmux_read_switch_state(gmux_data); 791 792 /* 793 * Retina MacBook Pros cannot switch the panel's AUX separately 794 * and need eDP pre-calibration. They are distinguishable from 795 * pre-retinas by having an "indexed" gmux. 796 * 797 * Pre-retina MacBook Pros can switch the panel's DDC separately. 798 */ 799 if (gmux_data->indexed) 800 ret = vga_switcheroo_register_handler(&gmux_handler_indexed, 801 VGA_SWITCHEROO_NEEDS_EDP_CONFIG); 802 else 803 ret = vga_switcheroo_register_handler(&gmux_handler_classic, 804 VGA_SWITCHEROO_CAN_SWITCH_DDC); 805 if (ret) { 806 pr_err("Failed to register vga_switcheroo handler\n"); 807 goto err_register_handler; 808 } 809 810 return 0; 811 812 err_register_handler: 813 gmux_disable_interrupts(gmux_data); 814 apple_gmux_data = NULL; 815 if (gmux_data->gpe >= 0) 816 acpi_disable_gpe(NULL, gmux_data->gpe); 817 err_enable_gpe: 818 if (gmux_data->gpe >= 0) 819 acpi_remove_notify_handler(gmux_data->dhandle, 820 ACPI_DEVICE_NOTIFY, 821 &gmux_notify_handler); 822 err_notify: 823 backlight_device_unregister(bdev); 824 err_release: 825 if (gmux_data->pdev) 826 vga_put(gmux_data->pdev, 827 VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM); 828 pci_dev_put(pdev); 829 release_region(gmux_data->iostart, gmux_data->iolen); 830 err_free: 831 kfree(gmux_data); 832 return ret; 833 } 834 835 static void gmux_remove(struct pnp_dev *pnp) 836 { 837 struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp); 838 839 vga_switcheroo_unregister_handler(); 840 gmux_disable_interrupts(gmux_data); 841 if (gmux_data->gpe >= 0) { 842 acpi_disable_gpe(NULL, gmux_data->gpe); 843 acpi_remove_notify_handler(gmux_data->dhandle, 844 ACPI_DEVICE_NOTIFY, 845 &gmux_notify_handler); 846 } 847 848 if (gmux_data->pdev) { 849 vga_put(gmux_data->pdev, 850 VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM); 851 pci_dev_put(gmux_data->pdev); 852 } 853 backlight_device_unregister(gmux_data->bdev); 854 855 release_region(gmux_data->iostart, gmux_data->iolen); 856 apple_gmux_data = NULL; 857 kfree(gmux_data); 858 859 acpi_video_register(); 860 apple_bl_register(); 861 } 862 863 static const struct pnp_device_id gmux_device_ids[] = { 864 {GMUX_ACPI_HID, 0}, 865 {"", 0} 866 }; 867 868 static const struct dev_pm_ops gmux_dev_pm_ops = { 869 .suspend = gmux_suspend, 870 .resume = gmux_resume, 871 }; 872 873 static struct pnp_driver gmux_pnp_driver = { 874 .name = "apple-gmux", 875 .probe = gmux_probe, 876 .remove = gmux_remove, 877 .id_table = gmux_device_ids, 878 .driver = { 879 .pm = &gmux_dev_pm_ops, 880 }, 881 }; 882 883 module_pnp_driver(gmux_pnp_driver); 884 MODULE_AUTHOR("Seth Forshee <seth.forshee@canonical.com>"); 885 MODULE_DESCRIPTION("Apple Gmux Driver"); 886 MODULE_LICENSE("GPL"); 887 MODULE_DEVICE_TABLE(pnp, gmux_device_ids); 888