mirror of https://gitee.com/openkylin/linux.git
Merge branch 'topic/hda-fix' into for-next
This commit is contained in:
commit
4032da5ffe
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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++;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* precondition and allocation for Intel codecs */
|
||||||
|
static int alloc_intel_hdmi(struct hda_codec *codec)
|
||||||
|
{
|
||||||
|
/* requires i915 binding */
|
||||||
|
if (!codec->bus->core.audio_component) {
|
||||||
|
codec_info(codec, "No i915 binding for Intel HDMI/DP codec\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 */
|
/* Intel Haswell and onwards; audio component with eld notifier */
|
||||||
static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid)
|
static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid)
|
||||||
{
|
{
|
||||||
struct hdmi_spec *spec;
|
struct hdmi_spec *spec;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
/* HSW+ 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;
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue