From ed8a723f4259ddc182b78c2d70930a9cc5266f87 Mon Sep 17 00:00:00 2001 From: Aaron Durbin Date: Tue, 24 Nov 2015 12:35:06 -0600 Subject: intel/skylake: add nhlt support The use of a NHLT table is required to make audio work on the skylake SoCs employing the internal DSP. The table describes the audo endpoints (render vs capture) along with their supported formats. These formats are not only dependent on the audio peripheral but also hardware interfaces. As such each format has an associated blob of DSP settings to make the peripheral work. Lastly, each of these settings are provided by Intel and need to be generated for each device's hardware connection plus mode/format it supports. This patch does not include the dsp setting blobs. The current supported connections: - digital mic array 2 channel - digital mic array 4 channel - Maxim 98357 amplifier - ADI ssm4567 - NAU88L25 headset codec BUG=chrome-os-partner:44481 BRANCH=None TEST=Built glados. Speakers, headphones, and mic on camera decently worked. CQ-DEPEND=CL:*239598 Change-Id: If1a9be97573b9b160893944661790cac7df26fca Signed-off-by: Patrick Georgi Original-Commit-Id: 1f5514e27811c500732de97e1cc7edeced2607e7 Original-Change-Id: Ib42e895f00e7605cb30ce24d9b8dd00bf68a7477 Original-Signed-off-by: Aaron Durbin Original-Reviewed-on: https://chromium-review.googlesource.com/313998 Original-Reviewed-by: Duncan Laurie Reviewed-on: https://review.coreboot.org/12938 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth --- src/soc/intel/skylake/Kconfig | 31 ++++++++++ src/soc/intel/skylake/Makefile.inc | 1 + src/soc/intel/skylake/include/soc/nhlt.h | 64 +++++++++++++++++++ src/soc/intel/skylake/nhlt/Makefile.inc | 43 +++++++++++++ src/soc/intel/skylake/nhlt/dmic.c | 99 ++++++++++++++++++++++++++++++ src/soc/intel/skylake/nhlt/max98357.c | 48 +++++++++++++++ src/soc/intel/skylake/nhlt/nau88l25.c | 73 ++++++++++++++++++++++ src/soc/intel/skylake/nhlt/nhlt.c | 102 +++++++++++++++++++++++++++++++ src/soc/intel/skylake/nhlt/ssm4567.c | 48 +++++++++++++++ 9 files changed, 509 insertions(+) create mode 100644 src/soc/intel/skylake/include/soc/nhlt.h create mode 100644 src/soc/intel/skylake/nhlt/Makefile.inc create mode 100644 src/soc/intel/skylake/nhlt/dmic.c create mode 100644 src/soc/intel/skylake/nhlt/max98357.c create mode 100644 src/soc/intel/skylake/nhlt/nau88l25.c create mode 100644 src/soc/intel/skylake/nhlt/nhlt.c create mode 100644 src/soc/intel/skylake/nhlt/ssm4567.c (limited to 'src') 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; +} -- cgit v1.2.3