Files
nvbright/README.md
T
2026-08-14 13:49:01 +03:00

96 lines
3.5 KiB
Markdown

# NVbright: directly control NVIDIA-based LCD backlight brightness on Apple MacBook Air A1370
NVbright is a lightweight utility for controlling LCD backlight brightness on NVIDIA-equipped Apple MacBooks running FreeBSD under EFI boot.
## About
On older NVIDIA-based Apple MacBooks (such as the MacBook Air A1370 with GeForce 320M, MCP89, or GT218 chipsets), LCD backlight level is modulated via a Pulse Width Modulation (PWM) signal generated by the GPU display engine (`PDISPLAY`).
Under macOS or BIOS compatibility mode, firmware dynamically alters backlight brightness through System Management Interrupts (SMI) triggered by legacy I/O port writes. However, when booting FreeBSD natively in EFI mode, this legacy SMI path is unavailable, leaving the screen backlight stuck or uncontrollable via standard ACPI methods.
`nvbright` addresses this by directly interacting with the GPU MMIO register BAR:
1. Identifies the NVIDIA VGA controller's physical MMIO BAR0 address dynamically using `/usr/sbin/pciconf`.
2. Maps the register space into memory via `/dev/mem` using `mmap(2)`.
3. Detects the active Serial Output Router (SOR) with an initialized PWM divisor (`PWM_DIV`).
4. Reads and computes current duty cycle or writes new values latching the display engine registers (`PWM_CTL`).
The register mapping and control logic mirror the Linux `nouveau` driver implementation for NV50 and NVA3 chip architectures:
- `NV50_PDISP_SOR_PWM_DIV(i) = 0x0061c080 + i * 0x800`
- `NV50_PDISP_SOR_PWM_CTL(i) = 0x0061c084 + i * 0x800`
- `CTL_NEW (0x80000000)`: Latch/apply updated brightness value
- `CTL_UNK (0x40000000)`: Required control flag on NVA3-class chipsets
## Build
`nvbright` is written in standard C and relies only on standard POSIX and FreeBSD system headers (`sys/mman.h`, `sys/types.h`, `fcntl.h`, `unistd.h`). No external dependencies or third-party libraries are required.
Compile using `make`:
```sh
make
```
Or compile manually using `clang` / `cc`:
```sh
cc -O2 -Wall -Wextra -o nvbright nvbright.c
```
To install the binary system-wide to `/usr/local/bin` (respects `PREFIX` and `DESTDIR`):
```sh
sudo make install
```
## Usage
Because `nvbright` requires direct access to `/dev/mem` to map GPU MMIO registers and executes `/usr/sbin/pciconf`, it must be run as root (e.g., with `sudo` or `doas`).
### Command Syntax
```sh
nvbright <get|set|up|down> [value 0-100]
```
### Commands
- **`get`**: Queries the hardware and prints the current brightness level (percentage from 0 to 100), active SOR index, and PWM divisor.
```sh
sudo nvbright get
```
*Example Output:*
```text
Brightness: 65 / 100 (SOR1, pwm_div=1024)
```
- **`set <0-100>`**: Sets the display backlight directly to the specified percentage value.
```sh
sudo nvbright set 75
```
*Example Output:*
```text
Set brightness: 75 / 100
```
- **`up`**: Increases brightness by 10% (clamped at 100%).
```sh
sudo nvbright up
```
- **`down`**: Decreases brightness by 10% (clamped at 0%).
```sh
sudo nvbright down
```
### Desktop and Window Manager Integration
You can bind `nvbright up` and `nvbright down` commands to the brightness keys (`XF86MonBrightnessUp` and `XF86MonBrightnessDown`) in window manager configurations (such as Sway, i3, or Openbox) or configure `sudoers` / `doas.conf` rules to allow execution without password prompts.
## Credits
Created by Luxferre in 2026, released into the public domain with no warranties.
Hardware register specifications and control flow inspired by the Linux `nouveau` DRM backlight driver (`nv50` / `nva3`).