aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_analog.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2007-08-10 11:09:26 -0400
committerJaroslav Kysela <perex@perex.cz>2007-10-16 09:58:43 -0400
commit82beb8fd365afe3891b277c46425083f13e23c56 (patch)
treea564d7228b59170aa490d4fc9284b5fa4442adb0 /sound/pci/hda/patch_analog.c
parentb3ac56364126f78cae94eb2a75b72d9ea85aca9d (diff)
[ALSA] hda-codec - optimize resume using caches
So far, the driver looked the table of snd_kcontrol_new used for creating mixer elements and forces to call each of its put callbacks in PM resume code. This is too ugly and hackish. Now, the resume is simplified using the codec amp and command register caches. The driver simply restores the values that have been written in the cache table. With this simplification, most codec support codes don't require any special resume callback. Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/pci/hda/patch_analog.c')
-rw-r--r--sound/pci/hda/patch_analog.c68
1 files changed, 25 insertions, 43 deletions
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index cc2e944cc59f..f20ddd85db22 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -318,31 +318,11 @@ static void ad198x_free(struct hda_codec *codec)
318 kfree(codec->spec); 318 kfree(codec->spec);
319} 319}
320 320
321#ifdef CONFIG_PM
322static int ad198x_resume(struct hda_codec *codec)
323{
324 struct ad198x_spec *spec = codec->spec;
325 int i;
326
327 codec->patch_ops.init(codec);
328 for (i = 0; i < spec->num_mixers; i++)
329 snd_hda_resume_ctls(codec, spec->mixers[i]);
330 if (spec->multiout.dig_out_nid)
331 snd_hda_resume_spdif_out(codec);
332 if (spec->dig_in_nid)
333 snd_hda_resume_spdif_in(codec);
334 return 0;
335}
336#endif
337
338static struct hda_codec_ops ad198x_patch_ops = { 321static struct hda_codec_ops ad198x_patch_ops = {
339 .build_controls = ad198x_build_controls, 322 .build_controls = ad198x_build_controls,
340 .build_pcms = ad198x_build_pcms, 323 .build_pcms = ad198x_build_pcms,
341 .init = ad198x_init, 324 .init = ad198x_init,
342 .free = ad198x_free, 325 .free = ad198x_free,
343#ifdef CONFIG_PM
344 .resume = ad198x_resume,
345#endif
346}; 326};
347 327
348 328
@@ -376,12 +356,12 @@ static int ad198x_eapd_put(struct snd_kcontrol *kcontrol,
376 eapd = ucontrol->value.integer.value[0]; 356 eapd = ucontrol->value.integer.value[0];
377 if (invert) 357 if (invert)
378 eapd = !eapd; 358 eapd = !eapd;
379 if (eapd == spec->cur_eapd && ! codec->in_resume) 359 if (eapd == spec->cur_eapd)
380 return 0; 360 return 0;
381 spec->cur_eapd = eapd; 361 spec->cur_eapd = eapd;
382 snd_hda_codec_write(codec, nid, 362 snd_hda_codec_write_cache(codec, nid,
383 0, AC_VERB_SET_EAPD_BTLENABLE, 363 0, AC_VERB_SET_EAPD_BTLENABLE,
384 eapd ? 0x02 : 0x00); 364 eapd ? 0x02 : 0x00);
385 return 1; 365 return 1;
386} 366}
387 367
@@ -882,8 +862,9 @@ static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
882 862
883 if (spec->spdif_route != ucontrol->value.enumerated.item[0]) { 863 if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
884 spec->spdif_route = ucontrol->value.enumerated.item[0]; 864 spec->spdif_route = ucontrol->value.enumerated.item[0];
885 snd_hda_codec_write(codec, spec->multiout.dig_out_nid, 0, 865 snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0,
886 AC_VERB_SET_CONNECT_SEL, spec->spdif_route); 866 AC_VERB_SET_CONNECT_SEL,
867 spec->spdif_route);
887 return 1; 868 return 1;
888 } 869 }
889 return 0; 870 return 0;
@@ -1824,33 +1805,34 @@ static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
1824 AC_VERB_GET_AMP_GAIN_MUTE, 1805 AC_VERB_GET_AMP_GAIN_MUTE,
1825 AC_AMP_GET_INPUT); 1806 AC_AMP_GET_INPUT);
1826 change = sel & 0x80; 1807 change = sel & 0x80;
1827 if (change || codec->in_resume) { 1808 if (change) {
1828 snd_hda_codec_write(codec, 0x1d, 0, 1809 snd_hda_codec_write_cache(codec, 0x1d, 0,
1829 AC_VERB_SET_AMP_GAIN_MUTE, 1810 AC_VERB_SET_AMP_GAIN_MUTE,
1830 AMP_IN_UNMUTE(0)); 1811 AMP_IN_UNMUTE(0));
1831 snd_hda_codec_write(codec, 0x1d, 0, 1812 snd_hda_codec_write_cache(codec, 0x1d, 0,
1832 AC_VERB_SET_AMP_GAIN_MUTE, 1813 AC_VERB_SET_AMP_GAIN_MUTE,
1833 AMP_IN_MUTE(1)); 1814 AMP_IN_MUTE(1));
1834 } 1815 }
1835 } else { 1816 } else {
1836 sel = snd_hda_codec_read(codec, 0x1d, 0, 1817 sel = snd_hda_codec_read(codec, 0x1d, 0,
1837 AC_VERB_GET_AMP_GAIN_MUTE, 1818 AC_VERB_GET_AMP_GAIN_MUTE,
1838 AC_AMP_GET_INPUT | 0x01); 1819 AC_AMP_GET_INPUT | 0x01);
1839 change = sel & 0x80; 1820 change = sel & 0x80;
1840 if (change || codec->in_resume) { 1821 if (change) {
1841 snd_hda_codec_write(codec, 0x1d, 0, 1822 snd_hda_codec_write_cache(codec, 0x1d, 0,
1842 AC_VERB_SET_AMP_GAIN_MUTE, 1823 AC_VERB_SET_AMP_GAIN_MUTE,
1843 AMP_IN_MUTE(0)); 1824 AMP_IN_MUTE(0));
1844 snd_hda_codec_write(codec, 0x1d, 0, 1825 snd_hda_codec_write_cache(codec, 0x1d, 0,
1845 AC_VERB_SET_AMP_GAIN_MUTE, 1826 AC_VERB_SET_AMP_GAIN_MUTE,
1846 AMP_IN_UNMUTE(1)); 1827 AMP_IN_UNMUTE(1));
1847 } 1828 }
1848 sel = snd_hda_codec_read(codec, 0x0b, 0, 1829 sel = snd_hda_codec_read(codec, 0x0b, 0,
1849 AC_VERB_GET_CONNECT_SEL, 0) + 1; 1830 AC_VERB_GET_CONNECT_SEL, 0) + 1;
1850 change |= sel != val; 1831 change |= sel != val;
1851 if (change || codec->in_resume) 1832 if (change)
1852 snd_hda_codec_write(codec, 0x0b, 0, 1833 snd_hda_codec_write_cache(codec, 0x0b, 0,
1853 AC_VERB_SET_CONNECT_SEL, val - 1); 1834 AC_VERB_SET_CONNECT_SEL,
1835 val - 1);
1854 } 1836 }
1855 return change; 1837 return change;
1856} 1838}