aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_sigmatel.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2009-01-20 09:28:38 -0500
committerTakashi Iwai <tiwai@suse.de>2009-01-20 09:31:14 -0500
commit7c7767ebe2fa847c91a0dd5551ca422aba359473 (patch)
tree8356cff935ff184fadfadc1881fdb81b74ac2a12 /sound/pci/hda/patch_sigmatel.c
parent29fdbec2dcb1ce364812778271056aa9516ff3ed (diff)
ALSA: hda - Halve too large volume scales for STAC/IDT codecs
STAC/IDT codecs have often too large volume scales such as -96dB, and exposing this as is results in too large scale in percentage representation. This patch adds the check of the volume scale and halves the volume range if it's too large automatically. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/patch_sigmatel.c')
-rw-r--r--sound/pci/hda/patch_sigmatel.c41
1 files changed, 33 insertions, 8 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index a4d4afe6b4f..c2d4abee3b0 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -166,6 +166,7 @@ struct sigmatel_spec {
166 unsigned int alt_switch: 1; 166 unsigned int alt_switch: 1;
167 unsigned int hp_detect: 1; 167 unsigned int hp_detect: 1;
168 unsigned int spdif_mute: 1; 168 unsigned int spdif_mute: 1;
169 unsigned int check_volume_offset:1;
169 170
170 /* gpio lines */ 171 /* gpio lines */
171 unsigned int eapd_mask; 172 unsigned int eapd_mask;
@@ -202,6 +203,8 @@ struct sigmatel_spec {
202 hda_nid_t hp_dacs[5]; 203 hda_nid_t hp_dacs[5];
203 hda_nid_t speaker_dacs[5]; 204 hda_nid_t speaker_dacs[5];
204 205
206 int volume_offset;
207
205 /* capture */ 208 /* capture */
206 hda_nid_t *adc_nids; 209 hda_nid_t *adc_nids;
207 unsigned int num_adcs; 210 unsigned int num_adcs;
@@ -1297,6 +1300,8 @@ static int stac92xx_build_controls(struct hda_codec *codec)
1297 unsigned int vmaster_tlv[4]; 1300 unsigned int vmaster_tlv[4];
1298 snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0], 1301 snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0],
1299 HDA_OUTPUT, vmaster_tlv); 1302 HDA_OUTPUT, vmaster_tlv);
1303 /* correct volume offset */
1304 vmaster_tlv[2] += vmaster_tlv[3] * spec->volume_offset;
1300 err = snd_hda_add_vmaster(codec, "Master Playback Volume", 1305 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
1301 vmaster_tlv, slave_vols); 1306 vmaster_tlv, slave_vols);
1302 if (err < 0) 1307 if (err < 0)
@@ -2980,14 +2985,34 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec)
2980} 2985}
2981 2986
2982/* create volume control/switch for the given prefx type */ 2987/* create volume control/switch for the given prefx type */
2983static int create_controls(struct sigmatel_spec *spec, const char *pfx, hda_nid_t nid, int chs) 2988static int create_controls(struct hda_codec *codec, const char *pfx,
2989 hda_nid_t nid, int chs)
2984{ 2990{
2991 struct sigmatel_spec *spec = codec->spec;
2985 char name[32]; 2992 char name[32];
2986 int err; 2993 int err;
2987 2994
2995 if (!spec->check_volume_offset) {
2996 unsigned int caps, step, nums, db_scale;
2997 caps = query_amp_caps(codec, nid, HDA_OUTPUT);
2998 step = (caps & AC_AMPCAP_STEP_SIZE) >>
2999 AC_AMPCAP_STEP_SIZE_SHIFT;
3000 step = (step + 1) * 25; /* in .01dB unit */
3001 nums = (caps & AC_AMPCAP_NUM_STEPS) >>
3002 AC_AMPCAP_NUM_STEPS_SHIFT;
3003 db_scale = nums * step;
3004 /* if dB scale is over -64dB, and finer enough,
3005 * let's reduce it to half
3006 */
3007 if (db_scale > 6400 && nums >= 0x1f)
3008 spec->volume_offset = nums / 2;
3009 spec->check_volume_offset = 1;
3010 }
3011
2988 sprintf(name, "%s Playback Volume", pfx); 3012 sprintf(name, "%s Playback Volume", pfx);
2989 err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, name, 3013 err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, name,
2990 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); 3014 HDA_COMPOSE_AMP_VAL_OFS(nid, chs, 0, HDA_OUTPUT,
3015 spec->volume_offset));
2991 if (err < 0) 3016 if (err < 0)
2992 return err; 3017 return err;
2993 sprintf(name, "%s Playback Switch", pfx); 3018 sprintf(name, "%s Playback Switch", pfx);
@@ -3053,10 +3078,10 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
3053 nid = spec->multiout.dac_nids[i]; 3078 nid = spec->multiout.dac_nids[i];
3054 if (i == 2) { 3079 if (i == 2) {
3055 /* Center/LFE */ 3080 /* Center/LFE */
3056 err = create_controls(spec, "Center", nid, 1); 3081 err = create_controls(codec, "Center", nid, 1);
3057 if (err < 0) 3082 if (err < 0)
3058 return err; 3083 return err;
3059 err = create_controls(spec, "LFE", nid, 2); 3084 err = create_controls(codec, "LFE", nid, 2);
3060 if (err < 0) 3085 if (err < 0)
3061 return err; 3086 return err;
3062 3087
@@ -3084,7 +3109,7 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
3084 break; 3109 break;
3085 } 3110 }
3086 } 3111 }
3087 err = create_controls(spec, name, nid, 3); 3112 err = create_controls(codec, name, nid, 3);
3088 if (err < 0) 3113 if (err < 0)
3089 return err; 3114 return err;
3090 } 3115 }
@@ -3139,7 +3164,7 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec,
3139 nid = spec->hp_dacs[i]; 3164 nid = spec->hp_dacs[i];
3140 if (!nid) 3165 if (!nid)
3141 continue; 3166 continue;
3142 err = create_controls(spec, pfxs[nums++], nid, 3); 3167 err = create_controls(codec, pfxs[nums++], nid, 3);
3143 if (err < 0) 3168 if (err < 0)
3144 return err; 3169 return err;
3145 } 3170 }
@@ -3153,7 +3178,7 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec,
3153 nid = spec->speaker_dacs[i]; 3178 nid = spec->speaker_dacs[i];
3154 if (!nid) 3179 if (!nid)
3155 continue; 3180 continue;
3156 err = create_controls(spec, pfxs[nums++], nid, 3); 3181 err = create_controls(codec, pfxs[nums++], nid, 3);
3157 if (err < 0) 3182 if (err < 0)
3158 return err; 3183 return err;
3159 } 3184 }
@@ -3729,7 +3754,7 @@ static int stac9200_auto_create_lfe_ctls(struct hda_codec *codec,
3729 } 3754 }
3730 3755
3731 if (lfe_pin) { 3756 if (lfe_pin) {
3732 err = create_controls(spec, "LFE", lfe_pin, 1); 3757 err = create_controls(codec, "LFE", lfe_pin, 1);
3733 if (err < 0) 3758 if (err < 0)
3734 return err; 3759 return err;
3735 } 3760 }