aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/hdaudio.h1
-rw-r--r--sound/hda/hdac_device.c7
-rw-r--r--sound/hda/hdac_sysfs.c3
-rw-r--r--sound/pci/hda/patch_realtek.c96
4 files changed, 80 insertions, 27 deletions
diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h
index 896c3f45503b..e8346784cf3f 100644
--- a/include/sound/hdaudio.h
+++ b/include/sound/hdaudio.h
@@ -81,6 +81,7 @@ struct hdac_device {
81 atomic_t in_pm; /* suspend/resume being performed */ 81 atomic_t in_pm; /* suspend/resume being performed */
82 82
83 /* sysfs */ 83 /* sysfs */
84 struct mutex widget_lock;
84 struct hdac_widget_tree *widgets; 85 struct hdac_widget_tree *widgets;
85 86
86 /* regmap */ 87 /* regmap */
diff --git a/sound/hda/hdac_device.c b/sound/hda/hdac_device.c
index 95b073ee4b32..4769f4c03e14 100644
--- a/sound/hda/hdac_device.c
+++ b/sound/hda/hdac_device.c
@@ -55,6 +55,7 @@ int snd_hdac_device_init(struct hdac_device *codec, struct hdac_bus *bus,
55 codec->bus = bus; 55 codec->bus = bus;
56 codec->addr = addr; 56 codec->addr = addr;
57 codec->type = HDA_DEV_CORE; 57 codec->type = HDA_DEV_CORE;
58 mutex_init(&codec->widget_lock);
58 pm_runtime_set_active(&codec->dev); 59 pm_runtime_set_active(&codec->dev);
59 pm_runtime_get_noresume(&codec->dev); 60 pm_runtime_get_noresume(&codec->dev);
60 atomic_set(&codec->in_pm, 0); 61 atomic_set(&codec->in_pm, 0);
@@ -141,7 +142,9 @@ int snd_hdac_device_register(struct hdac_device *codec)
141 err = device_add(&codec->dev); 142 err = device_add(&codec->dev);
142 if (err < 0) 143 if (err < 0)
143 return err; 144 return err;
145 mutex_lock(&codec->widget_lock);
144 err = hda_widget_sysfs_init(codec); 146 err = hda_widget_sysfs_init(codec);
147 mutex_unlock(&codec->widget_lock);
145 if (err < 0) { 148 if (err < 0) {
146 device_del(&codec->dev); 149 device_del(&codec->dev);
147 return err; 150 return err;
@@ -158,7 +161,9 @@ EXPORT_SYMBOL_GPL(snd_hdac_device_register);
158void snd_hdac_device_unregister(struct hdac_device *codec) 161void snd_hdac_device_unregister(struct hdac_device *codec)
159{ 162{
160 if (device_is_registered(&codec->dev)) { 163 if (device_is_registered(&codec->dev)) {
164 mutex_lock(&codec->widget_lock);
161 hda_widget_sysfs_exit(codec); 165 hda_widget_sysfs_exit(codec);
166 mutex_unlock(&codec->widget_lock);
162 device_del(&codec->dev); 167 device_del(&codec->dev);
163 snd_hdac_bus_remove_device(codec->bus, codec); 168 snd_hdac_bus_remove_device(codec->bus, codec);
164 } 169 }
@@ -404,7 +409,9 @@ int snd_hdac_refresh_widgets(struct hdac_device *codec, bool sysfs)
404 } 409 }
405 410
406 if (sysfs) { 411 if (sysfs) {
412 mutex_lock(&codec->widget_lock);
407 err = hda_widget_sysfs_reinit(codec, start_nid, nums); 413 err = hda_widget_sysfs_reinit(codec, start_nid, nums);
414 mutex_unlock(&codec->widget_lock);
408 if (err < 0) 415 if (err < 0)
409 return err; 416 return err;
410 } 417 }
diff --git a/sound/hda/hdac_sysfs.c b/sound/hda/hdac_sysfs.c
index fb2aa344981e..909d5ef1179c 100644
--- a/sound/hda/hdac_sysfs.c
+++ b/sound/hda/hdac_sysfs.c
@@ -395,6 +395,7 @@ static int widget_tree_create(struct hdac_device *codec)
395 return 0; 395 return 0;
396} 396}
397 397
398/* call with codec->widget_lock held */
398int hda_widget_sysfs_init(struct hdac_device *codec) 399int hda_widget_sysfs_init(struct hdac_device *codec)
399{ 400{
400 int err; 401 int err;
@@ -411,11 +412,13 @@ int hda_widget_sysfs_init(struct hdac_device *codec)
411 return 0; 412 return 0;
412} 413}
413 414
415/* call with codec->widget_lock held */
414void hda_widget_sysfs_exit(struct hdac_device *codec) 416void hda_widget_sysfs_exit(struct hdac_device *codec)
415{ 417{
416 widget_tree_free(codec); 418 widget_tree_free(codec);
417} 419}
418 420
421/* call with codec->widget_lock held */
419int hda_widget_sysfs_reinit(struct hdac_device *codec, 422int hda_widget_sysfs_reinit(struct hdac_device *codec,
420 hda_nid_t start_nid, int num_nodes) 423 hda_nid_t start_nid, int num_nodes)
421{ 424{
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index c53ca589c930..f83f21d64dd4 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -478,12 +478,45 @@ static void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
478 set_eapd(codec, *p, on); 478 set_eapd(codec, *p, on);
479} 479}
480 480
481static int find_ext_mic_pin(struct hda_codec *codec);
482
483static void alc_headset_mic_no_shutup(struct hda_codec *codec)
484{
485 const struct hda_pincfg *pin;
486 int mic_pin = find_ext_mic_pin(codec);
487 int i;
488
489 /* don't shut up pins when unloading the driver; otherwise it breaks
490 * the default pin setup at the next load of the driver
491 */
492 if (codec->bus->shutdown)
493 return;
494
495 snd_array_for_each(&codec->init_pins, i, pin) {
496 /* use read here for syncing after issuing each verb */
497 if (pin->nid != mic_pin)
498 snd_hda_codec_read(codec, pin->nid, 0,
499 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
500 }
501
502 codec->pins_shutup = 1;
503}
504
481static void alc_shutup_pins(struct hda_codec *codec) 505static void alc_shutup_pins(struct hda_codec *codec)
482{ 506{
483 struct alc_spec *spec = codec->spec; 507 struct alc_spec *spec = codec->spec;
484 508
485 if (!spec->no_shutup_pins) 509 switch (codec->core.vendor_id) {
486 snd_hda_shutup_pins(codec); 510 case 0x10ec0286:
511 case 0x10ec0288:
512 case 0x10ec0298:
513 alc_headset_mic_no_shutup(codec);
514 break;
515 default:
516 if (!spec->no_shutup_pins)
517 snd_hda_shutup_pins(codec);
518 break;
519 }
487} 520}
488 521
489/* generic shutup callback; 522/* generic shutup callback;
@@ -502,7 +535,6 @@ static void alc_eapd_shutup(struct hda_codec *codec)
502/* generic EAPD initialization */ 535/* generic EAPD initialization */
503static void alc_auto_init_amp(struct hda_codec *codec, int type) 536static void alc_auto_init_amp(struct hda_codec *codec, int type)
504{ 537{
505 alc_fill_eapd_coef(codec);
506 alc_auto_setup_eapd(codec, true); 538 alc_auto_setup_eapd(codec, true);
507 alc_write_gpio(codec); 539 alc_write_gpio(codec);
508 switch (type) { 540 switch (type) {
@@ -797,10 +829,22 @@ static int alc_build_controls(struct hda_codec *codec)
797 * Common callbacks 829 * Common callbacks
798 */ 830 */
799 831
832static void alc_pre_init(struct hda_codec *codec)
833{
834 alc_fill_eapd_coef(codec);
835}
836
837#define is_s4_resume(codec) \
838 ((codec)->core.dev.power.power_state.event == PM_EVENT_RESTORE)
839
800static int alc_init(struct hda_codec *codec) 840static int alc_init(struct hda_codec *codec)
801{ 841{
802 struct alc_spec *spec = codec->spec; 842 struct alc_spec *spec = codec->spec;
803 843
844 /* hibernation resume needs the full chip initialization */
845 if (is_s4_resume(codec))
846 alc_pre_init(codec);
847
804 if (spec->init_hook) 848 if (spec->init_hook)
805 spec->init_hook(codec); 849 spec->init_hook(codec);
806 850
@@ -1538,6 +1582,8 @@ static int patch_alc880(struct hda_codec *codec)
1538 1582
1539 codec->patch_ops.unsol_event = alc880_unsol_event; 1583 codec->patch_ops.unsol_event = alc880_unsol_event;
1540 1584
1585 alc_pre_init(codec);
1586
1541 snd_hda_pick_fixup(codec, alc880_fixup_models, alc880_fixup_tbl, 1587 snd_hda_pick_fixup(codec, alc880_fixup_models, alc880_fixup_tbl,
1542 alc880_fixups); 1588 alc880_fixups);
1543 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); 1589 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
@@ -1789,6 +1835,8 @@ static int patch_alc260(struct hda_codec *codec)
1789 1835
1790 spec->shutup = alc_eapd_shutup; 1836 spec->shutup = alc_eapd_shutup;
1791 1837
1838 alc_pre_init(codec);
1839
1792 snd_hda_pick_fixup(codec, alc260_fixup_models, alc260_fixup_tbl, 1840 snd_hda_pick_fixup(codec, alc260_fixup_models, alc260_fixup_tbl,
1793 alc260_fixups); 1841 alc260_fixups);
1794 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); 1842 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
@@ -2492,6 +2540,8 @@ static int patch_alc882(struct hda_codec *codec)
2492 break; 2540 break;
2493 } 2541 }
2494 2542
2543 alc_pre_init(codec);
2544
2495 snd_hda_pick_fixup(codec, alc882_fixup_models, alc882_fixup_tbl, 2545 snd_hda_pick_fixup(codec, alc882_fixup_models, alc882_fixup_tbl,
2496 alc882_fixups); 2546 alc882_fixups);
2497 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); 2547 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
@@ -2666,6 +2716,8 @@ static int patch_alc262(struct hda_codec *codec)
2666#endif 2716#endif
2667 alc_fix_pll_init(codec, 0x20, 0x0a, 10); 2717 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
2668 2718
2719 alc_pre_init(codec);
2720
2669 snd_hda_pick_fixup(codec, alc262_fixup_models, alc262_fixup_tbl, 2721 snd_hda_pick_fixup(codec, alc262_fixup_models, alc262_fixup_tbl,
2670 alc262_fixups); 2722 alc262_fixups);
2671 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); 2723 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
@@ -2810,6 +2862,8 @@ static int patch_alc268(struct hda_codec *codec)
2810 2862
2811 spec->shutup = alc_eapd_shutup; 2863 spec->shutup = alc_eapd_shutup;
2812 2864
2865 alc_pre_init(codec);
2866
2813 snd_hda_pick_fixup(codec, alc268_fixup_models, alc268_fixup_tbl, alc268_fixups); 2867 snd_hda_pick_fixup(codec, alc268_fixup_models, alc268_fixup_tbl, alc268_fixups);
2814 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); 2868 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
2815 2869
@@ -2924,27 +2978,6 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
2924 return alc_parse_auto_config(codec, alc269_ignore, ssids); 2978 return alc_parse_auto_config(codec, alc269_ignore, ssids);
2925} 2979}
2926 2980
2927static int find_ext_mic_pin(struct hda_codec *codec);
2928
2929static void alc286_shutup(struct hda_codec *codec)
2930{
2931 const struct hda_pincfg *pin;
2932 int i;
2933 int mic_pin = find_ext_mic_pin(codec);
2934 /* don't shut up pins when unloading the driver; otherwise it breaks
2935 * the default pin setup at the next load of the driver
2936 */
2937 if (codec->bus->shutdown)
2938 return;
2939 snd_array_for_each(&codec->init_pins, i, pin) {
2940 /* use read here for syncing after issuing each verb */
2941 if (pin->nid != mic_pin)
2942 snd_hda_codec_read(codec, pin->nid, 0,
2943 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
2944 }
2945 codec->pins_shutup = 1;
2946}
2947
2948static void alc269vb_toggle_power_output(struct hda_codec *codec, int power_up) 2981static void alc269vb_toggle_power_output(struct hda_codec *codec, int power_up)
2949{ 2982{
2950 alc_update_coef_idx(codec, 0x04, 1 << 11, power_up ? (1 << 11) : 0); 2983 alc_update_coef_idx(codec, 0x04, 1 << 11, power_up ? (1 << 11) : 0);
@@ -6964,7 +6997,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
6964 SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC), 6997 SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC),
6965 SND_PCI_QUIRK(0x1558, 0x1325, "System76 Darter Pro (darp5)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), 6998 SND_PCI_QUIRK(0x1558, 0x1325, "System76 Darter Pro (darp5)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
6966 SND_PCI_QUIRK(0x1558, 0x8550, "System76 Gazelle (gaze14)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), 6999 SND_PCI_QUIRK(0x1558, 0x8550, "System76 Gazelle (gaze14)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
6967 SND_PCI_QUIRK(0x1558, 0x8560, "System76 Gazelle (gaze14)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), 7000 SND_PCI_QUIRK(0x1558, 0x8551, "System76 Gazelle (gaze14)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
7001 SND_PCI_QUIRK(0x1558, 0x8560, "System76 Gazelle (gaze14)", ALC269_FIXUP_HEADSET_MIC),
7002 SND_PCI_QUIRK(0x1558, 0x8561, "System76 Gazelle (gaze14)", ALC269_FIXUP_HEADSET_MIC),
6968 SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC233_FIXUP_LENOVO_MULTI_CODECS), 7003 SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC233_FIXUP_LENOVO_MULTI_CODECS),
6969 SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), 7004 SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
6970 SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE), 7005 SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
@@ -7007,7 +7042,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
7007 SND_PCI_QUIRK(0x17aa, 0x313c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION), 7042 SND_PCI_QUIRK(0x17aa, 0x313c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
7008 SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI), 7043 SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
7009 SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC), 7044 SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
7010 SND_PCI_QUIRK(0x17aa, 0x3978, "IdeaPad Y410P", ALC269_FIXUP_NO_SHUTUP), 7045 SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
7011 SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), 7046 SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
7012 SND_PCI_QUIRK(0x17aa, 0x501a, "Thinkpad", ALC283_FIXUP_INT_MIC), 7047 SND_PCI_QUIRK(0x17aa, 0x501a, "Thinkpad", ALC283_FIXUP_INT_MIC),
7013 SND_PCI_QUIRK(0x17aa, 0x501e, "Thinkpad L440", ALC292_FIXUP_TPT440_DOCK), 7048 SND_PCI_QUIRK(0x17aa, 0x501e, "Thinkpad L440", ALC292_FIXUP_TPT440_DOCK),
@@ -7736,7 +7771,6 @@ static int patch_alc269(struct hda_codec *codec)
7736 case 0x10ec0286: 7771 case 0x10ec0286:
7737 case 0x10ec0288: 7772 case 0x10ec0288:
7738 spec->codec_variant = ALC269_TYPE_ALC286; 7773 spec->codec_variant = ALC269_TYPE_ALC286;
7739 spec->shutup = alc286_shutup;
7740 break; 7774 break;
7741 case 0x10ec0298: 7775 case 0x10ec0298:
7742 spec->codec_variant = ALC269_TYPE_ALC298; 7776 spec->codec_variant = ALC269_TYPE_ALC298;
@@ -7805,6 +7839,8 @@ static int patch_alc269(struct hda_codec *codec)
7805 spec->init_hook = alc5505_dsp_init; 7839 spec->init_hook = alc5505_dsp_init;
7806 } 7840 }
7807 7841
7842 alc_pre_init(codec);
7843
7808 snd_hda_pick_fixup(codec, alc269_fixup_models, 7844 snd_hda_pick_fixup(codec, alc269_fixup_models,
7809 alc269_fixup_tbl, alc269_fixups); 7845 alc269_fixup_tbl, alc269_fixups);
7810 snd_hda_pick_pin_fixup(codec, alc269_pin_fixup_tbl, alc269_fixups); 7846 snd_hda_pick_pin_fixup(codec, alc269_pin_fixup_tbl, alc269_fixups);
@@ -7947,6 +7983,8 @@ static int patch_alc861(struct hda_codec *codec)
7947 spec->power_hook = alc_power_eapd; 7983 spec->power_hook = alc_power_eapd;
7948#endif 7984#endif
7949 7985
7986 alc_pre_init(codec);
7987
7950 snd_hda_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups); 7988 snd_hda_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups);
7951 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); 7989 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
7952 7990
@@ -8044,6 +8082,8 @@ static int patch_alc861vd(struct hda_codec *codec)
8044 8082
8045 spec->shutup = alc_eapd_shutup; 8083 spec->shutup = alc_eapd_shutup;
8046 8084
8085 alc_pre_init(codec);
8086
8047 snd_hda_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups); 8087 snd_hda_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups);
8048 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); 8088 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
8049 8089
@@ -8779,6 +8819,8 @@ static int patch_alc662(struct hda_codec *codec)
8779 break; 8819 break;
8780 } 8820 }
8781 8821
8822 alc_pre_init(codec);
8823
8782 snd_hda_pick_fixup(codec, alc662_fixup_models, 8824 snd_hda_pick_fixup(codec, alc662_fixup_models,
8783 alc662_fixup_tbl, alc662_fixups); 8825 alc662_fixup_tbl, alc662_fixups);
8784 snd_hda_pick_pin_fixup(codec, alc662_pin_fixup_tbl, alc662_fixups); 8826 snd_hda_pick_pin_fixup(codec, alc662_pin_fixup_tbl, alc662_fixups);