Loading sound/soc/intel/skylake/skl-nhlt.h→include/sound/intel-nhlt.h +41 −10 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * skl-nhlt.h - Intel HDA Platform NHLT header * intel-nhlt.h - Intel HDA Platform NHLT header * * Copyright (C) 2015 Intel Corp * Author: Sanjiv Kumar <sanjiv.kumar@intel.com> * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Copyright (c) 2015-2019 Intel Corporation */ #ifndef __SKL_NHLT_H__ #define __SKL_NHLT_H__ #ifndef __INTEL_NHLT_H__ #define __INTEL_NHLT_H__ #include <linux/acpi.h> #if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_INTEL_NHLT) struct wav_fmt { u16 fmt_tag; u16 channels; Loading Loading @@ -97,16 +96,22 @@ struct nhlt_resource_desc { #define MIC_ARRAY_2CH 2 #define MIC_ARRAY_4CH 4 struct nhlt_tdm_config { struct nhlt_device_specific_config { u8 virtual_slot; u8 config_type; } __packed; struct nhlt_dmic_array_config { struct nhlt_tdm_config tdm_config; struct nhlt_device_specific_config device_config; u8 array_type; } __packed; struct nhlt_vendor_dmic_array_config { struct nhlt_dmic_array_config dmic_config; u8 nb_mics; /* TODO add vendor mic config */ } __packed; enum { NHLT_MIC_ARRAY_2CH_SMALL = 0xa, NHLT_MIC_ARRAY_2CH_BIG = 0xb, Loading @@ -116,4 +121,30 @@ enum { NHLT_MIC_ARRAY_VENDOR_DEFINED = 0xf, }; struct nhlt_acpi_table *intel_nhlt_init(struct device *dev); void intel_nhlt_free(struct nhlt_acpi_table *addr); int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt); #else struct nhlt_acpi_table; static inline struct nhlt_acpi_table *intel_nhlt_init(struct device *dev) { return NULL; } static inline void intel_nhlt_free(struct nhlt_acpi_table *addr) { } static inline int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt) { return 0; } #endif #endif sound/hda/Kconfig +5 −0 Original line number Diff line number Diff line Loading @@ -29,3 +29,8 @@ config SND_HDA_PREALLOC_SIZE Note that the pre-allocation size can be changed dynamically via a proc file (/proc/asound/card*/pcm*/sub*/prealloc), too. config SND_INTEL_NHLT tristate # this config should be selected only for Intel ACPI platforms. # A fallback is provided so that the code compiles in all cases. No newline at end of file sound/hda/Makefile +3 −0 Original line number Diff line number Diff line Loading @@ -13,3 +13,6 @@ obj-$(CONFIG_SND_HDA_CORE) += snd-hda-core.o #extended hda obj-$(CONFIG_SND_HDA_EXT_CORE) += ext/ snd-intel-nhlt-objs := intel-nhlt.o obj-$(CONFIG_SND_INTEL_NHLT) += snd-intel-nhlt.o sound/hda/intel-nhlt.c 0 → 100644 +107 −0 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2015-2019 Intel Corporation #include <linux/acpi.h> #include <sound/intel-nhlt.h> #define NHLT_ACPI_HEADER_SIG "NHLT" /* Unique identification for getting NHLT blobs */ static guid_t osc_guid = GUID_INIT(0xA69F886E, 0x6CEB, 0x4594, 0xA4, 0x1F, 0x7B, 0x5D, 0xCE, 0x24, 0xC5, 0x53); struct nhlt_acpi_table *intel_nhlt_init(struct device *dev) { acpi_handle handle; union acpi_object *obj; struct nhlt_resource_desc *nhlt_ptr; struct nhlt_acpi_table *nhlt_table = NULL; handle = ACPI_HANDLE(dev); if (!handle) { dev_err(dev, "Didn't find ACPI_HANDLE\n"); return NULL; } obj = acpi_evaluate_dsm(handle, &osc_guid, 1, 1, NULL); if (!obj) return NULL; if (obj->type != ACPI_TYPE_BUFFER) { dev_dbg(dev, "No NHLT table found\n"); ACPI_FREE(obj); return NULL; } nhlt_ptr = (struct nhlt_resource_desc *)obj->buffer.pointer; if (nhlt_ptr->length) nhlt_table = (struct nhlt_acpi_table *) memremap(nhlt_ptr->min_addr, nhlt_ptr->length, MEMREMAP_WB); ACPI_FREE(obj); if (nhlt_table && (strncmp(nhlt_table->header.signature, NHLT_ACPI_HEADER_SIG, strlen(NHLT_ACPI_HEADER_SIG)) != 0)) { memunmap(nhlt_table); dev_err(dev, "NHLT ACPI header signature incorrect\n"); return NULL; } return nhlt_table; } EXPORT_SYMBOL_GPL(intel_nhlt_init); void intel_nhlt_free(struct nhlt_acpi_table *nhlt) { memunmap((void *)nhlt); } EXPORT_SYMBOL_GPL(intel_nhlt_free); int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt) { struct nhlt_endpoint *epnt; struct nhlt_dmic_array_config *cfg; struct nhlt_vendor_dmic_array_config *cfg_vendor; unsigned int dmic_geo = 0; u8 j; if (!nhlt) return 0; epnt = (struct nhlt_endpoint *)nhlt->desc; for (j = 0; j < nhlt->endpoint_count; j++) { if (epnt->linktype == NHLT_LINK_DMIC) { cfg = (struct nhlt_dmic_array_config *) (epnt->config.caps); switch (cfg->array_type) { case NHLT_MIC_ARRAY_2CH_SMALL: case NHLT_MIC_ARRAY_2CH_BIG: dmic_geo = MIC_ARRAY_2CH; break; case NHLT_MIC_ARRAY_4CH_1ST_GEOM: case NHLT_MIC_ARRAY_4CH_L_SHAPED: case NHLT_MIC_ARRAY_4CH_2ND_GEOM: dmic_geo = MIC_ARRAY_4CH; break; case NHLT_MIC_ARRAY_VENDOR_DEFINED: cfg_vendor = (struct nhlt_vendor_dmic_array_config *)cfg; dmic_geo = cfg_vendor->nb_mics; break; default: dev_warn(dev, "undefined DMIC array_type 0x%0x\n", cfg->array_type); } } epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length); } return dmic_geo; } EXPORT_SYMBOL_GPL(intel_nhlt_get_dmic_geo); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("Intel NHLT driver"); sound/pci/hda/Kconfig +10 −0 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ config SND_HDA_INTEL tristate "HD Audio PCI" depends on SND_PCI select SND_HDA select SND_INTEL_NHLT if ACPI help Say Y here to include support for Intel "High Definition Audio" (Azalia) and its compatible devices. Loading @@ -22,6 +23,15 @@ config SND_HDA_INTEL To compile this driver as a module, choose M here: the module will be called snd-hda-intel. config SND_HDA_INTEL_DETECT_DMIC bool "DMIC detection and probe abort" depends on SND_HDA_INTEL help Say Y to detect digital microphones on SKL+ devices. DMICs cannot be handled by the HDaudio legacy driver and are currently only supported by the SOF driver. If unsure say N. config SND_HDA_TEGRA tristate "NVIDIA Tegra HD Audio" depends on ARCH_TEGRA Loading Loading
sound/soc/intel/skylake/skl-nhlt.h→include/sound/intel-nhlt.h +41 −10 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * skl-nhlt.h - Intel HDA Platform NHLT header * intel-nhlt.h - Intel HDA Platform NHLT header * * Copyright (C) 2015 Intel Corp * Author: Sanjiv Kumar <sanjiv.kumar@intel.com> * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Copyright (c) 2015-2019 Intel Corporation */ #ifndef __SKL_NHLT_H__ #define __SKL_NHLT_H__ #ifndef __INTEL_NHLT_H__ #define __INTEL_NHLT_H__ #include <linux/acpi.h> #if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_INTEL_NHLT) struct wav_fmt { u16 fmt_tag; u16 channels; Loading Loading @@ -97,16 +96,22 @@ struct nhlt_resource_desc { #define MIC_ARRAY_2CH 2 #define MIC_ARRAY_4CH 4 struct nhlt_tdm_config { struct nhlt_device_specific_config { u8 virtual_slot; u8 config_type; } __packed; struct nhlt_dmic_array_config { struct nhlt_tdm_config tdm_config; struct nhlt_device_specific_config device_config; u8 array_type; } __packed; struct nhlt_vendor_dmic_array_config { struct nhlt_dmic_array_config dmic_config; u8 nb_mics; /* TODO add vendor mic config */ } __packed; enum { NHLT_MIC_ARRAY_2CH_SMALL = 0xa, NHLT_MIC_ARRAY_2CH_BIG = 0xb, Loading @@ -116,4 +121,30 @@ enum { NHLT_MIC_ARRAY_VENDOR_DEFINED = 0xf, }; struct nhlt_acpi_table *intel_nhlt_init(struct device *dev); void intel_nhlt_free(struct nhlt_acpi_table *addr); int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt); #else struct nhlt_acpi_table; static inline struct nhlt_acpi_table *intel_nhlt_init(struct device *dev) { return NULL; } static inline void intel_nhlt_free(struct nhlt_acpi_table *addr) { } static inline int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt) { return 0; } #endif #endif
sound/hda/Kconfig +5 −0 Original line number Diff line number Diff line Loading @@ -29,3 +29,8 @@ config SND_HDA_PREALLOC_SIZE Note that the pre-allocation size can be changed dynamically via a proc file (/proc/asound/card*/pcm*/sub*/prealloc), too. config SND_INTEL_NHLT tristate # this config should be selected only for Intel ACPI platforms. # A fallback is provided so that the code compiles in all cases. No newline at end of file
sound/hda/Makefile +3 −0 Original line number Diff line number Diff line Loading @@ -13,3 +13,6 @@ obj-$(CONFIG_SND_HDA_CORE) += snd-hda-core.o #extended hda obj-$(CONFIG_SND_HDA_EXT_CORE) += ext/ snd-intel-nhlt-objs := intel-nhlt.o obj-$(CONFIG_SND_INTEL_NHLT) += snd-intel-nhlt.o
sound/hda/intel-nhlt.c 0 → 100644 +107 −0 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2015-2019 Intel Corporation #include <linux/acpi.h> #include <sound/intel-nhlt.h> #define NHLT_ACPI_HEADER_SIG "NHLT" /* Unique identification for getting NHLT blobs */ static guid_t osc_guid = GUID_INIT(0xA69F886E, 0x6CEB, 0x4594, 0xA4, 0x1F, 0x7B, 0x5D, 0xCE, 0x24, 0xC5, 0x53); struct nhlt_acpi_table *intel_nhlt_init(struct device *dev) { acpi_handle handle; union acpi_object *obj; struct nhlt_resource_desc *nhlt_ptr; struct nhlt_acpi_table *nhlt_table = NULL; handle = ACPI_HANDLE(dev); if (!handle) { dev_err(dev, "Didn't find ACPI_HANDLE\n"); return NULL; } obj = acpi_evaluate_dsm(handle, &osc_guid, 1, 1, NULL); if (!obj) return NULL; if (obj->type != ACPI_TYPE_BUFFER) { dev_dbg(dev, "No NHLT table found\n"); ACPI_FREE(obj); return NULL; } nhlt_ptr = (struct nhlt_resource_desc *)obj->buffer.pointer; if (nhlt_ptr->length) nhlt_table = (struct nhlt_acpi_table *) memremap(nhlt_ptr->min_addr, nhlt_ptr->length, MEMREMAP_WB); ACPI_FREE(obj); if (nhlt_table && (strncmp(nhlt_table->header.signature, NHLT_ACPI_HEADER_SIG, strlen(NHLT_ACPI_HEADER_SIG)) != 0)) { memunmap(nhlt_table); dev_err(dev, "NHLT ACPI header signature incorrect\n"); return NULL; } return nhlt_table; } EXPORT_SYMBOL_GPL(intel_nhlt_init); void intel_nhlt_free(struct nhlt_acpi_table *nhlt) { memunmap((void *)nhlt); } EXPORT_SYMBOL_GPL(intel_nhlt_free); int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt) { struct nhlt_endpoint *epnt; struct nhlt_dmic_array_config *cfg; struct nhlt_vendor_dmic_array_config *cfg_vendor; unsigned int dmic_geo = 0; u8 j; if (!nhlt) return 0; epnt = (struct nhlt_endpoint *)nhlt->desc; for (j = 0; j < nhlt->endpoint_count; j++) { if (epnt->linktype == NHLT_LINK_DMIC) { cfg = (struct nhlt_dmic_array_config *) (epnt->config.caps); switch (cfg->array_type) { case NHLT_MIC_ARRAY_2CH_SMALL: case NHLT_MIC_ARRAY_2CH_BIG: dmic_geo = MIC_ARRAY_2CH; break; case NHLT_MIC_ARRAY_4CH_1ST_GEOM: case NHLT_MIC_ARRAY_4CH_L_SHAPED: case NHLT_MIC_ARRAY_4CH_2ND_GEOM: dmic_geo = MIC_ARRAY_4CH; break; case NHLT_MIC_ARRAY_VENDOR_DEFINED: cfg_vendor = (struct nhlt_vendor_dmic_array_config *)cfg; dmic_geo = cfg_vendor->nb_mics; break; default: dev_warn(dev, "undefined DMIC array_type 0x%0x\n", cfg->array_type); } } epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length); } return dmic_geo; } EXPORT_SYMBOL_GPL(intel_nhlt_get_dmic_geo); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("Intel NHLT driver");
sound/pci/hda/Kconfig +10 −0 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ config SND_HDA_INTEL tristate "HD Audio PCI" depends on SND_PCI select SND_HDA select SND_INTEL_NHLT if ACPI help Say Y here to include support for Intel "High Definition Audio" (Azalia) and its compatible devices. Loading @@ -22,6 +23,15 @@ config SND_HDA_INTEL To compile this driver as a module, choose M here: the module will be called snd-hda-intel. config SND_HDA_INTEL_DETECT_DMIC bool "DMIC detection and probe abort" depends on SND_HDA_INTEL help Say Y to detect digital microphones on SKL+ devices. DMICs cannot be handled by the HDaudio legacy driver and are currently only supported by the SOF driver. If unsure say N. config SND_HDA_TEGRA tristate "NVIDIA Tegra HD Audio" depends on ARCH_TEGRA Loading