diff options
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/hda/Kconfig | 11 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.c | 8 | ||||
-rw-r--r-- | sound/pci/hda/hda_controller.c | 6 | ||||
-rw-r--r-- | sound/pci/hda/hda_controller.h | 3 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 105 | ||||
-rw-r--r-- | sound/pci/hda/hda_tegra.c | 84 |
6 files changed, 61 insertions, 156 deletions
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index 35d934309cb2..dae47a45b2b8 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig @@ -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. @@ -22,10 +23,20 @@ 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 select SND_HDA + select SND_HDA_ALIGNED_MMIO help Say Y here to support the HDA controller present in NVIDIA Tegra SoCs diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 51f10ed9bc43..a2fb19129219 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -846,7 +846,13 @@ static void snd_hda_codec_dev_release(struct device *dev) snd_hda_sysfs_clear(codec); kfree(codec->modelname); kfree(codec->wcaps); - kfree(codec); + + /* + * In the case of ASoC HD-audio, hda_codec is device managed. + * It will be freed when the ASoC device is removed. + */ + if (codec->core.type == HDA_DEV_LEGACY) + kfree(codec); } #define DEV_NAME_LEN 31 diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 48d863736b3c..97a43a28b9e4 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -1207,14 +1207,12 @@ void snd_hda_bus_reset(struct hda_bus *bus) } /* HD-audio bus initialization */ -int azx_bus_init(struct azx *chip, const char *model, - const struct hdac_io_ops *io_ops) +int azx_bus_init(struct azx *chip, const char *model) { struct hda_bus *bus = &chip->bus; int err; - err = snd_hdac_bus_init(&bus->core, chip->card->dev, &bus_core_ops, - io_ops); + err = snd_hdac_bus_init(&bus->core, chip->card->dev, &bus_core_ops); if (err < 0) return err; diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h index f2a6df5e6bcb..82e26442724b 100644 --- a/sound/pci/hda/hda_controller.h +++ b/sound/pci/hda/hda_controller.h @@ -206,8 +206,7 @@ void azx_stop_chip(struct azx *chip); irqreturn_t azx_interrupt(int irq, void *dev_id); /* Codec interface */ -int azx_bus_init(struct azx *chip, const char *model, - const struct hdac_io_ops *io_ops); +int azx_bus_init(struct azx *chip, const char *model); int azx_probe_codecs(struct azx *chip, unsigned int max_slots); int azx_codec_configure(struct azx *chip); int azx_init_streams(struct azx *chip); diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 99fc0917339b..2d0db3c9f335 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -46,6 +46,7 @@ #include <sound/initval.h> #include <sound/hdaudio.h> #include <sound/hda_i915.h> +#include <sound/intel-nhlt.h> #include <linux/vgaarb.h> #include <linux/vga_switcheroo.h> #include <linux/firmware.h> @@ -125,6 +126,7 @@ static char *patch[SNDRV_CARDS]; static bool beep_mode[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = CONFIG_SND_HDA_INPUT_BEEP_MODE}; #endif +static bool dmic_detect = IS_ENABLED(CONFIG_SND_HDA_INTEL_DETECT_DMIC); module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for Intel HD audio interface."); @@ -159,6 +161,8 @@ module_param_array(beep_mode, bool, NULL, 0444); MODULE_PARM_DESC(beep_mode, "Select HDA Beep registration mode " "(0=off, 1=on) (default=1)."); #endif +module_param(dmic_detect, bool, 0444); +MODULE_PARM_DESC(dmic_detect, "DMIC detect on SKL+ platforms"); #ifdef CONFIG_PM static int param_set_xint(const char *val, const struct kernel_param *kp); @@ -1684,7 +1688,6 @@ static int default_bdl_pos_adj(struct azx *chip) /* * constructor */ -static const struct hdac_io_ops pci_hda_io_ops; static const struct hda_controller_ops pci_hda_ops; static int azx_create(struct snd_card *card, struct pci_dev *pci, @@ -1744,13 +1747,17 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, else chip->bdl_pos_adj = bdl_pos_adj[dev]; - err = azx_bus_init(chip, model[dev], &pci_hda_io_ops); + err = azx_bus_init(chip, model[dev]); if (err < 0) { kfree(hda); pci_disable_device(pci); return err; } + /* use the non-cached pages in non-snoop mode */ + if (!azx_snoop(chip)) + azx_bus(chip)->dma_type = SNDRV_DMA_TYPE_DEV_UC; + /* Workaround for a communication error on CFL (bko#199007) and CNL */ if (IS_CFL(pci) || IS_CNL(pci)) azx_bus(chip)->polling_mode = 1; @@ -1985,41 +1992,6 @@ static void azx_firmware_cb(const struct firmware *fw, void *context) } #endif -/* - * HDA controller ops. - */ - -/* PCI register access. */ -static void pci_azx_writel(u32 value, u32 __iomem *addr) -{ - writel(value, addr); -} - -static u32 pci_azx_readl(u32 __iomem *addr) -{ - return readl(addr); -} - -static void pci_azx_writew(u16 value, u16 __iomem *addr) -{ - writew(value, addr); -} - -static u16 pci_azx_readw(u16 __iomem *addr) -{ - return readw(addr); -} - -static void pci_azx_writeb(u8 value, u8 __iomem *addr) -{ - writeb(value, addr); -} - -static u8 pci_azx_readb(u8 __iomem *addr) -{ - return readb(addr); -} - static int disable_msi_reset_irq(struct azx *chip) { struct hdac_bus *bus = azx_bus(chip); @@ -2036,24 +2008,6 @@ static int disable_msi_reset_irq(struct azx *chip) return 0; } -/* DMA page allocation helpers. */ -static int dma_alloc_pages(struct hdac_bus *bus, - int type, - size_t size, - struct snd_dma_buffer *buf) -{ - struct azx *chip = bus_to_azx(bus); - - if (!azx_snoop(chip) && type == SNDRV_DMA_TYPE_DEV) - type = SNDRV_DMA_TYPE_DEV_UC; - return snd_dma_alloc_pages(type, bus->dev, size, buf); -} - -static void dma_free_pages(struct hdac_bus *bus, struct snd_dma_buffer *buf) -{ - snd_dma_free_pages(buf); -} - static void pcm_mmap_prepare(struct snd_pcm_substream *substream, struct vm_area_struct *area) { @@ -2065,23 +2019,31 @@ static void pcm_mmap_prepare(struct snd_pcm_substream *substream, #endif } -static const struct hdac_io_ops pci_hda_io_ops = { - .reg_writel = pci_azx_writel, - .reg_readl = pci_azx_readl, - .reg_writew = pci_azx_writew, - .reg_readw = pci_azx_readw, - .reg_writeb = pci_azx_writeb, - .reg_readb = pci_azx_readb, - .dma_alloc_pages = dma_alloc_pages, - .dma_free_pages = dma_free_pages, -}; - static const struct hda_controller_ops pci_hda_ops = { .disable_msi_reset_irq = disable_msi_reset_irq, .pcm_mmap_prepare = pcm_mmap_prepare, .position_check = azx_position_check, }; +static int azx_check_dmic(struct pci_dev *pci, struct azx *chip) +{ + struct nhlt_acpi_table *nhlt; + int ret = 0; + + if (chip->driver_type == AZX_DRIVER_SKL && + pci->class != 0x040300) { + nhlt = intel_nhlt_init(&pci->dev); + if (nhlt) { + if (intel_nhlt_get_dmic_geo(&pci->dev, nhlt)) { + ret = -ENODEV; + dev_info(&pci->dev, "Digital mics found on Skylake+ platform, aborting probe\n"); + } + intel_nhlt_free(nhlt); + } + } + return ret; +} + static int azx_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { @@ -2112,6 +2074,17 @@ static int azx_probe(struct pci_dev *pci, card->private_data = chip; hda = container_of(chip, struct hda_intel, chip); + /* + * stop probe if digital microphones detected on Skylake+ platform + * with the DSP enabled. This is an opt-in behavior defined at build + * time or at run-time with a module parameter + */ + if (dmic_detect) { + err = azx_check_dmic(pci, chip); + if (err < 0) + goto out_free; + } + pci_set_drvdata(pci, card); err = register_vga_switcheroo(chip); diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c index 7dbe9f39fc79..8350954b7986 100644 --- a/sound/pci/hda/hda_tegra.c +++ b/sound/pci/hda/hda_tegra.c @@ -75,88 +75,6 @@ MODULE_PARM_DESC(power_save, #define power_save 0 #endif -/* - * DMA page allocation ops. - */ -static int dma_alloc_pages(struct hdac_bus *bus, int type, size_t size, - struct snd_dma_buffer *buf) -{ - return snd_dma_alloc_pages(type, bus->dev, size, buf); -} - -static void dma_free_pages(struct hdac_bus *bus, struct snd_dma_buffer *buf) -{ - snd_dma_free_pages(buf); -} - -/* - * Register access ops. Tegra HDA register access is DWORD only. - */ -static void hda_tegra_writel(u32 value, u32 __iomem *addr) -{ - writel(value, addr); -} - -static u32 hda_tegra_readl(u32 __iomem *addr) -{ - return readl(addr); -} - -static void hda_tegra_writew(u16 value, u16 __iomem *addr) -{ - unsigned int shift = ((unsigned long)(addr) & 0x3) << 3; - void __iomem *dword_addr = (void __iomem *)((unsigned long)(addr) & ~0x3); - u32 v; - - v = readl(dword_addr); - v &= ~(0xffff << shift); - v |= value << shift; - writel(v, dword_addr); -} - -static u16 hda_tegra_readw(u16 __iomem *addr) -{ - unsigned int shift = ((unsigned long)(addr) & 0x3) << 3; - void __iomem *dword_addr = (void __iomem *)((unsigned long)(addr) & ~0x3); - u32 v; - - v = readl(dword_addr); - return (v >> shift) & 0xffff; -} - -static void hda_tegra_writeb(u8 value, u8 __iomem *addr) -{ - unsigned int shift = ((unsigned long)(addr) & 0x3) << 3; - void __iomem *dword_addr = (void __iomem *)((unsigned long)(addr) & ~0x3); - u32 v; - - v = readl(dword_addr); - v &= ~(0xff << shift); - v |= value << shift; - writel(v, dword_addr); -} - -static u8 hda_tegra_readb(u8 __iomem *addr) -{ - unsigned int shift = ((unsigned long)(addr) & 0x3) << 3; - void __iomem *dword_addr = (void __iomem *)((unsigned long)(addr) & ~0x3); - u32 v; - - v = readl(dword_addr); - return (v >> shift) & 0xff; -} - -static const struct hdac_io_ops hda_tegra_io_ops = { - .reg_writel = hda_tegra_writel, - .reg_readl = hda_tegra_readl, - .reg_writew = hda_tegra_writew, - .reg_readw = hda_tegra_readw, - .reg_writeb = hda_tegra_writeb, - .reg_readb = hda_tegra_readb, - .dma_alloc_pages = dma_alloc_pages, - .dma_free_pages = dma_free_pages, -}; - static const struct hda_controller_ops hda_tegra_ops; /* nothing special */ static void hda_tegra_init(struct hda_tegra *hda) @@ -475,7 +393,7 @@ static int hda_tegra_create(struct snd_card *card, INIT_WORK(&hda->probe_work, hda_tegra_probe_work); - err = azx_bus_init(chip, NULL, &hda_tegra_io_ops); + err = azx_bus_init(chip, NULL); if (err < 0) return err; |