feat: power down dGPUs on hybrid graphics laptops

This commit is contained in:
daniel committed 2026-10-01 13:09:26 +02:00
1 parent 7f12e1a150
commit 24f88ec4c6
23 files changed
+4325 -1130

No files matched your search

+92
View File
@@ -0,0 +1,92 @@
/*
* AcpiPower.hpp
* ACPI device power management: _PSx methods, _PRx power resources,
* _DSM calls, and finding the namespace node behind a PCI function
* Copyright (c) 2026 Daniel Hammer
*/
#pragma once
#include <cstdint>
#include <ACPI/AML/AmlNamespace.hpp>
namespace Hal {
namespace AcpiPower {
// ============================================================================
// PCI <-> ACPI
// ============================================================================
// The Device node describing PCI function bus:dev.fn, or -1. When
// firmware declares more than one node at the same address (a generic
// placeholder plus a vendor SSDT's real one is common for GPUs), the
// one carrying power-management objects wins.
int32_t FindPciDevice(uint8_t bus, uint8_t dev, uint8_t fn);
// Forget the PCI address map built by FindPciDevice (bus numbers may
// change across a resume).
void InvalidatePciMap();
// True when `device` has a child object named `name` ("_PS3").
bool HasObject(int32_t device, const char* name);
// ============================================================================
// Power resources
// ============================================================================
static constexpr int MaxResources = 8;
// The power resources the device lists in _PR0.._PR3 (deduplicated).
int CollectResources(int32_t device, int32_t* out, int max);
// _STA of a power resource: 1 on, 0 off, -1 unknown.
int ResourceState(int32_t resource);
// ============================================================================
// Device power transitions
// ============================================================================
struct D3ColdReport {
bool RanPs3;
int ResourcesOff; // resources whose _OFF was run
int ResourcesShared; // left on: some other present device needs them
int ResourcesStillOn; // _OFF ran but _STA still says on
};
// Put an ACPI device into D3cold the way the spec orders it: _PS3,
// then every power resource it depends on off, last-listed first. A
// resource that a device outside `owners` also depends on is left
// on -- `owners` lists the nodes being powered down together (the
// functions of one card and the port above them), which may freely
// share, as may anything below them in the namespace. The PCI side
// (PMCSR to D3hot) is the caller's to do first.
void EnterD3Cold(int32_t device, const int32_t* owners, int ownerCount,
D3ColdReport& report);
// ============================================================================
// _DSM
// ============================================================================
// Evaluate _DSM(uuid, revision, function, arg3) on a device. False
// when the device has no _DSM or it failed.
bool EvaluateDsm(int32_t device, const uint8_t uuid[16], uint64_t revision,
uint64_t function, const AML::Object& arg3, AML::Object& result);
// The function bitmap _DSM function 0 reports for (uuid, revision),
// 0 when unsupported. Bit 0 set means "some functions exist".
uint64_t DsmFunctions(int32_t device, const uint8_t uuid[16], uint64_t revision,
const AML::Object& arg3);
// Helpers for building _DSM / method arguments.
AML::Object IntegerArg(uint64_t value);
AML::Object BufferArg(const uint8_t* bytes, uint32_t length);
AML::Object EmptyPackageArg();
// Integer value of a method result: an integer as is, a buffer read
// little-endian (up to 8 bytes).
uint64_t ResultInteger(const AML::Object& result);
};
};