diff options
8 files changed, 215 insertions, 2 deletions
diff --git a/src/mainboard/google/octopus/Kconfig.name b/src/mainboard/google/octopus/Kconfig.name index 6e3dbf493c..76715a5639 100644 --- a/src/mainboard/google/octopus/Kconfig.name +++ b/src/mainboard/google/octopus/Kconfig.name @@ -34,6 +34,7 @@ config BOARD_GOOGLE_BOBBA select BASEBOARD_OCTOPUS_LAPTOP select BOARD_GOOGLE_BASEBOARD_OCTOPUS select NHLT_DA7219 if INCLUDE_NHLT_BLOBS + select NHLT_RT5682 if INCLUDE_NHLT_BLOBS config BOARD_GOOGLE_MEEP bool "-> Meep" diff --git a/src/mainboard/google/octopus/mainboard.c b/src/mainboard/google/octopus/mainboard.c index e6dbd0330b..91d29cf61c 100644 --- a/src/mainboard/google/octopus/mainboard.c +++ b/src/mainboard/google/octopus/mainboard.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ #include <acpi/acpi.h> +#include <baseboard/cbi_ssfc.h> #include <baseboard/variants.h> #include <boardid.h> #include <bootstate.h> @@ -8,6 +9,7 @@ #include <device/device.h> #include <device/pci_def.h> #include <device/pci_ops.h> +#include <drivers/i2c/generic/chip.h> #include <ec/google/chromeec/ec.h> #include <ec/ec.h> #include <intelblocks/xhci.h> @@ -22,6 +24,9 @@ #include <variant/ec.h> #include <variant/gpio.h> +extern struct chip_operations drivers_i2c_generic_ops; +extern struct chip_operations drivers_i2c_da7219_ops; + static bool is_cnvi_held_in_reset(void) { struct device *dev = pcidev_path_on_root(PCH_DEVFN_CNVI); @@ -46,6 +51,41 @@ static void disable_wifi_wake(void) gpio_configure_pads(wifi_wake_gpio, ARRAY_SIZE(wifi_wake_gpio)); } +/* + * GPIO_137 for two audio codecs right now has the different configuration so + * if SSFC indicates that codec is different than default one then GPIO_137 + * needs to be overridden for the corresponding second source. + */ +static void gpio_modification_by_ssfc(struct pad_config *table, size_t num) +{ + /* For RT5682, GPIO 137 should be set as EDGE_BOTH. */ + const struct pad_config rt5682_gpio_137 = PAD_CFG_GPI_APIC_IOS(GPIO_137, + NONE, DEEP, EDGE_BOTH, INVERT, HIZCRx1, DISPUPD); + + if (table == NULL || num == 0) + return; + + /* + * Currently we only have the case of RT5682 as the second source. And + * in case of Ampton which used RT5682 as the default source, it didn't + * provide override_table right now so it will be returned ealier since + * table above is NULL. + */ + if (ssfc_get_audio_codec() != SSFC_AUDIO_CODEC_RT5682) + return; + + while (num--) { + if (table->pad == GPIO_137) { + *table = rt5682_gpio_137; + printk(BIOS_INFO, + "Configure GPIO 137 based on SSFC.\n"); + return; + } + + table++; + } +} + static void mainboard_init(void *chip_info) { int boardid; @@ -58,6 +98,8 @@ static void mainboard_init(void *chip_info) base_pads = variant_base_gpio_table(&base_num); override_pads = variant_override_gpio_table(&override_num); + gpio_modification_by_ssfc((struct pad_config *)override_pads, + override_num); gpio_configure_pads_with_override(base_pads, base_num, override_pads, override_num); @@ -128,10 +170,47 @@ static void wifi_device_update(void) dev->enabled = 0; } +/* + * Base on SSFC value in the CBI from EC to enable one of audio codec sources in + * the device tree. + */ +static void audio_codec_device_update(void) +{ + struct device *audio_dev = NULL; + struct bus *audio_i2c_bus = + pcidev_path_on_root(PCH_DEVFN_I2C5)->link_list; + enum ssfc_audio_codec codec = ssfc_get_audio_codec(); + + while ((audio_dev = dev_bus_each_child(audio_i2c_bus, audio_dev))) { + if (audio_dev->chip_info == NULL) + continue; + + if ((audio_dev->chip_ops == &drivers_i2c_da7219_ops) && + (codec == SSFC_AUDIO_CODEC_DA7219)) { + printk(BIOS_INFO, "enable DA7219.\n"); + continue; + } + + if ((audio_dev->chip_ops == &drivers_i2c_generic_ops) && + (codec == SSFC_AUDIO_CODEC_RT5682)) { + struct drivers_i2c_generic_config *cfg = + audio_dev->chip_info; + + if (cfg != NULL && !strcmp(cfg->hid, "10EC5682")) { + printk(BIOS_INFO, "enable RT5682.\n"); + continue; + } + } + + audio_dev->enabled = 0; + } +} + void mainboard_devtree_update(struct device *dev) { /* Apply common devtree updates. */ wifi_device_update(); + audio_codec_device_update(); /* Defer to variant for board-specific updates. */ variant_update_devtree(dev); diff --git a/src/mainboard/google/octopus/variants/baseboard/Makefile.inc b/src/mainboard/google/octopus/variants/baseboard/Makefile.inc index 63b03a6118..f28c3d6ce5 100644 --- a/src/mainboard/google/octopus/variants/baseboard/Makefile.inc +++ b/src/mainboard/google/octopus/variants/baseboard/Makefile.inc @@ -4,5 +4,6 @@ romstage-y += memory.c ramstage-y += gpio.c ramstage-y += nhlt.c +ramstage-y += cbi_ssfc.c smm-y += gpio.c diff --git a/src/mainboard/google/octopus/variants/baseboard/cbi_ssfc.c b/src/mainboard/google/octopus/variants/baseboard/cbi_ssfc.c new file mode 100644 index 0000000000..589f92e139 --- /dev/null +++ b/src/mainboard/google/octopus/variants/baseboard/cbi_ssfc.c @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include <baseboard/cbi_ssfc.h> +#include <console/console.h> +#include <ec/google/chromeec/ec.h> + +static int get_ssfc(uint32_t *val) +{ + static uint32_t known_value; + static enum { + SSFC_NOT_READ, + SSFC_AVAILABLE, + } ssfc_state = SSFC_NOT_READ; + + if (ssfc_state == SSFC_AVAILABLE) { + *val = known_value; + return 0; + } + + /* + * If SSFC field is not in the CBI then the value of SSFC will be 0 for + * further processing later since 0 of each bits group means default + * component in a variant. For more detail, please refer to cbi_ssfc.h. + */ + if (google_chromeec_cbi_get_ssfc(&known_value) != 0) { + printk(BIOS_DEBUG, "SSFC not set in CBI\n"); + return -1; + } + + ssfc_state = SSFC_AVAILABLE; + *val = known_value; + printk(BIOS_INFO, "SSFC 0x%x.\n", known_value); + + return 0; +} + +static unsigned int extract_field(uint32_t mask, int shift) +{ + uint32_t ssfc; + + /* On errors nothing is assumed to be set. */ + if (get_ssfc(&ssfc)) + return 0; + + return (ssfc >> shift) & mask; +} + +static enum ssfc_audio_codec ssfc_get_default_audio_codec(void) +{ + /* + * Octopus has two reference boards; yorp is with DA7219 and bip is with + * RT5682. Currently only AMPTON derived from bip so only it uses + * RT5682 as the default source in the first MP devices. + */ + if (CONFIG(BOARD_GOOGLE_AMPTON)) + return SSFC_AUDIO_CODEC_RT5682; + + return SSFC_AUDIO_CODEC_DA7219; +} + +enum ssfc_audio_codec ssfc_get_audio_codec(void) +{ + uint32_t codec = extract_field( + SSFC_AUDIO_CODEC_MASK, SSFC_AUDIO_CODEC_OFFSET); + + if (codec != SSFC_AUDIO_CODEC_DEFAULT) + return codec; + + return ssfc_get_default_audio_codec(); +} diff --git a/src/mainboard/google/octopus/variants/baseboard/include/baseboard/cbi_ssfc.h b/src/mainboard/google/octopus/variants/baseboard/include/baseboard/cbi_ssfc.h new file mode 100644 index 0000000000..84020d7eb3 --- /dev/null +++ b/src/mainboard/google/octopus/variants/baseboard/include/baseboard/cbi_ssfc.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _OCTOPUS_CBI_SSFC__H_ +#define _OCTOPUS_CBI_SSFC__H_ + +#include <inttypes.h> + +/**************************************************************************** + * Octopus CBI Second Source Factory Cache + * + * SSFC was introduced after variants were MPed already so we can expect there + * can be devices in the field without SSFC field in the CBI. For devices + * without SSFC field in the CBI, the value of SSFC will be 0 set by get_ssfc() + * in the cbi_ssfc.c. + * + * On the other hand, taking audio codec as the example there are two sources - + * DA7219 and RT5682 used in the MPed devices before introducing SSFC. As a + * result, the value 0 of each bits group for a specific component is defined as + * DEFAULT and different variants should transform this DEFAULT to one of + * sources they used as the first sources. In the example here, either DA7219 or + * RT5682 should be transformed. + */ + +/* + * Audio Codec (Bits 9-11) + * + */ +enum ssfc_audio_codec { + SSFC_AUDIO_CODEC_DEFAULT, + SSFC_AUDIO_CODEC_DA7219, + SSFC_AUDIO_CODEC_RT5682, +}; +#define SSFC_AUDIO_CODEC_OFFSET 9 +#define SSFC_AUDIO_CODEC_MASK 0x7 + +enum ssfc_audio_codec ssfc_get_audio_codec(void); + +#endif /* _OCTOPUS_CBI_SSFC__H_ */ diff --git a/src/mainboard/google/octopus/variants/baseboard/nhlt.c b/src/mainboard/google/octopus/variants/baseboard/nhlt.c index f1304f4720..9c9316c67a 100644 --- a/src/mainboard/google/octopus/variants/baseboard/nhlt.c +++ b/src/mainboard/google/octopus/variants/baseboard/nhlt.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ +#include <baseboard/cbi_ssfc.h> #include <baseboard/variants.h> #include <console/console.h> #include <nhlt.h> @@ -7,6 +8,8 @@ void __weak variant_nhlt_init(struct nhlt *nhlt) { + enum ssfc_audio_codec codec = ssfc_get_audio_codec(); + /* 2 Channel DMIC array. */ if (!nhlt_soc_add_dmic_array(nhlt, 2)) printk(BIOS_ERR, "Added 2CH DMIC array.\n"); @@ -19,13 +22,13 @@ void __weak variant_nhlt_init(struct nhlt *nhlt) * Headset codec is bi-directional but uses the same configuration * settings for render and capture endpoints. */ - if (CONFIG(NHLT_DA7219)) { + if (CONFIG(NHLT_DA7219) && codec == SSFC_AUDIO_CODEC_DA7219) { /* Dialog for Headset codec */ if (!nhlt_soc_add_da7219(nhlt, AUDIO_LINK_SSP2)) printk(BIOS_ERR, "Added Dialog_7219 codec.\n"); } - if (CONFIG(NHLT_RT5682)) { + if (CONFIG(NHLT_RT5682) && codec == SSFC_AUDIO_CODEC_RT5682) { /* Realtek for Headset codec */ if (!nhlt_soc_add_rt5682(nhlt, AUDIO_LINK_SSP2)) printk(BIOS_ERR, "Added ALC5682 codec.\n"); diff --git a/src/mainboard/google/octopus/variants/bobba/gpio.c b/src/mainboard/google/octopus/variants/bobba/gpio.c index fd94377582..11fe9b5eec 100644 --- a/src/mainboard/google/octopus/variants/bobba/gpio.c +++ b/src/mainboard/google/octopus/variants/bobba/gpio.c @@ -17,6 +17,10 @@ enum { static const struct pad_config default_override_table[] = { PAD_NC(GPIO_104, UP_20K), + /* GPIO_137 -- HP_INT_ODL and would be amend by SSFC. */ + PAD_CFG_GPI_APIC_IOS(GPIO_137, NONE, DEEP, LEVEL, INVERT, HIZCRx1, + DISPUPD), + /* EN_PP3300_TOUCHSCREEN */ PAD_CFG_GPO_IOSSTATE_IOSTERM(GPIO_146, 0, DEEP, NONE, Tx0RxDCRx0, DISPUPD), @@ -28,6 +32,10 @@ static const struct pad_config lte_override_table[] = { /* Default override table. */ PAD_NC(GPIO_104, UP_20K), + /* GPIO_137 -- HP_INT_ODL and would be amend by SSFC. */ + PAD_CFG_GPI_APIC_IOS(GPIO_137, NONE, DEEP, LEVEL, INVERT, HIZCRx1, + DISPUPD), + /* EN_PP3300_TOUCHSCREEN */ PAD_CFG_GPO_IOSSTATE_IOSTERM(GPIO_146, 0, DEEP, NONE, Tx0RxDCRx0, DISPUPD), diff --git a/src/mainboard/google/octopus/variants/bobba/overridetree.cb b/src/mainboard/google/octopus/variants/bobba/overridetree.cb index 3c7187e048..73adfef9ab 100644 --- a/src/mainboard/google/octopus/variants/bobba/overridetree.cb +++ b/src/mainboard/google/octopus/variants/bobba/overridetree.cb @@ -165,6 +165,19 @@ chip soc/intel/apollolake register "mic_amp_in_sel" = ""diff"" device i2c 1a on end end + chip drivers/i2c/generic + register "hid" = ""10EC5682"" + register "name" = ""RT58"" + register "desc" = ""Realtek RT5682"" + register "irq" = "ACPI_IRQ_LEVEL_LOW(GPIO_137_IRQ)" + register "probed" = "1" + register "property_count" = "1" + # Set the jd_src to RT5668_JD1 for jack detection + register "property_list[0].type" = "ACPI_DP_TYPE_INTEGER" + register "property_list[0].name" = ""realtek,jd-src"" + register "property_list[0].integer" = "1" + device i2c 1a on end + end end # - I2C 5 device pci 17.2 on chip drivers/i2c/generic |