ihdad: HDA verb constants module (Linux 7.1 hda_verbs.h)
Added verbs.rs with 200+ named constants ported from Linux 7.1 include/sound/hda_verbs.h. Replaces raw hex values (0xF00, 0xF01, etc.) with named constants throughout device.rs. Constants cover: widget types, GET/SET verbs, parameter IDs, widget/pin/amplifier capabilities, pin control, power states, PCM/stream format, digital converter bits, connection list. Bug fix: read_node() was calling AC_PAR_NODE_COUNT (0x04) for function_group_type query — corrected to AC_PAR_FUNCTION_TYPE (0x05). The old code happened to work because the low byte matched on the test codec, but was reading the wrong HDA parameter.
This commit is contained in:
@@ -13,6 +13,12 @@ use common::timeout::Timeout;
|
||||
use redox_scheme::scheme::SchemeSync;
|
||||
use redox_scheme::CallerCtx;
|
||||
use redox_scheme::OpenResult;
|
||||
use crate::hda::verbs::{
|
||||
AC_VERB_PARAMETERS, AC_VERB_GET_CONNECT_SEL, AC_VERB_GET_CONNECT_LIST,
|
||||
AC_VERB_GET_CONFIG_DEFAULT,
|
||||
AC_PAR_NODE_COUNT, AC_PAR_AUDIO_WIDGET_CAP, AC_PAR_CONNLIST_LEN,
|
||||
AC_PAR_FUNCTION_TYPE, AC_CLIST_LONG, AC_CLIST_LENGTH,
|
||||
};
|
||||
use scheme_utils::{FpathWriter, HandleMap};
|
||||
use syscall::error::{Error, Result, EACCES, EBADF, EIO, ENODEV, EWOULDBLOCK};
|
||||
|
||||
@@ -254,7 +260,7 @@ impl IntelHDA {
|
||||
|
||||
node.addr = addr;
|
||||
|
||||
temp = self.cmd.cmd12(addr, 0xF00, 0x04)?;
|
||||
temp = self.cmd.cmd12(addr, AC_VERB_PARAMETERS, AC_PAR_NODE_COUNT)?;
|
||||
|
||||
node.subnode_count = (temp & 0xff) as u16;
|
||||
node.subnode_start = ((temp >> 16) & 0xff) as u16;
|
||||
@@ -262,41 +268,37 @@ impl IntelHDA {
|
||||
if addr == (0, 0) {
|
||||
return Ok(node);
|
||||
}
|
||||
temp = self.cmd.cmd12(addr, 0xF00, 0x04)?;
|
||||
temp = self.cmd.cmd12(addr, AC_VERB_PARAMETERS, AC_PAR_FUNCTION_TYPE)?;
|
||||
|
||||
node.function_group_type = (temp & 0xff) as u8;
|
||||
|
||||
temp = self.cmd.cmd12(addr, 0xF00, 0x09)?;
|
||||
temp = self.cmd.cmd12(addr, AC_VERB_PARAMETERS, AC_PAR_AUDIO_WIDGET_CAP)?;
|
||||
node.capabilities = temp as u32;
|
||||
|
||||
temp = self.cmd.cmd12(addr, 0xF00, 0x0E)?;
|
||||
temp = self.cmd.cmd12(addr, AC_VERB_PARAMETERS, AC_PAR_CONNLIST_LEN)?;
|
||||
|
||||
node.conn_list_len = (temp & 0xFF) as u8;
|
||||
|
||||
node.connections = self.node_get_connection_list(&node)?;
|
||||
|
||||
node.connection_default = self.cmd.cmd12(addr, 0xF01, 0x00)? as u8;
|
||||
node.connection_default = self.cmd.cmd12(addr, AC_VERB_GET_CONNECT_SEL, 0x00)? as u8;
|
||||
|
||||
node.config_default = self.cmd.cmd12(addr, 0xF1C, 0x00)? as u32;
|
||||
node.config_default = self.cmd.cmd12(addr, AC_VERB_GET_CONFIG_DEFAULT, 0x00)? as u32;
|
||||
|
||||
Ok(node)
|
||||
}
|
||||
|
||||
pub fn node_get_connection_list(&mut self, node: &HDANode) -> Result<Vec<WidgetAddr>> {
|
||||
let len_field: u8 = (self.cmd.cmd12(node.addr, 0xF00, 0x0E)? & 0xFF) as u8;
|
||||
|
||||
// Highest bit is if addresses are represented in longer notation
|
||||
// lower 7 is actual count
|
||||
|
||||
let count: u8 = len_field & 0x7F;
|
||||
let use_long_addr: bool = (len_field >> 7) & 0x1 == 1;
|
||||
let len_field: u8 = (self.cmd.cmd12(node.addr, AC_VERB_PARAMETERS, AC_PAR_CONNLIST_LEN)? & 0xFF) as u8;
|
||||
let count: u8 = len_field & (AC_CLIST_LENGTH as u8);
|
||||
let use_long_addr: bool = (len_field & (AC_CLIST_LONG as u8)) != 0;
|
||||
|
||||
let mut current: u8 = 0;
|
||||
|
||||
let mut list = Vec::<WidgetAddr>::new();
|
||||
|
||||
while current < count {
|
||||
let response: u32 = (self.cmd.cmd12(node.addr, 0xF02, current)? & 0xFFFFFFFF) as u32;
|
||||
let response: u32 = (self.cmd.cmd12(node.addr, AC_VERB_GET_CONNECT_LIST, current)? & 0xFFFFFFFF) as u32;
|
||||
|
||||
if use_long_addr {
|
||||
for i in 0..2 {
|
||||
|
||||
Reference in New Issue
Block a user