Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 81621
b: refs/heads/master
c: 2134ea4
h: refs/heads/master
i:
  81619: 128eb8f
v: v3
  • Loading branch information
Takashi Iwai authored and Jaroslav Kysela committed Jan 31, 2008
1 parent cbbe577 commit 5ac7c4b
Show file tree
Hide file tree
Showing 6 changed files with 277 additions and 20 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 3b0a5f22d4649433a5842ffc7313803292e95718
refs/heads/master: 2134ea4f37d36addbe86d4901f6c67a22a5db006
60 changes: 60 additions & 0 deletions trunk/sound/pci/hda/hda_codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -1012,6 +1012,66 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
return 0;
}

/*
* set (static) TLV for virtual master volume; recalculated as max 0dB
*/
void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
unsigned int *tlv)
{
u32 caps;
int nums, step;

caps = query_amp_caps(codec, nid, dir);
nums = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
step = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
step = (step + 1) * 25;
tlv[0] = SNDRV_CTL_TLVT_DB_SCALE;
tlv[1] = 2 * sizeof(unsigned int);
tlv[2] = -nums * step;
tlv[3] = step;
}

/* find a mixer control element with the given name */
struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
const char *name)
{
struct snd_ctl_elem_id id;
memset(&id, 0, sizeof(id));
id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
strcpy(id.name, name);
return snd_ctl_find_id(codec->bus->card, &id);
}

/* create a virtual master control and add slaves */
int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
unsigned int *tlv, const char **slaves)
{
struct snd_kcontrol *kctl;
const char **s;
int err;

kctl = snd_ctl_make_virtual_master(name, tlv);
if (!kctl)
return -ENOMEM;
err = snd_ctl_add(codec->bus->card, kctl);
if (err < 0)
return err;

for (s = slaves; *s; s++) {
struct snd_kcontrol *sctl;

sctl = snd_hda_find_mixer_ctl(codec, *s);
if (!sctl) {
snd_printdd("Cannot find slave %s, skipped\n", *s);
continue;
}
err = snd_ctl_add_slave(kctl, sctl);
if (err < 0)
return err;
}
return 0;
}

/* switch */
int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
Expand Down
7 changes: 7 additions & 0 deletions trunk/sound/pci/hda/hda_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
void snd_hda_codec_resume_amp(struct hda_codec *codec);
#endif

void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
unsigned int *tlv);
struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
const char *name);
int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
unsigned int *tlv, const char **slaves);

/* amp value bits */
#define HDA_AMP_MUTE 0x80
#define HDA_AMP_UNMUTE 0x00
Expand Down
69 changes: 69 additions & 0 deletions trunk/sound/pci/hda/patch_analog.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ struct ad198x_spec {
#ifdef CONFIG_SND_HDA_POWER_SAVE
struct hda_loopback_check loopback;
#endif
/* for virtual master */
hda_nid_t vmaster_nid;
u32 vmaster_tlv[4];
const char **slave_vols;
const char **slave_sws;
};

/*
Expand Down Expand Up @@ -125,6 +130,28 @@ static int ad198x_init(struct hda_codec *codec)
return 0;
}

static const char *ad_slave_vols[] = {
"Front Playback Volume",
"Surround Playback Volume",
"Center Playback Volume",
"LFE Playback Volume",
"Side Playback Volume",
"Headphone Playback Volume",
"Mono Playback Volume",
NULL
};

static const char *ad_slave_sws[] = {
"Front Playback Switch",
"Surround Playback Switch",
"Center Playback Switch",
"LFE Playback Switch",
"Side Playback Switch",
"Headphone Playback Switch",
"Mono Playback Switch",
NULL
};

static int ad198x_build_controls(struct hda_codec *codec)
{
struct ad198x_spec *spec = codec->spec;
Expand All @@ -146,6 +173,27 @@ static int ad198x_build_controls(struct hda_codec *codec)
if (err < 0)
return err;
}

/* if we have no master control, let's create it */
if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
HDA_OUTPUT, spec->vmaster_tlv);
err = snd_hda_add_vmaster(codec, "Master Playback Volume",
spec->vmaster_tlv,
(spec->slave_vols ?
spec->slave_vols : ad_slave_vols));
if (err < 0)
return err;
}
if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
err = snd_hda_add_vmaster(codec, "Master Playback Switch",
NULL,
(spec->slave_sws ?
spec->slave_sws : ad_slave_sws));
if (err < 0)
return err;
}

return 0;
}

Expand Down Expand Up @@ -899,6 +947,7 @@ static int patch_ad1986a(struct hda_codec *codec)
#ifdef CONFIG_SND_HDA_POWER_SAVE
spec->loopback.amplist = ad1986a_loopbacks;
#endif
spec->vmaster_nid = 0x1b;

codec->patch_ops = ad198x_patch_ops;

Expand Down Expand Up @@ -1141,6 +1190,7 @@ static int patch_ad1983(struct hda_codec *codec)
#ifdef CONFIG_SND_HDA_POWER_SAVE
spec->loopback.amplist = ad1983_loopbacks;
#endif
spec->vmaster_nid = 0x05;

codec->patch_ops = ad198x_patch_ops;

Expand Down Expand Up @@ -1537,6 +1587,7 @@ static int patch_ad1981(struct hda_codec *codec)
#ifdef CONFIG_SND_HDA_POWER_SAVE
spec->loopback.amplist = ad1981_loopbacks;
#endif
spec->vmaster_nid = 0x05;

codec->patch_ops = ad198x_patch_ops;

Expand Down Expand Up @@ -2850,6 +2901,7 @@ static int patch_ad1988(struct hda_codec *codec)
#ifdef CONFIG_SND_HDA_POWER_SAVE
spec->loopback.amplist = ad1988_loopbacks;
#endif
spec->vmaster_nid = 0x04;

return 0;
}
Expand Down Expand Up @@ -3016,6 +3068,19 @@ static struct hda_amp_list ad1884_loopbacks[] = {
};
#endif

static const char *ad1884_slave_vols[] = {
"PCM Playback Volume",
"Mic Playback Volume",
"Mono Playback Volume",
"Front Mic Playback Volume",
"Mic Playback Volume",
"CD Playback Volume",
"Internal Mic Playback Volume",
"Docking Mic Playback Volume"
"Beep Playback Volume",
NULL
};

static int patch_ad1884(struct hda_codec *codec)
{
struct ad198x_spec *spec;
Expand Down Expand Up @@ -3043,6 +3108,9 @@ static int patch_ad1884(struct hda_codec *codec)
#ifdef CONFIG_SND_HDA_POWER_SAVE
spec->loopback.amplist = ad1884_loopbacks;
#endif
spec->vmaster_nid = 0x04;
/* we need to cover all playback volumes */
spec->slave_vols = ad1884_slave_vols;

codec->patch_ops = ad198x_patch_ops;

Expand Down Expand Up @@ -3485,6 +3553,7 @@ static int patch_ad1882(struct hda_codec *codec)
#ifdef CONFIG_SND_HDA_POWER_SAVE
spec->loopback.amplist = ad1882_loopbacks;
#endif
spec->vmaster_nid = 0x04;

codec->patch_ops = ad198x_patch_ops;

Expand Down
Loading

0 comments on commit 5ac7c4b

Please sign in to comment.