1 // SPDX-License-Identifier: GPL-2.0-only
12 "review.coreboot.org/coreboot.git/util/hda-decoder/decoder"
17 type decodeOperation
int
20 decodeToHumanReadable decodeOperation
= iota
24 var indentLevel
int = 0
26 func indentedPrintf(format
string, args
...interface{}) (n
int, err error
) {
27 s
:= fmt
.Sprintf("%s%s", strings
.Repeat("\t", indentLevel
), format
)
28 return fmt
.Printf(s
, args
...)
31 func stringToUint32(s
string) uint32 {
32 s
= strings
.Replace(s
, "0x", "", -1)
33 v
, err
:= strconv
.ParseUint(s
, 16, 32)
40 func decodeConfig(config
uint32) {
41 out
:= decoder
.ToHumanReadable(decoder
.Decode(config
))
43 indentedPrintf("%s,\n", out
.PortConnectivity
)
44 indentedPrintf("%s,\n", out
.Location
)
45 indentedPrintf("%s,\n", out
.DefaultDevice
)
46 indentedPrintf("%s,\n", out
.ConnectionType
)
47 indentedPrintf("%s,\n", out
.Color
)
48 indentedPrintf("%s,\n", out
.Misc
)
49 indentedPrintf("%s, %s\n", out
.DefaultAssociation
, out
.Sequence
)
52 func printDisconnectedPort(config
uint32) {
53 // The value 0x411111f0 is not defined in the specification, but is a
54 // common value vendors use to indicate "not connected".
55 const nc
uint32 = 0x411111f0
57 // Setting some values (e.g. 0x40000000) as `AZALIA_PIN_CFG_NC(0)` is
58 // probably harmless. However, we will stay on the safe side for now.
59 if (config
& 0xfffffff0) != nc
{
60 // Do not decode these values, as they would likely describe a
61 // bogus device which could be slighly confusing.
62 fmt
.Printf("0x%08x), // does not describe a jack or internal device\n", config
)
64 fmt
.Printf("AZALIA_PIN_CFG_NC(%d)),\n", (config
& 0x0000000f))
68 func decodeFile(path
string, codec
uint32, operation decodeOperation
) {
69 file
, err
:= os
.Open(path
)
75 scanner
:= bufio
.NewScanner(file
)
78 fields
:= strings
.Fields(scanner
.Text())
80 fmt
.Print("// Something went wrong\n")
84 pin
:= stringToUint32(fields
[0])
85 config
:= stringToUint32(fields
[1])
89 fmt
.Printf("address: %d, node ID: %#02x, configuration default: %#08x\n",
92 verbs
:= decoder
.ConfigToVerbs(codec
, pin
, config
)
93 fmt
.Printf(" %#08x\n", verbs
[0])
94 fmt
.Printf(" %#08x\n", verbs
[1])
95 fmt
.Printf(" %#08x\n", verbs
[2])
96 fmt
.Printf(" %#08x\n", verbs
[3])
97 case decodeToHumanReadable
:
98 indentedPrintf("AZALIA_PIN_CFG(%d, 0x%02x, ", codec
, pin
)
99 if decoder
.PortIsConnected(config
) {
100 fmt
.Printf("AZALIA_PIN_DESC(\n")
104 indentedPrintf(")),\n")
106 printDisconnectedPort(config
)
112 func getFileContents(path
string) string {
113 contents
, err
:= os
.ReadFile(path
)
117 return strings
.TrimSpace(string(contents
))
120 func getLineCount(path
string) int {
121 return len(strings
.Split(getFileContents(path
), "\n"))
124 func decodeDeviceCodec(path
string, codec
uint32, isLastCodec
bool, generate
bool) {
126 vendorId
:= getFileContents(path
+ "/vendor_id")
127 vendorName
:= getFileContents(path
+ "/vendor_name")
128 chipName
:= getFileContents(path
+ "/chip_name")
129 subsystemId
:= getFileContents(path
+ "/subsystem_id")
130 lineCount
:= getLineCount(path
+ "/init_pin_configs")
132 indentedPrintf("%s, // Vendor/Device ID: %s %s\n", vendorId
, vendorName
, chipName
)
133 indentedPrintf("%s, // Subsystem ID\n", subsystemId
)
134 indentedPrintf("%d,\n", lineCount
+1)
135 indentedPrintf("AZALIA_SUBVENDOR(%d, %s),\n\n", codec
, subsystemId
)
138 decodeFile(path
+"/init_pin_configs", codec
, decodeToHumanReadable
)
144 func decodeDeviceCodecs(generate
bool) {
145 matches
, err
:= filepath
.Glob("/sys/class/sound/hwC0D*")
149 re
:= regexp
.MustCompile(`D([0-9]+)$`)
151 for i
, match
:= range matches
{
152 codec
:= stringToUint32(re
.FindStringSubmatch(match
)[1])
153 isLastCodec
:= (i
+ 1) == len(matches
)
155 decodeDeviceCodec(match
, codec
, isLastCodec
, generate
)
159 func isFlagPassed(name
string) bool {
162 flag
.Visit(func(f
*flag
.Flag
) {
171 codec
:= flag
.Uint64("codec", 0, "Set the codec number when decoding a file\n"+
172 "This flag is only meaningful in combination with the 'file' flag")
173 config
:= flag
.Uint64("config", 0, "Decode a single configuration")
174 file
:= flag
.String("file", "", "Decode configurations in a file\n"+
175 "The decoder assumes each line in the file has the format: <pin> <config>")
176 generate
:= flag
.Bool("generate", false, "Automatically generate hda_verb.c for the host device")
177 toVerbs
:= flag
.Bool("to-verbs", false, "Convert configuration defaults to their corresponding verbs\n"+
178 "This flag is only meaningful in combination with the 'file' flag")
181 operation
:= decodeToHumanReadable
183 operation
= decodeToVerbs
186 if isFlagPassed("config") {
187 decodeConfig(uint32(*config
))
188 } else if isFlagPassed("file") {
189 decodeFile(*file
, uint32(*codec
), operation
)
192 fmt
.Printf("/* SPDX-License-Identifier: GPL-2.0-only */\n\n")
193 fmt
.Printf("#include <device/azalia_device.h>\n\n")
194 fmt
.Printf("const u32 cim_verb_data[] = {\n")
197 decodeDeviceCodecs(*generate
)
201 fmt
.Printf("const u32 pc_beep_verbs[] = {};\n")
202 fmt
.Printf("AZALIA_ARRAY_SIZES;\n")