mb/google/octopus: add audio codec into SSFC support for Bobba
BUG=b:174118027 BRANCH=octopus TEST=adjust SSFC value of CBI to select RT5682 or DA7219 then check whether device tree is updated correspondingly by disabling unselected one. Signed-off-by: Marco Chen <marcochen@google.com> Change-Id: Id37c4c5716ade0851cfcb24e12b390841e633ac9 Reviewed-on: https://review.coreboot.org/c/coreboot/+/48795 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Zhuohao Lee <zhuohao@chromium.org>
This commit is contained in:
parent
3f80a7aa6d
commit
07c80b2164
|
@ -34,6 +34,7 @@ config BOARD_GOOGLE_BOBBA
|
||||||
select BASEBOARD_OCTOPUS_LAPTOP
|
select BASEBOARD_OCTOPUS_LAPTOP
|
||||||
select BOARD_GOOGLE_BASEBOARD_OCTOPUS
|
select BOARD_GOOGLE_BASEBOARD_OCTOPUS
|
||||||
select NHLT_DA7219 if INCLUDE_NHLT_BLOBS
|
select NHLT_DA7219 if INCLUDE_NHLT_BLOBS
|
||||||
|
select NHLT_RT5682 if INCLUDE_NHLT_BLOBS
|
||||||
|
|
||||||
config BOARD_GOOGLE_MEEP
|
config BOARD_GOOGLE_MEEP
|
||||||
bool "-> Meep"
|
bool "-> Meep"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
|
||||||
#include <acpi/acpi.h>
|
#include <acpi/acpi.h>
|
||||||
|
#include <baseboard/cbi_ssfc.h>
|
||||||
#include <baseboard/variants.h>
|
#include <baseboard/variants.h>
|
||||||
#include <boardid.h>
|
#include <boardid.h>
|
||||||
#include <bootstate.h>
|
#include <bootstate.h>
|
||||||
|
@ -8,6 +9,7 @@
|
||||||
#include <device/device.h>
|
#include <device/device.h>
|
||||||
#include <device/pci_def.h>
|
#include <device/pci_def.h>
|
||||||
#include <device/pci_ops.h>
|
#include <device/pci_ops.h>
|
||||||
|
#include <drivers/i2c/generic/chip.h>
|
||||||
#include <ec/google/chromeec/ec.h>
|
#include <ec/google/chromeec/ec.h>
|
||||||
#include <ec/ec.h>
|
#include <ec/ec.h>
|
||||||
#include <intelblocks/xhci.h>
|
#include <intelblocks/xhci.h>
|
||||||
|
@ -22,6 +24,9 @@
|
||||||
#include <variant/ec.h>
|
#include <variant/ec.h>
|
||||||
#include <variant/gpio.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)
|
static bool is_cnvi_held_in_reset(void)
|
||||||
{
|
{
|
||||||
struct device *dev = pcidev_path_on_root(PCH_DEVFN_CNVI);
|
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_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)
|
static void mainboard_init(void *chip_info)
|
||||||
{
|
{
|
||||||
int boardid;
|
int boardid;
|
||||||
|
@ -58,6 +98,8 @@ static void mainboard_init(void *chip_info)
|
||||||
|
|
||||||
base_pads = variant_base_gpio_table(&base_num);
|
base_pads = variant_base_gpio_table(&base_num);
|
||||||
override_pads = variant_override_gpio_table(&override_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,
|
gpio_configure_pads_with_override(base_pads, base_num,
|
||||||
override_pads, override_num);
|
override_pads, override_num);
|
||||||
|
@ -128,10 +170,47 @@ static void wifi_device_update(void)
|
||||||
dev->enabled = 0;
|
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)
|
void mainboard_devtree_update(struct device *dev)
|
||||||
{
|
{
|
||||||
/* Apply common devtree updates. */
|
/* Apply common devtree updates. */
|
||||||
wifi_device_update();
|
wifi_device_update();
|
||||||
|
audio_codec_device_update();
|
||||||
|
|
||||||
/* Defer to variant for board-specific updates. */
|
/* Defer to variant for board-specific updates. */
|
||||||
variant_update_devtree(dev);
|
variant_update_devtree(dev);
|
||||||
|
|
|
@ -4,5 +4,6 @@ romstage-y += memory.c
|
||||||
|
|
||||||
ramstage-y += gpio.c
|
ramstage-y += gpio.c
|
||||||
ramstage-y += nhlt.c
|
ramstage-y += nhlt.c
|
||||||
|
ramstage-y += cbi_ssfc.c
|
||||||
|
|
||||||
smm-y += gpio.c
|
smm-y += gpio.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();
|
||||||
|
}
|
|
@ -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_ */
|
|
@ -1,5 +1,6 @@
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
|
||||||
|
#include <baseboard/cbi_ssfc.h>
|
||||||
#include <baseboard/variants.h>
|
#include <baseboard/variants.h>
|
||||||
#include <console/console.h>
|
#include <console/console.h>
|
||||||
#include <nhlt.h>
|
#include <nhlt.h>
|
||||||
|
@ -7,6 +8,8 @@
|
||||||
|
|
||||||
void __weak variant_nhlt_init(struct nhlt *nhlt)
|
void __weak variant_nhlt_init(struct nhlt *nhlt)
|
||||||
{
|
{
|
||||||
|
enum ssfc_audio_codec codec = ssfc_get_audio_codec();
|
||||||
|
|
||||||
/* 2 Channel DMIC array. */
|
/* 2 Channel DMIC array. */
|
||||||
if (!nhlt_soc_add_dmic_array(nhlt, 2))
|
if (!nhlt_soc_add_dmic_array(nhlt, 2))
|
||||||
printk(BIOS_ERR, "Added 2CH DMIC array.\n");
|
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
|
* Headset codec is bi-directional but uses the same configuration
|
||||||
* settings for render and capture endpoints.
|
* settings for render and capture endpoints.
|
||||||
*/
|
*/
|
||||||
if (CONFIG(NHLT_DA7219)) {
|
if (CONFIG(NHLT_DA7219) && codec == SSFC_AUDIO_CODEC_DA7219) {
|
||||||
/* Dialog for Headset codec */
|
/* Dialog for Headset codec */
|
||||||
if (!nhlt_soc_add_da7219(nhlt, AUDIO_LINK_SSP2))
|
if (!nhlt_soc_add_da7219(nhlt, AUDIO_LINK_SSP2))
|
||||||
printk(BIOS_ERR, "Added Dialog_7219 codec.\n");
|
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 */
|
/* Realtek for Headset codec */
|
||||||
if (!nhlt_soc_add_rt5682(nhlt, AUDIO_LINK_SSP2))
|
if (!nhlt_soc_add_rt5682(nhlt, AUDIO_LINK_SSP2))
|
||||||
printk(BIOS_ERR, "Added ALC5682 codec.\n");
|
printk(BIOS_ERR, "Added ALC5682 codec.\n");
|
||||||
|
|
|
@ -17,6 +17,10 @@ enum {
|
||||||
static const struct pad_config default_override_table[] = {
|
static const struct pad_config default_override_table[] = {
|
||||||
PAD_NC(GPIO_104, UP_20K),
|
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 */
|
/* EN_PP3300_TOUCHSCREEN */
|
||||||
PAD_CFG_GPO_IOSSTATE_IOSTERM(GPIO_146, 0, DEEP, NONE, Tx0RxDCRx0,
|
PAD_CFG_GPO_IOSSTATE_IOSTERM(GPIO_146, 0, DEEP, NONE, Tx0RxDCRx0,
|
||||||
DISPUPD),
|
DISPUPD),
|
||||||
|
@ -28,6 +32,10 @@ static const struct pad_config lte_override_table[] = {
|
||||||
/* Default override table. */
|
/* Default override table. */
|
||||||
PAD_NC(GPIO_104, UP_20K),
|
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 */
|
/* EN_PP3300_TOUCHSCREEN */
|
||||||
PAD_CFG_GPO_IOSSTATE_IOSTERM(GPIO_146, 0, DEEP, NONE, Tx0RxDCRx0,
|
PAD_CFG_GPO_IOSSTATE_IOSTERM(GPIO_146, 0, DEEP, NONE, Tx0RxDCRx0,
|
||||||
DISPUPD),
|
DISPUPD),
|
||||||
|
|
|
@ -165,6 +165,19 @@ chip soc/intel/apollolake
|
||||||
register "mic_amp_in_sel" = ""diff""
|
register "mic_amp_in_sel" = ""diff""
|
||||||
device i2c 1a on end
|
device i2c 1a on end
|
||||||
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
|
end # - I2C 5
|
||||||
device pci 17.2 on
|
device pci 17.2 on
|
||||||
chip drivers/i2c/generic
|
chip drivers/i2c/generic
|
||||||
|
|
Loading…
Reference in New Issue