Saurabh Satija (saurabh.satija@intel.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/15023
-gerrit
commit 28458cc9e9f9f307cc835a89d6b8f5c2f23c253e Author: Saurabh Satija saurabh.satija@intel.com Date: Thu Jun 23 14:46:27 2016 -0700
lib/nhlt: Add common NHLT audio for Intel platforms
The use of a NHLT table is required to make audio work on the Intel SoCs employing the internal DSP. The table describes the audio 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.
Change-Id: I3c75d3537288c47d29e8949ca253ea8c5c1a387d Signed-off-by: Saurabh Satija saurabh.satija@intel.com --- src/include/nhlt.h | 44 +++++++++++++++ src/lib/nhlt.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 199 insertions(+), 2 deletions(-)
diff --git a/src/include/nhlt.h b/src/include/nhlt.h index f0b3b6f..c728764 100644 --- a/src/include/nhlt.h +++ b/src/include/nhlt.h @@ -23,6 +23,34 @@ struct nhlt; struct nhlt_endpoint; struct nhlt_format; struct nhlt_format_config; +struct nhlt_tdm_config; + +/* + * Add a dmic array composed of the provided number of channels. + * Returns 0 on success, < 0 on error. + */ +int nhlt_add_dmic_array(struct nhlt *nhlt, int num_channels, + const struct nhlt_format_config *dmic_ch_config, int num_fmt); + +/* + * Add audio codec on provided SSP link. Return 0 on succes, < 0 on error. + * + * The same DSP firmware settings can be used for both the capture and render + * endpoints in some cases. Most of the smart amps use different DSP firmware + * settings for capture and render endpoints. + * + * render_cfg, capture_cfg: These are the audio codec configuration defined + * in mainboard souce code. + * cfg_size: This is the number of configurations defined in codec config. + * Each configuration is added as an endpoint. + * tdm_config: This is also board specific and defined in mainboard.c + * hwlink: This is the SSP hardware port number. + * direction: This can be Render only, Capture only or Bi-directional. + */ +int nhlt_add_codec_on_ssp(struct nhlt *nhlt, int hwlink, + const struct nhlt_format_config *render_cfg, int r_num_fmt, + const struct nhlt_format_config *capture_cfg, int c_num_fmt, + const struct nhlt_tdm_config *tdm_config, size_t tdm_size);
/* * Non HD Audio ACPI support. This table is typically used for Intel Smart @@ -108,6 +136,13 @@ int nhlt_endpoint_add_formats(struct nhlt_endpoint *endpoint, const struct nhlt_format_config *formats, size_t num_formats);
+/* Returns corresponding nhlt link type based on hardware link number. + * Hardware link number is the SSP port number on which the particular + * is present. This is specified in mainboard.c. + * This is defined in soc/nhlt.c + */ +int nhlt_soc_get_link_type(int hwlink, int soc_devtype); + /* * Increment the instance id for a given link type. This function is * used for marking a device being completely added to the NHLT object. @@ -148,6 +183,15 @@ uintptr_t nhlt_soc_serialize(struct nhlt *nhlt, uintptr_t acpi_addr); uintptr_t nhlt_soc_serialize_oem_overrides(struct nhlt *nhlt, uintptr_t acpi_addr, const char *oem_id, const char *oem_table_id);
+/* + * NHLT device types. These values are used with nhlt_soc_add_endpoint(). + */ +enum { + AUDIO_DEV_I2S, + AUDIO_DEV_DMIC, + AUDIO_DEV_BT, +}; + /* Link and device types. */ enum { NHLT_LINK_HDA, diff --git a/src/lib/nhlt.c b/src/lib/nhlt.c index 11a397c..0746efa 100644 --- a/src/lib/nhlt.c +++ b/src/lib/nhlt.c @@ -15,9 +15,12 @@
#include <arch/acpi.h> #include <cbfs.h> +#include <cbmem.h> #include <commonlib/endian.h> #include <console/console.h> #include <nhlt.h> +#include <soc/nvs.h> +#include <soc/nhlt.h> #include <stdlib.h> #include <string.h>
@@ -47,8 +50,7 @@ struct nhlt *nhlt_init(void) }
struct nhlt_endpoint *nhlt_add_endpoint(struct nhlt *nhlt, int link_type, - int device_type, int dir, - uint16_t vid, uint16_t did) + int device_type, int dir, uint16_t vid, uint16_t did) { struct nhlt_endpoint *endp;
@@ -437,3 +439,154 @@ uintptr_t nhlt_serialize_oem_overrides(struct nhlt *nhlt,
return acpi_addr; } + +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; + + nhlt_link_type = nhlt_soc_get_link_type(soc_hwintf, soc_devtype); + + if (nhlt_link_type == -1) + 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 link is the hardware port id. */ + 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) +{ + return nhlt_soc_serialize_oem_overrides(nhlt, acpi_addr, NULL, NULL); +} + +uintptr_t nhlt_soc_serialize_oem_overrides(struct nhlt *nhlt, + uintptr_t acpi_addr, const char *oem_id, const char *oem_table_id) +{ + struct 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_oem_overrides(nhlt, acpi_addr, oem_id, + oem_table_id); +} + +int nhlt_add_dmic_array(struct nhlt *nhlt, int num_channels, + const struct nhlt_format_config *dmic_ch_cfg, int num_fmt) +{ + struct nhlt_endpoint *endp; + struct nhlt_dmic_array_config mic_config; + + 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: + mic_config.array_type = NHLT_MIC_ARRAY_2CH_SMALL; + break; + case 4: + 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, dmic_ch_cfg, num_fmt); +} + +int nhlt_add_codec_on_ssp(struct nhlt *nhlt, int hwlink, + const struct nhlt_format_config *render_cfg, int r_num_fmt, + const struct nhlt_format_config *capture_cfg, int c_num_fmt, + const struct nhlt_tdm_config *tdm_config, size_t tdm_size) +{ + struct nhlt_endpoint *endp; + + /* For Bi-directional amplifiers, both capture and render + * configuratoins are needed. + */ + if (render_cfg == NULL && capture_cfg == NULL) + return -1; + + /* Render Endpoint */ + if (render_cfg != NULL) { + endp = nhlt_soc_add_endpoint(nhlt, hwlink, AUDIO_DEV_I2S, + NHLT_DIR_RENDER); + if (endp == NULL) + return -1; + + if (tdm_config != NULL) { + if (nhlt_endpoint_append_config(endp, tdm_config, + tdm_size)) + return -1; + } + + if (nhlt_endpoint_add_formats(endp, render_cfg, r_num_fmt)) + return -1; + } + + /* Capture Endpoint */ + if (capture_cfg != NULL) { + endp = nhlt_soc_add_endpoint(nhlt, hwlink, AUDIO_DEV_I2S, + NHLT_DIR_CAPTURE); + if (endp == NULL) + return -1; + + if (tdm_config != NULL) { + if (nhlt_endpoint_append_config(endp, tdm_config, + tdm_size)) + return -1; + } + + if (nhlt_endpoint_add_formats(endp, capture_cfg, c_num_fmt)) + return -1; + } + + nhlt_next_instance(nhlt, NHLT_LINK_SSP); + + return 0; +}