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