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