1 /* 2 * Copyright (c) 2026 Abdelkader Boudih <seuros@FreeBSD.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7 /* 8 * acpi_apple(4) - FreeBSD driver for Apple platform ACPI devices. 9 * 10 * Handles multiple Apple ACPI devices with a single driver: 11 * 12 * APP000B (GMUX) / APP9876 (PCH PMC) - platform instance: 13 * - Wake-on-LAN: walk ACPI namespace on shutdown, call _PSW(1) on 14 * any device with ACPI_FLAG_WAKE_ENABLED (dev.X.Y.wake=1). 15 * - Lid state: follow acpi_lid_event to blank and restore the 16 * backlight. 17 * 18 * APP0002 (PNLF) - backlight instance: 19 * - Panel backlight control via GPU PCI BAR MMIO registers. 20 * - Supports Intel PCH/CPU, Nvidia NV40/NV50, AMD R600+ families. 21 * - Registers with backlight(9) framework. 22 * 23 * OSDW() gates on OSYS==0x2710 ("Darwin"), installed via 24 * hw.acpi.apple_darwin_osi=1. _PSW on GIGE only fires if the bge(4) 25 * instance has ACPI_FLAG_WAKE_ENABLED (dev.bge.X.wake=1). 26 */ 27 28 #include <sys/cdefs.h> 29 #include "opt_acpi.h" 30 #include "apple_acpi.h" 31 32 #include "backlight_if.h" 33 34 #define _COMPONENT ACPI_OEM 35 ACPI_MODULE_NAME("Apple") 36 37 /* 38 * Attach to APP9876 (PCH PMC, T2 Macs), APP000B (GMUX, discrete GPU 39 * Macs), or APP0002 (panel backlight, all Intel Macs with display). 40 * APP0001 (SMC) is owned by asmc(4). 41 * 42 * BUS_PROBE_LOW_PRIORITY so a future apple_gmux driver can claim 43 * APP000B at default priority. 44 */ 45 static char *acpi_apple_ids[] = { "APP9876", "APP000B", "APP0002", NULL }; 46 47 static int 48 acpi_apple_probe(device_t dev) 49 { 50 int rv; 51 52 if (acpi_disabled("apple")) 53 return (ENXIO); 54 rv = ACPI_ID_PROBE(device_get_parent(dev), dev, acpi_apple_ids, NULL); 55 if (rv > 0) 56 return (rv); 57 58 if (acpi_MatchHid(acpi_get_handle(dev), "APP0002")) 59 device_set_desc(dev, "Apple Panel Backlight"); 60 else 61 device_set_desc(dev, "Apple platform controller"); 62 63 return (BUS_PROBE_LOW_PRIORITY); 64 } 65 66 static int 67 acpi_apple_attach(device_t dev) 68 { 69 struct acpi_apple_softc *sc; 70 71 sc = device_get_softc(dev); 72 sc->dev = dev; 73 sc->handle = acpi_get_handle(dev); 74 75 if (acpi_MatchHid(sc->handle, "APP0002")) 76 sc->mode = ACPI_APPLE_BACKLIGHT; 77 else 78 sc->mode = ACPI_APPLE_PLATFORM; 79 80 if (sc->mode == ACPI_APPLE_PLATFORM) 81 return (acpi_apple_platform_attach(sc)); 82 else 83 return (acpi_apple_backlight_attach(sc)); 84 } 85 86 static int 87 acpi_apple_detach(device_t dev) 88 { 89 struct acpi_apple_softc *sc; 90 91 sc = device_get_softc(dev); 92 if (sc->mode == ACPI_APPLE_PLATFORM) 93 acpi_apple_platform_detach(sc); 94 else 95 acpi_apple_backlight_detach(sc); 96 return (0); 97 } 98 99 static device_method_t acpi_apple_methods[] = { 100 DEVMETHOD(device_probe, acpi_apple_probe), 101 DEVMETHOD(device_attach, acpi_apple_attach), 102 DEVMETHOD(device_detach, acpi_apple_detach), 103 104 DEVMETHOD(backlight_update_status, acpi_apple_bl_update_status), 105 DEVMETHOD(backlight_get_status, acpi_apple_bl_get_status), 106 DEVMETHOD(backlight_get_info, acpi_apple_bl_get_info), 107 108 DEVMETHOD_END 109 }; 110 111 static driver_t acpi_apple_driver = { 112 "acpi_apple", 113 acpi_apple_methods, 114 sizeof(struct acpi_apple_softc), 115 }; 116 117 DRIVER_MODULE(acpi_apple, acpi, acpi_apple_driver, 0, 0); 118 MODULE_DEPEND(acpi_apple, acpi, 1, 1, 1); 119 MODULE_DEPEND(acpi_apple, backlight, 1, 1, 1); 120 MODULE_VERSION(acpi_apple, 1); 121