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