Nicholas Sudsgaard has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/80333?usp=email )
Change subject: device/azalia: Rework the verb table ......................................................................
device/azalia: Rework the verb table
This is a very experimental change and I would appreciate anyone's opinion on this. :)
My intentions are to make verb tables cleaner on the both the configuration and implementation side.
On the configuration side (i.e. hda_verbs.c) this method removes most superfluous comments (e.g. /* Subsystem ID */) and makes it more "structured".
On the implementation side I tried to make it easier to read (and hopefully maintain). For example, compare azalia_find_verb() and azalia_find_verb_table(). I also got rid of global variables (but introduced including c source files directly instead...).
Change-Id: If8b672e4fd800b34e5ba39fad174fcf1154b0a54 Signed-off-by: Nicholas Sudsgaard devel+coreboot@nsudsgaard.com --- M src/device/azalia_device.c M src/include/device/azalia_device.h A src/include/device/azalia_table_exporter.c M src/mainboard/hp/snb_ivb_laptops/variants/2560p/hda_verb.c 4 files changed, 115 insertions(+), 101 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/33/80333/1
diff --git a/src/device/azalia_device.c b/src/device/azalia_device.c index 298ceb2..ec63ed8 100644 --- a/src/device/azalia_device.c +++ b/src/device/azalia_device.c @@ -7,6 +7,7 @@ #include <device/mmio.h> #include <delay.h> #include <stdbool.h> +#include <stddef.h> #include <timer.h>
int azalia_set_bits(void *port, u32 mask, u32 val) @@ -102,48 +103,18 @@ return 0; }
-/* - * Find a specific entry within a verb table - * - * @param verb_table: verb table data - * @param verb_table_bytes: verb table size in bytes - * @param viddid: vendor/device to search for - * @param verb: pointer to entry within table - * - * Returns size of the entry within the verb table, - * Returns 0 if the entry is not found - * - * The HDA verb table is composed of dwords. A set of 4 dwords is - * grouped together to form a "jack" descriptor. - * Bits 31:28 - Codec Address - * Bits 27:20 - NID - * Bits 19:8 - Verb ID - * Bits 7:0 - Payload - * - * coreboot groups different codec verb tables into a single table - * and prefixes each with a specific header consisting of 3 - * dword entries: - * 1 - Codec Vendor/Device ID - * 2 - Subsystem ID - * 3 - Number of jacks (groups of 4 dwords) for this codec - */ -u32 azalia_find_verb(const u32 *verb_table, u32 verb_table_bytes, u32 viddid, const u32 **verb) +const struct verb_table azalia_find_verb_table(const u32 viddid) { - int idx = 0; + const struct codec_table codec_table = get_codec_table();
- while (idx < (verb_table_bytes / sizeof(u32))) { - /* Header contains the number of jacks, aka groups of 4 dwords */ - u32 verb_size = 4 * verb_table[idx + 2]; - if (verb_table[idx] != viddid) { - idx += verb_size + 3; // skip verb + header - continue; + for (size_t i = 0; i < codec_table.size; i++) { + const struct verb_table entry = codec_table.entries[i]; + + if (entry.vendor_id == viddid) { + return entry; } - *verb = &verb_table[idx + 3]; - return verb_size; } - - /* Not all codecs need to load another verb */ - return 0; + return EMPTY_VERB_TABLE; }
/* @@ -211,13 +182,13 @@ return wait_for_valid(base); }
-int azalia_program_verb_table(u8 *base, const u32 *verbs, u32 verb_size) +int azalia_program_verb_table(u8 *base, const struct verb_table verb_table) { - if (!verbs) + if (verb_table.size == 0) return 0;
- for (u32 i = 0; i < verb_size; i++) { - if (azalia_write_verb(base, verbs[i]) < 0) + for (size_t i = 0; i < verb_table.size; i++) { + if (azalia_write_verb(base, verb_table.verbs[i]) < 0) return -1; } return 0; @@ -244,39 +215,37 @@ return true; }
-static u32 get_verb(const u32 *verb_table, u32 verb_table_bytes, const u32 viddid, const u32 **verb) +static const struct verb_table get_verb_table(const u32 viddid) { - const u32 verb_size = azalia_find_verb(verb_table, verb_table_bytes, viddid, verb); + const struct verb_table verb_table = azalia_find_verb_table(viddid);
- if (verb_size == 0) { + if (verb_table.size == 0) { printk(BIOS_DEBUG, "azalia_audio: - no verb!\n"); - return 0; + } else { + printk(BIOS_DEBUG, "azalia_audio: - verb size: %zu\n", verb_table.size); } - printk(BIOS_DEBUG, "azalia_audio: - verb size: %u\n", verb_size); - return verb_size; + return verb_table; }
-static void load_verb(u8 *base, const u32 *verb, const u32 verb_size) +static void load_verb(u8 *base, const struct verb_table verb_table) { - if (azalia_program_verb_table(base, verb, verb_size) < 0) { + if (azalia_program_verb_table(base, verb_table) < 0) { printk(BIOS_DEBUG, "azalia_audio: - verb not loaded\n"); } else { printk(BIOS_DEBUG, "azalia_audio: - verb loaded\n"); } }
-void azalia_codec_init(u8 *base, int addr, const u32 *verb_table, u32 verb_table_bytes) +void azalia_codec_init(u8 *base, int addr) { const u32 viddid = read32(base + HDA_IR_REG); - const u32 *verb; - u32 verb_size;
printk(BIOS_DEBUG, "azalia_audio: initializing codec #%d...\n", addr); printk(BIOS_DEBUG, "azalia_audio: - vendor/device id: 0x%08x\n", viddid);
- verb_size = get_verb(verb_table, verb_table_bytes, viddid, &verb); - if (verb_size == 0) return; - load_verb(base, verb, verb_size); + const struct verb_table verb_table = get_verb_table(viddid); + if (verb_table.size == 0) return; + load_verb(base, verb_table);
mainboard_azalia_program_runtime_verbs(base, viddid); } @@ -286,11 +255,11 @@ for (int i = AZALIA_MAX_CODECS - 1; i >= 0; i--) { if (codec_mask & (1 << i)) { if (!codec_is_operative(base, i)) continue; - azalia_codec_init(base, i, cim_verb_data, cim_verb_data_size); + azalia_codec_init(base, i); } }
- azalia_program_verb_table(base, pc_beep_verbs, pc_beep_verbs_size); + azalia_program_verb_table(base, get_pc_beep_verb_table()); }
void azalia_audio_init(struct device *dev) diff --git a/src/include/device/azalia_device.h b/src/include/device/azalia_device.h index 24e2644..2644b54 100644 --- a/src/include/device/azalia_device.h +++ b/src/include/device/azalia_device.h @@ -6,6 +6,7 @@ #include <acpi/acpi.h> #include <device/mmio.h> #include <device/device.h> +#include <stddef.h> #include <stdint.h>
#define HDA_GCAP_REG 0x00 @@ -17,15 +18,33 @@ #define HDA_ICII_REG 0x68 #define HDA_ICII_BUSY (1 << 0) #define HDA_ICII_VALID (1 << 1) +#define HDA_MAX_CORBSIZE 256
#define AZALIA_MAX_CODECS 15
+#define EMPTY_VERB_TABLE (struct verb_table) { .size = 0 } + +struct verb_table { + const u32 vendor_id; + const u32 subsystem_id; + const size_t size; + const u32 verbs[HDA_MAX_CORBSIZE]; +}; + +struct codec_table { + const size_t size; + const struct verb_table *entries; +}; + +extern const struct codec_table get_codec_table(void); +extern const struct verb_table get_pc_beep_verb_table(void); + int azalia_set_bits(void *port, u32 mask, u32 val); int azalia_enter_reset(u8 *base); int azalia_exit_reset(u8 *base); -u32 azalia_find_verb(const u32 *verb_table, u32 verb_table_bytes, u32 viddid, const u32 **verb); -int azalia_program_verb_table(u8 *base, const u32 *verbs, u32 verb_size); -void azalia_codec_init(u8 *base, int addr, const u32 *verb_table, u32 verb_table_bytes); +const struct verb_table azalia_find_verb_table(const u32 viddid); +int azalia_program_verb_table(u8 *base, const struct verb_table verb_table); +void azalia_codec_init(u8 *base, int addr); void azalia_codecs_init(u8 *base, u16 codec_mask); void azalia_audio_init(struct device *dev); extern struct device_operations default_azalia_audio_ops; @@ -33,11 +52,6 @@ /* Optional hook to program codec settings that are only known at runtime */ void mainboard_azalia_program_runtime_verbs(u8 *base, u32 viddid);
-extern const u32 cim_verb_data[]; -extern const u32 cim_verb_data_size; -extern const u32 pc_beep_verbs[]; -extern const u32 pc_beep_verbs_size; - enum azalia_pin_connection { JACK = 0, NC, @@ -126,10 +140,6 @@ ((association) << 4) | \ ((sequence) << 0))
-#define AZALIA_ARRAY_SIZES const u32 pc_beep_verbs_size = \ - ARRAY_SIZE(pc_beep_verbs); \ - const u32 cim_verb_data_size = sizeof(cim_verb_data) - #define AZALIA_VERB_12B(codec, pin, verb, val) \ ((codec) << 28 | (pin) << 20 | (verb) << 8 | (val))
diff --git a/src/include/device/azalia_table_exporter.c b/src/include/device/azalia_table_exporter.c new file mode 100644 index 0000000..37b2df3 --- /dev/null +++ b/src/include/device/azalia_table_exporter.c @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +// Boilerplate code to export verb tables from each mainboard's hda_verb.c. +// DO NOT INCLUDE THIS FILE INTO ANY OTHER FILE. + +_Static_assert(ARRAY_SIZE(codec_table) <= AZALIA_MAX_CODECS); + +const struct codec_table get_codec_table(void) +{ + return (struct codec_table) { + .size = ARRAY_SIZE(codec_table), + .entries = codec_table, + }; +} + +const struct verb_table get_pc_beep_verb_table(void) +{ + return pc_beep_verbs; +} diff --git a/src/mainboard/hp/snb_ivb_laptops/variants/2560p/hda_verb.c b/src/mainboard/hp/snb_ivb_laptops/variants/2560p/hda_verb.c index eba1fb9..9b1626b 100644 --- a/src/mainboard/hp/snb_ivb_laptops/variants/2560p/hda_verb.c +++ b/src/mainboard/hp/snb_ivb_laptops/variants/2560p/hda_verb.c @@ -2,37 +2,53 @@
#include <device/azalia_device.h>
-const u32 cim_verb_data[] = { - 0x111d7605, /* Codec Vendor / Device ID: IDT */ - 0x103c162b, /* Subsystem ID */ - 11, /* Number of 4 dword sets */ - AZALIA_SUBVENDOR(0, 0x103c162b), - AZALIA_PIN_CFG(0, 0x0a, 0x40f000f0), - AZALIA_PIN_CFG(0, 0x0b, 0x0421401f), - AZALIA_PIN_CFG(0, 0x0c, 0x04a11020), - AZALIA_PIN_CFG(0, 0x0d, 0x90170110), - AZALIA_PIN_CFG(0, 0x0e, 0x40f000f0), - AZALIA_PIN_CFG(0, 0x0f, 0x40f000f0), - AZALIA_PIN_CFG(0, 0x10, 0x40f000f0), - AZALIA_PIN_CFG(0, 0x11, 0x90a60130), - AZALIA_PIN_CFG(0, 0x1f, 0x40f000f0), - AZALIA_PIN_CFG(0, 0x20, 0x40f000f0), - - 0x11c11040, /* Codec Vendor / Device ID: LSI */ - 0x103c3066, /* Subsystem ID */ - 1, /* Number of 4 dword sets */ - AZALIA_SUBVENDOR(1, 0x103c3066), - - 0x80862805, /* Codec Vendor / Device ID: Intel */ - 0x80860101, /* Subsystem ID */ - 4, /* Number of 4 dword sets */ - AZALIA_SUBVENDOR(3, 0x80860101), - AZALIA_PIN_CFG(3, 0x05, 0x18560010), - AZALIA_PIN_CFG(3, 0x06, 0x58560020), - AZALIA_PIN_CFG(3, 0x07, 0x18560030), - +static const struct verb_table idt_verbs = { + .vendor_id = 0x111d7605, + .subsystem_id = 0x103c162b, + .size = 11, + .verbs = { + AZALIA_SUBVENDOR(0, 0x103c162b), + AZALIA_PIN_CFG(0, 0x0a, 0x40f000f0), + AZALIA_PIN_CFG(0, 0x0b, 0x0421401f), + AZALIA_PIN_CFG(0, 0x0c, 0x04a11020), + AZALIA_PIN_CFG(0, 0x0d, 0x90170110), + AZALIA_PIN_CFG(0, 0x0e, 0x40f000f0), + AZALIA_PIN_CFG(0, 0x0f, 0x40f000f0), + AZALIA_PIN_CFG(0, 0x10, 0x40f000f0), + AZALIA_PIN_CFG(0, 0x11, 0x90a60130), + AZALIA_PIN_CFG(0, 0x1f, 0x40f000f0), + AZALIA_PIN_CFG(0, 0x20, 0x40f000f0), + }, };
-const u32 pc_beep_verbs[0] = {}; +static const struct verb_table lsi_verbs = { + .vendor_id = 0x11c11040, + .subsystem_id = 0x103c3066, + .size = 1, + .verbs = { + AZALIA_SUBVENDOR(1, 0x103c3066), + }, +};
-AZALIA_ARRAY_SIZES; +static const struct verb_table intel_verbs = { + .vendor_id = 0x80862805, + .subsystem_id = 0x80860101, + .size = 4, + .verbs = { + AZALIA_SUBVENDOR(3, 0x80860101), + AZALIA_PIN_CFG(3, 0x05, 0x18560010), + AZALIA_PIN_CFG(3, 0x06, 0x58560020), + AZALIA_PIN_CFG(3, 0x07, 0x18560030), + }, +}; + +static const struct verb_table codec_table[] = { + idt_verbs, + lsi_verbs, + intel_verbs, +}; + +static const struct verb_table pc_beep_verbs = EMPTY_VERB_TABLE; + +// Keep this on the last line! +#include <device/azalia_table_exporter.c>