aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2009-01-20 07:07:55 -0500
committerTakashi Iwai <tiwai@suse.de>2009-01-20 09:16:47 -0500
commit29fdbec2dcb1ce364812778271056aa9516ff3ed (patch)
treeb5d423645023b018b7e7de4e769c2f35d28e7885 /sound/pci/hda
parent989738c4f82126207b9e04c9395b78e544f3d33c (diff)
ALSA: hda - Add extra volume offset to standard volume amp macros
Added the volume offset to base for the standard volume controls to handle elements with too big volume scales like -96dB..0dB. For such elements, you can set the base volume to reduce the range. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda')
-rw-r--r--sound/pci/hda/hda_codec.c45
-rw-r--r--sound/pci/hda/hda_local.h5
2 files changed, 41 insertions, 9 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index b7bba7dc7cf1..0cf2424ada6a 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1119,6 +1119,7 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
1119 u16 nid = get_amp_nid(kcontrol); 1119 u16 nid = get_amp_nid(kcontrol);
1120 u8 chs = get_amp_channels(kcontrol); 1120 u8 chs = get_amp_channels(kcontrol);
1121 int dir = get_amp_direction(kcontrol); 1121 int dir = get_amp_direction(kcontrol);
1122 unsigned int ofs = get_amp_offset(kcontrol);
1122 u32 caps; 1123 u32 caps;
1123 1124
1124 caps = query_amp_caps(codec, nid, dir); 1125 caps = query_amp_caps(codec, nid, dir);
@@ -1130,6 +1131,8 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
1130 kcontrol->id.name); 1131 kcontrol->id.name);
1131 return -EINVAL; 1132 return -EINVAL;
1132 } 1133 }
1134 if (ofs < caps)
1135 caps -= ofs;
1133 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 1136 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1134 uinfo->count = chs == 3 ? 2 : 1; 1137 uinfo->count = chs == 3 ? 2 : 1;
1135 uinfo->value.integer.min = 0; 1138 uinfo->value.integer.min = 0;
@@ -1138,6 +1141,32 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
1138} 1141}
1139EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info); 1142EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
1140 1143
1144
1145static inline unsigned int
1146read_amp_value(struct hda_codec *codec, hda_nid_t nid,
1147 int ch, int dir, int idx, unsigned int ofs)
1148{
1149 unsigned int val;
1150 val = snd_hda_codec_amp_read(codec, nid, ch, dir, idx);
1151 val &= HDA_AMP_VOLMASK;
1152 if (val >= ofs)
1153 val -= ofs;
1154 else
1155 val = 0;
1156 return val;
1157}
1158
1159static inline int
1160update_amp_value(struct hda_codec *codec, hda_nid_t nid,
1161 int ch, int dir, int idx, unsigned int ofs,
1162 unsigned int val)
1163{
1164 if (val > 0)
1165 val += ofs;
1166 return snd_hda_codec_amp_update(codec, nid, ch, dir, idx,
1167 HDA_AMP_VOLMASK, val);
1168}
1169
1141int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, 1170int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
1142 struct snd_ctl_elem_value *ucontrol) 1171 struct snd_ctl_elem_value *ucontrol)
1143{ 1172{
@@ -1146,14 +1175,13 @@ int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
1146 int chs = get_amp_channels(kcontrol); 1175 int chs = get_amp_channels(kcontrol);
1147 int dir = get_amp_direction(kcontrol); 1176 int dir = get_amp_direction(kcontrol);
1148 int idx = get_amp_index(kcontrol); 1177 int idx = get_amp_index(kcontrol);
1178 unsigned int ofs = get_amp_offset(kcontrol);
1149 long *valp = ucontrol->value.integer.value; 1179 long *valp = ucontrol->value.integer.value;
1150 1180
1151 if (chs & 1) 1181 if (chs & 1)
1152 *valp++ = snd_hda_codec_amp_read(codec, nid, 0, dir, idx) 1182 *valp++ = read_amp_value(codec, nid, 0, dir, idx, ofs);
1153 & HDA_AMP_VOLMASK;
1154 if (chs & 2) 1183 if (chs & 2)
1155 *valp = snd_hda_codec_amp_read(codec, nid, 1, dir, idx) 1184 *valp = read_amp_value(codec, nid, 1, dir, idx, ofs);
1156 & HDA_AMP_VOLMASK;
1157 return 0; 1185 return 0;
1158} 1186}
1159EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get); 1187EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get);
@@ -1166,18 +1194,17 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
1166 int chs = get_amp_channels(kcontrol); 1194 int chs = get_amp_channels(kcontrol);
1167 int dir = get_amp_direction(kcontrol); 1195 int dir = get_amp_direction(kcontrol);
1168 int idx = get_amp_index(kcontrol); 1196 int idx = get_amp_index(kcontrol);
1197 unsigned int ofs = get_amp_offset(kcontrol);
1169 long *valp = ucontrol->value.integer.value; 1198 long *valp = ucontrol->value.integer.value;
1170 int change = 0; 1199 int change = 0;
1171 1200
1172 snd_hda_power_up(codec); 1201 snd_hda_power_up(codec);
1173 if (chs & 1) { 1202 if (chs & 1) {
1174 change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx, 1203 change = update_amp_value(codec, nid, 0, dir, idx, ofs, *valp);
1175 0x7f, *valp);
1176 valp++; 1204 valp++;
1177 } 1205 }
1178 if (chs & 2) 1206 if (chs & 2)
1179 change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, 1207 change |= update_amp_value(codec, nid, 1, dir, idx, ofs, *valp);
1180 0x7f, *valp);
1181 snd_hda_power_down(codec); 1208 snd_hda_power_down(codec);
1182 return change; 1209 return change;
1183} 1210}
@@ -1189,6 +1216,7 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1189 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 1216 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1190 hda_nid_t nid = get_amp_nid(kcontrol); 1217 hda_nid_t nid = get_amp_nid(kcontrol);
1191 int dir = get_amp_direction(kcontrol); 1218 int dir = get_amp_direction(kcontrol);
1219 unsigned int ofs = get_amp_offset(kcontrol);
1192 u32 caps, val1, val2; 1220 u32 caps, val1, val2;
1193 1221
1194 if (size < 4 * sizeof(unsigned int)) 1222 if (size < 4 * sizeof(unsigned int))
@@ -1197,6 +1225,7 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1197 val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT; 1225 val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
1198 val2 = (val2 + 1) * 25; 1226 val2 = (val2 + 1) * 25;
1199 val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT); 1227 val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
1228 val1 += ofs;
1200 val1 = ((int)val1) * ((int)val2); 1229 val1 = ((int)val1) * ((int)val2);
1201 if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv)) 1230 if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
1202 return -EFAULT; 1231 return -EFAULT;
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 1dd8716c387f..d53ce1f85419 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -26,8 +26,10 @@
26/* 26/*
27 * for mixer controls 27 * for mixer controls
28 */ 28 */
29#define HDA_COMPOSE_AMP_VAL_OFS(nid,chs,idx,dir,ofs) \
30 ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19) | ((ofs)<<23))
29#define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) \ 31#define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) \
30 ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19)) 32 HDA_COMPOSE_AMP_VAL_OFS(nid, chs, idx, dir, 0)
31/* mono volume with index (index=0,1,...) (channel=1,2) */ 33/* mono volume with index (index=0,1,...) (channel=1,2) */
32#define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ 34#define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \
33 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ 35 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \
@@ -456,6 +458,7 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec,
456#define get_amp_channels(kc) (((kc)->private_value >> 16) & 0x3) 458#define get_amp_channels(kc) (((kc)->private_value >> 16) & 0x3)
457#define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1) 459#define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1)
458#define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf) 460#define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf)
461#define get_amp_offset(kc) (((kc)->private_value >> 23) & 0x3f)
459 462
460/* 463/*
461 * CEA Short Audio Descriptor data 464 * CEA Short Audio Descriptor data