aboutsummaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
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 a4d4afe6b4f..c2d4abee3b0 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;
}