Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4032da5f authored by Takashi Iwai's avatar Takashi Iwai
Browse files

Merge branch 'topic/hda-fix' into for-next

parents f03293d8 43f6c8d9
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -295,6 +295,8 @@ struct hda_codec {


#define list_for_each_codec(c, bus) \
#define list_for_each_codec(c, bus) \
	list_for_each_entry(c, &(bus)->core.codec_list, core.list)
	list_for_each_entry(c, &(bus)->core.codec_list, core.list)
#define list_for_each_codec_safe(c, n, bus)				\
	list_for_each_entry_safe(c, n, &(bus)->core.codec_list, core.list)


/* snd_hda_codec_read/write optional flags */
/* snd_hda_codec_read/write optional flags */
#define HDA_RW_NO_RESPONSE_FALLBACK	(1 << 0)
#define HDA_RW_NO_RESPONSE_FALLBACK	(1 << 0)
+9 −2
Original line number Original line Diff line number Diff line
@@ -1337,10 +1337,17 @@ EXPORT_SYMBOL_GPL(azx_probe_codecs);
/* configure each codec instance */
/* configure each codec instance */
int azx_codec_configure(struct azx *chip)
int azx_codec_configure(struct azx *chip)
{
{
	struct hda_codec *codec;
	struct hda_codec *codec, *next;
	list_for_each_codec(codec, &chip->bus) {

	/* use _safe version here since snd_hda_codec_configure() deregisters
	 * the device upon error and deletes itself from the bus list.
	 */
	list_for_each_codec_safe(codec, next, &chip->bus) {
		snd_hda_codec_configure(codec);
		snd_hda_codec_configure(codec);
	}
	}

	if (!azx_bus(chip)->num_codecs)
		return -ENODEV;
	return 0;
	return 0;
}
}
EXPORT_SYMBOL_GPL(azx_codec_configure);
EXPORT_SYMBOL_GPL(azx_codec_configure);
+1 −0
Original line number Original line Diff line number Diff line
@@ -3216,6 +3216,7 @@ static int check_dyn_adc_switch(struct hda_codec *codec)
						spec->input_paths[i][nums]);
						spec->input_paths[i][nums]);
					spec->input_paths[i][nums] =
					spec->input_paths[i][nums] =
						spec->input_paths[i][n];
						spec->input_paths[i][n];
					spec->input_paths[i][n] = 0;
				}
				}
			}
			}
			nums++;
			nums++;
+21 −14
Original line number Original line Diff line number Diff line
@@ -1379,8 +1379,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;
@@ -2196,16 +2198,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
@@ -2217,9 +2212,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) {
@@ -2229,7 +2237,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;
+34 −60
Original line number Original line Diff line number Diff line
@@ -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)
	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;
@@ -2506,19 +2503,41 @@ static void i915_pin_cvt_fixup(struct hda_codec *codec,
	}
	}
}
}


/* Intel Haswell and onwards; audio component with eld notifier */
/* precondition and allocation for Intel codecs */
static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid)
static int alloc_intel_hdmi(struct hda_codec *codec)
{
{
	struct hdmi_spec *spec;
	/* requires i915 binding */
	int err;

	/* HSW+ requires i915 binding */
	if (!codec->bus->core.audio_component) {
	if (!codec->bus->core.audio_component) {
		codec_info(codec, "No i915 binding for Intel HDMI/DP codec\n");
		codec_info(codec, "No i915 binding for Intel HDMI/DP codec\n");
		return -ENODEV;
		return -ENODEV;
	}
	}


	err = alloc_generic_hdmi(codec);
	return alloc_generic_hdmi(codec);
}

/* parse and post-process for Intel codecs */
static int parse_intel_hdmi(struct hda_codec *codec)
{
	int err;

	err = hdmi_parse_codec(codec);
	if (err < 0) {
		generic_spec_free(codec);
		return err;
	}

	generic_hdmi_init_per_pins(codec);
	register_i915_notifier(codec);
	return 0;
}

/* Intel Haswell and onwards; audio component with eld notifier */
static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid)
{
	struct hdmi_spec *spec;
	int err;

	err = alloc_intel_hdmi(codec);
	if (err < 0)
	if (err < 0)
		return err;
		return err;
	spec = codec->spec;
	spec = codec->spec;
@@ -2542,15 +2561,7 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid)
	spec->ops.setup_stream = i915_hsw_setup_stream;
	spec->ops.setup_stream = i915_hsw_setup_stream;
	spec->ops.pin_cvt_fixup = i915_pin_cvt_fixup;
	spec->ops.pin_cvt_fixup = i915_pin_cvt_fixup;


	err = hdmi_parse_codec(codec);
	return parse_intel_hdmi(codec);
	if (err < 0) {
		generic_spec_free(codec);
		return err;
	}

	generic_hdmi_init_per_pins(codec);
	register_i915_notifier(codec);
	return 0;
}
}


static int patch_i915_hsw_hdmi(struct hda_codec *codec)
static int patch_i915_hsw_hdmi(struct hda_codec *codec)
@@ -2569,13 +2580,7 @@ static int patch_i915_byt_hdmi(struct hda_codec *codec)
	struct hdmi_spec *spec;
	struct hdmi_spec *spec;
	int err;
	int err;


	/* requires i915 binding */
	err = alloc_intel_hdmi(codec);
	if (!codec->bus->core.audio_component) {
		codec_info(codec, "No i915 binding for Intel HDMI/DP codec\n");
		return -ENODEV;
	}

	err = alloc_generic_hdmi(codec);
	if (err < 0)
	if (err < 0)
		return err;
		return err;
	spec = codec->spec;
	spec = codec->spec;
@@ -2590,49 +2595,18 @@ static int patch_i915_byt_hdmi(struct hda_codec *codec)


	spec->ops.pin_cvt_fixup = i915_pin_cvt_fixup;
	spec->ops.pin_cvt_fixup = i915_pin_cvt_fixup;


	err = hdmi_parse_codec(codec);
	return parse_intel_hdmi(codec);
	if (err < 0) {
		generic_spec_free(codec);
		return err;
	}

	generic_hdmi_init_per_pins(codec);
	register_i915_notifier(codec);
	return 0;
}
}


/* Intel IronLake, SandyBridge and IvyBridge; with eld notifier */
/* Intel IronLake, SandyBridge and IvyBridge; with eld notifier */
static int patch_i915_cpt_hdmi(struct hda_codec *codec)
static int patch_i915_cpt_hdmi(struct hda_codec *codec)
{
{
	struct hdmi_spec *spec;
	int err;
	int err;


	/* no i915 component should have been bound before this */
	err = alloc_intel_hdmi(codec);
	if (WARN_ON(codec->bus->core.audio_component))
		return -EBUSY;

	err = alloc_generic_hdmi(codec);
	if (err < 0)
	if (err < 0)
		return err;
		return err;
	spec = codec->spec;
	return parse_intel_hdmi(codec);

	/* 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);
	if (err < 0)
		goto error;

	generic_hdmi_init_per_pins(codec);
	register_i915_notifier(codec);
	return 0;

 error:
	generic_spec_free(codec);
	return err;
}
}


/*
/*