diff options
Diffstat (limited to 'sound/hda')
-rw-r--r-- | sound/hda/Kconfig | 1 | ||||
-rw-r--r-- | sound/hda/Makefile | 8 | ||||
-rw-r--r-- | sound/hda/ext/Makefile | 2 | ||||
-rw-r--r-- | sound/hda/hdac_controller.c | 127 | ||||
-rw-r--r-- | sound/hda/intel-dsp-config.c | 24 | ||||
-rw-r--r-- | sound/hda/trace.h | 6 |
6 files changed, 142 insertions, 26 deletions
diff --git a/sound/hda/Kconfig b/sound/hda/Kconfig index 741179ccbd..e2ac247fc1 100644 --- a/sound/hda/Kconfig +++ b/sound/hda/Kconfig @@ -42,6 +42,7 @@ config SND_INTEL_NHLT config SND_INTEL_DSP_CONFIG tristate + select ACPI_NHLT if ACPI select SND_INTEL_NHLT if ACPI select SND_INTEL_SOUNDWIRE_ACPI if ACPI # this config should be selected only for Intel DSP platforms. diff --git a/sound/hda/Makefile b/sound/hda/Makefile index 78f487a635..83cceafe0d 100644 --- a/sound/hda/Makefile +++ b/sound/hda/Makefile @@ -1,8 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 -snd-hda-core-objs := hda_bus_type.o hdac_bus.o hdac_device.o hdac_sysfs.o \ +snd-hda-core-y := hda_bus_type.o hdac_bus.o hdac_device.o hdac_sysfs.o \ hdac_regmap.o hdac_controller.o hdac_stream.o array.o hdmi_chmap.o -snd-hda-core-objs += trace.o +snd-hda-core-y += trace.o CFLAGS_trace.o := -I$(src) # for sync with i915 gfx driver @@ -14,9 +14,9 @@ obj-$(CONFIG_SND_HDA_CORE) += snd-hda-core.o #extended hda obj-$(CONFIG_SND_HDA_EXT_CORE) += ext/ -snd-intel-dspcfg-objs := intel-dsp-config.o +snd-intel-dspcfg-y := intel-dsp-config.o snd-intel-dspcfg-$(CONFIG_SND_INTEL_NHLT) += intel-nhlt.o obj-$(CONFIG_SND_INTEL_DSP_CONFIG) += snd-intel-dspcfg.o -snd-intel-sdw-acpi-objs := intel-sdw-acpi.o +snd-intel-sdw-acpi-y := intel-sdw-acpi.o obj-$(CONFIG_SND_INTEL_SOUNDWIRE_ACPI) += snd-intel-sdw-acpi.o diff --git a/sound/hda/ext/Makefile b/sound/hda/ext/Makefile index 154779bdc0..05883fb28d 100644 --- a/sound/hda/ext/Makefile +++ b/sound/hda/ext/Makefile @@ -1,4 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only -snd-hda-ext-core-objs := hdac_ext_bus.o hdac_ext_controller.o hdac_ext_stream.o +snd-hda-ext-core-y := hdac_ext_bus.o hdac_ext_controller.o hdac_ext_stream.o obj-$(CONFIG_SND_HDA_EXT_CORE) += snd-hda-ext-core.o diff --git a/sound/hda/hdac_controller.c b/sound/hda/hdac_controller.c index 7f3a000fab..b5c833b9f8 100644 --- a/sound/hda/hdac_controller.c +++ b/sound/hda/hdac_controller.c @@ -62,7 +62,8 @@ void snd_hdac_bus_init_cmd_io(struct hdac_bus *bus) azx_clear_corbrp(bus); /* enable corb dma */ - snd_hdac_chip_writeb(bus, CORBCTL, AZX_CORBCTL_RUN); + if (!bus->use_pio_for_commands) + snd_hdac_chip_writeb(bus, CORBCTL, AZX_CORBCTL_RUN); /* RIRB set up */ bus->rirb.addr = bus->rb.addr + 2048; @@ -135,14 +136,94 @@ static unsigned int azx_command_addr(u32 cmd) return addr; } +/* receive an Immediate Response with PIO */ +static int snd_hdac_bus_wait_for_pio_response(struct hdac_bus *bus, + unsigned int addr) +{ + int timeout = 50; + + while (timeout--) { + /* check IRV bit */ + if (snd_hdac_chip_readw(bus, IRS) & AZX_IRS_VALID) { + /* reuse rirb.res as the response return value */ + bus->rirb.res[addr] = snd_hdac_chip_readl(bus, IR); + return 0; + } + udelay(1); + } + + dev_dbg_ratelimited(bus->dev, "get_response_pio timeout: IRS=%#x\n", + snd_hdac_chip_readw(bus, IRS)); + + bus->rirb.res[addr] = -1; + + return -EIO; +} + /** - * snd_hdac_bus_send_cmd - send a command verb via CORB + * snd_hdac_bus_send_cmd_pio - send a command verb via Immediate Command * @bus: HD-audio core bus * @val: encoded verb value to send * * Returns zero for success or a negative error code. */ -int snd_hdac_bus_send_cmd(struct hdac_bus *bus, unsigned int val) +static int snd_hdac_bus_send_cmd_pio(struct hdac_bus *bus, unsigned int val) +{ + unsigned int addr = azx_command_addr(val); + int timeout = 50; + int ret = -EIO; + + spin_lock_irq(&bus->reg_lock); + + while (timeout--) { + /* check ICB bit */ + if (!((snd_hdac_chip_readw(bus, IRS) & AZX_IRS_BUSY))) { + /* Clear IRV bit */ + snd_hdac_chip_updatew(bus, IRS, AZX_IRS_VALID, AZX_IRS_VALID); + snd_hdac_chip_writel(bus, IC, val); + /* Set ICB bit */ + snd_hdac_chip_updatew(bus, IRS, AZX_IRS_BUSY, AZX_IRS_BUSY); + + ret = snd_hdac_bus_wait_for_pio_response(bus, addr); + goto out; + } + udelay(1); + } + + dev_dbg_ratelimited(bus->dev, "send_cmd_pio timeout: IRS=%#x, val=%#x\n", + snd_hdac_chip_readw(bus, IRS), val); + +out: + spin_unlock_irq(&bus->reg_lock); + + return ret; +} + +/** + * snd_hdac_bus_get_response_pio - receive a response via Immediate Response + * @bus: HD-audio core bus + * @addr: codec address + * @res: pointer to store the value, NULL when not needed + * + * Returns zero if a value is read, or a negative error code. + */ +static int snd_hdac_bus_get_response_pio(struct hdac_bus *bus, + unsigned int addr, unsigned int *res) +{ + if (res) + *res = bus->rirb.res[addr]; + + return 0; +} + +/** + * snd_hdac_bus_send_cmd_corb - send a command verb via CORB + * @bus: HD-audio core bus + * @val: encoded verb value to send + * + * Returns zero for success or a negative error code. + */ +static int snd_hdac_bus_send_cmd_corb(struct hdac_bus *bus, unsigned int val) { unsigned int addr = azx_command_addr(val); unsigned int wp, rp; @@ -176,7 +257,6 @@ int snd_hdac_bus_send_cmd(struct hdac_bus *bus, unsigned int val) return 0; } -EXPORT_SYMBOL_GPL(snd_hdac_bus_send_cmd); #define AZX_RIRB_EX_UNSOL_EV (1<<4) @@ -234,15 +314,15 @@ void snd_hdac_bus_update_rirb(struct hdac_bus *bus) EXPORT_SYMBOL_GPL(snd_hdac_bus_update_rirb); /** - * snd_hdac_bus_get_response - receive a response via RIRB + * snd_hdac_bus_get_response_rirb - receive a response via RIRB * @bus: HD-audio core bus * @addr: codec address * @res: pointer to store the value, NULL when not needed * * Returns zero if a value is read, or a negative error code. */ -int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr, - unsigned int *res) +static int snd_hdac_bus_get_response_rirb(struct hdac_bus *bus, + unsigned int addr, unsigned int *res) { unsigned long timeout; unsigned long loopcounter; @@ -293,6 +373,39 @@ int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr, return -EIO; } + +/** + * snd_hdac_bus_send_cmd - send a command verb via CORB or PIO + * @bus: HD-audio core bus + * @val: encoded verb value to send + * + * Returns zero for success or a negative error code. + */ +int snd_hdac_bus_send_cmd(struct hdac_bus *bus, unsigned int val) +{ + if (bus->use_pio_for_commands) + return snd_hdac_bus_send_cmd_pio(bus, val); + + return snd_hdac_bus_send_cmd_corb(bus, val); +} +EXPORT_SYMBOL_GPL(snd_hdac_bus_send_cmd); + +/** + * snd_hdac_bus_get_response - receive a response via RIRB or PIO + * @bus: HD-audio core bus + * @addr: codec address + * @res: pointer to store the value, NULL when not needed + * + * Returns zero if a value is read, or a negative error code. + */ +int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr, + unsigned int *res) +{ + if (bus->use_pio_for_commands) + return snd_hdac_bus_get_response_pio(bus, addr, res); + + return snd_hdac_bus_get_response_rirb(bus, addr, res); +} EXPORT_SYMBOL_GPL(snd_hdac_bus_get_response); #define HDAC_MAX_CAPS 10 diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c index e7c2ef6c6b..478d2b50c5 100644 --- a/sound/hda/intel-dsp-config.c +++ b/sound/hda/intel-dsp-config.c @@ -13,6 +13,8 @@ #include <sound/intel-nhlt.h> #include <sound/soc-acpi.h> +#include <acpi/nhlt.h> + static int dsp_driver; module_param(dsp_driver, int, 0444); @@ -593,15 +595,15 @@ static const struct config_entry *snd_intel_dsp_find_config static int snd_intel_dsp_check_dmic(struct pci_dev *pci) { - struct nhlt_acpi_table *nhlt; int ret = 0; - nhlt = intel_nhlt_init(&pci->dev); - if (nhlt) { - if (intel_nhlt_has_endpoint_type(nhlt, NHLT_LINK_DMIC)) - ret = 1; - intel_nhlt_free(nhlt); - } + acpi_nhlt_get_gbl_table(); + + if (acpi_nhlt_find_endpoint(ACPI_NHLT_LINKTYPE_PDM, -1, -1, -1)) + ret = 1; + + acpi_nhlt_put_gbl_table(); + return ret; } @@ -666,7 +668,7 @@ int snd_intel_dsp_driver_probe(struct pci_dev *pci) return SND_INTEL_DSP_DRIVER_LEGACY; } - dev_info(&pci->dev, "DSP detected with PCI class/subclass/prog-if info 0x%06x\n", pci->class); + dev_dbg(&pci->dev, "DSP detected with PCI class/subclass/prog-if info 0x%06x\n", pci->class); /* find the configuration for the specific device */ cfg = snd_intel_dsp_find_config(pci, config_table, ARRAY_SIZE(config_table)); @@ -676,12 +678,12 @@ int snd_intel_dsp_driver_probe(struct pci_dev *pci) if (cfg->flags & FLAG_SOF) { if (cfg->flags & FLAG_SOF_ONLY_IF_SOUNDWIRE && snd_intel_dsp_check_soundwire(pci) > 0) { - dev_info(&pci->dev, "SoundWire enabled on CannonLake+ platform, using SOF driver\n"); + dev_info_once(&pci->dev, "SoundWire enabled on CannonLake+ platform, using SOF driver\n"); return SND_INTEL_DSP_DRIVER_SOF; } if (cfg->flags & FLAG_SOF_ONLY_IF_DMIC && snd_intel_dsp_check_dmic(pci)) { - dev_info(&pci->dev, "Digital mics found on Skylake+ platform, using SOF driver\n"); + dev_info_once(&pci->dev, "Digital mics found on Skylake+ platform, using SOF driver\n"); return SND_INTEL_DSP_DRIVER_SOF; } if (!(cfg->flags & FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE)) @@ -692,7 +694,7 @@ int snd_intel_dsp_driver_probe(struct pci_dev *pci) if (cfg->flags & FLAG_SST) { if (cfg->flags & FLAG_SST_ONLY_IF_DMIC) { if (snd_intel_dsp_check_dmic(pci)) { - dev_info(&pci->dev, "Digital mics found on Skylake+ platform, using SST driver\n"); + dev_info_once(&pci->dev, "Digital mics found on Skylake+ platform, using SST driver\n"); return SND_INTEL_DSP_DRIVER_SST; } } else { diff --git a/sound/hda/trace.h b/sound/hda/trace.h index 2cc493434a..280c42f3eb 100644 --- a/sound/hda/trace.h +++ b/sound/hda/trace.h @@ -24,7 +24,7 @@ TRACE_EVENT(hda_send_cmd, __field(u32, cmd) ), TP_fast_assign( - __assign_str(name, dev_name((bus)->dev)); + __assign_str(name); __entry->cmd = cmd; ), TP_printk("[%s:%d] val=0x%08x", __get_str(name), __entry->cmd >> 28, __entry->cmd) @@ -39,7 +39,7 @@ TRACE_EVENT(hda_get_response, __field(u32, res) ), TP_fast_assign( - __assign_str(name, dev_name((bus)->dev)); + __assign_str(name); __entry->addr = addr; __entry->res = res; ), @@ -55,7 +55,7 @@ TRACE_EVENT(hda_unsol_event, __field(u32, res_ex) ), TP_fast_assign( - __assign_str(name, dev_name((bus)->dev)); + __assign_str(name); __entry->res = res; __entry->res_ex = res_ex; ), |