aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/hda_codec.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2008-01-10 10:53:55 -0500
committerJaroslav Kysela <perex@perex.cz>2008-01-31 11:29:54 -0500
commit2134ea4f37d36addbe86d4901f6c67a22a5db006 (patch)
tree804d187d5c46d71246db2d8919a59e2e7feef956 /sound/pci/hda/hda_codec.c
parent3b0a5f22d4649433a5842ffc7313803292e95718 (diff)
[ALSA] hda-codec - Add virtual master controls
Add master controls using vmaster to codecs that have no real hardware master volume registers. Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r--sound/pci/hda/hda_codec.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index a2b40dc372c9..caacc58c0813 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1012,6 +1012,66 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1012 return 0; 1012 return 0;
1013} 1013}
1014 1014
1015/*
1016 * set (static) TLV for virtual master volume; recalculated as max 0dB
1017 */
1018void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
1019 unsigned int *tlv)
1020{
1021 u32 caps;
1022 int nums, step;
1023
1024 caps = query_amp_caps(codec, nid, dir);
1025 nums = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1026 step = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1027 step = (step + 1) * 25;
1028 tlv[0] = SNDRV_CTL_TLVT_DB_SCALE;
1029 tlv[1] = 2 * sizeof(unsigned int);
1030 tlv[2] = -nums * step;
1031 tlv[3] = step;
1032}
1033
1034/* find a mixer control element with the given name */
1035struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
1036 const char *name)
1037{
1038 struct snd_ctl_elem_id id;
1039 memset(&id, 0, sizeof(id));
1040 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1041 strcpy(id.name, name);
1042 return snd_ctl_find_id(codec->bus->card, &id);
1043}
1044
1045/* create a virtual master control and add slaves */
1046int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
1047 unsigned int *tlv, const char **slaves)
1048{
1049 struct snd_kcontrol *kctl;
1050 const char **s;
1051 int err;
1052
1053 kctl = snd_ctl_make_virtual_master(name, tlv);
1054 if (!kctl)
1055 return -ENOMEM;
1056 err = snd_ctl_add(codec->bus->card, kctl);
1057 if (err < 0)
1058 return err;
1059
1060 for (s = slaves; *s; s++) {
1061 struct snd_kcontrol *sctl;
1062
1063 sctl = snd_hda_find_mixer_ctl(codec, *s);
1064 if (!sctl) {
1065 snd_printdd("Cannot find slave %s, skipped\n", *s);
1066 continue;
1067 }
1068 err = snd_ctl_add_slave(kctl, sctl);
1069 if (err < 0)
1070 return err;
1071 }
1072 return 0;
1073}
1074
1015/* switch */ 1075/* switch */
1016int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, 1076int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
1017 struct snd_ctl_elem_info *uinfo) 1077 struct snd_ctl_elem_info *uinfo)