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