aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_via.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2007-08-10 11:21:45 -0400
committerJaroslav Kysela <perex@perex.cz>2007-10-16 09:58:46 -0400
commitcb53c626e1145edf1d619bc4953f6293d3a77ace (patch)
tree715c2ef3d56a5ac7c79498800e888f562c1aa961 /sound/pci/hda/patch_via.c
parentcca3b3718ca96dca51daf1129ac03003bcede751 (diff)
[ALSA] hda-intel - Add POWER_SAVE option
Added CONFIG_SND_HDA_POWER_SAVE kconfig. It's an experimental option to achieve an aggressive power-saving. With this option, the driver will turn on/off the power of each codec and controller chip dynamically on demand. The patch introduces a new module option 'power_save'. It specifies the second of time-out for automatic power-down. As default, it's 10 seconds. Setting 0 means to suppress the power-saving feature. The codec may have analog-input loopbacks, which are usually represented by mixer elements such as 'Mic Playback Switch' or 'CD Playback Switch'. When these are on, we cannot turn off the mixer and the codec chip has to be kept on. For bookkeeping these states, a new codec-callback is introduced. For the bus-controller side, a new callback pm_notify is introduced, which can be used to turn on/off the contoller appropriately. Note that this power-saving might cause slight click-noise at power-on/off. Also, it might take some time to wake up the codec, and might even drop some tones at the very beginning. This seems to be the side-effect of turning off the controller chip. This turn-off of the controller can be disabled by undefining HDA_POWER_SAVE_RESET_CONTOLLER in hda_intel.c. Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/pci/hda/patch_via.c')
-rw-r--r--sound/pci/hda/patch_via.c68
1 files changed, 56 insertions, 12 deletions
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 6c734f07e5b5..33b5e1ffa817 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -115,6 +115,10 @@ struct via_spec {
115 struct snd_kcontrol_new *kctl_alloc; 115 struct snd_kcontrol_new *kctl_alloc;
116 struct hda_input_mux private_imux; 116 struct hda_input_mux private_imux;
117 hda_nid_t private_dac_nids[4]; 117 hda_nid_t private_dac_nids[4];
118
119#ifdef CONFIG_SND_HDA_POWER_SAVE
120 struct hda_loopback_check loopback;
121#endif
118}; 122};
119 123
120static hda_nid_t vt1708_adc_nids[2] = { 124static hda_nid_t vt1708_adc_nids[2] = {
@@ -305,15 +309,15 @@ static struct hda_verb vt1708_volume_init_verbs[] = {
305 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 309 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
306 310
307 311
308 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback 312 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
309 * mixer widget 313 * mixer widget
310 */ 314 */
311 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */ 315 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
312 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 316 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* master */
313 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 317 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
314 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 318 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
315 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 319 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
316 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 320 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
317 321
318 /* 322 /*
319 * Set up output mixers (0x19 - 0x1b) 323 * Set up output mixers (0x19 - 0x1b)
@@ -543,6 +547,14 @@ static int via_init(struct hda_codec *codec)
543 return 0; 547 return 0;
544} 548}
545 549
550#ifdef CONFIG_SND_HDA_POWER_SAVE
551static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid)
552{
553 struct via_spec *spec = codec->spec;
554 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
555}
556#endif
557
546/* 558/*
547 */ 559 */
548static struct hda_codec_ops via_patch_ops = { 560static struct hda_codec_ops via_patch_ops = {
@@ -550,6 +562,9 @@ static struct hda_codec_ops via_patch_ops = {
550 .build_pcms = via_build_pcms, 562 .build_pcms = via_build_pcms,
551 .init = via_init, 563 .init = via_init,
552 .free = via_free, 564 .free = via_free,
565#ifdef CONFIG_SND_HDA_POWER_SAVE
566 .check_power_status = via_check_power_status,
567#endif
553}; 568};
554 569
555/* fill in the dac_nids table from the parsed pin configuration */ 570/* fill in the dac_nids table from the parsed pin configuration */
@@ -738,6 +753,16 @@ static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec,
738 return 0; 753 return 0;
739} 754}
740 755
756#ifdef CONFIG_SND_HDA_POWER_SAVE
757static struct hda_amp_list vt1708_loopbacks[] = {
758 { 0x17, HDA_INPUT, 1 },
759 { 0x17, HDA_INPUT, 2 },
760 { 0x17, HDA_INPUT, 3 },
761 { 0x17, HDA_INPUT, 4 },
762 { } /* end */
763};
764#endif
765
741static int vt1708_parse_auto_config(struct hda_codec *codec) 766static int vt1708_parse_auto_config(struct hda_codec *codec)
742{ 767{
743 struct via_spec *spec = codec->spec; 768 struct via_spec *spec = codec->spec;
@@ -831,6 +856,9 @@ static int patch_vt1708(struct hda_codec *codec)
831 codec->patch_ops = via_patch_ops; 856 codec->patch_ops = via_patch_ops;
832 857
833 codec->patch_ops.init = via_auto_init; 858 codec->patch_ops.init = via_auto_init;
859#ifdef CONFIG_SND_HDA_POWER_SAVE
860 spec->loopback.amplist = vt1708_loopbacks;
861#endif
834 862
835 return 0; 863 return 0;
836} 864}
@@ -871,15 +899,15 @@ static struct hda_verb vt1709_10ch_volume_init_verbs[] = {
871 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 899 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
872 900
873 901
874 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback 902 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
875 * mixer widget 903 * mixer widget
876 */ 904 */
877 /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */ 905 /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
878 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, 906 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* unmute master */
879 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, 907 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
880 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, 908 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
881 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, 909 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
882 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, 910 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
883 911
884 /* 912 /*
885 * Set up output selector (0x1a, 0x1b, 0x29) 913 * Set up output selector (0x1a, 0x1b, 0x29)
@@ -1227,6 +1255,16 @@ static int vt1709_parse_auto_config(struct hda_codec *codec)
1227 return 1; 1255 return 1;
1228} 1256}
1229 1257
1258#ifdef CONFIG_SND_HDA_POWER_SAVE
1259static struct hda_amp_list vt1709_loopbacks[] = {
1260 { 0x18, HDA_INPUT, 1 },
1261 { 0x18, HDA_INPUT, 2 },
1262 { 0x18, HDA_INPUT, 3 },
1263 { 0x18, HDA_INPUT, 4 },
1264 { } /* end */
1265};
1266#endif
1267
1230static int patch_vt1709_10ch(struct hda_codec *codec) 1268static int patch_vt1709_10ch(struct hda_codec *codec)
1231{ 1269{
1232 struct via_spec *spec; 1270 struct via_spec *spec;
@@ -1269,6 +1307,9 @@ static int patch_vt1709_10ch(struct hda_codec *codec)
1269 codec->patch_ops = via_patch_ops; 1307 codec->patch_ops = via_patch_ops;
1270 1308
1271 codec->patch_ops.init = via_auto_init; 1309 codec->patch_ops.init = via_auto_init;
1310#ifdef CONFIG_SND_HDA_POWER_SAVE
1311 spec->loopback.amplist = vt1709_loopbacks;
1312#endif
1272 1313
1273 return 0; 1314 return 0;
1274} 1315}
@@ -1359,6 +1400,9 @@ static int patch_vt1709_6ch(struct hda_codec *codec)
1359 codec->patch_ops = via_patch_ops; 1400 codec->patch_ops = via_patch_ops;
1360 1401
1361 codec->patch_ops.init = via_auto_init; 1402 codec->patch_ops.init = via_auto_init;
1403#ifdef CONFIG_SND_HDA_POWER_SAVE
1404 spec->loopback.amplist = vt1709_loopbacks;
1405#endif
1362 1406
1363 return 0; 1407 return 0;
1364} 1408}