Commit fcc88d91 authored by Takashi Iwai's avatar Takashi Iwai

ALSA: hda - Bind with i915 component before codec binding

We used a on-demand i915 component binding for IvyBridge and
SandyBridge HDMI codecs, but it has a potential problem of the nested
module loading.  For avoiding that situation, assure the i915 binding
happening at the controller driver level for PCH controller devices,
where the initialization is performed in a detached work, instead of
calling from the codec driver probe.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 17890880
...@@ -1384,8 +1384,10 @@ static int azx_free(struct azx *chip) ...@@ -1384,8 +1384,10 @@ static int azx_free(struct azx *chip)
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
if (hda->need_i915_power) if (hda->need_i915_power)
snd_hdac_display_power(bus, false); snd_hdac_display_power(bus, false);
snd_hdac_i915_exit(bus);
} }
if (chip->driver_type == AZX_DRIVER_PCH ||
(chip->driver_caps & AZX_DCAPS_I915_POWERWELL))
snd_hdac_i915_exit(bus);
kfree(hda); kfree(hda);
return 0; return 0;
...@@ -2201,16 +2203,9 @@ static int azx_probe_continue(struct azx *chip) ...@@ -2201,16 +2203,9 @@ static int azx_probe_continue(struct azx *chip)
hda->probe_continued = 1; hda->probe_continued = 1;
/* Request display power well for the HDA controller or codec. For /* bind with i915 if needed */
* Haswell/Broadwell, both the display HDA controller and codec need if (chip->driver_type == AZX_DRIVER_PCH ||
* this power. For other platforms, like Baytrail/Braswell, only the (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)) {
* display codec needs the power and it can be released after probe.
*/
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
/* HSW/BDW controllers need this power */
if (CONTROLLER_IN_GPU(pci))
hda->need_i915_power = 1;
err = snd_hdac_i915_init(bus); err = snd_hdac_i915_init(bus);
if (err < 0) { if (err < 0) {
/* if the controller is bound only with HDMI/DP /* if the controller is bound only with HDMI/DP
...@@ -2222,9 +2217,22 @@ static int azx_probe_continue(struct azx *chip) ...@@ -2222,9 +2217,22 @@ static int azx_probe_continue(struct azx *chip)
dev_err(chip->card->dev, dev_err(chip->card->dev,
"HSW/BDW HD-audio HDMI/DP requires binding with gfx driver\n"); "HSW/BDW HD-audio HDMI/DP requires binding with gfx driver\n");
goto out_free; goto out_free;
} else } else {
goto skip_i915; /* don't bother any longer */
chip->driver_caps &= ~AZX_DCAPS_I915_POWERWELL;
}
} }
}
/* Request display power well for the HDA controller or codec. For
* Haswell/Broadwell, both the display HDA controller and codec need
* this power. For other platforms, like Baytrail/Braswell, only the
* display codec needs the power and it can be released after probe.
*/
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
/* HSW/BDW controllers need this power */
if (CONTROLLER_IN_GPU(pci))
hda->need_i915_power = 1;
err = snd_hdac_display_power(bus, true); err = snd_hdac_display_power(bus, true);
if (err < 0) { if (err < 0) {
...@@ -2234,7 +2242,6 @@ static int azx_probe_continue(struct azx *chip) ...@@ -2234,7 +2242,6 @@ static int azx_probe_continue(struct azx *chip)
} }
} }
skip_i915:
err = azx_first_init(chip); err = azx_first_init(chip);
if (err < 0) if (err < 0)
goto out_free; goto out_free;
......
...@@ -174,7 +174,6 @@ struct hdmi_spec { ...@@ -174,7 +174,6 @@ struct hdmi_spec {
/* i915/powerwell (Haswell+/Valleyview+) specific */ /* i915/powerwell (Haswell+/Valleyview+) specific */
bool use_acomp_notifier; /* use i915 eld_notify callback for hotplug */ bool use_acomp_notifier; /* use i915 eld_notify callback for hotplug */
struct i915_audio_component_audio_ops i915_audio_ops; struct i915_audio_component_audio_ops i915_audio_ops;
bool i915_bound; /* was i915 bound in this driver? */
struct hdac_chmap chmap; struct hdac_chmap chmap;
hda_nid_t vendor_nid; hda_nid_t vendor_nid;
...@@ -2234,8 +2233,6 @@ static void generic_spec_free(struct hda_codec *codec) ...@@ -2234,8 +2233,6 @@ static void generic_spec_free(struct hda_codec *codec)
struct hdmi_spec *spec = codec->spec; struct hdmi_spec *spec = codec->spec;
if (spec) { if (spec) {
if (spec->i915_bound)
snd_hdac_i915_exit(&codec->bus->core);
hdmi_array_free(spec); hdmi_array_free(spec);
kfree(spec); kfree(spec);
codec->spec = NULL; codec->spec = NULL;
...@@ -2607,21 +2604,17 @@ static int patch_i915_cpt_hdmi(struct hda_codec *codec) ...@@ -2607,21 +2604,17 @@ static int patch_i915_cpt_hdmi(struct hda_codec *codec)
struct hdmi_spec *spec; struct hdmi_spec *spec;
int err; int err;
/* no i915 component should have been bound before this */ /* requires i915 binding */
if (WARN_ON(codec->bus->core.audio_component)) if (!codec->bus->core.audio_component) {
return -EBUSY; codec_info(codec, "No i915 binding for Intel HDMI/DP codec\n");
return -ENODEV;
}
err = alloc_generic_hdmi(codec); err = alloc_generic_hdmi(codec);
if (err < 0) if (err < 0)
return err; return err;
spec = codec->spec; spec = codec->spec;
/* Try to bind with i915 now */
err = snd_hdac_i915_init(&codec->bus->core);
if (err < 0)
goto error;
spec->i915_bound = true;
err = hdmi_parse_codec(codec); err = hdmi_parse_codec(codec);
if (err < 0) if (err < 0)
goto error; goto error;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment