diff options
author | Takashi Iwai <tiwai@suse.de> | 2014-08-04 05:11:22 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2014-08-04 05:11:22 -0400 |
commit | 2e65b8916cce4436df29812610d2c2fecdb42b5a (patch) | |
tree | fdcae670bd651c8e772eb7cd60420eba5d26a0db /sound/pci | |
parent | 7440850c20b69658f322119d20a94dc914127cc7 (diff) | |
parent | 00ef99408b6cc8d86ca614ada8025aa3606860db (diff) |
Merge branch 'for-next' into for-linus
Diffstat (limited to 'sound/pci')
25 files changed, 841 insertions, 3745 deletions
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c index 9f10c9e0df5e..631aaa4046ad 100644 --- a/sound/pci/echoaudio/echoaudio.c +++ b/sound/pci/echoaudio/echoaudio.c | |||
@@ -1754,9 +1754,6 @@ static struct snd_kcontrol_new snd_echo_vumeters_switch = { | |||
1754 | static int snd_echo_vumeters_info(struct snd_kcontrol *kcontrol, | 1754 | static int snd_echo_vumeters_info(struct snd_kcontrol *kcontrol, |
1755 | struct snd_ctl_elem_info *uinfo) | 1755 | struct snd_ctl_elem_info *uinfo) |
1756 | { | 1756 | { |
1757 | struct echoaudio *chip; | ||
1758 | |||
1759 | chip = snd_kcontrol_chip(kcontrol); | ||
1760 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 1757 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
1761 | uinfo->count = 96; | 1758 | uinfo->count = 96; |
1762 | uinfo->value.integer.min = ECHOGAIN_MINOUT; | 1759 | uinfo->value.integer.min = ECHOGAIN_MINOUT; |
@@ -1798,9 +1795,6 @@ static struct snd_kcontrol_new snd_echo_vumeters = { | |||
1798 | static int snd_echo_channels_info_info(struct snd_kcontrol *kcontrol, | 1795 | static int snd_echo_channels_info_info(struct snd_kcontrol *kcontrol, |
1799 | struct snd_ctl_elem_info *uinfo) | 1796 | struct snd_ctl_elem_info *uinfo) |
1800 | { | 1797 | { |
1801 | struct echoaudio *chip; | ||
1802 | |||
1803 | chip = snd_kcontrol_chip(kcontrol); | ||
1804 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 1798 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
1805 | uinfo->count = 6; | 1799 | uinfo->count = 6; |
1806 | uinfo->value.integer.min = 0; | 1800 | uinfo->value.integer.min = 0; |
diff --git a/sound/pci/hda/dell_wmi_helper.c b/sound/pci/hda/dell_wmi_helper.c new file mode 100644 index 000000000000..9c22f95838ef --- /dev/null +++ b/sound/pci/hda/dell_wmi_helper.c | |||
@@ -0,0 +1,76 @@ | |||
1 | /* Helper functions for Dell Mic Mute LED control; | ||
2 | * to be included from codec driver | ||
3 | */ | ||
4 | |||
5 | #if IS_ENABLED(CONFIG_LEDS_DELL_NETBOOKS) | ||
6 | #include <linux/dell-led.h> | ||
7 | |||
8 | static int dell_led_value; | ||
9 | static int (*dell_led_set_func)(int, int); | ||
10 | static void (*dell_old_cap_hook)(struct hda_codec *, | ||
11 | struct snd_kcontrol *, | ||
12 | struct snd_ctl_elem_value *); | ||
13 | |||
14 | static void update_dell_wmi_micmute_led(struct hda_codec *codec, | ||
15 | struct snd_kcontrol *kcontrol, | ||
16 | struct snd_ctl_elem_value *ucontrol) | ||
17 | { | ||
18 | if (dell_old_cap_hook) | ||
19 | dell_old_cap_hook(codec, kcontrol, ucontrol); | ||
20 | |||
21 | if (!ucontrol || !dell_led_set_func) | ||
22 | return; | ||
23 | if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) { | ||
24 | /* TODO: How do I verify if it's a mono or stereo here? */ | ||
25 | int val = (ucontrol->value.integer.value[0] || ucontrol->value.integer.value[1]) ? 0 : 1; | ||
26 | if (val == dell_led_value) | ||
27 | return; | ||
28 | dell_led_value = val; | ||
29 | if (dell_led_set_func) | ||
30 | dell_led_set_func(DELL_LED_MICMUTE, dell_led_value); | ||
31 | } | ||
32 | } | ||
33 | |||
34 | |||
35 | static void alc_fixup_dell_wmi(struct hda_codec *codec, | ||
36 | const struct hda_fixup *fix, int action) | ||
37 | { | ||
38 | struct alc_spec *spec = codec->spec; | ||
39 | bool removefunc = false; | ||
40 | |||
41 | if (action == HDA_FIXUP_ACT_PROBE) { | ||
42 | if (!dell_led_set_func) | ||
43 | dell_led_set_func = symbol_request(dell_app_wmi_led_set); | ||
44 | if (!dell_led_set_func) { | ||
45 | codec_warn(codec, "Failed to find dell wmi symbol dell_app_wmi_led_set\n"); | ||
46 | return; | ||
47 | } | ||
48 | |||
49 | removefunc = true; | ||
50 | if (dell_led_set_func(DELL_LED_MICMUTE, false) >= 0) { | ||
51 | dell_led_value = 0; | ||
52 | if (spec->gen.num_adc_nids > 1) | ||
53 | codec_dbg(codec, "Skipping micmute LED control due to several ADCs"); | ||
54 | else { | ||
55 | dell_old_cap_hook = spec->gen.cap_sync_hook; | ||
56 | spec->gen.cap_sync_hook = update_dell_wmi_micmute_led; | ||
57 | removefunc = false; | ||
58 | } | ||
59 | } | ||
60 | |||
61 | } | ||
62 | |||
63 | if (dell_led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) { | ||
64 | symbol_put(dell_app_wmi_led_set); | ||
65 | dell_led_set_func = NULL; | ||
66 | dell_old_cap_hook = NULL; | ||
67 | } | ||
68 | } | ||
69 | |||
70 | #else /* CONFIG_LEDS_DELL_NETBOOKS */ | ||
71 | static void alc_fixup_dell_wmi(struct hda_codec *codec, | ||
72 | const struct hda_fixup *fix, int action) | ||
73 | { | ||
74 | } | ||
75 | |||
76 | #endif /* CONFIG_LEDS_DELL_NETBOOKS */ | ||
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c index dabe41975a9d..51dea49aadd4 100644 --- a/sound/pci/hda/hda_auto_parser.c +++ b/sound/pci/hda/hda_auto_parser.c | |||
@@ -17,8 +17,6 @@ | |||
17 | #include "hda_local.h" | 17 | #include "hda_local.h" |
18 | #include "hda_auto_parser.h" | 18 | #include "hda_auto_parser.h" |
19 | 19 | ||
20 | #define SFX "hda_codec: " | ||
21 | |||
22 | /* | 20 | /* |
23 | * Helper for automatic pin configuration | 21 | * Helper for automatic pin configuration |
24 | */ | 22 | */ |
@@ -856,7 +854,7 @@ void snd_hda_pick_pin_fixup(struct hda_codec *codec, | |||
856 | { | 854 | { |
857 | const struct snd_hda_pin_quirk *pq; | 855 | const struct snd_hda_pin_quirk *pq; |
858 | 856 | ||
859 | if (codec->fixup_forced) | 857 | if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET) |
860 | return; | 858 | return; |
861 | 859 | ||
862 | for (pq = pin_quirk; pq->subvendor; pq++) { | 860 | for (pq = pin_quirk; pq->subvendor; pq++) { |
@@ -882,14 +880,17 @@ void snd_hda_pick_fixup(struct hda_codec *codec, | |||
882 | const struct hda_fixup *fixlist) | 880 | const struct hda_fixup *fixlist) |
883 | { | 881 | { |
884 | const struct snd_pci_quirk *q; | 882 | const struct snd_pci_quirk *q; |
885 | int id = -1; | 883 | int id = HDA_FIXUP_ID_NOT_SET; |
886 | const char *name = NULL; | 884 | const char *name = NULL; |
887 | 885 | ||
886 | if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET) | ||
887 | return; | ||
888 | |||
888 | /* when model=nofixup is given, don't pick up any fixups */ | 889 | /* when model=nofixup is given, don't pick up any fixups */ |
889 | if (codec->modelname && !strcmp(codec->modelname, "nofixup")) { | 890 | if (codec->modelname && !strcmp(codec->modelname, "nofixup")) { |
890 | codec->fixup_list = NULL; | 891 | codec->fixup_list = NULL; |
891 | codec->fixup_id = -1; | 892 | codec->fixup_name = NULL; |
892 | codec->fixup_forced = 1; | 893 | codec->fixup_id = HDA_FIXUP_ID_NO_FIXUP; |
893 | return; | 894 | return; |
894 | } | 895 | } |
895 | 896 | ||
@@ -899,13 +900,12 @@ void snd_hda_pick_fixup(struct hda_codec *codec, | |||
899 | codec->fixup_id = models->id; | 900 | codec->fixup_id = models->id; |
900 | codec->fixup_name = models->name; | 901 | codec->fixup_name = models->name; |
901 | codec->fixup_list = fixlist; | 902 | codec->fixup_list = fixlist; |
902 | codec->fixup_forced = 1; | ||
903 | return; | 903 | return; |
904 | } | 904 | } |
905 | models++; | 905 | models++; |
906 | } | 906 | } |
907 | } | 907 | } |
908 | if (id < 0 && quirk) { | 908 | if (quirk) { |
909 | q = snd_pci_quirk_lookup(codec->bus->pci, quirk); | 909 | q = snd_pci_quirk_lookup(codec->bus->pci, quirk); |
910 | if (q) { | 910 | if (q) { |
911 | id = q->value; | 911 | id = q->value; |
@@ -929,7 +929,6 @@ void snd_hda_pick_fixup(struct hda_codec *codec, | |||
929 | } | 929 | } |
930 | } | 930 | } |
931 | 931 | ||
932 | codec->fixup_forced = 0; | ||
933 | codec->fixup_id = id; | 932 | codec->fixup_id = id; |
934 | if (id >= 0) { | 933 | if (id >= 0) { |
935 | codec->fixup_list = fixlist; | 934 | codec->fixup_list = fixlist; |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 4c20277a6835..ec6a7d0d1886 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -1476,6 +1476,7 @@ int snd_hda_codec_new(struct hda_bus *bus, | |||
1476 | 1476 | ||
1477 | INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work); | 1477 | INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work); |
1478 | codec->depop_delay = -1; | 1478 | codec->depop_delay = -1; |
1479 | codec->fixup_id = HDA_FIXUP_ID_NOT_SET; | ||
1479 | 1480 | ||
1480 | #ifdef CONFIG_PM | 1481 | #ifdef CONFIG_PM |
1481 | spin_lock_init(&codec->power_lock); | 1482 | spin_lock_init(&codec->power_lock); |
@@ -2727,7 +2728,7 @@ int snd_hda_codec_reset(struct hda_codec *codec) | |||
2727 | return 0; | 2728 | return 0; |
2728 | } | 2729 | } |
2729 | 2730 | ||
2730 | typedef int (*map_slave_func_t)(void *, struct snd_kcontrol *); | 2731 | typedef int (*map_slave_func_t)(struct hda_codec *, void *, struct snd_kcontrol *); |
2731 | 2732 | ||
2732 | /* apply the function to all matching slave ctls in the mixer list */ | 2733 | /* apply the function to all matching slave ctls in the mixer list */ |
2733 | static int map_slaves(struct hda_codec *codec, const char * const *slaves, | 2734 | static int map_slaves(struct hda_codec *codec, const char * const *slaves, |
@@ -2751,7 +2752,7 @@ static int map_slaves(struct hda_codec *codec, const char * const *slaves, | |||
2751 | name = tmpname; | 2752 | name = tmpname; |
2752 | } | 2753 | } |
2753 | if (!strcmp(sctl->id.name, name)) { | 2754 | if (!strcmp(sctl->id.name, name)) { |
2754 | err = func(data, sctl); | 2755 | err = func(codec, data, sctl); |
2755 | if (err) | 2756 | if (err) |
2756 | return err; | 2757 | return err; |
2757 | break; | 2758 | break; |
@@ -2761,13 +2762,15 @@ static int map_slaves(struct hda_codec *codec, const char * const *slaves, | |||
2761 | return 0; | 2762 | return 0; |
2762 | } | 2763 | } |
2763 | 2764 | ||
2764 | static int check_slave_present(void *data, struct snd_kcontrol *sctl) | 2765 | static int check_slave_present(struct hda_codec *codec, |
2766 | void *data, struct snd_kcontrol *sctl) | ||
2765 | { | 2767 | { |
2766 | return 1; | 2768 | return 1; |
2767 | } | 2769 | } |
2768 | 2770 | ||
2769 | /* guess the value corresponding to 0dB */ | 2771 | /* guess the value corresponding to 0dB */ |
2770 | static int get_kctl_0dB_offset(struct snd_kcontrol *kctl, int *step_to_check) | 2772 | static int get_kctl_0dB_offset(struct hda_codec *codec, |
2773 | struct snd_kcontrol *kctl, int *step_to_check) | ||
2771 | { | 2774 | { |
2772 | int _tlv[4]; | 2775 | int _tlv[4]; |
2773 | const int *tlv = NULL; | 2776 | const int *tlv = NULL; |
@@ -2788,7 +2791,7 @@ static int get_kctl_0dB_offset(struct snd_kcontrol *kctl, int *step_to_check) | |||
2788 | if (!step) | 2791 | if (!step) |
2789 | return -1; | 2792 | return -1; |
2790 | if (*step_to_check && *step_to_check != step) { | 2793 | if (*step_to_check && *step_to_check != step) { |
2791 | snd_printk(KERN_ERR "hda_codec: Mismatching dB step for vmaster slave (%d!=%d)\n", | 2794 | codec_err(codec, "Mismatching dB step for vmaster slave (%d!=%d)\n", |
2792 | - *step_to_check, step); | 2795 | - *step_to_check, step); |
2793 | return -1; | 2796 | return -1; |
2794 | } | 2797 | } |
@@ -2813,20 +2816,28 @@ static int put_kctl_with_value(struct snd_kcontrol *kctl, int val) | |||
2813 | } | 2816 | } |
2814 | 2817 | ||
2815 | /* initialize the slave volume with 0dB */ | 2818 | /* initialize the slave volume with 0dB */ |
2816 | static int init_slave_0dB(void *data, struct snd_kcontrol *slave) | 2819 | static int init_slave_0dB(struct hda_codec *codec, |
2820 | void *data, struct snd_kcontrol *slave) | ||
2817 | { | 2821 | { |
2818 | int offset = get_kctl_0dB_offset(slave, data); | 2822 | int offset = get_kctl_0dB_offset(codec, slave, data); |
2819 | if (offset > 0) | 2823 | if (offset > 0) |
2820 | put_kctl_with_value(slave, offset); | 2824 | put_kctl_with_value(slave, offset); |
2821 | return 0; | 2825 | return 0; |
2822 | } | 2826 | } |
2823 | 2827 | ||
2824 | /* unmute the slave */ | 2828 | /* unmute the slave */ |
2825 | static int init_slave_unmute(void *data, struct snd_kcontrol *slave) | 2829 | static int init_slave_unmute(struct hda_codec *codec, |
2830 | void *data, struct snd_kcontrol *slave) | ||
2826 | { | 2831 | { |
2827 | return put_kctl_with_value(slave, 1); | 2832 | return put_kctl_with_value(slave, 1); |
2828 | } | 2833 | } |
2829 | 2834 | ||
2835 | static int add_slave(struct hda_codec *codec, | ||
2836 | void *data, struct snd_kcontrol *slave) | ||
2837 | { | ||
2838 | return snd_ctl_add_slave(data, slave); | ||
2839 | } | ||
2840 | |||
2830 | /** | 2841 | /** |
2831 | * snd_hda_add_vmaster - create a virtual master control and add slaves | 2842 | * snd_hda_add_vmaster - create a virtual master control and add slaves |
2832 | * @codec: HD-audio codec | 2843 | * @codec: HD-audio codec |
@@ -2869,8 +2880,7 @@ int __snd_hda_add_vmaster(struct hda_codec *codec, char *name, | |||
2869 | if (err < 0) | 2880 | if (err < 0) |
2870 | return err; | 2881 | return err; |
2871 | 2882 | ||
2872 | err = map_slaves(codec, slaves, suffix, | 2883 | err = map_slaves(codec, slaves, suffix, add_slave, kctl); |
2873 | (map_slave_func_t)snd_ctl_add_slave, kctl); | ||
2874 | if (err < 0) | 2884 | if (err < 0) |
2875 | return err; | 2885 | return err; |
2876 | 2886 | ||
@@ -4280,6 +4290,7 @@ static struct hda_rate_tbl rate_bits[] = { | |||
4280 | 4290 | ||
4281 | /** | 4291 | /** |
4282 | * snd_hda_calc_stream_format - calculate format bitset | 4292 | * snd_hda_calc_stream_format - calculate format bitset |
4293 | * @codec: HD-audio codec | ||
4283 | * @rate: the sample rate | 4294 | * @rate: the sample rate |
4284 | * @channels: the number of channels | 4295 | * @channels: the number of channels |
4285 | * @format: the PCM format (SNDRV_PCM_FORMAT_XXX) | 4296 | * @format: the PCM format (SNDRV_PCM_FORMAT_XXX) |
@@ -4289,7 +4300,8 @@ static struct hda_rate_tbl rate_bits[] = { | |||
4289 | * | 4300 | * |
4290 | * Return zero if invalid. | 4301 | * Return zero if invalid. |
4291 | */ | 4302 | */ |
4292 | unsigned int snd_hda_calc_stream_format(unsigned int rate, | 4303 | unsigned int snd_hda_calc_stream_format(struct hda_codec *codec, |
4304 | unsigned int rate, | ||
4293 | unsigned int channels, | 4305 | unsigned int channels, |
4294 | unsigned int format, | 4306 | unsigned int format, |
4295 | unsigned int maxbps, | 4307 | unsigned int maxbps, |
@@ -4304,12 +4316,12 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate, | |||
4304 | break; | 4316 | break; |
4305 | } | 4317 | } |
4306 | if (!rate_bits[i].hz) { | 4318 | if (!rate_bits[i].hz) { |
4307 | snd_printdd("invalid rate %d\n", rate); | 4319 | codec_dbg(codec, "invalid rate %d\n", rate); |
4308 | return 0; | 4320 | return 0; |
4309 | } | 4321 | } |
4310 | 4322 | ||
4311 | if (channels == 0 || channels > 8) { | 4323 | if (channels == 0 || channels > 8) { |
4312 | snd_printdd("invalid channels %d\n", channels); | 4324 | codec_dbg(codec, "invalid channels %d\n", channels); |
4313 | return 0; | 4325 | return 0; |
4314 | } | 4326 | } |
4315 | val |= channels - 1; | 4327 | val |= channels - 1; |
@@ -4332,7 +4344,7 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate, | |||
4332 | val |= AC_FMT_BITS_20; | 4344 | val |= AC_FMT_BITS_20; |
4333 | break; | 4345 | break; |
4334 | default: | 4346 | default: |
4335 | snd_printdd("invalid format width %d\n", | 4347 | codec_dbg(codec, "invalid format width %d\n", |
4336 | snd_pcm_format_width(format)); | 4348 | snd_pcm_format_width(format)); |
4337 | return 0; | 4349 | return 0; |
4338 | } | 4350 | } |
@@ -5670,12 +5682,13 @@ EXPORT_SYMBOL_GPL(_snd_hda_set_pin_ctl); | |||
5670 | * suffix is appended to the label. This label index number is stored | 5682 | * suffix is appended to the label. This label index number is stored |
5671 | * to type_idx when non-NULL pointer is given. | 5683 | * to type_idx when non-NULL pointer is given. |
5672 | */ | 5684 | */ |
5673 | int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label, | 5685 | int snd_hda_add_imux_item(struct hda_codec *codec, |
5686 | struct hda_input_mux *imux, const char *label, | ||
5674 | int index, int *type_idx) | 5687 | int index, int *type_idx) |
5675 | { | 5688 | { |
5676 | int i, label_idx = 0; | 5689 | int i, label_idx = 0; |
5677 | if (imux->num_items >= HDA_MAX_NUM_INPUTS) { | 5690 | if (imux->num_items >= HDA_MAX_NUM_INPUTS) { |
5678 | snd_printd(KERN_ERR "hda_codec: Too many imux items!\n"); | 5691 | codec_err(codec, "hda_codec: Too many imux items!\n"); |
5679 | return -EINVAL; | 5692 | return -EINVAL; |
5680 | } | 5693 | } |
5681 | for (i = 0; i < imux->num_items; i++) { | 5694 | for (i = 0; i < imux->num_items; i++) { |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 5825aa17d8e3..bbc5a1392c75 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -402,7 +402,6 @@ struct hda_codec { | |||
402 | 402 | ||
403 | /* fix-up list */ | 403 | /* fix-up list */ |
404 | int fixup_id; | 404 | int fixup_id; |
405 | unsigned int fixup_forced:1; /* fixup explicitly set by user */ | ||
406 | const struct hda_fixup *fixup_list; | 405 | const struct hda_fixup *fixup_list; |
407 | const char *fixup_name; | 406 | const char *fixup_name; |
408 | 407 | ||
@@ -538,7 +537,8 @@ void __snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid, | |||
538 | int do_now); | 537 | int do_now); |
539 | #define snd_hda_codec_cleanup_stream(codec, nid) \ | 538 | #define snd_hda_codec_cleanup_stream(codec, nid) \ |
540 | __snd_hda_codec_cleanup_stream(codec, nid, 0) | 539 | __snd_hda_codec_cleanup_stream(codec, nid, 0) |
541 | unsigned int snd_hda_calc_stream_format(unsigned int rate, | 540 | unsigned int snd_hda_calc_stream_format(struct hda_codec *codec, |
541 | unsigned int rate, | ||
542 | unsigned int channels, | 542 | unsigned int channels, |
543 | unsigned int format, | 543 | unsigned int format, |
544 | unsigned int maxbps, | 544 | unsigned int maxbps, |
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 6df04d91c93c..8337645aa7a5 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/pm_runtime.h> | 28 | #include <linux/pm_runtime.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/reboot.h> | ||
30 | #include <sound/core.h> | 31 | #include <sound/core.h> |
31 | #include <sound/initval.h> | 32 | #include <sound/initval.h> |
32 | #include "hda_priv.h" | 33 | #include "hda_priv.h" |
@@ -152,11 +153,11 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) | |||
152 | upper_32_bits(azx_dev->bdl.addr)); | 153 | upper_32_bits(azx_dev->bdl.addr)); |
153 | 154 | ||
154 | /* enable the position buffer */ | 155 | /* enable the position buffer */ |
155 | if (chip->position_fix[0] != POS_FIX_LPIB || | 156 | if (chip->get_position[0] != azx_get_pos_lpib || |
156 | chip->position_fix[1] != POS_FIX_LPIB) { | 157 | chip->get_position[1] != azx_get_pos_lpib) { |
157 | if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) | 158 | if (!(azx_readl(chip, DPLBASE) & AZX_DPLBASE_ENABLE)) |
158 | azx_writel(chip, DPLBASE, | 159 | azx_writel(chip, DPLBASE, |
159 | (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE); | 160 | (u32)chip->posbuf.addr | AZX_DPLBASE_ENABLE); |
160 | } | 161 | } |
161 | 162 | ||
162 | /* set the interrupt enable bits in the descriptor control register */ | 163 | /* set the interrupt enable bits in the descriptor control register */ |
@@ -482,7 +483,8 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) | |||
482 | } | 483 | } |
483 | 484 | ||
484 | azx_stream_reset(chip, azx_dev); | 485 | azx_stream_reset(chip, azx_dev); |
485 | format_val = snd_hda_calc_stream_format(runtime->rate, | 486 | format_val = snd_hda_calc_stream_format(apcm->codec, |
487 | runtime->rate, | ||
486 | runtime->channels, | 488 | runtime->channels, |
487 | runtime->format, | 489 | runtime->format, |
488 | hinfo->maxbps, | 490 | hinfo->maxbps, |
@@ -673,125 +675,40 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
673 | return 0; | 675 | return 0; |
674 | } | 676 | } |
675 | 677 | ||
676 | /* get the current DMA position with correction on VIA chips */ | 678 | unsigned int azx_get_pos_lpib(struct azx *chip, struct azx_dev *azx_dev) |
677 | static unsigned int azx_via_get_position(struct azx *chip, | ||
678 | struct azx_dev *azx_dev) | ||
679 | { | 679 | { |
680 | unsigned int link_pos, mini_pos, bound_pos; | 680 | return azx_sd_readl(chip, azx_dev, SD_LPIB); |
681 | unsigned int mod_link_pos, mod_dma_pos, mod_mini_pos; | 681 | } |
682 | unsigned int fifo_size; | 682 | EXPORT_SYMBOL_GPL(azx_get_pos_lpib); |
683 | |||
684 | link_pos = azx_sd_readl(chip, azx_dev, SD_LPIB); | ||
685 | if (azx_dev->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
686 | /* Playback, no problem using link position */ | ||
687 | return link_pos; | ||
688 | } | ||
689 | |||
690 | /* Capture */ | ||
691 | /* For new chipset, | ||
692 | * use mod to get the DMA position just like old chipset | ||
693 | */ | ||
694 | mod_dma_pos = le32_to_cpu(*azx_dev->posbuf); | ||
695 | mod_dma_pos %= azx_dev->period_bytes; | ||
696 | |||
697 | /* azx_dev->fifo_size can't get FIFO size of in stream. | ||
698 | * Get from base address + offset. | ||
699 | */ | ||
700 | fifo_size = readw(chip->remap_addr + VIA_IN_STREAM0_FIFO_SIZE_OFFSET); | ||
701 | |||
702 | if (azx_dev->insufficient) { | ||
703 | /* Link position never gather than FIFO size */ | ||
704 | if (link_pos <= fifo_size) | ||
705 | return 0; | ||
706 | |||
707 | azx_dev->insufficient = 0; | ||
708 | } | ||
709 | |||
710 | if (link_pos <= fifo_size) | ||
711 | mini_pos = azx_dev->bufsize + link_pos - fifo_size; | ||
712 | else | ||
713 | mini_pos = link_pos - fifo_size; | ||
714 | |||
715 | /* Find nearest previous boudary */ | ||
716 | mod_mini_pos = mini_pos % azx_dev->period_bytes; | ||
717 | mod_link_pos = link_pos % azx_dev->period_bytes; | ||
718 | if (mod_link_pos >= fifo_size) | ||
719 | bound_pos = link_pos - mod_link_pos; | ||
720 | else if (mod_dma_pos >= mod_mini_pos) | ||
721 | bound_pos = mini_pos - mod_mini_pos; | ||
722 | else { | ||
723 | bound_pos = mini_pos - mod_mini_pos + azx_dev->period_bytes; | ||
724 | if (bound_pos >= azx_dev->bufsize) | ||
725 | bound_pos = 0; | ||
726 | } | ||
727 | 683 | ||
728 | /* Calculate real DMA position we want */ | 684 | unsigned int azx_get_pos_posbuf(struct azx *chip, struct azx_dev *azx_dev) |
729 | return bound_pos + mod_dma_pos; | 685 | { |
686 | return le32_to_cpu(*azx_dev->posbuf); | ||
730 | } | 687 | } |
688 | EXPORT_SYMBOL_GPL(azx_get_pos_posbuf); | ||
731 | 689 | ||
732 | unsigned int azx_get_position(struct azx *chip, | 690 | unsigned int azx_get_position(struct azx *chip, |
733 | struct azx_dev *azx_dev, | 691 | struct azx_dev *azx_dev) |
734 | bool with_check) | ||
735 | { | 692 | { |
736 | struct snd_pcm_substream *substream = azx_dev->substream; | 693 | struct snd_pcm_substream *substream = azx_dev->substream; |
737 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); | ||
738 | unsigned int pos; | 694 | unsigned int pos; |
739 | int stream = substream->stream; | 695 | int stream = substream->stream; |
740 | struct hda_pcm_stream *hinfo = apcm->hinfo[stream]; | ||
741 | int delay = 0; | 696 | int delay = 0; |
742 | 697 | ||
743 | switch (chip->position_fix[stream]) { | 698 | if (chip->get_position[stream]) |
744 | case POS_FIX_LPIB: | 699 | pos = chip->get_position[stream](chip, azx_dev); |
745 | /* read LPIB */ | 700 | else /* use the position buffer as default */ |
746 | pos = azx_sd_readl(chip, azx_dev, SD_LPIB); | 701 | pos = azx_get_pos_posbuf(chip, azx_dev); |
747 | break; | ||
748 | case POS_FIX_VIACOMBO: | ||
749 | pos = azx_via_get_position(chip, azx_dev); | ||
750 | break; | ||
751 | default: | ||
752 | /* use the position buffer */ | ||
753 | pos = le32_to_cpu(*azx_dev->posbuf); | ||
754 | if (with_check && chip->position_fix[stream] == POS_FIX_AUTO) { | ||
755 | if (!pos || pos == (u32)-1) { | ||
756 | dev_info(chip->card->dev, | ||
757 | "Invalid position buffer, using LPIB read method instead.\n"); | ||
758 | chip->position_fix[stream] = POS_FIX_LPIB; | ||
759 | pos = azx_sd_readl(chip, azx_dev, SD_LPIB); | ||
760 | } else | ||
761 | chip->position_fix[stream] = POS_FIX_POSBUF; | ||
762 | } | ||
763 | break; | ||
764 | } | ||
765 | 702 | ||
766 | if (pos >= azx_dev->bufsize) | 703 | if (pos >= azx_dev->bufsize) |
767 | pos = 0; | 704 | pos = 0; |
768 | 705 | ||
769 | /* calculate runtime delay from LPIB */ | ||
770 | if (substream->runtime && | ||
771 | chip->position_fix[stream] == POS_FIX_POSBUF && | ||
772 | (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) { | ||
773 | unsigned int lpib_pos = azx_sd_readl(chip, azx_dev, SD_LPIB); | ||
774 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
775 | delay = pos - lpib_pos; | ||
776 | else | ||
777 | delay = lpib_pos - pos; | ||
778 | if (delay < 0) { | ||
779 | if (delay >= azx_dev->delay_negative_threshold) | ||
780 | delay = 0; | ||
781 | else | ||
782 | delay += azx_dev->bufsize; | ||
783 | } | ||
784 | if (delay >= azx_dev->period_bytes) { | ||
785 | dev_info(chip->card->dev, | ||
786 | "Unstable LPIB (%d >= %d); disabling LPIB delay counting\n", | ||
787 | delay, azx_dev->period_bytes); | ||
788 | delay = 0; | ||
789 | chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY; | ||
790 | } | ||
791 | delay = bytes_to_frames(substream->runtime, delay); | ||
792 | } | ||
793 | |||
794 | if (substream->runtime) { | 706 | if (substream->runtime) { |
707 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); | ||
708 | struct hda_pcm_stream *hinfo = apcm->hinfo[stream]; | ||
709 | |||
710 | if (chip->get_delay[stream]) | ||
711 | delay += chip->get_delay[stream](chip, azx_dev, pos); | ||
795 | if (hinfo->ops.get_delay) | 712 | if (hinfo->ops.get_delay) |
796 | delay += hinfo->ops.get_delay(hinfo, apcm->codec, | 713 | delay += hinfo->ops.get_delay(hinfo, apcm->codec, |
797 | substream); | 714 | substream); |
@@ -809,7 +726,7 @@ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream) | |||
809 | struct azx *chip = apcm->chip; | 726 | struct azx *chip = apcm->chip; |
810 | struct azx_dev *azx_dev = get_azx_dev(substream); | 727 | struct azx_dev *azx_dev = get_azx_dev(substream); |
811 | return bytes_to_frames(substream->runtime, | 728 | return bytes_to_frames(substream->runtime, |
812 | azx_get_position(chip, azx_dev, false)); | 729 | azx_get_position(chip, azx_dev)); |
813 | } | 730 | } |
814 | 731 | ||
815 | static int azx_get_wallclock_tstamp(struct snd_pcm_substream *substream, | 732 | static int azx_get_wallclock_tstamp(struct snd_pcm_substream *substream, |
@@ -1059,10 +976,10 @@ static void azx_init_cmd_io(struct azx *chip) | |||
1059 | azx_writew(chip, CORBWP, 0); | 976 | azx_writew(chip, CORBWP, 0); |
1060 | 977 | ||
1061 | /* reset the corb hw read pointer */ | 978 | /* reset the corb hw read pointer */ |
1062 | azx_writew(chip, CORBRP, ICH6_CORBRP_RST); | 979 | azx_writew(chip, CORBRP, AZX_CORBRP_RST); |
1063 | if (!(chip->driver_caps & AZX_DCAPS_CORBRP_SELF_CLEAR)) { | 980 | if (!(chip->driver_caps & AZX_DCAPS_CORBRP_SELF_CLEAR)) { |
1064 | for (timeout = 1000; timeout > 0; timeout--) { | 981 | for (timeout = 1000; timeout > 0; timeout--) { |
1065 | if ((azx_readw(chip, CORBRP) & ICH6_CORBRP_RST) == ICH6_CORBRP_RST) | 982 | if ((azx_readw(chip, CORBRP) & AZX_CORBRP_RST) == AZX_CORBRP_RST) |
1066 | break; | 983 | break; |
1067 | udelay(1); | 984 | udelay(1); |
1068 | } | 985 | } |
@@ -1082,7 +999,7 @@ static void azx_init_cmd_io(struct azx *chip) | |||
1082 | } | 999 | } |
1083 | 1000 | ||
1084 | /* enable corb dma */ | 1001 | /* enable corb dma */ |
1085 | azx_writeb(chip, CORBCTL, ICH6_CORBCTL_RUN); | 1002 | azx_writeb(chip, CORBCTL, AZX_CORBCTL_RUN); |
1086 | 1003 | ||
1087 | /* RIRB set up */ | 1004 | /* RIRB set up */ |
1088 | chip->rirb.addr = chip->rb.addr + 2048; | 1005 | chip->rirb.addr = chip->rb.addr + 2048; |
@@ -1095,14 +1012,14 @@ static void azx_init_cmd_io(struct azx *chip) | |||
1095 | /* set the rirb size to 256 entries (ULI requires explicitly) */ | 1012 | /* set the rirb size to 256 entries (ULI requires explicitly) */ |
1096 | azx_writeb(chip, RIRBSIZE, 0x02); | 1013 | azx_writeb(chip, RIRBSIZE, 0x02); |
1097 | /* reset the rirb hw write pointer */ | 1014 | /* reset the rirb hw write pointer */ |
1098 | azx_writew(chip, RIRBWP, ICH6_RIRBWP_RST); | 1015 | azx_writew(chip, RIRBWP, AZX_RIRBWP_RST); |
1099 | /* set N=1, get RIRB response interrupt for new entry */ | 1016 | /* set N=1, get RIRB response interrupt for new entry */ |
1100 | if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) | 1017 | if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) |
1101 | azx_writew(chip, RINTCNT, 0xc0); | 1018 | azx_writew(chip, RINTCNT, 0xc0); |
1102 | else | 1019 | else |
1103 | azx_writew(chip, RINTCNT, 1); | 1020 | azx_writew(chip, RINTCNT, 1); |
1104 | /* enable rirb dma and response irq */ | 1021 | /* enable rirb dma and response irq */ |
1105 | azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN); | 1022 | azx_writeb(chip, RIRBCTL, AZX_RBCTL_DMA_EN | AZX_RBCTL_IRQ_EN); |
1106 | spin_unlock_irq(&chip->reg_lock); | 1023 | spin_unlock_irq(&chip->reg_lock); |
1107 | } | 1024 | } |
1108 | EXPORT_SYMBOL_GPL(azx_init_cmd_io); | 1025 | EXPORT_SYMBOL_GPL(azx_init_cmd_io); |
@@ -1146,7 +1063,7 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val) | |||
1146 | return -EIO; | 1063 | return -EIO; |
1147 | } | 1064 | } |
1148 | wp++; | 1065 | wp++; |
1149 | wp %= ICH6_MAX_CORB_ENTRIES; | 1066 | wp %= AZX_MAX_CORB_ENTRIES; |
1150 | 1067 | ||
1151 | rp = azx_readw(chip, CORBRP); | 1068 | rp = azx_readw(chip, CORBRP); |
1152 | if (wp == rp) { | 1069 | if (wp == rp) { |
@@ -1164,7 +1081,7 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val) | |||
1164 | return 0; | 1081 | return 0; |
1165 | } | 1082 | } |
1166 | 1083 | ||
1167 | #define ICH6_RIRB_EX_UNSOL_EV (1<<4) | 1084 | #define AZX_RIRB_EX_UNSOL_EV (1<<4) |
1168 | 1085 | ||
1169 | /* retrieve RIRB entry - called from interrupt handler */ | 1086 | /* retrieve RIRB entry - called from interrupt handler */ |
1170 | static void azx_update_rirb(struct azx *chip) | 1087 | static void azx_update_rirb(struct azx *chip) |
@@ -1185,7 +1102,7 @@ static void azx_update_rirb(struct azx *chip) | |||
1185 | 1102 | ||
1186 | while (chip->rirb.rp != wp) { | 1103 | while (chip->rirb.rp != wp) { |
1187 | chip->rirb.rp++; | 1104 | chip->rirb.rp++; |
1188 | chip->rirb.rp %= ICH6_MAX_RIRB_ENTRIES; | 1105 | chip->rirb.rp %= AZX_MAX_RIRB_ENTRIES; |
1189 | 1106 | ||
1190 | rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */ | 1107 | rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */ |
1191 | res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]); | 1108 | res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]); |
@@ -1196,8 +1113,7 @@ static void azx_update_rirb(struct azx *chip) | |||
1196 | res, res_ex, | 1113 | res, res_ex, |
1197 | chip->rirb.rp, wp); | 1114 | chip->rirb.rp, wp); |
1198 | snd_BUG(); | 1115 | snd_BUG(); |
1199 | } | 1116 | } else if (res_ex & AZX_RIRB_EX_UNSOL_EV) |
1200 | else if (res_ex & ICH6_RIRB_EX_UNSOL_EV) | ||
1201 | snd_hda_queue_unsol_event(chip->bus, res, res_ex); | 1117 | snd_hda_queue_unsol_event(chip->bus, res, res_ex); |
1202 | else if (chip->rirb.cmds[addr]) { | 1118 | else if (chip->rirb.cmds[addr]) { |
1203 | chip->rirb.res[addr] = res; | 1119 | chip->rirb.res[addr] = res; |
@@ -1305,7 +1221,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus, | |||
1305 | /* release CORB/RIRB */ | 1221 | /* release CORB/RIRB */ |
1306 | azx_free_cmd_io(chip); | 1222 | azx_free_cmd_io(chip); |
1307 | /* disable unsolicited responses */ | 1223 | /* disable unsolicited responses */ |
1308 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_UNSOL); | 1224 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~AZX_GCTL_UNSOL); |
1309 | return -1; | 1225 | return -1; |
1310 | } | 1226 | } |
1311 | 1227 | ||
@@ -1326,7 +1242,7 @@ static int azx_single_wait_for_response(struct azx *chip, unsigned int addr) | |||
1326 | 1242 | ||
1327 | while (timeout--) { | 1243 | while (timeout--) { |
1328 | /* check IRV busy bit */ | 1244 | /* check IRV busy bit */ |
1329 | if (azx_readw(chip, IRS) & ICH6_IRS_VALID) { | 1245 | if (azx_readw(chip, IRS) & AZX_IRS_VALID) { |
1330 | /* reuse rirb.res as the response return value */ | 1246 | /* reuse rirb.res as the response return value */ |
1331 | chip->rirb.res[addr] = azx_readl(chip, IR); | 1247 | chip->rirb.res[addr] = azx_readl(chip, IR); |
1332 | return 0; | 1248 | return 0; |
@@ -1350,13 +1266,13 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val) | |||
1350 | bus->rirb_error = 0; | 1266 | bus->rirb_error = 0; |
1351 | while (timeout--) { | 1267 | while (timeout--) { |
1352 | /* check ICB busy bit */ | 1268 | /* check ICB busy bit */ |
1353 | if (!((azx_readw(chip, IRS) & ICH6_IRS_BUSY))) { | 1269 | if (!((azx_readw(chip, IRS) & AZX_IRS_BUSY))) { |
1354 | /* Clear IRV valid bit */ | 1270 | /* Clear IRV valid bit */ |
1355 | azx_writew(chip, IRS, azx_readw(chip, IRS) | | 1271 | azx_writew(chip, IRS, azx_readw(chip, IRS) | |
1356 | ICH6_IRS_VALID); | 1272 | AZX_IRS_VALID); |
1357 | azx_writel(chip, IC, val); | 1273 | azx_writel(chip, IC, val); |
1358 | azx_writew(chip, IRS, azx_readw(chip, IRS) | | 1274 | azx_writew(chip, IRS, azx_readw(chip, IRS) | |
1359 | ICH6_IRS_BUSY); | 1275 | AZX_IRS_BUSY); |
1360 | return azx_single_wait_for_response(chip, addr); | 1276 | return azx_single_wait_for_response(chip, addr); |
1361 | } | 1277 | } |
1362 | udelay(1); | 1278 | udelay(1); |
@@ -1585,10 +1501,10 @@ void azx_enter_link_reset(struct azx *chip) | |||
1585 | unsigned long timeout; | 1501 | unsigned long timeout; |
1586 | 1502 | ||
1587 | /* reset controller */ | 1503 | /* reset controller */ |
1588 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_RESET); | 1504 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~AZX_GCTL_RESET); |
1589 | 1505 | ||
1590 | timeout = jiffies + msecs_to_jiffies(100); | 1506 | timeout = jiffies + msecs_to_jiffies(100); |
1591 | while ((azx_readb(chip, GCTL) & ICH6_GCTL_RESET) && | 1507 | while ((azx_readb(chip, GCTL) & AZX_GCTL_RESET) && |
1592 | time_before(jiffies, timeout)) | 1508 | time_before(jiffies, timeout)) |
1593 | usleep_range(500, 1000); | 1509 | usleep_range(500, 1000); |
1594 | } | 1510 | } |
@@ -1599,7 +1515,7 @@ static void azx_exit_link_reset(struct azx *chip) | |||
1599 | { | 1515 | { |
1600 | unsigned long timeout; | 1516 | unsigned long timeout; |
1601 | 1517 | ||
1602 | azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | ICH6_GCTL_RESET); | 1518 | azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | AZX_GCTL_RESET); |
1603 | 1519 | ||
1604 | timeout = jiffies + msecs_to_jiffies(100); | 1520 | timeout = jiffies + msecs_to_jiffies(100); |
1605 | while (!azx_readb(chip, GCTL) && | 1521 | while (!azx_readb(chip, GCTL) && |
@@ -1640,7 +1556,7 @@ static int azx_reset(struct azx *chip, bool full_reset) | |||
1640 | /* Accept unsolicited responses */ | 1556 | /* Accept unsolicited responses */ |
1641 | if (!chip->single_cmd) | 1557 | if (!chip->single_cmd) |
1642 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) | | 1558 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) | |
1643 | ICH6_GCTL_UNSOL); | 1559 | AZX_GCTL_UNSOL); |
1644 | 1560 | ||
1645 | /* detect codecs */ | 1561 | /* detect codecs */ |
1646 | if (!chip->codec_mask) { | 1562 | if (!chip->codec_mask) { |
@@ -1657,7 +1573,7 @@ static void azx_int_enable(struct azx *chip) | |||
1657 | { | 1573 | { |
1658 | /* enable controller CIE and GIE */ | 1574 | /* enable controller CIE and GIE */ |
1659 | azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) | | 1575 | azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) | |
1660 | ICH6_INT_CTRL_EN | ICH6_INT_GLOBAL_EN); | 1576 | AZX_INT_CTRL_EN | AZX_INT_GLOBAL_EN); |
1661 | } | 1577 | } |
1662 | 1578 | ||
1663 | /* disable interrupts */ | 1579 | /* disable interrupts */ |
@@ -1678,7 +1594,7 @@ static void azx_int_disable(struct azx *chip) | |||
1678 | 1594 | ||
1679 | /* disable controller CIE and GIE */ | 1595 | /* disable controller CIE and GIE */ |
1680 | azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) & | 1596 | azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) & |
1681 | ~(ICH6_INT_CTRL_EN | ICH6_INT_GLOBAL_EN)); | 1597 | ~(AZX_INT_CTRL_EN | AZX_INT_GLOBAL_EN)); |
1682 | } | 1598 | } |
1683 | 1599 | ||
1684 | /* clear interrupts */ | 1600 | /* clear interrupts */ |
@@ -1699,7 +1615,7 @@ static void azx_int_clear(struct azx *chip) | |||
1699 | azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); | 1615 | azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); |
1700 | 1616 | ||
1701 | /* clear int status */ | 1617 | /* clear int status */ |
1702 | azx_writel(chip, INTSTS, ICH6_INT_CTRL_EN | ICH6_INT_ALL_STREAM); | 1618 | azx_writel(chip, INTSTS, AZX_INT_CTRL_EN | AZX_INT_ALL_STREAM); |
1703 | } | 1619 | } |
1704 | 1620 | ||
1705 | /* | 1621 | /* |
@@ -2031,5 +1947,30 @@ int azx_init_stream(struct azx *chip) | |||
2031 | } | 1947 | } |
2032 | EXPORT_SYMBOL_GPL(azx_init_stream); | 1948 | EXPORT_SYMBOL_GPL(azx_init_stream); |
2033 | 1949 | ||
1950 | /* | ||
1951 | * reboot notifier for hang-up problem at power-down | ||
1952 | */ | ||
1953 | static int azx_halt(struct notifier_block *nb, unsigned long event, void *buf) | ||
1954 | { | ||
1955 | struct azx *chip = container_of(nb, struct azx, reboot_notifier); | ||
1956 | snd_hda_bus_reboot_notify(chip->bus); | ||
1957 | azx_stop_chip(chip); | ||
1958 | return NOTIFY_OK; | ||
1959 | } | ||
1960 | |||
1961 | void azx_notifier_register(struct azx *chip) | ||
1962 | { | ||
1963 | chip->reboot_notifier.notifier_call = azx_halt; | ||
1964 | register_reboot_notifier(&chip->reboot_notifier); | ||
1965 | } | ||
1966 | EXPORT_SYMBOL_GPL(azx_notifier_register); | ||
1967 | |||
1968 | void azx_notifier_unregister(struct azx *chip) | ||
1969 | { | ||
1970 | if (chip->reboot_notifier.notifier_call) | ||
1971 | unregister_reboot_notifier(&chip->reboot_notifier); | ||
1972 | } | ||
1973 | EXPORT_SYMBOL_GPL(azx_notifier_unregister); | ||
1974 | |||
2034 | MODULE_LICENSE("GPL"); | 1975 | MODULE_LICENSE("GPL"); |
2035 | MODULE_DESCRIPTION("Common HDA driver funcitons"); | 1976 | MODULE_DESCRIPTION("Common HDA driver funcitons"); |
diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h index baf0e77330af..c90d10fd4d8f 100644 --- a/sound/pci/hda/hda_controller.h +++ b/sound/pci/hda/hda_controller.h | |||
@@ -25,9 +25,9 @@ static inline struct azx_dev *get_azx_dev(struct snd_pcm_substream *substream) | |||
25 | { | 25 | { |
26 | return substream->runtime->private_data; | 26 | return substream->runtime->private_data; |
27 | } | 27 | } |
28 | unsigned int azx_get_position(struct azx *chip, | 28 | unsigned int azx_get_position(struct azx *chip, struct azx_dev *azx_dev); |
29 | struct azx_dev *azx_dev, | 29 | unsigned int azx_get_pos_lpib(struct azx *chip, struct azx_dev *azx_dev); |
30 | bool with_check); | 30 | unsigned int azx_get_pos_posbuf(struct azx *chip, struct azx_dev *azx_dev); |
31 | 31 | ||
32 | /* Stream control. */ | 32 | /* Stream control. */ |
33 | void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev); | 33 | void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev); |
@@ -50,4 +50,7 @@ int azx_codec_configure(struct azx *chip); | |||
50 | int azx_mixer_create(struct azx *chip); | 50 | int azx_mixer_create(struct azx *chip); |
51 | int azx_init_stream(struct azx *chip); | 51 | int azx_init_stream(struct azx *chip); |
52 | 52 | ||
53 | void azx_notifier_register(struct azx *chip); | ||
54 | void azx_notifier_unregister(struct azx *chip); | ||
55 | |||
53 | #endif /* __SOUND_HDA_CONTROLLER_H */ | 56 | #endif /* __SOUND_HDA_CONTROLLER_H */ |
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index 46690a7f48f6..e1cd34d9011d 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c | |||
@@ -167,7 +167,8 @@ static unsigned int hdmi_get_eld_data(struct hda_codec *codec, hda_nid_t nid, | |||
167 | (buf[byte] >> (lowbit)) & ((1 << (bits)) - 1); \ | 167 | (buf[byte] >> (lowbit)) & ((1 << (bits)) - 1); \ |
168 | }) | 168 | }) |
169 | 169 | ||
170 | static void hdmi_update_short_audio_desc(struct cea_sad *a, | 170 | static void hdmi_update_short_audio_desc(struct hda_codec *codec, |
171 | struct cea_sad *a, | ||
171 | const unsigned char *buf) | 172 | const unsigned char *buf) |
172 | { | 173 | { |
173 | int i; | 174 | int i; |
@@ -188,8 +189,7 @@ static void hdmi_update_short_audio_desc(struct cea_sad *a, | |||
188 | a->format = GRAB_BITS(buf, 0, 3, 4); | 189 | a->format = GRAB_BITS(buf, 0, 3, 4); |
189 | switch (a->format) { | 190 | switch (a->format) { |
190 | case AUDIO_CODING_TYPE_REF_STREAM_HEADER: | 191 | case AUDIO_CODING_TYPE_REF_STREAM_HEADER: |
191 | snd_printd(KERN_INFO | 192 | codec_info(codec, "HDMI: audio coding type 0 not expected\n"); |
192 | "HDMI: audio coding type 0 not expected\n"); | ||
193 | break; | 193 | break; |
194 | 194 | ||
195 | case AUDIO_CODING_TYPE_LPCM: | 195 | case AUDIO_CODING_TYPE_LPCM: |
@@ -233,9 +233,9 @@ static void hdmi_update_short_audio_desc(struct cea_sad *a, | |||
233 | a->format = GRAB_BITS(buf, 2, 3, 5); | 233 | a->format = GRAB_BITS(buf, 2, 3, 5); |
234 | if (a->format == AUDIO_CODING_XTYPE_HE_REF_CT || | 234 | if (a->format == AUDIO_CODING_XTYPE_HE_REF_CT || |
235 | a->format >= AUDIO_CODING_XTYPE_FIRST_RESERVED) { | 235 | a->format >= AUDIO_CODING_XTYPE_FIRST_RESERVED) { |
236 | snd_printd(KERN_INFO | 236 | codec_info(codec, |
237 | "HDMI: audio coding xtype %d not expected\n", | 237 | "HDMI: audio coding xtype %d not expected\n", |
238 | a->format); | 238 | a->format); |
239 | a->format = 0; | 239 | a->format = 0; |
240 | } else | 240 | } else |
241 | a->format += AUDIO_CODING_TYPE_HE_AAC - | 241 | a->format += AUDIO_CODING_TYPE_HE_AAC - |
@@ -247,7 +247,7 @@ static void hdmi_update_short_audio_desc(struct cea_sad *a, | |||
247 | /* | 247 | /* |
248 | * Be careful, ELD buf could be totally rubbish! | 248 | * Be careful, ELD buf could be totally rubbish! |
249 | */ | 249 | */ |
250 | int snd_hdmi_parse_eld(struct parsed_hdmi_eld *e, | 250 | int snd_hdmi_parse_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e, |
251 | const unsigned char *buf, int size) | 251 | const unsigned char *buf, int size) |
252 | { | 252 | { |
253 | int mnl; | 253 | int mnl; |
@@ -256,8 +256,7 @@ int snd_hdmi_parse_eld(struct parsed_hdmi_eld *e, | |||
256 | e->eld_ver = GRAB_BITS(buf, 0, 3, 5); | 256 | e->eld_ver = GRAB_BITS(buf, 0, 3, 5); |
257 | if (e->eld_ver != ELD_VER_CEA_861D && | 257 | if (e->eld_ver != ELD_VER_CEA_861D && |
258 | e->eld_ver != ELD_VER_PARTIAL) { | 258 | e->eld_ver != ELD_VER_PARTIAL) { |
259 | snd_printd(KERN_INFO "HDMI: Unknown ELD version %d\n", | 259 | codec_info(codec, "HDMI: Unknown ELD version %d\n", e->eld_ver); |
260 | e->eld_ver); | ||
261 | goto out_fail; | 260 | goto out_fail; |
262 | } | 261 | } |
263 | 262 | ||
@@ -280,20 +279,20 @@ int snd_hdmi_parse_eld(struct parsed_hdmi_eld *e, | |||
280 | e->product_id = get_unaligned_le16(buf + 18); | 279 | e->product_id = get_unaligned_le16(buf + 18); |
281 | 280 | ||
282 | if (mnl > ELD_MAX_MNL) { | 281 | if (mnl > ELD_MAX_MNL) { |
283 | snd_printd(KERN_INFO "HDMI: MNL is reserved value %d\n", mnl); | 282 | codec_info(codec, "HDMI: MNL is reserved value %d\n", mnl); |
284 | goto out_fail; | 283 | goto out_fail; |
285 | } else if (ELD_FIXED_BYTES + mnl > size) { | 284 | } else if (ELD_FIXED_BYTES + mnl > size) { |
286 | snd_printd(KERN_INFO "HDMI: out of range MNL %d\n", mnl); | 285 | codec_info(codec, "HDMI: out of range MNL %d\n", mnl); |
287 | goto out_fail; | 286 | goto out_fail; |
288 | } else | 287 | } else |
289 | strlcpy(e->monitor_name, buf + ELD_FIXED_BYTES, mnl + 1); | 288 | strlcpy(e->monitor_name, buf + ELD_FIXED_BYTES, mnl + 1); |
290 | 289 | ||
291 | for (i = 0; i < e->sad_count; i++) { | 290 | for (i = 0; i < e->sad_count; i++) { |
292 | if (ELD_FIXED_BYTES + mnl + 3 * (i + 1) > size) { | 291 | if (ELD_FIXED_BYTES + mnl + 3 * (i + 1) > size) { |
293 | snd_printd(KERN_INFO "HDMI: out of range SAD %d\n", i); | 292 | codec_info(codec, "HDMI: out of range SAD %d\n", i); |
294 | goto out_fail; | 293 | goto out_fail; |
295 | } | 294 | } |
296 | hdmi_update_short_audio_desc(e->sad + i, | 295 | hdmi_update_short_audio_desc(codec, e->sad + i, |
297 | buf + ELD_FIXED_BYTES + mnl + 3 * i); | 296 | buf + ELD_FIXED_BYTES + mnl + 3 * i); |
298 | } | 297 | } |
299 | 298 | ||
@@ -394,7 +393,8 @@ static void hdmi_print_pcm_rates(int pcm, char *buf, int buflen) | |||
394 | 393 | ||
395 | #define SND_PRINT_RATES_ADVISED_BUFSIZE 80 | 394 | #define SND_PRINT_RATES_ADVISED_BUFSIZE 80 |
396 | 395 | ||
397 | static void hdmi_show_short_audio_desc(struct cea_sad *a) | 396 | static void hdmi_show_short_audio_desc(struct hda_codec *codec, |
397 | struct cea_sad *a) | ||
398 | { | 398 | { |
399 | char buf[SND_PRINT_RATES_ADVISED_BUFSIZE]; | 399 | char buf[SND_PRINT_RATES_ADVISED_BUFSIZE]; |
400 | char buf2[8 + SND_PRINT_BITS_ADVISED_BUFSIZE] = ", bits ="; | 400 | char buf2[8 + SND_PRINT_BITS_ADVISED_BUFSIZE] = ", bits ="; |
@@ -412,12 +412,10 @@ static void hdmi_show_short_audio_desc(struct cea_sad *a) | |||
412 | else | 412 | else |
413 | buf2[0] = '\0'; | 413 | buf2[0] = '\0'; |
414 | 414 | ||
415 | _snd_printd(SND_PR_VERBOSE, "HDMI: supports coding type %s:" | 415 | codec_dbg(codec, |
416 | " channels = %d, rates =%s%s\n", | 416 | "HDMI: supports coding type %s: channels = %d, rates =%s%s\n", |
417 | cea_audio_coding_type_names[a->format], | 417 | cea_audio_coding_type_names[a->format], |
418 | a->channels, | 418 | a->channels, buf, buf2); |
419 | buf, | ||
420 | buf2); | ||
421 | } | 419 | } |
422 | 420 | ||
423 | void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen) | 421 | void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen) |
@@ -432,22 +430,22 @@ void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen) | |||
432 | buf[j] = '\0'; /* necessary when j == 0 */ | 430 | buf[j] = '\0'; /* necessary when j == 0 */ |
433 | } | 431 | } |
434 | 432 | ||
435 | void snd_hdmi_show_eld(struct parsed_hdmi_eld *e) | 433 | void snd_hdmi_show_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e) |
436 | { | 434 | { |
437 | int i; | 435 | int i; |
438 | 436 | ||
439 | _snd_printd(SND_PR_VERBOSE, "HDMI: detected monitor %s at connection type %s\n", | 437 | codec_dbg(codec, "HDMI: detected monitor %s at connection type %s\n", |
440 | e->monitor_name, | 438 | e->monitor_name, |
441 | eld_connection_type_names[e->conn_type]); | 439 | eld_connection_type_names[e->conn_type]); |
442 | 440 | ||
443 | if (e->spk_alloc) { | 441 | if (e->spk_alloc) { |
444 | char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; | 442 | char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; |
445 | snd_print_channel_allocation(e->spk_alloc, buf, sizeof(buf)); | 443 | snd_print_channel_allocation(e->spk_alloc, buf, sizeof(buf)); |
446 | _snd_printd(SND_PR_VERBOSE, "HDMI: available speakers:%s\n", buf); | 444 | codec_dbg(codec, "HDMI: available speakers:%s\n", buf); |
447 | } | 445 | } |
448 | 446 | ||
449 | for (i = 0; i < e->sad_count; i++) | 447 | for (i = 0; i < e->sad_count; i++) |
450 | hdmi_show_short_audio_desc(e->sad + i); | 448 | hdmi_show_short_audio_desc(codec, e->sad + i); |
451 | } | 449 | } |
452 | 450 | ||
453 | #ifdef CONFIG_PROC_FS | 451 | #ifdef CONFIG_PROC_FS |
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 589e47c5aeb3..b956449ddada 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -350,16 +350,16 @@ static void print_nid_path(struct hda_codec *codec, | |||
350 | const char *pfx, struct nid_path *path) | 350 | const char *pfx, struct nid_path *path) |
351 | { | 351 | { |
352 | char buf[40]; | 352 | char buf[40]; |
353 | char *pos = buf; | ||
353 | int i; | 354 | int i; |
354 | 355 | ||
356 | *pos = 0; | ||
357 | for (i = 0; i < path->depth; i++) | ||
358 | pos += scnprintf(pos, sizeof(buf) - (pos - buf), "%s%02x", | ||
359 | pos != buf ? ":" : "", | ||
360 | path->path[i]); | ||
355 | 361 | ||
356 | buf[0] = 0; | 362 | codec_dbg(codec, "%s path: depth=%d '%s'\n", pfx, path->depth, buf); |
357 | for (i = 0; i < path->depth; i++) { | ||
358 | char tmp[4]; | ||
359 | sprintf(tmp, ":%02x", path->path[i]); | ||
360 | strlcat(buf, tmp, sizeof(buf)); | ||
361 | } | ||
362 | codec_dbg(codec, "%s path: depth=%d %s\n", pfx, path->depth, buf); | ||
363 | } | 363 | } |
364 | 364 | ||
365 | /* called recursively */ | 365 | /* called recursively */ |
@@ -1700,9 +1700,11 @@ static int fill_and_eval_dacs(struct hda_codec *codec, | |||
1700 | #define DEBUG_BADNESS | 1700 | #define DEBUG_BADNESS |
1701 | 1701 | ||
1702 | #ifdef DEBUG_BADNESS | 1702 | #ifdef DEBUG_BADNESS |
1703 | #define debug_badness(fmt, args...) codec_dbg(codec, fmt, ##args) | 1703 | #define debug_badness(fmt, ...) \ |
1704 | codec_dbg(codec, fmt, ##__VA_ARGS__) | ||
1704 | #else | 1705 | #else |
1705 | #define debug_badness(...) | 1706 | #define debug_badness(fmt, ...) \ |
1707 | do { if (0) codec_dbg(codec, fmt, ##__VA_ARGS__); } while (0) | ||
1706 | #endif | 1708 | #endif |
1707 | 1709 | ||
1708 | #ifdef DEBUG_BADNESS | 1710 | #ifdef DEBUG_BADNESS |
@@ -3054,7 +3056,7 @@ static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin, | |||
3054 | if (spec->hp_mic_pin == pin) | 3056 | if (spec->hp_mic_pin == pin) |
3055 | spec->hp_mic_mux_idx = imux->num_items; | 3057 | spec->hp_mic_mux_idx = imux->num_items; |
3056 | spec->imux_pins[imux->num_items] = pin; | 3058 | spec->imux_pins[imux->num_items] = pin; |
3057 | snd_hda_add_imux_item(imux, label, cfg_idx, NULL); | 3059 | snd_hda_add_imux_item(codec, imux, label, cfg_idx, NULL); |
3058 | imux_added = true; | 3060 | imux_added = true; |
3059 | if (spec->dyn_adc_switch) | 3061 | if (spec->dyn_adc_switch) |
3060 | spec->dyn_adc_idx[imux_idx] = c; | 3062 | spec->dyn_adc_idx[imux_idx] = c; |
diff --git a/sound/pci/hda/hda_i915.c b/sound/pci/hda/hda_i915.c index 8b4940ba33d6..d4d0375ac181 100644 --- a/sound/pci/hda/hda_i915.c +++ b/sound/pci/hda/hda_i915.c | |||
@@ -28,8 +28,8 @@ | |||
28 | * Clock) to 24MHz BCLK: BCLK = CDCLK * M / N | 28 | * Clock) to 24MHz BCLK: BCLK = CDCLK * M / N |
29 | * The values will be lost when the display power well is disabled. | 29 | * The values will be lost when the display power well is disabled. |
30 | */ | 30 | */ |
31 | #define ICH6_REG_EM4 0x100c | 31 | #define AZX_REG_EM4 0x100c |
32 | #define ICH6_REG_EM5 0x1010 | 32 | #define AZX_REG_EM5 0x1010 |
33 | 33 | ||
34 | static int (*get_power)(void); | 34 | static int (*get_power)(void); |
35 | static int (*put_power)(void); | 35 | static int (*put_power)(void); |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 83cd19017cf3..387fc73a5c89 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -44,7 +44,6 @@ | |||
44 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
45 | #include <linux/pci.h> | 45 | #include <linux/pci.h> |
46 | #include <linux/mutex.h> | 46 | #include <linux/mutex.h> |
47 | #include <linux/reboot.h> | ||
48 | #include <linux/io.h> | 47 | #include <linux/io.h> |
49 | #include <linux/pm_runtime.h> | 48 | #include <linux/pm_runtime.h> |
50 | #include <linux/clocksource.h> | 49 | #include <linux/clocksource.h> |
@@ -66,6 +65,52 @@ | |||
66 | #include "hda_priv.h" | 65 | #include "hda_priv.h" |
67 | #include "hda_i915.h" | 66 | #include "hda_i915.h" |
68 | 67 | ||
68 | /* position fix mode */ | ||
69 | enum { | ||
70 | POS_FIX_AUTO, | ||
71 | POS_FIX_LPIB, | ||
72 | POS_FIX_POSBUF, | ||
73 | POS_FIX_VIACOMBO, | ||
74 | POS_FIX_COMBO, | ||
75 | }; | ||
76 | |||
77 | /* Defines for ATI HD Audio support in SB450 south bridge */ | ||
78 | #define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR 0x42 | ||
79 | #define ATI_SB450_HDAUDIO_ENABLE_SNOOP 0x02 | ||
80 | |||
81 | /* Defines for Nvidia HDA support */ | ||
82 | #define NVIDIA_HDA_TRANSREG_ADDR 0x4e | ||
83 | #define NVIDIA_HDA_ENABLE_COHBITS 0x0f | ||
84 | #define NVIDIA_HDA_ISTRM_COH 0x4d | ||
85 | #define NVIDIA_HDA_OSTRM_COH 0x4c | ||
86 | #define NVIDIA_HDA_ENABLE_COHBIT 0x01 | ||
87 | |||
88 | /* Defines for Intel SCH HDA snoop control */ | ||
89 | #define INTEL_SCH_HDA_DEVC 0x78 | ||
90 | #define INTEL_SCH_HDA_DEVC_NOSNOOP (0x1<<11) | ||
91 | |||
92 | /* Define IN stream 0 FIFO size offset in VIA controller */ | ||
93 | #define VIA_IN_STREAM0_FIFO_SIZE_OFFSET 0x90 | ||
94 | /* Define VIA HD Audio Device ID*/ | ||
95 | #define VIA_HDAC_DEVICE_ID 0x3288 | ||
96 | |||
97 | /* max number of SDs */ | ||
98 | /* ICH, ATI and VIA have 4 playback and 4 capture */ | ||
99 | #define ICH6_NUM_CAPTURE 4 | ||
100 | #define ICH6_NUM_PLAYBACK 4 | ||
101 | |||
102 | /* ULI has 6 playback and 5 capture */ | ||
103 | #define ULI_NUM_CAPTURE 5 | ||
104 | #define ULI_NUM_PLAYBACK 6 | ||
105 | |||
106 | /* ATI HDMI may have up to 8 playbacks and 0 capture */ | ||
107 | #define ATIHDMI_NUM_CAPTURE 0 | ||
108 | #define ATIHDMI_NUM_PLAYBACK 8 | ||
109 | |||
110 | /* TERA has 4 playback and 3 capture */ | ||
111 | #define TERA_NUM_CAPTURE 3 | ||
112 | #define TERA_NUM_PLAYBACK 4 | ||
113 | |||
69 | 114 | ||
70 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; | 115 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; |
71 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; | 116 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; |
@@ -290,8 +335,28 @@ static char *driver_short_names[] = { | |||
290 | 335 | ||
291 | struct hda_intel { | 336 | struct hda_intel { |
292 | struct azx chip; | 337 | struct azx chip; |
293 | }; | ||
294 | 338 | ||
339 | /* for pending irqs */ | ||
340 | struct work_struct irq_pending_work; | ||
341 | |||
342 | /* sync probing */ | ||
343 | struct completion probe_wait; | ||
344 | struct work_struct probe_work; | ||
345 | |||
346 | /* card list (for power_save trigger) */ | ||
347 | struct list_head list; | ||
348 | |||
349 | /* extra flags */ | ||
350 | unsigned int irq_pending_warned:1; | ||
351 | |||
352 | /* VGA-switcheroo setup */ | ||
353 | unsigned int use_vga_switcheroo:1; | ||
354 | unsigned int vga_switcheroo_registered:1; | ||
355 | unsigned int init_failed:1; /* delayed init failed */ | ||
356 | |||
357 | /* secondary power domain for hdmi audio under vga device */ | ||
358 | struct dev_pm_domain hdmi_pm_domain; | ||
359 | }; | ||
295 | 360 | ||
296 | #ifdef CONFIG_X86 | 361 | #ifdef CONFIG_X86 |
297 | static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool on) | 362 | static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool on) |
@@ -373,7 +438,7 @@ static void azx_init_pci(struct azx *chip) | |||
373 | */ | 438 | */ |
374 | if (!(chip->driver_caps & AZX_DCAPS_NO_TCSEL)) { | 439 | if (!(chip->driver_caps & AZX_DCAPS_NO_TCSEL)) { |
375 | dev_dbg(chip->card->dev, "Clearing TCSEL\n"); | 440 | dev_dbg(chip->card->dev, "Clearing TCSEL\n"); |
376 | update_pci_byte(chip->pci, ICH6_PCIREG_TCSEL, 0x07, 0); | 441 | update_pci_byte(chip->pci, AZX_PCIREG_TCSEL, 0x07, 0); |
377 | } | 442 | } |
378 | 443 | ||
379 | /* For ATI SB450/600/700/800/900 and AMD Hudson azalia HD audio, | 444 | /* For ATI SB450/600/700/800/900 and AMD Hudson azalia HD audio, |
@@ -421,11 +486,44 @@ static void azx_init_pci(struct azx *chip) | |||
421 | } | 486 | } |
422 | } | 487 | } |
423 | 488 | ||
489 | /* calculate runtime delay from LPIB */ | ||
490 | static int azx_get_delay_from_lpib(struct azx *chip, struct azx_dev *azx_dev, | ||
491 | unsigned int pos) | ||
492 | { | ||
493 | struct snd_pcm_substream *substream = azx_dev->substream; | ||
494 | int stream = substream->stream; | ||
495 | unsigned int lpib_pos = azx_get_pos_lpib(chip, azx_dev); | ||
496 | int delay; | ||
497 | |||
498 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
499 | delay = pos - lpib_pos; | ||
500 | else | ||
501 | delay = lpib_pos - pos; | ||
502 | if (delay < 0) { | ||
503 | if (delay >= azx_dev->delay_negative_threshold) | ||
504 | delay = 0; | ||
505 | else | ||
506 | delay += azx_dev->bufsize; | ||
507 | } | ||
508 | |||
509 | if (delay >= azx_dev->period_bytes) { | ||
510 | dev_info(chip->card->dev, | ||
511 | "Unstable LPIB (%d >= %d); disabling LPIB delay counting\n", | ||
512 | delay, azx_dev->period_bytes); | ||
513 | delay = 0; | ||
514 | chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY; | ||
515 | chip->get_delay[stream] = NULL; | ||
516 | } | ||
517 | |||
518 | return bytes_to_frames(substream->runtime, delay); | ||
519 | } | ||
520 | |||
424 | static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev); | 521 | static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev); |
425 | 522 | ||
426 | /* called from IRQ */ | 523 | /* called from IRQ */ |
427 | static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev) | 524 | static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev) |
428 | { | 525 | { |
526 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | ||
429 | int ok; | 527 | int ok; |
430 | 528 | ||
431 | ok = azx_position_ok(chip, azx_dev); | 529 | ok = azx_position_ok(chip, azx_dev); |
@@ -435,7 +533,7 @@ static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev) | |||
435 | } else if (ok == 0 && chip->bus && chip->bus->workq) { | 533 | } else if (ok == 0 && chip->bus && chip->bus->workq) { |
436 | /* bogus IRQ, process it later */ | 534 | /* bogus IRQ, process it later */ |
437 | azx_dev->irq_pending = 1; | 535 | azx_dev->irq_pending = 1; |
438 | queue_work(chip->bus->workq, &chip->irq_pending_work); | 536 | queue_work(chip->bus->workq, &hda->irq_pending_work); |
439 | } | 537 | } |
440 | return 0; | 538 | return 0; |
441 | } | 539 | } |
@@ -451,6 +549,8 @@ static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev) | |||
451 | */ | 549 | */ |
452 | static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) | 550 | static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) |
453 | { | 551 | { |
552 | struct snd_pcm_substream *substream = azx_dev->substream; | ||
553 | int stream = substream->stream; | ||
454 | u32 wallclk; | 554 | u32 wallclk; |
455 | unsigned int pos; | 555 | unsigned int pos; |
456 | 556 | ||
@@ -458,7 +558,25 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) | |||
458 | if (wallclk < (azx_dev->period_wallclk * 2) / 3) | 558 | if (wallclk < (azx_dev->period_wallclk * 2) / 3) |
459 | return -1; /* bogus (too early) interrupt */ | 559 | return -1; /* bogus (too early) interrupt */ |
460 | 560 | ||
461 | pos = azx_get_position(chip, azx_dev, true); | 561 | if (chip->get_position[stream]) |
562 | pos = chip->get_position[stream](chip, azx_dev); | ||
563 | else { /* use the position buffer as default */ | ||
564 | pos = azx_get_pos_posbuf(chip, azx_dev); | ||
565 | if (!pos || pos == (u32)-1) { | ||
566 | dev_info(chip->card->dev, | ||
567 | "Invalid position buffer, using LPIB read method instead.\n"); | ||
568 | chip->get_position[stream] = azx_get_pos_lpib; | ||
569 | pos = azx_get_pos_lpib(chip, azx_dev); | ||
570 | chip->get_delay[stream] = NULL; | ||
571 | } else { | ||
572 | chip->get_position[stream] = azx_get_pos_posbuf; | ||
573 | if (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY) | ||
574 | chip->get_delay[stream] = azx_get_delay_from_lpib; | ||
575 | } | ||
576 | } | ||
577 | |||
578 | if (pos >= azx_dev->bufsize) | ||
579 | pos = 0; | ||
462 | 580 | ||
463 | if (WARN_ONCE(!azx_dev->period_bytes, | 581 | if (WARN_ONCE(!azx_dev->period_bytes, |
464 | "hda-intel: zero azx_dev->period_bytes")) | 582 | "hda-intel: zero azx_dev->period_bytes")) |
@@ -476,14 +594,15 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) | |||
476 | */ | 594 | */ |
477 | static void azx_irq_pending_work(struct work_struct *work) | 595 | static void azx_irq_pending_work(struct work_struct *work) |
478 | { | 596 | { |
479 | struct azx *chip = container_of(work, struct azx, irq_pending_work); | 597 | struct hda_intel *hda = container_of(work, struct hda_intel, irq_pending_work); |
598 | struct azx *chip = &hda->chip; | ||
480 | int i, pending, ok; | 599 | int i, pending, ok; |
481 | 600 | ||
482 | if (!chip->irq_pending_warned) { | 601 | if (!hda->irq_pending_warned) { |
483 | dev_info(chip->card->dev, | 602 | dev_info(chip->card->dev, |
484 | "IRQ timing workaround is activated for card #%d. Suggest a bigger bdl_pos_adj.\n", | 603 | "IRQ timing workaround is activated for card #%d. Suggest a bigger bdl_pos_adj.\n", |
485 | chip->card->number); | 604 | chip->card->number); |
486 | chip->irq_pending_warned = 1; | 605 | hda->irq_pending_warned = 1; |
487 | } | 606 | } |
488 | 607 | ||
489 | for (;;) { | 608 | for (;;) { |
@@ -541,27 +660,86 @@ static int azx_acquire_irq(struct azx *chip, int do_disconnect) | |||
541 | return 0; | 660 | return 0; |
542 | } | 661 | } |
543 | 662 | ||
663 | /* get the current DMA position with correction on VIA chips */ | ||
664 | static unsigned int azx_via_get_position(struct azx *chip, | ||
665 | struct azx_dev *azx_dev) | ||
666 | { | ||
667 | unsigned int link_pos, mini_pos, bound_pos; | ||
668 | unsigned int mod_link_pos, mod_dma_pos, mod_mini_pos; | ||
669 | unsigned int fifo_size; | ||
670 | |||
671 | link_pos = azx_sd_readl(chip, azx_dev, SD_LPIB); | ||
672 | if (azx_dev->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
673 | /* Playback, no problem using link position */ | ||
674 | return link_pos; | ||
675 | } | ||
676 | |||
677 | /* Capture */ | ||
678 | /* For new chipset, | ||
679 | * use mod to get the DMA position just like old chipset | ||
680 | */ | ||
681 | mod_dma_pos = le32_to_cpu(*azx_dev->posbuf); | ||
682 | mod_dma_pos %= azx_dev->period_bytes; | ||
683 | |||
684 | /* azx_dev->fifo_size can't get FIFO size of in stream. | ||
685 | * Get from base address + offset. | ||
686 | */ | ||
687 | fifo_size = readw(chip->remap_addr + VIA_IN_STREAM0_FIFO_SIZE_OFFSET); | ||
688 | |||
689 | if (azx_dev->insufficient) { | ||
690 | /* Link position never gather than FIFO size */ | ||
691 | if (link_pos <= fifo_size) | ||
692 | return 0; | ||
693 | |||
694 | azx_dev->insufficient = 0; | ||
695 | } | ||
696 | |||
697 | if (link_pos <= fifo_size) | ||
698 | mini_pos = azx_dev->bufsize + link_pos - fifo_size; | ||
699 | else | ||
700 | mini_pos = link_pos - fifo_size; | ||
701 | |||
702 | /* Find nearest previous boudary */ | ||
703 | mod_mini_pos = mini_pos % azx_dev->period_bytes; | ||
704 | mod_link_pos = link_pos % azx_dev->period_bytes; | ||
705 | if (mod_link_pos >= fifo_size) | ||
706 | bound_pos = link_pos - mod_link_pos; | ||
707 | else if (mod_dma_pos >= mod_mini_pos) | ||
708 | bound_pos = mini_pos - mod_mini_pos; | ||
709 | else { | ||
710 | bound_pos = mini_pos - mod_mini_pos + azx_dev->period_bytes; | ||
711 | if (bound_pos >= azx_dev->bufsize) | ||
712 | bound_pos = 0; | ||
713 | } | ||
714 | |||
715 | /* Calculate real DMA position we want */ | ||
716 | return bound_pos + mod_dma_pos; | ||
717 | } | ||
718 | |||
544 | #ifdef CONFIG_PM | 719 | #ifdef CONFIG_PM |
545 | static DEFINE_MUTEX(card_list_lock); | 720 | static DEFINE_MUTEX(card_list_lock); |
546 | static LIST_HEAD(card_list); | 721 | static LIST_HEAD(card_list); |
547 | 722 | ||
548 | static void azx_add_card_list(struct azx *chip) | 723 | static void azx_add_card_list(struct azx *chip) |
549 | { | 724 | { |
725 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | ||
550 | mutex_lock(&card_list_lock); | 726 | mutex_lock(&card_list_lock); |
551 | list_add(&chip->list, &card_list); | 727 | list_add(&hda->list, &card_list); |
552 | mutex_unlock(&card_list_lock); | 728 | mutex_unlock(&card_list_lock); |
553 | } | 729 | } |
554 | 730 | ||
555 | static void azx_del_card_list(struct azx *chip) | 731 | static void azx_del_card_list(struct azx *chip) |
556 | { | 732 | { |
733 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | ||
557 | mutex_lock(&card_list_lock); | 734 | mutex_lock(&card_list_lock); |
558 | list_del_init(&chip->list); | 735 | list_del_init(&hda->list); |
559 | mutex_unlock(&card_list_lock); | 736 | mutex_unlock(&card_list_lock); |
560 | } | 737 | } |
561 | 738 | ||
562 | /* trigger power-save check at writing parameter */ | 739 | /* trigger power-save check at writing parameter */ |
563 | static int param_set_xint(const char *val, const struct kernel_param *kp) | 740 | static int param_set_xint(const char *val, const struct kernel_param *kp) |
564 | { | 741 | { |
742 | struct hda_intel *hda; | ||
565 | struct azx *chip; | 743 | struct azx *chip; |
566 | struct hda_codec *c; | 744 | struct hda_codec *c; |
567 | int prev = power_save; | 745 | int prev = power_save; |
@@ -571,7 +749,8 @@ static int param_set_xint(const char *val, const struct kernel_param *kp) | |||
571 | return ret; | 749 | return ret; |
572 | 750 | ||
573 | mutex_lock(&card_list_lock); | 751 | mutex_lock(&card_list_lock); |
574 | list_for_each_entry(chip, &card_list, list) { | 752 | list_for_each_entry(hda, &card_list, list) { |
753 | chip = &hda->chip; | ||
575 | if (!chip->bus || chip->disabled) | 754 | if (!chip->bus || chip->disabled) |
576 | continue; | 755 | continue; |
577 | list_for_each_entry(c, &chip->bus->codec_list, list) | 756 | list_for_each_entry(c, &chip->bus->codec_list, list) |
@@ -593,10 +772,16 @@ static int azx_suspend(struct device *dev) | |||
593 | { | 772 | { |
594 | struct pci_dev *pci = to_pci_dev(dev); | 773 | struct pci_dev *pci = to_pci_dev(dev); |
595 | struct snd_card *card = dev_get_drvdata(dev); | 774 | struct snd_card *card = dev_get_drvdata(dev); |
596 | struct azx *chip = card->private_data; | 775 | struct azx *chip; |
776 | struct hda_intel *hda; | ||
597 | struct azx_pcm *p; | 777 | struct azx_pcm *p; |
598 | 778 | ||
599 | if (chip->disabled || chip->init_failed) | 779 | if (!card) |
780 | return 0; | ||
781 | |||
782 | chip = card->private_data; | ||
783 | hda = container_of(chip, struct hda_intel, chip); | ||
784 | if (chip->disabled || hda->init_failed) | ||
600 | return 0; | 785 | return 0; |
601 | 786 | ||
602 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | 787 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
@@ -626,9 +811,15 @@ static int azx_resume(struct device *dev) | |||
626 | { | 811 | { |
627 | struct pci_dev *pci = to_pci_dev(dev); | 812 | struct pci_dev *pci = to_pci_dev(dev); |
628 | struct snd_card *card = dev_get_drvdata(dev); | 813 | struct snd_card *card = dev_get_drvdata(dev); |
629 | struct azx *chip = card->private_data; | 814 | struct azx *chip; |
815 | struct hda_intel *hda; | ||
630 | 816 | ||
631 | if (chip->disabled || chip->init_failed) | 817 | if (!card) |
818 | return 0; | ||
819 | |||
820 | chip = card->private_data; | ||
821 | hda = container_of(chip, struct hda_intel, chip); | ||
822 | if (chip->disabled || hda->init_failed) | ||
632 | return 0; | 823 | return 0; |
633 | 824 | ||
634 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { | 825 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { |
@@ -663,9 +854,15 @@ static int azx_resume(struct device *dev) | |||
663 | static int azx_runtime_suspend(struct device *dev) | 854 | static int azx_runtime_suspend(struct device *dev) |
664 | { | 855 | { |
665 | struct snd_card *card = dev_get_drvdata(dev); | 856 | struct snd_card *card = dev_get_drvdata(dev); |
666 | struct azx *chip = card->private_data; | 857 | struct azx *chip; |
858 | struct hda_intel *hda; | ||
859 | |||
860 | if (!card) | ||
861 | return 0; | ||
667 | 862 | ||
668 | if (chip->disabled || chip->init_failed) | 863 | chip = card->private_data; |
864 | hda = container_of(chip, struct hda_intel, chip); | ||
865 | if (chip->disabled || hda->init_failed) | ||
669 | return 0; | 866 | return 0; |
670 | 867 | ||
671 | if (!(chip->driver_caps & AZX_DCAPS_PM_RUNTIME)) | 868 | if (!(chip->driver_caps & AZX_DCAPS_PM_RUNTIME)) |
@@ -687,12 +884,18 @@ static int azx_runtime_suspend(struct device *dev) | |||
687 | static int azx_runtime_resume(struct device *dev) | 884 | static int azx_runtime_resume(struct device *dev) |
688 | { | 885 | { |
689 | struct snd_card *card = dev_get_drvdata(dev); | 886 | struct snd_card *card = dev_get_drvdata(dev); |
690 | struct azx *chip = card->private_data; | 887 | struct azx *chip; |
888 | struct hda_intel *hda; | ||
691 | struct hda_bus *bus; | 889 | struct hda_bus *bus; |
692 | struct hda_codec *codec; | 890 | struct hda_codec *codec; |
693 | int status; | 891 | int status; |
694 | 892 | ||
695 | if (chip->disabled || chip->init_failed) | 893 | if (!card) |
894 | return 0; | ||
895 | |||
896 | chip = card->private_data; | ||
897 | hda = container_of(chip, struct hda_intel, chip); | ||
898 | if (chip->disabled || hda->init_failed) | ||
696 | return 0; | 899 | return 0; |
697 | 900 | ||
698 | if (!(chip->driver_caps & AZX_DCAPS_PM_RUNTIME)) | 901 | if (!(chip->driver_caps & AZX_DCAPS_PM_RUNTIME)) |
@@ -727,9 +930,15 @@ static int azx_runtime_resume(struct device *dev) | |||
727 | static int azx_runtime_idle(struct device *dev) | 930 | static int azx_runtime_idle(struct device *dev) |
728 | { | 931 | { |
729 | struct snd_card *card = dev_get_drvdata(dev); | 932 | struct snd_card *card = dev_get_drvdata(dev); |
730 | struct azx *chip = card->private_data; | 933 | struct azx *chip; |
934 | struct hda_intel *hda; | ||
935 | |||
936 | if (!card) | ||
937 | return 0; | ||
731 | 938 | ||
732 | if (chip->disabled || chip->init_failed) | 939 | chip = card->private_data; |
940 | hda = container_of(chip, struct hda_intel, chip); | ||
941 | if (chip->disabled || hda->init_failed) | ||
733 | return 0; | 942 | return 0; |
734 | 943 | ||
735 | if (!power_save_controller || | 944 | if (!power_save_controller || |
@@ -753,29 +962,6 @@ static const struct dev_pm_ops azx_pm = { | |||
753 | #endif /* CONFIG_PM */ | 962 | #endif /* CONFIG_PM */ |
754 | 963 | ||
755 | 964 | ||
756 | /* | ||
757 | * reboot notifier for hang-up problem at power-down | ||
758 | */ | ||
759 | static int azx_halt(struct notifier_block *nb, unsigned long event, void *buf) | ||
760 | { | ||
761 | struct azx *chip = container_of(nb, struct azx, reboot_notifier); | ||
762 | snd_hda_bus_reboot_notify(chip->bus); | ||
763 | azx_stop_chip(chip); | ||
764 | return NOTIFY_OK; | ||
765 | } | ||
766 | |||
767 | static void azx_notifier_register(struct azx *chip) | ||
768 | { | ||
769 | chip->reboot_notifier.notifier_call = azx_halt; | ||
770 | register_reboot_notifier(&chip->reboot_notifier); | ||
771 | } | ||
772 | |||
773 | static void azx_notifier_unregister(struct azx *chip) | ||
774 | { | ||
775 | if (chip->reboot_notifier.notifier_call) | ||
776 | unregister_reboot_notifier(&chip->reboot_notifier); | ||
777 | } | ||
778 | |||
779 | static int azx_probe_continue(struct azx *chip); | 965 | static int azx_probe_continue(struct azx *chip); |
780 | 966 | ||
781 | #ifdef SUPPORT_VGA_SWITCHEROO | 967 | #ifdef SUPPORT_VGA_SWITCHEROO |
@@ -786,10 +972,11 @@ static void azx_vs_set_state(struct pci_dev *pci, | |||
786 | { | 972 | { |
787 | struct snd_card *card = pci_get_drvdata(pci); | 973 | struct snd_card *card = pci_get_drvdata(pci); |
788 | struct azx *chip = card->private_data; | 974 | struct azx *chip = card->private_data; |
975 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | ||
789 | bool disabled; | 976 | bool disabled; |
790 | 977 | ||
791 | wait_for_completion(&chip->probe_wait); | 978 | wait_for_completion(&hda->probe_wait); |
792 | if (chip->init_failed) | 979 | if (hda->init_failed) |
793 | return; | 980 | return; |
794 | 981 | ||
795 | disabled = (state == VGA_SWITCHEROO_OFF); | 982 | disabled = (state == VGA_SWITCHEROO_OFF); |
@@ -803,7 +990,7 @@ static void azx_vs_set_state(struct pci_dev *pci, | |||
803 | "Start delayed initialization\n"); | 990 | "Start delayed initialization\n"); |
804 | if (azx_probe_continue(chip) < 0) { | 991 | if (azx_probe_continue(chip) < 0) { |
805 | dev_err(chip->card->dev, "initialization error\n"); | 992 | dev_err(chip->card->dev, "initialization error\n"); |
806 | chip->init_failed = true; | 993 | hda->init_failed = true; |
807 | } | 994 | } |
808 | } | 995 | } |
809 | } else { | 996 | } else { |
@@ -833,9 +1020,10 @@ static bool azx_vs_can_switch(struct pci_dev *pci) | |||
833 | { | 1020 | { |
834 | struct snd_card *card = pci_get_drvdata(pci); | 1021 | struct snd_card *card = pci_get_drvdata(pci); |
835 | struct azx *chip = card->private_data; | 1022 | struct azx *chip = card->private_data; |
1023 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | ||
836 | 1024 | ||
837 | wait_for_completion(&chip->probe_wait); | 1025 | wait_for_completion(&hda->probe_wait); |
838 | if (chip->init_failed) | 1026 | if (hda->init_failed) |
839 | return false; | 1027 | return false; |
840 | if (chip->disabled || !chip->bus) | 1028 | if (chip->disabled || !chip->bus) |
841 | return true; | 1029 | return true; |
@@ -847,11 +1035,12 @@ static bool azx_vs_can_switch(struct pci_dev *pci) | |||
847 | 1035 | ||
848 | static void init_vga_switcheroo(struct azx *chip) | 1036 | static void init_vga_switcheroo(struct azx *chip) |
849 | { | 1037 | { |
1038 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | ||
850 | struct pci_dev *p = get_bound_vga(chip->pci); | 1039 | struct pci_dev *p = get_bound_vga(chip->pci); |
851 | if (p) { | 1040 | if (p) { |
852 | dev_info(chip->card->dev, | 1041 | dev_info(chip->card->dev, |
853 | "Handle VGA-switcheroo audio client\n"); | 1042 | "Handle VGA-switcheroo audio client\n"); |
854 | chip->use_vga_switcheroo = 1; | 1043 | hda->use_vga_switcheroo = 1; |
855 | pci_dev_put(p); | 1044 | pci_dev_put(p); |
856 | } | 1045 | } |
857 | } | 1046 | } |
@@ -863,9 +1052,10 @@ static const struct vga_switcheroo_client_ops azx_vs_ops = { | |||
863 | 1052 | ||
864 | static int register_vga_switcheroo(struct azx *chip) | 1053 | static int register_vga_switcheroo(struct azx *chip) |
865 | { | 1054 | { |
1055 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | ||
866 | int err; | 1056 | int err; |
867 | 1057 | ||
868 | if (!chip->use_vga_switcheroo) | 1058 | if (!hda->use_vga_switcheroo) |
869 | return 0; | 1059 | return 0; |
870 | /* FIXME: currently only handling DIS controller | 1060 | /* FIXME: currently only handling DIS controller |
871 | * is there any machine with two switchable HDMI audio controllers? | 1061 | * is there any machine with two switchable HDMI audio controllers? |
@@ -875,11 +1065,11 @@ static int register_vga_switcheroo(struct azx *chip) | |||
875 | chip->bus != NULL); | 1065 | chip->bus != NULL); |
876 | if (err < 0) | 1066 | if (err < 0) |
877 | return err; | 1067 | return err; |
878 | chip->vga_switcheroo_registered = 1; | 1068 | hda->vga_switcheroo_registered = 1; |
879 | 1069 | ||
880 | /* register as an optimus hdmi audio power domain */ | 1070 | /* register as an optimus hdmi audio power domain */ |
881 | vga_switcheroo_init_domain_pm_optimus_hdmi_audio(chip->card->dev, | 1071 | vga_switcheroo_init_domain_pm_optimus_hdmi_audio(chip->card->dev, |
882 | &chip->hdmi_pm_domain); | 1072 | &hda->hdmi_pm_domain); |
883 | return 0; | 1073 | return 0; |
884 | } | 1074 | } |
885 | #else | 1075 | #else |
@@ -895,7 +1085,6 @@ static int azx_free(struct azx *chip) | |||
895 | { | 1085 | { |
896 | struct pci_dev *pci = chip->pci; | 1086 | struct pci_dev *pci = chip->pci; |
897 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | 1087 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); |
898 | |||
899 | int i; | 1088 | int i; |
900 | 1089 | ||
901 | if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME) | 1090 | if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME) |
@@ -906,13 +1095,13 @@ static int azx_free(struct azx *chip) | |||
906 | 1095 | ||
907 | azx_notifier_unregister(chip); | 1096 | azx_notifier_unregister(chip); |
908 | 1097 | ||
909 | chip->init_failed = 1; /* to be sure */ | 1098 | hda->init_failed = 1; /* to be sure */ |
910 | complete_all(&chip->probe_wait); | 1099 | complete_all(&hda->probe_wait); |
911 | 1100 | ||
912 | if (use_vga_switcheroo(chip)) { | 1101 | if (use_vga_switcheroo(hda)) { |
913 | if (chip->disabled && chip->bus) | 1102 | if (chip->disabled && chip->bus) |
914 | snd_hda_unlock_devices(chip->bus); | 1103 | snd_hda_unlock_devices(chip->bus); |
915 | if (chip->vga_switcheroo_registered) | 1104 | if (hda->vga_switcheroo_registered) |
916 | vga_switcheroo_unregister_client(chip->pci); | 1105 | vga_switcheroo_unregister_client(chip->pci); |
917 | } | 1106 | } |
918 | 1107 | ||
@@ -1048,6 +1237,30 @@ static int check_position_fix(struct azx *chip, int fix) | |||
1048 | return POS_FIX_AUTO; | 1237 | return POS_FIX_AUTO; |
1049 | } | 1238 | } |
1050 | 1239 | ||
1240 | static void assign_position_fix(struct azx *chip, int fix) | ||
1241 | { | ||
1242 | static azx_get_pos_callback_t callbacks[] = { | ||
1243 | [POS_FIX_AUTO] = NULL, | ||
1244 | [POS_FIX_LPIB] = azx_get_pos_lpib, | ||
1245 | [POS_FIX_POSBUF] = azx_get_pos_posbuf, | ||
1246 | [POS_FIX_VIACOMBO] = azx_via_get_position, | ||
1247 | [POS_FIX_COMBO] = azx_get_pos_lpib, | ||
1248 | }; | ||
1249 | |||
1250 | chip->get_position[0] = chip->get_position[1] = callbacks[fix]; | ||
1251 | |||
1252 | /* combo mode uses LPIB only for playback */ | ||
1253 | if (fix == POS_FIX_COMBO) | ||
1254 | chip->get_position[1] = NULL; | ||
1255 | |||
1256 | if (fix == POS_FIX_POSBUF && | ||
1257 | (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) { | ||
1258 | chip->get_delay[0] = chip->get_delay[1] = | ||
1259 | azx_get_delay_from_lpib; | ||
1260 | } | ||
1261 | |||
1262 | } | ||
1263 | |||
1051 | /* | 1264 | /* |
1052 | * black-lists for probe_mask | 1265 | * black-lists for probe_mask |
1053 | */ | 1266 | */ |
@@ -1173,7 +1386,8 @@ static void azx_check_snoop_available(struct azx *chip) | |||
1173 | 1386 | ||
1174 | static void azx_probe_work(struct work_struct *work) | 1387 | static void azx_probe_work(struct work_struct *work) |
1175 | { | 1388 | { |
1176 | azx_probe_continue(container_of(work, struct azx, probe_work)); | 1389 | struct hda_intel *hda = container_of(work, struct hda_intel, probe_work); |
1390 | azx_probe_continue(&hda->chip); | ||
1177 | } | 1391 | } |
1178 | 1392 | ||
1179 | /* | 1393 | /* |
@@ -1216,19 +1430,13 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1216 | check_msi(chip); | 1430 | check_msi(chip); |
1217 | chip->dev_index = dev; | 1431 | chip->dev_index = dev; |
1218 | chip->jackpoll_ms = jackpoll_ms; | 1432 | chip->jackpoll_ms = jackpoll_ms; |
1219 | INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work); | ||
1220 | INIT_LIST_HEAD(&chip->pcm_list); | 1433 | INIT_LIST_HEAD(&chip->pcm_list); |
1221 | INIT_LIST_HEAD(&chip->list); | 1434 | INIT_WORK(&hda->irq_pending_work, azx_irq_pending_work); |
1435 | INIT_LIST_HEAD(&hda->list); | ||
1222 | init_vga_switcheroo(chip); | 1436 | init_vga_switcheroo(chip); |
1223 | init_completion(&chip->probe_wait); | 1437 | init_completion(&hda->probe_wait); |
1224 | 1438 | ||
1225 | chip->position_fix[0] = chip->position_fix[1] = | 1439 | assign_position_fix(chip, check_position_fix(chip, position_fix[dev])); |
1226 | check_position_fix(chip, position_fix[dev]); | ||
1227 | /* combo mode uses LPIB for playback */ | ||
1228 | if (chip->position_fix[0] == POS_FIX_COMBO) { | ||
1229 | chip->position_fix[0] = POS_FIX_LPIB; | ||
1230 | chip->position_fix[1] = POS_FIX_AUTO; | ||
1231 | } | ||
1232 | 1440 | ||
1233 | check_probe_mask(chip, dev); | 1441 | check_probe_mask(chip, dev); |
1234 | 1442 | ||
@@ -1257,7 +1465,7 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1257 | } | 1465 | } |
1258 | 1466 | ||
1259 | /* continue probing in work context as may trigger request module */ | 1467 | /* continue probing in work context as may trigger request module */ |
1260 | INIT_WORK(&chip->probe_work, azx_probe_work); | 1468 | INIT_WORK(&hda->probe_work, azx_probe_work); |
1261 | 1469 | ||
1262 | *rchip = chip; | 1470 | *rchip = chip; |
1263 | 1471 | ||
@@ -1315,7 +1523,7 @@ static int azx_first_init(struct azx *chip) | |||
1315 | NULL); | 1523 | NULL); |
1316 | if (p_smbus) { | 1524 | if (p_smbus) { |
1317 | if (p_smbus->revision < 0x30) | 1525 | if (p_smbus->revision < 0x30) |
1318 | gcap &= ~ICH6_GCAP_64OK; | 1526 | gcap &= ~AZX_GCAP_64OK; |
1319 | pci_dev_put(p_smbus); | 1527 | pci_dev_put(p_smbus); |
1320 | } | 1528 | } |
1321 | } | 1529 | } |
@@ -1323,7 +1531,7 @@ static int azx_first_init(struct azx *chip) | |||
1323 | /* disable 64bit DMA address on some devices */ | 1531 | /* disable 64bit DMA address on some devices */ |
1324 | if (chip->driver_caps & AZX_DCAPS_NO_64BIT) { | 1532 | if (chip->driver_caps & AZX_DCAPS_NO_64BIT) { |
1325 | dev_dbg(card->dev, "Disabling 64bit DMA\n"); | 1533 | dev_dbg(card->dev, "Disabling 64bit DMA\n"); |
1326 | gcap &= ~ICH6_GCAP_64OK; | 1534 | gcap &= ~AZX_GCAP_64OK; |
1327 | } | 1535 | } |
1328 | 1536 | ||
1329 | /* disable buffer size rounding to 128-byte multiples if supported */ | 1537 | /* disable buffer size rounding to 128-byte multiples if supported */ |
@@ -1339,7 +1547,7 @@ static int azx_first_init(struct azx *chip) | |||
1339 | } | 1547 | } |
1340 | 1548 | ||
1341 | /* allow 64bit DMA address if supported by H/W */ | 1549 | /* allow 64bit DMA address if supported by H/W */ |
1342 | if ((gcap & ICH6_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64))) | 1550 | if ((gcap & AZX_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64))) |
1343 | pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(64)); | 1551 | pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(64)); |
1344 | else { | 1552 | else { |
1345 | pci_set_dma_mask(pci, DMA_BIT_MASK(32)); | 1553 | pci_set_dma_mask(pci, DMA_BIT_MASK(32)); |
@@ -1583,6 +1791,7 @@ static int azx_probe(struct pci_dev *pci, | |||
1583 | { | 1791 | { |
1584 | static int dev; | 1792 | static int dev; |
1585 | struct snd_card *card; | 1793 | struct snd_card *card; |
1794 | struct hda_intel *hda; | ||
1586 | struct azx *chip; | 1795 | struct azx *chip; |
1587 | bool schedule_probe; | 1796 | bool schedule_probe; |
1588 | int err; | 1797 | int err; |
@@ -1606,6 +1815,7 @@ static int azx_probe(struct pci_dev *pci, | |||
1606 | if (err < 0) | 1815 | if (err < 0) |
1607 | goto out_free; | 1816 | goto out_free; |
1608 | card->private_data = chip; | 1817 | card->private_data = chip; |
1818 | hda = container_of(chip, struct hda_intel, chip); | ||
1609 | 1819 | ||
1610 | pci_set_drvdata(pci, card); | 1820 | pci_set_drvdata(pci, card); |
1611 | 1821 | ||
@@ -1642,11 +1852,11 @@ static int azx_probe(struct pci_dev *pci, | |||
1642 | #endif | 1852 | #endif |
1643 | 1853 | ||
1644 | if (schedule_probe) | 1854 | if (schedule_probe) |
1645 | schedule_work(&chip->probe_work); | 1855 | schedule_work(&hda->probe_work); |
1646 | 1856 | ||
1647 | dev++; | 1857 | dev++; |
1648 | if (chip->disabled) | 1858 | if (chip->disabled) |
1649 | complete_all(&chip->probe_wait); | 1859 | complete_all(&hda->probe_wait); |
1650 | return 0; | 1860 | return 0; |
1651 | 1861 | ||
1652 | out_free: | 1862 | out_free: |
@@ -1662,6 +1872,7 @@ static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] = { | |||
1662 | 1872 | ||
1663 | static int azx_probe_continue(struct azx *chip) | 1873 | static int azx_probe_continue(struct azx *chip) |
1664 | { | 1874 | { |
1875 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | ||
1665 | struct pci_dev *pci = chip->pci; | 1876 | struct pci_dev *pci = chip->pci; |
1666 | int dev = chip->dev_index; | 1877 | int dev = chip->dev_index; |
1667 | int err; | 1878 | int err; |
@@ -1735,13 +1946,13 @@ static int azx_probe_continue(struct azx *chip) | |||
1735 | power_down_all_codecs(chip); | 1946 | power_down_all_codecs(chip); |
1736 | azx_notifier_register(chip); | 1947 | azx_notifier_register(chip); |
1737 | azx_add_card_list(chip); | 1948 | azx_add_card_list(chip); |
1738 | if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME) || chip->use_vga_switcheroo) | 1949 | if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME) || hda->use_vga_switcheroo) |
1739 | pm_runtime_put_noidle(&pci->dev); | 1950 | pm_runtime_put_noidle(&pci->dev); |
1740 | 1951 | ||
1741 | out_free: | 1952 | out_free: |
1742 | if (err < 0) | 1953 | if (err < 0) |
1743 | chip->init_failed = 1; | 1954 | hda->init_failed = 1; |
1744 | complete_all(&chip->probe_wait); | 1955 | complete_all(&hda->probe_wait); |
1745 | return err; | 1956 | return err; |
1746 | } | 1957 | } |
1747 | 1958 | ||
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 4e2d4863daa1..364bb413e02a 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -268,7 +268,8 @@ int snd_hda_input_mux_put(struct hda_codec *codec, | |||
268 | const struct hda_input_mux *imux, | 268 | const struct hda_input_mux *imux, |
269 | struct snd_ctl_elem_value *ucontrol, hda_nid_t nid, | 269 | struct snd_ctl_elem_value *ucontrol, hda_nid_t nid, |
270 | unsigned int *cur_val); | 270 | unsigned int *cur_val); |
271 | int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label, | 271 | int snd_hda_add_imux_item(struct hda_codec *codec, |
272 | struct hda_input_mux *imux, const char *label, | ||
272 | int index, int *type_index_ret); | 273 | int index, int *type_index_ret); |
273 | 274 | ||
274 | /* | 275 | /* |
@@ -437,6 +438,8 @@ struct snd_hda_pin_quirk { | |||
437 | 438 | ||
438 | #endif | 439 | #endif |
439 | 440 | ||
441 | #define HDA_FIXUP_ID_NOT_SET -1 | ||
442 | #define HDA_FIXUP_ID_NO_FIXUP -2 | ||
440 | 443 | ||
441 | /* fixup types */ | 444 | /* fixup types */ |
442 | enum { | 445 | enum { |
@@ -773,9 +776,9 @@ struct hdmi_eld { | |||
773 | int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid); | 776 | int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid); |
774 | int snd_hdmi_get_eld(struct hda_codec *codec, hda_nid_t nid, | 777 | int snd_hdmi_get_eld(struct hda_codec *codec, hda_nid_t nid, |
775 | unsigned char *buf, int *eld_size); | 778 | unsigned char *buf, int *eld_size); |
776 | int snd_hdmi_parse_eld(struct parsed_hdmi_eld *e, | 779 | int snd_hdmi_parse_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e, |
777 | const unsigned char *buf, int size); | 780 | const unsigned char *buf, int size); |
778 | void snd_hdmi_show_eld(struct parsed_hdmi_eld *e); | 781 | void snd_hdmi_show_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e); |
779 | void snd_hdmi_eld_update_pcm_info(struct parsed_hdmi_eld *e, | 782 | void snd_hdmi_eld_update_pcm_info(struct parsed_hdmi_eld *e, |
780 | struct hda_pcm_stream *hinfo); | 783 | struct hda_pcm_stream *hinfo); |
781 | 784 | ||
diff --git a/sound/pci/hda/hda_priv.h b/sound/pci/hda/hda_priv.h index e9d1a5762a55..949cd437eeb2 100644 --- a/sound/pci/hda/hda_priv.h +++ b/sound/pci/hda/hda_priv.h | |||
@@ -22,107 +22,87 @@ | |||
22 | /* | 22 | /* |
23 | * registers | 23 | * registers |
24 | */ | 24 | */ |
25 | #define ICH6_REG_GCAP 0x00 | 25 | #define AZX_REG_GCAP 0x00 |
26 | #define ICH6_GCAP_64OK (1 << 0) /* 64bit address support */ | 26 | #define AZX_GCAP_64OK (1 << 0) /* 64bit address support */ |
27 | #define ICH6_GCAP_NSDO (3 << 1) /* # of serial data out signals */ | 27 | #define AZX_GCAP_NSDO (3 << 1) /* # of serial data out signals */ |
28 | #define ICH6_GCAP_BSS (31 << 3) /* # of bidirectional streams */ | 28 | #define AZX_GCAP_BSS (31 << 3) /* # of bidirectional streams */ |
29 | #define ICH6_GCAP_ISS (15 << 8) /* # of input streams */ | 29 | #define AZX_GCAP_ISS (15 << 8) /* # of input streams */ |
30 | #define ICH6_GCAP_OSS (15 << 12) /* # of output streams */ | 30 | #define AZX_GCAP_OSS (15 << 12) /* # of output streams */ |
31 | #define ICH6_REG_VMIN 0x02 | 31 | #define AZX_REG_VMIN 0x02 |
32 | #define ICH6_REG_VMAJ 0x03 | 32 | #define AZX_REG_VMAJ 0x03 |
33 | #define ICH6_REG_OUTPAY 0x04 | 33 | #define AZX_REG_OUTPAY 0x04 |
34 | #define ICH6_REG_INPAY 0x06 | 34 | #define AZX_REG_INPAY 0x06 |
35 | #define ICH6_REG_GCTL 0x08 | 35 | #define AZX_REG_GCTL 0x08 |
36 | #define ICH6_GCTL_RESET (1 << 0) /* controller reset */ | 36 | #define AZX_GCTL_RESET (1 << 0) /* controller reset */ |
37 | #define ICH6_GCTL_FCNTRL (1 << 1) /* flush control */ | 37 | #define AZX_GCTL_FCNTRL (1 << 1) /* flush control */ |
38 | #define ICH6_GCTL_UNSOL (1 << 8) /* accept unsol. response enable */ | 38 | #define AZX_GCTL_UNSOL (1 << 8) /* accept unsol. response enable */ |
39 | #define ICH6_REG_WAKEEN 0x0c | 39 | #define AZX_REG_WAKEEN 0x0c |
40 | #define ICH6_REG_STATESTS 0x0e | 40 | #define AZX_REG_STATESTS 0x0e |
41 | #define ICH6_REG_GSTS 0x10 | 41 | #define AZX_REG_GSTS 0x10 |
42 | #define ICH6_GSTS_FSTS (1 << 1) /* flush status */ | 42 | #define AZX_GSTS_FSTS (1 << 1) /* flush status */ |
43 | #define ICH6_REG_INTCTL 0x20 | 43 | #define AZX_REG_INTCTL 0x20 |
44 | #define ICH6_REG_INTSTS 0x24 | 44 | #define AZX_REG_INTSTS 0x24 |
45 | #define ICH6_REG_WALLCLK 0x30 /* 24Mhz source */ | 45 | #define AZX_REG_WALLCLK 0x30 /* 24Mhz source */ |
46 | #define ICH6_REG_OLD_SSYNC 0x34 /* SSYNC for old ICH */ | 46 | #define AZX_REG_OLD_SSYNC 0x34 /* SSYNC for old ICH */ |
47 | #define ICH6_REG_SSYNC 0x38 | 47 | #define AZX_REG_SSYNC 0x38 |
48 | #define ICH6_REG_CORBLBASE 0x40 | 48 | #define AZX_REG_CORBLBASE 0x40 |
49 | #define ICH6_REG_CORBUBASE 0x44 | 49 | #define AZX_REG_CORBUBASE 0x44 |
50 | #define ICH6_REG_CORBWP 0x48 | 50 | #define AZX_REG_CORBWP 0x48 |
51 | #define ICH6_REG_CORBRP 0x4a | 51 | #define AZX_REG_CORBRP 0x4a |
52 | #define ICH6_CORBRP_RST (1 << 15) /* read pointer reset */ | 52 | #define AZX_CORBRP_RST (1 << 15) /* read pointer reset */ |
53 | #define ICH6_REG_CORBCTL 0x4c | 53 | #define AZX_REG_CORBCTL 0x4c |
54 | #define ICH6_CORBCTL_RUN (1 << 1) /* enable DMA */ | 54 | #define AZX_CORBCTL_RUN (1 << 1) /* enable DMA */ |
55 | #define ICH6_CORBCTL_CMEIE (1 << 0) /* enable memory error irq */ | 55 | #define AZX_CORBCTL_CMEIE (1 << 0) /* enable memory error irq */ |
56 | #define ICH6_REG_CORBSTS 0x4d | 56 | #define AZX_REG_CORBSTS 0x4d |
57 | #define ICH6_CORBSTS_CMEI (1 << 0) /* memory error indication */ | 57 | #define AZX_CORBSTS_CMEI (1 << 0) /* memory error indication */ |
58 | #define ICH6_REG_CORBSIZE 0x4e | 58 | #define AZX_REG_CORBSIZE 0x4e |
59 | 59 | ||
60 | #define ICH6_REG_RIRBLBASE 0x50 | 60 | #define AZX_REG_RIRBLBASE 0x50 |
61 | #define ICH6_REG_RIRBUBASE 0x54 | 61 | #define AZX_REG_RIRBUBASE 0x54 |
62 | #define ICH6_REG_RIRBWP 0x58 | 62 | #define AZX_REG_RIRBWP 0x58 |
63 | #define ICH6_RIRBWP_RST (1 << 15) /* write pointer reset */ | 63 | #define AZX_RIRBWP_RST (1 << 15) /* write pointer reset */ |
64 | #define ICH6_REG_RINTCNT 0x5a | 64 | #define AZX_REG_RINTCNT 0x5a |
65 | #define ICH6_REG_RIRBCTL 0x5c | 65 | #define AZX_REG_RIRBCTL 0x5c |
66 | #define ICH6_RBCTL_IRQ_EN (1 << 0) /* enable IRQ */ | 66 | #define AZX_RBCTL_IRQ_EN (1 << 0) /* enable IRQ */ |
67 | #define ICH6_RBCTL_DMA_EN (1 << 1) /* enable DMA */ | 67 | #define AZX_RBCTL_DMA_EN (1 << 1) /* enable DMA */ |
68 | #define ICH6_RBCTL_OVERRUN_EN (1 << 2) /* enable overrun irq */ | 68 | #define AZX_RBCTL_OVERRUN_EN (1 << 2) /* enable overrun irq */ |
69 | #define ICH6_REG_RIRBSTS 0x5d | 69 | #define AZX_REG_RIRBSTS 0x5d |
70 | #define ICH6_RBSTS_IRQ (1 << 0) /* response irq */ | 70 | #define AZX_RBSTS_IRQ (1 << 0) /* response irq */ |
71 | #define ICH6_RBSTS_OVERRUN (1 << 2) /* overrun irq */ | 71 | #define AZX_RBSTS_OVERRUN (1 << 2) /* overrun irq */ |
72 | #define ICH6_REG_RIRBSIZE 0x5e | 72 | #define AZX_REG_RIRBSIZE 0x5e |
73 | 73 | ||
74 | #define ICH6_REG_IC 0x60 | 74 | #define AZX_REG_IC 0x60 |
75 | #define ICH6_REG_IR 0x64 | 75 | #define AZX_REG_IR 0x64 |
76 | #define ICH6_REG_IRS 0x68 | 76 | #define AZX_REG_IRS 0x68 |
77 | #define ICH6_IRS_VALID (1<<1) | 77 | #define AZX_IRS_VALID (1<<1) |
78 | #define ICH6_IRS_BUSY (1<<0) | 78 | #define AZX_IRS_BUSY (1<<0) |
79 | 79 | ||
80 | #define ICH6_REG_DPLBASE 0x70 | 80 | #define AZX_REG_DPLBASE 0x70 |
81 | #define ICH6_REG_DPUBASE 0x74 | 81 | #define AZX_REG_DPUBASE 0x74 |
82 | #define ICH6_DPLBASE_ENABLE 0x1 /* Enable position buffer */ | 82 | #define AZX_DPLBASE_ENABLE 0x1 /* Enable position buffer */ |
83 | 83 | ||
84 | /* SD offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ | 84 | /* SD offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ |
85 | enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | 85 | enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; |
86 | 86 | ||
87 | /* stream register offsets from stream base */ | 87 | /* stream register offsets from stream base */ |
88 | #define ICH6_REG_SD_CTL 0x00 | 88 | #define AZX_REG_SD_CTL 0x00 |
89 | #define ICH6_REG_SD_STS 0x03 | 89 | #define AZX_REG_SD_STS 0x03 |
90 | #define ICH6_REG_SD_LPIB 0x04 | 90 | #define AZX_REG_SD_LPIB 0x04 |
91 | #define ICH6_REG_SD_CBL 0x08 | 91 | #define AZX_REG_SD_CBL 0x08 |
92 | #define ICH6_REG_SD_LVI 0x0c | 92 | #define AZX_REG_SD_LVI 0x0c |
93 | #define ICH6_REG_SD_FIFOW 0x0e | 93 | #define AZX_REG_SD_FIFOW 0x0e |
94 | #define ICH6_REG_SD_FIFOSIZE 0x10 | 94 | #define AZX_REG_SD_FIFOSIZE 0x10 |
95 | #define ICH6_REG_SD_FORMAT 0x12 | 95 | #define AZX_REG_SD_FORMAT 0x12 |
96 | #define ICH6_REG_SD_BDLPL 0x18 | 96 | #define AZX_REG_SD_BDLPL 0x18 |
97 | #define ICH6_REG_SD_BDLPU 0x1c | 97 | #define AZX_REG_SD_BDLPU 0x1c |
98 | 98 | ||
99 | /* PCI space */ | 99 | /* PCI space */ |
100 | #define ICH6_PCIREG_TCSEL 0x44 | 100 | #define AZX_PCIREG_TCSEL 0x44 |
101 | 101 | ||
102 | /* | 102 | /* |
103 | * other constants | 103 | * other constants |
104 | */ | 104 | */ |
105 | 105 | ||
106 | /* max number of SDs */ | ||
107 | /* ICH, ATI and VIA have 4 playback and 4 capture */ | ||
108 | #define ICH6_NUM_CAPTURE 4 | ||
109 | #define ICH6_NUM_PLAYBACK 4 | ||
110 | |||
111 | /* ULI has 6 playback and 5 capture */ | ||
112 | #define ULI_NUM_CAPTURE 5 | ||
113 | #define ULI_NUM_PLAYBACK 6 | ||
114 | |||
115 | /* ATI HDMI may have up to 8 playbacks and 0 capture */ | ||
116 | #define ATIHDMI_NUM_CAPTURE 0 | ||
117 | #define ATIHDMI_NUM_PLAYBACK 8 | ||
118 | |||
119 | /* TERA has 4 playback and 3 capture */ | ||
120 | #define TERA_NUM_CAPTURE 3 | ||
121 | #define TERA_NUM_PLAYBACK 4 | ||
122 | |||
123 | /* this number is statically defined for simplicity */ | ||
124 | #define MAX_AZX_DEV 16 | ||
125 | |||
126 | /* max number of fragments - we may use more if allocating more pages for BDL */ | 106 | /* max number of fragments - we may use more if allocating more pages for BDL */ |
127 | #define BDL_SIZE 4096 | 107 | #define BDL_SIZE 4096 |
128 | #define AZX_MAX_BDL_ENTRIES (BDL_SIZE / 16) | 108 | #define AZX_MAX_BDL_ENTRIES (BDL_SIZE / 16) |
@@ -160,13 +140,13 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | |||
160 | #define SD_STS_FIFO_READY 0x20 /* FIFO ready */ | 140 | #define SD_STS_FIFO_READY 0x20 /* FIFO ready */ |
161 | 141 | ||
162 | /* INTCTL and INTSTS */ | 142 | /* INTCTL and INTSTS */ |
163 | #define ICH6_INT_ALL_STREAM 0xff /* all stream interrupts */ | 143 | #define AZX_INT_ALL_STREAM 0xff /* all stream interrupts */ |
164 | #define ICH6_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */ | 144 | #define AZX_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */ |
165 | #define ICH6_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */ | 145 | #define AZX_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */ |
166 | 146 | ||
167 | /* below are so far hardcoded - should read registers in future */ | 147 | /* below are so far hardcoded - should read registers in future */ |
168 | #define ICH6_MAX_CORB_ENTRIES 256 | 148 | #define AZX_MAX_CORB_ENTRIES 256 |
169 | #define ICH6_MAX_RIRB_ENTRIES 256 | 149 | #define AZX_MAX_RIRB_ENTRIES 256 |
170 | 150 | ||
171 | /* driver quirks (capabilities) */ | 151 | /* driver quirks (capabilities) */ |
172 | /* bits 0-7 are used for indicating driver type */ | 152 | /* bits 0-7 are used for indicating driver type */ |
@@ -192,35 +172,6 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | |||
192 | #define AZX_DCAPS_I915_POWERWELL (1 << 27) /* HSW i915 powerwell support */ | 172 | #define AZX_DCAPS_I915_POWERWELL (1 << 27) /* HSW i915 powerwell support */ |
193 | #define AZX_DCAPS_CORBRP_SELF_CLEAR (1 << 28) /* CORBRP clears itself after reset */ | 173 | #define AZX_DCAPS_CORBRP_SELF_CLEAR (1 << 28) /* CORBRP clears itself after reset */ |
194 | 174 | ||
195 | /* position fix mode */ | ||
196 | enum { | ||
197 | POS_FIX_AUTO, | ||
198 | POS_FIX_LPIB, | ||
199 | POS_FIX_POSBUF, | ||
200 | POS_FIX_VIACOMBO, | ||
201 | POS_FIX_COMBO, | ||
202 | }; | ||
203 | |||
204 | /* Defines for ATI HD Audio support in SB450 south bridge */ | ||
205 | #define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR 0x42 | ||
206 | #define ATI_SB450_HDAUDIO_ENABLE_SNOOP 0x02 | ||
207 | |||
208 | /* Defines for Nvidia HDA support */ | ||
209 | #define NVIDIA_HDA_TRANSREG_ADDR 0x4e | ||
210 | #define NVIDIA_HDA_ENABLE_COHBITS 0x0f | ||
211 | #define NVIDIA_HDA_ISTRM_COH 0x4d | ||
212 | #define NVIDIA_HDA_OSTRM_COH 0x4c | ||
213 | #define NVIDIA_HDA_ENABLE_COHBIT 0x01 | ||
214 | |||
215 | /* Defines for Intel SCH HDA snoop control */ | ||
216 | #define INTEL_SCH_HDA_DEVC 0x78 | ||
217 | #define INTEL_SCH_HDA_DEVC_NOSNOOP (0x1<<11) | ||
218 | |||
219 | /* Define IN stream 0 FIFO size offset in VIA controller */ | ||
220 | #define VIA_IN_STREAM0_FIFO_SIZE_OFFSET 0x90 | ||
221 | /* Define VIA HD Audio Device ID*/ | ||
222 | #define VIA_HDAC_DEVICE_ID 0x3288 | ||
223 | |||
224 | /* HD Audio class code */ | 175 | /* HD Audio class code */ |
225 | #define PCI_CLASS_MULTIMEDIA_HD_AUDIO 0x0403 | 176 | #define PCI_CLASS_MULTIMEDIA_HD_AUDIO 0x0403 |
226 | 177 | ||
@@ -325,6 +276,9 @@ struct azx_pcm { | |||
325 | struct list_head list; | 276 | struct list_head list; |
326 | }; | 277 | }; |
327 | 278 | ||
279 | typedef unsigned int (*azx_get_pos_callback_t)(struct azx *, struct azx_dev *); | ||
280 | typedef int (*azx_get_delay_callback_t)(struct azx *, struct azx_dev *, unsigned int pos); | ||
281 | |||
328 | struct azx { | 282 | struct azx { |
329 | struct snd_card *card; | 283 | struct snd_card *card; |
330 | struct pci_dev *pci; | 284 | struct pci_dev *pci; |
@@ -343,6 +297,10 @@ struct azx { | |||
343 | /* Register interaction. */ | 297 | /* Register interaction. */ |
344 | const struct hda_controller_ops *ops; | 298 | const struct hda_controller_ops *ops; |
345 | 299 | ||
300 | /* position adjustment callbacks */ | ||
301 | azx_get_pos_callback_t get_position[2]; | ||
302 | azx_get_delay_callback_t get_delay[2]; | ||
303 | |||
346 | /* pci resources */ | 304 | /* pci resources */ |
347 | unsigned long addr; | 305 | unsigned long addr; |
348 | void __iomem *remap_addr; | 306 | void __iomem *remap_addr; |
@@ -351,7 +309,6 @@ struct azx { | |||
351 | /* locks */ | 309 | /* locks */ |
352 | spinlock_t reg_lock; | 310 | spinlock_t reg_lock; |
353 | struct mutex open_mutex; /* Prevents concurrent open/close operations */ | 311 | struct mutex open_mutex; /* Prevents concurrent open/close operations */ |
354 | struct completion probe_wait; | ||
355 | 312 | ||
356 | /* streams (x num_streams) */ | 313 | /* streams (x num_streams) */ |
357 | struct azx_dev *azx_dev; | 314 | struct azx_dev *azx_dev; |
@@ -378,7 +335,6 @@ struct azx { | |||
378 | #endif | 335 | #endif |
379 | 336 | ||
380 | /* flags */ | 337 | /* flags */ |
381 | int position_fix[2]; /* for both playback/capture streams */ | ||
382 | const int *bdl_pos_adj; | 338 | const int *bdl_pos_adj; |
383 | int poll_count; | 339 | int poll_count; |
384 | unsigned int running:1; | 340 | unsigned int running:1; |
@@ -386,46 +342,23 @@ struct azx { | |||
386 | unsigned int single_cmd:1; | 342 | unsigned int single_cmd:1; |
387 | unsigned int polling_mode:1; | 343 | unsigned int polling_mode:1; |
388 | unsigned int msi:1; | 344 | unsigned int msi:1; |
389 | unsigned int irq_pending_warned:1; | ||
390 | unsigned int probing:1; /* codec probing phase */ | 345 | unsigned int probing:1; /* codec probing phase */ |
391 | unsigned int snoop:1; | 346 | unsigned int snoop:1; |
392 | unsigned int align_buffer_size:1; | 347 | unsigned int align_buffer_size:1; |
393 | unsigned int region_requested:1; | 348 | unsigned int region_requested:1; |
394 | |||
395 | /* VGA-switcheroo setup */ | ||
396 | unsigned int use_vga_switcheroo:1; | ||
397 | unsigned int vga_switcheroo_registered:1; | ||
398 | unsigned int init_failed:1; /* delayed init failed */ | ||
399 | unsigned int disabled:1; /* disabled by VGA-switcher */ | 349 | unsigned int disabled:1; /* disabled by VGA-switcher */ |
400 | 350 | ||
401 | /* for debugging */ | 351 | /* for debugging */ |
402 | unsigned int last_cmd[AZX_MAX_CODECS]; | 352 | unsigned int last_cmd[AZX_MAX_CODECS]; |
403 | 353 | ||
404 | /* for pending irqs */ | ||
405 | struct work_struct irq_pending_work; | ||
406 | |||
407 | struct work_struct probe_work; | ||
408 | |||
409 | /* reboot notifier (for mysterious hangup problem at power-down) */ | 354 | /* reboot notifier (for mysterious hangup problem at power-down) */ |
410 | struct notifier_block reboot_notifier; | 355 | struct notifier_block reboot_notifier; |
411 | 356 | ||
412 | /* card list (for power_save trigger) */ | ||
413 | struct list_head list; | ||
414 | |||
415 | #ifdef CONFIG_SND_HDA_DSP_LOADER | 357 | #ifdef CONFIG_SND_HDA_DSP_LOADER |
416 | struct azx_dev saved_azx_dev; | 358 | struct azx_dev saved_azx_dev; |
417 | #endif | 359 | #endif |
418 | |||
419 | /* secondary power domain for hdmi audio under vga device */ | ||
420 | struct dev_pm_domain hdmi_pm_domain; | ||
421 | }; | 360 | }; |
422 | 361 | ||
423 | #ifdef CONFIG_SND_VERBOSE_PRINTK | ||
424 | #define SFX /* nop */ | ||
425 | #else | ||
426 | #define SFX "hda-intel " | ||
427 | #endif | ||
428 | |||
429 | #ifdef CONFIG_X86 | 362 | #ifdef CONFIG_X86 |
430 | #define azx_snoop(chip) ((chip)->snoop) | 363 | #define azx_snoop(chip) ((chip)->snoop) |
431 | #else | 364 | #else |
@@ -437,29 +370,29 @@ struct azx { | |||
437 | */ | 370 | */ |
438 | 371 | ||
439 | #define azx_writel(chip, reg, value) \ | 372 | #define azx_writel(chip, reg, value) \ |
440 | ((chip)->ops->reg_writel(value, (chip)->remap_addr + ICH6_REG_##reg)) | 373 | ((chip)->ops->reg_writel(value, (chip)->remap_addr + AZX_REG_##reg)) |
441 | #define azx_readl(chip, reg) \ | 374 | #define azx_readl(chip, reg) \ |
442 | ((chip)->ops->reg_readl((chip)->remap_addr + ICH6_REG_##reg)) | 375 | ((chip)->ops->reg_readl((chip)->remap_addr + AZX_REG_##reg)) |
443 | #define azx_writew(chip, reg, value) \ | 376 | #define azx_writew(chip, reg, value) \ |
444 | ((chip)->ops->reg_writew(value, (chip)->remap_addr + ICH6_REG_##reg)) | 377 | ((chip)->ops->reg_writew(value, (chip)->remap_addr + AZX_REG_##reg)) |
445 | #define azx_readw(chip, reg) \ | 378 | #define azx_readw(chip, reg) \ |
446 | ((chip)->ops->reg_readw((chip)->remap_addr + ICH6_REG_##reg)) | 379 | ((chip)->ops->reg_readw((chip)->remap_addr + AZX_REG_##reg)) |
447 | #define azx_writeb(chip, reg, value) \ | 380 | #define azx_writeb(chip, reg, value) \ |
448 | ((chip)->ops->reg_writeb(value, (chip)->remap_addr + ICH6_REG_##reg)) | 381 | ((chip)->ops->reg_writeb(value, (chip)->remap_addr + AZX_REG_##reg)) |
449 | #define azx_readb(chip, reg) \ | 382 | #define azx_readb(chip, reg) \ |
450 | ((chip)->ops->reg_readb((chip)->remap_addr + ICH6_REG_##reg)) | 383 | ((chip)->ops->reg_readb((chip)->remap_addr + AZX_REG_##reg)) |
451 | 384 | ||
452 | #define azx_sd_writel(chip, dev, reg, value) \ | 385 | #define azx_sd_writel(chip, dev, reg, value) \ |
453 | ((chip)->ops->reg_writel(value, (dev)->sd_addr + ICH6_REG_##reg)) | 386 | ((chip)->ops->reg_writel(value, (dev)->sd_addr + AZX_REG_##reg)) |
454 | #define azx_sd_readl(chip, dev, reg) \ | 387 | #define azx_sd_readl(chip, dev, reg) \ |
455 | ((chip)->ops->reg_readl((dev)->sd_addr + ICH6_REG_##reg)) | 388 | ((chip)->ops->reg_readl((dev)->sd_addr + AZX_REG_##reg)) |
456 | #define azx_sd_writew(chip, dev, reg, value) \ | 389 | #define azx_sd_writew(chip, dev, reg, value) \ |
457 | ((chip)->ops->reg_writew(value, (dev)->sd_addr + ICH6_REG_##reg)) | 390 | ((chip)->ops->reg_writew(value, (dev)->sd_addr + AZX_REG_##reg)) |
458 | #define azx_sd_readw(chip, dev, reg) \ | 391 | #define azx_sd_readw(chip, dev, reg) \ |
459 | ((chip)->ops->reg_readw((dev)->sd_addr + ICH6_REG_##reg)) | 392 | ((chip)->ops->reg_readw((dev)->sd_addr + AZX_REG_##reg)) |
460 | #define azx_sd_writeb(chip, dev, reg, value) \ | 393 | #define azx_sd_writeb(chip, dev, reg, value) \ |
461 | ((chip)->ops->reg_writeb(value, (dev)->sd_addr + ICH6_REG_##reg)) | 394 | ((chip)->ops->reg_writeb(value, (dev)->sd_addr + AZX_REG_##reg)) |
462 | #define azx_sd_readb(chip, dev, reg) \ | 395 | #define azx_sd_readb(chip, dev, reg) \ |
463 | ((chip)->ops->reg_readb((dev)->sd_addr + ICH6_REG_##reg)) | 396 | ((chip)->ops->reg_readb((dev)->sd_addr + AZX_REG_##reg)) |
464 | 397 | ||
465 | #endif /* __SOUND_HDA_PRIV_H */ | 398 | #endif /* __SOUND_HDA_PRIV_H */ |
diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c index 358414da6418..227990bc02e3 100644 --- a/sound/pci/hda/hda_tegra.c +++ b/sound/pci/hda/hda_tegra.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include <linux/moduleparam.h> | 29 | #include <linux/moduleparam.h> |
30 | #include <linux/mutex.h> | 30 | #include <linux/mutex.h> |
31 | #include <linux/of_device.h> | 31 | #include <linux/of_device.h> |
32 | #include <linux/reboot.h> | ||
33 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
34 | #include <linux/time.h> | 33 | #include <linux/time.h> |
35 | 34 | ||
@@ -272,13 +271,9 @@ static int hda_tegra_resume(struct device *dev) | |||
272 | struct snd_card *card = dev_get_drvdata(dev); | 271 | struct snd_card *card = dev_get_drvdata(dev); |
273 | struct azx *chip = card->private_data; | 272 | struct azx *chip = card->private_data; |
274 | struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip); | 273 | struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip); |
275 | int status; | ||
276 | 274 | ||
277 | hda_tegra_enable_clocks(hda); | 275 | hda_tegra_enable_clocks(hda); |
278 | 276 | ||
279 | /* Read STATESTS before controller reset */ | ||
280 | status = azx_readw(chip, STATESTS); | ||
281 | |||
282 | hda_tegra_init(hda); | 277 | hda_tegra_init(hda); |
283 | 278 | ||
284 | azx_init_chip(chip, 1); | 279 | azx_init_chip(chip, 1); |
@@ -295,30 +290,6 @@ static const struct dev_pm_ops hda_tegra_pm = { | |||
295 | }; | 290 | }; |
296 | 291 | ||
297 | /* | 292 | /* |
298 | * reboot notifier for hang-up problem at power-down | ||
299 | */ | ||
300 | static int hda_tegra_halt(struct notifier_block *nb, unsigned long event, | ||
301 | void *buf) | ||
302 | { | ||
303 | struct azx *chip = container_of(nb, struct azx, reboot_notifier); | ||
304 | snd_hda_bus_reboot_notify(chip->bus); | ||
305 | azx_stop_chip(chip); | ||
306 | return NOTIFY_OK; | ||
307 | } | ||
308 | |||
309 | static void hda_tegra_notifier_register(struct azx *chip) | ||
310 | { | ||
311 | chip->reboot_notifier.notifier_call = hda_tegra_halt; | ||
312 | register_reboot_notifier(&chip->reboot_notifier); | ||
313 | } | ||
314 | |||
315 | static void hda_tegra_notifier_unregister(struct azx *chip) | ||
316 | { | ||
317 | if (chip->reboot_notifier.notifier_call) | ||
318 | unregister_reboot_notifier(&chip->reboot_notifier); | ||
319 | } | ||
320 | |||
321 | /* | ||
322 | * destructor | 293 | * destructor |
323 | */ | 294 | */ |
324 | static int hda_tegra_dev_free(struct snd_device *device) | 295 | static int hda_tegra_dev_free(struct snd_device *device) |
@@ -326,7 +297,7 @@ static int hda_tegra_dev_free(struct snd_device *device) | |||
326 | int i; | 297 | int i; |
327 | struct azx *chip = device->device_data; | 298 | struct azx *chip = device->device_data; |
328 | 299 | ||
329 | hda_tegra_notifier_unregister(chip); | 300 | azx_notifier_unregister(chip); |
330 | 301 | ||
331 | if (chip->initialized) { | 302 | if (chip->initialized) { |
332 | for (i = 0; i < chip->num_streams; i++) | 303 | for (i = 0; i < chip->num_streams; i++) |
@@ -478,10 +449,7 @@ static int hda_tegra_create(struct snd_card *card, | |||
478 | chip->driver_type = driver_caps & 0xff; | 449 | chip->driver_type = driver_caps & 0xff; |
479 | chip->dev_index = 0; | 450 | chip->dev_index = 0; |
480 | INIT_LIST_HEAD(&chip->pcm_list); | 451 | INIT_LIST_HEAD(&chip->pcm_list); |
481 | INIT_LIST_HEAD(&chip->list); | ||
482 | 452 | ||
483 | chip->position_fix[0] = POS_FIX_AUTO; | ||
484 | chip->position_fix[1] = POS_FIX_AUTO; | ||
485 | chip->codec_probe_mask = -1; | 453 | chip->codec_probe_mask = -1; |
486 | 454 | ||
487 | chip->single_cmd = false; | 455 | chip->single_cmd = false; |
@@ -559,7 +527,7 @@ static int hda_tegra_probe(struct platform_device *pdev) | |||
559 | 527 | ||
560 | chip->running = 1; | 528 | chip->running = 1; |
561 | power_down_all_codecs(chip); | 529 | power_down_all_codecs(chip); |
562 | hda_tegra_notifier_register(chip); | 530 | azx_notifier_register(chip); |
563 | 531 | ||
564 | return 0; | 532 | return 0; |
565 | 533 | ||
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 092f2bd030bd..4f3aba78f720 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c | |||
@@ -2046,14 +2046,14 @@ enum dma_state { | |||
2046 | DMA_STATE_RUN = 1 | 2046 | DMA_STATE_RUN = 1 |
2047 | }; | 2047 | }; |
2048 | 2048 | ||
2049 | static int dma_convert_to_hda_format( | 2049 | static int dma_convert_to_hda_format(struct hda_codec *codec, |
2050 | unsigned int sample_rate, | 2050 | unsigned int sample_rate, |
2051 | unsigned short channels, | 2051 | unsigned short channels, |
2052 | unsigned short *hda_format) | 2052 | unsigned short *hda_format) |
2053 | { | 2053 | { |
2054 | unsigned int format_val; | 2054 | unsigned int format_val; |
2055 | 2055 | ||
2056 | format_val = snd_hda_calc_stream_format( | 2056 | format_val = snd_hda_calc_stream_format(codec, |
2057 | sample_rate, | 2057 | sample_rate, |
2058 | channels, | 2058 | channels, |
2059 | SNDRV_PCM_FORMAT_S32_LE, | 2059 | SNDRV_PCM_FORMAT_S32_LE, |
@@ -2452,7 +2452,7 @@ static int dspxfr_image(struct hda_codec *codec, | |||
2452 | } | 2452 | } |
2453 | 2453 | ||
2454 | dma_engine->codec = codec; | 2454 | dma_engine->codec = codec; |
2455 | dma_convert_to_hda_format(sample_rate, channels, &hda_format); | 2455 | dma_convert_to_hda_format(codec, sample_rate, channels, &hda_format); |
2456 | dma_engine->m_converter_format = hda_format; | 2456 | dma_engine->m_converter_format = hda_format; |
2457 | dma_engine->buf_size = (ovly ? DSP_DMA_WRITE_BUFLEN_OVLY : | 2457 | dma_engine->buf_size = (ovly ? DSP_DMA_WRITE_BUFLEN_OVLY : |
2458 | DSP_DMA_WRITE_BUFLEN_INIT) * 2; | 2458 | DSP_DMA_WRITE_BUFLEN_INIT) * 2; |
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 387f0b551889..3db724eaa53c 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c | |||
@@ -657,8 +657,10 @@ static void cs4208_fixup_mac(struct hda_codec *codec, | |||
657 | { | 657 | { |
658 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | 658 | if (action != HDA_FIXUP_ACT_PRE_PROBE) |
659 | return; | 659 | return; |
660 | |||
661 | codec->fixup_id = HDA_FIXUP_ID_NOT_SET; | ||
660 | snd_hda_pick_fixup(codec, NULL, cs4208_mac_fixup_tbl, cs4208_fixups); | 662 | snd_hda_pick_fixup(codec, NULL, cs4208_mac_fixup_tbl, cs4208_fixups); |
661 | if (codec->fixup_id < 0 || codec->fixup_id == CS4208_MAC_AUTO) | 663 | if (codec->fixup_id == HDA_FIXUP_ID_NOT_SET) |
662 | codec->fixup_id = CS4208_GPIO0; /* default fixup */ | 664 | codec->fixup_id = CS4208_GPIO0; /* default fixup */ |
663 | snd_hda_apply_fixup(codec, action); | 665 | snd_hda_apply_fixup(codec, action); |
664 | } | 666 | } |
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c index 061ea5965dd5..ed3d133ffbb6 100644 --- a/sound/pci/hda/patch_cmedia.c +++ b/sound/pci/hda/patch_cmedia.c | |||
@@ -31,550 +31,11 @@ | |||
31 | #include "hda_jack.h" | 31 | #include "hda_jack.h" |
32 | #include "hda_generic.h" | 32 | #include "hda_generic.h" |
33 | 33 | ||
34 | #undef ENABLE_CMI_STATIC_QUIRKS | ||
35 | |||
36 | #ifdef ENABLE_CMI_STATIC_QUIRKS | ||
37 | #define NUM_PINS 11 | ||
38 | |||
39 | |||
40 | /* board config type */ | ||
41 | enum { | ||
42 | CMI_MINIMAL, /* back 3-jack */ | ||
43 | CMI_MIN_FP, /* back 3-jack + front-panel 2-jack */ | ||
44 | CMI_FULL, /* back 6-jack + front-panel 2-jack */ | ||
45 | CMI_FULL_DIG, /* back 6-jack + front-panel 2-jack + digital I/O */ | ||
46 | CMI_ALLOUT, /* back 5-jack + front-panel 2-jack + digital out */ | ||
47 | CMI_AUTO, /* let driver guess it */ | ||
48 | CMI_MODELS | ||
49 | }; | ||
50 | #endif /* ENABLE_CMI_STATIC_QUIRKS */ | ||
51 | |||
52 | struct cmi_spec { | 34 | struct cmi_spec { |
53 | struct hda_gen_spec gen; | 35 | struct hda_gen_spec gen; |
54 | |||
55 | #ifdef ENABLE_CMI_STATIC_QUIRKS | ||
56 | /* below are only for static models */ | ||
57 | |||
58 | int board_config; | ||
59 | unsigned int no_line_in: 1; /* no line-in (5-jack) */ | ||
60 | unsigned int front_panel: 1; /* has front-panel 2-jack */ | ||
61 | |||
62 | /* playback */ | ||
63 | struct hda_multi_out multiout; | ||
64 | hda_nid_t dac_nids[AUTO_CFG_MAX_OUTS]; /* NID for each DAC */ | ||
65 | int num_dacs; | ||
66 | |||
67 | /* capture */ | ||
68 | const hda_nid_t *adc_nids; | ||
69 | hda_nid_t dig_in_nid; | ||
70 | |||
71 | /* capture source */ | ||
72 | const struct hda_input_mux *input_mux; | ||
73 | unsigned int cur_mux[2]; | ||
74 | |||
75 | /* channel mode */ | ||
76 | int num_channel_modes; | ||
77 | const struct hda_channel_mode *channel_modes; | ||
78 | |||
79 | struct hda_pcm pcm_rec[2]; /* PCM information */ | ||
80 | |||
81 | /* pin default configuration */ | ||
82 | hda_nid_t pin_nid[NUM_PINS]; | ||
83 | unsigned int def_conf[NUM_PINS]; | ||
84 | unsigned int pin_def_confs; | ||
85 | |||
86 | /* multichannel pins */ | ||
87 | struct hda_verb multi_init[9]; /* 2 verbs for each pin + terminator */ | ||
88 | #endif /* ENABLE_CMI_STATIC_QUIRKS */ | ||
89 | }; | ||
90 | |||
91 | #ifdef ENABLE_CMI_STATIC_QUIRKS | ||
92 | /* | ||
93 | * input MUX | ||
94 | */ | ||
95 | static int cmi_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | ||
96 | { | ||
97 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
98 | struct cmi_spec *spec = codec->spec; | ||
99 | return snd_hda_input_mux_info(spec->input_mux, uinfo); | ||
100 | } | ||
101 | |||
102 | static int cmi_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
103 | { | ||
104 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
105 | struct cmi_spec *spec = codec->spec; | ||
106 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
107 | |||
108 | ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx]; | ||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | static int cmi_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
113 | { | ||
114 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
115 | struct cmi_spec *spec = codec->spec; | ||
116 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
117 | |||
118 | return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, | ||
119 | spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]); | ||
120 | } | ||
121 | |||
122 | /* | ||
123 | * shared line-in, mic for surrounds | ||
124 | */ | ||
125 | |||
126 | /* 3-stack / 2 channel */ | ||
127 | static const struct hda_verb cmi9880_ch2_init[] = { | ||
128 | /* set line-in PIN for input */ | ||
129 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
130 | /* set mic PIN for input, also enable vref */ | ||
131 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
132 | /* route front PCM (DAC1) to HP */ | ||
133 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, | ||
134 | {} | ||
135 | }; | ||
136 | |||
137 | /* 3-stack / 6 channel */ | ||
138 | static const struct hda_verb cmi9880_ch6_init[] = { | ||
139 | /* set line-in PIN for output */ | ||
140 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
141 | /* set mic PIN for output */ | ||
142 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
143 | /* route front PCM (DAC1) to HP */ | ||
144 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, | ||
145 | {} | ||
146 | }; | ||
147 | |||
148 | /* 3-stack+front / 8 channel */ | ||
149 | static const struct hda_verb cmi9880_ch8_init[] = { | ||
150 | /* set line-in PIN for output */ | ||
151 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
152 | /* set mic PIN for output */ | ||
153 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
154 | /* route rear-surround PCM (DAC4) to HP */ | ||
155 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x03 }, | ||
156 | {} | ||
157 | }; | ||
158 | |||
159 | static const struct hda_channel_mode cmi9880_channel_modes[3] = { | ||
160 | { 2, cmi9880_ch2_init }, | ||
161 | { 6, cmi9880_ch6_init }, | ||
162 | { 8, cmi9880_ch8_init }, | ||
163 | }; | ||
164 | |||
165 | static int cmi_ch_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | ||
166 | { | ||
167 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
168 | struct cmi_spec *spec = codec->spec; | ||
169 | return snd_hda_ch_mode_info(codec, uinfo, spec->channel_modes, | ||
170 | spec->num_channel_modes); | ||
171 | } | ||
172 | |||
173 | static int cmi_ch_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
174 | { | ||
175 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
176 | struct cmi_spec *spec = codec->spec; | ||
177 | return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_modes, | ||
178 | spec->num_channel_modes, spec->multiout.max_channels); | ||
179 | } | ||
180 | |||
181 | static int cmi_ch_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
182 | { | ||
183 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
184 | struct cmi_spec *spec = codec->spec; | ||
185 | return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_modes, | ||
186 | spec->num_channel_modes, &spec->multiout.max_channels); | ||
187 | } | ||
188 | |||
189 | /* | ||
190 | */ | ||
191 | static const struct snd_kcontrol_new cmi9880_basic_mixer[] = { | ||
192 | /* CMI9880 has no playback volumes! */ | ||
193 | HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), /* front */ | ||
194 | HDA_CODEC_MUTE("Surround Playback Switch", 0x04, 0x0, HDA_OUTPUT), | ||
195 | HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT), | ||
196 | HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT), | ||
197 | HDA_CODEC_MUTE("Side Playback Switch", 0x06, 0x0, HDA_OUTPUT), | ||
198 | { | ||
199 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
200 | /* The multiple "Capture Source" controls confuse alsamixer | ||
201 | * So call somewhat different.. | ||
202 | */ | ||
203 | /* .name = "Capture Source", */ | ||
204 | .name = "Input Source", | ||
205 | .count = 2, | ||
206 | .info = cmi_mux_enum_info, | ||
207 | .get = cmi_mux_enum_get, | ||
208 | .put = cmi_mux_enum_put, | ||
209 | }, | ||
210 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0, HDA_INPUT), | ||
211 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0, HDA_INPUT), | ||
212 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0, HDA_INPUT), | ||
213 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0, HDA_INPUT), | ||
214 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x23, 0, HDA_OUTPUT), | ||
215 | HDA_CODEC_MUTE("Beep Playback Switch", 0x23, 0, HDA_OUTPUT), | ||
216 | { } /* end */ | ||
217 | }; | 36 | }; |
218 | 37 | ||
219 | /* | 38 | /* |
220 | * shared I/O pins | ||
221 | */ | ||
222 | static const struct snd_kcontrol_new cmi9880_ch_mode_mixer[] = { | ||
223 | { | ||
224 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
225 | .name = "Channel Mode", | ||
226 | .info = cmi_ch_mode_info, | ||
227 | .get = cmi_ch_mode_get, | ||
228 | .put = cmi_ch_mode_put, | ||
229 | }, | ||
230 | { } /* end */ | ||
231 | }; | ||
232 | |||
233 | /* AUD-in selections: | ||
234 | * 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x1f 0x20 | ||
235 | */ | ||
236 | static const struct hda_input_mux cmi9880_basic_mux = { | ||
237 | .num_items = 4, | ||
238 | .items = { | ||
239 | { "Front Mic", 0x5 }, | ||
240 | { "Rear Mic", 0x2 }, | ||
241 | { "Line", 0x1 }, | ||
242 | { "CD", 0x7 }, | ||
243 | } | ||
244 | }; | ||
245 | |||
246 | static const struct hda_input_mux cmi9880_no_line_mux = { | ||
247 | .num_items = 3, | ||
248 | .items = { | ||
249 | { "Front Mic", 0x5 }, | ||
250 | { "Rear Mic", 0x2 }, | ||
251 | { "CD", 0x7 }, | ||
252 | } | ||
253 | }; | ||
254 | |||
255 | /* front, rear, clfe, rear_surr */ | ||
256 | static const hda_nid_t cmi9880_dac_nids[4] = { | ||
257 | 0x03, 0x04, 0x05, 0x06 | ||
258 | }; | ||
259 | /* ADC0, ADC1 */ | ||
260 | static const hda_nid_t cmi9880_adc_nids[2] = { | ||
261 | 0x08, 0x09 | ||
262 | }; | ||
263 | |||
264 | #define CMI_DIG_OUT_NID 0x07 | ||
265 | #define CMI_DIG_IN_NID 0x0a | ||
266 | |||
267 | /* | ||
268 | */ | ||
269 | static const struct hda_verb cmi9880_basic_init[] = { | ||
270 | /* port-D for line out (rear panel) */ | ||
271 | { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
272 | /* port-E for HP out (front panel) */ | ||
273 | { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
274 | /* route front PCM to HP */ | ||
275 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, | ||
276 | /* port-A for surround (rear panel) */ | ||
277 | { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
278 | /* port-G for CLFE (rear panel) */ | ||
279 | { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
280 | { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 }, | ||
281 | /* port-H for side (rear panel) */ | ||
282 | { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
283 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 }, | ||
284 | /* port-C for line-in (rear panel) */ | ||
285 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
286 | /* port-B for mic-in (rear panel) with vref */ | ||
287 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
288 | /* port-F for mic-in (front panel) with vref */ | ||
289 | { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
290 | /* CD-in */ | ||
291 | { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
292 | /* route front mic to ADC1/2 */ | ||
293 | { 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 }, | ||
294 | { 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 }, | ||
295 | {} /* terminator */ | ||
296 | }; | ||
297 | |||
298 | static const struct hda_verb cmi9880_allout_init[] = { | ||
299 | /* port-D for line out (rear panel) */ | ||
300 | { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
301 | /* port-E for HP out (front panel) */ | ||
302 | { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
303 | /* route front PCM to HP */ | ||
304 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, | ||
305 | /* port-A for side (rear panel) */ | ||
306 | { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
307 | /* port-G for CLFE (rear panel) */ | ||
308 | { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
309 | { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 }, | ||
310 | /* port-H for side (rear panel) */ | ||
311 | { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
312 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 }, | ||
313 | /* port-C for surround (rear panel) */ | ||
314 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
315 | /* port-B for mic-in (rear panel) with vref */ | ||
316 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
317 | /* port-F for mic-in (front panel) with vref */ | ||
318 | { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
319 | /* CD-in */ | ||
320 | { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
321 | /* route front mic to ADC1/2 */ | ||
322 | { 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 }, | ||
323 | { 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 }, | ||
324 | {} /* terminator */ | ||
325 | }; | ||
326 | |||
327 | /* | ||
328 | */ | ||
329 | static int cmi9880_build_controls(struct hda_codec *codec) | ||
330 | { | ||
331 | struct cmi_spec *spec = codec->spec; | ||
332 | struct snd_kcontrol *kctl; | ||
333 | int i, err; | ||
334 | |||
335 | err = snd_hda_add_new_ctls(codec, cmi9880_basic_mixer); | ||
336 | if (err < 0) | ||
337 | return err; | ||
338 | if (spec->channel_modes) { | ||
339 | err = snd_hda_add_new_ctls(codec, cmi9880_ch_mode_mixer); | ||
340 | if (err < 0) | ||
341 | return err; | ||
342 | } | ||
343 | if (spec->multiout.dig_out_nid) { | ||
344 | err = snd_hda_create_spdif_out_ctls(codec, | ||
345 | spec->multiout.dig_out_nid, | ||
346 | spec->multiout.dig_out_nid); | ||
347 | if (err < 0) | ||
348 | return err; | ||
349 | err = snd_hda_create_spdif_share_sw(codec, | ||
350 | &spec->multiout); | ||
351 | if (err < 0) | ||
352 | return err; | ||
353 | spec->multiout.share_spdif = 1; | ||
354 | } | ||
355 | if (spec->dig_in_nid) { | ||
356 | err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); | ||
357 | if (err < 0) | ||
358 | return err; | ||
359 | } | ||
360 | |||
361 | /* assign Capture Source enums to NID */ | ||
362 | kctl = snd_hda_find_mixer_ctl(codec, "Capture Source"); | ||
363 | for (i = 0; kctl && i < kctl->count; i++) { | ||
364 | err = snd_hda_add_nid(codec, kctl, i, spec->adc_nids[i]); | ||
365 | if (err < 0) | ||
366 | return err; | ||
367 | } | ||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | static int cmi9880_init(struct hda_codec *codec) | ||
372 | { | ||
373 | struct cmi_spec *spec = codec->spec; | ||
374 | if (spec->board_config == CMI_ALLOUT) | ||
375 | snd_hda_sequence_write(codec, cmi9880_allout_init); | ||
376 | else | ||
377 | snd_hda_sequence_write(codec, cmi9880_basic_init); | ||
378 | if (spec->board_config == CMI_AUTO) | ||
379 | snd_hda_sequence_write(codec, spec->multi_init); | ||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | /* | ||
384 | * Analog playback callbacks | ||
385 | */ | ||
386 | static int cmi9880_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
387 | struct hda_codec *codec, | ||
388 | struct snd_pcm_substream *substream) | ||
389 | { | ||
390 | struct cmi_spec *spec = codec->spec; | ||
391 | return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, | ||
392 | hinfo); | ||
393 | } | ||
394 | |||
395 | static int cmi9880_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
396 | struct hda_codec *codec, | ||
397 | unsigned int stream_tag, | ||
398 | unsigned int format, | ||
399 | struct snd_pcm_substream *substream) | ||
400 | { | ||
401 | struct cmi_spec *spec = codec->spec; | ||
402 | return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag, | ||
403 | format, substream); | ||
404 | } | ||
405 | |||
406 | static int cmi9880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
407 | struct hda_codec *codec, | ||
408 | struct snd_pcm_substream *substream) | ||
409 | { | ||
410 | struct cmi_spec *spec = codec->spec; | ||
411 | return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); | ||
412 | } | ||
413 | |||
414 | /* | ||
415 | * Digital out | ||
416 | */ | ||
417 | static int cmi9880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
418 | struct hda_codec *codec, | ||
419 | struct snd_pcm_substream *substream) | ||
420 | { | ||
421 | struct cmi_spec *spec = codec->spec; | ||
422 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | ||
423 | } | ||
424 | |||
425 | static int cmi9880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, | ||
426 | struct hda_codec *codec, | ||
427 | struct snd_pcm_substream *substream) | ||
428 | { | ||
429 | struct cmi_spec *spec = codec->spec; | ||
430 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | ||
431 | } | ||
432 | |||
433 | static int cmi9880_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
434 | struct hda_codec *codec, | ||
435 | unsigned int stream_tag, | ||
436 | unsigned int format, | ||
437 | struct snd_pcm_substream *substream) | ||
438 | { | ||
439 | struct cmi_spec *spec = codec->spec; | ||
440 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, | ||
441 | format, substream); | ||
442 | } | ||
443 | |||
444 | /* | ||
445 | * Analog capture | ||
446 | */ | ||
447 | static int cmi9880_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
448 | struct hda_codec *codec, | ||
449 | unsigned int stream_tag, | ||
450 | unsigned int format, | ||
451 | struct snd_pcm_substream *substream) | ||
452 | { | ||
453 | struct cmi_spec *spec = codec->spec; | ||
454 | |||
455 | snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], | ||
456 | stream_tag, 0, format); | ||
457 | return 0; | ||
458 | } | ||
459 | |||
460 | static int cmi9880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
461 | struct hda_codec *codec, | ||
462 | struct snd_pcm_substream *substream) | ||
463 | { | ||
464 | struct cmi_spec *spec = codec->spec; | ||
465 | |||
466 | snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]); | ||
467 | return 0; | ||
468 | } | ||
469 | |||
470 | |||
471 | /* | ||
472 | */ | ||
473 | static const struct hda_pcm_stream cmi9880_pcm_analog_playback = { | ||
474 | .substreams = 1, | ||
475 | .channels_min = 2, | ||
476 | .channels_max = 8, | ||
477 | .nid = 0x03, /* NID to query formats and rates */ | ||
478 | .ops = { | ||
479 | .open = cmi9880_playback_pcm_open, | ||
480 | .prepare = cmi9880_playback_pcm_prepare, | ||
481 | .cleanup = cmi9880_playback_pcm_cleanup | ||
482 | }, | ||
483 | }; | ||
484 | |||
485 | static const struct hda_pcm_stream cmi9880_pcm_analog_capture = { | ||
486 | .substreams = 2, | ||
487 | .channels_min = 2, | ||
488 | .channels_max = 2, | ||
489 | .nid = 0x08, /* NID to query formats and rates */ | ||
490 | .ops = { | ||
491 | .prepare = cmi9880_capture_pcm_prepare, | ||
492 | .cleanup = cmi9880_capture_pcm_cleanup | ||
493 | }, | ||
494 | }; | ||
495 | |||
496 | static const struct hda_pcm_stream cmi9880_pcm_digital_playback = { | ||
497 | .substreams = 1, | ||
498 | .channels_min = 2, | ||
499 | .channels_max = 2, | ||
500 | /* NID is set in cmi9880_build_pcms */ | ||
501 | .ops = { | ||
502 | .open = cmi9880_dig_playback_pcm_open, | ||
503 | .close = cmi9880_dig_playback_pcm_close, | ||
504 | .prepare = cmi9880_dig_playback_pcm_prepare | ||
505 | }, | ||
506 | }; | ||
507 | |||
508 | static const struct hda_pcm_stream cmi9880_pcm_digital_capture = { | ||
509 | .substreams = 1, | ||
510 | .channels_min = 2, | ||
511 | .channels_max = 2, | ||
512 | /* NID is set in cmi9880_build_pcms */ | ||
513 | }; | ||
514 | |||
515 | static int cmi9880_build_pcms(struct hda_codec *codec) | ||
516 | { | ||
517 | struct cmi_spec *spec = codec->spec; | ||
518 | struct hda_pcm *info = spec->pcm_rec; | ||
519 | |||
520 | codec->num_pcms = 1; | ||
521 | codec->pcm_info = info; | ||
522 | |||
523 | info->name = "CMI9880"; | ||
524 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cmi9880_pcm_analog_playback; | ||
525 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = cmi9880_pcm_analog_capture; | ||
526 | |||
527 | if (spec->multiout.dig_out_nid || spec->dig_in_nid) { | ||
528 | codec->num_pcms++; | ||
529 | info++; | ||
530 | info->name = "CMI9880 Digital"; | ||
531 | info->pcm_type = HDA_PCM_TYPE_SPDIF; | ||
532 | if (spec->multiout.dig_out_nid) { | ||
533 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cmi9880_pcm_digital_playback; | ||
534 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; | ||
535 | } | ||
536 | if (spec->dig_in_nid) { | ||
537 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = cmi9880_pcm_digital_capture; | ||
538 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid; | ||
539 | } | ||
540 | } | ||
541 | |||
542 | return 0; | ||
543 | } | ||
544 | |||
545 | static void cmi9880_free(struct hda_codec *codec) | ||
546 | { | ||
547 | kfree(codec->spec); | ||
548 | } | ||
549 | |||
550 | /* | ||
551 | */ | ||
552 | |||
553 | static const char * const cmi9880_models[CMI_MODELS] = { | ||
554 | [CMI_MINIMAL] = "minimal", | ||
555 | [CMI_MIN_FP] = "min_fp", | ||
556 | [CMI_FULL] = "full", | ||
557 | [CMI_FULL_DIG] = "full_dig", | ||
558 | [CMI_ALLOUT] = "allout", | ||
559 | [CMI_AUTO] = "auto", | ||
560 | }; | ||
561 | |||
562 | static const struct snd_pci_quirk cmi9880_cfg_tbl[] = { | ||
563 | SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", CMI_FULL_DIG), | ||
564 | SND_PCI_QUIRK(0x1854, 0x002b, "LG LS75", CMI_MINIMAL), | ||
565 | SND_PCI_QUIRK(0x1854, 0x0032, "LG", CMI_FULL_DIG), | ||
566 | {} /* terminator */ | ||
567 | }; | ||
568 | |||
569 | static const struct hda_codec_ops cmi9880_patch_ops = { | ||
570 | .build_controls = cmi9880_build_controls, | ||
571 | .build_pcms = cmi9880_build_pcms, | ||
572 | .init = cmi9880_init, | ||
573 | .free = cmi9880_free, | ||
574 | }; | ||
575 | #endif /* ENABLE_CMI_STATIC_QUIRKS */ | ||
576 | |||
577 | /* | ||
578 | * stuff for auto-parser | 39 | * stuff for auto-parser |
579 | */ | 40 | */ |
580 | static const struct hda_codec_ops cmi_auto_patch_ops = { | 41 | static const struct hda_codec_ops cmi_auto_patch_ops = { |
@@ -585,12 +46,18 @@ static const struct hda_codec_ops cmi_auto_patch_ops = { | |||
585 | .unsol_event = snd_hda_jack_unsol_event, | 46 | .unsol_event = snd_hda_jack_unsol_event, |
586 | }; | 47 | }; |
587 | 48 | ||
588 | static int cmi_parse_auto_config(struct hda_codec *codec) | 49 | static int patch_cmi9880(struct hda_codec *codec) |
589 | { | 50 | { |
590 | struct cmi_spec *spec = codec->spec; | 51 | struct cmi_spec *spec; |
591 | struct auto_pin_cfg *cfg = &spec->gen.autocfg; | 52 | struct auto_pin_cfg *cfg; |
592 | int err; | 53 | int err; |
593 | 54 | ||
55 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
56 | if (spec == NULL) | ||
57 | return -ENOMEM; | ||
58 | |||
59 | codec->spec = spec; | ||
60 | cfg = &spec->gen.autocfg; | ||
594 | snd_hda_gen_spec_init(&spec->gen); | 61 | snd_hda_gen_spec_init(&spec->gen); |
595 | 62 | ||
596 | err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0); | 63 | err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0); |
@@ -608,79 +75,6 @@ static int cmi_parse_auto_config(struct hda_codec *codec) | |||
608 | return err; | 75 | return err; |
609 | } | 76 | } |
610 | 77 | ||
611 | |||
612 | static int patch_cmi9880(struct hda_codec *codec) | ||
613 | { | ||
614 | struct cmi_spec *spec; | ||
615 | |||
616 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
617 | if (spec == NULL) | ||
618 | return -ENOMEM; | ||
619 | |||
620 | codec->spec = spec; | ||
621 | #ifdef ENABLE_CMI_STATIC_QUIRKS | ||
622 | spec->board_config = snd_hda_check_board_config(codec, CMI_MODELS, | ||
623 | cmi9880_models, | ||
624 | cmi9880_cfg_tbl); | ||
625 | if (spec->board_config < 0) { | ||
626 | codec_dbg(codec, "%s: BIOS auto-probing.\n", | ||
627 | codec->chip_name); | ||
628 | spec->board_config = CMI_AUTO; /* try everything */ | ||
629 | } | ||
630 | |||
631 | if (spec->board_config == CMI_AUTO) | ||
632 | return cmi_parse_auto_config(codec); | ||
633 | |||
634 | /* copy default DAC NIDs */ | ||
635 | memcpy(spec->dac_nids, cmi9880_dac_nids, sizeof(spec->dac_nids)); | ||
636 | spec->num_dacs = 4; | ||
637 | |||
638 | switch (spec->board_config) { | ||
639 | case CMI_MINIMAL: | ||
640 | case CMI_MIN_FP: | ||
641 | spec->channel_modes = cmi9880_channel_modes; | ||
642 | if (spec->board_config == CMI_MINIMAL) | ||
643 | spec->num_channel_modes = 2; | ||
644 | else { | ||
645 | spec->front_panel = 1; | ||
646 | spec->num_channel_modes = 3; | ||
647 | } | ||
648 | spec->multiout.max_channels = cmi9880_channel_modes[0].channels; | ||
649 | spec->input_mux = &cmi9880_basic_mux; | ||
650 | break; | ||
651 | case CMI_FULL: | ||
652 | case CMI_FULL_DIG: | ||
653 | spec->front_panel = 1; | ||
654 | spec->multiout.max_channels = 8; | ||
655 | spec->input_mux = &cmi9880_basic_mux; | ||
656 | if (spec->board_config == CMI_FULL_DIG) { | ||
657 | spec->multiout.dig_out_nid = CMI_DIG_OUT_NID; | ||
658 | spec->dig_in_nid = CMI_DIG_IN_NID; | ||
659 | } | ||
660 | break; | ||
661 | case CMI_ALLOUT: | ||
662 | default: | ||
663 | spec->front_panel = 1; | ||
664 | spec->multiout.max_channels = 8; | ||
665 | spec->no_line_in = 1; | ||
666 | spec->input_mux = &cmi9880_no_line_mux; | ||
667 | spec->multiout.dig_out_nid = CMI_DIG_OUT_NID; | ||
668 | break; | ||
669 | } | ||
670 | |||
671 | spec->multiout.num_dacs = spec->num_dacs; | ||
672 | spec->multiout.dac_nids = spec->dac_nids; | ||
673 | |||
674 | spec->adc_nids = cmi9880_adc_nids; | ||
675 | |||
676 | codec->patch_ops = cmi9880_patch_ops; | ||
677 | |||
678 | return 0; | ||
679 | #else | ||
680 | return cmi_parse_auto_config(codec); | ||
681 | #endif | ||
682 | } | ||
683 | |||
684 | /* | 78 | /* |
685 | * patch entries | 79 | * patch entries |
686 | */ | 80 | */ |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 1dc7e974f3b1..7627a69ca6d7 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -34,27 +34,6 @@ | |||
34 | #include "hda_jack.h" | 34 | #include "hda_jack.h" |
35 | #include "hda_generic.h" | 35 | #include "hda_generic.h" |
36 | 36 | ||
37 | #undef ENABLE_CXT_STATIC_QUIRKS | ||
38 | |||
39 | #define CXT_PIN_DIR_IN 0x00 | ||
40 | #define CXT_PIN_DIR_OUT 0x01 | ||
41 | #define CXT_PIN_DIR_INOUT 0x02 | ||
42 | #define CXT_PIN_DIR_IN_NOMICBIAS 0x03 | ||
43 | #define CXT_PIN_DIR_INOUT_NOMICBIAS 0x04 | ||
44 | |||
45 | #define CONEXANT_HP_EVENT 0x37 | ||
46 | #define CONEXANT_MIC_EVENT 0x38 | ||
47 | #define CONEXANT_LINE_EVENT 0x39 | ||
48 | |||
49 | /* Conexant 5051 specific */ | ||
50 | |||
51 | #define CXT5051_SPDIF_OUT 0x12 | ||
52 | #define CXT5051_PORTB_EVENT 0x38 | ||
53 | #define CXT5051_PORTC_EVENT 0x39 | ||
54 | |||
55 | #define AUTO_MIC_PORTB (1 << 1) | ||
56 | #define AUTO_MIC_PORTC (1 << 2) | ||
57 | |||
58 | struct conexant_spec { | 37 | struct conexant_spec { |
59 | struct hda_gen_spec gen; | 38 | struct hda_gen_spec gen; |
60 | 39 | ||
@@ -72,64 +51,6 @@ struct conexant_spec { | |||
72 | bool dc_enable; | 51 | bool dc_enable; |
73 | unsigned int dc_input_bias; /* offset into olpc_xo_dc_bias */ | 52 | unsigned int dc_input_bias; /* offset into olpc_xo_dc_bias */ |
74 | struct nid_path *dc_mode_path; | 53 | struct nid_path *dc_mode_path; |
75 | |||
76 | #ifdef ENABLE_CXT_STATIC_QUIRKS | ||
77 | const struct snd_kcontrol_new *mixers[5]; | ||
78 | int num_mixers; | ||
79 | hda_nid_t vmaster_nid; | ||
80 | |||
81 | const struct hda_verb *init_verbs[5]; /* initialization verbs | ||
82 | * don't forget NULL | ||
83 | * termination! | ||
84 | */ | ||
85 | unsigned int num_init_verbs; | ||
86 | |||
87 | /* playback */ | ||
88 | struct hda_multi_out multiout; /* playback set-up | ||
89 | * max_channels, dacs must be set | ||
90 | * dig_out_nid and hp_nid are optional | ||
91 | */ | ||
92 | unsigned int cur_eapd; | ||
93 | unsigned int hp_present; | ||
94 | unsigned int line_present; | ||
95 | unsigned int auto_mic; | ||
96 | |||
97 | /* capture */ | ||
98 | unsigned int num_adc_nids; | ||
99 | const hda_nid_t *adc_nids; | ||
100 | hda_nid_t dig_in_nid; /* digital-in NID; optional */ | ||
101 | |||
102 | unsigned int cur_adc_idx; | ||
103 | hda_nid_t cur_adc; | ||
104 | unsigned int cur_adc_stream_tag; | ||
105 | unsigned int cur_adc_format; | ||
106 | |||
107 | const struct hda_pcm_stream *capture_stream; | ||
108 | |||
109 | /* capture source */ | ||
110 | const struct hda_input_mux *input_mux; | ||
111 | const hda_nid_t *capsrc_nids; | ||
112 | unsigned int cur_mux[3]; | ||
113 | |||
114 | /* channel model */ | ||
115 | const struct hda_channel_mode *channel_mode; | ||
116 | int num_channel_mode; | ||
117 | |||
118 | /* PCM information */ | ||
119 | struct hda_pcm pcm_rec[2]; /* used in build_pcms() */ | ||
120 | |||
121 | unsigned int spdif_route; | ||
122 | |||
123 | unsigned int port_d_mode; | ||
124 | unsigned int dell_automute:1; | ||
125 | unsigned int dell_vostro:1; | ||
126 | unsigned int ideapad:1; | ||
127 | unsigned int thinkpad:1; | ||
128 | unsigned int hp_laptop:1; | ||
129 | unsigned int asus:1; | ||
130 | |||
131 | unsigned int mic_boost; /* offset into cxt5066_analog_mic_boost */ | ||
132 | #endif /* ENABLE_CXT_STATIC_QUIRKS */ | ||
133 | }; | 54 | }; |
134 | 55 | ||
135 | 56 | ||
@@ -173,2533 +94,6 @@ static int add_beep_ctls(struct hda_codec *codec) | |||
173 | #define add_beep_ctls(codec) 0 | 94 | #define add_beep_ctls(codec) 0 |
174 | #endif | 95 | #endif |
175 | 96 | ||
176 | |||
177 | #ifdef ENABLE_CXT_STATIC_QUIRKS | ||
178 | static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
179 | struct hda_codec *codec, | ||
180 | struct snd_pcm_substream *substream) | ||
181 | { | ||
182 | struct conexant_spec *spec = codec->spec; | ||
183 | return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, | ||
184 | hinfo); | ||
185 | } | ||
186 | |||
187 | static int conexant_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
188 | struct hda_codec *codec, | ||
189 | unsigned int stream_tag, | ||
190 | unsigned int format, | ||
191 | struct snd_pcm_substream *substream) | ||
192 | { | ||
193 | struct conexant_spec *spec = codec->spec; | ||
194 | return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, | ||
195 | stream_tag, | ||
196 | format, substream); | ||
197 | } | ||
198 | |||
199 | static int conexant_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
200 | struct hda_codec *codec, | ||
201 | struct snd_pcm_substream *substream) | ||
202 | { | ||
203 | struct conexant_spec *spec = codec->spec; | ||
204 | return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); | ||
205 | } | ||
206 | |||
207 | /* | ||
208 | * Digital out | ||
209 | */ | ||
210 | static int conexant_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
211 | struct hda_codec *codec, | ||
212 | struct snd_pcm_substream *substream) | ||
213 | { | ||
214 | struct conexant_spec *spec = codec->spec; | ||
215 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | ||
216 | } | ||
217 | |||
218 | static int conexant_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, | ||
219 | struct hda_codec *codec, | ||
220 | struct snd_pcm_substream *substream) | ||
221 | { | ||
222 | struct conexant_spec *spec = codec->spec; | ||
223 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | ||
224 | } | ||
225 | |||
226 | static int conexant_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
227 | struct hda_codec *codec, | ||
228 | unsigned int stream_tag, | ||
229 | unsigned int format, | ||
230 | struct snd_pcm_substream *substream) | ||
231 | { | ||
232 | struct conexant_spec *spec = codec->spec; | ||
233 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, | ||
234 | stream_tag, | ||
235 | format, substream); | ||
236 | } | ||
237 | |||
238 | /* | ||
239 | * Analog capture | ||
240 | */ | ||
241 | static int conexant_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
242 | struct hda_codec *codec, | ||
243 | unsigned int stream_tag, | ||
244 | unsigned int format, | ||
245 | struct snd_pcm_substream *substream) | ||
246 | { | ||
247 | struct conexant_spec *spec = codec->spec; | ||
248 | snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], | ||
249 | stream_tag, 0, format); | ||
250 | return 0; | ||
251 | } | ||
252 | |||
253 | static int conexant_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
254 | struct hda_codec *codec, | ||
255 | struct snd_pcm_substream *substream) | ||
256 | { | ||
257 | struct conexant_spec *spec = codec->spec; | ||
258 | snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]); | ||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | |||
263 | |||
264 | static const struct hda_pcm_stream conexant_pcm_analog_playback = { | ||
265 | .substreams = 1, | ||
266 | .channels_min = 2, | ||
267 | .channels_max = 2, | ||
268 | .nid = 0, /* fill later */ | ||
269 | .ops = { | ||
270 | .open = conexant_playback_pcm_open, | ||
271 | .prepare = conexant_playback_pcm_prepare, | ||
272 | .cleanup = conexant_playback_pcm_cleanup | ||
273 | }, | ||
274 | }; | ||
275 | |||
276 | static const struct hda_pcm_stream conexant_pcm_analog_capture = { | ||
277 | .substreams = 1, | ||
278 | .channels_min = 2, | ||
279 | .channels_max = 2, | ||
280 | .nid = 0, /* fill later */ | ||
281 | .ops = { | ||
282 | .prepare = conexant_capture_pcm_prepare, | ||
283 | .cleanup = conexant_capture_pcm_cleanup | ||
284 | }, | ||
285 | }; | ||
286 | |||
287 | |||
288 | static const struct hda_pcm_stream conexant_pcm_digital_playback = { | ||
289 | .substreams = 1, | ||
290 | .channels_min = 2, | ||
291 | .channels_max = 2, | ||
292 | .nid = 0, /* fill later */ | ||
293 | .ops = { | ||
294 | .open = conexant_dig_playback_pcm_open, | ||
295 | .close = conexant_dig_playback_pcm_close, | ||
296 | .prepare = conexant_dig_playback_pcm_prepare | ||
297 | }, | ||
298 | }; | ||
299 | |||
300 | static const struct hda_pcm_stream conexant_pcm_digital_capture = { | ||
301 | .substreams = 1, | ||
302 | .channels_min = 2, | ||
303 | .channels_max = 2, | ||
304 | /* NID is set in alc_build_pcms */ | ||
305 | }; | ||
306 | |||
307 | static int cx5051_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
308 | struct hda_codec *codec, | ||
309 | unsigned int stream_tag, | ||
310 | unsigned int format, | ||
311 | struct snd_pcm_substream *substream) | ||
312 | { | ||
313 | struct conexant_spec *spec = codec->spec; | ||
314 | spec->cur_adc = spec->adc_nids[spec->cur_adc_idx]; | ||
315 | spec->cur_adc_stream_tag = stream_tag; | ||
316 | spec->cur_adc_format = format; | ||
317 | snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format); | ||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | static int cx5051_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
322 | struct hda_codec *codec, | ||
323 | struct snd_pcm_substream *substream) | ||
324 | { | ||
325 | struct conexant_spec *spec = codec->spec; | ||
326 | snd_hda_codec_cleanup_stream(codec, spec->cur_adc); | ||
327 | spec->cur_adc = 0; | ||
328 | return 0; | ||
329 | } | ||
330 | |||
331 | static const struct hda_pcm_stream cx5051_pcm_analog_capture = { | ||
332 | .substreams = 1, | ||
333 | .channels_min = 2, | ||
334 | .channels_max = 2, | ||
335 | .nid = 0, /* fill later */ | ||
336 | .ops = { | ||
337 | .prepare = cx5051_capture_pcm_prepare, | ||
338 | .cleanup = cx5051_capture_pcm_cleanup | ||
339 | }, | ||
340 | }; | ||
341 | |||
342 | static int conexant_build_pcms(struct hda_codec *codec) | ||
343 | { | ||
344 | struct conexant_spec *spec = codec->spec; | ||
345 | struct hda_pcm *info = spec->pcm_rec; | ||
346 | |||
347 | codec->num_pcms = 1; | ||
348 | codec->pcm_info = info; | ||
349 | |||
350 | info->name = "CONEXANT Analog"; | ||
351 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = conexant_pcm_analog_playback; | ||
352 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = | ||
353 | spec->multiout.max_channels; | ||
354 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = | ||
355 | spec->multiout.dac_nids[0]; | ||
356 | if (spec->capture_stream) | ||
357 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = *spec->capture_stream; | ||
358 | else { | ||
359 | if (codec->vendor_id == 0x14f15051) | ||
360 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = | ||
361 | cx5051_pcm_analog_capture; | ||
362 | else { | ||
363 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = | ||
364 | conexant_pcm_analog_capture; | ||
365 | info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = | ||
366 | spec->num_adc_nids; | ||
367 | } | ||
368 | } | ||
369 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; | ||
370 | |||
371 | if (spec->multiout.dig_out_nid) { | ||
372 | info++; | ||
373 | codec->num_pcms++; | ||
374 | info->name = "Conexant Digital"; | ||
375 | info->pcm_type = HDA_PCM_TYPE_SPDIF; | ||
376 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = | ||
377 | conexant_pcm_digital_playback; | ||
378 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = | ||
379 | spec->multiout.dig_out_nid; | ||
380 | if (spec->dig_in_nid) { | ||
381 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = | ||
382 | conexant_pcm_digital_capture; | ||
383 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = | ||
384 | spec->dig_in_nid; | ||
385 | } | ||
386 | } | ||
387 | |||
388 | return 0; | ||
389 | } | ||
390 | |||
391 | static int conexant_mux_enum_info(struct snd_kcontrol *kcontrol, | ||
392 | struct snd_ctl_elem_info *uinfo) | ||
393 | { | ||
394 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
395 | struct conexant_spec *spec = codec->spec; | ||
396 | |||
397 | return snd_hda_input_mux_info(spec->input_mux, uinfo); | ||
398 | } | ||
399 | |||
400 | static int conexant_mux_enum_get(struct snd_kcontrol *kcontrol, | ||
401 | struct snd_ctl_elem_value *ucontrol) | ||
402 | { | ||
403 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
404 | struct conexant_spec *spec = codec->spec; | ||
405 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
406 | |||
407 | ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx]; | ||
408 | return 0; | ||
409 | } | ||
410 | |||
411 | static int conexant_mux_enum_put(struct snd_kcontrol *kcontrol, | ||
412 | struct snd_ctl_elem_value *ucontrol) | ||
413 | { | ||
414 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
415 | struct conexant_spec *spec = codec->spec; | ||
416 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
417 | |||
418 | return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, | ||
419 | spec->capsrc_nids[adc_idx], | ||
420 | &spec->cur_mux[adc_idx]); | ||
421 | } | ||
422 | |||
423 | static void conexant_set_power(struct hda_codec *codec, hda_nid_t fg, | ||
424 | unsigned int power_state) | ||
425 | { | ||
426 | if (power_state == AC_PWRST_D3) | ||
427 | msleep(100); | ||
428 | snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, | ||
429 | power_state); | ||
430 | /* partial workaround for "azx_get_response timeout" */ | ||
431 | if (power_state == AC_PWRST_D0) | ||
432 | msleep(10); | ||
433 | snd_hda_codec_set_power_to_all(codec, fg, power_state); | ||
434 | } | ||
435 | |||
436 | static int conexant_init(struct hda_codec *codec) | ||
437 | { | ||
438 | struct conexant_spec *spec = codec->spec; | ||
439 | int i; | ||
440 | |||
441 | for (i = 0; i < spec->num_init_verbs; i++) | ||
442 | snd_hda_sequence_write(codec, spec->init_verbs[i]); | ||
443 | return 0; | ||
444 | } | ||
445 | |||
446 | static void conexant_free(struct hda_codec *codec) | ||
447 | { | ||
448 | kfree(codec->spec); | ||
449 | } | ||
450 | |||
451 | static const struct snd_kcontrol_new cxt_capture_mixers[] = { | ||
452 | { | ||
453 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
454 | .name = "Capture Source", | ||
455 | .info = conexant_mux_enum_info, | ||
456 | .get = conexant_mux_enum_get, | ||
457 | .put = conexant_mux_enum_put | ||
458 | }, | ||
459 | {} | ||
460 | }; | ||
461 | |||
462 | static const char * const slave_pfxs[] = { | ||
463 | "Headphone", "Speaker", "Bass Speaker", "Front", "Surround", "CLFE", | ||
464 | NULL | ||
465 | }; | ||
466 | |||
467 | static int conexant_build_controls(struct hda_codec *codec) | ||
468 | { | ||
469 | struct conexant_spec *spec = codec->spec; | ||
470 | unsigned int i; | ||
471 | int err; | ||
472 | |||
473 | for (i = 0; i < spec->num_mixers; i++) { | ||
474 | err = snd_hda_add_new_ctls(codec, spec->mixers[i]); | ||
475 | if (err < 0) | ||
476 | return err; | ||
477 | } | ||
478 | if (spec->multiout.dig_out_nid) { | ||
479 | err = snd_hda_create_spdif_out_ctls(codec, | ||
480 | spec->multiout.dig_out_nid, | ||
481 | spec->multiout.dig_out_nid); | ||
482 | if (err < 0) | ||
483 | return err; | ||
484 | err = snd_hda_create_spdif_share_sw(codec, | ||
485 | &spec->multiout); | ||
486 | if (err < 0) | ||
487 | return err; | ||
488 | spec->multiout.share_spdif = 1; | ||
489 | } | ||
490 | if (spec->dig_in_nid) { | ||
491 | err = snd_hda_create_spdif_in_ctls(codec,spec->dig_in_nid); | ||
492 | if (err < 0) | ||
493 | return err; | ||
494 | } | ||
495 | |||
496 | /* if we have no master control, let's create it */ | ||
497 | if (spec->vmaster_nid && | ||
498 | !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { | ||
499 | unsigned int vmaster_tlv[4]; | ||
500 | snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, | ||
501 | HDA_OUTPUT, vmaster_tlv); | ||
502 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", | ||
503 | vmaster_tlv, slave_pfxs, | ||
504 | "Playback Volume"); | ||
505 | if (err < 0) | ||
506 | return err; | ||
507 | } | ||
508 | if (spec->vmaster_nid && | ||
509 | !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { | ||
510 | err = snd_hda_add_vmaster(codec, "Master Playback Switch", | ||
511 | NULL, slave_pfxs, | ||
512 | "Playback Switch"); | ||
513 | if (err < 0) | ||
514 | return err; | ||
515 | } | ||
516 | |||
517 | if (spec->input_mux) { | ||
518 | err = snd_hda_add_new_ctls(codec, cxt_capture_mixers); | ||
519 | if (err < 0) | ||
520 | return err; | ||
521 | } | ||
522 | |||
523 | err = add_beep_ctls(codec); | ||
524 | if (err < 0) | ||
525 | return err; | ||
526 | |||
527 | return 0; | ||
528 | } | ||
529 | |||
530 | static const struct hda_codec_ops conexant_patch_ops = { | ||
531 | .build_controls = conexant_build_controls, | ||
532 | .build_pcms = conexant_build_pcms, | ||
533 | .init = conexant_init, | ||
534 | .free = conexant_free, | ||
535 | .set_power_state = conexant_set_power, | ||
536 | }; | ||
537 | |||
538 | static int patch_conexant_auto(struct hda_codec *codec); | ||
539 | /* | ||
540 | * EAPD control | ||
541 | * the private value = nid | (invert << 8) | ||
542 | */ | ||
543 | |||
544 | #define cxt_eapd_info snd_ctl_boolean_mono_info | ||
545 | |||
546 | static int cxt_eapd_get(struct snd_kcontrol *kcontrol, | ||
547 | struct snd_ctl_elem_value *ucontrol) | ||
548 | { | ||
549 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
550 | struct conexant_spec *spec = codec->spec; | ||
551 | int invert = (kcontrol->private_value >> 8) & 1; | ||
552 | if (invert) | ||
553 | ucontrol->value.integer.value[0] = !spec->cur_eapd; | ||
554 | else | ||
555 | ucontrol->value.integer.value[0] = spec->cur_eapd; | ||
556 | return 0; | ||
557 | |||
558 | } | ||
559 | |||
560 | static int cxt_eapd_put(struct snd_kcontrol *kcontrol, | ||
561 | struct snd_ctl_elem_value *ucontrol) | ||
562 | { | ||
563 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
564 | struct conexant_spec *spec = codec->spec; | ||
565 | int invert = (kcontrol->private_value >> 8) & 1; | ||
566 | hda_nid_t nid = kcontrol->private_value & 0xff; | ||
567 | unsigned int eapd; | ||
568 | |||
569 | eapd = !!ucontrol->value.integer.value[0]; | ||
570 | if (invert) | ||
571 | eapd = !eapd; | ||
572 | if (eapd == spec->cur_eapd) | ||
573 | return 0; | ||
574 | |||
575 | spec->cur_eapd = eapd; | ||
576 | snd_hda_codec_write_cache(codec, nid, | ||
577 | 0, AC_VERB_SET_EAPD_BTLENABLE, | ||
578 | eapd ? 0x02 : 0x00); | ||
579 | return 1; | ||
580 | } | ||
581 | |||
582 | /* controls for test mode */ | ||
583 | #ifdef CONFIG_SND_DEBUG | ||
584 | |||
585 | #define CXT_EAPD_SWITCH(xname, nid, mask) \ | ||
586 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | ||
587 | .info = cxt_eapd_info, \ | ||
588 | .get = cxt_eapd_get, \ | ||
589 | .put = cxt_eapd_put, \ | ||
590 | .private_value = nid | (mask<<16) } | ||
591 | |||
592 | |||
593 | |||
594 | static int conexant_ch_mode_info(struct snd_kcontrol *kcontrol, | ||
595 | struct snd_ctl_elem_info *uinfo) | ||
596 | { | ||
597 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
598 | struct conexant_spec *spec = codec->spec; | ||
599 | return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode, | ||
600 | spec->num_channel_mode); | ||
601 | } | ||
602 | |||
603 | static int conexant_ch_mode_get(struct snd_kcontrol *kcontrol, | ||
604 | struct snd_ctl_elem_value *ucontrol) | ||
605 | { | ||
606 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
607 | struct conexant_spec *spec = codec->spec; | ||
608 | return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode, | ||
609 | spec->num_channel_mode, | ||
610 | spec->multiout.max_channels); | ||
611 | } | ||
612 | |||
613 | static int conexant_ch_mode_put(struct snd_kcontrol *kcontrol, | ||
614 | struct snd_ctl_elem_value *ucontrol) | ||
615 | { | ||
616 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
617 | struct conexant_spec *spec = codec->spec; | ||
618 | int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, | ||
619 | spec->num_channel_mode, | ||
620 | &spec->multiout.max_channels); | ||
621 | return err; | ||
622 | } | ||
623 | |||
624 | #define CXT_PIN_MODE(xname, nid, dir) \ | ||
625 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | ||
626 | .info = conexant_ch_mode_info, \ | ||
627 | .get = conexant_ch_mode_get, \ | ||
628 | .put = conexant_ch_mode_put, \ | ||
629 | .private_value = nid | (dir<<16) } | ||
630 | |||
631 | #endif /* CONFIG_SND_DEBUG */ | ||
632 | |||
633 | /* Conexant 5045 specific */ | ||
634 | |||
635 | static const hda_nid_t cxt5045_dac_nids[1] = { 0x19 }; | ||
636 | static const hda_nid_t cxt5045_adc_nids[1] = { 0x1a }; | ||
637 | static const hda_nid_t cxt5045_capsrc_nids[1] = { 0x1a }; | ||
638 | #define CXT5045_SPDIF_OUT 0x18 | ||
639 | |||
640 | static const struct hda_channel_mode cxt5045_modes[1] = { | ||
641 | { 2, NULL }, | ||
642 | }; | ||
643 | |||
644 | static const struct hda_input_mux cxt5045_capture_source = { | ||
645 | .num_items = 2, | ||
646 | .items = { | ||
647 | { "Internal Mic", 0x1 }, | ||
648 | { "Mic", 0x2 }, | ||
649 | } | ||
650 | }; | ||
651 | |||
652 | static const struct hda_input_mux cxt5045_capture_source_benq = { | ||
653 | .num_items = 4, | ||
654 | .items = { | ||
655 | { "Internal Mic", 0x1 }, | ||
656 | { "Mic", 0x2 }, | ||
657 | { "Line", 0x3 }, | ||
658 | { "Mixer", 0x0 }, | ||
659 | } | ||
660 | }; | ||
661 | |||
662 | /* turn on/off EAPD (+ mute HP) as a master switch */ | ||
663 | static int cxt5045_hp_master_sw_put(struct snd_kcontrol *kcontrol, | ||
664 | struct snd_ctl_elem_value *ucontrol) | ||
665 | { | ||
666 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
667 | struct conexant_spec *spec = codec->spec; | ||
668 | unsigned int bits; | ||
669 | |||
670 | if (!cxt_eapd_put(kcontrol, ucontrol)) | ||
671 | return 0; | ||
672 | |||
673 | /* toggle internal speakers mute depending of presence of | ||
674 | * the headphone jack | ||
675 | */ | ||
676 | bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE; | ||
677 | snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0, | ||
678 | HDA_AMP_MUTE, bits); | ||
679 | |||
680 | bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE; | ||
681 | snd_hda_codec_amp_stereo(codec, 0x11, HDA_OUTPUT, 0, | ||
682 | HDA_AMP_MUTE, bits); | ||
683 | return 1; | ||
684 | } | ||
685 | |||
686 | /* bind volumes of both NID 0x10 and 0x11 */ | ||
687 | static const struct hda_bind_ctls cxt5045_hp_bind_master_vol = { | ||
688 | .ops = &snd_hda_bind_vol, | ||
689 | .values = { | ||
690 | HDA_COMPOSE_AMP_VAL(0x10, 3, 0, HDA_OUTPUT), | ||
691 | HDA_COMPOSE_AMP_VAL(0x11, 3, 0, HDA_OUTPUT), | ||
692 | 0 | ||
693 | }, | ||
694 | }; | ||
695 | |||
696 | /* toggle input of built-in and mic jack appropriately */ | ||
697 | static void cxt5045_hp_automic(struct hda_codec *codec) | ||
698 | { | ||
699 | static const struct hda_verb mic_jack_on[] = { | ||
700 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
701 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
702 | {} | ||
703 | }; | ||
704 | static const struct hda_verb mic_jack_off[] = { | ||
705 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
706 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
707 | {} | ||
708 | }; | ||
709 | unsigned int present; | ||
710 | |||
711 | present = snd_hda_jack_detect(codec, 0x12); | ||
712 | if (present) | ||
713 | snd_hda_sequence_write(codec, mic_jack_on); | ||
714 | else | ||
715 | snd_hda_sequence_write(codec, mic_jack_off); | ||
716 | } | ||
717 | |||
718 | |||
719 | /* mute internal speaker if HP is plugged */ | ||
720 | static void cxt5045_hp_automute(struct hda_codec *codec) | ||
721 | { | ||
722 | struct conexant_spec *spec = codec->spec; | ||
723 | unsigned int bits; | ||
724 | |||
725 | spec->hp_present = snd_hda_jack_detect(codec, 0x11); | ||
726 | |||
727 | bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; | ||
728 | snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0, | ||
729 | HDA_AMP_MUTE, bits); | ||
730 | } | ||
731 | |||
732 | /* unsolicited event for HP jack sensing */ | ||
733 | static void cxt5045_hp_unsol_event(struct hda_codec *codec, | ||
734 | unsigned int res) | ||
735 | { | ||
736 | res >>= 26; | ||
737 | switch (res) { | ||
738 | case CONEXANT_HP_EVENT: | ||
739 | cxt5045_hp_automute(codec); | ||
740 | break; | ||
741 | case CONEXANT_MIC_EVENT: | ||
742 | cxt5045_hp_automic(codec); | ||
743 | break; | ||
744 | |||
745 | } | ||
746 | } | ||
747 | |||
748 | static const struct snd_kcontrol_new cxt5045_mixers[] = { | ||
749 | HDA_CODEC_VOLUME("Capture Volume", 0x1a, 0x00, HDA_INPUT), | ||
750 | HDA_CODEC_MUTE("Capture Switch", 0x1a, 0x0, HDA_INPUT), | ||
751 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT), | ||
752 | HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT), | ||
753 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x1, HDA_INPUT), | ||
754 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x1, HDA_INPUT), | ||
755 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x17, 0x2, HDA_INPUT), | ||
756 | HDA_CODEC_MUTE("Mic Playback Switch", 0x17, 0x2, HDA_INPUT), | ||
757 | HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol), | ||
758 | { | ||
759 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
760 | .name = "Master Playback Switch", | ||
761 | .info = cxt_eapd_info, | ||
762 | .get = cxt_eapd_get, | ||
763 | .put = cxt5045_hp_master_sw_put, | ||
764 | .private_value = 0x10, | ||
765 | }, | ||
766 | |||
767 | {} | ||
768 | }; | ||
769 | |||
770 | static const struct snd_kcontrol_new cxt5045_benq_mixers[] = { | ||
771 | HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x3, HDA_INPUT), | ||
772 | HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x3, HDA_INPUT), | ||
773 | |||
774 | {} | ||
775 | }; | ||
776 | |||
777 | static const struct hda_verb cxt5045_init_verbs[] = { | ||
778 | /* Line in, Mic */ | ||
779 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, | ||
780 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, | ||
781 | /* HP, Amp */ | ||
782 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
783 | {0x10, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
784 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
785 | {0x11, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
786 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
787 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
788 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
789 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
790 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
791 | /* Record selector: Internal mic */ | ||
792 | {0x1a, AC_VERB_SET_CONNECT_SEL,0x1}, | ||
793 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, | ||
794 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, | ||
795 | /* SPDIF route: PCM */ | ||
796 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
797 | { 0x13, AC_VERB_SET_CONNECT_SEL, 0x0 }, | ||
798 | /* EAPD */ | ||
799 | {0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x2 }, /* default on */ | ||
800 | { } /* end */ | ||
801 | }; | ||
802 | |||
803 | static const struct hda_verb cxt5045_benq_init_verbs[] = { | ||
804 | /* Internal Mic, Mic */ | ||
805 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, | ||
806 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, | ||
807 | /* Line In,HP, Amp */ | ||
808 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
809 | {0x10, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
810 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
811 | {0x11, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
812 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
813 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
814 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
815 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
816 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
817 | /* Record selector: Internal mic */ | ||
818 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
819 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, | ||
820 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, | ||
821 | /* SPDIF route: PCM */ | ||
822 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
823 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
824 | /* EAPD */ | ||
825 | {0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
826 | { } /* end */ | ||
827 | }; | ||
828 | |||
829 | static const struct hda_verb cxt5045_hp_sense_init_verbs[] = { | ||
830 | /* pin sensing on HP jack */ | ||
831 | {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
832 | { } /* end */ | ||
833 | }; | ||
834 | |||
835 | static const struct hda_verb cxt5045_mic_sense_init_verbs[] = { | ||
836 | /* pin sensing on HP jack */ | ||
837 | {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | ||
838 | { } /* end */ | ||
839 | }; | ||
840 | |||
841 | #ifdef CONFIG_SND_DEBUG | ||
842 | /* Test configuration for debugging, modelled after the ALC260 test | ||
843 | * configuration. | ||
844 | */ | ||
845 | static const struct hda_input_mux cxt5045_test_capture_source = { | ||
846 | .num_items = 5, | ||
847 | .items = { | ||
848 | { "MIXER", 0x0 }, | ||
849 | { "MIC1 pin", 0x1 }, | ||
850 | { "LINE1 pin", 0x2 }, | ||
851 | { "HP-OUT pin", 0x3 }, | ||
852 | { "CD pin", 0x4 }, | ||
853 | }, | ||
854 | }; | ||
855 | |||
856 | static const struct snd_kcontrol_new cxt5045_test_mixer[] = { | ||
857 | |||
858 | /* Output controls */ | ||
859 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x10, 0x0, HDA_OUTPUT), | ||
860 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x10, 0x0, HDA_OUTPUT), | ||
861 | HDA_CODEC_VOLUME("HP-OUT Playback Volume", 0x11, 0x0, HDA_OUTPUT), | ||
862 | HDA_CODEC_MUTE("HP-OUT Playback Switch", 0x11, 0x0, HDA_OUTPUT), | ||
863 | HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x12, 0x0, HDA_OUTPUT), | ||
864 | HDA_CODEC_MUTE("LINE1 Playback Switch", 0x12, 0x0, HDA_OUTPUT), | ||
865 | |||
866 | /* Modes for retasking pin widgets */ | ||
867 | CXT_PIN_MODE("HP-OUT pin mode", 0x11, CXT_PIN_DIR_INOUT), | ||
868 | CXT_PIN_MODE("LINE1 pin mode", 0x12, CXT_PIN_DIR_INOUT), | ||
869 | |||
870 | /* EAPD Switch Control */ | ||
871 | CXT_EAPD_SWITCH("External Amplifier", 0x10, 0x0), | ||
872 | |||
873 | /* Loopback mixer controls */ | ||
874 | |||
875 | HDA_CODEC_VOLUME("PCM Volume", 0x17, 0x0, HDA_INPUT), | ||
876 | HDA_CODEC_MUTE("PCM Switch", 0x17, 0x0, HDA_INPUT), | ||
877 | HDA_CODEC_VOLUME("MIC1 pin Volume", 0x17, 0x1, HDA_INPUT), | ||
878 | HDA_CODEC_MUTE("MIC1 pin Switch", 0x17, 0x1, HDA_INPUT), | ||
879 | HDA_CODEC_VOLUME("LINE1 pin Volume", 0x17, 0x2, HDA_INPUT), | ||
880 | HDA_CODEC_MUTE("LINE1 pin Switch", 0x17, 0x2, HDA_INPUT), | ||
881 | HDA_CODEC_VOLUME("HP-OUT pin Volume", 0x17, 0x3, HDA_INPUT), | ||
882 | HDA_CODEC_MUTE("HP-OUT pin Switch", 0x17, 0x3, HDA_INPUT), | ||
883 | HDA_CODEC_VOLUME("CD pin Volume", 0x17, 0x4, HDA_INPUT), | ||
884 | HDA_CODEC_MUTE("CD pin Switch", 0x17, 0x4, HDA_INPUT), | ||
885 | { | ||
886 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
887 | .name = "Input Source", | ||
888 | .info = conexant_mux_enum_info, | ||
889 | .get = conexant_mux_enum_get, | ||
890 | .put = conexant_mux_enum_put, | ||
891 | }, | ||
892 | /* Audio input controls */ | ||
893 | HDA_CODEC_VOLUME("Capture Volume", 0x1a, 0x0, HDA_INPUT), | ||
894 | HDA_CODEC_MUTE("Capture Switch", 0x1a, 0x0, HDA_INPUT), | ||
895 | { } /* end */ | ||
896 | }; | ||
897 | |||
898 | static const struct hda_verb cxt5045_test_init_verbs[] = { | ||
899 | /* Set connections */ | ||
900 | { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 }, | ||
901 | { 0x11, AC_VERB_SET_CONNECT_SEL, 0x0 }, | ||
902 | { 0x12, AC_VERB_SET_CONNECT_SEL, 0x0 }, | ||
903 | /* Enable retasking pins as output, initially without power amp */ | ||
904 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
905 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
906 | |||
907 | /* Disable digital (SPDIF) pins initially, but users can enable | ||
908 | * them via a mixer switch. In the case of SPDIF-out, this initverb | ||
909 | * payload also sets the generation to 0, output to be in "consumer" | ||
910 | * PCM format, copyright asserted, no pre-emphasis and no validity | ||
911 | * control. | ||
912 | */ | ||
913 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
914 | {0x18, AC_VERB_SET_DIGI_CONVERT_1, 0}, | ||
915 | |||
916 | /* Unmute retasking pin widget output buffers since the default | ||
917 | * state appears to be output. As the pin mode is changed by the | ||
918 | * user the pin mode control will take care of enabling the pin's | ||
919 | * input/output buffers as needed. | ||
920 | */ | ||
921 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
922 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
923 | |||
924 | /* Mute capture amp left and right */ | ||
925 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
926 | |||
927 | /* Set ADC connection select to match default mixer setting (mic1 | ||
928 | * pin) | ||
929 | */ | ||
930 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
931 | {0x17, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
932 | |||
933 | /* Mute all inputs to mixer widget (even unconnected ones) */ | ||
934 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* Mixer */ | ||
935 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* Mic1 pin */ | ||
936 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* Line pin */ | ||
937 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* HP pin */ | ||
938 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ | ||
939 | |||
940 | { } | ||
941 | }; | ||
942 | #endif | ||
943 | |||
944 | |||
945 | /* initialize jack-sensing, too */ | ||
946 | static int cxt5045_init(struct hda_codec *codec) | ||
947 | { | ||
948 | conexant_init(codec); | ||
949 | cxt5045_hp_automute(codec); | ||
950 | return 0; | ||
951 | } | ||
952 | |||
953 | |||
954 | enum { | ||
955 | CXT5045_LAPTOP_HPSENSE, | ||
956 | CXT5045_LAPTOP_MICSENSE, | ||
957 | CXT5045_LAPTOP_HPMICSENSE, | ||
958 | CXT5045_BENQ, | ||
959 | #ifdef CONFIG_SND_DEBUG | ||
960 | CXT5045_TEST, | ||
961 | #endif | ||
962 | CXT5045_AUTO, | ||
963 | CXT5045_MODELS | ||
964 | }; | ||
965 | |||
966 | static const char * const cxt5045_models[CXT5045_MODELS] = { | ||
967 | [CXT5045_LAPTOP_HPSENSE] = "laptop-hpsense", | ||
968 | [CXT5045_LAPTOP_MICSENSE] = "laptop-micsense", | ||
969 | [CXT5045_LAPTOP_HPMICSENSE] = "laptop-hpmicsense", | ||
970 | [CXT5045_BENQ] = "benq", | ||
971 | #ifdef CONFIG_SND_DEBUG | ||
972 | [CXT5045_TEST] = "test", | ||
973 | #endif | ||
974 | [CXT5045_AUTO] = "auto", | ||
975 | }; | ||
976 | |||
977 | static const struct snd_pci_quirk cxt5045_cfg_tbl[] = { | ||
978 | SND_PCI_QUIRK(0x152d, 0x0753, "Benq R55E", CXT5045_BENQ), | ||
979 | SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP_MICSENSE), | ||
980 | SND_PCI_QUIRK(0x1734, 0x10cb, "Fujitsu Si3515", CXT5045_LAPTOP_HPMICSENSE), | ||
981 | SND_PCI_QUIRK(0x1734, 0x110e, "Fujitsu V5505", | ||
982 | CXT5045_LAPTOP_HPMICSENSE), | ||
983 | SND_PCI_QUIRK(0x1509, 0x1e40, "FIC", CXT5045_LAPTOP_HPMICSENSE), | ||
984 | SND_PCI_QUIRK(0x1509, 0x2f05, "FIC", CXT5045_LAPTOP_HPMICSENSE), | ||
985 | SND_PCI_QUIRK(0x1509, 0x2f06, "FIC", CXT5045_LAPTOP_HPMICSENSE), | ||
986 | SND_PCI_QUIRK_MASK(0x1631, 0xff00, 0xc100, "Packard Bell", | ||
987 | CXT5045_LAPTOP_HPMICSENSE), | ||
988 | SND_PCI_QUIRK(0x8086, 0x2111, "Conexant Reference board", CXT5045_LAPTOP_HPSENSE), | ||
989 | {} | ||
990 | }; | ||
991 | |||
992 | static int patch_cxt5045(struct hda_codec *codec) | ||
993 | { | ||
994 | struct conexant_spec *spec; | ||
995 | int board_config; | ||
996 | |||
997 | board_config = snd_hda_check_board_config(codec, CXT5045_MODELS, | ||
998 | cxt5045_models, | ||
999 | cxt5045_cfg_tbl); | ||
1000 | if (board_config < 0) | ||
1001 | board_config = CXT5045_AUTO; /* model=auto as default */ | ||
1002 | if (board_config == CXT5045_AUTO) | ||
1003 | return patch_conexant_auto(codec); | ||
1004 | |||
1005 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1006 | if (!spec) | ||
1007 | return -ENOMEM; | ||
1008 | codec->spec = spec; | ||
1009 | codec->single_adc_amp = 1; | ||
1010 | |||
1011 | spec->multiout.max_channels = 2; | ||
1012 | spec->multiout.num_dacs = ARRAY_SIZE(cxt5045_dac_nids); | ||
1013 | spec->multiout.dac_nids = cxt5045_dac_nids; | ||
1014 | spec->multiout.dig_out_nid = CXT5045_SPDIF_OUT; | ||
1015 | spec->num_adc_nids = 1; | ||
1016 | spec->adc_nids = cxt5045_adc_nids; | ||
1017 | spec->capsrc_nids = cxt5045_capsrc_nids; | ||
1018 | spec->input_mux = &cxt5045_capture_source; | ||
1019 | spec->num_mixers = 1; | ||
1020 | spec->mixers[0] = cxt5045_mixers; | ||
1021 | spec->num_init_verbs = 1; | ||
1022 | spec->init_verbs[0] = cxt5045_init_verbs; | ||
1023 | spec->spdif_route = 0; | ||
1024 | spec->num_channel_mode = ARRAY_SIZE(cxt5045_modes); | ||
1025 | spec->channel_mode = cxt5045_modes; | ||
1026 | |||
1027 | set_beep_amp(spec, 0x16, 0, 1); | ||
1028 | |||
1029 | codec->patch_ops = conexant_patch_ops; | ||
1030 | |||
1031 | switch (board_config) { | ||
1032 | case CXT5045_LAPTOP_HPSENSE: | ||
1033 | codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; | ||
1034 | spec->input_mux = &cxt5045_capture_source; | ||
1035 | spec->num_init_verbs = 2; | ||
1036 | spec->init_verbs[1] = cxt5045_hp_sense_init_verbs; | ||
1037 | spec->mixers[0] = cxt5045_mixers; | ||
1038 | codec->patch_ops.init = cxt5045_init; | ||
1039 | break; | ||
1040 | case CXT5045_LAPTOP_MICSENSE: | ||
1041 | codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; | ||
1042 | spec->input_mux = &cxt5045_capture_source; | ||
1043 | spec->num_init_verbs = 2; | ||
1044 | spec->init_verbs[1] = cxt5045_mic_sense_init_verbs; | ||
1045 | spec->mixers[0] = cxt5045_mixers; | ||
1046 | codec->patch_ops.init = cxt5045_init; | ||
1047 | break; | ||
1048 | default: | ||
1049 | case CXT5045_LAPTOP_HPMICSENSE: | ||
1050 | codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; | ||
1051 | spec->input_mux = &cxt5045_capture_source; | ||
1052 | spec->num_init_verbs = 3; | ||
1053 | spec->init_verbs[1] = cxt5045_hp_sense_init_verbs; | ||
1054 | spec->init_verbs[2] = cxt5045_mic_sense_init_verbs; | ||
1055 | spec->mixers[0] = cxt5045_mixers; | ||
1056 | codec->patch_ops.init = cxt5045_init; | ||
1057 | break; | ||
1058 | case CXT5045_BENQ: | ||
1059 | codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; | ||
1060 | spec->input_mux = &cxt5045_capture_source_benq; | ||
1061 | spec->num_init_verbs = 1; | ||
1062 | spec->init_verbs[0] = cxt5045_benq_init_verbs; | ||
1063 | spec->mixers[0] = cxt5045_mixers; | ||
1064 | spec->mixers[1] = cxt5045_benq_mixers; | ||
1065 | spec->num_mixers = 2; | ||
1066 | codec->patch_ops.init = cxt5045_init; | ||
1067 | break; | ||
1068 | #ifdef CONFIG_SND_DEBUG | ||
1069 | case CXT5045_TEST: | ||
1070 | spec->input_mux = &cxt5045_test_capture_source; | ||
1071 | spec->mixers[0] = cxt5045_test_mixer; | ||
1072 | spec->init_verbs[0] = cxt5045_test_init_verbs; | ||
1073 | break; | ||
1074 | |||
1075 | #endif | ||
1076 | } | ||
1077 | |||
1078 | switch (codec->subsystem_id >> 16) { | ||
1079 | case 0x103c: | ||
1080 | case 0x1631: | ||
1081 | case 0x1734: | ||
1082 | case 0x17aa: | ||
1083 | /* HP, Packard Bell, Fujitsu-Siemens & Lenovo laptops have | ||
1084 | * really bad sound over 0dB on NID 0x17. Fix max PCM level to | ||
1085 | * 0 dB (originally it has 0x2b steps with 0dB offset 0x14) | ||
1086 | */ | ||
1087 | snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT, | ||
1088 | (0x14 << AC_AMPCAP_OFFSET_SHIFT) | | ||
1089 | (0x14 << AC_AMPCAP_NUM_STEPS_SHIFT) | | ||
1090 | (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | | ||
1091 | (1 << AC_AMPCAP_MUTE_SHIFT)); | ||
1092 | break; | ||
1093 | } | ||
1094 | |||
1095 | if (spec->beep_amp) | ||
1096 | snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp)); | ||
1097 | |||
1098 | return 0; | ||
1099 | } | ||
1100 | |||
1101 | |||
1102 | /* Conexant 5047 specific */ | ||
1103 | #define CXT5047_SPDIF_OUT 0x11 | ||
1104 | |||
1105 | static const hda_nid_t cxt5047_dac_nids[1] = { 0x10 }; /* 0x1c */ | ||
1106 | static const hda_nid_t cxt5047_adc_nids[1] = { 0x12 }; | ||
1107 | static const hda_nid_t cxt5047_capsrc_nids[1] = { 0x1a }; | ||
1108 | |||
1109 | static const struct hda_channel_mode cxt5047_modes[1] = { | ||
1110 | { 2, NULL }, | ||
1111 | }; | ||
1112 | |||
1113 | static const struct hda_input_mux cxt5047_toshiba_capture_source = { | ||
1114 | .num_items = 2, | ||
1115 | .items = { | ||
1116 | { "ExtMic", 0x2 }, | ||
1117 | { "Line-In", 0x1 }, | ||
1118 | } | ||
1119 | }; | ||
1120 | |||
1121 | /* turn on/off EAPD (+ mute HP) as a master switch */ | ||
1122 | static int cxt5047_hp_master_sw_put(struct snd_kcontrol *kcontrol, | ||
1123 | struct snd_ctl_elem_value *ucontrol) | ||
1124 | { | ||
1125 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1126 | struct conexant_spec *spec = codec->spec; | ||
1127 | unsigned int bits; | ||
1128 | |||
1129 | if (!cxt_eapd_put(kcontrol, ucontrol)) | ||
1130 | return 0; | ||
1131 | |||
1132 | /* toggle internal speakers mute depending of presence of | ||
1133 | * the headphone jack | ||
1134 | */ | ||
1135 | bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE; | ||
1136 | /* NOTE: Conexat codec needs the index for *OUTPUT* amp of | ||
1137 | * pin widgets unlike other codecs. In this case, we need to | ||
1138 | * set index 0x01 for the volume from the mixer amp 0x19. | ||
1139 | */ | ||
1140 | snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01, | ||
1141 | HDA_AMP_MUTE, bits); | ||
1142 | bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE; | ||
1143 | snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0, | ||
1144 | HDA_AMP_MUTE, bits); | ||
1145 | return 1; | ||
1146 | } | ||
1147 | |||
1148 | /* mute internal speaker if HP is plugged */ | ||
1149 | static void cxt5047_hp_automute(struct hda_codec *codec) | ||
1150 | { | ||
1151 | struct conexant_spec *spec = codec->spec; | ||
1152 | unsigned int bits; | ||
1153 | |||
1154 | spec->hp_present = snd_hda_jack_detect(codec, 0x13); | ||
1155 | |||
1156 | bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; | ||
1157 | /* See the note in cxt5047_hp_master_sw_put */ | ||
1158 | snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01, | ||
1159 | HDA_AMP_MUTE, bits); | ||
1160 | } | ||
1161 | |||
1162 | /* toggle input of built-in and mic jack appropriately */ | ||
1163 | static void cxt5047_hp_automic(struct hda_codec *codec) | ||
1164 | { | ||
1165 | static const struct hda_verb mic_jack_on[] = { | ||
1166 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
1167 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1168 | {} | ||
1169 | }; | ||
1170 | static const struct hda_verb mic_jack_off[] = { | ||
1171 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
1172 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1173 | {} | ||
1174 | }; | ||
1175 | unsigned int present; | ||
1176 | |||
1177 | present = snd_hda_jack_detect(codec, 0x15); | ||
1178 | if (present) | ||
1179 | snd_hda_sequence_write(codec, mic_jack_on); | ||
1180 | else | ||
1181 | snd_hda_sequence_write(codec, mic_jack_off); | ||
1182 | } | ||
1183 | |||
1184 | /* unsolicited event for HP jack sensing */ | ||
1185 | static void cxt5047_hp_unsol_event(struct hda_codec *codec, | ||
1186 | unsigned int res) | ||
1187 | { | ||
1188 | switch (res >> 26) { | ||
1189 | case CONEXANT_HP_EVENT: | ||
1190 | cxt5047_hp_automute(codec); | ||
1191 | break; | ||
1192 | case CONEXANT_MIC_EVENT: | ||
1193 | cxt5047_hp_automic(codec); | ||
1194 | break; | ||
1195 | } | ||
1196 | } | ||
1197 | |||
1198 | static const struct snd_kcontrol_new cxt5047_base_mixers[] = { | ||
1199 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x19, 0x02, HDA_INPUT), | ||
1200 | HDA_CODEC_MUTE("Mic Playback Switch", 0x19, 0x02, HDA_INPUT), | ||
1201 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x1a, 0x0, HDA_OUTPUT), | ||
1202 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), | ||
1203 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), | ||
1204 | HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), | ||
1205 | HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT), | ||
1206 | { | ||
1207 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1208 | .name = "Master Playback Switch", | ||
1209 | .info = cxt_eapd_info, | ||
1210 | .get = cxt_eapd_get, | ||
1211 | .put = cxt5047_hp_master_sw_put, | ||
1212 | .private_value = 0x13, | ||
1213 | }, | ||
1214 | |||
1215 | {} | ||
1216 | }; | ||
1217 | |||
1218 | static const struct snd_kcontrol_new cxt5047_hp_spk_mixers[] = { | ||
1219 | /* See the note in cxt5047_hp_master_sw_put */ | ||
1220 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x01, HDA_OUTPUT), | ||
1221 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x13, 0x00, HDA_OUTPUT), | ||
1222 | {} | ||
1223 | }; | ||
1224 | |||
1225 | static const struct snd_kcontrol_new cxt5047_hp_only_mixers[] = { | ||
1226 | HDA_CODEC_VOLUME("Master Playback Volume", 0x13, 0x00, HDA_OUTPUT), | ||
1227 | { } /* end */ | ||
1228 | }; | ||
1229 | |||
1230 | static const struct hda_verb cxt5047_init_verbs[] = { | ||
1231 | /* Line in, Mic, Built-in Mic */ | ||
1232 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
1233 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, | ||
1234 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, | ||
1235 | /* HP, Speaker */ | ||
1236 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
1237 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, /* mixer(0x19) */ | ||
1238 | {0x1d, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mixer(0x19) */ | ||
1239 | /* Record selector: Mic */ | ||
1240 | {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, | ||
1241 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, | ||
1242 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, | ||
1243 | {0x1A, AC_VERB_SET_CONNECT_SEL,0x02}, | ||
1244 | {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, | ||
1245 | AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x00}, | ||
1246 | {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, | ||
1247 | AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x03}, | ||
1248 | /* SPDIF route: PCM */ | ||
1249 | { 0x18, AC_VERB_SET_CONNECT_SEL, 0x0 }, | ||
1250 | /* Enable unsolicited events */ | ||
1251 | {0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
1252 | {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | ||
1253 | { } /* end */ | ||
1254 | }; | ||
1255 | |||
1256 | /* configuration for Toshiba Laptops */ | ||
1257 | static const struct hda_verb cxt5047_toshiba_init_verbs[] = { | ||
1258 | {0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x0}, /* default off */ | ||
1259 | {} | ||
1260 | }; | ||
1261 | |||
1262 | /* Test configuration for debugging, modelled after the ALC260 test | ||
1263 | * configuration. | ||
1264 | */ | ||
1265 | #ifdef CONFIG_SND_DEBUG | ||
1266 | static const struct hda_input_mux cxt5047_test_capture_source = { | ||
1267 | .num_items = 4, | ||
1268 | .items = { | ||
1269 | { "LINE1 pin", 0x0 }, | ||
1270 | { "MIC1 pin", 0x1 }, | ||
1271 | { "MIC2 pin", 0x2 }, | ||
1272 | { "CD pin", 0x3 }, | ||
1273 | }, | ||
1274 | }; | ||
1275 | |||
1276 | static const struct snd_kcontrol_new cxt5047_test_mixer[] = { | ||
1277 | |||
1278 | /* Output only controls */ | ||
1279 | HDA_CODEC_VOLUME("OutAmp-1 Volume", 0x10, 0x0, HDA_OUTPUT), | ||
1280 | HDA_CODEC_MUTE("OutAmp-1 Switch", 0x10,0x0, HDA_OUTPUT), | ||
1281 | HDA_CODEC_VOLUME("OutAmp-2 Volume", 0x1c, 0x0, HDA_OUTPUT), | ||
1282 | HDA_CODEC_MUTE("OutAmp-2 Switch", 0x1c, 0x0, HDA_OUTPUT), | ||
1283 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x0, HDA_OUTPUT), | ||
1284 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x1d, 0x0, HDA_OUTPUT), | ||
1285 | HDA_CODEC_VOLUME("HeadPhone Playback Volume", 0x13, 0x0, HDA_OUTPUT), | ||
1286 | HDA_CODEC_MUTE("HeadPhone Playback Switch", 0x13, 0x0, HDA_OUTPUT), | ||
1287 | HDA_CODEC_VOLUME("Line1-Out Playback Volume", 0x14, 0x0, HDA_OUTPUT), | ||
1288 | HDA_CODEC_MUTE("Line1-Out Playback Switch", 0x14, 0x0, HDA_OUTPUT), | ||
1289 | HDA_CODEC_VOLUME("Line2-Out Playback Volume", 0x15, 0x0, HDA_OUTPUT), | ||
1290 | HDA_CODEC_MUTE("Line2-Out Playback Switch", 0x15, 0x0, HDA_OUTPUT), | ||
1291 | |||
1292 | /* Modes for retasking pin widgets */ | ||
1293 | CXT_PIN_MODE("LINE1 pin mode", 0x14, CXT_PIN_DIR_INOUT), | ||
1294 | CXT_PIN_MODE("MIC1 pin mode", 0x15, CXT_PIN_DIR_INOUT), | ||
1295 | |||
1296 | /* EAPD Switch Control */ | ||
1297 | CXT_EAPD_SWITCH("External Amplifier", 0x13, 0x0), | ||
1298 | |||
1299 | /* Loopback mixer controls */ | ||
1300 | HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x12, 0x01, HDA_INPUT), | ||
1301 | HDA_CODEC_MUTE("MIC1 Playback Switch", 0x12, 0x01, HDA_INPUT), | ||
1302 | HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x12, 0x02, HDA_INPUT), | ||
1303 | HDA_CODEC_MUTE("MIC2 Playback Switch", 0x12, 0x02, HDA_INPUT), | ||
1304 | HDA_CODEC_VOLUME("LINE Playback Volume", 0x12, 0x0, HDA_INPUT), | ||
1305 | HDA_CODEC_MUTE("LINE Playback Switch", 0x12, 0x0, HDA_INPUT), | ||
1306 | HDA_CODEC_VOLUME("CD Playback Volume", 0x12, 0x04, HDA_INPUT), | ||
1307 | HDA_CODEC_MUTE("CD Playback Switch", 0x12, 0x04, HDA_INPUT), | ||
1308 | |||
1309 | HDA_CODEC_VOLUME("Capture-1 Volume", 0x19, 0x0, HDA_INPUT), | ||
1310 | HDA_CODEC_MUTE("Capture-1 Switch", 0x19, 0x0, HDA_INPUT), | ||
1311 | HDA_CODEC_VOLUME("Capture-2 Volume", 0x19, 0x1, HDA_INPUT), | ||
1312 | HDA_CODEC_MUTE("Capture-2 Switch", 0x19, 0x1, HDA_INPUT), | ||
1313 | HDA_CODEC_VOLUME("Capture-3 Volume", 0x19, 0x2, HDA_INPUT), | ||
1314 | HDA_CODEC_MUTE("Capture-3 Switch", 0x19, 0x2, HDA_INPUT), | ||
1315 | HDA_CODEC_VOLUME("Capture-4 Volume", 0x19, 0x3, HDA_INPUT), | ||
1316 | HDA_CODEC_MUTE("Capture-4 Switch", 0x19, 0x3, HDA_INPUT), | ||
1317 | { | ||
1318 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1319 | .name = "Input Source", | ||
1320 | .info = conexant_mux_enum_info, | ||
1321 | .get = conexant_mux_enum_get, | ||
1322 | .put = conexant_mux_enum_put, | ||
1323 | }, | ||
1324 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x1a, 0x0, HDA_OUTPUT), | ||
1325 | |||
1326 | { } /* end */ | ||
1327 | }; | ||
1328 | |||
1329 | static const struct hda_verb cxt5047_test_init_verbs[] = { | ||
1330 | /* Enable retasking pins as output, initially without power amp */ | ||
1331 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1332 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1333 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1334 | |||
1335 | /* Disable digital (SPDIF) pins initially, but users can enable | ||
1336 | * them via a mixer switch. In the case of SPDIF-out, this initverb | ||
1337 | * payload also sets the generation to 0, output to be in "consumer" | ||
1338 | * PCM format, copyright asserted, no pre-emphasis and no validity | ||
1339 | * control. | ||
1340 | */ | ||
1341 | {0x18, AC_VERB_SET_DIGI_CONVERT_1, 0}, | ||
1342 | |||
1343 | /* Ensure mic1, mic2, line1 pin widgets take input from the | ||
1344 | * OUT1 sum bus when acting as an output. | ||
1345 | */ | ||
1346 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0}, | ||
1347 | {0x1b, AC_VERB_SET_CONNECT_SEL, 0}, | ||
1348 | |||
1349 | /* Start with output sum widgets muted and their output gains at min */ | ||
1350 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
1351 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
1352 | |||
1353 | /* Unmute retasking pin widget output buffers since the default | ||
1354 | * state appears to be output. As the pin mode is changed by the | ||
1355 | * user the pin mode control will take care of enabling the pin's | ||
1356 | * input/output buffers as needed. | ||
1357 | */ | ||
1358 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1359 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1360 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1361 | |||
1362 | /* Mute capture amp left and right */ | ||
1363 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
1364 | |||
1365 | /* Set ADC connection select to match default mixer setting (mic1 | ||
1366 | * pin) | ||
1367 | */ | ||
1368 | {0x12, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1369 | |||
1370 | /* Mute all inputs to mixer widget (even unconnected ones) */ | ||
1371 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ | ||
1372 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ | ||
1373 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ | ||
1374 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ | ||
1375 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ | ||
1376 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ | ||
1377 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ | ||
1378 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ | ||
1379 | |||
1380 | { } | ||
1381 | }; | ||
1382 | #endif | ||
1383 | |||
1384 | |||
1385 | /* initialize jack-sensing, too */ | ||
1386 | static int cxt5047_hp_init(struct hda_codec *codec) | ||
1387 | { | ||
1388 | conexant_init(codec); | ||
1389 | cxt5047_hp_automute(codec); | ||
1390 | return 0; | ||
1391 | } | ||
1392 | |||
1393 | |||
1394 | enum { | ||
1395 | CXT5047_LAPTOP, /* Laptops w/o EAPD support */ | ||
1396 | CXT5047_LAPTOP_HP, /* Some HP laptops */ | ||
1397 | CXT5047_LAPTOP_EAPD, /* Laptops with EAPD support */ | ||
1398 | #ifdef CONFIG_SND_DEBUG | ||
1399 | CXT5047_TEST, | ||
1400 | #endif | ||
1401 | CXT5047_AUTO, | ||
1402 | CXT5047_MODELS | ||
1403 | }; | ||
1404 | |||
1405 | static const char * const cxt5047_models[CXT5047_MODELS] = { | ||
1406 | [CXT5047_LAPTOP] = "laptop", | ||
1407 | [CXT5047_LAPTOP_HP] = "laptop-hp", | ||
1408 | [CXT5047_LAPTOP_EAPD] = "laptop-eapd", | ||
1409 | #ifdef CONFIG_SND_DEBUG | ||
1410 | [CXT5047_TEST] = "test", | ||
1411 | #endif | ||
1412 | [CXT5047_AUTO] = "auto", | ||
1413 | }; | ||
1414 | |||
1415 | static const struct snd_pci_quirk cxt5047_cfg_tbl[] = { | ||
1416 | SND_PCI_QUIRK(0x103c, 0x30a5, "HP DV5200T/DV8000T", CXT5047_LAPTOP_HP), | ||
1417 | SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP DV Series", | ||
1418 | CXT5047_LAPTOP), | ||
1419 | SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P100", CXT5047_LAPTOP_EAPD), | ||
1420 | {} | ||
1421 | }; | ||
1422 | |||
1423 | static int patch_cxt5047(struct hda_codec *codec) | ||
1424 | { | ||
1425 | struct conexant_spec *spec; | ||
1426 | int board_config; | ||
1427 | |||
1428 | board_config = snd_hda_check_board_config(codec, CXT5047_MODELS, | ||
1429 | cxt5047_models, | ||
1430 | cxt5047_cfg_tbl); | ||
1431 | if (board_config < 0) | ||
1432 | board_config = CXT5047_AUTO; /* model=auto as default */ | ||
1433 | if (board_config == CXT5047_AUTO) | ||
1434 | return patch_conexant_auto(codec); | ||
1435 | |||
1436 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1437 | if (!spec) | ||
1438 | return -ENOMEM; | ||
1439 | codec->spec = spec; | ||
1440 | codec->pin_amp_workaround = 1; | ||
1441 | |||
1442 | spec->multiout.max_channels = 2; | ||
1443 | spec->multiout.num_dacs = ARRAY_SIZE(cxt5047_dac_nids); | ||
1444 | spec->multiout.dac_nids = cxt5047_dac_nids; | ||
1445 | spec->multiout.dig_out_nid = CXT5047_SPDIF_OUT; | ||
1446 | spec->num_adc_nids = 1; | ||
1447 | spec->adc_nids = cxt5047_adc_nids; | ||
1448 | spec->capsrc_nids = cxt5047_capsrc_nids; | ||
1449 | spec->num_mixers = 1; | ||
1450 | spec->mixers[0] = cxt5047_base_mixers; | ||
1451 | spec->num_init_verbs = 1; | ||
1452 | spec->init_verbs[0] = cxt5047_init_verbs; | ||
1453 | spec->spdif_route = 0; | ||
1454 | spec->num_channel_mode = ARRAY_SIZE(cxt5047_modes), | ||
1455 | spec->channel_mode = cxt5047_modes, | ||
1456 | |||
1457 | codec->patch_ops = conexant_patch_ops; | ||
1458 | |||
1459 | switch (board_config) { | ||
1460 | case CXT5047_LAPTOP: | ||
1461 | spec->num_mixers = 2; | ||
1462 | spec->mixers[1] = cxt5047_hp_spk_mixers; | ||
1463 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; | ||
1464 | break; | ||
1465 | case CXT5047_LAPTOP_HP: | ||
1466 | spec->num_mixers = 2; | ||
1467 | spec->mixers[1] = cxt5047_hp_only_mixers; | ||
1468 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; | ||
1469 | codec->patch_ops.init = cxt5047_hp_init; | ||
1470 | break; | ||
1471 | case CXT5047_LAPTOP_EAPD: | ||
1472 | spec->input_mux = &cxt5047_toshiba_capture_source; | ||
1473 | spec->num_mixers = 2; | ||
1474 | spec->mixers[1] = cxt5047_hp_spk_mixers; | ||
1475 | spec->num_init_verbs = 2; | ||
1476 | spec->init_verbs[1] = cxt5047_toshiba_init_verbs; | ||
1477 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; | ||
1478 | break; | ||
1479 | #ifdef CONFIG_SND_DEBUG | ||
1480 | case CXT5047_TEST: | ||
1481 | spec->input_mux = &cxt5047_test_capture_source; | ||
1482 | spec->mixers[0] = cxt5047_test_mixer; | ||
1483 | spec->init_verbs[0] = cxt5047_test_init_verbs; | ||
1484 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; | ||
1485 | #endif | ||
1486 | } | ||
1487 | spec->vmaster_nid = 0x13; | ||
1488 | |||
1489 | switch (codec->subsystem_id >> 16) { | ||
1490 | case 0x103c: | ||
1491 | /* HP laptops have really bad sound over 0 dB on NID 0x10. | ||
1492 | * Fix max PCM level to 0 dB (originally it has 0x1e steps | ||
1493 | * with 0 dB offset 0x17) | ||
1494 | */ | ||
1495 | snd_hda_override_amp_caps(codec, 0x10, HDA_INPUT, | ||
1496 | (0x17 << AC_AMPCAP_OFFSET_SHIFT) | | ||
1497 | (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | | ||
1498 | (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | | ||
1499 | (1 << AC_AMPCAP_MUTE_SHIFT)); | ||
1500 | break; | ||
1501 | } | ||
1502 | |||
1503 | return 0; | ||
1504 | } | ||
1505 | |||
1506 | /* Conexant 5051 specific */ | ||
1507 | static const hda_nid_t cxt5051_dac_nids[1] = { 0x10 }; | ||
1508 | static const hda_nid_t cxt5051_adc_nids[2] = { 0x14, 0x15 }; | ||
1509 | |||
1510 | static const struct hda_channel_mode cxt5051_modes[1] = { | ||
1511 | { 2, NULL }, | ||
1512 | }; | ||
1513 | |||
1514 | static void cxt5051_update_speaker(struct hda_codec *codec) | ||
1515 | { | ||
1516 | struct conexant_spec *spec = codec->spec; | ||
1517 | unsigned int pinctl; | ||
1518 | /* headphone pin */ | ||
1519 | pinctl = (spec->hp_present && spec->cur_eapd) ? PIN_HP : 0; | ||
1520 | snd_hda_set_pin_ctl(codec, 0x16, pinctl); | ||
1521 | /* speaker pin */ | ||
1522 | pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0; | ||
1523 | snd_hda_set_pin_ctl(codec, 0x1a, pinctl); | ||
1524 | /* on ideapad there is an additional speaker (subwoofer) to mute */ | ||
1525 | if (spec->ideapad) | ||
1526 | snd_hda_set_pin_ctl(codec, 0x1b, pinctl); | ||
1527 | } | ||
1528 | |||
1529 | /* turn on/off EAPD (+ mute HP) as a master switch */ | ||
1530 | static int cxt5051_hp_master_sw_put(struct snd_kcontrol *kcontrol, | ||
1531 | struct snd_ctl_elem_value *ucontrol) | ||
1532 | { | ||
1533 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1534 | |||
1535 | if (!cxt_eapd_put(kcontrol, ucontrol)) | ||
1536 | return 0; | ||
1537 | cxt5051_update_speaker(codec); | ||
1538 | return 1; | ||
1539 | } | ||
1540 | |||
1541 | /* toggle input of built-in and mic jack appropriately */ | ||
1542 | static void cxt5051_portb_automic(struct hda_codec *codec) | ||
1543 | { | ||
1544 | struct conexant_spec *spec = codec->spec; | ||
1545 | unsigned int present; | ||
1546 | |||
1547 | if (!(spec->auto_mic & AUTO_MIC_PORTB)) | ||
1548 | return; | ||
1549 | present = snd_hda_jack_detect(codec, 0x17); | ||
1550 | snd_hda_codec_write(codec, 0x14, 0, | ||
1551 | AC_VERB_SET_CONNECT_SEL, | ||
1552 | present ? 0x01 : 0x00); | ||
1553 | } | ||
1554 | |||
1555 | /* switch the current ADC according to the jack state */ | ||
1556 | static void cxt5051_portc_automic(struct hda_codec *codec) | ||
1557 | { | ||
1558 | struct conexant_spec *spec = codec->spec; | ||
1559 | unsigned int present; | ||
1560 | hda_nid_t new_adc; | ||
1561 | |||
1562 | if (!(spec->auto_mic & AUTO_MIC_PORTC)) | ||
1563 | return; | ||
1564 | present = snd_hda_jack_detect(codec, 0x18); | ||
1565 | if (present) | ||
1566 | spec->cur_adc_idx = 1; | ||
1567 | else | ||
1568 | spec->cur_adc_idx = 0; | ||
1569 | new_adc = spec->adc_nids[spec->cur_adc_idx]; | ||
1570 | if (spec->cur_adc && spec->cur_adc != new_adc) { | ||
1571 | /* stream is running, let's swap the current ADC */ | ||
1572 | __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1); | ||
1573 | spec->cur_adc = new_adc; | ||
1574 | snd_hda_codec_setup_stream(codec, new_adc, | ||
1575 | spec->cur_adc_stream_tag, 0, | ||
1576 | spec->cur_adc_format); | ||
1577 | } | ||
1578 | } | ||
1579 | |||
1580 | /* mute internal speaker if HP is plugged */ | ||
1581 | static void cxt5051_hp_automute(struct hda_codec *codec) | ||
1582 | { | ||
1583 | struct conexant_spec *spec = codec->spec; | ||
1584 | |||
1585 | spec->hp_present = snd_hda_jack_detect(codec, 0x16); | ||
1586 | cxt5051_update_speaker(codec); | ||
1587 | } | ||
1588 | |||
1589 | /* unsolicited event for HP jack sensing */ | ||
1590 | static void cxt5051_hp_unsol_event(struct hda_codec *codec, | ||
1591 | unsigned int res) | ||
1592 | { | ||
1593 | switch (res >> 26) { | ||
1594 | case CONEXANT_HP_EVENT: | ||
1595 | cxt5051_hp_automute(codec); | ||
1596 | break; | ||
1597 | case CXT5051_PORTB_EVENT: | ||
1598 | cxt5051_portb_automic(codec); | ||
1599 | break; | ||
1600 | case CXT5051_PORTC_EVENT: | ||
1601 | cxt5051_portc_automic(codec); | ||
1602 | break; | ||
1603 | } | ||
1604 | } | ||
1605 | |||
1606 | static const struct snd_kcontrol_new cxt5051_playback_mixers[] = { | ||
1607 | HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT), | ||
1608 | { | ||
1609 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1610 | .name = "Master Playback Switch", | ||
1611 | .info = cxt_eapd_info, | ||
1612 | .get = cxt_eapd_get, | ||
1613 | .put = cxt5051_hp_master_sw_put, | ||
1614 | .private_value = 0x1a, | ||
1615 | }, | ||
1616 | {} | ||
1617 | }; | ||
1618 | |||
1619 | static const struct snd_kcontrol_new cxt5051_capture_mixers[] = { | ||
1620 | HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT), | ||
1621 | HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), | ||
1622 | HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x01, HDA_INPUT), | ||
1623 | HDA_CODEC_MUTE("Mic Switch", 0x14, 0x01, HDA_INPUT), | ||
1624 | HDA_CODEC_VOLUME("Dock Mic Volume", 0x15, 0x00, HDA_INPUT), | ||
1625 | HDA_CODEC_MUTE("Dock Mic Switch", 0x15, 0x00, HDA_INPUT), | ||
1626 | {} | ||
1627 | }; | ||
1628 | |||
1629 | static const struct snd_kcontrol_new cxt5051_hp_mixers[] = { | ||
1630 | HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT), | ||
1631 | HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), | ||
1632 | HDA_CODEC_VOLUME("Mic Volume", 0x15, 0x00, HDA_INPUT), | ||
1633 | HDA_CODEC_MUTE("Mic Switch", 0x15, 0x00, HDA_INPUT), | ||
1634 | {} | ||
1635 | }; | ||
1636 | |||
1637 | static const struct snd_kcontrol_new cxt5051_hp_dv6736_mixers[] = { | ||
1638 | HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x00, HDA_INPUT), | ||
1639 | HDA_CODEC_MUTE("Capture Switch", 0x14, 0x00, HDA_INPUT), | ||
1640 | {} | ||
1641 | }; | ||
1642 | |||
1643 | static const struct snd_kcontrol_new cxt5051_f700_mixers[] = { | ||
1644 | HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x01, HDA_INPUT), | ||
1645 | HDA_CODEC_MUTE("Capture Switch", 0x14, 0x01, HDA_INPUT), | ||
1646 | {} | ||
1647 | }; | ||
1648 | |||
1649 | static const struct snd_kcontrol_new cxt5051_toshiba_mixers[] = { | ||
1650 | HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT), | ||
1651 | HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), | ||
1652 | HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x01, HDA_INPUT), | ||
1653 | HDA_CODEC_MUTE("Mic Switch", 0x14, 0x01, HDA_INPUT), | ||
1654 | {} | ||
1655 | }; | ||
1656 | |||
1657 | static const struct hda_verb cxt5051_init_verbs[] = { | ||
1658 | /* Line in, Mic */ | ||
1659 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | ||
1660 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1661 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | ||
1662 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1663 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
1664 | {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | ||
1665 | /* SPK */ | ||
1666 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1667 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1668 | /* HP, Amp */ | ||
1669 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
1670 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1671 | /* DAC1 */ | ||
1672 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1673 | /* Record selector: Internal mic */ | ||
1674 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, | ||
1675 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, | ||
1676 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, | ||
1677 | /* SPDIF route: PCM */ | ||
1678 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1679 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
1680 | /* EAPD */ | ||
1681 | {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
1682 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, | ||
1683 | { } /* end */ | ||
1684 | }; | ||
1685 | |||
1686 | static const struct hda_verb cxt5051_hp_dv6736_init_verbs[] = { | ||
1687 | /* Line in, Mic */ | ||
1688 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | ||
1689 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1690 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, | ||
1691 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, | ||
1692 | /* SPK */ | ||
1693 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1694 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1695 | /* HP, Amp */ | ||
1696 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
1697 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1698 | /* DAC1 */ | ||
1699 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1700 | /* Record selector: Internal mic */ | ||
1701 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, | ||
1702 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
1703 | /* SPDIF route: PCM */ | ||
1704 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
1705 | /* EAPD */ | ||
1706 | {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
1707 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, | ||
1708 | { } /* end */ | ||
1709 | }; | ||
1710 | |||
1711 | static const struct hda_verb cxt5051_f700_init_verbs[] = { | ||
1712 | /* Line in, Mic */ | ||
1713 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | ||
1714 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1715 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, | ||
1716 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, | ||
1717 | /* SPK */ | ||
1718 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1719 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1720 | /* HP, Amp */ | ||
1721 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
1722 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1723 | /* DAC1 */ | ||
1724 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1725 | /* Record selector: Internal mic */ | ||
1726 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, | ||
1727 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
1728 | /* SPDIF route: PCM */ | ||
1729 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
1730 | /* EAPD */ | ||
1731 | {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
1732 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, | ||
1733 | { } /* end */ | ||
1734 | }; | ||
1735 | |||
1736 | static void cxt5051_init_mic_port(struct hda_codec *codec, hda_nid_t nid, | ||
1737 | unsigned int event) | ||
1738 | { | ||
1739 | snd_hda_codec_write(codec, nid, 0, | ||
1740 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
1741 | AC_USRSP_EN | event); | ||
1742 | } | ||
1743 | |||
1744 | static const struct hda_verb cxt5051_ideapad_init_verbs[] = { | ||
1745 | /* Subwoofer */ | ||
1746 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1747 | {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1748 | { } /* end */ | ||
1749 | }; | ||
1750 | |||
1751 | /* initialize jack-sensing, too */ | ||
1752 | static int cxt5051_init(struct hda_codec *codec) | ||
1753 | { | ||
1754 | struct conexant_spec *spec = codec->spec; | ||
1755 | |||
1756 | conexant_init(codec); | ||
1757 | |||
1758 | if (spec->auto_mic & AUTO_MIC_PORTB) | ||
1759 | cxt5051_init_mic_port(codec, 0x17, CXT5051_PORTB_EVENT); | ||
1760 | if (spec->auto_mic & AUTO_MIC_PORTC) | ||
1761 | cxt5051_init_mic_port(codec, 0x18, CXT5051_PORTC_EVENT); | ||
1762 | |||
1763 | if (codec->patch_ops.unsol_event) { | ||
1764 | cxt5051_hp_automute(codec); | ||
1765 | cxt5051_portb_automic(codec); | ||
1766 | cxt5051_portc_automic(codec); | ||
1767 | } | ||
1768 | return 0; | ||
1769 | } | ||
1770 | |||
1771 | |||
1772 | enum { | ||
1773 | CXT5051_LAPTOP, /* Laptops w/ EAPD support */ | ||
1774 | CXT5051_HP, /* no docking */ | ||
1775 | CXT5051_HP_DV6736, /* HP without mic switch */ | ||
1776 | CXT5051_F700, /* HP Compaq Presario F700 */ | ||
1777 | CXT5051_TOSHIBA, /* Toshiba M300 & co */ | ||
1778 | CXT5051_IDEAPAD, /* Lenovo IdeaPad Y430 */ | ||
1779 | CXT5051_AUTO, /* auto-parser */ | ||
1780 | CXT5051_MODELS | ||
1781 | }; | ||
1782 | |||
1783 | static const char *const cxt5051_models[CXT5051_MODELS] = { | ||
1784 | [CXT5051_LAPTOP] = "laptop", | ||
1785 | [CXT5051_HP] = "hp", | ||
1786 | [CXT5051_HP_DV6736] = "hp-dv6736", | ||
1787 | [CXT5051_F700] = "hp-700", | ||
1788 | [CXT5051_TOSHIBA] = "toshiba", | ||
1789 | [CXT5051_IDEAPAD] = "ideapad", | ||
1790 | [CXT5051_AUTO] = "auto", | ||
1791 | }; | ||
1792 | |||
1793 | static const struct snd_pci_quirk cxt5051_cfg_tbl[] = { | ||
1794 | SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV6736", CXT5051_HP_DV6736), | ||
1795 | SND_PCI_QUIRK(0x103c, 0x360b, "Compaq Presario CQ60", CXT5051_HP), | ||
1796 | SND_PCI_QUIRK(0x103c, 0x30ea, "Compaq Presario F700", CXT5051_F700), | ||
1797 | SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba M30x", CXT5051_TOSHIBA), | ||
1798 | SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", | ||
1799 | CXT5051_LAPTOP), | ||
1800 | SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP), | ||
1801 | SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo IdeaPad", CXT5051_IDEAPAD), | ||
1802 | {} | ||
1803 | }; | ||
1804 | |||
1805 | static int patch_cxt5051(struct hda_codec *codec) | ||
1806 | { | ||
1807 | struct conexant_spec *spec; | ||
1808 | int board_config; | ||
1809 | |||
1810 | board_config = snd_hda_check_board_config(codec, CXT5051_MODELS, | ||
1811 | cxt5051_models, | ||
1812 | cxt5051_cfg_tbl); | ||
1813 | if (board_config < 0) | ||
1814 | board_config = CXT5051_AUTO; /* model=auto as default */ | ||
1815 | if (board_config == CXT5051_AUTO) | ||
1816 | return patch_conexant_auto(codec); | ||
1817 | |||
1818 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1819 | if (!spec) | ||
1820 | return -ENOMEM; | ||
1821 | codec->spec = spec; | ||
1822 | codec->pin_amp_workaround = 1; | ||
1823 | |||
1824 | codec->patch_ops = conexant_patch_ops; | ||
1825 | codec->patch_ops.init = cxt5051_init; | ||
1826 | |||
1827 | spec->multiout.max_channels = 2; | ||
1828 | spec->multiout.num_dacs = ARRAY_SIZE(cxt5051_dac_nids); | ||
1829 | spec->multiout.dac_nids = cxt5051_dac_nids; | ||
1830 | spec->multiout.dig_out_nid = CXT5051_SPDIF_OUT; | ||
1831 | spec->num_adc_nids = 1; /* not 2; via auto-mic switch */ | ||
1832 | spec->adc_nids = cxt5051_adc_nids; | ||
1833 | spec->num_mixers = 2; | ||
1834 | spec->mixers[0] = cxt5051_capture_mixers; | ||
1835 | spec->mixers[1] = cxt5051_playback_mixers; | ||
1836 | spec->num_init_verbs = 1; | ||
1837 | spec->init_verbs[0] = cxt5051_init_verbs; | ||
1838 | spec->spdif_route = 0; | ||
1839 | spec->num_channel_mode = ARRAY_SIZE(cxt5051_modes); | ||
1840 | spec->channel_mode = cxt5051_modes; | ||
1841 | spec->cur_adc = 0; | ||
1842 | spec->cur_adc_idx = 0; | ||
1843 | |||
1844 | set_beep_amp(spec, 0x13, 0, HDA_OUTPUT); | ||
1845 | |||
1846 | codec->patch_ops.unsol_event = cxt5051_hp_unsol_event; | ||
1847 | |||
1848 | spec->auto_mic = AUTO_MIC_PORTB | AUTO_MIC_PORTC; | ||
1849 | switch (board_config) { | ||
1850 | case CXT5051_HP: | ||
1851 | spec->mixers[0] = cxt5051_hp_mixers; | ||
1852 | break; | ||
1853 | case CXT5051_HP_DV6736: | ||
1854 | spec->init_verbs[0] = cxt5051_hp_dv6736_init_verbs; | ||
1855 | spec->mixers[0] = cxt5051_hp_dv6736_mixers; | ||
1856 | spec->auto_mic = 0; | ||
1857 | break; | ||
1858 | case CXT5051_F700: | ||
1859 | spec->init_verbs[0] = cxt5051_f700_init_verbs; | ||
1860 | spec->mixers[0] = cxt5051_f700_mixers; | ||
1861 | spec->auto_mic = 0; | ||
1862 | break; | ||
1863 | case CXT5051_TOSHIBA: | ||
1864 | spec->mixers[0] = cxt5051_toshiba_mixers; | ||
1865 | spec->auto_mic = AUTO_MIC_PORTB; | ||
1866 | break; | ||
1867 | case CXT5051_IDEAPAD: | ||
1868 | spec->init_verbs[spec->num_init_verbs++] = | ||
1869 | cxt5051_ideapad_init_verbs; | ||
1870 | spec->ideapad = 1; | ||
1871 | break; | ||
1872 | } | ||
1873 | |||
1874 | if (spec->beep_amp) | ||
1875 | snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp)); | ||
1876 | |||
1877 | return 0; | ||
1878 | } | ||
1879 | |||
1880 | /* Conexant 5066 specific */ | ||
1881 | |||
1882 | static const hda_nid_t cxt5066_dac_nids[1] = { 0x10 }; | ||
1883 | static const hda_nid_t cxt5066_adc_nids[3] = { 0x14, 0x15, 0x16 }; | ||
1884 | static const hda_nid_t cxt5066_capsrc_nids[1] = { 0x17 }; | ||
1885 | static const hda_nid_t cxt5066_digout_pin_nids[2] = { 0x20, 0x22 }; | ||
1886 | |||
1887 | static const struct hda_channel_mode cxt5066_modes[1] = { | ||
1888 | { 2, NULL }, | ||
1889 | }; | ||
1890 | |||
1891 | #define HP_PRESENT_PORT_A (1 << 0) | ||
1892 | #define HP_PRESENT_PORT_D (1 << 1) | ||
1893 | #define hp_port_a_present(spec) ((spec)->hp_present & HP_PRESENT_PORT_A) | ||
1894 | #define hp_port_d_present(spec) ((spec)->hp_present & HP_PRESENT_PORT_D) | ||
1895 | |||
1896 | static void cxt5066_update_speaker(struct hda_codec *codec) | ||
1897 | { | ||
1898 | struct conexant_spec *spec = codec->spec; | ||
1899 | unsigned int pinctl; | ||
1900 | |||
1901 | codec_dbg(codec, | ||
1902 | "CXT5066: update speaker, hp_present=%d, cur_eapd=%d\n", | ||
1903 | spec->hp_present, spec->cur_eapd); | ||
1904 | |||
1905 | /* Port A (HP) */ | ||
1906 | pinctl = (hp_port_a_present(spec) && spec->cur_eapd) ? PIN_HP : 0; | ||
1907 | snd_hda_set_pin_ctl(codec, 0x19, pinctl); | ||
1908 | |||
1909 | /* Port D (HP/LO) */ | ||
1910 | pinctl = spec->cur_eapd ? spec->port_d_mode : 0; | ||
1911 | if (spec->dell_automute || spec->thinkpad) { | ||
1912 | /* Mute if Port A is connected */ | ||
1913 | if (hp_port_a_present(spec)) | ||
1914 | pinctl = 0; | ||
1915 | } else { | ||
1916 | /* Thinkpad/Dell doesn't give pin-D status */ | ||
1917 | if (!hp_port_d_present(spec)) | ||
1918 | pinctl = 0; | ||
1919 | } | ||
1920 | snd_hda_set_pin_ctl(codec, 0x1c, pinctl); | ||
1921 | |||
1922 | /* CLASS_D AMP */ | ||
1923 | pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0; | ||
1924 | snd_hda_set_pin_ctl(codec, 0x1f, pinctl); | ||
1925 | } | ||
1926 | |||
1927 | /* turn on/off EAPD (+ mute HP) as a master switch */ | ||
1928 | static int cxt5066_hp_master_sw_put(struct snd_kcontrol *kcontrol, | ||
1929 | struct snd_ctl_elem_value *ucontrol) | ||
1930 | { | ||
1931 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1932 | |||
1933 | if (!cxt_eapd_put(kcontrol, ucontrol)) | ||
1934 | return 0; | ||
1935 | |||
1936 | cxt5066_update_speaker(codec); | ||
1937 | return 1; | ||
1938 | } | ||
1939 | |||
1940 | /* toggle input of built-in digital mic and mic jack appropriately */ | ||
1941 | static void cxt5066_vostro_automic(struct hda_codec *codec) | ||
1942 | { | ||
1943 | unsigned int present; | ||
1944 | |||
1945 | struct hda_verb ext_mic_present[] = { | ||
1946 | /* enable external mic, port B */ | ||
1947 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1948 | |||
1949 | /* switch to external mic input */ | ||
1950 | {0x17, AC_VERB_SET_CONNECT_SEL, 0}, | ||
1951 | {0x14, AC_VERB_SET_CONNECT_SEL, 0}, | ||
1952 | |||
1953 | /* disable internal digital mic */ | ||
1954 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
1955 | {} | ||
1956 | }; | ||
1957 | static const struct hda_verb ext_mic_absent[] = { | ||
1958 | /* enable internal mic, port C */ | ||
1959 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
1960 | |||
1961 | /* switch to internal mic input */ | ||
1962 | {0x14, AC_VERB_SET_CONNECT_SEL, 2}, | ||
1963 | |||
1964 | /* disable external mic, port B */ | ||
1965 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
1966 | {} | ||
1967 | }; | ||
1968 | |||
1969 | present = snd_hda_jack_detect(codec, 0x1a); | ||
1970 | if (present) { | ||
1971 | codec_dbg(codec, "CXT5066: external microphone detected\n"); | ||
1972 | snd_hda_sequence_write(codec, ext_mic_present); | ||
1973 | } else { | ||
1974 | codec_dbg(codec, "CXT5066: external microphone absent\n"); | ||
1975 | snd_hda_sequence_write(codec, ext_mic_absent); | ||
1976 | } | ||
1977 | } | ||
1978 | |||
1979 | /* toggle input of built-in digital mic and mic jack appropriately */ | ||
1980 | static void cxt5066_ideapad_automic(struct hda_codec *codec) | ||
1981 | { | ||
1982 | unsigned int present; | ||
1983 | |||
1984 | struct hda_verb ext_mic_present[] = { | ||
1985 | {0x14, AC_VERB_SET_CONNECT_SEL, 0}, | ||
1986 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1987 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
1988 | {} | ||
1989 | }; | ||
1990 | static const struct hda_verb ext_mic_absent[] = { | ||
1991 | {0x14, AC_VERB_SET_CONNECT_SEL, 2}, | ||
1992 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
1993 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
1994 | {} | ||
1995 | }; | ||
1996 | |||
1997 | present = snd_hda_jack_detect(codec, 0x1b); | ||
1998 | if (present) { | ||
1999 | codec_dbg(codec, "CXT5066: external microphone detected\n"); | ||
2000 | snd_hda_sequence_write(codec, ext_mic_present); | ||
2001 | } else { | ||
2002 | codec_dbg(codec, "CXT5066: external microphone absent\n"); | ||
2003 | snd_hda_sequence_write(codec, ext_mic_absent); | ||
2004 | } | ||
2005 | } | ||
2006 | |||
2007 | |||
2008 | /* toggle input of built-in digital mic and mic jack appropriately */ | ||
2009 | static void cxt5066_asus_automic(struct hda_codec *codec) | ||
2010 | { | ||
2011 | unsigned int present; | ||
2012 | |||
2013 | present = snd_hda_jack_detect(codec, 0x1b); | ||
2014 | codec_dbg(codec, "CXT5066: external microphone present=%d\n", present); | ||
2015 | snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL, | ||
2016 | present ? 1 : 0); | ||
2017 | } | ||
2018 | |||
2019 | |||
2020 | /* toggle input of built-in digital mic and mic jack appropriately */ | ||
2021 | static void cxt5066_hp_laptop_automic(struct hda_codec *codec) | ||
2022 | { | ||
2023 | unsigned int present; | ||
2024 | |||
2025 | present = snd_hda_jack_detect(codec, 0x1b); | ||
2026 | codec_dbg(codec, "CXT5066: external microphone present=%d\n", present); | ||
2027 | snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL, | ||
2028 | present ? 1 : 3); | ||
2029 | } | ||
2030 | |||
2031 | |||
2032 | /* toggle input of built-in digital mic and mic jack appropriately | ||
2033 | order is: external mic -> dock mic -> interal mic */ | ||
2034 | static void cxt5066_thinkpad_automic(struct hda_codec *codec) | ||
2035 | { | ||
2036 | unsigned int ext_present, dock_present; | ||
2037 | |||
2038 | static const struct hda_verb ext_mic_present[] = { | ||
2039 | {0x14, AC_VERB_SET_CONNECT_SEL, 0}, | ||
2040 | {0x17, AC_VERB_SET_CONNECT_SEL, 1}, | ||
2041 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
2042 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2043 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2044 | {} | ||
2045 | }; | ||
2046 | static const struct hda_verb dock_mic_present[] = { | ||
2047 | {0x14, AC_VERB_SET_CONNECT_SEL, 0}, | ||
2048 | {0x17, AC_VERB_SET_CONNECT_SEL, 0}, | ||
2049 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
2050 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2051 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2052 | {} | ||
2053 | }; | ||
2054 | static const struct hda_verb ext_mic_absent[] = { | ||
2055 | {0x14, AC_VERB_SET_CONNECT_SEL, 2}, | ||
2056 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
2057 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2058 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2059 | {} | ||
2060 | }; | ||
2061 | |||
2062 | ext_present = snd_hda_jack_detect(codec, 0x1b); | ||
2063 | dock_present = snd_hda_jack_detect(codec, 0x1a); | ||
2064 | if (ext_present) { | ||
2065 | codec_dbg(codec, "CXT5066: external microphone detected\n"); | ||
2066 | snd_hda_sequence_write(codec, ext_mic_present); | ||
2067 | } else if (dock_present) { | ||
2068 | codec_dbg(codec, "CXT5066: dock microphone detected\n"); | ||
2069 | snd_hda_sequence_write(codec, dock_mic_present); | ||
2070 | } else { | ||
2071 | codec_dbg(codec, "CXT5066: external microphone absent\n"); | ||
2072 | snd_hda_sequence_write(codec, ext_mic_absent); | ||
2073 | } | ||
2074 | } | ||
2075 | |||
2076 | /* mute internal speaker if HP is plugged */ | ||
2077 | static void cxt5066_hp_automute(struct hda_codec *codec) | ||
2078 | { | ||
2079 | struct conexant_spec *spec = codec->spec; | ||
2080 | unsigned int portA, portD; | ||
2081 | |||
2082 | /* Port A */ | ||
2083 | portA = snd_hda_jack_detect(codec, 0x19); | ||
2084 | |||
2085 | /* Port D */ | ||
2086 | portD = snd_hda_jack_detect(codec, 0x1c); | ||
2087 | |||
2088 | spec->hp_present = portA ? HP_PRESENT_PORT_A : 0; | ||
2089 | spec->hp_present |= portD ? HP_PRESENT_PORT_D : 0; | ||
2090 | codec_dbg(codec, "CXT5066: hp automute portA=%x portD=%x present=%d\n", | ||
2091 | portA, portD, spec->hp_present); | ||
2092 | cxt5066_update_speaker(codec); | ||
2093 | } | ||
2094 | |||
2095 | /* Dispatch the right mic autoswitch function */ | ||
2096 | static void cxt5066_automic(struct hda_codec *codec) | ||
2097 | { | ||
2098 | struct conexant_spec *spec = codec->spec; | ||
2099 | |||
2100 | if (spec->dell_vostro) | ||
2101 | cxt5066_vostro_automic(codec); | ||
2102 | else if (spec->ideapad) | ||
2103 | cxt5066_ideapad_automic(codec); | ||
2104 | else if (spec->thinkpad) | ||
2105 | cxt5066_thinkpad_automic(codec); | ||
2106 | else if (spec->hp_laptop) | ||
2107 | cxt5066_hp_laptop_automic(codec); | ||
2108 | else if (spec->asus) | ||
2109 | cxt5066_asus_automic(codec); | ||
2110 | } | ||
2111 | |||
2112 | /* unsolicited event for jack sensing */ | ||
2113 | static void cxt5066_unsol_event(struct hda_codec *codec, unsigned int res) | ||
2114 | { | ||
2115 | codec_dbg(codec, "CXT5066: unsol event %x (%x)\n", res, res >> 26); | ||
2116 | switch (res >> 26) { | ||
2117 | case CONEXANT_HP_EVENT: | ||
2118 | cxt5066_hp_automute(codec); | ||
2119 | break; | ||
2120 | case CONEXANT_MIC_EVENT: | ||
2121 | cxt5066_automic(codec); | ||
2122 | break; | ||
2123 | } | ||
2124 | } | ||
2125 | |||
2126 | |||
2127 | static const struct hda_input_mux cxt5066_analog_mic_boost = { | ||
2128 | .num_items = 5, | ||
2129 | .items = { | ||
2130 | { "0dB", 0 }, | ||
2131 | { "10dB", 1 }, | ||
2132 | { "20dB", 2 }, | ||
2133 | { "30dB", 3 }, | ||
2134 | { "40dB", 4 }, | ||
2135 | }, | ||
2136 | }; | ||
2137 | |||
2138 | static void cxt5066_set_mic_boost(struct hda_codec *codec) | ||
2139 | { | ||
2140 | struct conexant_spec *spec = codec->spec; | ||
2141 | snd_hda_codec_write_cache(codec, 0x17, 0, | ||
2142 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
2143 | AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT | | ||
2144 | cxt5066_analog_mic_boost.items[spec->mic_boost].index); | ||
2145 | if (spec->ideapad || spec->thinkpad) { | ||
2146 | /* adjust the internal mic as well...it is not through 0x17 */ | ||
2147 | snd_hda_codec_write_cache(codec, 0x23, 0, | ||
2148 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
2149 | AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_INPUT | | ||
2150 | cxt5066_analog_mic_boost. | ||
2151 | items[spec->mic_boost].index); | ||
2152 | } | ||
2153 | } | ||
2154 | |||
2155 | static int cxt5066_mic_boost_mux_enum_info(struct snd_kcontrol *kcontrol, | ||
2156 | struct snd_ctl_elem_info *uinfo) | ||
2157 | { | ||
2158 | return snd_hda_input_mux_info(&cxt5066_analog_mic_boost, uinfo); | ||
2159 | } | ||
2160 | |||
2161 | static int cxt5066_mic_boost_mux_enum_get(struct snd_kcontrol *kcontrol, | ||
2162 | struct snd_ctl_elem_value *ucontrol) | ||
2163 | { | ||
2164 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2165 | struct conexant_spec *spec = codec->spec; | ||
2166 | ucontrol->value.enumerated.item[0] = spec->mic_boost; | ||
2167 | return 0; | ||
2168 | } | ||
2169 | |||
2170 | static int cxt5066_mic_boost_mux_enum_put(struct snd_kcontrol *kcontrol, | ||
2171 | struct snd_ctl_elem_value *ucontrol) | ||
2172 | { | ||
2173 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2174 | struct conexant_spec *spec = codec->spec; | ||
2175 | const struct hda_input_mux *imux = &cxt5066_analog_mic_boost; | ||
2176 | unsigned int idx; | ||
2177 | idx = ucontrol->value.enumerated.item[0]; | ||
2178 | if (idx >= imux->num_items) | ||
2179 | idx = imux->num_items - 1; | ||
2180 | |||
2181 | spec->mic_boost = idx; | ||
2182 | cxt5066_set_mic_boost(codec); | ||
2183 | return 1; | ||
2184 | } | ||
2185 | |||
2186 | static void conexant_check_dig_outs(struct hda_codec *codec, | ||
2187 | const hda_nid_t *dig_pins, | ||
2188 | int num_pins) | ||
2189 | { | ||
2190 | struct conexant_spec *spec = codec->spec; | ||
2191 | hda_nid_t *nid_loc = &spec->multiout.dig_out_nid; | ||
2192 | int i; | ||
2193 | |||
2194 | for (i = 0; i < num_pins; i++, dig_pins++) { | ||
2195 | unsigned int cfg = snd_hda_codec_get_pincfg(codec, *dig_pins); | ||
2196 | if (get_defcfg_connect(cfg) == AC_JACK_PORT_NONE) | ||
2197 | continue; | ||
2198 | if (snd_hda_get_connections(codec, *dig_pins, nid_loc, 1) != 1) | ||
2199 | continue; | ||
2200 | } | ||
2201 | } | ||
2202 | |||
2203 | static const struct hda_input_mux cxt5066_capture_source = { | ||
2204 | .num_items = 4, | ||
2205 | .items = { | ||
2206 | { "Mic B", 0 }, | ||
2207 | { "Mic C", 1 }, | ||
2208 | { "Mic E", 2 }, | ||
2209 | { "Mic F", 3 }, | ||
2210 | }, | ||
2211 | }; | ||
2212 | |||
2213 | static const struct hda_bind_ctls cxt5066_bind_capture_vol_others = { | ||
2214 | .ops = &snd_hda_bind_vol, | ||
2215 | .values = { | ||
2216 | HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_INPUT), | ||
2217 | HDA_COMPOSE_AMP_VAL(0x14, 3, 2, HDA_INPUT), | ||
2218 | 0 | ||
2219 | }, | ||
2220 | }; | ||
2221 | |||
2222 | static const struct hda_bind_ctls cxt5066_bind_capture_sw_others = { | ||
2223 | .ops = &snd_hda_bind_sw, | ||
2224 | .values = { | ||
2225 | HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_INPUT), | ||
2226 | HDA_COMPOSE_AMP_VAL(0x14, 3, 2, HDA_INPUT), | ||
2227 | 0 | ||
2228 | }, | ||
2229 | }; | ||
2230 | |||
2231 | static const struct snd_kcontrol_new cxt5066_mixer_master[] = { | ||
2232 | HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT), | ||
2233 | {} | ||
2234 | }; | ||
2235 | |||
2236 | static const struct snd_kcontrol_new cxt5066_mixers[] = { | ||
2237 | { | ||
2238 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2239 | .name = "Master Playback Switch", | ||
2240 | .info = cxt_eapd_info, | ||
2241 | .get = cxt_eapd_get, | ||
2242 | .put = cxt5066_hp_master_sw_put, | ||
2243 | .private_value = 0x1d, | ||
2244 | }, | ||
2245 | |||
2246 | { | ||
2247 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2248 | .name = "Analog Mic Boost Capture Enum", | ||
2249 | .info = cxt5066_mic_boost_mux_enum_info, | ||
2250 | .get = cxt5066_mic_boost_mux_enum_get, | ||
2251 | .put = cxt5066_mic_boost_mux_enum_put, | ||
2252 | }, | ||
2253 | |||
2254 | HDA_BIND_VOL("Capture Volume", &cxt5066_bind_capture_vol_others), | ||
2255 | HDA_BIND_SW("Capture Switch", &cxt5066_bind_capture_sw_others), | ||
2256 | {} | ||
2257 | }; | ||
2258 | |||
2259 | static const struct snd_kcontrol_new cxt5066_vostro_mixers[] = { | ||
2260 | { | ||
2261 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2262 | .name = "Internal Mic Boost Capture Enum", | ||
2263 | .info = cxt5066_mic_boost_mux_enum_info, | ||
2264 | .get = cxt5066_mic_boost_mux_enum_get, | ||
2265 | .put = cxt5066_mic_boost_mux_enum_put, | ||
2266 | .private_value = 0x23 | 0x100, | ||
2267 | }, | ||
2268 | {} | ||
2269 | }; | ||
2270 | |||
2271 | static const struct hda_verb cxt5066_init_verbs[] = { | ||
2272 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */ | ||
2273 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */ | ||
2274 | {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */ | ||
2275 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */ | ||
2276 | |||
2277 | /* Speakers */ | ||
2278 | {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2279 | {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2280 | |||
2281 | /* HP, Amp */ | ||
2282 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
2283 | {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2284 | |||
2285 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
2286 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2287 | |||
2288 | /* DAC1 */ | ||
2289 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
2290 | |||
2291 | /* Node 14 connections: 0x17 0x18 0x23 0x24 0x27 */ | ||
2292 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50}, | ||
2293 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
2294 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2) | 0x50}, | ||
2295 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
2296 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
2297 | |||
2298 | /* no digital microphone support yet */ | ||
2299 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2300 | |||
2301 | /* Audio input selector */ | ||
2302 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3}, | ||
2303 | |||
2304 | /* SPDIF route: PCM */ | ||
2305 | {0x20, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
2306 | {0x22, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
2307 | |||
2308 | {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2309 | {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2310 | |||
2311 | /* EAPD */ | ||
2312 | {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
2313 | |||
2314 | /* not handling these yet */ | ||
2315 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, | ||
2316 | {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, | ||
2317 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, | ||
2318 | {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, | ||
2319 | {0x1d, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, | ||
2320 | {0x1e, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, | ||
2321 | {0x20, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, | ||
2322 | {0x22, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, | ||
2323 | { } /* end */ | ||
2324 | }; | ||
2325 | |||
2326 | static const struct hda_verb cxt5066_init_verbs_vostro[] = { | ||
2327 | /* Port A: headphones */ | ||
2328 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2329 | {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2330 | |||
2331 | /* Port B: external microphone */ | ||
2332 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2333 | |||
2334 | /* Port C: unused */ | ||
2335 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2336 | |||
2337 | /* Port D: unused */ | ||
2338 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2339 | |||
2340 | /* Port E: unused, but has primary EAPD */ | ||
2341 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2342 | {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
2343 | |||
2344 | /* Port F: unused */ | ||
2345 | {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2346 | |||
2347 | /* Port G: internal speakers */ | ||
2348 | {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2349 | {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2350 | |||
2351 | /* DAC1 */ | ||
2352 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
2353 | |||
2354 | /* DAC2: unused */ | ||
2355 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2356 | |||
2357 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
2358 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
2359 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
2360 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
2361 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
2362 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
2363 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
2364 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
2365 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
2366 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
2367 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
2368 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
2369 | |||
2370 | /* Digital microphone port */ | ||
2371 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
2372 | |||
2373 | /* Audio input selectors */ | ||
2374 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3}, | ||
2375 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | ||
2376 | |||
2377 | /* Disable SPDIF */ | ||
2378 | {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2379 | {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2380 | |||
2381 | /* enable unsolicited events for Port A and B */ | ||
2382 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
2383 | {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | ||
2384 | { } /* end */ | ||
2385 | }; | ||
2386 | |||
2387 | static const struct hda_verb cxt5066_init_verbs_ideapad[] = { | ||
2388 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */ | ||
2389 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */ | ||
2390 | {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */ | ||
2391 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */ | ||
2392 | |||
2393 | /* Speakers */ | ||
2394 | {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2395 | {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2396 | |||
2397 | /* HP, Amp */ | ||
2398 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
2399 | {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2400 | |||
2401 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
2402 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2403 | |||
2404 | /* DAC1 */ | ||
2405 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
2406 | |||
2407 | /* Node 14 connections: 0x17 0x18 0x23 0x24 0x27 */ | ||
2408 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50}, | ||
2409 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
2410 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2) | 0x50}, | ||
2411 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
2412 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
2413 | {0x14, AC_VERB_SET_CONNECT_SEL, 2}, /* default to internal mic */ | ||
2414 | |||
2415 | /* Audio input selector */ | ||
2416 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x2}, | ||
2417 | {0x17, AC_VERB_SET_CONNECT_SEL, 1}, /* route ext mic */ | ||
2418 | |||
2419 | /* SPDIF route: PCM */ | ||
2420 | {0x20, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
2421 | {0x22, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
2422 | |||
2423 | {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2424 | {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2425 | |||
2426 | /* internal microphone */ | ||
2427 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* enable internal mic */ | ||
2428 | |||
2429 | /* EAPD */ | ||
2430 | {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
2431 | |||
2432 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
2433 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | ||
2434 | { } /* end */ | ||
2435 | }; | ||
2436 | |||
2437 | static const struct hda_verb cxt5066_init_verbs_thinkpad[] = { | ||
2438 | {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */ | ||
2439 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */ | ||
2440 | |||
2441 | /* Port G: internal speakers */ | ||
2442 | {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2443 | {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2444 | |||
2445 | /* Port A: HP, Amp */ | ||
2446 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2447 | {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2448 | |||
2449 | /* Port B: Mic Dock */ | ||
2450 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2451 | |||
2452 | /* Port C: Mic */ | ||
2453 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2454 | |||
2455 | /* Port D: HP Dock, Amp */ | ||
2456 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2457 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2458 | |||
2459 | /* DAC1 */ | ||
2460 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
2461 | |||
2462 | /* Node 14 connections: 0x17 0x18 0x23 0x24 0x27 */ | ||
2463 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50}, | ||
2464 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
2465 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2) | 0x50}, | ||
2466 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
2467 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
2468 | {0x14, AC_VERB_SET_CONNECT_SEL, 2}, /* default to internal mic */ | ||
2469 | |||
2470 | /* Audio input selector */ | ||
2471 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x2}, | ||
2472 | {0x17, AC_VERB_SET_CONNECT_SEL, 1}, /* route ext mic */ | ||
2473 | |||
2474 | /* SPDIF route: PCM */ | ||
2475 | {0x20, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
2476 | {0x22, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
2477 | |||
2478 | {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2479 | {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2480 | |||
2481 | /* internal microphone */ | ||
2482 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* enable internal mic */ | ||
2483 | |||
2484 | /* EAPD */ | ||
2485 | {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
2486 | |||
2487 | /* enable unsolicited events for Port A, B, C and D */ | ||
2488 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
2489 | {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
2490 | {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | ||
2491 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | ||
2492 | { } /* end */ | ||
2493 | }; | ||
2494 | |||
2495 | static const struct hda_verb cxt5066_init_verbs_portd_lo[] = { | ||
2496 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2497 | { } /* end */ | ||
2498 | }; | ||
2499 | |||
2500 | |||
2501 | static const struct hda_verb cxt5066_init_verbs_hp_laptop[] = { | ||
2502 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
2503 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
2504 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | ||
2505 | { } /* end */ | ||
2506 | }; | ||
2507 | |||
2508 | /* initialize jack-sensing, too */ | ||
2509 | static int cxt5066_init(struct hda_codec *codec) | ||
2510 | { | ||
2511 | codec_dbg(codec, "CXT5066: init\n"); | ||
2512 | conexant_init(codec); | ||
2513 | if (codec->patch_ops.unsol_event) { | ||
2514 | cxt5066_hp_automute(codec); | ||
2515 | cxt5066_automic(codec); | ||
2516 | } | ||
2517 | cxt5066_set_mic_boost(codec); | ||
2518 | return 0; | ||
2519 | } | ||
2520 | |||
2521 | enum { | ||
2522 | CXT5066_LAPTOP, /* Laptops w/ EAPD support */ | ||
2523 | CXT5066_DELL_LAPTOP, /* Dell Laptop */ | ||
2524 | CXT5066_DELL_VOSTRO, /* Dell Vostro 1015i */ | ||
2525 | CXT5066_IDEAPAD, /* Lenovo IdeaPad U150 */ | ||
2526 | CXT5066_THINKPAD, /* Lenovo ThinkPad T410s, others? */ | ||
2527 | CXT5066_ASUS, /* Asus K52JU, Lenovo G560 - Int mic at 0x1a and Ext mic at 0x1b */ | ||
2528 | CXT5066_HP_LAPTOP, /* HP Laptop */ | ||
2529 | CXT5066_AUTO, /* BIOS auto-parser */ | ||
2530 | CXT5066_MODELS | ||
2531 | }; | ||
2532 | |||
2533 | static const char * const cxt5066_models[CXT5066_MODELS] = { | ||
2534 | [CXT5066_LAPTOP] = "laptop", | ||
2535 | [CXT5066_DELL_LAPTOP] = "dell-laptop", | ||
2536 | [CXT5066_DELL_VOSTRO] = "dell-vostro", | ||
2537 | [CXT5066_IDEAPAD] = "ideapad", | ||
2538 | [CXT5066_THINKPAD] = "thinkpad", | ||
2539 | [CXT5066_ASUS] = "asus", | ||
2540 | [CXT5066_HP_LAPTOP] = "hp-laptop", | ||
2541 | [CXT5066_AUTO] = "auto", | ||
2542 | }; | ||
2543 | |||
2544 | static const struct snd_pci_quirk cxt5066_cfg_tbl[] = { | ||
2545 | SND_PCI_QUIRK_MASK(0x1025, 0xff00, 0x0400, "Acer", CXT5066_IDEAPAD), | ||
2546 | SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTRO), | ||
2547 | SND_PCI_QUIRK(0x1028, 0x02f5, "Dell Vostro 320", CXT5066_IDEAPAD), | ||
2548 | SND_PCI_QUIRK(0x1028, 0x0401, "Dell Vostro 1014", CXT5066_DELL_VOSTRO), | ||
2549 | SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD), | ||
2550 | SND_PCI_QUIRK(0x1028, 0x050f, "Dell Inspiron", CXT5066_IDEAPAD), | ||
2551 | SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP), | ||
2552 | SND_PCI_QUIRK(0x1043, 0x13f3, "Asus A52J", CXT5066_ASUS), | ||
2553 | SND_PCI_QUIRK(0x1043, 0x1643, "Asus K52JU", CXT5066_ASUS), | ||
2554 | SND_PCI_QUIRK(0x1043, 0x1993, "Asus U50F", CXT5066_ASUS), | ||
2555 | SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD), | ||
2556 | SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", | ||
2557 | CXT5066_LAPTOP), | ||
2558 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD), | ||
2559 | SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD), | ||
2560 | SND_PCI_QUIRK(0x17aa, 0x21c6, "Thinkpad Edge 13", CXT5066_ASUS), | ||
2561 | SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS), | ||
2562 | SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS), | ||
2563 | {} | ||
2564 | }; | ||
2565 | |||
2566 | static int patch_cxt5066(struct hda_codec *codec) | ||
2567 | { | ||
2568 | struct conexant_spec *spec; | ||
2569 | int board_config; | ||
2570 | |||
2571 | board_config = snd_hda_check_board_config(codec, CXT5066_MODELS, | ||
2572 | cxt5066_models, cxt5066_cfg_tbl); | ||
2573 | if (board_config < 0) | ||
2574 | board_config = CXT5066_AUTO; /* model=auto as default */ | ||
2575 | if (board_config == CXT5066_AUTO) | ||
2576 | return patch_conexant_auto(codec); | ||
2577 | |||
2578 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
2579 | if (!spec) | ||
2580 | return -ENOMEM; | ||
2581 | codec->spec = spec; | ||
2582 | |||
2583 | codec->patch_ops = conexant_patch_ops; | ||
2584 | codec->patch_ops.init = conexant_init; | ||
2585 | |||
2586 | spec->dell_automute = 0; | ||
2587 | spec->multiout.max_channels = 2; | ||
2588 | spec->multiout.num_dacs = ARRAY_SIZE(cxt5066_dac_nids); | ||
2589 | spec->multiout.dac_nids = cxt5066_dac_nids; | ||
2590 | conexant_check_dig_outs(codec, cxt5066_digout_pin_nids, | ||
2591 | ARRAY_SIZE(cxt5066_digout_pin_nids)); | ||
2592 | spec->num_adc_nids = 1; | ||
2593 | spec->adc_nids = cxt5066_adc_nids; | ||
2594 | spec->capsrc_nids = cxt5066_capsrc_nids; | ||
2595 | spec->input_mux = &cxt5066_capture_source; | ||
2596 | |||
2597 | spec->port_d_mode = PIN_HP; | ||
2598 | |||
2599 | spec->num_init_verbs = 1; | ||
2600 | spec->init_verbs[0] = cxt5066_init_verbs; | ||
2601 | spec->num_channel_mode = ARRAY_SIZE(cxt5066_modes); | ||
2602 | spec->channel_mode = cxt5066_modes; | ||
2603 | spec->cur_adc = 0; | ||
2604 | spec->cur_adc_idx = 0; | ||
2605 | |||
2606 | set_beep_amp(spec, 0x13, 0, HDA_OUTPUT); | ||
2607 | |||
2608 | switch (board_config) { | ||
2609 | default: | ||
2610 | case CXT5066_LAPTOP: | ||
2611 | spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; | ||
2612 | spec->mixers[spec->num_mixers++] = cxt5066_mixers; | ||
2613 | break; | ||
2614 | case CXT5066_DELL_LAPTOP: | ||
2615 | spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; | ||
2616 | spec->mixers[spec->num_mixers++] = cxt5066_mixers; | ||
2617 | |||
2618 | spec->port_d_mode = PIN_OUT; | ||
2619 | spec->init_verbs[spec->num_init_verbs] = cxt5066_init_verbs_portd_lo; | ||
2620 | spec->num_init_verbs++; | ||
2621 | spec->dell_automute = 1; | ||
2622 | break; | ||
2623 | case CXT5066_ASUS: | ||
2624 | case CXT5066_HP_LAPTOP: | ||
2625 | codec->patch_ops.init = cxt5066_init; | ||
2626 | codec->patch_ops.unsol_event = cxt5066_unsol_event; | ||
2627 | spec->init_verbs[spec->num_init_verbs] = | ||
2628 | cxt5066_init_verbs_hp_laptop; | ||
2629 | spec->num_init_verbs++; | ||
2630 | spec->hp_laptop = board_config == CXT5066_HP_LAPTOP; | ||
2631 | spec->asus = board_config == CXT5066_ASUS; | ||
2632 | spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; | ||
2633 | spec->mixers[spec->num_mixers++] = cxt5066_mixers; | ||
2634 | /* no S/PDIF out */ | ||
2635 | if (board_config == CXT5066_HP_LAPTOP) | ||
2636 | spec->multiout.dig_out_nid = 0; | ||
2637 | /* input source automatically selected */ | ||
2638 | spec->input_mux = NULL; | ||
2639 | spec->port_d_mode = 0; | ||
2640 | spec->mic_boost = 3; /* default 30dB gain */ | ||
2641 | break; | ||
2642 | |||
2643 | case CXT5066_DELL_VOSTRO: | ||
2644 | codec->patch_ops.init = cxt5066_init; | ||
2645 | codec->patch_ops.unsol_event = cxt5066_unsol_event; | ||
2646 | spec->init_verbs[0] = cxt5066_init_verbs_vostro; | ||
2647 | spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; | ||
2648 | spec->mixers[spec->num_mixers++] = cxt5066_mixers; | ||
2649 | spec->mixers[spec->num_mixers++] = cxt5066_vostro_mixers; | ||
2650 | spec->port_d_mode = 0; | ||
2651 | spec->dell_vostro = 1; | ||
2652 | spec->mic_boost = 3; /* default 30dB gain */ | ||
2653 | |||
2654 | /* no S/PDIF out */ | ||
2655 | spec->multiout.dig_out_nid = 0; | ||
2656 | |||
2657 | /* input source automatically selected */ | ||
2658 | spec->input_mux = NULL; | ||
2659 | break; | ||
2660 | case CXT5066_IDEAPAD: | ||
2661 | codec->patch_ops.init = cxt5066_init; | ||
2662 | codec->patch_ops.unsol_event = cxt5066_unsol_event; | ||
2663 | spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; | ||
2664 | spec->mixers[spec->num_mixers++] = cxt5066_mixers; | ||
2665 | spec->init_verbs[0] = cxt5066_init_verbs_ideapad; | ||
2666 | spec->port_d_mode = 0; | ||
2667 | spec->ideapad = 1; | ||
2668 | spec->mic_boost = 2; /* default 20dB gain */ | ||
2669 | |||
2670 | /* no S/PDIF out */ | ||
2671 | spec->multiout.dig_out_nid = 0; | ||
2672 | |||
2673 | /* input source automatically selected */ | ||
2674 | spec->input_mux = NULL; | ||
2675 | break; | ||
2676 | case CXT5066_THINKPAD: | ||
2677 | codec->patch_ops.init = cxt5066_init; | ||
2678 | codec->patch_ops.unsol_event = cxt5066_unsol_event; | ||
2679 | spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; | ||
2680 | spec->mixers[spec->num_mixers++] = cxt5066_mixers; | ||
2681 | spec->init_verbs[0] = cxt5066_init_verbs_thinkpad; | ||
2682 | spec->thinkpad = 1; | ||
2683 | spec->port_d_mode = PIN_OUT; | ||
2684 | spec->mic_boost = 2; /* default 20dB gain */ | ||
2685 | |||
2686 | /* no S/PDIF out */ | ||
2687 | spec->multiout.dig_out_nid = 0; | ||
2688 | |||
2689 | /* input source automatically selected */ | ||
2690 | spec->input_mux = NULL; | ||
2691 | break; | ||
2692 | } | ||
2693 | |||
2694 | if (spec->beep_amp) | ||
2695 | snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp)); | ||
2696 | |||
2697 | return 0; | ||
2698 | } | ||
2699 | |||
2700 | #endif /* ENABLE_CXT_STATIC_QUIRKS */ | ||
2701 | |||
2702 | |||
2703 | /* | 97 | /* |
2704 | * Automatic parser for CX20641 & co | 98 | * Automatic parser for CX20641 & co |
2705 | */ | 99 | */ |
@@ -3487,35 +881,28 @@ static int patch_conexant_auto(struct hda_codec *codec) | |||
3487 | return err; | 881 | return err; |
3488 | } | 882 | } |
3489 | 883 | ||
3490 | #ifndef ENABLE_CXT_STATIC_QUIRKS | ||
3491 | #define patch_cxt5045 patch_conexant_auto | ||
3492 | #define patch_cxt5047 patch_conexant_auto | ||
3493 | #define patch_cxt5051 patch_conexant_auto | ||
3494 | #define patch_cxt5066 patch_conexant_auto | ||
3495 | #endif | ||
3496 | |||
3497 | /* | 884 | /* |
3498 | */ | 885 | */ |
3499 | 886 | ||
3500 | static const struct hda_codec_preset snd_hda_preset_conexant[] = { | 887 | static const struct hda_codec_preset snd_hda_preset_conexant[] = { |
3501 | { .id = 0x14f15045, .name = "CX20549 (Venice)", | 888 | { .id = 0x14f15045, .name = "CX20549 (Venice)", |
3502 | .patch = patch_cxt5045 }, | 889 | .patch = patch_conexant_auto }, |
3503 | { .id = 0x14f15047, .name = "CX20551 (Waikiki)", | 890 | { .id = 0x14f15047, .name = "CX20551 (Waikiki)", |
3504 | .patch = patch_cxt5047 }, | 891 | .patch = patch_conexant_auto }, |
3505 | { .id = 0x14f15051, .name = "CX20561 (Hermosa)", | 892 | { .id = 0x14f15051, .name = "CX20561 (Hermosa)", |
3506 | .patch = patch_cxt5051 }, | 893 | .patch = patch_conexant_auto }, |
3507 | { .id = 0x14f15066, .name = "CX20582 (Pebble)", | 894 | { .id = 0x14f15066, .name = "CX20582 (Pebble)", |
3508 | .patch = patch_cxt5066 }, | 895 | .patch = patch_conexant_auto }, |
3509 | { .id = 0x14f15067, .name = "CX20583 (Pebble HSF)", | 896 | { .id = 0x14f15067, .name = "CX20583 (Pebble HSF)", |
3510 | .patch = patch_cxt5066 }, | 897 | .patch = patch_conexant_auto }, |
3511 | { .id = 0x14f15068, .name = "CX20584", | 898 | { .id = 0x14f15068, .name = "CX20584", |
3512 | .patch = patch_cxt5066 }, | 899 | .patch = patch_conexant_auto }, |
3513 | { .id = 0x14f15069, .name = "CX20585", | 900 | { .id = 0x14f15069, .name = "CX20585", |
3514 | .patch = patch_cxt5066 }, | 901 | .patch = patch_conexant_auto }, |
3515 | { .id = 0x14f1506c, .name = "CX20588", | 902 | { .id = 0x14f1506c, .name = "CX20588", |
3516 | .patch = patch_cxt5066 }, | 903 | .patch = patch_conexant_auto }, |
3517 | { .id = 0x14f1506e, .name = "CX20590", | 904 | { .id = 0x14f1506e, .name = "CX20590", |
3518 | .patch = patch_cxt5066 }, | 905 | .patch = patch_conexant_auto }, |
3519 | { .id = 0x14f15097, .name = "CX20631", | 906 | { .id = 0x14f15097, .name = "CX20631", |
3520 | .patch = patch_conexant_auto }, | 907 | .patch = patch_conexant_auto }, |
3521 | { .id = 0x14f15098, .name = "CX20632", | 908 | { .id = 0x14f15098, .name = "CX20632", |
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index ba4ca52072ff..a21090bc1d45 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -648,7 +648,8 @@ static int get_channel_allocation_order(int ca) | |||
648 | * | 648 | * |
649 | * TODO: it could select the wrong CA from multiple candidates. | 649 | * TODO: it could select the wrong CA from multiple candidates. |
650 | */ | 650 | */ |
651 | static int hdmi_channel_allocation(struct hdmi_eld *eld, int channels) | 651 | static int hdmi_channel_allocation(struct hda_codec *codec, |
652 | struct hdmi_eld *eld, int channels) | ||
652 | { | 653 | { |
653 | int i; | 654 | int i; |
654 | int ca = 0; | 655 | int ca = 0; |
@@ -694,7 +695,7 @@ static int hdmi_channel_allocation(struct hdmi_eld *eld, int channels) | |||
694 | } | 695 | } |
695 | 696 | ||
696 | snd_print_channel_allocation(eld->info.spk_alloc, buf, sizeof(buf)); | 697 | snd_print_channel_allocation(eld->info.spk_alloc, buf, sizeof(buf)); |
697 | snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n", | 698 | codec_dbg(codec, "HDMI: select CA 0x%x for %d-channel allocation: %s\n", |
698 | ca, channels, buf); | 699 | ca, channels, buf); |
699 | 700 | ||
700 | return ca; | 701 | return ca; |
@@ -1131,7 +1132,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, | |||
1131 | if (!non_pcm && per_pin->chmap_set) | 1132 | if (!non_pcm && per_pin->chmap_set) |
1132 | ca = hdmi_manual_channel_allocation(channels, per_pin->chmap); | 1133 | ca = hdmi_manual_channel_allocation(channels, per_pin->chmap); |
1133 | else | 1134 | else |
1134 | ca = hdmi_channel_allocation(eld, channels); | 1135 | ca = hdmi_channel_allocation(codec, eld, channels); |
1135 | if (ca < 0) | 1136 | if (ca < 0) |
1136 | ca = 0; | 1137 | ca = 0; |
1137 | 1138 | ||
@@ -1557,13 +1558,13 @@ static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) | |||
1557 | eld->eld_valid = false; | 1558 | eld->eld_valid = false; |
1558 | else { | 1559 | else { |
1559 | memset(&eld->info, 0, sizeof(struct parsed_hdmi_eld)); | 1560 | memset(&eld->info, 0, sizeof(struct parsed_hdmi_eld)); |
1560 | if (snd_hdmi_parse_eld(&eld->info, eld->eld_buffer, | 1561 | if (snd_hdmi_parse_eld(codec, &eld->info, eld->eld_buffer, |
1561 | eld->eld_size) < 0) | 1562 | eld->eld_size) < 0) |
1562 | eld->eld_valid = false; | 1563 | eld->eld_valid = false; |
1563 | } | 1564 | } |
1564 | 1565 | ||
1565 | if (eld->eld_valid) { | 1566 | if (eld->eld_valid) { |
1566 | snd_hdmi_show_eld(&eld->info); | 1567 | snd_hdmi_show_eld(codec, &eld->info); |
1567 | update_eld = true; | 1568 | update_eld = true; |
1568 | } | 1569 | } |
1569 | else if (repoll) { | 1570 | else if (repoll) { |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index b60824e90408..654c8f16d150 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -101,6 +101,7 @@ struct alc_spec { | |||
101 | /* mute LED for HP laptops, see alc269_fixup_mic_mute_hook() */ | 101 | /* mute LED for HP laptops, see alc269_fixup_mic_mute_hook() */ |
102 | int mute_led_polarity; | 102 | int mute_led_polarity; |
103 | hda_nid_t mute_led_nid; | 103 | hda_nid_t mute_led_nid; |
104 | hda_nid_t cap_mute_led_nid; | ||
104 | 105 | ||
105 | unsigned int gpio_led; /* used for alc269_fixup_hp_gpio_led() */ | 106 | unsigned int gpio_led; /* used for alc269_fixup_hp_gpio_led() */ |
106 | 107 | ||
@@ -3402,7 +3403,8 @@ static unsigned int led_power_filter(struct hda_codec *codec, | |||
3402 | { | 3403 | { |
3403 | struct alc_spec *spec = codec->spec; | 3404 | struct alc_spec *spec = codec->spec; |
3404 | 3405 | ||
3405 | if (power_state != AC_PWRST_D3 || nid != spec->mute_led_nid) | 3406 | if (power_state != AC_PWRST_D3 || nid == 0 || |
3407 | (nid != spec->mute_led_nid && nid != spec->cap_mute_led_nid)) | ||
3406 | return power_state; | 3408 | return power_state; |
3407 | 3409 | ||
3408 | /* Set pin ctl again, it might have just been set to 0 */ | 3410 | /* Set pin ctl again, it might have just been set to 0 */ |
@@ -3520,6 +3522,68 @@ static void alc269_fixup_hp_gpio_led(struct hda_codec *codec, | |||
3520 | } | 3522 | } |
3521 | } | 3523 | } |
3522 | 3524 | ||
3525 | /* turn on/off mic-mute LED per capture hook */ | ||
3526 | static void alc269_fixup_hp_cap_mic_mute_hook(struct hda_codec *codec, | ||
3527 | struct snd_kcontrol *kcontrol, | ||
3528 | struct snd_ctl_elem_value *ucontrol) | ||
3529 | { | ||
3530 | struct alc_spec *spec = codec->spec; | ||
3531 | unsigned int pinval, enable, disable; | ||
3532 | |||
3533 | pinval = snd_hda_codec_get_pin_target(codec, spec->cap_mute_led_nid); | ||
3534 | pinval &= ~AC_PINCTL_VREFEN; | ||
3535 | enable = pinval | AC_PINCTL_VREF_80; | ||
3536 | disable = pinval | AC_PINCTL_VREF_HIZ; | ||
3537 | |||
3538 | if (!ucontrol) | ||
3539 | return; | ||
3540 | |||
3541 | if (ucontrol->value.integer.value[0] || | ||
3542 | ucontrol->value.integer.value[1]) | ||
3543 | pinval = disable; | ||
3544 | else | ||
3545 | pinval = enable; | ||
3546 | |||
3547 | if (spec->cap_mute_led_nid) | ||
3548 | snd_hda_set_pin_ctl_cache(codec, spec->cap_mute_led_nid, pinval); | ||
3549 | } | ||
3550 | |||
3551 | static void alc269_fixup_hp_gpio_mic1_led(struct hda_codec *codec, | ||
3552 | const struct hda_fixup *fix, int action) | ||
3553 | { | ||
3554 | struct alc_spec *spec = codec->spec; | ||
3555 | static const struct hda_verb gpio_init[] = { | ||
3556 | { 0x01, AC_VERB_SET_GPIO_MASK, 0x08 }, | ||
3557 | { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x08 }, | ||
3558 | {} | ||
3559 | }; | ||
3560 | |||
3561 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { | ||
3562 | spec->gen.vmaster_mute.hook = alc269_fixup_hp_gpio_mute_hook; | ||
3563 | spec->gen.cap_sync_hook = alc269_fixup_hp_cap_mic_mute_hook; | ||
3564 | spec->gpio_led = 0; | ||
3565 | spec->cap_mute_led_nid = 0x18; | ||
3566 | snd_hda_add_verbs(codec, gpio_init); | ||
3567 | codec->power_filter = led_power_filter; | ||
3568 | } | ||
3569 | } | ||
3570 | |||
3571 | static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec, | ||
3572 | const struct hda_fixup *fix, int action) | ||
3573 | { | ||
3574 | struct alc_spec *spec = codec->spec; | ||
3575 | |||
3576 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { | ||
3577 | spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook; | ||
3578 | spec->gen.cap_sync_hook = alc269_fixup_hp_cap_mic_mute_hook; | ||
3579 | spec->mute_led_polarity = 0; | ||
3580 | spec->mute_led_nid = 0x1a; | ||
3581 | spec->cap_mute_led_nid = 0x18; | ||
3582 | spec->gen.vmaster_mute_enum = 1; | ||
3583 | codec->power_filter = led_power_filter; | ||
3584 | } | ||
3585 | } | ||
3586 | |||
3523 | static void alc_headset_mode_unplugged(struct hda_codec *codec) | 3587 | static void alc_headset_mode_unplugged(struct hda_codec *codec) |
3524 | { | 3588 | { |
3525 | int val; | 3589 | int val; |
@@ -4231,6 +4295,9 @@ static void alc290_fixup_mono_speakers(struct hda_codec *codec, | |||
4231 | /* for hda_fixup_thinkpad_acpi() */ | 4295 | /* for hda_fixup_thinkpad_acpi() */ |
4232 | #include "thinkpad_helper.c" | 4296 | #include "thinkpad_helper.c" |
4233 | 4297 | ||
4298 | /* for dell wmi mic mute led */ | ||
4299 | #include "dell_wmi_helper.c" | ||
4300 | |||
4234 | enum { | 4301 | enum { |
4235 | ALC269_FIXUP_SONY_VAIO, | 4302 | ALC269_FIXUP_SONY_VAIO, |
4236 | ALC275_FIXUP_SONY_VAIO_GPIO2, | 4303 | ALC275_FIXUP_SONY_VAIO_GPIO2, |
@@ -4255,6 +4322,8 @@ enum { | |||
4255 | ALC269_FIXUP_HP_MUTE_LED_MIC1, | 4322 | ALC269_FIXUP_HP_MUTE_LED_MIC1, |
4256 | ALC269_FIXUP_HP_MUTE_LED_MIC2, | 4323 | ALC269_FIXUP_HP_MUTE_LED_MIC2, |
4257 | ALC269_FIXUP_HP_GPIO_LED, | 4324 | ALC269_FIXUP_HP_GPIO_LED, |
4325 | ALC269_FIXUP_HP_GPIO_MIC1_LED, | ||
4326 | ALC269_FIXUP_HP_LINE1_MIC1_LED, | ||
4258 | ALC269_FIXUP_INV_DMIC, | 4327 | ALC269_FIXUP_INV_DMIC, |
4259 | ALC269_FIXUP_LENOVO_DOCK, | 4328 | ALC269_FIXUP_LENOVO_DOCK, |
4260 | ALC269_FIXUP_NO_SHUTUP, | 4329 | ALC269_FIXUP_NO_SHUTUP, |
@@ -4292,6 +4361,8 @@ enum { | |||
4292 | ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC, | 4361 | ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC, |
4293 | ALC293_FIXUP_DELL1_MIC_NO_PRESENCE, | 4362 | ALC293_FIXUP_DELL1_MIC_NO_PRESENCE, |
4294 | ALC292_FIXUP_TPT440_DOCK, | 4363 | ALC292_FIXUP_TPT440_DOCK, |
4364 | ALC283_FIXUP_BXBT2807_MIC, | ||
4365 | ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED, | ||
4295 | }; | 4366 | }; |
4296 | 4367 | ||
4297 | static const struct hda_fixup alc269_fixups[] = { | 4368 | static const struct hda_fixup alc269_fixups[] = { |
@@ -4447,6 +4518,14 @@ static const struct hda_fixup alc269_fixups[] = { | |||
4447 | .type = HDA_FIXUP_FUNC, | 4518 | .type = HDA_FIXUP_FUNC, |
4448 | .v.func = alc269_fixup_hp_gpio_led, | 4519 | .v.func = alc269_fixup_hp_gpio_led, |
4449 | }, | 4520 | }, |
4521 | [ALC269_FIXUP_HP_GPIO_MIC1_LED] = { | ||
4522 | .type = HDA_FIXUP_FUNC, | ||
4523 | .v.func = alc269_fixup_hp_gpio_mic1_led, | ||
4524 | }, | ||
4525 | [ALC269_FIXUP_HP_LINE1_MIC1_LED] = { | ||
4526 | .type = HDA_FIXUP_FUNC, | ||
4527 | .v.func = alc269_fixup_hp_line1_mic1_led, | ||
4528 | }, | ||
4450 | [ALC269_FIXUP_INV_DMIC] = { | 4529 | [ALC269_FIXUP_INV_DMIC] = { |
4451 | .type = HDA_FIXUP_FUNC, | 4530 | .type = HDA_FIXUP_FUNC, |
4452 | .v.func = alc_fixup_inv_dmic_0x12, | 4531 | .v.func = alc_fixup_inv_dmic_0x12, |
@@ -4718,6 +4797,20 @@ static const struct hda_fixup alc269_fixups[] = { | |||
4718 | .chained = true, | 4797 | .chained = true, |
4719 | .chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST | 4798 | .chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST |
4720 | }, | 4799 | }, |
4800 | [ALC283_FIXUP_BXBT2807_MIC] = { | ||
4801 | .type = HDA_FIXUP_PINS, | ||
4802 | .v.pins = (const struct hda_pintbl[]) { | ||
4803 | { 0x19, 0x04a110f0 }, | ||
4804 | { }, | ||
4805 | }, | ||
4806 | }, | ||
4807 | [ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED] = { | ||
4808 | .type = HDA_FIXUP_FUNC, | ||
4809 | .v.func = alc_fixup_dell_wmi, | ||
4810 | .chained_before = true, | ||
4811 | .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE | ||
4812 | }, | ||
4813 | |||
4721 | }; | 4814 | }; |
4722 | 4815 | ||
4723 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { | 4816 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { |
@@ -4727,7 +4820,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
4727 | SND_PCI_QUIRK(0x1025, 0x047c, "Acer AC700", ALC269_FIXUP_ACER_AC700), | 4820 | SND_PCI_QUIRK(0x1025, 0x047c, "Acer AC700", ALC269_FIXUP_ACER_AC700), |
4728 | SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK), | 4821 | SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK), |
4729 | SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK), | 4822 | SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK), |
4730 | SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC), | ||
4731 | SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572), | 4823 | SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572), |
4732 | SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), | 4824 | SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), |
4733 | SND_PCI_QUIRK(0x1028, 0x05bd, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), | 4825 | SND_PCI_QUIRK(0x1028, 0x05bd, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), |
@@ -4761,10 +4853,12 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
4761 | SND_PCI_QUIRK(0x1028, 0x0606, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | 4853 | SND_PCI_QUIRK(0x1028, 0x0606, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), |
4762 | SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | 4854 | SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), |
4763 | SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | 4855 | SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), |
4856 | SND_PCI_QUIRK(0x1028, 0x0610, "Dell", ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED), | ||
4764 | SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | 4857 | SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), |
4765 | SND_PCI_QUIRK(0x1028, 0x0614, "Dell Inspiron 3135", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | 4858 | SND_PCI_QUIRK(0x1028, 0x0614, "Dell Inspiron 3135", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), |
4766 | SND_PCI_QUIRK(0x1028, 0x0615, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK), | 4859 | SND_PCI_QUIRK(0x1028, 0x0615, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK), |
4767 | SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK), | 4860 | SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK), |
4861 | SND_PCI_QUIRK(0x1028, 0x061f, "Dell", ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED), | ||
4768 | SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS_HSJACK), | 4862 | SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS_HSJACK), |
4769 | SND_PCI_QUIRK(0x1028, 0x063f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), | 4863 | SND_PCI_QUIRK(0x1028, 0x063f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), |
4770 | SND_PCI_QUIRK(0x1028, 0x064a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), | 4864 | SND_PCI_QUIRK(0x1028, 0x064a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), |
@@ -4782,6 +4876,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
4782 | SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4876 | SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4783 | SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED), | 4877 | SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED), |
4784 | /* ALC282 */ | 4878 | /* ALC282 */ |
4879 | SND_PCI_QUIRK(0x103c, 0x21f8, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4880 | SND_PCI_QUIRK(0x103c, 0x21f9, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4785 | SND_PCI_QUIRK(0x103c, 0x220d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4881 | SND_PCI_QUIRK(0x103c, 0x220d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4786 | SND_PCI_QUIRK(0x103c, 0x220e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4882 | SND_PCI_QUIRK(0x103c, 0x220e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4787 | SND_PCI_QUIRK(0x103c, 0x220f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4883 | SND_PCI_QUIRK(0x103c, 0x220f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
@@ -4790,6 +4886,20 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
4790 | SND_PCI_QUIRK(0x103c, 0x2212, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4886 | SND_PCI_QUIRK(0x103c, 0x2212, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4791 | SND_PCI_QUIRK(0x103c, 0x2213, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4887 | SND_PCI_QUIRK(0x103c, 0x2213, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4792 | SND_PCI_QUIRK(0x103c, 0x2214, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4888 | SND_PCI_QUIRK(0x103c, 0x2214, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4889 | SND_PCI_QUIRK(0x103c, 0x2234, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4890 | SND_PCI_QUIRK(0x103c, 0x2235, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4891 | SND_PCI_QUIRK(0x103c, 0x2236, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4892 | SND_PCI_QUIRK(0x103c, 0x2237, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4893 | SND_PCI_QUIRK(0x103c, 0x2238, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4894 | SND_PCI_QUIRK(0x103c, 0x2239, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4895 | SND_PCI_QUIRK(0x103c, 0x2246, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4896 | SND_PCI_QUIRK(0x103c, 0x2247, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4897 | SND_PCI_QUIRK(0x103c, 0x2248, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4898 | SND_PCI_QUIRK(0x103c, 0x2249, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4899 | SND_PCI_QUIRK(0x103c, 0x224a, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4900 | SND_PCI_QUIRK(0x103c, 0x224b, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4901 | SND_PCI_QUIRK(0x103c, 0x224c, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4902 | SND_PCI_QUIRK(0x103c, 0x224d, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4793 | SND_PCI_QUIRK(0x103c, 0x2266, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4903 | SND_PCI_QUIRK(0x103c, 0x2266, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4794 | SND_PCI_QUIRK(0x103c, 0x2267, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4904 | SND_PCI_QUIRK(0x103c, 0x2267, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4795 | SND_PCI_QUIRK(0x103c, 0x2268, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4905 | SND_PCI_QUIRK(0x103c, 0x2268, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
@@ -4814,13 +4924,43 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
4814 | SND_PCI_QUIRK(0x103c, 0x22ce, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4924 | SND_PCI_QUIRK(0x103c, 0x22ce, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4815 | SND_PCI_QUIRK(0x103c, 0x22cf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4925 | SND_PCI_QUIRK(0x103c, 0x22cf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4816 | SND_PCI_QUIRK(0x103c, 0x22d0, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4926 | SND_PCI_QUIRK(0x103c, 0x22d0, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4927 | SND_PCI_QUIRK(0x103c, 0x22da, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4928 | SND_PCI_QUIRK(0x103c, 0x22db, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4929 | SND_PCI_QUIRK(0x103c, 0x22dc, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4930 | SND_PCI_QUIRK(0x103c, 0x22fb, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4931 | SND_PCI_QUIRK(0x103c, 0x8004, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4817 | /* ALC290 */ | 4932 | /* ALC290 */ |
4933 | SND_PCI_QUIRK(0x103c, 0x221b, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4934 | SND_PCI_QUIRK(0x103c, 0x221c, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4935 | SND_PCI_QUIRK(0x103c, 0x221d, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4936 | SND_PCI_QUIRK(0x103c, 0x2220, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4937 | SND_PCI_QUIRK(0x103c, 0x2221, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4938 | SND_PCI_QUIRK(0x103c, 0x2222, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4939 | SND_PCI_QUIRK(0x103c, 0x2223, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4940 | SND_PCI_QUIRK(0x103c, 0x2224, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4941 | SND_PCI_QUIRK(0x103c, 0x2225, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4942 | SND_PCI_QUIRK(0x103c, 0x2246, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4943 | SND_PCI_QUIRK(0x103c, 0x2247, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4944 | SND_PCI_QUIRK(0x103c, 0x2248, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4945 | SND_PCI_QUIRK(0x103c, 0x2249, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4946 | SND_PCI_QUIRK(0x103c, 0x2253, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4947 | SND_PCI_QUIRK(0x103c, 0x2254, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4948 | SND_PCI_QUIRK(0x103c, 0x2255, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4949 | SND_PCI_QUIRK(0x103c, 0x2256, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4950 | SND_PCI_QUIRK(0x103c, 0x2257, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4951 | SND_PCI_QUIRK(0x103c, 0x2258, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4952 | SND_PCI_QUIRK(0x103c, 0x2259, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4953 | SND_PCI_QUIRK(0x103c, 0x225a, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4818 | SND_PCI_QUIRK(0x103c, 0x2260, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4954 | SND_PCI_QUIRK(0x103c, 0x2260, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4819 | SND_PCI_QUIRK(0x103c, 0x2261, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4955 | SND_PCI_QUIRK(0x103c, 0x2261, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4820 | SND_PCI_QUIRK(0x103c, 0x2262, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4956 | SND_PCI_QUIRK(0x103c, 0x2262, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4821 | SND_PCI_QUIRK(0x103c, 0x2263, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4957 | SND_PCI_QUIRK(0x103c, 0x2263, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4822 | SND_PCI_QUIRK(0x103c, 0x2264, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4958 | SND_PCI_QUIRK(0x103c, 0x2264, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4823 | SND_PCI_QUIRK(0x103c, 0x2265, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4959 | SND_PCI_QUIRK(0x103c, 0x2265, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4960 | SND_PCI_QUIRK(0x103c, 0x2272, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4961 | SND_PCI_QUIRK(0x103c, 0x2273, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4962 | SND_PCI_QUIRK(0x103c, 0x2277, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4963 | SND_PCI_QUIRK(0x103c, 0x2278, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4824 | SND_PCI_QUIRK(0x103c, 0x227d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4964 | SND_PCI_QUIRK(0x103c, 0x227d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4825 | SND_PCI_QUIRK(0x103c, 0x227e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4965 | SND_PCI_QUIRK(0x103c, 0x227e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4826 | SND_PCI_QUIRK(0x103c, 0x227f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4966 | SND_PCI_QUIRK(0x103c, 0x227f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
@@ -4843,7 +4983,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
4843 | SND_PCI_QUIRK(0x103c, 0x2335, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4983 | SND_PCI_QUIRK(0x103c, 0x2335, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4844 | SND_PCI_QUIRK(0x103c, 0x2336, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4984 | SND_PCI_QUIRK(0x103c, 0x2336, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4845 | SND_PCI_QUIRK(0x103c, 0x2337, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4985 | SND_PCI_QUIRK(0x103c, 0x2337, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4846 | SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED), | ||
4847 | SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300), | 4986 | SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300), |
4848 | SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 4987 | SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
4849 | SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 4988 | SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
@@ -4864,9 +5003,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
4864 | SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), | 5003 | SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), |
4865 | SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), | 5004 | SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), |
4866 | SND_PCI_QUIRK(0x104d, 0x9099, "Sony VAIO S13", ALC275_FIXUP_SONY_DISABLE_AAMIX), | 5005 | SND_PCI_QUIRK(0x104d, 0x9099, "Sony VAIO S13", ALC275_FIXUP_SONY_DISABLE_AAMIX), |
4867 | SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), | ||
4868 | SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK), | 5006 | SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK), |
4869 | SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC), | 5007 | SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC), |
5008 | SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_BXBT2807_MIC), | ||
4870 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), | 5009 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), |
4871 | SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE), | 5010 | SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE), |
4872 | SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE), | 5011 | SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE), |
@@ -4891,7 +5030,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
4891 | SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 5030 | SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
4892 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K), | 5031 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K), |
4893 | SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD), | 5032 | SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD), |
4894 | SND_PCI_QUIRK_VENDOR(0x17aa, "Thinkpad", ALC269_FIXUP_THINKPAD_ACPI), | ||
4895 | SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */ | 5033 | SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */ |
4896 | 5034 | ||
4897 | #if 0 | 5035 | #if 0 |
@@ -4945,6 +5083,14 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
4945 | {} | 5083 | {} |
4946 | }; | 5084 | }; |
4947 | 5085 | ||
5086 | static const struct snd_pci_quirk alc269_fixup_vendor_tbl[] = { | ||
5087 | SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC), | ||
5088 | SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED), | ||
5089 | SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), | ||
5090 | SND_PCI_QUIRK_VENDOR(0x17aa, "Thinkpad", ALC269_FIXUP_THINKPAD_ACPI), | ||
5091 | {} | ||
5092 | }; | ||
5093 | |||
4948 | static const struct hda_model_fixup alc269_fixup_models[] = { | 5094 | static const struct hda_model_fixup alc269_fixup_models[] = { |
4949 | {.id = ALC269_FIXUP_AMIC, .name = "laptop-amic"}, | 5095 | {.id = ALC269_FIXUP_AMIC, .name = "laptop-amic"}, |
4950 | {.id = ALC269_FIXUP_DMIC, .name = "laptop-dmic"}, | 5096 | {.id = ALC269_FIXUP_DMIC, .name = "laptop-dmic"}, |
@@ -5040,6 +5186,17 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { | |||
5040 | {0x1d, 0x40700001}, | 5186 | {0x1d, 0x40700001}, |
5041 | {0x1e, 0x411111f0}, | 5187 | {0x1e, 0x411111f0}, |
5042 | {0x21, 0x02211040}), | 5188 | {0x21, 0x02211040}), |
5189 | SND_HDA_PIN_QUIRK(0x10ec0282, 0x103c, "HP 15 Touchsmart", ALC269_FIXUP_HP_MUTE_LED_MIC1, | ||
5190 | {0x12, 0x99a30130}, | ||
5191 | {0x14, 0x90170110}, | ||
5192 | {0x17, 0x40000000}, | ||
5193 | {0x18, 0x411111f0}, | ||
5194 | {0x19, 0x03a11020}, | ||
5195 | {0x1a, 0x411111f0}, | ||
5196 | {0x1b, 0x411111f0}, | ||
5197 | {0x1d, 0x40f41905}, | ||
5198 | {0x1e, 0x411111f0}, | ||
5199 | {0x21, 0x0321101f}), | ||
5043 | SND_HDA_PIN_QUIRK(0x10ec0283, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, | 5200 | SND_HDA_PIN_QUIRK(0x10ec0283, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, |
5044 | {0x12, 0x90a60130}, | 5201 | {0x12, 0x90a60130}, |
5045 | {0x14, 0x90170110}, | 5202 | {0x14, 0x90170110}, |
@@ -5162,6 +5319,8 @@ static int patch_alc269(struct hda_codec *codec) | |||
5162 | snd_hda_pick_fixup(codec, alc269_fixup_models, | 5319 | snd_hda_pick_fixup(codec, alc269_fixup_models, |
5163 | alc269_fixup_tbl, alc269_fixups); | 5320 | alc269_fixup_tbl, alc269_fixups); |
5164 | snd_hda_pick_pin_fixup(codec, alc269_pin_fixup_tbl, alc269_fixups); | 5321 | snd_hda_pick_pin_fixup(codec, alc269_pin_fixup_tbl, alc269_fixups); |
5322 | snd_hda_pick_fixup(codec, NULL, alc269_fixup_vendor_tbl, | ||
5323 | alc269_fixups); | ||
5165 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 5324 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
5166 | 5325 | ||
5167 | alc_auto_parse_customize_define(codec); | 5326 | alc_auto_parse_customize_define(codec); |
@@ -5858,6 +6017,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { | |||
5858 | SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), | 6017 | SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), |
5859 | SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), | 6018 | SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), |
5860 | SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), | 6019 | SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), |
6020 | SND_PCI_QUIRK(0x1028, 0x05fe, "Dell XPS 15", ALC668_FIXUP_DELL_XPS13), | ||
5861 | SND_PCI_QUIRK(0x1028, 0x060a, "Dell XPS 13", ALC668_FIXUP_DELL_XPS13), | 6021 | SND_PCI_QUIRK(0x1028, 0x060a, "Dell XPS 13", ALC668_FIXUP_DELL_XPS13), |
5862 | SND_PCI_QUIRK(0x1028, 0x0625, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), | 6022 | SND_PCI_QUIRK(0x1028, 0x0625, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), |
5863 | SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), | 6023 | SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 4d3a3b932690..ea823e1100da 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -104,6 +104,7 @@ enum { | |||
104 | STAC_92HD83XXX_HP, | 104 | STAC_92HD83XXX_HP, |
105 | STAC_HP_ENVY_BASS, | 105 | STAC_HP_ENVY_BASS, |
106 | STAC_HP_BNB13_EQ, | 106 | STAC_HP_BNB13_EQ, |
107 | STAC_HP_ENVY_TS_BASS, | ||
107 | STAC_92HD83XXX_MODELS | 108 | STAC_92HD83XXX_MODELS |
108 | }; | 109 | }; |
109 | 110 | ||
@@ -1018,7 +1019,7 @@ static int stac_create_spdif_mux_ctls(struct hda_codec *codec) | |||
1018 | for (i = 0; i < num_cons; i++) { | 1019 | for (i = 0; i < num_cons; i++) { |
1019 | if (snd_BUG_ON(!labels[i])) | 1020 | if (snd_BUG_ON(!labels[i])) |
1020 | return -EINVAL; | 1021 | return -EINVAL; |
1021 | snd_hda_add_imux_item(&spec->spdif_mux, labels[i], i, NULL); | 1022 | snd_hda_add_imux_item(codec, &spec->spdif_mux, labels[i], i, NULL); |
1022 | } | 1023 | } |
1023 | 1024 | ||
1024 | kctl = snd_hda_gen_add_kctl(&spec->gen, NULL, &stac_smux_mixer); | 1025 | kctl = snd_hda_gen_add_kctl(&spec->gen, NULL, &stac_smux_mixer); |
@@ -2680,6 +2681,13 @@ static const struct hda_fixup stac92hd83xxx_fixups[] = { | |||
2680 | .chained = true, | 2681 | .chained = true, |
2681 | .chain_id = STAC_92HD83XXX_HP_MIC_LED, | 2682 | .chain_id = STAC_92HD83XXX_HP_MIC_LED, |
2682 | }, | 2683 | }, |
2684 | [STAC_HP_ENVY_TS_BASS] = { | ||
2685 | .type = HDA_FIXUP_PINS, | ||
2686 | .v.pins = (const struct hda_pintbl[]) { | ||
2687 | { 0x10, 0x92170111 }, | ||
2688 | {} | ||
2689 | }, | ||
2690 | }, | ||
2683 | }; | 2691 | }; |
2684 | 2692 | ||
2685 | static const struct hda_model_fixup stac92hd83xxx_models[] = { | 2693 | static const struct hda_model_fixup stac92hd83xxx_models[] = { |
@@ -2696,6 +2704,7 @@ static const struct hda_model_fixup stac92hd83xxx_models[] = { | |||
2696 | { .id = STAC_92HD83XXX_HEADSET_JACK, .name = "headset-jack" }, | 2704 | { .id = STAC_92HD83XXX_HEADSET_JACK, .name = "headset-jack" }, |
2697 | { .id = STAC_HP_ENVY_BASS, .name = "hp-envy-bass" }, | 2705 | { .id = STAC_HP_ENVY_BASS, .name = "hp-envy-bass" }, |
2698 | { .id = STAC_HP_BNB13_EQ, .name = "hp-bnb13-eq" }, | 2706 | { .id = STAC_HP_BNB13_EQ, .name = "hp-bnb13-eq" }, |
2707 | { .id = STAC_HP_ENVY_TS_BASS, .name = "hp-envy-ts-bass" }, | ||
2699 | {} | 2708 | {} |
2700 | }; | 2709 | }; |
2701 | 2710 | ||
@@ -2751,6 +2760,8 @@ static const struct snd_pci_quirk stac92hd83xxx_fixup_tbl[] = { | |||
2751 | "HP bNB13", STAC_HP_BNB13_EQ), | 2760 | "HP bNB13", STAC_HP_BNB13_EQ), |
2752 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x190A, | 2761 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x190A, |
2753 | "HP bNB13", STAC_HP_BNB13_EQ), | 2762 | "HP bNB13", STAC_HP_BNB13_EQ), |
2763 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x190e, | ||
2764 | "HP ENVY TS", STAC_HP_ENVY_TS_BASS), | ||
2754 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1940, | 2765 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1940, |
2755 | "HP bNB13", STAC_HP_BNB13_EQ), | 2766 | "HP bNB13", STAC_HP_BNB13_EQ), |
2756 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1941, | 2767 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1941, |
@@ -3450,9 +3461,11 @@ static void stac922x_fixup_intel_mac_auto(struct hda_codec *codec, | |||
3450 | { | 3461 | { |
3451 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | 3462 | if (action != HDA_FIXUP_ACT_PRE_PROBE) |
3452 | return; | 3463 | return; |
3464 | |||
3465 | codec->fixup_id = HDA_FIXUP_ID_NOT_SET; | ||
3453 | snd_hda_pick_fixup(codec, NULL, stac922x_intel_mac_fixup_tbl, | 3466 | snd_hda_pick_fixup(codec, NULL, stac922x_intel_mac_fixup_tbl, |
3454 | stac922x_fixups); | 3467 | stac922x_fixups); |
3455 | if (codec->fixup_id != STAC_INTEL_MAC_AUTO) | 3468 | if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET) |
3456 | snd_hda_apply_fixup(codec, action); | 3469 | snd_hda_apply_fixup(codec, action); |
3457 | } | 3470 | } |
3458 | 3471 | ||
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h index b209fc30b334..58f8f2ae758d 100644 --- a/sound/pci/ice1712/ice1712.h +++ b/sound/pci/ice1712/ice1712.h | |||
@@ -41,14 +41,17 @@ | |||
41 | #define ICEREG(ice, x) ((ice)->port + ICE1712_REG_##x) | 41 | #define ICEREG(ice, x) ((ice)->port + ICE1712_REG_##x) |
42 | 42 | ||
43 | #define ICE1712_REG_CONTROL 0x00 /* byte */ | 43 | #define ICE1712_REG_CONTROL 0x00 /* byte */ |
44 | #define ICE1712_RESET 0x80 /* reset whole chip */ | 44 | #define ICE1712_RESET 0x80 /* soft reset whole chip */ |
45 | #define ICE1712_SERR_LEVEL 0x04 /* SERR# level otherwise edge */ | 45 | #define ICE1712_SERR_ASSERT_DS_DMA 0x40 /* disabled SERR# assertion for the DS DMA Ch-C irq otherwise enabled */ |
46 | #define ICE1712_DOS_VOL 0x10 /* DOS WT/FM volume control */ | ||
47 | #define ICE1712_SERR_LEVEL 0x08 /* SERR# level otherwise edge */ | ||
48 | #define ICE1712_SERR_ASSERT_SB 0x02 /* disabled SERR# assertion for SB irq otherwise enabled */ | ||
46 | #define ICE1712_NATIVE 0x01 /* native mode otherwise SB */ | 49 | #define ICE1712_NATIVE 0x01 /* native mode otherwise SB */ |
47 | #define ICE1712_REG_IRQMASK 0x01 /* byte */ | 50 | #define ICE1712_REG_IRQMASK 0x01 /* byte */ |
48 | #define ICE1712_IRQ_MPU1 0x80 | 51 | #define ICE1712_IRQ_MPU1 0x80 /* MIDI irq mask */ |
49 | #define ICE1712_IRQ_TIMER 0x40 | 52 | #define ICE1712_IRQ_TIMER 0x40 /* Timer mask */ |
50 | #define ICE1712_IRQ_MPU2 0x20 | 53 | #define ICE1712_IRQ_MPU2 0x20 /* Secondary MIDI irq mask */ |
51 | #define ICE1712_IRQ_PROPCM 0x10 | 54 | #define ICE1712_IRQ_PROPCM 0x10 /* professional multi-track */ |
52 | #define ICE1712_IRQ_FM 0x08 /* FM/MIDI - legacy */ | 55 | #define ICE1712_IRQ_FM 0x08 /* FM/MIDI - legacy */ |
53 | #define ICE1712_IRQ_PBKDS 0x04 /* playback DS channels */ | 56 | #define ICE1712_IRQ_PBKDS 0x04 /* playback DS channels */ |
54 | #define ICE1712_IRQ_CONCAP 0x02 /* consumer capture */ | 57 | #define ICE1712_IRQ_CONCAP 0x02 /* consumer capture */ |
diff --git a/sound/pci/mixart/mixart_core.c b/sound/pci/mixart/mixart_core.c index 71f4bdcc4055..84f67450924e 100644 --- a/sound/pci/mixart/mixart_core.c +++ b/sound/pci/mixart/mixart_core.c | |||
@@ -151,13 +151,11 @@ static int send_msg( struct mixart_mgr *mgr, | |||
151 | { | 151 | { |
152 | u32 headptr, tailptr; | 152 | u32 headptr, tailptr; |
153 | u32 msg_frame_address; | 153 | u32 msg_frame_address; |
154 | int err, i; | 154 | int i; |
155 | 155 | ||
156 | if (snd_BUG_ON(msg->size % 4)) | 156 | if (snd_BUG_ON(msg->size % 4)) |
157 | return -EINVAL; | 157 | return -EINVAL; |
158 | 158 | ||
159 | err = 0; | ||
160 | |||
161 | /* get message frame address */ | 159 | /* get message frame address */ |
162 | tailptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_TAIL)); | 160 | tailptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_TAIL)); |
163 | headptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_HEAD)); | 161 | headptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_HEAD)); |
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 1272c18a2544..da875dced2ef 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c | |||
@@ -3880,14 +3880,12 @@ void snd_trident_free_voice(struct snd_trident * trident, struct snd_trident_voi | |||
3880 | { | 3880 | { |
3881 | unsigned long flags; | 3881 | unsigned long flags; |
3882 | void (*private_free)(struct snd_trident_voice *); | 3882 | void (*private_free)(struct snd_trident_voice *); |
3883 | void *private_data; | ||
3884 | 3883 | ||
3885 | if (voice == NULL || !voice->use) | 3884 | if (voice == NULL || !voice->use) |
3886 | return; | 3885 | return; |
3887 | snd_trident_clear_voices(trident, voice->number, voice->number); | 3886 | snd_trident_clear_voices(trident, voice->number, voice->number); |
3888 | spin_lock_irqsave(&trident->voice_alloc, flags); | 3887 | spin_lock_irqsave(&trident->voice_alloc, flags); |
3889 | private_free = voice->private_free; | 3888 | private_free = voice->private_free; |
3890 | private_data = voice->private_data; | ||
3891 | voice->private_free = NULL; | 3889 | voice->private_free = NULL; |
3892 | voice->private_data = NULL; | 3890 | voice->private_data = NULL; |
3893 | if (voice->pcm) | 3891 | if (voice->pcm) |
diff --git a/sound/pci/trident/trident_memory.c b/sound/pci/trident/trident_memory.c index 3102a579660b..04c474658e3c 100644 --- a/sound/pci/trident/trident_memory.c +++ b/sound/pci/trident/trident_memory.c | |||
@@ -139,12 +139,11 @@ static inline void *offset_ptr(struct snd_trident *trident, int offset) | |||
139 | static struct snd_util_memblk * | 139 | static struct snd_util_memblk * |
140 | search_empty(struct snd_util_memhdr *hdr, int size) | 140 | search_empty(struct snd_util_memhdr *hdr, int size) |
141 | { | 141 | { |
142 | struct snd_util_memblk *blk, *prev; | 142 | struct snd_util_memblk *blk; |
143 | int page, psize; | 143 | int page, psize; |
144 | struct list_head *p; | 144 | struct list_head *p; |
145 | 145 | ||
146 | psize = get_aligned_page(size + ALIGN_PAGE_SIZE -1); | 146 | psize = get_aligned_page(size + ALIGN_PAGE_SIZE -1); |
147 | prev = NULL; | ||
148 | page = 0; | 147 | page = 0; |
149 | list_for_each(p, &hdr->block) { | 148 | list_for_each(p, &hdr->block) { |
150 | blk = list_entry(p, struct snd_util_memblk, list); | 149 | blk = list_entry(p, struct snd_util_memblk, list); |