xref: /freebsd/sys/dev/apple_acpi/apple_acpi.c (revision c4fde87a3236b500246d4fce76dbca2a3d64f73a)
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