diff options
author | Takashi Iwai <tiwai@suse.de> | 2011-06-30 11:24:47 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-06-30 11:24:47 -0400 |
commit | 2525050518496dfd6905abfa8d6d34288eed36d7 (patch) | |
tree | 046b47fd2e011a30f5cd4a992fadd2376e074545 /sound/pci/hda/patch_via.c | |
parent | e322a36d3998f7f53c76e25e32302632326ec224 (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.c | 43 |
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 | ||
732 | static const struct snd_kcontrol_new via_hp_mixer = { | 747 | static 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; |