aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_via.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2011-06-30 11:24:47 -0400
committerTakashi Iwai <tiwai@suse.de>2011-06-30 11:24:47 -0400
commit2525050518496dfd6905abfa8d6d34288eed36d7 (patch)
tree046b47fd2e011a30f5cd4a992fadd2376e074545 /sound/pci/hda/patch_via.c
parente322a36d3998f7f53c76e25e32302632326ec224 (diff)
ALSA: hda - Re-implementation of VIA Independent-HP sharing with side stream
This patch adds the re-implementation of Independent-HP mode in the case where the DAC is shared between HP and side-channel streams. Now the driver tries to parse the output-path using the pre-parsed side-channel DAC for the independent HP output, too. When a playback PCM stream is opened with this shared mode, the Independent-HP mixer switch can't be changed for avoiding the conflict, thus it returns -EBUSY error. One remaining unintuitive issue is that the DAC volume is still controlled as "Side" volume although it's shared by both independent-HP and side streams. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/patch_via.c')
-rw-r--r--sound/pci/hda/patch_via.c43
1 files changed, 37 insertions, 6 deletions
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 93fcea045e3b..5ef14dd7a568 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -128,6 +128,7 @@ struct via_spec {
128 struct hda_multi_out multiout; 128 struct hda_multi_out multiout;
129 hda_nid_t slave_dig_outs[2]; 129 hda_nid_t slave_dig_outs[2];
130 hda_nid_t hp_dac_nid; 130 hda_nid_t hp_dac_nid;
131 bool hp_indep_shared; /* indep HP-DAC is shared with side ch */
131 int num_active_streams; 132 int num_active_streams;
132 133
133 struct nid_path out_path[4]; 134 struct nid_path out_path[4];
@@ -714,19 +715,33 @@ static int via_independent_hp_put(struct snd_kcontrol *kcontrol,
714{ 715{
715 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 716 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
716 struct via_spec *spec = codec->spec; 717 struct via_spec *spec = codec->spec;
718 int cur;
717 719
718 spec->hp_independent_mode = !!ucontrol->value.enumerated.item[0]; 720 /* no independent-hp status change during PCM playback is running */
719 if (spec->hp_independent_mode) { 721 if (spec->num_active_streams)
722 return -EBUSY;
723
724 cur = !!ucontrol->value.enumerated.item[0];
725 if (spec->hp_independent_mode == cur)
726 return 0;
727 spec->hp_independent_mode = cur;
728 if (cur) {
720 activate_output_path(codec, &spec->hp_dep_path, false, false); 729 activate_output_path(codec, &spec->hp_dep_path, false, false);
721 activate_output_path(codec, &spec->hp_path, true, false); 730 activate_output_path(codec, &spec->hp_path, true, false);
731 if (spec->hp_indep_shared)
732 activate_output_path(codec, &spec->out_path[HDA_SIDE],
733 false, false);
722 } else { 734 } else {
723 activate_output_path(codec, &spec->hp_path, false, false); 735 activate_output_path(codec, &spec->hp_path, false, false);
724 activate_output_path(codec, &spec->hp_dep_path, true, false); 736 activate_output_path(codec, &spec->hp_dep_path, true, false);
737 if (spec->hp_indep_shared)
738 activate_output_path(codec, &spec->out_path[HDA_SIDE],
739 true, false);
725 } 740 }
726 741
727 /* update jack power state */ 742 /* update jack power state */
728 set_widgets_power_state(codec); 743 set_widgets_power_state(codec);
729 return 0; 744 return 1;
730} 745}
731 746
732static const struct snd_kcontrol_new via_hp_mixer = { 747static const struct snd_kcontrol_new via_hp_mixer = {
@@ -942,10 +957,19 @@ static int via_playback_multi_pcm_open(struct hda_pcm_stream *hinfo,
942 struct snd_pcm_substream *substream) 957 struct snd_pcm_substream *substream)
943{ 958{
944 struct via_spec *spec = codec->spec; 959 struct via_spec *spec = codec->spec;
960 const struct auto_pin_cfg *cfg = &spec->autocfg;
945 int err; 961 int err;
946 962
947 if (!spec->hp_independent_mode) 963 spec->multiout.hp_nid = 0;
948 spec->multiout.hp_nid = spec->hp_dac_nid; 964 spec->multiout.num_dacs = cfg->line_outs + spec->smart51_nums;
965 if (!spec->hp_independent_mode) {
966 if (!spec->hp_indep_shared)
967 spec->multiout.hp_nid = spec->hp_dac_nid;
968 } else {
969 if (spec->hp_indep_shared)
970 spec->multiout.num_dacs = cfg->line_outs - 1;
971 }
972 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
949 set_stream_active(codec, true); 973 set_stream_active(codec, true);
950 err = snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, 974 err = snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
951 hinfo); 975 hinfo);
@@ -1815,13 +1839,20 @@ static int via_auto_create_hp_ctls(struct hda_codec *codec, hda_nid_t pin)
1815 1839
1816 if (parse_output_path(codec, pin, 0, &spec->hp_path)) 1840 if (parse_output_path(codec, pin, 0, &spec->hp_path))
1817 spec->hp_dac_nid = spec->hp_path.path[0]; 1841 spec->hp_dac_nid = spec->hp_path.path[0];
1842 else if (spec->multiout.dac_nids[HDA_SIDE] &&
1843 parse_output_path(codec, pin,
1844 spec->multiout.dac_nids[HDA_SIDE],
1845 &spec->hp_path)) {
1846 spec->hp_dac_nid = spec->hp_path.path[0];
1847 spec->hp_indep_shared = true;
1848 }
1818 1849
1819 if (!parse_output_path(codec, pin, spec->multiout.dac_nids[HDA_FRONT], 1850 if (!parse_output_path(codec, pin, spec->multiout.dac_nids[HDA_FRONT],
1820 &spec->hp_dep_path) && 1851 &spec->hp_dep_path) &&
1821 !spec->hp_dac_nid) 1852 !spec->hp_dac_nid)
1822 return 0; 1853 return 0;
1823 1854
1824 if (spec->hp_dac_nid) 1855 if (spec->hp_dac_nid && !spec->hp_indep_shared)
1825 path = &spec->hp_path; 1856 path = &spec->hp_path;
1826 else 1857 else
1827 path = &spec->hp_dep_path; 1858 path = &spec->hp_dep_path;