mb/google/rauru: Add pwrsel init in romstage
[coreboot2.git] / util / hda-decoder / main.go
blobc0a88adf2ebd25943719a3496a573a41e3e81eaf
1 // SPDX-License-Identifier: GPL-2.0-only
2 package main
4 import (
5 "bufio"
6 "flag"
7 "fmt"
8 "log"
9 "os"
10 "path/filepath"
11 "regexp"
12 "review.coreboot.org/coreboot.git/util/hda-decoder/decoder"
13 "strconv"
14 "strings"
17 type decodeOperation int
19 const (
20 decodeToHumanReadable decodeOperation = iota
21 decodeToVerbs
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)
34 if err != nil {
35 log.Fatal(err)
37 return uint32(v)
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)
63 } else {
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)
70 if err != nil {
71 log.Fatal(err)
73 defer file.Close()
75 scanner := bufio.NewScanner(file)
77 for scanner.Scan() {
78 fields := strings.Fields(scanner.Text())
79 if len(fields) != 2 {
80 fmt.Print("// Something went wrong\n")
81 continue
84 pin := stringToUint32(fields[0])
85 config := stringToUint32(fields[1])
87 switch operation {
88 case decodeToVerbs:
89 fmt.Printf("address: %d, node ID: %#02x, configuration default: %#08x\n",
90 codec, pin, config)
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")
101 indentLevel += 1
102 decodeConfig(config)
103 indentLevel -= 1
104 indentedPrintf(")),\n")
105 } else {
106 printDisconnectedPort(config)
112 func getFileContents(path string) string {
113 contents, err := os.ReadFile(path)
114 if err != nil {
115 log.Fatal(err)
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) {
125 if generate {
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)
139 if !isLastCodec {
140 fmt.Printf("\n")
144 func decodeDeviceCodecs(generate bool) {
145 matches, err := filepath.Glob("/sys/class/sound/hwC0D*")
146 if err != nil {
147 log.Fatal(err)
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 {
160 found := false
162 flag.Visit(func(f *flag.Flag) {
163 if f.Name == name {
164 found = true
167 return found
170 func main() {
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")
179 flag.Parse()
181 operation := decodeToHumanReadable
182 if *toVerbs {
183 operation = decodeToVerbs
186 if isFlagPassed("config") {
187 decodeConfig(uint32(*config))
188 } else if isFlagPassed("file") {
189 decodeFile(*file, uint32(*codec), operation)
190 } else {
191 if *generate {
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")
195 indentLevel += 1
197 decodeDeviceCodecs(*generate)
198 if *generate {
199 indentLevel -= 1
200 fmt.Printf("};\n\n")
201 fmt.Printf("const u32 pc_beep_verbs[] = {};\n")
202 fmt.Printf("AZALIA_ARRAY_SIZES;\n")