apple-gmux.c 31 KB

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