aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_realtek.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_realtek.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_realtek.c')
-rw-r--r--sound/pci/hda/patch_realtek.c167
1 files changed, 87 insertions, 80 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 39c08bb670d1..63011133e3fb 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -442,8 +442,9 @@ static int alc_pin_mode_put(struct snd_kcontrol *kcontrol,
442 change = pinctl != alc_pin_mode_values[val]; 442 change = pinctl != alc_pin_mode_values[val];
443 if (change) { 443 if (change) {
444 /* Set pin mode to that requested */ 444 /* Set pin mode to that requested */
445 snd_hda_codec_write(codec,nid,0,AC_VERB_SET_PIN_WIDGET_CONTROL, 445 snd_hda_codec_write_cache(codec, nid, 0,
446 alc_pin_mode_values[val]); 446 AC_VERB_SET_PIN_WIDGET_CONTROL,
447 alc_pin_mode_values[val]);
447 448
448 /* Also enable the retasking pin's input/output as required 449 /* Also enable the retasking pin's input/output as required
449 * for the requested pin mode. Enum values of 2 or less are 450 * for the requested pin mode. Enum values of 2 or less are
@@ -456,19 +457,23 @@ static int alc_pin_mode_put(struct snd_kcontrol *kcontrol,
456 * this turns out to be necessary in the future. 457 * this turns out to be necessary in the future.
457 */ 458 */
458 if (val <= 2) { 459 if (val <= 2) {
459 snd_hda_codec_write(codec, nid, 0, 460 snd_hda_codec_amp_update(codec, nid, 0, HDA_OUTPUT, 0,
460 AC_VERB_SET_AMP_GAIN_MUTE, 461 0x80, 0x80);
461 AMP_OUT_MUTE); 462 snd_hda_codec_amp_update(codec, nid, 1, HDA_OUTPUT, 0,
462 snd_hda_codec_write(codec, nid, 0, 463 0x80, 0x80);
463 AC_VERB_SET_AMP_GAIN_MUTE, 464 snd_hda_codec_amp_update(codec, nid, 0, HDA_INPUT, 0,
464 AMP_IN_UNMUTE(0)); 465 0x80, 0x00);
466 snd_hda_codec_amp_update(codec, nid, 1, HDA_INPUT, 0,
467 0x80, 0x00);
465 } else { 468 } else {
466 snd_hda_codec_write(codec, nid, 0, 469 snd_hda_codec_amp_update(codec, nid, 0, HDA_INPUT, 0,
467 AC_VERB_SET_AMP_GAIN_MUTE, 470 0x80, 0x80);
468 AMP_IN_MUTE(0)); 471 snd_hda_codec_amp_update(codec, nid, 1, HDA_INPUT, 0,
469 snd_hda_codec_write(codec, nid, 0, 472 0x80, 0x80);
470 AC_VERB_SET_AMP_GAIN_MUTE, 473 snd_hda_codec_amp_update(codec, nid, 0, HDA_OUTPUT, 0,
471 AMP_OUT_UNMUTE); 474 0x80, 0x00);
475 snd_hda_codec_amp_update(codec, nid, 1, HDA_OUTPUT, 0,
476 0x80, 0x00);
472 } 477 }
473 } 478 }
474 return change; 479 return change;
@@ -520,7 +525,8 @@ static int alc_gpio_data_put(struct snd_kcontrol *kcontrol,
520 gpio_data &= ~mask; 525 gpio_data &= ~mask;
521 else 526 else
522 gpio_data |= mask; 527 gpio_data |= mask;
523 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_GPIO_DATA, gpio_data); 528 snd_hda_codec_write_cache(codec, nid, 0,
529 AC_VERB_SET_GPIO_DATA, gpio_data);
524 530
525 return change; 531 return change;
526} 532}
@@ -573,8 +579,8 @@ static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol,
573 ctrl_data &= ~mask; 579 ctrl_data &= ~mask;
574 else 580 else
575 ctrl_data |= mask; 581 ctrl_data |= mask;
576 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, 582 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
577 ctrl_data); 583 ctrl_data);
578 584
579 return change; 585 return change;
580} 586}
@@ -2026,27 +2032,6 @@ static void alc_unsol_event(struct hda_codec *codec, unsigned int res)
2026 spec->unsol_event(codec, res); 2032 spec->unsol_event(codec, res);
2027} 2033}
2028 2034
2029#ifdef CONFIG_PM
2030/*
2031 * resume
2032 */
2033static int alc_resume(struct hda_codec *codec)
2034{
2035 struct alc_spec *spec = codec->spec;
2036 int i;
2037
2038 alc_init(codec);
2039 for (i = 0; i < spec->num_mixers; i++)
2040 snd_hda_resume_ctls(codec, spec->mixers[i]);
2041 if (spec->multiout.dig_out_nid)
2042 snd_hda_resume_spdif_out(codec);
2043 if (spec->dig_in_nid)
2044 snd_hda_resume_spdif_in(codec);
2045
2046 return 0;
2047}
2048#endif
2049
2050/* 2035/*
2051 * Analog playback callbacks 2036 * Analog playback callbacks
2052 */ 2037 */
@@ -2278,9 +2263,6 @@ static struct hda_codec_ops alc_patch_ops = {
2278 .init = alc_init, 2263 .init = alc_init,
2279 .free = alc_free, 2264 .free = alc_free,
2280 .unsol_event = alc_unsol_event, 2265 .unsol_event = alc_unsol_event,
2281#ifdef CONFIG_PM
2282 .resume = alc_resume,
2283#endif
2284}; 2266};
2285 2267
2286 2268
@@ -2377,11 +2359,15 @@ static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol,
2377 AC_VERB_GET_PIN_WIDGET_CONTROL, 0); 2359 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
2378 new_ctl = ctls[ucontrol->value.enumerated.item[0]]; 2360 new_ctl = ctls[ucontrol->value.enumerated.item[0]];
2379 if (old_ctl != new_ctl) { 2361 if (old_ctl != new_ctl) {
2380 snd_hda_codec_write(codec, nid, 0, 2362 int val;
2381 AC_VERB_SET_PIN_WIDGET_CONTROL, new_ctl); 2363 snd_hda_codec_write_cache(codec, nid, 0,
2382 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 2364 AC_VERB_SET_PIN_WIDGET_CONTROL,
2383 (ucontrol->value.enumerated.item[0] >= 3 ? 2365 new_ctl);
2384 0xb080 : 0xb000)); 2366 val = ucontrol->value.enumerated.item[0] >= 3 ? 0x80 : 0x00;
2367 snd_hda_codec_amp_update(codec, nid, 0, HDA_OUTPUT, 0,
2368 0x80, val);
2369 snd_hda_codec_amp_update(codec, nid, 1, HDA_OUTPUT, 0,
2370 0x80, val);
2385 return 1; 2371 return 1;
2386 } 2372 }
2387 return 0; 2373 return 0;
@@ -2424,7 +2410,8 @@ static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol,
2424 sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3; 2410 sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3;
2425 if (ucontrol->value.enumerated.item[0] != sel) { 2411 if (ucontrol->value.enumerated.item[0] != sel) {
2426 sel = ucontrol->value.enumerated.item[0] & 3; 2412 sel = ucontrol->value.enumerated.item[0] & 3;
2427 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, sel); 2413 snd_hda_codec_write_cache(codec, nid, 0,
2414 AC_VERB_SET_CONNECT_SEL, sel);
2428 return 1; 2415 return 1;
2429 } 2416 }
2430 return 0; 2417 return 0;
@@ -4054,13 +4041,17 @@ static void alc260_replacer_672v_automute(struct hda_codec *codec)
4054 present = snd_hda_codec_read(codec, 0x0f, 0, 4041 present = snd_hda_codec_read(codec, 0x0f, 0,
4055 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; 4042 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
4056 if (present) { 4043 if (present) {
4057 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 1); 4044 snd_hda_codec_write_cache(codec, 0x01, 0,
4058 snd_hda_codec_write(codec, 0x0f, 0, 4045 AC_VERB_SET_GPIO_DATA, 1);
4059 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP); 4046 snd_hda_codec_write_cache(codec, 0x0f, 0,
4047 AC_VERB_SET_PIN_WIDGET_CONTROL,
4048 PIN_HP);
4060 } else { 4049 } else {
4061 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0); 4050 snd_hda_codec_write_cache(codec, 0x01, 0,
4062 snd_hda_codec_write(codec, 0x0f, 0, 4051 AC_VERB_SET_GPIO_DATA, 0);
4063 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); 4052 snd_hda_codec_write_cache(codec, 0x0f, 0,
4053 AC_VERB_SET_PIN_WIDGET_CONTROL,
4054 PIN_OUT);
4064 } 4055 }
4065} 4056}
4066 4057
@@ -4797,12 +4788,16 @@ static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol,
4797 idx = ucontrol->value.enumerated.item[0]; 4788 idx = ucontrol->value.enumerated.item[0];
4798 if (idx >= imux->num_items) 4789 if (idx >= imux->num_items)
4799 idx = imux->num_items - 1; 4790 idx = imux->num_items - 1;
4800 if (*cur_val == idx && !codec->in_resume) 4791 if (*cur_val == idx)
4801 return 0; 4792 return 0;
4802 for (i = 0; i < imux->num_items; i++) { 4793 for (i = 0; i < imux->num_items; i++) {
4803 unsigned int v = (i == idx) ? 0x7000 : 0x7080; 4794 unsigned int v = (i == idx) ? 0x00 : 0x80;
4804 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 4795 snd_hda_codec_amp_update(codec, nid, 0, HDA_INPUT,
4805 v | (imux->items[i].index << 8)); 4796 imux->items[i].index,
4797 0x80, v);
4798 snd_hda_codec_amp_update(codec, nid, 1, HDA_INPUT,
4799 imux->items[i].index,
4800 0x80, v);
4806 } 4801 }
4807 *cur_val = idx; 4802 *cur_val = idx;
4808 return 1; 4803 return 1;
@@ -5187,7 +5182,8 @@ static void alc882_targa_automute(struct hda_codec *codec)
5187 0x80, present ? 0x80 : 0); 5182 0x80, present ? 0x80 : 0);
5188 snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0, 5183 snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0,
5189 0x80, present ? 0x80 : 0); 5184 0x80, present ? 0x80 : 0);
5190 snd_hda_codec_write(codec, 1, 0, AC_VERB_SET_GPIO_DATA, present ? 1 : 3); 5185 snd_hda_codec_write_cache(codec, 1, 0, AC_VERB_SET_GPIO_DATA,
5186 present ? 1 : 3);
5191} 5187}
5192 5188
5193static void alc882_targa_unsol_event(struct hda_codec *codec, unsigned int res) 5189static void alc882_targa_unsol_event(struct hda_codec *codec, unsigned int res)
@@ -5777,12 +5773,16 @@ static int alc883_mux_enum_put(struct snd_kcontrol *kcontrol,
5777 idx = ucontrol->value.enumerated.item[0]; 5773 idx = ucontrol->value.enumerated.item[0];
5778 if (idx >= imux->num_items) 5774 if (idx >= imux->num_items)
5779 idx = imux->num_items - 1; 5775 idx = imux->num_items - 1;
5780 if (*cur_val == idx && !codec->in_resume) 5776 if (*cur_val == idx)
5781 return 0; 5777 return 0;
5782 for (i = 0; i < imux->num_items; i++) { 5778 for (i = 0; i < imux->num_items; i++) {
5783 unsigned int v = (i == idx) ? 0x7000 : 0x7080; 5779 unsigned int v = (i == idx) ? 0x00 : 0x80;
5784 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 5780 snd_hda_codec_amp_update(codec, nid, 0, HDA_INPUT,
5785 v | (imux->items[i].index << 8)); 5781 imux->items[i].index,
5782 0x80, v);
5783 snd_hda_codec_amp_update(codec, nid, 1, HDA_INPUT,
5784 imux->items[i].index,
5785 0x80, v);
5786 } 5786 }
5787 *cur_val = idx; 5787 *cur_val = idx;
5788 return 1; 5788 return 1;
@@ -6509,8 +6509,8 @@ static void alc883_tagra_automute(struct hda_codec *codec)
6509 0x80, bits); 6509 0x80, bits);
6510 snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0, 6510 snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0,
6511 0x80, bits); 6511 0x80, bits);
6512 snd_hda_codec_write(codec, 1, 0, AC_VERB_SET_GPIO_DATA, 6512 snd_hda_codec_write_cache(codec, 1, 0, AC_VERB_SET_GPIO_DATA,
6513 present ? 1 : 3); 6513 present ? 1 : 3);
6514} 6514}
6515 6515
6516static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res) 6516static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res)
@@ -7510,8 +7510,8 @@ static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,
7510 0x80, valp[0] ? 0 : 0x80); 7510 0x80, valp[0] ? 0 : 0x80);
7511 change |= snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, 7511 change |= snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
7512 0x80, valp[1] ? 0 : 0x80); 7512 0x80, valp[1] ? 0 : 0x80);
7513 if (change || codec->in_resume) 7513 if (change)
7514 alc262_fujitsu_automute(codec, codec->in_resume); 7514 alc262_fujitsu_automute(codec, 0);
7515 return change; 7515 return change;
7516} 7516}
7517 7517
@@ -8328,14 +8328,17 @@ static int alc268_mux_enum_put(struct snd_kcontrol *kcontrol,
8328 idx = ucontrol->value.enumerated.item[0]; 8328 idx = ucontrol->value.enumerated.item[0];
8329 if (idx >= imux->num_items) 8329 if (idx >= imux->num_items)
8330 idx = imux->num_items - 1; 8330 idx = imux->num_items - 1;
8331 if (*cur_val == idx && !codec->in_resume) 8331 if (*cur_val == idx)
8332 return 0; 8332 return 0;
8333 for (i = 0; i < imux->num_items; i++) { 8333 for (i = 0; i < imux->num_items; i++) {
8334 unsigned int v = (i == idx) ? 0x7000 : 0x7080; 8334 unsigned int v = (i == idx) ? 0x00 : 0x80;
8335 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 8335 snd_hda_codec_amp_update(codec, nid, 0, HDA_INPUT,
8336 v | (imux->items[i].index << 8)); 8336 imux->items[i].index, 0x80, v);
8337 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, 8337 snd_hda_codec_amp_update(codec, nid, 1, HDA_INPUT,
8338 idx ); 8338 imux->items[i].index, 0x80, v);
8339 snd_hda_codec_write_cache(codec, nid, 0,
8340 AC_VERB_SET_CONNECT_SEL,
8341 idx );
8339 } 8342 }
8340 *cur_val = idx; 8343 *cur_val = idx;
8341 return 1; 8344 return 1;
@@ -9916,12 +9919,14 @@ static int alc861vd_mux_enum_put(struct snd_kcontrol *kcontrol,
9916 idx = ucontrol->value.enumerated.item[0]; 9919 idx = ucontrol->value.enumerated.item[0];
9917 if (idx >= imux->num_items) 9920 if (idx >= imux->num_items)
9918 idx = imux->num_items - 1; 9921 idx = imux->num_items - 1;
9919 if (*cur_val == idx && !codec->in_resume) 9922 if (*cur_val == idx)
9920 return 0; 9923 return 0;
9921 for (i = 0; i < imux->num_items; i++) { 9924 for (i = 0; i < imux->num_items; i++) {
9922 unsigned int v = (i == idx) ? 0x7000 : 0x7080; 9925 unsigned int v = (i == idx) ? 0x00 : 0x80;
9923 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 9926 snd_hda_codec_amp_update(codec, nid, 0, HDA_INPUT,
9924 v | (imux->items[i].index << 8)); 9927 imux->items[i].index, 0x80, v);
9928 snd_hda_codec_amp_update(codec, nid, 1, HDA_INPUT,
9929 imux->items[i].index, 0x80, v);
9925 } 9930 }
9926 *cur_val = idx; 9931 *cur_val = idx;
9927 return 1; 9932 return 1;
@@ -10847,12 +10852,14 @@ static int alc662_mux_enum_put(struct snd_kcontrol *kcontrol,
10847 idx = ucontrol->value.enumerated.item[0]; 10852 idx = ucontrol->value.enumerated.item[0];
10848 if (idx >= imux->num_items) 10853 if (idx >= imux->num_items)
10849 idx = imux->num_items - 1; 10854 idx = imux->num_items - 1;
10850 if (*cur_val == idx && !codec->in_resume) 10855 if (*cur_val == idx)
10851 return 0; 10856 return 0;
10852 for (i = 0; i < imux->num_items; i++) { 10857 for (i = 0; i < imux->num_items; i++) {
10853 unsigned int v = (i == idx) ? 0x7000 : 0x7080; 10858 unsigned int v = (i == idx) ? 0x00 : 0x80;
10854 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 10859 snd_hda_codec_amp_update(codec, nid, 0, HDA_INPUT,
10855 v | (imux->items[i].index << 8)); 10860 imux->items[i].index, 0x80, v);
10861 snd_hda_codec_amp_update(codec, nid, 1, HDA_INPUT,
10862 imux->items[i].index, 0x80, v);
10856 } 10863 }
10857 *cur_val = idx; 10864 *cur_val = idx;
10858 return 1; 10865 return 1;