diff options
author | Takashi Iwai <tiwai@suse.de> | 2023-10-31 08:58:36 +0100 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2023-10-31 08:58:36 +0100 |
commit | c468b5dd759ede754b23cbc9c50b048a781d4217 (patch) | |
tree | 3ec5f17b34fbb4711253fc4698d9cacbf6b9e71b /sound/hda | |
parent | 99248c8902f505ec064cf2b0f74629016f2f4c82 (diff) | |
parent | f71e0be5d297b25453fdf4c1757b3e83e94b5f98 (diff) |
Merge branch 'for-next' into for-linus
Pull 6.7 materials
Signed-off-by: Takashi Iwai <tiwai@suse.de>
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 | 23 |
3 files changed, 74 insertions, 16 deletions
diff --git a/sound/hda/ext/hdac_ext_stream.c b/sound/hda/ext/hdac_ext_stream.c index 11b7119cc47e..a3ac738f1130 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 b428537f284c..365c36fdf205 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 2633a4bb1d85..6ce24e248f8e 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 @@ -354,8 +365,10 @@ struct hdac_stream *snd_hdac_stream_assign(struct hdac_bus *bus, struct hdac_stream *res = NULL; /* make a non-zero unique key for the substream */ - int key = (substream->pcm->device << 16) | (substream->number << 2) | - (substream->stream + 1); + int key = (substream->number << 2) | (substream->stream + 1); + + if (substream->pcm) + key |= (substream->pcm->device << 16); spin_lock_irq(&bus->reg_lock); list_for_each_entry(azx_dev, &bus->stream_list, list) { @@ -943,7 +956,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; |