xref: /linux/drivers/platform/x86/apple-gmux.c (revision 6e7fd890f1d6ac83805409e9c346240de2705584)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *  Gmux driver for Apple laptops
4  *
5  *  Copyright (C) Canonical Ltd. <seth.forshee@canonical.com>
6  *  Copyright (C) 2010-2012 Andreas Heider <andreas@meetr.de>
7  *  Copyright (C) 2015 Lukas Wunner <lukas@wunner.de>
8  *  Copyright (C) 2023 Orlando Chamberlain <orlandoch.dev@gmail.com>
9  */
10 
11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12 
13 #include <linux/module.h>
14 #include <linux/kernel.h>
15 #include <linux/init.h>
16 #include <linux/backlight.h>
17 #include <linux/acpi.h>
18 #include <linux/pnp.h>
19 #include <linux/apple-gmux.h>
20 #include <linux/slab.h>
21 #include <linux/delay.h>
22 #include <linux/pci.h>
23 #include <linux/vga_switcheroo.h>
24 #include <linux/debugfs.h>
25 #include <acpi/video.h>
26 #include <asm/io.h>
27 
28 /**
29  * DOC: Overview
30  *
31  * gmux is a microcontroller built into the MacBook Pro to support dual GPUs:
32  * A `Lattice XP2`_ on pre-retinas, a `Renesas R4F2113`_ on pre-T2 retinas.
33  *
34  * On T2 Macbooks, the gmux is part of the T2 Coprocessor's SMC. The SMC has
35  * an I2C connection to a `NXP PCAL6524` GPIO expander, which enables/disables
36  * the voltage regulators of the discrete GPU, drives the display panel power,
37  * and has a GPIO to switch the eDP mux. The Intel CPU can interact with
38  * gmux through MMIO, similar to how the main SMC interface is controlled.
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 pre-T2
46  * retina gmux are infixed ``_index_``, and those on T2 Macs are infixed
47  * with ``_mmio_``.
48  *
49  * .. _Lattice XP2:
50  *     http://www.latticesemi.com/en/Products/FPGAandCPLD/LatticeXP2.aspx
51  * .. _Renesas R4F2113:
52  *     http://www.renesas.com/products/mpumcu/h8s/h8s2100/h8s2113/index.jsp
53  * .. _NXP PCAL6524:
54  *     https://www.nxp.com/docs/en/data-sheet/PCAL6524.pdf
55  */
56 
57 struct apple_gmux_config;
58 
59 struct apple_gmux_data {
60 	u8 __iomem *iomem_base;
61 	unsigned long iostart;
62 	unsigned long iolen;
63 	const struct apple_gmux_config *config;
64 	struct mutex index_lock;
65 
66 	struct backlight_device *bdev;
67 
68 	/* switcheroo data */
69 	acpi_handle dhandle;
70 	int gpe;
71 	bool external_switchable;
72 	enum vga_switcheroo_client_id switch_state_display;
73 	enum vga_switcheroo_client_id switch_state_ddc;
74 	enum vga_switcheroo_client_id switch_state_external;
75 	enum vga_switcheroo_state power_state;
76 	struct completion powerchange_done;
77 
78 	/* debugfs data */
79 	u8 selected_port;
80 	struct dentry *debug_dentry;
81 };
82 
83 static struct apple_gmux_data *apple_gmux_data;
84 
85 struct apple_gmux_config {
86 	u8 (*read8)(struct apple_gmux_data *gmux_data, int port);
87 	void (*write8)(struct apple_gmux_data *gmux_data, int port, u8 val);
88 	u32 (*read32)(struct apple_gmux_data *gmux_data, int port);
89 	void (*write32)(struct apple_gmux_data *gmux_data, int port, u32 val);
90 	const struct vga_switcheroo_handler *gmux_handler;
91 	enum vga_switcheroo_handler_flags_t handler_flags;
92 	unsigned long resource_type;
93 	bool read_version_as_u32;
94 	char *name;
95 };
96 
97 #define GMUX_INTERRUPT_ENABLE		0xff
98 #define GMUX_INTERRUPT_DISABLE		0x00
99 
100 #define GMUX_INTERRUPT_STATUS_ACTIVE	0
101 #define GMUX_INTERRUPT_STATUS_DISPLAY	(1 << 0)
102 #define GMUX_INTERRUPT_STATUS_POWER	(1 << 2)
103 #define GMUX_INTERRUPT_STATUS_HOTPLUG	(1 << 3)
104 
105 #define GMUX_BRIGHTNESS_MASK		0x00ffffff
106 #define GMUX_MAX_BRIGHTNESS		GMUX_BRIGHTNESS_MASK
107 
108 # define MMIO_GMUX_MAX_BRIGHTNESS	0xffff
109 
110 static u8 gmux_pio_read8(struct apple_gmux_data *gmux_data, int port)
111 {
112 	return inb(gmux_data->iostart + port);
113 }
114 
115 static void gmux_pio_write8(struct apple_gmux_data *gmux_data, int port,
116 			       u8 val)
117 {
118 	outb(val, gmux_data->iostart + port);
119 }
120 
121 static u32 gmux_pio_read32(struct apple_gmux_data *gmux_data, int port)
122 {
123 	return inl(gmux_data->iostart + port);
124 }
125 
126 static void gmux_pio_write32(struct apple_gmux_data *gmux_data, int port,
127 			     u32 val)
128 {
129 	int i;
130 	u8 tmpval;
131 
132 	for (i = 0; i < 4; i++) {
133 		tmpval = (val >> (i * 8)) & 0xff;
134 		outb(tmpval, gmux_data->iostart + port + i);
135 	}
136 }
137 
138 static int gmux_index_wait_ready(struct apple_gmux_data *gmux_data)
139 {
140 	int i = 200;
141 	u8 gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE);
142 
143 	while (i && (gwr & 0x01)) {
144 		inb(gmux_data->iostart + GMUX_PORT_READ);
145 		gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE);
146 		udelay(100);
147 		i--;
148 	}
149 
150 	return !!i;
151 }
152 
153 static int gmux_index_wait_complete(struct apple_gmux_data *gmux_data)
154 {
155 	int i = 200;
156 	u8 gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE);
157 
158 	while (i && !(gwr & 0x01)) {
159 		gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE);
160 		udelay(100);
161 		i--;
162 	}
163 
164 	if (gwr & 0x01)
165 		inb(gmux_data->iostart + GMUX_PORT_READ);
166 
167 	return !!i;
168 }
169 
170 static u8 gmux_index_read8(struct apple_gmux_data *gmux_data, int port)
171 {
172 	u8 val;
173 
174 	mutex_lock(&gmux_data->index_lock);
175 	gmux_index_wait_ready(gmux_data);
176 	outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ);
177 	gmux_index_wait_complete(gmux_data);
178 	val = inb(gmux_data->iostart + GMUX_PORT_VALUE);
179 	mutex_unlock(&gmux_data->index_lock);
180 
181 	return val;
182 }
183 
184 static void gmux_index_write8(struct apple_gmux_data *gmux_data, int port,
185 			      u8 val)
186 {
187 	mutex_lock(&gmux_data->index_lock);
188 	outb(val, gmux_data->iostart + GMUX_PORT_VALUE);
189 	gmux_index_wait_ready(gmux_data);
190 	outb(port & 0xff, gmux_data->iostart + GMUX_PORT_WRITE);
191 	gmux_index_wait_complete(gmux_data);
192 	mutex_unlock(&gmux_data->index_lock);
193 }
194 
195 static u32 gmux_index_read32(struct apple_gmux_data *gmux_data, int port)
196 {
197 	u32 val;
198 
199 	mutex_lock(&gmux_data->index_lock);
200 	gmux_index_wait_ready(gmux_data);
201 	outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ);
202 	gmux_index_wait_complete(gmux_data);
203 	val = inl(gmux_data->iostart + GMUX_PORT_VALUE);
204 	mutex_unlock(&gmux_data->index_lock);
205 
206 	return val;
207 }
208 
209 static void gmux_index_write32(struct apple_gmux_data *gmux_data, int port,
210 			       u32 val)
211 {
212 	int i;
213 	u8 tmpval;
214 
215 	mutex_lock(&gmux_data->index_lock);
216 
217 	for (i = 0; i < 4; i++) {
218 		tmpval = (val >> (i * 8)) & 0xff;
219 		outb(tmpval, gmux_data->iostart + GMUX_PORT_VALUE + i);
220 	}
221 
222 	gmux_index_wait_ready(gmux_data);
223 	outb(port & 0xff, gmux_data->iostart + GMUX_PORT_WRITE);
224 	gmux_index_wait_complete(gmux_data);
225 	mutex_unlock(&gmux_data->index_lock);
226 }
227 
228 static int gmux_mmio_wait(struct apple_gmux_data *gmux_data)
229 {
230 	int i = 200;
231 	u8 gwr = ioread8(gmux_data->iomem_base + GMUX_MMIO_COMMAND_SEND);
232 
233 	while (i && gwr) {
234 		gwr = ioread8(gmux_data->iomem_base + GMUX_MMIO_COMMAND_SEND);
235 		udelay(100);
236 		i--;
237 	}
238 
239 	return !!i;
240 }
241 
242 static u8 gmux_mmio_read8(struct apple_gmux_data *gmux_data, int port)
243 {
244 	u8 val;
245 
246 	mutex_lock(&gmux_data->index_lock);
247 	gmux_mmio_wait(gmux_data);
248 	iowrite8((port & 0xff), gmux_data->iomem_base + GMUX_MMIO_PORT_SELECT);
249 	iowrite8(GMUX_MMIO_READ | sizeof(val),
250 		gmux_data->iomem_base + GMUX_MMIO_COMMAND_SEND);
251 	gmux_mmio_wait(gmux_data);
252 	val = ioread8(gmux_data->iomem_base);
253 	mutex_unlock(&gmux_data->index_lock);
254 
255 	return val;
256 }
257 
258 static void gmux_mmio_write8(struct apple_gmux_data *gmux_data, int port,
259 			      u8 val)
260 {
261 	mutex_lock(&gmux_data->index_lock);
262 	gmux_mmio_wait(gmux_data);
263 	iowrite8(val, gmux_data->iomem_base);
264 
265 	iowrite8(port & 0xff, gmux_data->iomem_base + GMUX_MMIO_PORT_SELECT);
266 	iowrite8(GMUX_MMIO_WRITE | sizeof(val),
267 		gmux_data->iomem_base + GMUX_MMIO_COMMAND_SEND);
268 
269 	gmux_mmio_wait(gmux_data);
270 	mutex_unlock(&gmux_data->index_lock);
271 }
272 
273 static u32 gmux_mmio_read32(struct apple_gmux_data *gmux_data, int port)
274 {
275 	u32 val;
276 
277 	mutex_lock(&gmux_data->index_lock);
278 	gmux_mmio_wait(gmux_data);
279 	iowrite8((port & 0xff), gmux_data->iomem_base + GMUX_MMIO_PORT_SELECT);
280 	iowrite8(GMUX_MMIO_READ | sizeof(val),
281 		gmux_data->iomem_base + GMUX_MMIO_COMMAND_SEND);
282 	gmux_mmio_wait(gmux_data);
283 	val = ioread32be(gmux_data->iomem_base);
284 	mutex_unlock(&gmux_data->index_lock);
285 
286 	return val;
287 }
288 
289 static void gmux_mmio_write32(struct apple_gmux_data *gmux_data, int port,
290 			       u32 val)
291 {
292 	mutex_lock(&gmux_data->index_lock);
293 	iowrite32be(val, gmux_data->iomem_base);
294 	iowrite8(port & 0xff, gmux_data->iomem_base + GMUX_MMIO_PORT_SELECT);
295 	iowrite8(GMUX_MMIO_WRITE | sizeof(val),
296 		gmux_data->iomem_base + GMUX_MMIO_COMMAND_SEND);
297 	gmux_mmio_wait(gmux_data);
298 	mutex_unlock(&gmux_data->index_lock);
299 }
300 
301 static u8 gmux_read8(struct apple_gmux_data *gmux_data, int port)
302 {
303 	return gmux_data->config->read8(gmux_data, port);
304 }
305 
306 static void gmux_write8(struct apple_gmux_data *gmux_data, int port, u8 val)
307 {
308 	return gmux_data->config->write8(gmux_data, port, val);
309 }
310 
311 static u32 gmux_read32(struct apple_gmux_data *gmux_data, int port)
312 {
313 	return gmux_data->config->read32(gmux_data, port);
314 }
315 
316 static void gmux_write32(struct apple_gmux_data *gmux_data, int port,
317 			     u32 val)
318 {
319 	return gmux_data->config->write32(gmux_data, port, val);
320 }
321 
322 /**
323  * DOC: Backlight control
324  *
325  * On single GPU MacBooks, the PWM signal for the backlight is generated by
326  * the GPU. On dual GPU MacBook Pros by contrast, either GPU may be suspended
327  * to conserve energy. Hence the PWM signal needs to be generated by a separate
328  * backlight driver which is controlled by gmux. The earliest generation
329  * MBP5 2008/09 uses a `TI LP8543`_ backlight driver. Newer models
330  * use a `TI LP8545`_ or a TI LP8548.
331  *
332  * .. _TI LP8543: https://www.ti.com/lit/ds/symlink/lp8543.pdf
333  * .. _TI LP8545: https://www.ti.com/lit/ds/symlink/lp8545.pdf
334  */
335 
336 static int gmux_get_brightness(struct backlight_device *bd)
337 {
338 	struct apple_gmux_data *gmux_data = bl_get_data(bd);
339 	return gmux_read32(gmux_data, GMUX_PORT_BRIGHTNESS) &
340 	       GMUX_BRIGHTNESS_MASK;
341 }
342 
343 static int gmux_update_status(struct backlight_device *bd)
344 {
345 	struct apple_gmux_data *gmux_data = bl_get_data(bd);
346 	u32 brightness = backlight_get_brightness(bd);
347 
348 	gmux_write32(gmux_data, GMUX_PORT_BRIGHTNESS, brightness);
349 
350 	return 0;
351 }
352 
353 static const struct backlight_ops gmux_bl_ops = {
354 	.options = BL_CORE_SUSPENDRESUME,
355 	.get_brightness = gmux_get_brightness,
356 	.update_status = gmux_update_status,
357 };
358 
359 /**
360  * DOC: Graphics mux
361  *
362  * On pre-retinas, the LVDS outputs of both GPUs feed into gmux which muxes
363  * either of them to the panel. One of the tricks gmux has up its sleeve is
364  * to lengthen the blanking interval of its output during a switch to
365  * synchronize it with the GPU switched to. This allows for a flicker-free
366  * switch that is imperceptible by the user (`US 8,687,007 B2`_).
367  *
368  * On retinas, muxing is no longer done by gmux itself, but by a separate
369  * chip which is controlled by gmux. The chip is triple sourced, it is
370  * either an `NXP CBTL06142`_, `TI HD3SS212`_ or `Pericom PI3VDP12412`_.
371  * The panel is driven with eDP instead of LVDS since the pixel clock
372  * required for retina resolution exceeds LVDS' limits.
373  *
374  * Pre-retinas are able to switch the panel's DDC pins separately.
375  * This is handled by a `TI SN74LV4066A`_ which is controlled by gmux.
376  * The inactive GPU can thus probe the panel's EDID without switching over
377  * the entire panel. Retinas lack this functionality as the chips used for
378  * eDP muxing are incapable of switching the AUX channel separately (see
379  * the linked data sheets, Pericom would be capable but this is unused).
380  * However the retina panel has the NO_AUX_HANDSHAKE_LINK_TRAINING bit set
381  * in its DPCD, allowing the inactive GPU to skip the AUX handshake and
382  * set up the output with link parameters pre-calibrated by the active GPU.
383  *
384  * The external DP port is only fully switchable on the first two unibody
385  * MacBook Pro generations, MBP5 2008/09 and MBP6 2010. This is done by an
386  * `NXP CBTL06141`_ which is controlled by gmux. It's the predecessor of the
387  * eDP mux on retinas, the difference being support for 2.7 versus 5.4 Gbit/s.
388  *
389  * The following MacBook Pro generations replaced the external DP port with a
390  * combined DP/Thunderbolt port and lost the ability to switch it between GPUs,
391  * connecting it either to the discrete GPU or the Thunderbolt controller.
392  * Oddly enough, while the full port is no longer switchable, AUX and HPD
393  * are still switchable by way of an `NXP CBTL03062`_ (on pre-retinas
394  * MBP8 2011 and MBP9 2012) or two `TI TS3DS10224`_ (on pre-t2 retinas) under
395  * the control of gmux. Since the integrated GPU is missing the main link,
396  * external displays appear to it as phantoms which fail to link-train.
397  *
398  * gmux receives the HPD signal of all display connectors and sends an
399  * interrupt on hotplug. On generations which cannot switch external ports,
400  * the discrete GPU can then be woken to drive the newly connected display.
401  * The ability to switch AUX on these generations could be used to improve
402  * reliability of hotplug detection by having the integrated GPU poll the
403  * ports while the discrete GPU is asleep, but currently we do not make use
404  * of this feature.
405  *
406  * Our switching policy for the external port is that on those generations
407  * which are able to switch it fully, the port is switched together with the
408  * panel when IGD / DIS commands are issued to vga_switcheroo. It is thus
409  * possible to drive e.g. a beamer on battery power with the integrated GPU.
410  * The user may manually switch to the discrete GPU if more performance is
411  * needed.
412  *
413  * On all newer generations, the external port can only be driven by the
414  * discrete GPU. If a display is plugged in while the panel is switched to
415  * the integrated GPU, *both* GPUs will be in use for maximum performance.
416  * To decrease power consumption, the user may manually switch to the
417  * discrete GPU, thereby suspending the integrated GPU.
418  *
419  * gmux' initial switch state on bootup is user configurable via the EFI
420  * variable ``gpu-power-prefs-fa4ce28d-b62f-4c99-9cc3-6815686e30f9`` (5th byte,
421  * 1 = IGD, 0 = DIS). Based on this setting, the EFI firmware tells gmux to
422  * switch the panel and the external DP connector and allocates a framebuffer
423  * for the selected GPU.
424  *
425  * .. _US 8,687,007 B2: https://pimg-fpiw.uspto.gov/fdd/07/870/086/0.pdf
426  * .. _NXP CBTL06141:   https://www.nxp.com/documents/data_sheet/CBTL06141.pdf
427  * .. _NXP CBTL06142:   https://www.nxp.com/documents/data_sheet/CBTL06141.pdf
428  * .. _TI HD3SS212:     https://www.ti.com/lit/ds/symlink/hd3ss212.pdf
429  * .. _Pericom PI3VDP12412: https://www.pericom.com/assets/Datasheets/PI3VDP12412.pdf
430  * .. _TI SN74LV4066A:  https://www.ti.com/lit/ds/symlink/sn74lv4066a.pdf
431  * .. _NXP CBTL03062:   http://pdf.datasheetarchive.com/indexerfiles/Datasheets-SW16/DSASW00308511.pdf
432  * .. _TI TS3DS10224:   https://www.ti.com/lit/ds/symlink/ts3ds10224.pdf
433  */
434 
435 static void gmux_read_switch_state(struct apple_gmux_data *gmux_data)
436 {
437 	if (gmux_read8(gmux_data, GMUX_PORT_SWITCH_DDC) == 1)
438 		gmux_data->switch_state_ddc = VGA_SWITCHEROO_IGD;
439 	else
440 		gmux_data->switch_state_ddc = VGA_SWITCHEROO_DIS;
441 
442 	if (gmux_read8(gmux_data, GMUX_PORT_SWITCH_DISPLAY) & 1)
443 		gmux_data->switch_state_display = VGA_SWITCHEROO_DIS;
444 	else
445 		gmux_data->switch_state_display = VGA_SWITCHEROO_IGD;
446 
447 	if (gmux_read8(gmux_data, GMUX_PORT_SWITCH_EXTERNAL) == 2)
448 		gmux_data->switch_state_external = VGA_SWITCHEROO_IGD;
449 	else
450 		gmux_data->switch_state_external = VGA_SWITCHEROO_DIS;
451 }
452 
453 static void gmux_write_switch_state(struct apple_gmux_data *gmux_data)
454 {
455 	if (gmux_data->switch_state_ddc == VGA_SWITCHEROO_IGD)
456 		gmux_write8(gmux_data, GMUX_PORT_SWITCH_DDC, 1);
457 	else
458 		gmux_write8(gmux_data, GMUX_PORT_SWITCH_DDC, 2);
459 
460 	if (gmux_data->switch_state_display == VGA_SWITCHEROO_IGD)
461 		gmux_write8(gmux_data, GMUX_PORT_SWITCH_DISPLAY, 2);
462 	else
463 		gmux_write8(gmux_data, GMUX_PORT_SWITCH_DISPLAY, 3);
464 
465 	if (gmux_data->switch_state_external == VGA_SWITCHEROO_IGD)
466 		gmux_write8(gmux_data, GMUX_PORT_SWITCH_EXTERNAL, 2);
467 	else
468 		gmux_write8(gmux_data, GMUX_PORT_SWITCH_EXTERNAL, 3);
469 }
470 
471 static int gmux_switchto(enum vga_switcheroo_client_id id)
472 {
473 	apple_gmux_data->switch_state_ddc = id;
474 	apple_gmux_data->switch_state_display = id;
475 	if (apple_gmux_data->external_switchable)
476 		apple_gmux_data->switch_state_external = id;
477 
478 	gmux_write_switch_state(apple_gmux_data);
479 
480 	return 0;
481 }
482 
483 static int gmux_switch_ddc(enum vga_switcheroo_client_id id)
484 {
485 	enum vga_switcheroo_client_id old_ddc_owner =
486 		apple_gmux_data->switch_state_ddc;
487 
488 	if (id == old_ddc_owner)
489 		return id;
490 
491 	pr_debug("Switching DDC from %d to %d\n", old_ddc_owner, id);
492 	apple_gmux_data->switch_state_ddc = id;
493 
494 	if (id == VGA_SWITCHEROO_IGD)
495 		gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 1);
496 	else
497 		gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 2);
498 
499 	return old_ddc_owner;
500 }
501 
502 /**
503  * DOC: Power control
504  *
505  * gmux is able to cut power to the discrete GPU. It automatically takes care
506  * of the correct sequence to tear down and bring up the power rails for
507  * core voltage, VRAM and PCIe.
508  */
509 
510 static int gmux_set_discrete_state(struct apple_gmux_data *gmux_data,
511 				   enum vga_switcheroo_state state)
512 {
513 	reinit_completion(&gmux_data->powerchange_done);
514 
515 	if (state == VGA_SWITCHEROO_ON) {
516 		gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 1);
517 		gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 3);
518 		pr_debug("Discrete card powered up\n");
519 	} else {
520 		gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 1);
521 		gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 0);
522 		pr_debug("Discrete card powered down\n");
523 	}
524 
525 	gmux_data->power_state = state;
526 
527 	if (gmux_data->gpe >= 0 &&
528 	    !wait_for_completion_interruptible_timeout(&gmux_data->powerchange_done,
529 						       msecs_to_jiffies(200)))
530 		pr_warn("Timeout waiting for gmux switch to complete\n");
531 
532 	return 0;
533 }
534 
535 static int gmux_set_power_state(enum vga_switcheroo_client_id id,
536 				enum vga_switcheroo_state state)
537 {
538 	if (id == VGA_SWITCHEROO_IGD)
539 		return 0;
540 
541 	return gmux_set_discrete_state(apple_gmux_data, state);
542 }
543 
544 static enum vga_switcheroo_client_id gmux_get_client_id(struct pci_dev *pdev)
545 {
546 	/*
547 	 * Early Macbook Pros with switchable graphics use nvidia
548 	 * integrated graphics. Hardcode that the 9400M is integrated.
549 	 */
550 	if (pdev->vendor == PCI_VENDOR_ID_INTEL)
551 		return VGA_SWITCHEROO_IGD;
552 	else if (pdev->vendor == PCI_VENDOR_ID_NVIDIA &&
553 		 pdev->device == 0x0863)
554 		return VGA_SWITCHEROO_IGD;
555 	else
556 		return VGA_SWITCHEROO_DIS;
557 }
558 
559 static const struct vga_switcheroo_handler gmux_handler_no_ddc = {
560 	.switchto = gmux_switchto,
561 	.power_state = gmux_set_power_state,
562 	.get_client_id = gmux_get_client_id,
563 };
564 
565 static const struct vga_switcheroo_handler gmux_handler_ddc = {
566 	.switchto = gmux_switchto,
567 	.switch_ddc = gmux_switch_ddc,
568 	.power_state = gmux_set_power_state,
569 	.get_client_id = gmux_get_client_id,
570 };
571 
572 static const struct apple_gmux_config apple_gmux_pio = {
573 	.read8 = &gmux_pio_read8,
574 	.write8 = &gmux_pio_write8,
575 	.read32 = &gmux_pio_read32,
576 	.write32 = &gmux_pio_write32,
577 	.gmux_handler = &gmux_handler_ddc,
578 	.handler_flags = VGA_SWITCHEROO_CAN_SWITCH_DDC,
579 	.resource_type = IORESOURCE_IO,
580 	.read_version_as_u32 = false,
581 	.name = "classic"
582 };
583 
584 static const struct apple_gmux_config apple_gmux_index = {
585 	.read8 = &gmux_index_read8,
586 	.write8 = &gmux_index_write8,
587 	.read32 = &gmux_index_read32,
588 	.write32 = &gmux_index_write32,
589 	.gmux_handler = &gmux_handler_no_ddc,
590 	.handler_flags = VGA_SWITCHEROO_NEEDS_EDP_CONFIG,
591 	.resource_type = IORESOURCE_IO,
592 	.read_version_as_u32 = true,
593 	.name = "indexed"
594 };
595 
596 static const struct apple_gmux_config apple_gmux_mmio = {
597 	.read8 = &gmux_mmio_read8,
598 	.write8 = &gmux_mmio_write8,
599 	.read32 = &gmux_mmio_read32,
600 	.write32 = &gmux_mmio_write32,
601 	.gmux_handler = &gmux_handler_no_ddc,
602 	.handler_flags = VGA_SWITCHEROO_NEEDS_EDP_CONFIG,
603 	.resource_type = IORESOURCE_MEM,
604 	.read_version_as_u32 = true,
605 	.name = "T2"
606 };
607 
608 
609 /**
610  * DOC: Interrupt
611  *
612  * gmux is also connected to a GPIO pin of the southbridge and thereby is able
613  * to trigger an ACPI GPE. ACPI name GMGP holds this GPIO pin's number. On the
614  * MBP5 2008/09 it's GPIO pin 22 of the Nvidia MCP79, on following generations
615  * it's GPIO pin 6 of the Intel PCH, on MMIO gmux's it's pin 21.
616  *
617  * The GPE merely signals that an interrupt occurred, the actual type of event
618  * is identified by reading a gmux register.
619  *
620  * In addition to the GMGP name, gmux's ACPI device also has two methods GMSP
621  * and GMLV. GMLV likely means "GMUX Level", and reads the value of the GPIO,
622  * while GMSP likely means "GMUX Set Polarity", and seems to write to the GPIO's
623  * value. On newer Macbooks (This was introduced with or sometime before the
624  * MacBookPro14,3), the ACPI GPE method differentiates between the OS type: On
625  * Darwin, only a notification is signaled, whereas on other OSes, the GPIO's
626  * value is read and then inverted.
627  *
628  * Because Linux masquerades as Darwin, it ends up in the notification-only code
629  * path. On MMIO gmux's, this seems to lead to us being unable to clear interrupts,
630  * unless we call GMSP(0). Without this, there is a flood of status=0 interrupts
631  * that can't be cleared. This issue seems to be unique to MMIO gmux's.
632  */
633 
634 static inline void gmux_disable_interrupts(struct apple_gmux_data *gmux_data)
635 {
636 	gmux_write8(gmux_data, GMUX_PORT_INTERRUPT_ENABLE,
637 		    GMUX_INTERRUPT_DISABLE);
638 }
639 
640 static inline void gmux_enable_interrupts(struct apple_gmux_data *gmux_data)
641 {
642 	gmux_write8(gmux_data, GMUX_PORT_INTERRUPT_ENABLE,
643 		    GMUX_INTERRUPT_ENABLE);
644 }
645 
646 static inline u8 gmux_interrupt_get_status(struct apple_gmux_data *gmux_data)
647 {
648 	return gmux_read8(gmux_data, GMUX_PORT_INTERRUPT_STATUS);
649 }
650 
651 static void gmux_clear_interrupts(struct apple_gmux_data *gmux_data)
652 {
653 	u8 status;
654 
655 	/* to clear interrupts write back current status */
656 	status = gmux_interrupt_get_status(gmux_data);
657 	gmux_write8(gmux_data, GMUX_PORT_INTERRUPT_STATUS, status);
658 	/* Prevent flood of status=0 interrupts */
659 	if (gmux_data->config == &apple_gmux_mmio)
660 		acpi_execute_simple_method(gmux_data->dhandle, "GMSP", 0);
661 }
662 
663 static void gmux_notify_handler(acpi_handle device, u32 value, void *context)
664 {
665 	u8 status;
666 	struct pnp_dev *pnp = (struct pnp_dev *)context;
667 	struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp);
668 
669 	status = gmux_interrupt_get_status(gmux_data);
670 	gmux_disable_interrupts(gmux_data);
671 	pr_debug("Notify handler called: status %d\n", status);
672 
673 	gmux_clear_interrupts(gmux_data);
674 	gmux_enable_interrupts(gmux_data);
675 
676 	if (status & GMUX_INTERRUPT_STATUS_POWER)
677 		complete(&gmux_data->powerchange_done);
678 }
679 
680 /**
681  * DOC: Debugfs Interface
682  *
683  * gmux ports can be accessed from userspace as a debugfs interface. For example:
684  *
685  * # echo 4 > /sys/kernel/debug/apple_gmux/selected_port
686  * # cat /sys/kernel/debug/apple_gmux/selected_port_data | xxd -p
687  * 00000005
688  *
689  * Reads 4 bytes from port 4 (GMUX_PORT_VERSION_MAJOR).
690  *
691  * 1 and 4 byte writes are also allowed.
692  */
693 
694 static ssize_t gmux_selected_port_data_write(struct file *file,
695 		const char __user *userbuf, size_t count, loff_t *ppos)
696 {
697 	struct apple_gmux_data *gmux_data = file->private_data;
698 
699 	if (*ppos)
700 		return -EINVAL;
701 
702 	if (count == 1) {
703 		u8 data;
704 
705 		if (copy_from_user(&data, userbuf, 1))
706 			return -EFAULT;
707 
708 		gmux_write8(gmux_data, gmux_data->selected_port, data);
709 	} else if (count == 4) {
710 		u32 data;
711 
712 		if (copy_from_user(&data, userbuf, 4))
713 			return -EFAULT;
714 
715 		gmux_write32(gmux_data, gmux_data->selected_port, data);
716 	} else
717 		return -EINVAL;
718 
719 	return count;
720 }
721 
722 static ssize_t gmux_selected_port_data_read(struct file *file,
723 		char __user *userbuf, size_t count, loff_t *ppos)
724 {
725 	struct apple_gmux_data *gmux_data = file->private_data;
726 	u32 data;
727 
728 	data = gmux_read32(gmux_data, gmux_data->selected_port);
729 
730 	return simple_read_from_buffer(userbuf, count, ppos, &data, sizeof(data));
731 }
732 
733 static const struct file_operations gmux_port_data_ops = {
734 	.open = simple_open,
735 	.write = gmux_selected_port_data_write,
736 	.read = gmux_selected_port_data_read
737 };
738 
739 static void gmux_init_debugfs(struct apple_gmux_data *gmux_data)
740 {
741 	gmux_data->debug_dentry = debugfs_create_dir(KBUILD_MODNAME, NULL);
742 
743 	debugfs_create_u8("selected_port", 0644, gmux_data->debug_dentry,
744 			&gmux_data->selected_port);
745 	debugfs_create_file("selected_port_data", 0644, gmux_data->debug_dentry,
746 			gmux_data, &gmux_port_data_ops);
747 }
748 
749 static void gmux_fini_debugfs(struct apple_gmux_data *gmux_data)
750 {
751 	debugfs_remove_recursive(gmux_data->debug_dentry);
752 }
753 
754 static int gmux_suspend(struct device *dev)
755 {
756 	struct pnp_dev *pnp = to_pnp_dev(dev);
757 	struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp);
758 
759 	gmux_disable_interrupts(gmux_data);
760 	return 0;
761 }
762 
763 static int gmux_resume(struct device *dev)
764 {
765 	struct pnp_dev *pnp = to_pnp_dev(dev);
766 	struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp);
767 
768 	gmux_enable_interrupts(gmux_data);
769 	gmux_write_switch_state(gmux_data);
770 	if (gmux_data->power_state == VGA_SWITCHEROO_OFF)
771 		gmux_set_discrete_state(gmux_data, gmux_data->power_state);
772 	return 0;
773 }
774 
775 static int is_thunderbolt(struct device *dev, void *data)
776 {
777 	return to_pci_dev(dev)->is_thunderbolt;
778 }
779 
780 static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
781 {
782 	struct apple_gmux_data *gmux_data;
783 	struct resource *res;
784 	struct backlight_properties props;
785 	struct backlight_device *bdev = NULL;
786 	u8 ver_major, ver_minor, ver_release;
787 	bool register_bdev = true;
788 	int ret = -ENXIO;
789 	acpi_status status;
790 	unsigned long long gpe;
791 	enum apple_gmux_type type;
792 	u32 version;
793 
794 	if (apple_gmux_data)
795 		return -EBUSY;
796 
797 	if (!apple_gmux_detect(pnp, &type)) {
798 		pr_info("gmux device not present\n");
799 		return -ENODEV;
800 	}
801 
802 	gmux_data = kzalloc(sizeof(*gmux_data), GFP_KERNEL);
803 	if (!gmux_data)
804 		return -ENOMEM;
805 	pnp_set_drvdata(pnp, gmux_data);
806 
807 	switch (type) {
808 	case APPLE_GMUX_TYPE_MMIO:
809 		gmux_data->config = &apple_gmux_mmio;
810 		mutex_init(&gmux_data->index_lock);
811 
812 		res = pnp_get_resource(pnp, IORESOURCE_MEM, 0);
813 		gmux_data->iostart = res->start;
814 		/* Although the ACPI table only allocates 8 bytes, we need 16. */
815 		gmux_data->iolen = 16;
816 		if (!request_mem_region(gmux_data->iostart, gmux_data->iolen,
817 					"Apple gmux")) {
818 			pr_err("gmux I/O already in use\n");
819 			goto err_free;
820 		}
821 		gmux_data->iomem_base = ioremap(gmux_data->iostart, gmux_data->iolen);
822 		if (!gmux_data->iomem_base) {
823 			pr_err("couldn't remap gmux mmio region");
824 			goto err_release;
825 		}
826 		goto get_version;
827 	case APPLE_GMUX_TYPE_INDEXED:
828 		gmux_data->config = &apple_gmux_index;
829 		mutex_init(&gmux_data->index_lock);
830 		break;
831 	case APPLE_GMUX_TYPE_PIO:
832 		gmux_data->config = &apple_gmux_pio;
833 		break;
834 	}
835 
836 	res = pnp_get_resource(pnp, IORESOURCE_IO, 0);
837 	gmux_data->iostart = res->start;
838 	gmux_data->iolen = resource_size(res);
839 
840 	if (!request_region(gmux_data->iostart, gmux_data->iolen,
841 			    "Apple gmux")) {
842 		pr_err("gmux I/O already in use\n");
843 		goto err_free;
844 	}
845 
846 get_version:
847 	if (gmux_data->config->read_version_as_u32) {
848 		version = gmux_read32(gmux_data, GMUX_PORT_VERSION_MAJOR);
849 		ver_major = (version >> 24) & 0xff;
850 		ver_minor = (version >> 16) & 0xff;
851 		ver_release = (version >> 8) & 0xff;
852 	} else {
853 		ver_major = gmux_read8(gmux_data, GMUX_PORT_VERSION_MAJOR);
854 		ver_minor = gmux_read8(gmux_data, GMUX_PORT_VERSION_MINOR);
855 		ver_release = gmux_read8(gmux_data, GMUX_PORT_VERSION_RELEASE);
856 	}
857 	pr_info("Found gmux version %d.%d.%d [%s]\n", ver_major, ver_minor,
858 		ver_release, gmux_data->config->name);
859 
860 	memset(&props, 0, sizeof(props));
861 	props.type = BACKLIGHT_PLATFORM;
862 
863 	/*
864 	 * All MMIO gmux's have 0xffff as max brightness, but some iMacs incorrectly
865 	 * report 0x03ff, despite the firmware being happy to set 0xffff as the brightness
866 	 * at boot. Force 0xffff for all MMIO gmux's so they all have the correct brightness
867 	 * range.
868 	 */
869 	if (type == APPLE_GMUX_TYPE_MMIO)
870 		props.max_brightness = MMIO_GMUX_MAX_BRIGHTNESS;
871 	else
872 		props.max_brightness = gmux_read32(gmux_data, GMUX_PORT_MAX_BRIGHTNESS);
873 
874 #if IS_REACHABLE(CONFIG_ACPI_VIDEO)
875 	register_bdev = acpi_video_get_backlight_type() == acpi_backlight_apple_gmux;
876 #endif
877 	if (register_bdev) {
878 		/*
879 		 * Currently it's assumed that the maximum brightness is less than
880 		 * 2^24 for compatibility with old gmux versions. Cap the max
881 		 * brightness at this value, but print a warning if the hardware
882 		 * reports something higher so that it can be fixed.
883 		 */
884 		if (WARN_ON(props.max_brightness > GMUX_MAX_BRIGHTNESS))
885 			props.max_brightness = GMUX_MAX_BRIGHTNESS;
886 
887 		bdev = backlight_device_register("gmux_backlight", &pnp->dev,
888 						 gmux_data, &gmux_bl_ops, &props);
889 		if (IS_ERR(bdev)) {
890 			ret = PTR_ERR(bdev);
891 			goto err_unmap;
892 		}
893 
894 		gmux_data->bdev = bdev;
895 		bdev->props.brightness = gmux_get_brightness(bdev);
896 		backlight_update_status(bdev);
897 	}
898 
899 	gmux_data->power_state = VGA_SWITCHEROO_ON;
900 
901 	gmux_data->dhandle = ACPI_HANDLE(&pnp->dev);
902 	if (!gmux_data->dhandle) {
903 		pr_err("Cannot find acpi handle for pnp device %s\n",
904 		       dev_name(&pnp->dev));
905 		ret = -ENODEV;
906 		goto err_notify;
907 	}
908 
909 	status = acpi_evaluate_integer(gmux_data->dhandle, "GMGP", NULL, &gpe);
910 	if (ACPI_SUCCESS(status)) {
911 		gmux_data->gpe = (int)gpe;
912 
913 		status = acpi_install_notify_handler(gmux_data->dhandle,
914 						     ACPI_DEVICE_NOTIFY,
915 						     &gmux_notify_handler, pnp);
916 		if (ACPI_FAILURE(status)) {
917 			pr_err("Install notify handler failed: %s\n",
918 			       acpi_format_exception(status));
919 			ret = -ENODEV;
920 			goto err_notify;
921 		}
922 
923 		status = acpi_enable_gpe(NULL, gmux_data->gpe);
924 		if (ACPI_FAILURE(status)) {
925 			pr_err("Cannot enable gpe: %s\n",
926 			       acpi_format_exception(status));
927 			goto err_enable_gpe;
928 		}
929 	} else {
930 		pr_warn("No GPE found for gmux\n");
931 		gmux_data->gpe = -1;
932 	}
933 
934 	/*
935 	 * If Thunderbolt is present, the external DP port is not fully
936 	 * switchable. Force its AUX channel to the discrete GPU.
937 	 */
938 	gmux_data->external_switchable =
939 		!bus_for_each_dev(&pci_bus_type, NULL, NULL, is_thunderbolt);
940 	if (!gmux_data->external_switchable)
941 		gmux_write8(gmux_data, GMUX_PORT_SWITCH_EXTERNAL, 3);
942 
943 	apple_gmux_data = gmux_data;
944 	init_completion(&gmux_data->powerchange_done);
945 	gmux_enable_interrupts(gmux_data);
946 	gmux_read_switch_state(gmux_data);
947 
948 	/*
949 	 * Retina MacBook Pros cannot switch the panel's AUX separately
950 	 * and need eDP pre-calibration. They are distinguishable from
951 	 * pre-retinas by having an "indexed" or "T2" gmux.
952 	 *
953 	 * Pre-retina MacBook Pros can switch the panel's DDC separately.
954 	 */
955 	ret = vga_switcheroo_register_handler(gmux_data->config->gmux_handler,
956 			gmux_data->config->handler_flags);
957 	if (ret) {
958 		pr_err("Failed to register vga_switcheroo handler\n");
959 		goto err_register_handler;
960 	}
961 
962 	gmux_init_debugfs(gmux_data);
963 	return 0;
964 
965 err_register_handler:
966 	gmux_disable_interrupts(gmux_data);
967 	apple_gmux_data = NULL;
968 	if (gmux_data->gpe >= 0)
969 		acpi_disable_gpe(NULL, gmux_data->gpe);
970 err_enable_gpe:
971 	if (gmux_data->gpe >= 0)
972 		acpi_remove_notify_handler(gmux_data->dhandle,
973 					   ACPI_DEVICE_NOTIFY,
974 					   &gmux_notify_handler);
975 err_notify:
976 	backlight_device_unregister(bdev);
977 err_unmap:
978 	if (gmux_data->iomem_base)
979 		iounmap(gmux_data->iomem_base);
980 err_release:
981 	if (gmux_data->config->resource_type == IORESOURCE_MEM)
982 		release_mem_region(gmux_data->iostart, gmux_data->iolen);
983 	else
984 		release_region(gmux_data->iostart, gmux_data->iolen);
985 err_free:
986 	kfree(gmux_data);
987 	return ret;
988 }
989 
990 static void gmux_remove(struct pnp_dev *pnp)
991 {
992 	struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp);
993 
994 	gmux_fini_debugfs(gmux_data);
995 	vga_switcheroo_unregister_handler();
996 	gmux_disable_interrupts(gmux_data);
997 	if (gmux_data->gpe >= 0) {
998 		acpi_disable_gpe(NULL, gmux_data->gpe);
999 		acpi_remove_notify_handler(gmux_data->dhandle,
1000 					   ACPI_DEVICE_NOTIFY,
1001 					   &gmux_notify_handler);
1002 	}
1003 
1004 	backlight_device_unregister(gmux_data->bdev);
1005 
1006 	if (gmux_data->iomem_base) {
1007 		iounmap(gmux_data->iomem_base);
1008 		release_mem_region(gmux_data->iostart, gmux_data->iolen);
1009 	} else
1010 		release_region(gmux_data->iostart, gmux_data->iolen);
1011 	apple_gmux_data = NULL;
1012 	kfree(gmux_data);
1013 }
1014 
1015 static const struct pnp_device_id gmux_device_ids[] = {
1016 	{GMUX_ACPI_HID, 0},
1017 	{"", 0}
1018 };
1019 
1020 static const struct dev_pm_ops gmux_dev_pm_ops = {
1021 	.suspend = gmux_suspend,
1022 	.resume = gmux_resume,
1023 };
1024 
1025 static struct pnp_driver gmux_pnp_driver = {
1026 	.name		= "apple-gmux",
1027 	.probe		= gmux_probe,
1028 	.remove		= gmux_remove,
1029 	.id_table	= gmux_device_ids,
1030 	.driver		= {
1031 			.pm = &gmux_dev_pm_ops,
1032 	},
1033 };
1034 
1035 module_pnp_driver(gmux_pnp_driver);
1036 MODULE_AUTHOR("Seth Forshee <seth.forshee@canonical.com>");
1037 MODULE_DESCRIPTION("Apple Gmux Driver");
1038 MODULE_LICENSE("GPL");
1039 MODULE_DEVICE_TABLE(pnp, gmux_device_ids);
1040