aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2012-03-12 07:30:22 -0400
committerTakashi Iwai <tiwai@suse.de>2012-03-12 09:52:42 -0400
commit2faa3bf15ba69fa12bc53926b88982b3875abb3f (patch)
tree8186f1baa526ee5618393e14a9eb7fc40a029b80 /sound/pci
parent29e5853d618282d8277ce8a8304f7424eb60deb5 (diff)
ALSA: hda - Rewrite the mute-LED hook with vmaster hook in patch_sigmatel.c
The mute-LED is controlled in patch_sigmatel.c by (ab-)using the powersave hook. This can be now rewritten with the vmaster hook instead, which is much simpler and can work even without CONFIG_SND_HDA_POWER_SAVE kconfig. A drawback is that the mute-LED corresponds _only_ to the Master mixer switch instead of checking the whole DACs. But usually this shouldn't be a big problem as PA enables the mixer elements accordingly. Also, this patch changes the code to create vmaster always even on STAC9200 and STAC925x. The former "Master" on these chips are renamed as "PCM" now. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r--sound/pci/hda/patch_sigmatel.c136
1 files changed, 49 insertions, 87 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 5988dbdedc4e..6e926497b230 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -310,6 +310,8 @@ struct sigmatel_spec {
310 unsigned long auto_capvols[MAX_ADCS_NUM]; 310 unsigned long auto_capvols[MAX_ADCS_NUM];
311 unsigned auto_dmic_cnt; 311 unsigned auto_dmic_cnt;
312 hda_nid_t auto_dmic_nids[MAX_DMICS_NUM]; 312 hda_nid_t auto_dmic_nids[MAX_DMICS_NUM];
313
314 struct snd_kcontrol *vmaster_sw_kctl;
313}; 315};
314 316
315static const hda_nid_t stac9200_adc_nids[1] = { 317static const hda_nid_t stac9200_adc_nids[1] = {
@@ -1007,8 +1009,8 @@ static const struct hda_verb stac9205_core_init[] = {
1007 } 1009 }
1008 1010
1009static const struct snd_kcontrol_new stac9200_mixer[] = { 1011static const struct snd_kcontrol_new stac9200_mixer[] = {
1010 HDA_CODEC_VOLUME_MIN_MUTE("Master Playback Volume", 0xb, 0, HDA_OUTPUT), 1012 HDA_CODEC_VOLUME_MIN_MUTE("PCM Playback Volume", 0xb, 0, HDA_OUTPUT),
1011 HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), 1013 HDA_CODEC_MUTE("PCM Playback Switch", 0xb, 0, HDA_OUTPUT),
1012 HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT), 1014 HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT),
1013 HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT), 1015 HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT),
1014 { } /* end */ 1016 { } /* end */
@@ -1035,8 +1037,8 @@ static const struct snd_kcontrol_new stac92hd71bxx_loopback[] = {
1035}; 1037};
1036 1038
1037static const struct snd_kcontrol_new stac925x_mixer[] = { 1039static const struct snd_kcontrol_new stac925x_mixer[] = {
1038 HDA_CODEC_VOLUME_MIN_MUTE("Master Playback Volume", 0xe, 0, HDA_OUTPUT), 1040 HDA_CODEC_VOLUME_MIN_MUTE("PCM Playback Volume", 0xe, 0, HDA_OUTPUT),
1039 HDA_CODEC_MUTE("Master Playback Switch", 0x0e, 0, HDA_OUTPUT), 1041 HDA_CODEC_MUTE("PCM Playback Switch", 0x0e, 0, HDA_OUTPUT),
1040 { } /* end */ 1042 { } /* end */
1041}; 1043};
1042 1044
@@ -1074,11 +1076,19 @@ static const char * const slave_pfxs[] = {
1074 NULL 1076 NULL
1075}; 1077};
1076 1078
1079static void stac92xx_update_led_status(struct hda_codec *codec, int enabled);
1080
1081static void stac92xx_vmaster_hook(void *private_data, int val)
1082{
1083 stac92xx_update_led_status(private_data, val);
1084}
1085
1077static void stac92xx_free_kctls(struct hda_codec *codec); 1086static void stac92xx_free_kctls(struct hda_codec *codec);
1078 1087
1079static int stac92xx_build_controls(struct hda_codec *codec) 1088static int stac92xx_build_controls(struct hda_codec *codec)
1080{ 1089{
1081 struct sigmatel_spec *spec = codec->spec; 1090 struct sigmatel_spec *spec = codec->spec;
1091 unsigned int vmaster_tlv[4];
1082 int err; 1092 int err;
1083 int i; 1093 int i;
1084 1094
@@ -1135,26 +1145,29 @@ static int stac92xx_build_controls(struct hda_codec *codec)
1135 } 1145 }
1136 1146
1137 /* if we have no master control, let's create it */ 1147 /* if we have no master control, let's create it */
1138 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { 1148 snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0],
1139 unsigned int vmaster_tlv[4]; 1149 HDA_OUTPUT, vmaster_tlv);
1140 snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0], 1150 /* correct volume offset */
1141 HDA_OUTPUT, vmaster_tlv); 1151 vmaster_tlv[2] += vmaster_tlv[3] * spec->volume_offset;
1142 /* correct volume offset */ 1152 /* minimum value is actually mute */
1143 vmaster_tlv[2] += vmaster_tlv[3] * spec->volume_offset; 1153 vmaster_tlv[3] |= TLV_DB_SCALE_MUTE;
1144 /* minimum value is actually mute */ 1154 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
1145 vmaster_tlv[3] |= TLV_DB_SCALE_MUTE; 1155 vmaster_tlv, slave_pfxs,
1146 err = snd_hda_add_vmaster(codec, "Master Playback Volume", 1156 "Playback Volume");
1147 vmaster_tlv, slave_pfxs, 1157 if (err < 0)
1148 "Playback Volume"); 1158 return err;
1149 if (err < 0) 1159
1150 return err; 1160 err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
1151 } 1161 NULL, slave_pfxs,
1152 if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { 1162 "Playback Switch", true,
1153 err = snd_hda_add_vmaster(codec, "Master Playback Switch", 1163 &spec->vmaster_sw_kctl);
1154 NULL, slave_pfxs, 1164 if (err < 0)
1155 "Playback Switch"); 1165 return err;
1156 if (err < 0) 1166
1157 return err; 1167 if (spec->gpio_led) {
1168 snd_ctl_add_vmaster_hook(spec->vmaster_sw_kctl,
1169 stac92xx_vmaster_hook, codec);
1170 snd_ctl_sync_vmaster_hook(spec->vmaster_sw_kctl);
1158 } 1171 }
1159 1172
1160 if (spec->aloopback_ctl && 1173 if (spec->aloopback_ctl &&
@@ -4419,8 +4432,7 @@ static int stac92xx_init(struct hda_codec *codec)
4419 snd_hda_jack_report_sync(codec); 4432 snd_hda_jack_report_sync(codec);
4420 4433
4421 /* sync mute LED */ 4434 /* sync mute LED */
4422 if (spec->gpio_led) 4435 snd_ctl_sync_vmaster_hook(spec->vmaster_sw_kctl);
4423 hda_call_check_power_status(codec, 0x01);
4424 if (spec->dac_list) 4436 if (spec->dac_list)
4425 stac92xx_power_down(codec); 4437 stac92xx_power_down(codec);
4426 return 0; 4438 return 0;
@@ -5033,83 +5045,37 @@ static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg,
5033 afg_power_state); 5045 afg_power_state);
5034 snd_hda_codec_set_power_to_all(codec, fg, power_state, true); 5046 snd_hda_codec_set_power_to_all(codec, fg, power_state, true);
5035} 5047}
5048#endif /* CONFIG_SND_HDA_POWER_SAVE */
5049#endif /* CONFIG_PM */
5036 5050
5037/* 5051/* update mute-LED accoring to the master switch */
5038 * For this feature CONFIG_SND_HDA_POWER_SAVE is needed 5052static void stac92xx_update_led_status(struct hda_codec *codec, int enabled)
5039 * as mute LED state is updated in check_power_status hook
5040 */
5041static int stac92xx_update_led_status(struct hda_codec *codec)
5042{ 5053{
5043 struct sigmatel_spec *spec = codec->spec; 5054 struct sigmatel_spec *spec = codec->spec;
5044 int i, num_ext_dacs, muted = 1; 5055 int muted = !enabled;
5045 unsigned int muted_lvl, notmtd_lvl;
5046 hda_nid_t nid;
5047 5056
5048 if (!spec->gpio_led) 5057 if (!spec->gpio_led)
5049 return 0; 5058 return;
5059
5060 /* LED state is inverted on these systems */
5061 if (spec->gpio_led_polarity)
5062 muted = !muted;
5050 5063
5051 for (i = 0; i < spec->multiout.num_dacs; i++) {
5052 nid = spec->multiout.dac_nids[i];
5053 if (!(snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) &
5054 HDA_AMP_MUTE)) {
5055 muted = 0; /* something heard */
5056 break;
5057 }
5058 }
5059 if (muted && spec->multiout.hp_nid)
5060 if (!(snd_hda_codec_amp_read(codec,
5061 spec->multiout.hp_nid, 0, HDA_OUTPUT, 0) &
5062 HDA_AMP_MUTE)) {
5063 muted = 0; /* HP is not muted */
5064 }
5065 num_ext_dacs = ARRAY_SIZE(spec->multiout.extra_out_nid);
5066 for (i = 0; muted && i < num_ext_dacs; i++) {
5067 nid = spec->multiout.extra_out_nid[i];
5068 if (nid == 0)
5069 break;
5070 if (!(snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) &
5071 HDA_AMP_MUTE)) {
5072 muted = 0; /* extra output is not muted */
5073 }
5074 }
5075 /*polarity defines *not* muted state level*/ 5064 /*polarity defines *not* muted state level*/
5076 if (!spec->vref_mute_led_nid) { 5065 if (!spec->vref_mute_led_nid) {
5077 if (muted) 5066 if (muted)
5078 spec->gpio_data &= ~spec->gpio_led; /* orange */ 5067 spec->gpio_data &= ~spec->gpio_led; /* orange */
5079 else 5068 else
5080 spec->gpio_data |= spec->gpio_led; /* white */ 5069 spec->gpio_data |= spec->gpio_led; /* white */
5081
5082 if (!spec->gpio_led_polarity) {
5083 /* LED state is inverted on these systems */
5084 spec->gpio_data ^= spec->gpio_led;
5085 }
5086 stac_gpio_set(codec, spec->gpio_mask, 5070 stac_gpio_set(codec, spec->gpio_mask,
5087 spec->gpio_dir, spec->gpio_data); 5071 spec->gpio_dir, spec->gpio_data);
5088 } else { 5072 } else {
5089 notmtd_lvl = spec->gpio_led_polarity ? 5073 spec->vref_led = muted ? AC_PINCTL_VREF_50 : AC_PINCTL_VREF_GRD;
5090 AC_PINCTL_VREF_50 : AC_PINCTL_VREF_GRD;
5091 muted_lvl = spec->gpio_led_polarity ?
5092 AC_PINCTL_VREF_GRD : AC_PINCTL_VREF_50;
5093 spec->vref_led = muted ? muted_lvl : notmtd_lvl;
5094 stac_vrefout_set(codec, spec->vref_mute_led_nid, 5074 stac_vrefout_set(codec, spec->vref_mute_led_nid,
5095 spec->vref_led); 5075 spec->vref_led);
5096 } 5076 }
5097 return 0;
5098} 5077}
5099 5078
5100/*
5101 * use power check for controlling mute led of HP notebooks
5102 */
5103static int stac92xx_check_power_status(struct hda_codec *codec,
5104 hda_nid_t nid)
5105{
5106 stac92xx_update_led_status(codec);
5107
5108 return 0;
5109}
5110#endif /* CONFIG_SND_HDA_POWER_SAVE */
5111#endif /* CONFIG_PM */
5112
5113static const struct hda_codec_ops stac92xx_patch_ops = { 5079static const struct hda_codec_ops stac92xx_patch_ops = {
5114 .build_controls = stac92xx_build_controls, 5080 .build_controls = stac92xx_build_controls,
5115 .build_pcms = stac92xx_build_pcms, 5081 .build_pcms = stac92xx_build_pcms,
@@ -5627,8 +5593,6 @@ again:
5627 stac92xx_set_power_state; 5593 stac92xx_set_power_state;
5628 } 5594 }
5629 codec->patch_ops.pre_resume = stac92xx_pre_resume; 5595 codec->patch_ops.pre_resume = stac92xx_pre_resume;
5630 codec->patch_ops.check_power_status =
5631 stac92xx_check_power_status;
5632 } 5596 }
5633#endif 5597#endif
5634 5598
@@ -5938,8 +5902,6 @@ again:
5938 stac92xx_set_power_state; 5902 stac92xx_set_power_state;
5939 } 5903 }
5940 codec->patch_ops.pre_resume = stac92xx_pre_resume; 5904 codec->patch_ops.pre_resume = stac92xx_pre_resume;
5941 codec->patch_ops.check_power_status =
5942 stac92xx_check_power_status;
5943 } 5905 }
5944#endif 5906#endif
5945 5907