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