1 From 7c7767ebe2fa847c91a0dd5551ca422aba359473 Mon Sep 17 00:00:00 2001
2 From: Takashi Iwai <tiwai@suse.de>
3 Date: Tue, 20 Jan 2009 15:28:38 +0100
4 Subject: ALSA: hda - Halve too large volume scales for STAC/IDT codecs
8 STAC/IDT codecs have often too large volume scales such as -96dB,
9 and exposing this as is results in too large scale in percentage
12 This patch adds the check of the volume scale and halves the
13 volume range if it's too large automatically.
15 Signed-off-by: Takashi Iwai <tiwai@suse.de>
18 sound/pci/hda/patch_sigmatel.c | 41 +++++++++++++++++++++++++++++++++--------
19 1 file changed, 33 insertions(+), 8 deletions(-)
21 --- a/sound/pci/hda/patch_sigmatel.c
22 +++ b/sound/pci/hda/patch_sigmatel.c
23 @@ -155,6 +155,7 @@ struct sigmatel_spec {
24 unsigned int alt_switch: 1;
25 unsigned int hp_detect: 1;
26 unsigned int spdif_mute: 1;
27 + unsigned int check_volume_offset:1;
30 unsigned int eapd_mask;
31 @@ -183,6 +184,8 @@ struct sigmatel_spec {
32 struct hda_multi_out multiout;
33 hda_nid_t dac_nids[5];
39 unsigned int num_adcs;
40 @@ -1310,6 +1313,8 @@ static int stac92xx_build_controls(struc
41 unsigned int vmaster_tlv[4];
42 snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0],
43 HDA_OUTPUT, vmaster_tlv);
44 + /* correct volume offset */
45 + vmaster_tlv[2] += vmaster_tlv[3] * spec->volume_offset;
46 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
47 vmaster_tlv, slave_vols);
49 @@ -2885,14 +2890,34 @@ static int stac92xx_auto_fill_dac_nids(s
52 /* create volume control/switch for the given prefx type */
53 -static int create_controls(struct sigmatel_spec *spec, const char *pfx, hda_nid_t nid, int chs)
54 +static int create_controls(struct hda_codec *codec, const char *pfx,
55 + hda_nid_t nid, int chs)
57 + struct sigmatel_spec *spec = codec->spec;
61 + if (!spec->check_volume_offset) {
62 + unsigned int caps, step, nums, db_scale;
63 + caps = query_amp_caps(codec, nid, HDA_OUTPUT);
64 + step = (caps & AC_AMPCAP_STEP_SIZE) >>
65 + AC_AMPCAP_STEP_SIZE_SHIFT;
66 + step = (step + 1) * 25; /* in .01dB unit */
67 + nums = (caps & AC_AMPCAP_NUM_STEPS) >>
68 + AC_AMPCAP_NUM_STEPS_SHIFT;
69 + db_scale = nums * step;
70 + /* if dB scale is over -64dB, and finer enough,
71 + * let's reduce it to half
73 + if (db_scale > 6400 && nums >= 0x1f)
74 + spec->volume_offset = nums / 2;
75 + spec->check_volume_offset = 1;
78 sprintf(name, "%s Playback Volume", pfx);
79 err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, name,
80 - HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
81 + HDA_COMPOSE_AMP_VAL_OFS(nid, chs, 0, HDA_OUTPUT,
82 + spec->volume_offset));
85 sprintf(name, "%s Playback Switch", pfx);
86 @@ -2948,10 +2973,10 @@ static int stac92xx_auto_create_multi_ou
90 - err = create_controls(spec, "Center", nid, 1);
91 + err = create_controls(codec, "Center", nid, 1);
94 - err = create_controls(spec, "LFE", nid, 2);
95 + err = create_controls(codec, "LFE", nid, 2);
99 @@ -2967,7 +2992,7 @@ static int stac92xx_auto_create_multi_ou
103 - err = create_controls(spec, chname[i], nid, 3);
104 + err = create_controls(codec, chname[i], nid, 3);
108 @@ -3074,13 +3099,13 @@ static int stac92xx_auto_create_hp_ctls(
109 static const char *pfxs[] = {
110 "Speaker", "External Speaker", "Speaker2",
112 - err = create_controls(spec, pfxs[i - old_num_dacs],
113 + err = create_controls(codec, pfxs[i - old_num_dacs],
114 spec->multiout.dac_nids[i], 3);
118 if (spec->multiout.hp_nid) {
119 - err = create_controls(spec, "Headphone",
120 + err = create_controls(codec, "Headphone",
121 spec->multiout.hp_nid, 3);
124 @@ -3670,7 +3695,7 @@ static int stac9200_auto_create_lfe_ctls
128 - err = create_controls(spec, "LFE", lfe_pin, 1);
129 + err = create_controls(codec, "LFE", lfe_pin, 1);