quirks: universal consumption model — open driver-scoped domain channel
Redesign grounded in the Linux 7.1 quirk-consumption cross-reference (9 families, one three-layer invariant: match -> store -> consume): - New open domain channel: [[<domain>_quirk]] TOML tables matched by (vendor, device) with wildcards, accumulated as string flags by quirks::lookup_driver_quirks(domain, vid, did). The table name IS the domain key — new driver domains need zero registry code (Linux Type-C model: driver-owned fixup tables like HDA's per-codec lists). - lookup_audio_quirks(vid, did) as the first domain convenience API for ihdad's future integration. - quirks.d/15-audio.toml converted from [[pci_quirk]] to [[audio_quirk]] — the audio_* flags (force_eapd, single_cmd, position_fix_lpib, mirroring Linux sound/pci/hda) are now carried as data instead of warned-and-dropped on every probe cycle. - Docs: three-layer model in QUIRKS-SYSTEM.md + consumption contract (bind-time / core-runtime / driver-runtime); QUIRKS-IMPROVEMENT-PLAN.md v2.0 with the redesign assessment and cutover-era reality (stale pcid-spawner broker references removed). - 75/75 redox-driver-sys tests pass (new domain loader test).
This commit is contained in:
@@ -9,6 +9,79 @@ This plan replaces vague “quirks support” follow-up work with a concrete pat
|
||||
3. reduce duplicated quirk logic,
|
||||
4. leave DMI and USB device quirks in a maintainable state.
|
||||
|
||||
**v2.0 update (2026-07-24):** adds the **universal quirk-consumption model** (§ below) — a
|
||||
redesign assessment grounded in a full cross-reference of Linux 7.1 quirk consumption across
|
||||
all 9 quirk families (PCI, USB, HDA, DMI, ATA, NVMe, HID, ACPI, MMC), and the first
|
||||
implementation of it: the open driver-scoped domain channel (`[[<domain>_quirk]]` tables +
|
||||
`quirks::lookup_driver_quirks`), which also resolves the `audio_*` unknown-flag drift.
|
||||
|
||||
## Universal quirk-consumption model (v2.0 redesign assessment)
|
||||
|
||||
### What the Linux 7.1 cross-reference established
|
||||
|
||||
Linux has **no unified registry** — 9 separate per-subsystem tables. But every one of them
|
||||
follows the same three-layer invariant:
|
||||
|
||||
```
|
||||
[1] MATCH (typed keys: VID/DID, class, subsystem IDs, model strings, DMI, CID/dates)
|
||||
[2] STORE (flag bits or fixup pointers attached to the device object)
|
||||
[3] CONSUME (the subsystem CORE or the owning driver, at FIXED lifecycle points)
|
||||
```
|
||||
|
||||
Three consumption classes exist:
|
||||
|
||||
| Class | Linux example | Mechanism |
|
||||
|---|---|---|
|
||||
| **A. Core lifecycle callbacks** | PCI `DECLARE_PCI_FIXUP_*` (8 passes: early/header/final/enable/resume/...) | Core invokes quirk *functions* at lifecycle points; drivers never look anything up |
|
||||
| **B. Core flag checks** | USB `usb_detect_quirks`, NVMe `.driver_data`, HID `hid_lookup_quirk`, ATA `ata_dev_quirks` | Flags set on the device object at enumeration; the subsystem core checks them at behavior points |
|
||||
| **C. Driver-owned domain tables** | HDA `snd_hda_pick_fixup` (5 actions: PRE_PROBE/PROBE/BUILD/INIT/FREE) | The driver matches its OWN table at its own lifecycle points |
|
||||
|
||||
### Red Bear's position (post-cutover, 2026-07-24)
|
||||
|
||||
Red Bear diverges from Linux deliberately and correctly by having **one unified registry**
|
||||
(`redox-driver-sys`: compiled tables + TOML + DMI) instead of N tables. The registry is the
|
||||
right base; what was missing is the lifecycle model and the Type-C driver-domain channel.
|
||||
|
||||
**The redesigned model — one registry, three consumption classes:**
|
||||
|
||||
1. **Bind-time (Class B, owned by driver-manager).** Spawn-time quirk decisions: env hints
|
||||
(`REDBEAR_DRIVER_PCI_IRQ_MODE`, `DISABLE_ACCEL`, `IOMMU_GROUP`, `NUMA_NODE`,
|
||||
`MSIX_VECTORS`), `NEED_FIRMWARE` deferral, blacklist interplay. Implemented and
|
||||
QEMU-validated in the cutover.
|
||||
2. **Core-runtime (Class B, owned by subsystem daemons).** Each subsystem daemon queries the
|
||||
registry at its own behavior points: `xhcid` (51-flag xHCI table), `redox-drm`
|
||||
(IRQ/accel), `linux-kpi` C drivers (`pci_has_quirk()`), `acpid` (system quirks), and —
|
||||
planned — `pcid` for config-space behaviors and `evdevd`/HID for input quirks.
|
||||
3. **Driver-runtime (Class C, NEW — open domain channel).** Driver-owned domains carried as
|
||||
string flags keyed by domain name: `[[<domain>_quirk]]` TOML tables, matched by
|
||||
`(vendor, device)` with wildcards, accumulated by
|
||||
`quirks::lookup_driver_quirks(domain, vid, did) -> Vec<String>`. **New domains need zero
|
||||
registry code — the table name is the domain key.** First instance: `[[audio_quirk]]`
|
||||
(`quirks.d/15-audio.toml`) with `quirks::lookup_audio_quirks()` for ihdad's future
|
||||
integration, mirroring Linux's per-codec HDA fixup model.
|
||||
|
||||
### What this changes vs the v1 plan
|
||||
|
||||
- The v1 plan's "brokered quirk bits from **pcid-spawner**" is **stale** — pcid-spawner is
|
||||
retired (gated fallback); driver-manager is the bind-time consumer now, and the broker
|
||||
concept is subsumed by Class 1 above.
|
||||
- The v1 plan had no answer for driver-specific quirks (audio) — they warned as unknown
|
||||
flags and were dropped. Class 3 is the answer: carried, queryable, zero-warning.
|
||||
- Lifecycle beyond spawn (Linux Class A phases: early pre-claim vs enable vs suspend/resume)
|
||||
remains a **next-milestone** item: `phase = "early"|"enable"` on entries, with
|
||||
driver-manager consulting the registry during enumeration (early) in addition to spawn
|
||||
(enable). PM phases wait for the power-management roadmap.
|
||||
|
||||
### Consumption contract per class (who may query what)
|
||||
|
||||
| Consumer | API | Class |
|
||||
|---|---|---|
|
||||
| driver-manager (spawn) | `lookup_pci_quirks` → env hints, deferrals | 1 |
|
||||
| Rust drivers/daemons | `info.quirks()`, `lookup_usb_quirks`, `lookup_xhci_controller_quirks_full`, `lookup_hid_quirks` | 2 |
|
||||
| C drivers via linux-kpi | `pci_has_quirk()` / `pci_get_quirk_flags()` | 2 |
|
||||
| Driver-owned domains | `lookup_driver_quirks(domain, vid, did)`, `lookup_audio_quirks(vid, did)` | 3 |
|
||||
| Tooling (lspci/lsusb/info) | same lookups, display-only | — |
|
||||
|
||||
## Current status snapshot
|
||||
|
||||
Completed from this plan:
|
||||
@@ -43,9 +116,11 @@ shipped paths.
|
||||
|
||||
It is based on the current in-tree state of:
|
||||
|
||||
- `redox-driver-sys` as the canonical quirks library,
|
||||
- `pcid-spawner` as an upstream-owned PCI launch broker that now brokers canonical quirks,
|
||||
- `redox-drm`, `xhcid`, and the amdgpu Redox glue/runtime path as real runtime PCI quirk consumers,
|
||||
- `redox-driver-sys` as the canonical quirks library (three-layer model: match → store →
|
||||
consume; typed bitflag domains plus the open driver-scoped domain channel),
|
||||
- `driver-manager` as the bind-time quirk consumer (spawn env hints, deferrals) — validated
|
||||
in the 2026-07-23/24 QEMU gate,
|
||||
- `redox-drm`, `xhcid`, and the amdgpu Redox glue/runtime path as runtime quirk consumers,
|
||||
- `lspci`, `lsusb`, and `redbear-info` as reporting surfaces.
|
||||
|
||||
## Reassessment Summary
|
||||
@@ -63,7 +138,6 @@ It is based on the current in-tree state of:
|
||||
|
||||
- USB quirks now have a first real runtime consumer in `xhcid`, but broader USB-driver adoption is still missing.
|
||||
- The `linux-kpi` bridge now has a first real in-tree C consumer: amdgpu uses it for quirk-aware IRQ expectation logging. Broader C-driver adoption is still missing.
|
||||
- `pcid-spawner` still synthesizes a partial `PciDeviceInfo` instead of reusing a richer canonical PCI object, because it operates as an upstream-owned broker with a narrow interface.
|
||||
|
||||
### What should not be “fixed” in the wrong layer
|
||||
|
||||
@@ -97,7 +171,9 @@ All other code should either:
|
||||
|
||||
- **Rust PCI drivers using `redox-driver-sys`** should call `info.quirks()` directly.
|
||||
- **C drivers using `linux-kpi`** should call `pci_has_quirk()` / `pci_get_quirk_flags()` directly in probe/init paths.
|
||||
- **Upstream base drivers that cannot depend on `redox-driver-sys`** may continue using brokered quirk bits from `pcid-spawner`, but only if that broker is made semantically identical to the canonical library.
|
||||
- **Driver-owned domain quirks** (audio, future nvme/ata) use
|
||||
`lookup_driver_quirks(domain, vendor, device)` / `lookup_audio_quirks(vendor, device)` —
|
||||
see the universal model § above.
|
||||
- **USB device quirks** should be consumed inside `xhcid` device enumeration/configuration logic, not only in tooling.
|
||||
|
||||
## Concrete Work Plan
|
||||
|
||||
@@ -15,6 +15,25 @@ For the current follow-up cleanup and integration roadmap, see
|
||||
|
||||
## Architecture
|
||||
|
||||
The system follows the same three-layer invariant as every Linux quirk family
|
||||
(cross-referenced 2026-07-24 against Linux 7.1 PCI/USB/HDA/DMI/ATA/NVMe/HID/ACPI/MMC):
|
||||
|
||||
```
|
||||
[1] MATCH typed keys — (vendor, device, subvendor/subdevice, class, revision, DMI)
|
||||
[2] STORE flag bits (typed domains) or string flags (open driver domains)
|
||||
[3] CONSUME a fixed consumer at a fixed point — never ad-hoc lookups
|
||||
```
|
||||
|
||||
Consumption contract (who consumes, at which point):
|
||||
|
||||
| Class | Consumer | Point | Mechanism |
|
||||
|---|---|---|---|
|
||||
| Bind-time | `driver-manager` | probe/spawn | env hints (`REDBEAR_DRIVER_*`), `NEED_FIRMWARE` deferral, blacklist |
|
||||
| Core-runtime | subsystem daemons (`xhcid`, `redox-drm`, `acpid`, linux-kpi C drivers) | their own behavior points | `info.quirks()`, `lookup_usb_quirks`, `lookup_xhci_controller_quirks_full`, `pci_has_quirk()` |
|
||||
| Driver-runtime | the owning driver (e.g. ihdad, future nvme/ata) | driver init | `lookup_driver_quirks(domain, vid, did)` — open `[[<domain>_quirk]]` tables |
|
||||
|
||||
Lookup flow for typed PCI flags:
|
||||
|
||||
```
|
||||
Driver probes device
|
||||
└─ PciDeviceInfo::quirks()
|
||||
@@ -28,6 +47,29 @@ All matching entries accumulate via bitwise OR, so broad rules (e.g., "all AMD G
|
||||
need firmware") and narrow rules (e.g., "this specific revision has broken MSI-X")
|
||||
compose naturally.
|
||||
|
||||
## Open driver-scoped domains (Type C, 2026-07-24)
|
||||
|
||||
Driver-owned quirk domains follow Linux's Type-C model (driver-owned fixup tables,
|
||||
e.g. HDA's per-codec fixup lists). The registry matches and carries plain string
|
||||
flags; the owning driver is the sole consumer and semantic owner:
|
||||
|
||||
```toml
|
||||
[[audio_quirk]]
|
||||
vendor = 0x8086
|
||||
device = 0x284b
|
||||
flags = ["audio_force_eapd"]
|
||||
```
|
||||
|
||||
- Table name = domain key: any `[[<domain>_quirk]]` table works with **zero registry
|
||||
code** for a new driver domain.
|
||||
- Match keys: `vendor`, `device` (hex, `0xFFFF` wildcard).
|
||||
- Query: `redox_driver_sys::quirks::lookup_driver_quirks(domain, vendor, device)
|
||||
-> Vec<String>`; convenience: `lookup_audio_quirks(vendor, device)`.
|
||||
- First instance: `quirks.d/15-audio.toml` (HDA quirks: force-EAPD, single-command,
|
||||
position-fix-LPIB — mirrors Linux `sound/pci/hda` device quirks). ihdad consumes
|
||||
these when its quirk integration lands; the flags were previously dropped with
|
||||
"unknown flag" warnings.
|
||||
|
||||
## Quirk Sources
|
||||
|
||||
### 1. Compiled-in Tables
|
||||
@@ -470,7 +512,7 @@ cargo test
|
||||
| Q3 | xhcid PCI controller quirks (interrupt + reset delay) | ✅ Done |
|
||||
| Q3 | xhcid xHCI controller quirks — canonical 51-flag table (Linux 7.1 port, ~85 entries) | ✅ Done (2026-07-18, P2-A) |
|
||||
| Q3 | xhcid USB device quirks (descriptor/configuration/BOS handling) | ✅ Done |
|
||||
| Q3 | pcid-spawner quirk passthrough | ✅ Done |
|
||||
| Q3 | driver-manager bind-time consumption (spawn env hints, NEED_FIRMWARE deferral) | ✅ Done — QEMU-validated 2026-07-23/24 |
|
||||
| Q3 | linux-kpi quirk flag bridge | ✅ Done |
|
||||
| Q3 | amdgpu linux-kpi quirk consumption | ✅ Done |
|
||||
| Q3 | redbear-info --quirks display | ✅ Done |
|
||||
@@ -497,7 +539,11 @@ the honest breakdown.
|
||||
- amdgpu: startup firmware requirement enforced at the Rust DRM boundary, with real quirk-aware runtime logging for `NO_ASPM`, `NEED_IOMMU`, `NO_MSI`, `NO_MSIX`
|
||||
|
||||
**Infrastructure (data flows, reporting, and partial integration):**
|
||||
- pcid-spawner: computes `PCI_QUIRK_FLAGS` by calling the canonical `redox-driver-sys` lookup on synthesized `PciDeviceInfo`, then passes the env var onward
|
||||
- driver-manager: bind-time consumption — spawn env hints
|
||||
(`REDBEAR_DRIVER_PCI_IRQ_MODE`, `REDBEAR_DRIVER_DISABLE_ACCEL`,
|
||||
`REDBEAR_DRIVER_IOMMU_GROUP`, `REDBEAR_DRIVER_NUMA_NODE`,
|
||||
`REDBEAR_DRIVER_MSIX_VECTORS`) and `NEED_FIRMWARE` probe deferral, validated in
|
||||
the 2026-07-23/24 QEMU gate
|
||||
- linux-kpi: `pci_get_quirk_flags()` / `pci_has_quirk()` C FFI is available for C drivers and is now consumed by the Red Bear amdgpu path
|
||||
- redbear-info: `--quirks` reads `/etc/quirks.d/*.toml` and reports configured PCI/USB/DMI entries
|
||||
- lspci: shows active quirk flags per PCI device (via redox-driver-sys lookup)
|
||||
@@ -523,6 +569,5 @@ Those selectors are used only for pre-descriptor timing flags (`RESET_DELAY`, `H
|
||||
`SHORT_SET_ADDR_TIMEOUT`) where vendor/product IDs are not yet available.
|
||||
|
||||
**Remaining infrastructure work:**
|
||||
- none in the current quirks scope
|
||||
|
||||
`pcid-spawner` now brokers quirks through the canonical `redox-driver-sys` lookup instead of carrying a separate in-tree PCI quirk engine.
|
||||
- lifecycle phases beyond spawn (`phase = "early"|"enable"` on entries — early
|
||||
pre-claim vs enable; PM phases follow the power-management roadmap)
|
||||
|
||||
@@ -361,6 +361,24 @@ pub fn lookup_usb_quirks(vendor: u16, product: u16) -> UsbQuirkFlags {
|
||||
flags
|
||||
}
|
||||
|
||||
/// Look up driver-scoped quirk flags for a domain (`"audio"`, `"nvme"`, ...)
|
||||
/// from open `[[<domain>_quirk]]` TOML tables. The registry matches and
|
||||
/// carries string flags; the owning driver interprets them. This is the
|
||||
/// Linux Type-C model (driver-owned fixup tables such as HDA's per-codec
|
||||
/// fixup lists) — the table name is the domain key, so new driver domains
|
||||
/// need no registry code.
|
||||
pub fn lookup_driver_quirks(domain: &str, vendor: u16, device: u16) -> Vec<String> {
|
||||
toml_loader::load_domain_quirks(domain, vendor, device).unwrap_or_default()
|
||||
}
|
||||
|
||||
/// Audio (HDA) driver quirk flags for a PCI vendor/device pair, from
|
||||
/// `[[audio_quirk]]` entries (`quirks.d/15-audio.toml`). Mirrors Linux's
|
||||
/// `sound/pci/hda` per-device quirk model: force-EAPD, single-command mode,
|
||||
/// position-fix-LPIB and friends are interpreted by the audio driver itself.
|
||||
pub fn lookup_audio_quirks(vendor: u16, device: u16) -> Vec<String> {
|
||||
lookup_driver_quirks("audio", vendor, device)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -61,6 +61,71 @@ pub fn load_dmi_system_quirks(dmi_info: &DmiInfo) -> Result<SystemQuirkFlags, ()
|
||||
Ok(flags)
|
||||
}
|
||||
|
||||
/// A driver-scoped quirk entry from an open `[[<domain>_quirk]]` TOML table.
|
||||
///
|
||||
/// Domain tables carry plain string flags; the owning driver interprets
|
||||
/// them. This is the Linux Type-C model (driver-owned fixup tables such as
|
||||
/// HDA's per-codec fixup lists): the registry matches and carries the data,
|
||||
/// the driver is the sole consumer and semantic owner. New driver domains
|
||||
/// need no registry code — the table name IS the domain key.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct DomainQuirkEntry {
|
||||
pub vendor: u16,
|
||||
pub device: u16,
|
||||
pub flags: Vec<String>,
|
||||
}
|
||||
|
||||
/// Accumulate string flags from all `[[<domain>_quirk]]` entries matching
|
||||
/// `(vendor, device)` (`0xFFFF` wildcards match everything).
|
||||
pub fn load_domain_quirks(domain: &str, vendor: u16, device: u16) -> Result<Vec<String>, ()> {
|
||||
load_domain_quirks_from(QUIRKS_DIR, domain, vendor, device).map_err(|_| ())
|
||||
}
|
||||
|
||||
fn load_domain_quirks_from(
|
||||
dir: &str,
|
||||
domain: &str,
|
||||
vendor: u16,
|
||||
device: u16,
|
||||
) -> std::io::Result<Vec<String>> {
|
||||
let table_name = format!("{domain}_quirk");
|
||||
let mut out = Vec::new();
|
||||
for path in sorted_toml_files(dir)? {
|
||||
let path_str = path.display().to_string();
|
||||
let Ok(content) = std::fs::read_to_string(&path) else {
|
||||
continue;
|
||||
};
|
||||
let Ok(doc) = content.parse::<toml::Value>() else {
|
||||
continue;
|
||||
};
|
||||
let Some(arr) = doc.get(&table_name).and_then(|v| v.as_array()) else {
|
||||
continue;
|
||||
};
|
||||
for item in arr {
|
||||
let Some(table) = item.as_table() else {
|
||||
continue;
|
||||
};
|
||||
let entry_vendor = table
|
||||
.get("vendor")
|
||||
.and_then(|v| bounded_u16(v, "vendor", &path_str))
|
||||
.unwrap_or(PCI_QUIRK_ANY_ID);
|
||||
let entry_device = table
|
||||
.get("device")
|
||||
.and_then(|v| bounded_u16(v, "device", &path_str))
|
||||
.unwrap_or(PCI_QUIRK_ANY_ID);
|
||||
let vendor_matches = entry_vendor == vendor || entry_vendor == PCI_QUIRK_ANY_ID;
|
||||
let device_matches = entry_device == device || entry_device == PCI_QUIRK_ANY_ID;
|
||||
if vendor_matches && device_matches {
|
||||
if let Some(names) = table.get("flags").and_then(|v| v.as_array()) {
|
||||
for name in names.iter().filter_map(toml::Value::as_str) {
|
||||
out.push(name.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
fn bounded_u16(val: &toml::Value, field: &str, path: &str) -> Option<u16> {
|
||||
match val.as_integer() {
|
||||
Some(v) => u16::try_from(v).ok().or_else(|| {
|
||||
@@ -703,4 +768,50 @@ mod tests {
|
||||
assert_eq!(rules[0].flags, PciQuirkFlags::NO_ASPM);
|
||||
assert_eq!(system_rules[0].flags, SystemQuirkFlags::KBD_DEACTIVATE_FIXUP);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn domain_quirks_match_and_accumulate() {
|
||||
let dir = std::env::temp_dir().join(format!(
|
||||
"rb-quirks-domain-{}-{}",
|
||||
std::process::id(),
|
||||
std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_nanos()
|
||||
));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
std::fs::write(
|
||||
dir.join("15-audio.toml"),
|
||||
r#"
|
||||
[[audio_quirk]]
|
||||
vendor = 0x8086
|
||||
device = 0x284b
|
||||
flags = ["audio_force_eapd"]
|
||||
|
||||
[[audio_quirk]]
|
||||
vendor = 0x8086
|
||||
flags = ["audio_single_cmd"]
|
||||
|
||||
[[audio_quirk]]
|
||||
vendor = 0x1002
|
||||
device = 0x4370
|
||||
flags = ["audio_position_fix_lpib"]
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let exact = load_domain_quirks_from(dir.to_str().unwrap(), "audio", 0x8086, 0x284b).unwrap();
|
||||
assert_eq!(exact, vec!["audio_force_eapd", "audio_single_cmd"]);
|
||||
|
||||
let other_device = load_domain_quirks_from(dir.to_str().unwrap(), "audio", 0x8086, 0x9999).unwrap();
|
||||
assert_eq!(other_device, vec!["audio_single_cmd"]);
|
||||
|
||||
let other_vendor = load_domain_quirks_from(dir.to_str().unwrap(), "audio", 0x1002, 0x284b).unwrap();
|
||||
assert!(other_vendor.is_empty());
|
||||
|
||||
let wrong_domain = load_domain_quirks_from(dir.to_str().unwrap(), "nvme", 0x8086, 0x284b).unwrap();
|
||||
assert!(wrong_domain.is_empty());
|
||||
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,43 +2,43 @@
|
||||
# These apply to HDA controllers and codec devices.
|
||||
|
||||
# Intel ICH8 HDA — force EAPD on outputs
|
||||
[[pci_quirk]]
|
||||
[[audio_quirk]]
|
||||
vendor = 0x8086
|
||||
device = 0x284b
|
||||
flags = ["audio_force_eapd"]
|
||||
|
||||
# Intel ICH9 HDA (QEMU) — use immediate command interface
|
||||
[[pci_quirk]]
|
||||
[[audio_quirk]]
|
||||
vendor = 0x8086
|
||||
device = 0x293e
|
||||
flags = ["audio_single_cmd"]
|
||||
|
||||
# Intel 6-series PCH HDA — position fix LPIB
|
||||
[[pci_quirk]]
|
||||
[[audio_quirk]]
|
||||
vendor = 0x8086
|
||||
device = 0x1c20
|
||||
flags = ["audio_position_fix_lpib"]
|
||||
|
||||
# Intel 7-series PCH HDA — position fix LPIB
|
||||
[[pci_quirk]]
|
||||
[[audio_quirk]]
|
||||
vendor = 0x8086
|
||||
device = 0x1e20
|
||||
flags = ["audio_position_fix_lpib"]
|
||||
|
||||
# Intel Sunrise Point HDA — position fix LPIB
|
||||
[[pci_quirk]]
|
||||
[[audio_quirk]]
|
||||
vendor = 0x8086
|
||||
device = 0xa170
|
||||
flags = ["audio_position_fix_lpib"]
|
||||
|
||||
# Intel Cannon Point HDA — position fix LPIB
|
||||
[[pci_quirk]]
|
||||
[[audio_quirk]]
|
||||
vendor = 0x8086
|
||||
device = 0x9dc8
|
||||
flags = ["audio_position_fix_lpib"]
|
||||
|
||||
# AMD FCH HDA — single command fallback
|
||||
[[pci_quirk]]
|
||||
[[audio_quirk]]
|
||||
vendor = 0x1022
|
||||
device = 0x1457
|
||||
flags = ["audio_single_cmd"]
|
||||
|
||||
Reference in New Issue
Block a user