aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/pci/hda/patch_analog.c266
1 files changed, 261 insertions, 5 deletions
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index a186b3da20b7..5d8328a64207 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -35,6 +35,10 @@
35struct ad198x_spec { 35struct ad198x_spec {
36 struct hda_gen_spec gen; 36 struct hda_gen_spec gen;
37 37
38 /* for auto parser */
39 int smux_paths[4];
40 unsigned int cur_smux;
41
38 const struct snd_kcontrol_new *mixers[6]; 42 const struct snd_kcontrol_new *mixers[6];
39 int num_mixers; 43 int num_mixers;
40 unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */ 44 unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
@@ -1519,13 +1523,94 @@ static const char * const ad1983_models[AD1983_MODELS] = {
1519 [AD1983_BASIC] = "basic", 1523 [AD1983_BASIC] = "basic",
1520}; 1524};
1521 1525
1526/*
1527 * SPDIF mux control for AD1983 auto-parser
1528 */
1529static int ad1983_auto_smux_enum_info(struct snd_kcontrol *kcontrol,
1530 struct snd_ctl_elem_info *uinfo)
1531{
1532 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1533 struct ad198x_spec *spec = codec->spec;
1534 static const char * const texts2[] = { "PCM", "ADC" };
1535 static const char * const texts3[] = { "PCM", "ADC1", "ADC2" };
1536 hda_nid_t dig_out = spec->gen.multiout.dig_out_nid;
1537 int num_conns = snd_hda_get_num_conns(codec, dig_out);
1538
1539 if (num_conns == 2)
1540 return snd_hda_enum_helper_info(kcontrol, uinfo, 2, texts2);
1541 else if (num_conns == 3)
1542 return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3);
1543 else
1544 return -EINVAL;
1545}
1546
1547static int ad1983_auto_smux_enum_get(struct snd_kcontrol *kcontrol,
1548 struct snd_ctl_elem_value *ucontrol)
1549{
1550 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1551 struct ad198x_spec *spec = codec->spec;
1552
1553 ucontrol->value.enumerated.item[0] = spec->cur_smux;
1554 return 0;
1555}
1556
1557static int ad1983_auto_smux_enum_put(struct snd_kcontrol *kcontrol,
1558 struct snd_ctl_elem_value *ucontrol)
1559{
1560 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1561 struct ad198x_spec *spec = codec->spec;
1562 unsigned int val = ucontrol->value.enumerated.item[0];
1563 hda_nid_t dig_out = spec->gen.multiout.dig_out_nid;
1564 int num_conns = snd_hda_get_num_conns(codec, dig_out);
1565
1566 if (val >= num_conns)
1567 return -EINVAL;
1568 if (spec->cur_smux == val)
1569 return 0;
1570 spec->cur_smux = val;
1571 snd_hda_codec_write_cache(codec, dig_out, 0,
1572 AC_VERB_SET_CONNECT_SEL, val);
1573 return 1;
1574}
1575
1576static struct snd_kcontrol_new ad1983_auto_smux_mixer = {
1577 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1578 .name = "IEC958 Playback Source",
1579 .info = ad1983_auto_smux_enum_info,
1580 .get = ad1983_auto_smux_enum_get,
1581 .put = ad1983_auto_smux_enum_put,
1582};
1583
1584static int ad1983_add_spdif_mux_ctl(struct hda_codec *codec)
1585{
1586 struct ad198x_spec *spec = codec->spec;
1587 hda_nid_t dig_out = spec->gen.multiout.dig_out_nid;
1588 int num_conns;
1589
1590 if (!dig_out)
1591 return 0;
1592 num_conns = snd_hda_get_num_conns(codec, dig_out);
1593 if (num_conns != 2 && num_conns != 3)
1594 return 0;
1595 if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &ad1983_auto_smux_mixer))
1596 return -ENOMEM;
1597 return 0;
1598}
1599
1522static int ad1983_parse_auto_config(struct hda_codec *codec) 1600static int ad1983_parse_auto_config(struct hda_codec *codec)
1523{ 1601{
1524 struct ad198x_spec *spec = codec->spec; 1602 struct ad198x_spec *spec = codec->spec;
1603 int err;
1525 1604
1526 spec->beep_dev_nid = 0x10; 1605 spec->beep_dev_nid = 0x10;
1527 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); 1606 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
1528 return ad198x_parse_auto_config(codec); 1607 err = ad198x_parse_auto_config(codec);
1608 if (err < 0)
1609 return err;
1610 err = ad1983_add_spdif_mux_ctl(codec);
1611 if (err < 0)
1612 return err;
1613 return 0;
1529} 1614}
1530 1615
1531static int patch_ad1983(struct hda_codec *codec) 1616static int patch_ad1983(struct hda_codec *codec)
@@ -1950,11 +2035,18 @@ static const struct snd_pci_quirk ad1981_cfg_tbl[] = {
1950static int ad1981_parse_auto_config(struct hda_codec *codec) 2035static int ad1981_parse_auto_config(struct hda_codec *codec)
1951{ 2036{
1952 struct ad198x_spec *spec = codec->spec; 2037 struct ad198x_spec *spec = codec->spec;
2038 int err;
1953 2039
1954 spec->gen.mixer_nid = 0x0e; 2040 spec->gen.mixer_nid = 0x0e;
1955 spec->beep_dev_nid = 0x10; 2041 spec->beep_dev_nid = 0x10;
1956 set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT); 2042 set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT);
1957 return ad198x_parse_auto_config(codec); 2043 err = ad198x_parse_auto_config(codec);
2044 if (err < 0)
2045 return err;
2046 err = ad1983_add_spdif_mux_ctl(codec);
2047 if (err < 0)
2048 return err;
2049 return 0;
1958} 2050}
1959 2051
1960static int patch_ad1981(struct hda_codec *codec) 2052static int patch_ad1981(struct hda_codec *codec)
@@ -2820,17 +2912,167 @@ static const struct hda_amp_list ad1988_loopbacks[] = {
2820}; 2912};
2821#endif 2913#endif
2822 2914
2915static int ad1988_auto_smux_enum_info(struct snd_kcontrol *kcontrol,
2916 struct snd_ctl_elem_info *uinfo)
2917{
2918 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2919 static const char * const texts[] = {
2920 "PCM", "ADC1", "ADC2", "ADC3",
2921 };
2922 int num_conns = snd_hda_get_num_conns(codec, 0x0b) + 1;
2923 if (num_conns > 4)
2924 num_conns = 4;
2925 return snd_hda_enum_helper_info(kcontrol, uinfo, num_conns, texts);
2926}
2927
2928static int ad1988_auto_smux_enum_get(struct snd_kcontrol *kcontrol,
2929 struct snd_ctl_elem_value *ucontrol)
2930{
2931 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2932 struct ad198x_spec *spec = codec->spec;
2933
2934 ucontrol->value.enumerated.item[0] = spec->cur_smux;
2935 return 0;
2936}
2937
2938static int ad1988_auto_smux_enum_put(struct snd_kcontrol *kcontrol,
2939 struct snd_ctl_elem_value *ucontrol)
2940{
2941 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2942 struct ad198x_spec *spec = codec->spec;
2943 unsigned int val = ucontrol->value.enumerated.item[0];
2944 struct nid_path *path;
2945 int num_conns = snd_hda_get_num_conns(codec, 0x0b) + 1;
2946
2947 if (val >= num_conns)
2948 return -EINVAL;
2949 if (spec->cur_smux == val)
2950 return 0;
2951
2952 mutex_lock(&codec->control_mutex);
2953 codec->cached_write = 1;
2954 path = snd_hda_get_path_from_idx(codec,
2955 spec->smux_paths[spec->cur_smux]);
2956 if (path)
2957 snd_hda_activate_path(codec, path, false, true);
2958 path = snd_hda_get_path_from_idx(codec, spec->smux_paths[val]);
2959 if (path)
2960 snd_hda_activate_path(codec, path, true, true);
2961 spec->cur_smux = val;
2962 codec->cached_write = 0;
2963 mutex_unlock(&codec->control_mutex);
2964 snd_hda_codec_flush_cache(codec); /* flush the updates */
2965 return 1;
2966}
2967
2968static struct snd_kcontrol_new ad1988_auto_smux_mixer = {
2969 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2970 .name = "IEC958 Playback Source",
2971 .info = ad1988_auto_smux_enum_info,
2972 .get = ad1988_auto_smux_enum_get,
2973 .put = ad1988_auto_smux_enum_put,
2974};
2975
2976static int ad1988_auto_init(struct hda_codec *codec)
2977{
2978 struct ad198x_spec *spec = codec->spec;
2979 int i, err;
2980
2981 err = snd_hda_gen_init(codec);
2982 if (err < 0)
2983 return err;
2984 if (!spec->gen.autocfg.dig_outs)
2985 return 0;
2986
2987 for (i = 0; i < 4; i++) {
2988 struct nid_path *path;
2989 path = snd_hda_get_path_from_idx(codec, spec->smux_paths[i]);
2990 if (path)
2991 snd_hda_activate_path(codec, path, path->active, false);
2992 }
2993
2994 return 0;
2995}
2996
2997static int ad1988_add_spdif_mux_ctl(struct hda_codec *codec)
2998{
2999 struct ad198x_spec *spec = codec->spec;
3000 int i, num_conns;
3001 /* we create four static faked paths, since AD codecs have odd
3002 * widget connections regarding the SPDIF out source
3003 */
3004 static struct nid_path fake_paths[4] = {
3005 {
3006 .depth = 3,
3007 .path = { 0x02, 0x1d, 0x1b },
3008 .idx = { 0, 0, 0 },
3009 .multi = { 0, 0, 0 },
3010 },
3011 {
3012 .depth = 4,
3013 .path = { 0x08, 0x0b, 0x1d, 0x1b },
3014 .idx = { 0, 0, 1, 0 },
3015 .multi = { 0, 1, 0, 0 },
3016 },
3017 {
3018 .depth = 4,
3019 .path = { 0x09, 0x0b, 0x1d, 0x1b },
3020 .idx = { 0, 1, 1, 0 },
3021 .multi = { 0, 1, 0, 0 },
3022 },
3023 {
3024 .depth = 4,
3025 .path = { 0x0f, 0x0b, 0x1d, 0x1b },
3026 .idx = { 0, 2, 1, 0 },
3027 .multi = { 0, 1, 0, 0 },
3028 },
3029 };
3030
3031 /* SPDIF source mux appears to be present only on AD1988A */
3032 if (!spec->gen.autocfg.dig_outs ||
3033 get_wcaps_type(get_wcaps(codec, 0x1d)) != AC_WID_AUD_MIX)
3034 return 0;
3035
3036 num_conns = snd_hda_get_num_conns(codec, 0x0b) + 1;
3037 if (num_conns != 3 && num_conns != 4)
3038 return 0;
3039
3040 for (i = 0; i < num_conns; i++) {
3041 struct nid_path *path = snd_array_new(&spec->gen.paths);
3042 if (!path)
3043 return -ENOMEM;
3044 *path = fake_paths[i];
3045 if (!i)
3046 path->active = 1;
3047 spec->smux_paths[i] = snd_hda_get_path_idx(codec, path);
3048 }
3049
3050 if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &ad1988_auto_smux_mixer))
3051 return -ENOMEM;
3052
3053 codec->patch_ops.init = ad1988_auto_init;
3054
3055 return 0;
3056}
3057
2823/* 3058/*
2824 */ 3059 */
2825 3060
2826static int ad1988_parse_auto_config(struct hda_codec *codec) 3061static int ad1988_parse_auto_config(struct hda_codec *codec)
2827{ 3062{
2828 struct ad198x_spec *spec = codec->spec; 3063 struct ad198x_spec *spec = codec->spec;
3064 int err;
2829 3065
2830 spec->gen.mixer_nid = 0x20; 3066 spec->gen.mixer_nid = 0x20;
2831 spec->beep_dev_nid = 0x10; 3067 spec->beep_dev_nid = 0x10;
2832 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); 3068 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
2833 return ad198x_parse_auto_config(codec); 3069 err = ad198x_parse_auto_config(codec);
3070 if (err < 0)
3071 return err;
3072 err = ad1988_add_spdif_mux_ctl(codec);
3073 if (err < 0)
3074 return err;
3075 return 0;
2834} 3076}
2835 3077
2836/* 3078/*
@@ -3174,11 +3416,18 @@ static const char * const ad1884_models[AD1884_MODELS] = {
3174static int ad1884_parse_auto_config(struct hda_codec *codec) 3416static int ad1884_parse_auto_config(struct hda_codec *codec)
3175{ 3417{
3176 struct ad198x_spec *spec = codec->spec; 3418 struct ad198x_spec *spec = codec->spec;
3419 int err;
3177 3420
3178 spec->gen.mixer_nid = 0x20; 3421 spec->gen.mixer_nid = 0x20;
3179 spec->beep_dev_nid = 0x10; 3422 spec->beep_dev_nid = 0x10;
3180 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); 3423 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3181 return ad198x_parse_auto_config(codec); 3424 err = ad198x_parse_auto_config(codec);
3425 if (err < 0)
3426 return err;
3427 err = ad1983_add_spdif_mux_ctl(codec);
3428 if (err < 0)
3429 return err;
3430 return 0;
3182} 3431}
3183 3432
3184static int patch_ad1884_auto(struct hda_codec *codec) 3433static int patch_ad1884_auto(struct hda_codec *codec)
@@ -4635,11 +4884,18 @@ static const char * const ad1882_models[AD1986A_MODELS] = {
4635static int ad1882_parse_auto_config(struct hda_codec *codec) 4884static int ad1882_parse_auto_config(struct hda_codec *codec)
4636{ 4885{
4637 struct ad198x_spec *spec = codec->spec; 4886 struct ad198x_spec *spec = codec->spec;
4887 int err;
4638 4888
4639 spec->gen.mixer_nid = 0x20; 4889 spec->gen.mixer_nid = 0x20;
4640 spec->beep_dev_nid = 0x10; 4890 spec->beep_dev_nid = 0x10;
4641 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); 4891 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
4642 return ad198x_parse_auto_config(codec); 4892 err = ad198x_parse_auto_config(codec);
4893 if (err < 0)
4894 return err;
4895 err = ad1988_add_spdif_mux_ctl(codec);
4896 if (err < 0)
4897 return err;
4898 return 0;
4643} 4899}
4644 4900
4645static int patch_ad1882(struct hda_codec *codec) 4901static int patch_ad1882(struct hda_codec *codec)