From f9b54e1961c7052e7d7817d707826eb2b9a1ca09 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 11 Jul 2018 15:05:06 +0200 Subject: ALSA: hda/i915: Allow delayed i915 audio component binding Currently HD-audio i915 audio binding doesn't support any delayed binding, and supposes that the i915 driver registers the component immediately. This has been OK, so far, but the work-in-progress change in i915 may introduce the asynchronous binding, which effectively delays the component registration. For addressing it, implement a completion to be synced with the master binding. The timeout is set to 10 seconds which should be long enough and hopefully be not too annoying if anyone boots up a debugging session with i915 KMS turned off. Signed-off-by: Takashi Iwai --- sound/hda/hdac_i915.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'sound/hda') diff --git a/sound/hda/hdac_i915.c b/sound/hda/hdac_i915.c index 8f2aa8bc1185..b5282cbbe489 100644 --- a/sound/hda/hdac_i915.c +++ b/sound/hda/hdac_i915.c @@ -20,6 +20,8 @@ #include #include +static struct completion bind_complete; + #define CONTROLLER_IN_GPU(pci) (((pci)->device == 0x0a0c) || \ ((pci)->device == 0x0c0c) || \ ((pci)->device == 0x0d0c) || \ @@ -97,6 +99,19 @@ static bool i915_gfx_present(void) return pci_dev_present(ids); } +static int i915_master_bind(struct device *dev, + struct drm_audio_component *acomp) +{ + complete_all(&bind_complete); + /* clear audio_ops here as it was needed only for completion call */ + acomp->audio_ops = NULL; + return 0; +} + +static const struct drm_audio_component_audio_ops i915_init_ops = { + .master_bind = i915_master_bind +}; + /** * snd_hdac_i915_init - Initialize i915 audio component * @bus: HDA core bus @@ -117,7 +132,9 @@ int snd_hdac_i915_init(struct hdac_bus *bus) if (!i915_gfx_present()) return -ENODEV; - err = snd_hdac_acomp_init(bus, NULL, + init_completion(&bind_complete); + + err = snd_hdac_acomp_init(bus, &i915_init_ops, i915_component_master_match, sizeof(struct i915_audio_component) - sizeof(*acomp)); if (err < 0) @@ -125,8 +142,11 @@ int snd_hdac_i915_init(struct hdac_bus *bus) acomp = bus->audio_component; if (!acomp) return -ENODEV; - if (!acomp->ops) + if (!acomp->ops) { request_module("i915"); + /* 10s timeout */ + wait_for_completion_timeout(&bind_complete, 10 * 1000); + } if (!acomp->ops) { snd_hdac_acomp_exit(bus); return -ENODEV; -- cgit v1.2.3