summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2009-01-20 15:28:38 +0100
committerTakashi Iwai <tiwai@suse.de>2009-01-20 15:31:14 +0100
commit7c7767ebe2fa847c91a0dd5551ca422aba359473 (patch)
tree8356cff935ff184fadfadc1881fdb81b74ac2a12 /sound
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')
-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 a4d4afe6b4fc..c2d4abee3b09 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -166,6 +166,7 @@ struct sigmatel_spec {
unsigned int alt_switch: 1;
unsigned int hp_detect: 1;
unsigned int spdif_mute: 1;
+ unsigned int check_volume_offset:1;
/* gpio lines */
unsigned int eapd_mask;
@@ -202,6 +203,8 @@ struct sigmatel_spec {
hda_nid_t hp_dacs[5];
hda_nid_t speaker_dacs[5];
+ int volume_offset;
+
/* capture */
hda_nid_t *adc_nids;
unsigned int num_adcs;
@@ -1297,6 +1300,8 @@ static int stac92xx_build_controls(struct hda_codec *codec)
unsigned int vmaster_tlv[4];
snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0],
HDA_OUTPUT, vmaster_tlv);
+ /* correct volume offset */
+ vmaster_tlv[2] += vmaster_tlv[3] * spec->volume_offset;
err = snd_hda_add_vmaster(codec, "Master Playback Volume",
vmaster_tlv, slave_vols);
if (err < 0)
@@ -2980,14 +2985,34 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec)
}
/* create volume control/switch for the given prefx type */
-static int create_controls(struct sigmatel_spec *spec, const char *pfx, hda_nid_t nid, int chs)
+static int create_controls(struct hda_codec *codec, const char *pfx,
+ hda_nid_t nid, int chs)
{
+ struct sigmatel_spec *spec = codec->spec;
char name[32];
int err;
+ if (!spec->check_volume_offset) {
+ unsigned int caps, step, nums, db_scale;
+ caps = query_amp_caps(codec, nid, HDA_OUTPUT);
+ step = (caps & AC_AMPCAP_STEP_SIZE) >>
+ AC_AMPCAP_STEP_SIZE_SHIFT;
+ step = (step + 1) * 25; /* in .01dB unit */
+ nums = (caps & AC_AMPCAP_NUM_STEPS) >>
+ AC_AMPCAP_NUM_STEPS_SHIFT;
+ db_scale = nums * step;
+ /* if dB scale is over -64dB, and finer enough,
+ * let's reduce it to half
+ */
+ if (db_scale > 6400 && nums >= 0x1f)
+ spec->volume_offset = nums / 2;
+ spec->check_volume_offset = 1;
+ }
+
sprintf(name, "%s Playback Volume", pfx);
err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, name,
- HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
+ HDA_COMPOSE_AMP_VAL_OFS(nid, chs, 0, HDA_OUTPUT,
+ spec->volume_offset));
if (err < 0)
return err;
sprintf(name, "%s Playback Switch", pfx);
@@ -3053,10 +3078,10 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
nid = spec->multiout.dac_nids[i];
if (i == 2) {
/* Center/LFE */
- err = create_controls(spec, "Center", nid, 1);
+ err = create_controls(codec, "Center", nid, 1);
if (err < 0)
return err;
- err = create_controls(spec, "LFE", nid, 2);
+ err = create_controls(codec, "LFE", nid, 2);
if (err < 0)
return err;
@@ -3084,7 +3109,7 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
break;
}
}
- err = create_controls(spec, name, nid, 3);
+ err = create_controls(codec, name, nid, 3);
if (err < 0)
return err;
}
@@ -3139,7 +3164,7 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec,
nid = spec->hp_dacs[i];
if (!nid)
continue;
- err = create_controls(spec, pfxs[nums++], nid, 3);
+ err = create_controls(codec, pfxs[nums++], nid, 3);
if (err < 0)
return err;
}
@@ -3153,7 +3178,7 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec,
nid = spec->speaker_dacs[i];
if (!nid)
continue;
- err = create_controls(spec, pfxs[nums++], nid, 3);
+ err = create_controls(codec, pfxs[nums++], nid, 3);
if (err < 0)
return err;
}
@@ -3729,7 +3754,7 @@ static int stac9200_auto_create_lfe_ctls(struct hda_codec *codec,
}
if (lfe_pin) {
- err = create_controls(spec, "LFE", lfe_pin, 1);
+ err = create_controls(codec, "LFE", lfe_pin, 1);
if (err < 0)
return err;
}