diff options
Diffstat (limited to 'sound/hda')
-rw-r--r-- | sound/hda/ext/hdac_ext_stream.c | 43 | ||||
-rw-r--r-- | sound/hda/hdac_i915.c | 24 | ||||
-rw-r--r-- | sound/hda/hdac_stream.c | 26 | ||||
-rw-r--r-- | sound/hda/intel-dsp-config.c | 10 |
4 files changed, 83 insertions, 20 deletions
diff --git a/sound/hda/ext/hdac_ext_stream.c b/sound/hda/ext/hdac_ext_stream.c index 11b7119cc4..a3ac738f11 100644 --- a/sound/hda/ext/hdac_ext_stream.c +++ b/sound/hda/ext/hdac_ext_stream.c @@ -10,6 +10,8 @@ */ #include <linux/delay.h> +#include <linux/pci.h> +#include <linux/pci_ids.h> #include <linux/slab.h> #include <sound/pcm.h> #include <sound/hda_register.h> @@ -17,6 +19,39 @@ #include <sound/compress_driver.h> /** + * snd_hdac_ext_host_stream_setup - Setup a HOST stream. + * @hext_stream: HDAudio stream to set up. + * @code_loading: Whether the stream is for PCM or code-loading. + * + * Return: Zero on success or negative error code. + */ +int snd_hdac_ext_host_stream_setup(struct hdac_ext_stream *hext_stream, bool code_loading) +{ + return hext_stream->host_setup(hdac_stream(hext_stream), code_loading); +} +EXPORT_SYMBOL_GPL(snd_hdac_ext_host_stream_setup); + +/** + * snd_hdac_apl_host_stream_setup - Setup a HOST stream following procedure + * recommended for ApolloLake devices. + * @hstream: HDAudio stream to set up. + * @code_loading: Whether the stream is for PCM or code-loading. + * + * Return: Zero on success or negative error code. + */ +static int snd_hdac_apl_host_stream_setup(struct hdac_stream *hstream, bool code_loading) +{ + struct hdac_ext_stream *hext_stream = stream_to_hdac_ext_stream(hstream); + int ret; + + snd_hdac_ext_stream_decouple(hstream->bus, hext_stream, false); + ret = snd_hdac_stream_setup(hstream, code_loading); + snd_hdac_ext_stream_decouple(hstream->bus, hext_stream, true); + + return ret; +} + +/** * snd_hdac_ext_stream_init - initialize each stream (aka device) * @bus: HD-audio core bus * @hext_stream: HD-audio ext core stream object to initialize @@ -55,9 +90,16 @@ static void snd_hdac_ext_stream_init(struct hdac_bus *bus, int snd_hdac_ext_stream_init_all(struct hdac_bus *bus, int start_idx, int num_stream, int dir) { + struct pci_dev *pci = to_pci_dev(bus->dev); + int (*setup_op)(struct hdac_stream *, bool); int stream_tag = 0; int i, tag, idx = start_idx; + if (pci->device == PCI_DEVICE_ID_INTEL_HDA_APL) + setup_op = snd_hdac_apl_host_stream_setup; + else + setup_op = snd_hdac_stream_setup; + for (i = 0; i < num_stream; i++) { struct hdac_ext_stream *hext_stream = kzalloc(sizeof(*hext_stream), GFP_KERNEL); @@ -66,6 +108,7 @@ int snd_hdac_ext_stream_init_all(struct hdac_bus *bus, int start_idx, tag = ++stream_tag; snd_hdac_ext_stream_init(bus, hext_stream, idx, dir, tag); idx++; + hext_stream->host_setup = setup_op; } return 0; diff --git a/sound/hda/hdac_i915.c b/sound/hda/hdac_i915.c index b428537f28..365c36fdf2 100644 --- a/sound/hda/hdac_i915.c +++ b/sound/hda/hdac_i915.c @@ -10,6 +10,12 @@ #include <sound/hdaudio.h> #include <sound/hda_i915.h> #include <sound/hda_register.h> +#include <video/nomodeset.h> + +static int gpu_bind = -1; +module_param(gpu_bind, int, 0644); +MODULE_PARM_DESC(gpu_bind, "Whether to bind sound component to GPU " + "(1=always, 0=never, -1=on nomodeset(default))"); /** * snd_hdac_i915_set_bclk - Reprogram BCLK for HSW/BDW @@ -109,7 +115,8 @@ static int i915_component_master_match(struct device *dev, int subcomponent, hdac_pci = to_pci_dev(bus->dev); i915_pci = to_pci_dev(dev); - if (!strcmp(dev->driver->name, "i915") && + if ((!strcmp(dev->driver->name, "i915") || + !strcmp(dev->driver->name, "xe")) && subcomponent == I915_COMPONENT_AUDIO && connectivity_check(i915_pci, hdac_pci)) return 1; @@ -122,6 +129,9 @@ static int i915_gfx_present(struct pci_dev *hdac_pci) { struct pci_dev *display_dev = NULL; + if (!gpu_bind || (gpu_bind < 0 && video_firmware_drivers_only())) + return false; + for_each_pci_dev(display_dev) { if (display_dev->vendor == PCI_VENDOR_ID_INTEL && (display_dev->class >> 16) == PCI_BASE_CLASS_DISPLAY && @@ -163,17 +173,9 @@ int snd_hdac_i915_init(struct hdac_bus *bus) if (!acomp) return -ENODEV; if (!acomp->ops) { - if (!IS_ENABLED(CONFIG_MODULES) || - !request_module("i915")) { - /* 60s timeout */ - wait_for_completion_killable_timeout(&acomp->master_bind_complete, - msecs_to_jiffies(60 * 1000)); - } - } - if (!acomp->ops) { - dev_info(bus->dev, "couldn't bind with audio component\n"); snd_hdac_acomp_exit(bus); - return -ENODEV; + return dev_err_probe(bus->dev, -EPROBE_DEFER, + "couldn't bind with audio component\n"); } return 0; } diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c index 214a068052..610ea7a33c 100644 --- a/sound/hda/hdac_stream.c +++ b/sound/hda/hdac_stream.c @@ -252,12 +252,15 @@ EXPORT_SYMBOL_GPL(snd_hdac_stream_reset); /** * snd_hdac_stream_setup - set up the SD for streaming * @azx_dev: HD-audio core stream to set up + * @code_loading: Whether the stream is for PCM or code-loading. */ -int snd_hdac_stream_setup(struct hdac_stream *azx_dev) +int snd_hdac_stream_setup(struct hdac_stream *azx_dev, bool code_loading) { struct hdac_bus *bus = azx_dev->bus; struct snd_pcm_runtime *runtime; unsigned int val; + u16 reg; + int ret; if (azx_dev->substream) runtime = azx_dev->substream->runtime; @@ -300,7 +303,15 @@ int snd_hdac_stream_setup(struct hdac_stream *azx_dev) /* set the interrupt enable bits in the descriptor control register */ snd_hdac_stream_updatel(azx_dev, SD_CTL, 0, SD_INT_MASK); - azx_dev->fifo_size = snd_hdac_stream_readw(azx_dev, SD_FIFOSIZE) + 1; + if (!code_loading) { + /* Once SDxFMT is set, the controller programs SDxFIFOS to non-zero value. */ + ret = snd_hdac_stream_readw_poll(azx_dev, SD_FIFOSIZE, reg, + reg & AZX_SD_FIFOSIZE_MASK, 3, 300); + if (ret) + dev_dbg(bus->dev, "polling SD_FIFOSIZE 0x%04x failed: %d\n", + AZX_REG_SD_FIFOSIZE, ret); + azx_dev->fifo_size = reg; + } /* when LPIB delay correction gives a small negative value, * we ignore it; currently set the threshold statically to @@ -660,17 +671,15 @@ void snd_hdac_stream_timecounter_init(struct hdac_stream *azx_dev, struct hdac_stream *s; bool inited = false; u64 cycle_last = 0; - int i = 0; list_for_each_entry(s, &bus->stream_list, list) { - if (streams & (1 << i)) { + if ((streams & (1 << s->index))) { azx_timecounter_init(s, inited, cycle_last); if (!inited) { inited = true; cycle_last = s->tc.cycle_last; } } - i++; } snd_pcm_gettime(runtime, &runtime->trigger_tstamp); @@ -715,14 +724,13 @@ void snd_hdac_stream_sync(struct hdac_stream *azx_dev, bool start, unsigned int streams) { struct hdac_bus *bus = azx_dev->bus; - int i, nwait, timeout; + int nwait, timeout; struct hdac_stream *s; for (timeout = 5000; timeout; timeout--) { nwait = 0; - i = 0; list_for_each_entry(s, &bus->stream_list, list) { - if (!(streams & (1 << i++))) + if (!(streams & (1 << s->index))) continue; if (start) { @@ -945,7 +953,7 @@ int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format, if (err < 0) goto error; - snd_hdac_stream_setup(azx_dev); + snd_hdac_stream_setup(azx_dev, true); snd_hdac_dsp_unlock(azx_dev); return azx_dev->stream_tag; diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c index 756fa0aa69..6a384b922e 100644 --- a/sound/hda/intel-dsp-config.c +++ b/sound/hda/intel-dsp-config.c @@ -521,6 +521,16 @@ static const struct config_entry config_table[] = { .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, .device = PCI_DEVICE_ID_INTEL_HDA_MTL, }, + /* ArrowLake-S */ + { + .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, + .device = PCI_DEVICE_ID_INTEL_HDA_ARL_S, + }, + /* ArrowLake */ + { + .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, + .device = PCI_DEVICE_ID_INTEL_HDA_ARL, + }, #endif /* Lunar Lake */ |