diff --git a/src/soc/intel/skylake/Kconfig b/src/soc/intel/skylake/Kconfig index 1f7be57642..76459c9bca 100644 --- a/src/soc/intel/skylake/Kconfig +++ b/src/soc/intel/skylake/Kconfig @@ -11,6 +11,7 @@ config CPU_SPECIFIC_OPTIONS select ARCH_RAMSTAGE_X86_32 select ARCH_ROMSTAGE_X86_32 select ARCH_VERSTAGE_X86_32 + select ACPI_NHLT select BACKUP_DEFAULT_SMM_REGION select CACHE_MRC_SETTINGS select CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM if RELOCATABLE_RAMSTAGE @@ -139,4 +140,34 @@ config CHIPSET_BOOTBLOCK_INCLUDE string default "soc/intel/skylake/bootblock/timestamp.inc" +config NHLT_DMIC_2CH + bool + default n + help + Include DSP firmware settings for 2 channel DMIC array. + +config NHLT_DMIC_4CH + bool + default n + help + Include DSP firmware settings for 4 channel DMIC array. + +config NHLT_NAU88L25 + bool + default n + help + Include DSP firmware settings for nau88l25 headset codec. + +config NHLT_MAX98357 + bool + default n + help + Include DSP firmware settings for max98357 amplifier. + +config NHLT_SSM4567 + bool + default n + help + Include DSP firmware settings for ssm4567 smart amplifier. + endif diff --git a/src/soc/intel/skylake/Makefile.inc b/src/soc/intel/skylake/Makefile.inc index 9dd4cac8c3..d6c2212310 100644 --- a/src/soc/intel/skylake/Makefile.inc +++ b/src/soc/intel/skylake/Makefile.inc @@ -1,5 +1,6 @@ ifeq ($(CONFIG_SOC_INTEL_SKYLAKE),y) +subdirs-y += nhlt subdirs-y += romstage subdirs-y += ../../../cpu/intel/microcode subdirs-y += ../../../cpu/intel/turbo diff --git a/src/soc/intel/skylake/include/soc/nhlt.h b/src/soc/intel/skylake/include/soc/nhlt.h new file mode 100644 index 0000000000..3800bb978d --- /dev/null +++ b/src/soc/intel/skylake/include/soc/nhlt.h @@ -0,0 +1,64 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2015 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _SOC_NHLT_H_ +#define _SOC_NHLT_H_ + +#include + +/* + * Skylake NHLT device and hardware link types. These values are to be used + * with nhlt_soc_add_endpoint(). + */ + +enum { + AUDIO_LINK_SSP0, + AUDIO_LINK_SSP1, + AUDIO_LINK_SSP2, /* Only Bluetooth supported on SSP2. */ + AUDIO_LINK_DMIC, +}; + +enum { + AUDIO_DEV_I2S, + AUDIO_DEV_DMIC, + AUDIO_DEV_BT, +}; + +/* + * Add a dmic array composed of the provided number of channels. The skylake + * SoC currently only supports dmic arrays on the dmic signals. Either 2 + * or 4 channel arrays are supported. Returns 0 on success, < 0 on error. + */ +int nhlt_soc_add_dmic_array(struct nhlt *nhlt, int num_channels); + +/* + * Add nau88l25 headset codec on provided SSP link. Return 0 on succes, < 0 + * on error. + */ +int nhlt_soc_add_nau88l25(struct nhlt *nhlt, int hwlink); + +/* + * Add ssm4567 smart amplifiers in stereo configuration on provided SSP link. + * Return 0 on success, < 0 on error. + */ +int nhlt_soc_add_ssm4567(struct nhlt *nhlt, int hwlink); + +/* + * Add max98357a amplifier in stereo configuration on provide SSP link. + * Return 0 on success, < 0 on error. + */ +int nhlt_soc_add_max98357(struct nhlt *nhlt, int hwlink); + +#endif diff --git a/src/soc/intel/skylake/nhlt/Makefile.inc b/src/soc/intel/skylake/nhlt/Makefile.inc new file mode 100644 index 0000000000..201dad5328 --- /dev/null +++ b/src/soc/intel/skylake/nhlt/Makefile.inc @@ -0,0 +1,43 @@ +ramstage-y += nhlt.c +ramstage-y += dmic.c +ramstage-y += nau88l25.c +ramstage-y += max98357.c +ramstage-y += ssm4567.c + +# DSP firmware settings files. +NHLT_BLOB_PATH = 3rdparty/blobs/soc/intel/skylake +DMIC_2CH_48KHZ_16B = dmic-2ch-48khz-16b.bin +DMIC_2CH_48KHZ_32B = dmic-2ch-48khz-32b.bin +DMIC_4CH_48KHZ_16B = dmic-4ch-48khz-16b.bin +DMIC_4CH_48KHZ_32B = dmic-4ch-48khz-32b.bin +NAU88L25 = nau88l25-2ch-48khz-24b.bin +MAX98357_RENDER = max98357-render-2ch-48khz-24b.bin +SSM4567_RENDER = ssm4567-render-2ch-48khz-24b.bin + +cbfs-files-$(CONFIG_NHLT_DMIC_2CH) += $(DMIC_2CH_48KHZ_16B) +$(DMIC_2CH_48KHZ_16B)-file := $(NHLT_BLOB_PATH)/$(DMIC_2CH_48KHZ_16B) +$(DMIC_2CH_48KHZ_16B)-type := raw + +cbfs-files-$(CONFIG_NHLT_DMIC_2CH) += $(DMIC_2CH_48KHZ_32B) +$(DMIC_2CH_48KHZ_32B)-file := $(NHLT_BLOB_PATH)/$(DMIC_2CH_48KHZ_32B) +$(DMIC_2CH_48KHZ_32B)-type := raw + +cbfs-files-$(CONFIG_NHLT_DMIC_4CH) += $(DMIC_4CH_48KHZ_16B) +$(DMIC_4CH_48KHZ_16B)-file := $(NHLT_BLOB_PATH)/$(DMIC_4CH_48KHZ_16B) +$(DMIC_4CH_48KHZ_16B)-type := raw + +cbfs-files-$(CONFIG_NHLT_DMIC_4CH) += $(DMIC_4CH_48KHZ_32B) +$(DMIC_4CH_48KHZ_32B)-file := $(NHLT_BLOB_PATH)/$(DMIC_4CH_48KHZ_32B) +$(DMIC_4CH_48KHZ_32B)-type := raw + +cbfs-files-$(CONFIG_NHLT_NAU88L25) += $(NAU88L25) +$(NAU88L25)-file := $(NHLT_BLOB_PATH)/$(NAU88L25) +$(NAU88L25)-type := raw + +cbfs-files-$(CONFIG_NHLT_MAX98357) += $(MAX98357_RENDER) +$(MAX98357_RENDER)-file := $(NHLT_BLOB_PATH)/$(MAX98357_RENDER) +$(MAX98357_RENDER)-type := raw + +cbfs-files-$(CONFIG_NHLT_SSM4567) += $(SSM4567_RENDER) +$(SSM4567_RENDER)-file := $(NHLT_BLOB_PATH)/$(SSM4567_RENDER) +$(SSM4567_RENDER)-type := raw diff --git a/src/soc/intel/skylake/nhlt/dmic.c b/src/soc/intel/skylake/nhlt/dmic.c new file mode 100644 index 0000000000..0aadbb20df --- /dev/null +++ b/src/soc/intel/skylake/nhlt/dmic.c @@ -0,0 +1,99 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2015 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +static const struct nhlt_format_config dmic_2ch_cfg[] = { + /* 48 KHz 16-bits per sample. */ + { + .num_channels = 2, + .sample_freq_khz = 48, + .container_bits_per_sample = 16, + .valid_bits_per_sample = 16, + .speaker_mask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT, + .settings_file = "dmic-2ch-48khz-16b.bin", + }, + /* 48 KHz 32-bits per sample. */ + { + .num_channels = 2, + .sample_freq_khz = 48, + .container_bits_per_sample = 32, + .valid_bits_per_sample = 32, + .speaker_mask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT, + .settings_file = "dmic-2ch-48khz-32b.bin", + }, +}; + +static const struct nhlt_format_config dmic_4ch_cfg[] = { + /* 48 KHz 16-bits per sample. */ + { + .num_channels = 4, + .sample_freq_khz = 48, + .container_bits_per_sample = 16, + .valid_bits_per_sample = 16, + .speaker_mask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | + SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT, + .settings_file = "dmic-4ch-48khz-16b.bin", + }, + /* 48 KHz 32-bits per sample. */ + { + .num_channels = 4, + .sample_freq_khz = 48, + .container_bits_per_sample = 32, + .valid_bits_per_sample = 32, + .speaker_mask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | + SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT, + .settings_file = "dmic-4ch-48khz-32b.bin", + }, +}; + +int nhlt_soc_add_dmic_array(struct nhlt *nhlt, int num_channels) +{ + struct nhlt_endpoint *endp; + struct nhlt_dmic_array_config mic_config; + const struct nhlt_format_config *formats; + size_t num_formats; + + if (num_channels != 2 && num_channels != 4) + return -1; + + endp = nhlt_soc_add_endpoint(nhlt, AUDIO_LINK_DMIC, AUDIO_DEV_DMIC, + NHLT_DIR_CAPTURE); + + if (endp == NULL) + return -1; + + memset(&mic_config, 0, sizeof(mic_config)); + mic_config.tdm_config.config_type = NHLT_TDM_MIC_ARRAY; + + switch (num_channels) { + case 2: + formats = dmic_2ch_cfg; + num_formats = ARRAY_SIZE(dmic_2ch_cfg); + mic_config.array_type = NHLT_MIC_ARRAY_2CH_SMALL; + break; + case 4: + formats = dmic_4ch_cfg; + num_formats = ARRAY_SIZE(dmic_4ch_cfg); + mic_config.array_type = NHLT_MIC_ARRAY_4CH_L_SHAPED; + break; + } + + if (nhlt_endpoint_append_config(endp, &mic_config, sizeof(mic_config))) + return -1; + + return nhlt_endpoint_add_formats(endp, formats, num_formats); +} diff --git a/src/soc/intel/skylake/nhlt/max98357.c b/src/soc/intel/skylake/nhlt/max98357.c new file mode 100644 index 0000000000..fa14dd2f61 --- /dev/null +++ b/src/soc/intel/skylake/nhlt/max98357.c @@ -0,0 +1,48 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2015 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +static const struct nhlt_format_config max98357_render_cfg[] = { + /* 48 KHz 24-bits per sample. */ + { + .num_channels = 2, + .sample_freq_khz = 48, + .container_bits_per_sample = 32, + .valid_bits_per_sample = 24, + .speaker_mask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT, + .settings_file = "max98357-render-2ch-48khz-24b.bin", + }, +}; + +int nhlt_soc_add_max98357(struct nhlt *nhlt, int hwlink) +{ + struct nhlt_endpoint *endp; + + /* Render Endpoint */ + endp = nhlt_soc_add_endpoint(nhlt, hwlink, AUDIO_DEV_I2S, + NHLT_DIR_RENDER); + + if (endp == NULL) + return -1; + + if (nhlt_endpoint_add_formats(endp, max98357_render_cfg, + ARRAY_SIZE(max98357_render_cfg))) + return -1; + + nhlt_next_instance(nhlt, NHLT_LINK_SSP); + + return 0; +} diff --git a/src/soc/intel/skylake/nhlt/nau88l25.c b/src/soc/intel/skylake/nhlt/nau88l25.c new file mode 100644 index 0000000000..d9b9cbd849 --- /dev/null +++ b/src/soc/intel/skylake/nhlt/nau88l25.c @@ -0,0 +1,73 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2015 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +/* The same DSP firmwware settings are used for both the capture and + * render endpoints. */ +static const struct nhlt_format_config nau88l25_cfg[] = { + /* 48 KHz 24-bits per sample. */ + { + .num_channels = 2, + .sample_freq_khz = 48, + .container_bits_per_sample = 32, + .valid_bits_per_sample = 24, + .speaker_mask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT, + .settings_file = "nau88l25-2ch-48khz-24b.bin", + }, +}; + +int nhlt_soc_add_nau88l25(struct nhlt *nhlt, int hwlink) +{ + struct nhlt_endpoint *endp; + /* The nau88l25 just has headphones and a mic. Both the capture and + * render endpoints occupy the same virtual slot. */ + struct nhlt_tdm_config tdm_config = { + .virtual_slot = 0, + .config_type = NHLT_TDM_BASIC, + }; + const void *fmt_cfg = nau88l25_cfg; + size_t fmt_sz = ARRAY_SIZE(nau88l25_cfg); + + /* Render Endpoint */ + endp = nhlt_soc_add_endpoint(nhlt, hwlink, AUDIO_DEV_I2S, + NHLT_DIR_RENDER); + + if (endp == NULL) + return -1; + + if (nhlt_endpoint_append_config(endp, &tdm_config, sizeof(tdm_config))) + return -1; + + if (nhlt_endpoint_add_formats(endp, fmt_cfg, fmt_sz)) + return -1; + + /* Capture Endpoint */ + endp = nhlt_soc_add_endpoint(nhlt, hwlink, AUDIO_DEV_I2S, + NHLT_DIR_CAPTURE); + + if (endp == NULL) + return -1; + + if (nhlt_endpoint_append_config(endp, &tdm_config, sizeof(tdm_config))) + return -1; + + if (nhlt_endpoint_add_formats(endp, fmt_cfg, fmt_sz)) + return -1; + + nhlt_next_instance(nhlt, NHLT_LINK_SSP); + + return 0; +} diff --git a/src/soc/intel/skylake/nhlt/nhlt.c b/src/soc/intel/skylake/nhlt/nhlt.c new file mode 100644 index 0000000000..56e7d39254 --- /dev/null +++ b/src/soc/intel/skylake/nhlt/nhlt.c @@ -0,0 +1,102 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2015 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include + +#define NHLT_VID 0x8086 +#define NHLT_DID_DMIC 0xae20 +#define NHLT_DID_BT 0xae30 +#define NHLT_DID_SSP 0xae34 + +struct nhlt_endpoint *nhlt_soc_add_endpoint(struct nhlt *nhlt, int soc_hwintf, + int soc_devtype, int dir) +{ + int nhlt_link_type; + int nhlt_dev_type; + uint16_t did; + struct nhlt_endpoint *endp; + + /* Check link type and device type. */ + switch (soc_hwintf) { + case AUDIO_LINK_SSP0: + case AUDIO_LINK_SSP1: + /* Only I2S devices on SSP0 and SSP1. */ + if (soc_devtype != AUDIO_DEV_I2S) + return NULL; + nhlt_link_type = NHLT_LINK_SSP; + break; + case AUDIO_LINK_SSP2: + /* Only Bluetooth devices on SSP2. */ + if (soc_devtype != AUDIO_DEV_BT) + return NULL; + nhlt_link_type = NHLT_LINK_SSP; + break; + case AUDIO_LINK_DMIC: + /* Only DMIC devices on DMIC links. */ + if (soc_devtype != AUDIO_DEV_DMIC) + return NULL; + nhlt_link_type = NHLT_LINK_PDM; + break; + default: + return NULL; + } + + switch (soc_devtype) { + case AUDIO_DEV_I2S: + nhlt_dev_type = NHLT_SSP_DEV_I2S; + did = NHLT_DID_SSP; + break; + case AUDIO_DEV_DMIC: + nhlt_dev_type = NHLT_PDM_DEV; + did = NHLT_DID_DMIC; + break; + case AUDIO_DEV_BT: + nhlt_dev_type = NHLT_SSP_DEV_BT; + did = NHLT_DID_BT; + break; + default: + return NULL; + } + + endp = nhlt_add_endpoint(nhlt, nhlt_link_type, nhlt_dev_type, dir, + NHLT_VID, did); + + if (endp == NULL) + return NULL; + + /* Virtual bus id of SSP links are the hardware port ids proper. */ + if (nhlt_link_type == NHLT_LINK_SSP) + endp->virtual_bus_id = soc_hwintf; + + return endp; +} + +uintptr_t nhlt_soc_serialize(struct nhlt *nhlt, uintptr_t acpi_addr) +{ + global_nvs_t *gnvs; + + gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS); + + if (gnvs == NULL) + return acpi_addr; + + /* Update NHLT GNVS Data */ + gnvs->nhla = (uintptr_t)acpi_addr; + gnvs->nhll = nhlt_current_size(nhlt); + + return nhlt_serialize(nhlt, acpi_addr); +} diff --git a/src/soc/intel/skylake/nhlt/ssm4567.c b/src/soc/intel/skylake/nhlt/ssm4567.c new file mode 100644 index 0000000000..f531e25a35 --- /dev/null +++ b/src/soc/intel/skylake/nhlt/ssm4567.c @@ -0,0 +1,48 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2015 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +static const struct nhlt_format_config ssm4567_render_cfg[] = { + /* 48 KHz 24-bits per sample. */ + { + .num_channels = 2, + .sample_freq_khz = 48, + .container_bits_per_sample = 32, + .valid_bits_per_sample = 24, + .speaker_mask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT, + .settings_file = "ssm4567-render-2ch-48khz-24b.bin", + }, +}; + +int nhlt_soc_add_ssm4567(struct nhlt *nhlt, int hwlink) +{ + struct nhlt_endpoint *endp; + + /* Render Endpoint */ + endp = nhlt_soc_add_endpoint(nhlt, hwlink, AUDIO_DEV_I2S, + NHLT_DIR_RENDER); + + if (endp == NULL) + return -1; + + if (nhlt_endpoint_add_formats(endp, ssm4567_render_cfg, + ARRAY_SIZE(ssm4567_render_cfg))) + return -1; + + nhlt_next_instance(nhlt, NHLT_LINK_SSP); + + return 0; +}