Lines Matching +full:0 +full:- +full:indexed
1 // SPDX-License-Identifier: GPL-2.0-only
6 * Copyright (C) 2010-2012 Andreas Heider <andreas@meetr.de>
19 #include <linux/apple-gmux.h>
31 * A `Lattice XP2`_ on pre-retinas, a `Renesas R4F2113`_ on retinas.
34 * dual GPUs but no built-in display.)
38 * to access a pre-retina gmux are infixed ``_pio_``, those for a retina gmux
50 bool indexed; member
72 #define GMUX_PORT_VERSION_MAJOR 0x04
73 #define GMUX_PORT_VERSION_MINOR 0x05
74 #define GMUX_PORT_VERSION_RELEASE 0x06
75 #define GMUX_PORT_SWITCH_DISPLAY 0x10
76 #define GMUX_PORT_SWITCH_GET_DISPLAY 0x11
77 #define GMUX_PORT_INTERRUPT_ENABLE 0x14
78 #define GMUX_PORT_INTERRUPT_STATUS 0x16
79 #define GMUX_PORT_SWITCH_DDC 0x28
80 #define GMUX_PORT_SWITCH_EXTERNAL 0x40
81 #define GMUX_PORT_SWITCH_GET_EXTERNAL 0x41
82 #define GMUX_PORT_DISCRETE_POWER 0x50
83 #define GMUX_PORT_MAX_BRIGHTNESS 0x70
84 #define GMUX_PORT_BRIGHTNESS 0x74
85 #define GMUX_PORT_VALUE 0xc2
86 #define GMUX_PORT_READ 0xd0
87 #define GMUX_PORT_WRITE 0xd4
91 #define GMUX_INTERRUPT_ENABLE 0xff
92 #define GMUX_INTERRUPT_DISABLE 0x00
94 #define GMUX_INTERRUPT_STATUS_ACTIVE 0
95 #define GMUX_INTERRUPT_STATUS_DISPLAY (1 << 0)
99 #define GMUX_BRIGHTNESS_MASK 0x00ffffff
104 return inb(gmux_data->iostart + port); in gmux_pio_read8()
110 outb(val, gmux_data->iostart + port); in gmux_pio_write8()
115 return inl(gmux_data->iostart + port); in gmux_pio_read32()
124 for (i = 0; i < 4; i++) { in gmux_pio_write32()
125 tmpval = (val >> (i * 8)) & 0xff; in gmux_pio_write32()
126 outb(tmpval, gmux_data->iostart + port + i); in gmux_pio_write32()
133 u8 gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE); in gmux_index_wait_ready()
135 while (i && (gwr & 0x01)) { in gmux_index_wait_ready()
136 inb(gmux_data->iostart + GMUX_PORT_READ); in gmux_index_wait_ready()
137 gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE); in gmux_index_wait_ready()
139 i--; in gmux_index_wait_ready()
148 u8 gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE); in gmux_index_wait_complete()
150 while (i && !(gwr & 0x01)) { in gmux_index_wait_complete()
151 gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE); in gmux_index_wait_complete()
153 i--; in gmux_index_wait_complete()
156 if (gwr & 0x01) in gmux_index_wait_complete()
157 inb(gmux_data->iostart + GMUX_PORT_READ); in gmux_index_wait_complete()
166 mutex_lock(&gmux_data->index_lock); in gmux_index_read8()
168 outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ); in gmux_index_read8()
170 val = inb(gmux_data->iostart + GMUX_PORT_VALUE); in gmux_index_read8()
171 mutex_unlock(&gmux_data->index_lock); in gmux_index_read8()
179 mutex_lock(&gmux_data->index_lock); in gmux_index_write8()
180 outb(val, gmux_data->iostart + GMUX_PORT_VALUE); in gmux_index_write8()
182 outb(port & 0xff, gmux_data->iostart + GMUX_PORT_WRITE); in gmux_index_write8()
184 mutex_unlock(&gmux_data->index_lock); in gmux_index_write8()
191 mutex_lock(&gmux_data->index_lock); in gmux_index_read32()
193 outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ); in gmux_index_read32()
195 val = inl(gmux_data->iostart + GMUX_PORT_VALUE); in gmux_index_read32()
196 mutex_unlock(&gmux_data->index_lock); in gmux_index_read32()
207 mutex_lock(&gmux_data->index_lock); in gmux_index_write32()
209 for (i = 0; i < 4; i++) { in gmux_index_write32()
210 tmpval = (val >> (i * 8)) & 0xff; in gmux_index_write32()
211 outb(tmpval, gmux_data->iostart + GMUX_PORT_VALUE + i); in gmux_index_write32()
215 outb(port & 0xff, gmux_data->iostart + GMUX_PORT_WRITE); in gmux_index_write32()
217 mutex_unlock(&gmux_data->index_lock); in gmux_index_write32()
222 if (gmux_data->indexed) in gmux_read8()
230 if (gmux_data->indexed) in gmux_write8()
238 if (gmux_data->indexed) in gmux_read32()
247 if (gmux_data->indexed) in gmux_write32()
257 outb(0xaa, gmux_data->iostart + 0xcc); in gmux_is_indexed()
258 outb(0x55, gmux_data->iostart + 0xcd); in gmux_is_indexed()
259 outb(0x00, gmux_data->iostart + 0xce); in gmux_is_indexed()
261 val = inb(gmux_data->iostart + 0xcc) | in gmux_is_indexed()
262 (inb(gmux_data->iostart + 0xcd) << 8); in gmux_is_indexed()
264 if (val == 0x55aa) in gmux_is_indexed()
294 u32 brightness = bd->props.brightness; in gmux_update_status()
296 if (bd->props.state & BL_CORE_SUSPENDED) in gmux_update_status()
297 return 0; in gmux_update_status()
301 return 0; in gmux_update_status()
313 * On pre-retinas, the LVDS outputs of both GPUs feed into gmux which muxes
316 * synchronize it with the GPU switched to. This allows for a flicker-free
325 * Pre-retinas are able to switch the panel's DDC pins separately.
333 * set up the output with link parameters pre-calibrated by the active GPU.
344 * are still switchable by way of an `NXP CBTL03062`_ (on pre-retinas
347 * external displays appear to it as phantoms which fail to link-train.
371 * variable ``gpu-power-prefs-fa4ce28d-b62f-4c99-9cc3-6815686e30f9`` (5th byte,
372 * 1 = IGD, 0 = DIS). Based on this setting, the EFI firmware tells gmux to
376 * .. _US 8,687,007 B2: https://pimg-fpiw.uspto.gov/fdd/07/870/086/0.pdf
382 …* .. _NXP CBTL03062: http://pdf.datasheetarchive.com/indexerfiles/Datasheets-SW16/DSASW00308511.…
389 gmux_data->switch_state_ddc = VGA_SWITCHEROO_IGD; in gmux_read_switch_state()
391 gmux_data->switch_state_ddc = VGA_SWITCHEROO_DIS; in gmux_read_switch_state()
394 gmux_data->switch_state_display = VGA_SWITCHEROO_IGD; in gmux_read_switch_state()
396 gmux_data->switch_state_display = VGA_SWITCHEROO_DIS; in gmux_read_switch_state()
399 gmux_data->switch_state_external = VGA_SWITCHEROO_IGD; in gmux_read_switch_state()
401 gmux_data->switch_state_external = VGA_SWITCHEROO_DIS; in gmux_read_switch_state()
406 if (gmux_data->switch_state_ddc == VGA_SWITCHEROO_IGD) in gmux_write_switch_state()
411 if (gmux_data->switch_state_display == VGA_SWITCHEROO_IGD) in gmux_write_switch_state()
416 if (gmux_data->switch_state_external == VGA_SWITCHEROO_IGD) in gmux_write_switch_state()
424 apple_gmux_data->switch_state_ddc = id; in gmux_switchto()
425 apple_gmux_data->switch_state_display = id; in gmux_switchto()
426 if (apple_gmux_data->external_switchable) in gmux_switchto()
427 apple_gmux_data->switch_state_external = id; in gmux_switchto()
431 return 0; in gmux_switchto()
437 apple_gmux_data->switch_state_ddc; in gmux_switch_ddc()
443 apple_gmux_data->switch_state_ddc = id; in gmux_switch_ddc()
464 reinit_completion(&gmux_data->powerchange_done); in gmux_set_discrete_state()
472 gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 0); in gmux_set_discrete_state()
476 gmux_data->power_state = state; in gmux_set_discrete_state()
478 if (gmux_data->gpe >= 0 && in gmux_set_discrete_state()
479 !wait_for_completion_interruptible_timeout(&gmux_data->powerchange_done, in gmux_set_discrete_state()
483 return 0; in gmux_set_discrete_state()
490 return 0; in gmux_set_power_state()
501 if (pdev->vendor == PCI_VENDOR_ID_INTEL) in gmux_get_client_id()
503 else if (pdev->vendor == PCI_VENDOR_ID_NVIDIA && in gmux_get_client_id()
504 pdev->device == 0x0863) in gmux_get_client_id()
573 complete(&gmux_data->powerchange_done); in gmux_notify_handler()
582 return 0; in gmux_suspend()
592 if (gmux_data->power_state == VGA_SWITCHEROO_OFF) in gmux_resume()
593 gmux_set_discrete_state(gmux_data, gmux_data->power_state); in gmux_resume()
594 return 0; in gmux_resume()
599 return to_pci_dev(dev)->is_thunderbolt; in is_thunderbolt()
609 int ret = -ENXIO; in gmux_probe()
614 return -EBUSY; in gmux_probe()
618 return -ENOMEM; in gmux_probe()
621 res = pnp_get_resource(pnp, IORESOURCE_IO, 0); in gmux_probe()
627 gmux_data->iostart = res->start; in gmux_probe()
628 gmux_data->iolen = res->end - res->start; in gmux_probe()
630 if (gmux_data->iolen < GMUX_MIN_IO_LEN) { in gmux_probe()
632 gmux_data->iolen, GMUX_MIN_IO_LEN); in gmux_probe()
636 if (!request_region(gmux_data->iostart, gmux_data->iolen, in gmux_probe()
644 * device isn't present or that it's a new one that uses indexed in gmux_probe()
651 if (ver_major == 0xff && ver_minor == 0xff && ver_release == 0xff) { in gmux_probe()
654 mutex_init(&gmux_data->index_lock); in gmux_probe()
655 gmux_data->indexed = true; in gmux_probe()
658 ver_major = (version >> 24) & 0xff; in gmux_probe()
659 ver_minor = (version >> 16) & 0xff; in gmux_probe()
660 ver_release = (version >> 8) & 0xff; in gmux_probe()
663 ret = -ENODEV; in gmux_probe()
668 ver_release, (gmux_data->indexed ? "indexed" : "classic")); in gmux_probe()
670 memset(&props, 0, sizeof(props)); in gmux_probe()
683 bdev = backlight_device_register("gmux_backlight", &pnp->dev, in gmux_probe()
690 gmux_data->bdev = bdev; in gmux_probe()
691 bdev->props.brightness = gmux_get_brightness(bdev); in gmux_probe()
703 gmux_data->power_state = VGA_SWITCHEROO_ON; in gmux_probe()
705 gmux_data->dhandle = ACPI_HANDLE(&pnp->dev); in gmux_probe()
706 if (!gmux_data->dhandle) { in gmux_probe()
708 dev_name(&pnp->dev)); in gmux_probe()
709 ret = -ENODEV; in gmux_probe()
713 status = acpi_evaluate_integer(gmux_data->dhandle, "GMGP", NULL, &gpe); in gmux_probe()
715 gmux_data->gpe = (int)gpe; in gmux_probe()
717 status = acpi_install_notify_handler(gmux_data->dhandle, in gmux_probe()
723 ret = -ENODEV; in gmux_probe()
727 status = acpi_enable_gpe(NULL, gmux_data->gpe); in gmux_probe()
735 gmux_data->gpe = -1; in gmux_probe()
742 gmux_data->external_switchable = in gmux_probe()
744 if (!gmux_data->external_switchable) in gmux_probe()
748 init_completion(&gmux_data->powerchange_done); in gmux_probe()
754 * and need eDP pre-calibration. They are distinguishable from in gmux_probe()
755 * pre-retinas by having an "indexed" gmux. in gmux_probe()
757 * Pre-retina MacBook Pros can switch the panel's DDC separately. in gmux_probe()
759 if (gmux_data->indexed) in gmux_probe()
770 return 0; in gmux_probe()
775 if (gmux_data->gpe >= 0) in gmux_probe()
776 acpi_disable_gpe(NULL, gmux_data->gpe); in gmux_probe()
778 if (gmux_data->gpe >= 0) in gmux_probe()
779 acpi_remove_notify_handler(gmux_data->dhandle, in gmux_probe()
785 release_region(gmux_data->iostart, gmux_data->iolen); in gmux_probe()
797 if (gmux_data->gpe >= 0) { in gmux_remove()
798 acpi_disable_gpe(NULL, gmux_data->gpe); in gmux_remove()
799 acpi_remove_notify_handler(gmux_data->dhandle, in gmux_remove()
804 backlight_device_unregister(gmux_data->bdev); in gmux_remove()
806 release_region(gmux_data->iostart, gmux_data->iolen); in gmux_remove()
815 {GMUX_ACPI_HID, 0},
816 {"", 0}
825 .name = "apple-gmux",