ALSA: hda - Add TLV_DB_SCALE_MUTE bit for relevant controls
The DACs on Sigmatel/IDT codecs do mute at the lowest volume level, and in the earlier drivers, we passed TLV_DB_SCALE_MUTE bit for each volume control element like Speaker and Headphone as well as Master. Along with the translation to the generic parser, however, the TLV bit was lost for the slave controls (e.g. Speaker) but set only to Master. In theory this should have sufficed, but apps, particularly PA, do care the slave volume bits, so we seem to see a regression in the volume controls. This patch adds a flag to hda_gen_spec to specify the DAC mute feature, and adds the TLV bit properly for all relevant volume controls. Also, the TLV bit for vmaster is set in hda_generic.c, so that we can get rid of all tricks from the codec driver side. As the similar hack is applied to Conexant 5051 stuff, we can get rid of it as well. BugLink: https://bugs.launchpad.net/bugs/1357928 Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Родитель
aec856d0a8
Коммит
d89c6c0c91
|
@ -31,6 +31,7 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <sound/core.h>
|
#include <sound/core.h>
|
||||||
#include <sound/jack.h>
|
#include <sound/jack.h>
|
||||||
|
#include <sound/tlv.h>
|
||||||
#include "hda_codec.h"
|
#include "hda_codec.h"
|
||||||
#include "hda_local.h"
|
#include "hda_local.h"
|
||||||
#include "hda_auto_parser.h"
|
#include "hda_auto_parser.h"
|
||||||
|
@ -1105,6 +1106,7 @@ enum {
|
||||||
*/
|
*/
|
||||||
static int assign_out_path_ctls(struct hda_codec *codec, struct nid_path *path)
|
static int assign_out_path_ctls(struct hda_codec *codec, struct nid_path *path)
|
||||||
{
|
{
|
||||||
|
struct hda_gen_spec *spec = codec->spec;
|
||||||
hda_nid_t nid;
|
hda_nid_t nid;
|
||||||
unsigned int val;
|
unsigned int val;
|
||||||
int badness = 0;
|
int badness = 0;
|
||||||
|
@ -1119,6 +1121,8 @@ static int assign_out_path_ctls(struct hda_codec *codec, struct nid_path *path)
|
||||||
nid = look_for_out_vol_nid(codec, path);
|
nid = look_for_out_vol_nid(codec, path);
|
||||||
if (nid) {
|
if (nid) {
|
||||||
val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
|
val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
|
||||||
|
if (spec->dac_min_mute)
|
||||||
|
val |= HDA_AMP_VAL_MIN_MUTE;
|
||||||
if (is_ctl_used(codec, val, NID_PATH_VOL_CTL))
|
if (is_ctl_used(codec, val, NID_PATH_VOL_CTL))
|
||||||
badness += BAD_SHARED_VOL;
|
badness += BAD_SHARED_VOL;
|
||||||
else
|
else
|
||||||
|
@ -1880,9 +1884,12 @@ static int parse_output_paths(struct hda_codec *codec)
|
||||||
path = snd_hda_get_path_from_idx(codec, spec->out_paths[0]);
|
path = snd_hda_get_path_from_idx(codec, spec->out_paths[0]);
|
||||||
if (path)
|
if (path)
|
||||||
spec->vmaster_nid = look_for_out_vol_nid(codec, path);
|
spec->vmaster_nid = look_for_out_vol_nid(codec, path);
|
||||||
if (spec->vmaster_nid)
|
if (spec->vmaster_nid) {
|
||||||
snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
|
snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
|
||||||
HDA_OUTPUT, spec->vmaster_tlv);
|
HDA_OUTPUT, spec->vmaster_tlv);
|
||||||
|
if (spec->dac_min_mute)
|
||||||
|
spec->vmaster_tlv[3] |= TLV_DB_SCALE_MUTE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set initial pinctl targets */
|
/* set initial pinctl targets */
|
||||||
|
|
|
@ -231,6 +231,7 @@ struct hda_gen_spec {
|
||||||
unsigned int add_stereo_mix_input:1; /* add aamix as a capture src */
|
unsigned int add_stereo_mix_input:1; /* add aamix as a capture src */
|
||||||
unsigned int add_jack_modes:1; /* add i/o jack mode enum ctls */
|
unsigned int add_jack_modes:1; /* add i/o jack mode enum ctls */
|
||||||
unsigned int power_down_unused:1; /* power down unused widgets */
|
unsigned int power_down_unused:1; /* power down unused widgets */
|
||||||
|
unsigned int dac_min_mute:1; /* minimal = mute for DACs */
|
||||||
|
|
||||||
/* other internal flags */
|
/* other internal flags */
|
||||||
unsigned int no_analog:1; /* digital I/O only */
|
unsigned int no_analog:1; /* digital I/O only */
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <sound/core.h>
|
#include <sound/core.h>
|
||||||
#include <sound/jack.h>
|
#include <sound/jack.h>
|
||||||
#include <sound/tlv.h>
|
|
||||||
|
|
||||||
#include "hda_codec.h"
|
#include "hda_codec.h"
|
||||||
#include "hda_local.h"
|
#include "hda_local.h"
|
||||||
|
@ -779,6 +778,7 @@ static const struct hda_model_fixup cxt5066_fixup_models[] = {
|
||||||
*/
|
*/
|
||||||
static void add_cx5051_fake_mutes(struct hda_codec *codec)
|
static void add_cx5051_fake_mutes(struct hda_codec *codec)
|
||||||
{
|
{
|
||||||
|
struct conexant_spec *spec = codec->spec;
|
||||||
static hda_nid_t out_nids[] = {
|
static hda_nid_t out_nids[] = {
|
||||||
0x10, 0x11, 0
|
0x10, 0x11, 0
|
||||||
};
|
};
|
||||||
|
@ -788,6 +788,7 @@ static void add_cx5051_fake_mutes(struct hda_codec *codec)
|
||||||
snd_hda_override_amp_caps(codec, *p, HDA_OUTPUT,
|
snd_hda_override_amp_caps(codec, *p, HDA_OUTPUT,
|
||||||
AC_AMPCAP_MIN_MUTE |
|
AC_AMPCAP_MIN_MUTE |
|
||||||
query_amp_caps(codec, *p, HDA_OUTPUT));
|
query_amp_caps(codec, *p, HDA_OUTPUT));
|
||||||
|
spec->gen.dac_min_mute = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int patch_conexant_auto(struct hda_codec *codec)
|
static int patch_conexant_auto(struct hda_codec *codec)
|
||||||
|
@ -860,11 +861,6 @@ static int patch_conexant_auto(struct hda_codec *codec)
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (codec->vendor_id == 0x14f15051) {
|
|
||||||
/* minimum value is actually mute */
|
|
||||||
spec->gen.vmaster_tlv[3] |= TLV_DB_SCALE_MUTE;
|
|
||||||
}
|
|
||||||
|
|
||||||
codec->patch_ops = cx_auto_patch_ops;
|
codec->patch_ops = cx_auto_patch_ops;
|
||||||
|
|
||||||
/* Some laptops with Conexant chips show stalls in S3 resume,
|
/* Some laptops with Conexant chips show stalls in S3 resume,
|
||||||
|
|
|
@ -32,7 +32,6 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <sound/core.h>
|
#include <sound/core.h>
|
||||||
#include <sound/jack.h>
|
#include <sound/jack.h>
|
||||||
#include <sound/tlv.h>
|
|
||||||
#include "hda_codec.h"
|
#include "hda_codec.h"
|
||||||
#include "hda_local.h"
|
#include "hda_local.h"
|
||||||
#include "hda_auto_parser.h"
|
#include "hda_auto_parser.h"
|
||||||
|
@ -4227,9 +4226,6 @@ static int stac_parse_auto_config(struct hda_codec *codec)
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
/* minimum value is actually mute */
|
|
||||||
spec->gen.vmaster_tlv[3] |= TLV_DB_SCALE_MUTE;
|
|
||||||
|
|
||||||
/* setup analog beep controls */
|
/* setup analog beep controls */
|
||||||
if (spec->anabeep_nid > 0) {
|
if (spec->anabeep_nid > 0) {
|
||||||
err = stac_auto_create_beep_ctls(codec,
|
err = stac_auto_create_beep_ctls(codec,
|
||||||
|
@ -4413,6 +4409,7 @@ static int alloc_stac_spec(struct hda_codec *codec)
|
||||||
snd_hda_gen_spec_init(&spec->gen);
|
snd_hda_gen_spec_init(&spec->gen);
|
||||||
codec->spec = spec;
|
codec->spec = spec;
|
||||||
codec->no_trigger_sense = 1; /* seems common with STAC/IDT codecs */
|
codec->no_trigger_sense = 1; /* seems common with STAC/IDT codecs */
|
||||||
|
spec->gen.dac_min_mute = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче