diff options
Diffstat (limited to 'sound/pci')
49 files changed, 2346 insertions, 601 deletions
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index e49c0fe21b0d..8a6b1803c763 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig | |||
@@ -475,6 +475,7 @@ config SND_FM801_TEA575X | |||
475 | depends on SND_FM801_TEA575X_BOOL | 475 | depends on SND_FM801_TEA575X_BOOL |
476 | default SND_FM801 | 476 | default SND_FM801 |
477 | select VIDEO_V4L1 | 477 | select VIDEO_V4L1 |
478 | select VIDEO_DEV | ||
478 | 479 | ||
479 | config SND_HDA_INTEL | 480 | config SND_HDA_INTEL |
480 | tristate "Intel HD Audio" | 481 | tristate "Intel HD Audio" |
@@ -743,4 +744,17 @@ config SND_YMFPCI | |||
743 | To compile this driver as a module, choose M here: the module | 744 | To compile this driver as a module, choose M here: the module |
744 | will be called snd-ymfpci. | 745 | will be called snd-ymfpci. |
745 | 746 | ||
747 | config SND_AC97_POWER_SAVE | ||
748 | bool "AC97 Power-Saving Mode" | ||
749 | depends on SND_AC97_CODEC && EXPERIMENTAL | ||
750 | default n | ||
751 | help | ||
752 | Say Y here to enable the aggressive power-saving support of | ||
753 | AC97 codecs. In this mode, the power-mode is dynamically | ||
754 | controlled at each open/close. | ||
755 | |||
756 | The mode is activated by passing power_save=1 option to | ||
757 | snd-ac97-codec driver. You can toggle it dynamically over | ||
758 | sysfs, too. | ||
759 | |||
746 | endmenu | 760 | endmenu |
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 51e83d7a839a..a79e91850ba3 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/mutex.h> | 31 | #include <linux/mutex.h> |
32 | #include <sound/core.h> | 32 | #include <sound/core.h> |
33 | #include <sound/pcm.h> | 33 | #include <sound/pcm.h> |
34 | #include <sound/tlv.h> | ||
34 | #include <sound/ac97_codec.h> | 35 | #include <sound/ac97_codec.h> |
35 | #include <sound/asoundef.h> | 36 | #include <sound/asoundef.h> |
36 | #include <sound/initval.h> | 37 | #include <sound/initval.h> |
@@ -47,6 +48,11 @@ static int enable_loopback; | |||
47 | module_param(enable_loopback, bool, 0444); | 48 | module_param(enable_loopback, bool, 0444); |
48 | MODULE_PARM_DESC(enable_loopback, "Enable AC97 ADC/DAC Loopback Control"); | 49 | MODULE_PARM_DESC(enable_loopback, "Enable AC97 ADC/DAC Loopback Control"); |
49 | 50 | ||
51 | #ifdef CONFIG_SND_AC97_POWER_SAVE | ||
52 | static int power_save; | ||
53 | module_param(power_save, bool, 0644); | ||
54 | MODULE_PARM_DESC(power_save, "Enable AC97 power-saving control"); | ||
55 | #endif | ||
50 | /* | 56 | /* |
51 | 57 | ||
52 | */ | 58 | */ |
@@ -151,7 +157,7 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = { | |||
151 | { 0x4e534300, 0xffffffff, "LM4540,43,45,46,48", NULL, NULL }, // only guess --jk | 157 | { 0x4e534300, 0xffffffff, "LM4540,43,45,46,48", NULL, NULL }, // only guess --jk |
152 | { 0x4e534331, 0xffffffff, "LM4549", NULL, NULL }, | 158 | { 0x4e534331, 0xffffffff, "LM4549", NULL, NULL }, |
153 | { 0x4e534350, 0xffffffff, "LM4550", patch_lm4550, NULL }, // volume wrap fix | 159 | { 0x4e534350, 0xffffffff, "LM4550", patch_lm4550, NULL }, // volume wrap fix |
154 | { 0x50534304, 0xffffffff, "UCB1400", NULL, NULL }, | 160 | { 0x50534304, 0xffffffff, "UCB1400", patch_ucb1400, NULL }, |
155 | { 0x53494c20, 0xffffffe0, "Si3036,8", mpatch_si3036, mpatch_si3036, AC97_MODEM_PATCH }, | 161 | { 0x53494c20, 0xffffffe0, "Si3036,8", mpatch_si3036, mpatch_si3036, AC97_MODEM_PATCH }, |
156 | { 0x54524102, 0xffffffff, "TR28022", NULL, NULL }, | 162 | { 0x54524102, 0xffffffff, "TR28022", NULL, NULL }, |
157 | { 0x54524106, 0xffffffff, "TR28026", NULL, NULL }, | 163 | { 0x54524106, 0xffffffff, "TR28026", NULL, NULL }, |
@@ -187,6 +193,8 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = { | |||
187 | }; | 193 | }; |
188 | 194 | ||
189 | 195 | ||
196 | static void update_power_regs(struct snd_ac97 *ac97); | ||
197 | |||
190 | /* | 198 | /* |
191 | * I/O routines | 199 | * I/O routines |
192 | */ | 200 | */ |
@@ -554,6 +562,18 @@ int snd_ac97_put_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value | |||
554 | } | 562 | } |
555 | err = snd_ac97_update_bits(ac97, reg, val_mask, val); | 563 | err = snd_ac97_update_bits(ac97, reg, val_mask, val); |
556 | snd_ac97_page_restore(ac97, page_save); | 564 | snd_ac97_page_restore(ac97, page_save); |
565 | #ifdef CONFIG_SND_AC97_POWER_SAVE | ||
566 | /* check analog mixer power-down */ | ||
567 | if ((val_mask & 0x8000) && | ||
568 | (kcontrol->private_value & (1<<30))) { | ||
569 | if (val & 0x8000) | ||
570 | ac97->power_up &= ~(1 << (reg>>1)); | ||
571 | else | ||
572 | ac97->power_up |= 1 << (reg>>1); | ||
573 | if (power_save) | ||
574 | update_power_regs(ac97); | ||
575 | } | ||
576 | #endif | ||
557 | return err; | 577 | return err; |
558 | } | 578 | } |
559 | 579 | ||
@@ -962,6 +982,10 @@ static int snd_ac97_bus_dev_free(struct snd_device *device) | |||
962 | static int snd_ac97_free(struct snd_ac97 *ac97) | 982 | static int snd_ac97_free(struct snd_ac97 *ac97) |
963 | { | 983 | { |
964 | if (ac97) { | 984 | if (ac97) { |
985 | #ifdef CONFIG_SND_AC97_POWER_SAVE | ||
986 | if (ac97->power_workq) | ||
987 | destroy_workqueue(ac97->power_workq); | ||
988 | #endif | ||
965 | snd_ac97_proc_done(ac97); | 989 | snd_ac97_proc_done(ac97); |
966 | if (ac97->bus) | 990 | if (ac97->bus) |
967 | ac97->bus->codec[ac97->num] = NULL; | 991 | ac97->bus->codec[ac97->num] = NULL; |
@@ -1117,7 +1141,9 @@ struct snd_kcontrol *snd_ac97_cnew(const struct snd_kcontrol_new *_template, str | |||
1117 | /* | 1141 | /* |
1118 | * create mute switch(es) for normal stereo controls | 1142 | * create mute switch(es) for normal stereo controls |
1119 | */ | 1143 | */ |
1120 | static int snd_ac97_cmute_new_stereo(struct snd_card *card, char *name, int reg, int check_stereo, struct snd_ac97 *ac97) | 1144 | static int snd_ac97_cmute_new_stereo(struct snd_card *card, char *name, int reg, |
1145 | int check_stereo, int check_amix, | ||
1146 | struct snd_ac97 *ac97) | ||
1121 | { | 1147 | { |
1122 | struct snd_kcontrol *kctl; | 1148 | struct snd_kcontrol *kctl; |
1123 | int err; | 1149 | int err; |
@@ -1137,10 +1163,14 @@ static int snd_ac97_cmute_new_stereo(struct snd_card *card, char *name, int reg, | |||
1137 | } | 1163 | } |
1138 | if (mute_mask == 0x8080) { | 1164 | if (mute_mask == 0x8080) { |
1139 | struct snd_kcontrol_new tmp = AC97_DOUBLE(name, reg, 15, 7, 1, 1); | 1165 | struct snd_kcontrol_new tmp = AC97_DOUBLE(name, reg, 15, 7, 1, 1); |
1166 | if (check_amix) | ||
1167 | tmp.private_value |= (1 << 30); | ||
1140 | tmp.index = ac97->num; | 1168 | tmp.index = ac97->num; |
1141 | kctl = snd_ctl_new1(&tmp, ac97); | 1169 | kctl = snd_ctl_new1(&tmp, ac97); |
1142 | } else { | 1170 | } else { |
1143 | struct snd_kcontrol_new tmp = AC97_SINGLE(name, reg, 15, 1, 1); | 1171 | struct snd_kcontrol_new tmp = AC97_SINGLE(name, reg, 15, 1, 1); |
1172 | if (check_amix) | ||
1173 | tmp.private_value |= (1 << 30); | ||
1144 | tmp.index = ac97->num; | 1174 | tmp.index = ac97->num; |
1145 | kctl = snd_ctl_new1(&tmp, ac97); | 1175 | kctl = snd_ctl_new1(&tmp, ac97); |
1146 | } | 1176 | } |
@@ -1153,6 +1183,32 @@ static int snd_ac97_cmute_new_stereo(struct snd_card *card, char *name, int reg, | |||
1153 | } | 1183 | } |
1154 | 1184 | ||
1155 | /* | 1185 | /* |
1186 | * set dB information | ||
1187 | */ | ||
1188 | static DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0); | ||
1189 | static DECLARE_TLV_DB_SCALE(db_scale_5bit, -4650, 150, 0); | ||
1190 | static DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0); | ||
1191 | static DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); | ||
1192 | static DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0); | ||
1193 | |||
1194 | static unsigned int *find_db_scale(unsigned int maxval) | ||
1195 | { | ||
1196 | switch (maxval) { | ||
1197 | case 0x0f: return db_scale_4bit; | ||
1198 | case 0x1f: return db_scale_5bit; | ||
1199 | case 0x3f: return db_scale_6bit; | ||
1200 | } | ||
1201 | return NULL; | ||
1202 | } | ||
1203 | |||
1204 | static void set_tlv_db_scale(struct snd_kcontrol *kctl, unsigned int *tlv) | ||
1205 | { | ||
1206 | kctl->tlv.p = tlv; | ||
1207 | if (tlv) | ||
1208 | kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; | ||
1209 | } | ||
1210 | |||
1211 | /* | ||
1156 | * create a volume for normal stereo/mono controls | 1212 | * create a volume for normal stereo/mono controls |
1157 | */ | 1213 | */ |
1158 | static int snd_ac97_cvol_new(struct snd_card *card, char *name, int reg, unsigned int lo_max, | 1214 | static int snd_ac97_cvol_new(struct snd_card *card, char *name, int reg, unsigned int lo_max, |
@@ -1174,6 +1230,10 @@ static int snd_ac97_cvol_new(struct snd_card *card, char *name, int reg, unsigne | |||
1174 | tmp.index = ac97->num; | 1230 | tmp.index = ac97->num; |
1175 | kctl = snd_ctl_new1(&tmp, ac97); | 1231 | kctl = snd_ctl_new1(&tmp, ac97); |
1176 | } | 1232 | } |
1233 | if (reg >= AC97_PHONE && reg <= AC97_PCM) | ||
1234 | set_tlv_db_scale(kctl, db_scale_5bit_12db_max); | ||
1235 | else | ||
1236 | set_tlv_db_scale(kctl, find_db_scale(lo_max)); | ||
1177 | err = snd_ctl_add(card, kctl); | 1237 | err = snd_ctl_add(card, kctl); |
1178 | if (err < 0) | 1238 | if (err < 0) |
1179 | return err; | 1239 | return err; |
@@ -1186,7 +1246,9 @@ static int snd_ac97_cvol_new(struct snd_card *card, char *name, int reg, unsigne | |||
1186 | /* | 1246 | /* |
1187 | * create a mute-switch and a volume for normal stereo/mono controls | 1247 | * create a mute-switch and a volume for normal stereo/mono controls |
1188 | */ | 1248 | */ |
1189 | static int snd_ac97_cmix_new_stereo(struct snd_card *card, const char *pfx, int reg, int check_stereo, struct snd_ac97 *ac97) | 1249 | static int snd_ac97_cmix_new_stereo(struct snd_card *card, const char *pfx, |
1250 | int reg, int check_stereo, int check_amix, | ||
1251 | struct snd_ac97 *ac97) | ||
1190 | { | 1252 | { |
1191 | int err; | 1253 | int err; |
1192 | char name[44]; | 1254 | char name[44]; |
@@ -1197,7 +1259,9 @@ static int snd_ac97_cmix_new_stereo(struct snd_card *card, const char *pfx, int | |||
1197 | 1259 | ||
1198 | if (snd_ac97_try_bit(ac97, reg, 15)) { | 1260 | if (snd_ac97_try_bit(ac97, reg, 15)) { |
1199 | sprintf(name, "%s Switch", pfx); | 1261 | sprintf(name, "%s Switch", pfx); |
1200 | if ((err = snd_ac97_cmute_new_stereo(card, name, reg, check_stereo, ac97)) < 0) | 1262 | if ((err = snd_ac97_cmute_new_stereo(card, name, reg, |
1263 | check_stereo, check_amix, | ||
1264 | ac97)) < 0) | ||
1201 | return err; | 1265 | return err; |
1202 | } | 1266 | } |
1203 | check_volume_resolution(ac97, reg, &lo_max, &hi_max); | 1267 | check_volume_resolution(ac97, reg, &lo_max, &hi_max); |
@@ -1209,8 +1273,10 @@ static int snd_ac97_cmix_new_stereo(struct snd_card *card, const char *pfx, int | |||
1209 | return 0; | 1273 | return 0; |
1210 | } | 1274 | } |
1211 | 1275 | ||
1212 | #define snd_ac97_cmix_new(card, pfx, reg, ac97) snd_ac97_cmix_new_stereo(card, pfx, reg, 0, ac97) | 1276 | #define snd_ac97_cmix_new(card, pfx, reg, acheck, ac97) \ |
1213 | #define snd_ac97_cmute_new(card, name, reg, ac97) snd_ac97_cmute_new_stereo(card, name, reg, 0, ac97) | 1277 | snd_ac97_cmix_new_stereo(card, pfx, reg, 0, acheck, ac97) |
1278 | #define snd_ac97_cmute_new(card, name, reg, acheck, ac97) \ | ||
1279 | snd_ac97_cmute_new_stereo(card, name, reg, 0, acheck, ac97) | ||
1214 | 1280 | ||
1215 | static unsigned int snd_ac97_determine_spdif_rates(struct snd_ac97 *ac97); | 1281 | static unsigned int snd_ac97_determine_spdif_rates(struct snd_ac97 *ac97); |
1216 | 1282 | ||
@@ -1226,9 +1292,11 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) | |||
1226 | /* AD claims to remove this control from AD1887, although spec v2.2 does not allow this */ | 1292 | /* AD claims to remove this control from AD1887, although spec v2.2 does not allow this */ |
1227 | if (snd_ac97_try_volume_mix(ac97, AC97_MASTER)) { | 1293 | if (snd_ac97_try_volume_mix(ac97, AC97_MASTER)) { |
1228 | if (ac97->flags & AC97_HAS_NO_MASTER_VOL) | 1294 | if (ac97->flags & AC97_HAS_NO_MASTER_VOL) |
1229 | err = snd_ac97_cmute_new(card, "Master Playback Switch", AC97_MASTER, ac97); | 1295 | err = snd_ac97_cmute_new(card, "Master Playback Switch", |
1296 | AC97_MASTER, 0, ac97); | ||
1230 | else | 1297 | else |
1231 | err = snd_ac97_cmix_new(card, "Master Playback", AC97_MASTER, ac97); | 1298 | err = snd_ac97_cmix_new(card, "Master Playback", |
1299 | AC97_MASTER, 0, ac97); | ||
1232 | if (err < 0) | 1300 | if (err < 0) |
1233 | return err; | 1301 | return err; |
1234 | } | 1302 | } |
@@ -1245,6 +1313,7 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) | |||
1245 | snd_ac97_change_volume_params2(ac97, AC97_CENTER_LFE_MASTER, 0, &max); | 1313 | snd_ac97_change_volume_params2(ac97, AC97_CENTER_LFE_MASTER, 0, &max); |
1246 | kctl->private_value &= ~(0xff << 16); | 1314 | kctl->private_value &= ~(0xff << 16); |
1247 | kctl->private_value |= (int)max << 16; | 1315 | kctl->private_value |= (int)max << 16; |
1316 | set_tlv_db_scale(kctl, find_db_scale(max)); | ||
1248 | snd_ac97_write_cache(ac97, AC97_CENTER_LFE_MASTER, ac97->regs[AC97_CENTER_LFE_MASTER] | max); | 1317 | snd_ac97_write_cache(ac97, AC97_CENTER_LFE_MASTER, ac97->regs[AC97_CENTER_LFE_MASTER] | max); |
1249 | } | 1318 | } |
1250 | 1319 | ||
@@ -1258,6 +1327,7 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) | |||
1258 | snd_ac97_change_volume_params2(ac97, AC97_CENTER_LFE_MASTER, 8, &max); | 1327 | snd_ac97_change_volume_params2(ac97, AC97_CENTER_LFE_MASTER, 8, &max); |
1259 | kctl->private_value &= ~(0xff << 16); | 1328 | kctl->private_value &= ~(0xff << 16); |
1260 | kctl->private_value |= (int)max << 16; | 1329 | kctl->private_value |= (int)max << 16; |
1330 | set_tlv_db_scale(kctl, find_db_scale(max)); | ||
1261 | snd_ac97_write_cache(ac97, AC97_CENTER_LFE_MASTER, ac97->regs[AC97_CENTER_LFE_MASTER] | max << 8); | 1331 | snd_ac97_write_cache(ac97, AC97_CENTER_LFE_MASTER, ac97->regs[AC97_CENTER_LFE_MASTER] | max << 8); |
1262 | } | 1332 | } |
1263 | 1333 | ||
@@ -1265,19 +1335,23 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) | |||
1265 | if ((snd_ac97_try_volume_mix(ac97, AC97_SURROUND_MASTER)) | 1335 | if ((snd_ac97_try_volume_mix(ac97, AC97_SURROUND_MASTER)) |
1266 | && !(ac97->flags & AC97_AD_MULTI)) { | 1336 | && !(ac97->flags & AC97_AD_MULTI)) { |
1267 | /* Surround Master (0x38) is with stereo mutes */ | 1337 | /* Surround Master (0x38) is with stereo mutes */ |
1268 | if ((err = snd_ac97_cmix_new_stereo(card, "Surround Playback", AC97_SURROUND_MASTER, 1, ac97)) < 0) | 1338 | if ((err = snd_ac97_cmix_new_stereo(card, "Surround Playback", |
1339 | AC97_SURROUND_MASTER, 1, 0, | ||
1340 | ac97)) < 0) | ||
1269 | return err; | 1341 | return err; |
1270 | } | 1342 | } |
1271 | 1343 | ||
1272 | /* build headphone controls */ | 1344 | /* build headphone controls */ |
1273 | if (snd_ac97_try_volume_mix(ac97, AC97_HEADPHONE)) { | 1345 | if (snd_ac97_try_volume_mix(ac97, AC97_HEADPHONE)) { |
1274 | if ((err = snd_ac97_cmix_new(card, "Headphone Playback", AC97_HEADPHONE, ac97)) < 0) | 1346 | if ((err = snd_ac97_cmix_new(card, "Headphone Playback", |
1347 | AC97_HEADPHONE, 0, ac97)) < 0) | ||
1275 | return err; | 1348 | return err; |
1276 | } | 1349 | } |
1277 | 1350 | ||
1278 | /* build master mono controls */ | 1351 | /* build master mono controls */ |
1279 | if (snd_ac97_try_volume_mix(ac97, AC97_MASTER_MONO)) { | 1352 | if (snd_ac97_try_volume_mix(ac97, AC97_MASTER_MONO)) { |
1280 | if ((err = snd_ac97_cmix_new(card, "Master Mono Playback", AC97_MASTER_MONO, ac97)) < 0) | 1353 | if ((err = snd_ac97_cmix_new(card, "Master Mono Playback", |
1354 | AC97_MASTER_MONO, 0, ac97)) < 0) | ||
1281 | return err; | 1355 | return err; |
1282 | } | 1356 | } |
1283 | 1357 | ||
@@ -1301,8 +1375,9 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) | |||
1301 | ((ac97->flags & AC97_HAS_PC_BEEP) || | 1375 | ((ac97->flags & AC97_HAS_PC_BEEP) || |
1302 | snd_ac97_try_volume_mix(ac97, AC97_PC_BEEP))) { | 1376 | snd_ac97_try_volume_mix(ac97, AC97_PC_BEEP))) { |
1303 | for (idx = 0; idx < 2; idx++) | 1377 | for (idx = 0; idx < 2; idx++) |
1304 | if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_pc_beep[idx], ac97))) < 0) | 1378 | if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_pc_beep[idx], ac97))) < 0) |
1305 | return err; | 1379 | return err; |
1380 | set_tlv_db_scale(kctl, db_scale_4bit); | ||
1306 | snd_ac97_write_cache(ac97, AC97_PC_BEEP, | 1381 | snd_ac97_write_cache(ac97, AC97_PC_BEEP, |
1307 | snd_ac97_read(ac97, AC97_PC_BEEP) | 0x801e); | 1382 | snd_ac97_read(ac97, AC97_PC_BEEP) | 0x801e); |
1308 | } | 1383 | } |
@@ -1310,7 +1385,8 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) | |||
1310 | /* build Phone controls */ | 1385 | /* build Phone controls */ |
1311 | if (!(ac97->flags & AC97_HAS_NO_PHONE)) { | 1386 | if (!(ac97->flags & AC97_HAS_NO_PHONE)) { |
1312 | if (snd_ac97_try_volume_mix(ac97, AC97_PHONE)) { | 1387 | if (snd_ac97_try_volume_mix(ac97, AC97_PHONE)) { |
1313 | if ((err = snd_ac97_cmix_new(card, "Phone Playback", AC97_PHONE, ac97)) < 0) | 1388 | if ((err = snd_ac97_cmix_new(card, "Phone Playback", |
1389 | AC97_PHONE, 1, ac97)) < 0) | ||
1314 | return err; | 1390 | return err; |
1315 | } | 1391 | } |
1316 | } | 1392 | } |
@@ -1318,7 +1394,8 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) | |||
1318 | /* build MIC controls */ | 1394 | /* build MIC controls */ |
1319 | if (!(ac97->flags & AC97_HAS_NO_MIC)) { | 1395 | if (!(ac97->flags & AC97_HAS_NO_MIC)) { |
1320 | if (snd_ac97_try_volume_mix(ac97, AC97_MIC)) { | 1396 | if (snd_ac97_try_volume_mix(ac97, AC97_MIC)) { |
1321 | if ((err = snd_ac97_cmix_new(card, "Mic Playback", AC97_MIC, ac97)) < 0) | 1397 | if ((err = snd_ac97_cmix_new(card, "Mic Playback", |
1398 | AC97_MIC, 1, ac97)) < 0) | ||
1322 | return err; | 1399 | return err; |
1323 | if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_mic_boost, ac97))) < 0) | 1400 | if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_mic_boost, ac97))) < 0) |
1324 | return err; | 1401 | return err; |
@@ -1327,14 +1404,16 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) | |||
1327 | 1404 | ||
1328 | /* build Line controls */ | 1405 | /* build Line controls */ |
1329 | if (snd_ac97_try_volume_mix(ac97, AC97_LINE)) { | 1406 | if (snd_ac97_try_volume_mix(ac97, AC97_LINE)) { |
1330 | if ((err = snd_ac97_cmix_new(card, "Line Playback", AC97_LINE, ac97)) < 0) | 1407 | if ((err = snd_ac97_cmix_new(card, "Line Playback", |
1408 | AC97_LINE, 1, ac97)) < 0) | ||
1331 | return err; | 1409 | return err; |
1332 | } | 1410 | } |
1333 | 1411 | ||
1334 | /* build CD controls */ | 1412 | /* build CD controls */ |
1335 | if (!(ac97->flags & AC97_HAS_NO_CD)) { | 1413 | if (!(ac97->flags & AC97_HAS_NO_CD)) { |
1336 | if (snd_ac97_try_volume_mix(ac97, AC97_CD)) { | 1414 | if (snd_ac97_try_volume_mix(ac97, AC97_CD)) { |
1337 | if ((err = snd_ac97_cmix_new(card, "CD Playback", AC97_CD, ac97)) < 0) | 1415 | if ((err = snd_ac97_cmix_new(card, "CD Playback", |
1416 | AC97_CD, 1, ac97)) < 0) | ||
1338 | return err; | 1417 | return err; |
1339 | } | 1418 | } |
1340 | } | 1419 | } |
@@ -1342,7 +1421,8 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) | |||
1342 | /* build Video controls */ | 1421 | /* build Video controls */ |
1343 | if (!(ac97->flags & AC97_HAS_NO_VIDEO)) { | 1422 | if (!(ac97->flags & AC97_HAS_NO_VIDEO)) { |
1344 | if (snd_ac97_try_volume_mix(ac97, AC97_VIDEO)) { | 1423 | if (snd_ac97_try_volume_mix(ac97, AC97_VIDEO)) { |
1345 | if ((err = snd_ac97_cmix_new(card, "Video Playback", AC97_VIDEO, ac97)) < 0) | 1424 | if ((err = snd_ac97_cmix_new(card, "Video Playback", |
1425 | AC97_VIDEO, 1, ac97)) < 0) | ||
1346 | return err; | 1426 | return err; |
1347 | } | 1427 | } |
1348 | } | 1428 | } |
@@ -1350,7 +1430,8 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) | |||
1350 | /* build Aux controls */ | 1430 | /* build Aux controls */ |
1351 | if (!(ac97->flags & AC97_HAS_NO_AUX)) { | 1431 | if (!(ac97->flags & AC97_HAS_NO_AUX)) { |
1352 | if (snd_ac97_try_volume_mix(ac97, AC97_AUX)) { | 1432 | if (snd_ac97_try_volume_mix(ac97, AC97_AUX)) { |
1353 | if ((err = snd_ac97_cmix_new(card, "Aux Playback", AC97_AUX, ac97)) < 0) | 1433 | if ((err = snd_ac97_cmix_new(card, "Aux Playback", |
1434 | AC97_AUX, 1, ac97)) < 0) | ||
1354 | return err; | 1435 | return err; |
1355 | } | 1436 | } |
1356 | } | 1437 | } |
@@ -1363,31 +1444,38 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) | |||
1363 | else | 1444 | else |
1364 | init_val = 0x9f1f; | 1445 | init_val = 0x9f1f; |
1365 | for (idx = 0; idx < 2; idx++) | 1446 | for (idx = 0; idx < 2; idx++) |
1366 | if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_ad18xx_pcm[idx], ac97))) < 0) | 1447 | if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_pcm[idx], ac97))) < 0) |
1367 | return err; | 1448 | return err; |
1449 | set_tlv_db_scale(kctl, db_scale_5bit); | ||
1368 | ac97->spec.ad18xx.pcmreg[0] = init_val; | 1450 | ac97->spec.ad18xx.pcmreg[0] = init_val; |
1369 | if (ac97->scaps & AC97_SCAP_SURROUND_DAC) { | 1451 | if (ac97->scaps & AC97_SCAP_SURROUND_DAC) { |
1370 | for (idx = 0; idx < 2; idx++) | 1452 | for (idx = 0; idx < 2; idx++) |
1371 | if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_ad18xx_surround[idx], ac97))) < 0) | 1453 | if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_surround[idx], ac97))) < 0) |
1372 | return err; | 1454 | return err; |
1455 | set_tlv_db_scale(kctl, db_scale_5bit); | ||
1373 | ac97->spec.ad18xx.pcmreg[1] = init_val; | 1456 | ac97->spec.ad18xx.pcmreg[1] = init_val; |
1374 | } | 1457 | } |
1375 | if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC) { | 1458 | if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC) { |
1376 | for (idx = 0; idx < 2; idx++) | 1459 | for (idx = 0; idx < 2; idx++) |
1377 | if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_ad18xx_center[idx], ac97))) < 0) | 1460 | if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_center[idx], ac97))) < 0) |
1378 | return err; | 1461 | return err; |
1462 | set_tlv_db_scale(kctl, db_scale_5bit); | ||
1379 | for (idx = 0; idx < 2; idx++) | 1463 | for (idx = 0; idx < 2; idx++) |
1380 | if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_ad18xx_lfe[idx], ac97))) < 0) | 1464 | if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_lfe[idx], ac97))) < 0) |
1381 | return err; | 1465 | return err; |
1466 | set_tlv_db_scale(kctl, db_scale_5bit); | ||
1382 | ac97->spec.ad18xx.pcmreg[2] = init_val; | 1467 | ac97->spec.ad18xx.pcmreg[2] = init_val; |
1383 | } | 1468 | } |
1384 | snd_ac97_write_cache(ac97, AC97_PCM, init_val); | 1469 | snd_ac97_write_cache(ac97, AC97_PCM, init_val); |
1385 | } else { | 1470 | } else { |
1386 | if (!(ac97->flags & AC97_HAS_NO_STD_PCM)) { | 1471 | if (!(ac97->flags & AC97_HAS_NO_STD_PCM)) { |
1387 | if (ac97->flags & AC97_HAS_NO_PCM_VOL) | 1472 | if (ac97->flags & AC97_HAS_NO_PCM_VOL) |
1388 | err = snd_ac97_cmute_new(card, "PCM Playback Switch", AC97_PCM, ac97); | 1473 | err = snd_ac97_cmute_new(card, |
1474 | "PCM Playback Switch", | ||
1475 | AC97_PCM, 0, ac97); | ||
1389 | else | 1476 | else |
1390 | err = snd_ac97_cmix_new(card, "PCM Playback", AC97_PCM, ac97); | 1477 | err = snd_ac97_cmix_new(card, "PCM Playback", |
1478 | AC97_PCM, 0, ac97); | ||
1391 | if (err < 0) | 1479 | if (err < 0) |
1392 | return err; | 1480 | return err; |
1393 | } | 1481 | } |
@@ -1398,19 +1486,23 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) | |||
1398 | if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_capture_src, ac97))) < 0) | 1486 | if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_capture_src, ac97))) < 0) |
1399 | return err; | 1487 | return err; |
1400 | if (snd_ac97_try_bit(ac97, AC97_REC_GAIN, 15)) { | 1488 | if (snd_ac97_try_bit(ac97, AC97_REC_GAIN, 15)) { |
1401 | if ((err = snd_ac97_cmute_new(card, "Capture Switch", AC97_REC_GAIN, ac97)) < 0) | 1489 | err = snd_ac97_cmute_new(card, "Capture Switch", |
1490 | AC97_REC_GAIN, 0, ac97); | ||
1491 | if (err < 0) | ||
1402 | return err; | 1492 | return err; |
1403 | } | 1493 | } |
1404 | if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_capture_vol, ac97))) < 0) | 1494 | if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_control_capture_vol, ac97))) < 0) |
1405 | return err; | 1495 | return err; |
1496 | set_tlv_db_scale(kctl, db_scale_rec_gain); | ||
1406 | snd_ac97_write_cache(ac97, AC97_REC_SEL, 0x0000); | 1497 | snd_ac97_write_cache(ac97, AC97_REC_SEL, 0x0000); |
1407 | snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x0000); | 1498 | snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x0000); |
1408 | } | 1499 | } |
1409 | /* build MIC Capture controls */ | 1500 | /* build MIC Capture controls */ |
1410 | if (snd_ac97_try_volume_mix(ac97, AC97_REC_GAIN_MIC)) { | 1501 | if (snd_ac97_try_volume_mix(ac97, AC97_REC_GAIN_MIC)) { |
1411 | for (idx = 0; idx < 2; idx++) | 1502 | for (idx = 0; idx < 2; idx++) |
1412 | if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_mic_capture[idx], ac97))) < 0) | 1503 | if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_mic_capture[idx], ac97))) < 0) |
1413 | return err; | 1504 | return err; |
1505 | set_tlv_db_scale(kctl, db_scale_rec_gain); | ||
1414 | snd_ac97_write_cache(ac97, AC97_REC_GAIN_MIC, 0x0000); | 1506 | snd_ac97_write_cache(ac97, AC97_REC_GAIN_MIC, 0x0000); |
1415 | } | 1507 | } |
1416 | 1508 | ||
@@ -1481,6 +1573,12 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) | |||
1481 | } | 1573 | } |
1482 | 1574 | ||
1483 | /* build S/PDIF controls */ | 1575 | /* build S/PDIF controls */ |
1576 | |||
1577 | /* Hack for ASUS P5P800-VM, which does not indicate S/PDIF capability */ | ||
1578 | if (ac97->subsystem_vendor == 0x1043 && | ||
1579 | ac97->subsystem_device == 0x810f) | ||
1580 | ac97->ext_id |= AC97_EI_SPDIF; | ||
1581 | |||
1484 | if ((ac97->ext_id & AC97_EI_SPDIF) && !(ac97->scaps & AC97_SCAP_NO_SPDIF)) { | 1582 | if ((ac97->ext_id & AC97_EI_SPDIF) && !(ac97->scaps & AC97_SCAP_NO_SPDIF)) { |
1485 | if (ac97->build_ops->build_spdif) { | 1583 | if (ac97->build_ops->build_spdif) { |
1486 | if ((err = ac97->build_ops->build_spdif(ac97)) < 0) | 1584 | if ((err = ac97->build_ops->build_spdif(ac97)) < 0) |
@@ -1817,18 +1915,25 @@ static int snd_ac97_dev_register(struct snd_device *device) | |||
1817 | return 0; | 1915 | return 0; |
1818 | } | 1916 | } |
1819 | 1917 | ||
1820 | /* unregister ac97 codec */ | 1918 | /* disconnect ac97 codec */ |
1821 | static int snd_ac97_dev_unregister(struct snd_device *device) | 1919 | static int snd_ac97_dev_disconnect(struct snd_device *device) |
1822 | { | 1920 | { |
1823 | struct snd_ac97 *ac97 = device->device_data; | 1921 | struct snd_ac97 *ac97 = device->device_data; |
1824 | if (ac97->dev.bus) | 1922 | if (ac97->dev.bus) |
1825 | device_unregister(&ac97->dev); | 1923 | device_unregister(&ac97->dev); |
1826 | return snd_ac97_free(ac97); | 1924 | return 0; |
1827 | } | 1925 | } |
1828 | 1926 | ||
1829 | /* build_ops to do nothing */ | 1927 | /* build_ops to do nothing */ |
1830 | static struct snd_ac97_build_ops null_build_ops; | 1928 | static struct snd_ac97_build_ops null_build_ops; |
1831 | 1929 | ||
1930 | #ifdef CONFIG_SND_AC97_POWER_SAVE | ||
1931 | static void do_update_power(void *data) | ||
1932 | { | ||
1933 | update_power_regs(data); | ||
1934 | } | ||
1935 | #endif | ||
1936 | |||
1832 | /** | 1937 | /** |
1833 | * snd_ac97_mixer - create an Codec97 component | 1938 | * snd_ac97_mixer - create an Codec97 component |
1834 | * @bus: the AC97 bus which codec is attached to | 1939 | * @bus: the AC97 bus which codec is attached to |
@@ -1860,7 +1965,7 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, | |||
1860 | static struct snd_device_ops ops = { | 1965 | static struct snd_device_ops ops = { |
1861 | .dev_free = snd_ac97_dev_free, | 1966 | .dev_free = snd_ac97_dev_free, |
1862 | .dev_register = snd_ac97_dev_register, | 1967 | .dev_register = snd_ac97_dev_register, |
1863 | .dev_unregister = snd_ac97_dev_unregister, | 1968 | .dev_disconnect = snd_ac97_dev_disconnect, |
1864 | }; | 1969 | }; |
1865 | 1970 | ||
1866 | snd_assert(rac97 != NULL, return -EINVAL); | 1971 | snd_assert(rac97 != NULL, return -EINVAL); |
@@ -1883,6 +1988,10 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, | |||
1883 | bus->codec[ac97->num] = ac97; | 1988 | bus->codec[ac97->num] = ac97; |
1884 | mutex_init(&ac97->reg_mutex); | 1989 | mutex_init(&ac97->reg_mutex); |
1885 | mutex_init(&ac97->page_mutex); | 1990 | mutex_init(&ac97->page_mutex); |
1991 | #ifdef CONFIG_SND_AC97_POWER_SAVE | ||
1992 | ac97->power_workq = create_workqueue("ac97"); | ||
1993 | INIT_WORK(&ac97->power_work, do_update_power, ac97); | ||
1994 | #endif | ||
1886 | 1995 | ||
1887 | #ifdef CONFIG_PCI | 1996 | #ifdef CONFIG_PCI |
1888 | if (ac97->pci) { | 1997 | if (ac97->pci) { |
@@ -2117,15 +2226,8 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, | |||
2117 | return -ENOMEM; | 2226 | return -ENOMEM; |
2118 | } | 2227 | } |
2119 | } | 2228 | } |
2120 | /* make sure the proper powerdown bits are cleared */ | 2229 | if (ac97_is_audio(ac97)) |
2121 | if (ac97->scaps && ac97_is_audio(ac97)) { | 2230 | update_power_regs(ac97); |
2122 | reg = snd_ac97_read(ac97, AC97_EXTENDED_STATUS); | ||
2123 | if (ac97->scaps & AC97_SCAP_SURROUND_DAC) | ||
2124 | reg &= ~AC97_EA_PRJ; | ||
2125 | if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC) | ||
2126 | reg &= ~(AC97_EA_PRI | AC97_EA_PRK); | ||
2127 | snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, reg); | ||
2128 | } | ||
2129 | snd_ac97_proc_init(ac97); | 2231 | snd_ac97_proc_init(ac97); |
2130 | if ((err = snd_device_new(card, SNDRV_DEV_CODEC, ac97, &ops)) < 0) { | 2232 | if ((err = snd_device_new(card, SNDRV_DEV_CODEC, ac97, &ops)) < 0) { |
2131 | snd_ac97_free(ac97); | 2233 | snd_ac97_free(ac97); |
@@ -2153,19 +2255,152 @@ static void snd_ac97_powerdown(struct snd_ac97 *ac97) | |||
2153 | snd_ac97_write(ac97, AC97_HEADPHONE, 0x9f9f); | 2255 | snd_ac97_write(ac97, AC97_HEADPHONE, 0x9f9f); |
2154 | } | 2256 | } |
2155 | 2257 | ||
2156 | power = ac97->regs[AC97_POWERDOWN] | 0x8000; /* EAPD */ | 2258 | /* surround, CLFE, mic powerdown */ |
2157 | power |= 0x4000; /* Headphone amplifier powerdown */ | 2259 | power = ac97->regs[AC97_EXTENDED_STATUS]; |
2158 | power |= 0x0300; /* ADC & DAC powerdown */ | 2260 | if (ac97->scaps & AC97_SCAP_SURROUND_DAC) |
2159 | snd_ac97_write(ac97, AC97_POWERDOWN, power); | 2261 | power |= AC97_EA_PRJ; |
2160 | udelay(100); | 2262 | if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC) |
2161 | power |= 0x0400; /* Analog Mixer powerdown (Vref on) */ | 2263 | power |= AC97_EA_PRI | AC97_EA_PRK; |
2264 | power |= AC97_EA_PRL; | ||
2265 | snd_ac97_write(ac97, AC97_EXTENDED_STATUS, power); | ||
2266 | |||
2267 | /* powerdown external amplifier */ | ||
2268 | if (ac97->scaps & AC97_SCAP_INV_EAPD) | ||
2269 | power = ac97->regs[AC97_POWERDOWN] & ~AC97_PD_EAPD; | ||
2270 | else if (! (ac97->scaps & AC97_SCAP_EAPD_LED)) | ||
2271 | power = ac97->regs[AC97_POWERDOWN] | AC97_PD_EAPD; | ||
2272 | power |= AC97_PD_PR6; /* Headphone amplifier powerdown */ | ||
2273 | power |= AC97_PD_PR0 | AC97_PD_PR1; /* ADC & DAC powerdown */ | ||
2162 | snd_ac97_write(ac97, AC97_POWERDOWN, power); | 2274 | snd_ac97_write(ac97, AC97_POWERDOWN, power); |
2163 | udelay(100); | 2275 | udelay(100); |
2164 | #if 0 | 2276 | power |= AC97_PD_PR2 | AC97_PD_PR3; /* Analog Mixer powerdown */ |
2165 | /* FIXME: this causes click noises on some boards at resume */ | ||
2166 | power |= 0x3800; /* AC-link powerdown, internal Clk disable */ | ||
2167 | snd_ac97_write(ac97, AC97_POWERDOWN, power); | 2277 | snd_ac97_write(ac97, AC97_POWERDOWN, power); |
2278 | #ifdef CONFIG_SND_AC97_POWER_SAVE | ||
2279 | if (power_save) { | ||
2280 | udelay(100); | ||
2281 | /* AC-link powerdown, internal Clk disable */ | ||
2282 | /* FIXME: this may cause click noises on some boards */ | ||
2283 | power |= AC97_PD_PR4 | AC97_PD_PR5; | ||
2284 | snd_ac97_write(ac97, AC97_POWERDOWN, power); | ||
2285 | } | ||
2286 | #endif | ||
2287 | } | ||
2288 | |||
2289 | |||
2290 | struct ac97_power_reg { | ||
2291 | unsigned short reg; | ||
2292 | unsigned short power_reg; | ||
2293 | unsigned short mask; | ||
2294 | }; | ||
2295 | |||
2296 | enum { PWIDX_ADC, PWIDX_FRONT, PWIDX_CLFE, PWIDX_SURR, PWIDX_MIC, PWIDX_SIZE }; | ||
2297 | |||
2298 | static struct ac97_power_reg power_regs[PWIDX_SIZE] = { | ||
2299 | [PWIDX_ADC] = { AC97_PCM_LR_ADC_RATE, AC97_POWERDOWN, AC97_PD_PR0}, | ||
2300 | [PWIDX_FRONT] = { AC97_PCM_FRONT_DAC_RATE, AC97_POWERDOWN, AC97_PD_PR1}, | ||
2301 | [PWIDX_CLFE] = { AC97_PCM_LFE_DAC_RATE, AC97_EXTENDED_STATUS, | ||
2302 | AC97_EA_PRI | AC97_EA_PRK}, | ||
2303 | [PWIDX_SURR] = { AC97_PCM_SURR_DAC_RATE, AC97_EXTENDED_STATUS, | ||
2304 | AC97_EA_PRJ}, | ||
2305 | [PWIDX_MIC] = { AC97_PCM_MIC_ADC_RATE, AC97_EXTENDED_STATUS, | ||
2306 | AC97_EA_PRL}, | ||
2307 | }; | ||
2308 | |||
2309 | #ifdef CONFIG_SND_AC97_POWER_SAVE | ||
2310 | /** | ||
2311 | * snd_ac97_update_power - update the powerdown register | ||
2312 | * @ac97: the codec instance | ||
2313 | * @reg: the rate register, e.g. AC97_PCM_FRONT_DAC_RATE | ||
2314 | * @powerup: non-zero when power up the part | ||
2315 | * | ||
2316 | * Update the AC97 powerdown register bits of the given part. | ||
2317 | */ | ||
2318 | int snd_ac97_update_power(struct snd_ac97 *ac97, int reg, int powerup) | ||
2319 | { | ||
2320 | int i; | ||
2321 | |||
2322 | if (! ac97) | ||
2323 | return 0; | ||
2324 | |||
2325 | if (reg) { | ||
2326 | /* SPDIF requires DAC power, too */ | ||
2327 | if (reg == AC97_SPDIF) | ||
2328 | reg = AC97_PCM_FRONT_DAC_RATE; | ||
2329 | for (i = 0; i < PWIDX_SIZE; i++) { | ||
2330 | if (power_regs[i].reg == reg) { | ||
2331 | if (powerup) | ||
2332 | ac97->power_up |= (1 << i); | ||
2333 | else | ||
2334 | ac97->power_up &= ~(1 << i); | ||
2335 | break; | ||
2336 | } | ||
2337 | } | ||
2338 | } | ||
2339 | |||
2340 | if (! power_save) | ||
2341 | return 0; | ||
2342 | |||
2343 | if (! powerup && ac97->power_workq) | ||
2344 | /* adjust power-down bits after two seconds delay | ||
2345 | * (for avoiding loud click noises for many (OSS) apps | ||
2346 | * that open/close frequently) | ||
2347 | */ | ||
2348 | queue_delayed_work(ac97->power_workq, &ac97->power_work, HZ*2); | ||
2349 | else | ||
2350 | update_power_regs(ac97); | ||
2351 | |||
2352 | return 0; | ||
2353 | } | ||
2354 | |||
2355 | EXPORT_SYMBOL(snd_ac97_update_power); | ||
2356 | #endif /* CONFIG_SND_AC97_POWER_SAVE */ | ||
2357 | |||
2358 | static void update_power_regs(struct snd_ac97 *ac97) | ||
2359 | { | ||
2360 | unsigned int power_up, bits; | ||
2361 | int i; | ||
2362 | |||
2363 | #ifdef CONFIG_SND_AC97_POWER_SAVE | ||
2364 | if (power_save) | ||
2365 | power_up = ac97->power_up; | ||
2366 | else { | ||
2168 | #endif | 2367 | #endif |
2368 | power_up = (1 << PWIDX_FRONT) | (1 << PWIDX_ADC); | ||
2369 | power_up |= (1 << PWIDX_MIC); | ||
2370 | if (ac97->scaps & AC97_SCAP_SURROUND_DAC) | ||
2371 | power_up |= (1 << PWIDX_SURR); | ||
2372 | if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC) | ||
2373 | power_up |= (1 << PWIDX_CLFE); | ||
2374 | #ifdef CONFIG_SND_AC97_POWER_SAVE | ||
2375 | } | ||
2376 | #endif | ||
2377 | if (power_up) { | ||
2378 | if (ac97->regs[AC97_POWERDOWN] & AC97_PD_PR2) { | ||
2379 | /* needs power-up analog mix and vref */ | ||
2380 | snd_ac97_update_bits(ac97, AC97_POWERDOWN, | ||
2381 | AC97_PD_PR3, 0); | ||
2382 | msleep(1); | ||
2383 | snd_ac97_update_bits(ac97, AC97_POWERDOWN, | ||
2384 | AC97_PD_PR2, 0); | ||
2385 | } | ||
2386 | } | ||
2387 | for (i = 0; i < PWIDX_SIZE; i++) { | ||
2388 | if (power_up & (1 << i)) | ||
2389 | bits = 0; | ||
2390 | else | ||
2391 | bits = power_regs[i].mask; | ||
2392 | snd_ac97_update_bits(ac97, power_regs[i].power_reg, | ||
2393 | power_regs[i].mask, bits); | ||
2394 | } | ||
2395 | if (! power_up) { | ||
2396 | if (! (ac97->regs[AC97_POWERDOWN] & AC97_PD_PR2)) { | ||
2397 | /* power down analog mix and vref */ | ||
2398 | snd_ac97_update_bits(ac97, AC97_POWERDOWN, | ||
2399 | AC97_PD_PR2, AC97_PD_PR2); | ||
2400 | snd_ac97_update_bits(ac97, AC97_POWERDOWN, | ||
2401 | AC97_PD_PR3, AC97_PD_PR3); | ||
2402 | } | ||
2403 | } | ||
2169 | } | 2404 | } |
2170 | 2405 | ||
2171 | 2406 | ||
@@ -2484,6 +2719,7 @@ static int tune_mute_led(struct snd_ac97 *ac97) | |||
2484 | msw->put = master_mute_sw_put; | 2719 | msw->put = master_mute_sw_put; |
2485 | snd_ac97_remove_ctl(ac97, "External Amplifier", NULL); | 2720 | snd_ac97_remove_ctl(ac97, "External Amplifier", NULL); |
2486 | snd_ac97_update_bits(ac97, AC97_POWERDOWN, 0x8000, 0x8000); /* mute LED on */ | 2721 | snd_ac97_update_bits(ac97, AC97_POWERDOWN, 0x8000, 0x8000); /* mute LED on */ |
2722 | ac97->scaps |= AC97_SCAP_EAPD_LED; | ||
2487 | return 0; | 2723 | return 0; |
2488 | } | 2724 | } |
2489 | 2725 | ||
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 094cfc1f3a19..dc28b111a06d 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <sound/core.h> | 32 | #include <sound/core.h> |
33 | #include <sound/pcm.h> | 33 | #include <sound/pcm.h> |
34 | #include <sound/control.h> | 34 | #include <sound/control.h> |
35 | #include <sound/tlv.h> | ||
35 | #include <sound/ac97_codec.h> | 36 | #include <sound/ac97_codec.h> |
36 | #include "ac97_patch.h" | 37 | #include "ac97_patch.h" |
37 | #include "ac97_id.h" | 38 | #include "ac97_id.h" |
@@ -51,6 +52,20 @@ static int patch_build_controls(struct snd_ac97 * ac97, const struct snd_kcontro | |||
51 | return 0; | 52 | return 0; |
52 | } | 53 | } |
53 | 54 | ||
55 | /* replace with a new TLV */ | ||
56 | static void reset_tlv(struct snd_ac97 *ac97, const char *name, | ||
57 | unsigned int *tlv) | ||
58 | { | ||
59 | struct snd_ctl_elem_id sid; | ||
60 | struct snd_kcontrol *kctl; | ||
61 | memset(&sid, 0, sizeof(sid)); | ||
62 | strcpy(sid.name, name); | ||
63 | sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
64 | kctl = snd_ctl_find_id(ac97->bus->card, &sid); | ||
65 | if (kctl && kctl->tlv.p) | ||
66 | kctl->tlv.p = tlv; | ||
67 | } | ||
68 | |||
54 | /* set to the page, update bits and restore the page */ | 69 | /* set to the page, update bits and restore the page */ |
55 | static int ac97_update_bits_page(struct snd_ac97 *ac97, unsigned short reg, unsigned short mask, unsigned short value, unsigned short page) | 70 | static int ac97_update_bits_page(struct snd_ac97 *ac97, unsigned short reg, unsigned short mask, unsigned short value, unsigned short page) |
56 | { | 71 | { |
@@ -466,7 +481,7 @@ int patch_wolfson05(struct snd_ac97 * ac97) | |||
466 | ac97->build_ops = &patch_wolfson_wm9705_ops; | 481 | ac97->build_ops = &patch_wolfson_wm9705_ops; |
467 | #ifdef CONFIG_TOUCHSCREEN_WM9705 | 482 | #ifdef CONFIG_TOUCHSCREEN_WM9705 |
468 | /* WM9705 touchscreen uses AUX and VIDEO for touch */ | 483 | /* WM9705 touchscreen uses AUX and VIDEO for touch */ |
469 | ac97->flags |=3D AC97_HAS_NO_VIDEO | AC97_HAS_NO_AUX; | 484 | ac97->flags |= AC97_HAS_NO_VIDEO | AC97_HAS_NO_AUX; |
470 | #endif | 485 | #endif |
471 | return 0; | 486 | return 0; |
472 | } | 487 | } |
@@ -1380,6 +1395,17 @@ static void ad1888_resume(struct snd_ac97 *ac97) | |||
1380 | 1395 | ||
1381 | #endif | 1396 | #endif |
1382 | 1397 | ||
1398 | static const struct snd_ac97_res_table ad1819_restbl[] = { | ||
1399 | { AC97_PHONE, 0x9f1f }, | ||
1400 | { AC97_MIC, 0x9f1f }, | ||
1401 | { AC97_LINE, 0x9f1f }, | ||
1402 | { AC97_CD, 0x9f1f }, | ||
1403 | { AC97_VIDEO, 0x9f1f }, | ||
1404 | { AC97_AUX, 0x9f1f }, | ||
1405 | { AC97_PCM, 0x9f1f }, | ||
1406 | { } /* terminator */ | ||
1407 | }; | ||
1408 | |||
1383 | int patch_ad1819(struct snd_ac97 * ac97) | 1409 | int patch_ad1819(struct snd_ac97 * ac97) |
1384 | { | 1410 | { |
1385 | unsigned short scfg; | 1411 | unsigned short scfg; |
@@ -1387,6 +1413,7 @@ int patch_ad1819(struct snd_ac97 * ac97) | |||
1387 | // patch for Analog Devices | 1413 | // patch for Analog Devices |
1388 | scfg = snd_ac97_read(ac97, AC97_AD_SERIAL_CFG); | 1414 | scfg = snd_ac97_read(ac97, AC97_AD_SERIAL_CFG); |
1389 | snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, scfg | 0x7000); /* select all codecs */ | 1415 | snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, scfg | 0x7000); /* select all codecs */ |
1416 | ac97->res_table = ad1819_restbl; | ||
1390 | return 0; | 1417 | return 0; |
1391 | } | 1418 | } |
1392 | 1419 | ||
@@ -1522,12 +1549,16 @@ static const struct snd_kcontrol_new snd_ac97_controls_ad1885[] = { | |||
1522 | AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 8, 1, 1), /* inverted */ | 1549 | AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 8, 1, 1), /* inverted */ |
1523 | }; | 1550 | }; |
1524 | 1551 | ||
1552 | static DECLARE_TLV_DB_SCALE(db_scale_6bit_6db_max, -8850, 150, 0); | ||
1553 | |||
1525 | static int patch_ad1885_specific(struct snd_ac97 * ac97) | 1554 | static int patch_ad1885_specific(struct snd_ac97 * ac97) |
1526 | { | 1555 | { |
1527 | int err; | 1556 | int err; |
1528 | 1557 | ||
1529 | if ((err = patch_build_controls(ac97, snd_ac97_controls_ad1885, ARRAY_SIZE(snd_ac97_controls_ad1885))) < 0) | 1558 | if ((err = patch_build_controls(ac97, snd_ac97_controls_ad1885, ARRAY_SIZE(snd_ac97_controls_ad1885))) < 0) |
1530 | return err; | 1559 | return err; |
1560 | reset_tlv(ac97, "Headphone Playback Volume", | ||
1561 | db_scale_6bit_6db_max); | ||
1531 | return 0; | 1562 | return 0; |
1532 | } | 1563 | } |
1533 | 1564 | ||
@@ -1551,12 +1582,27 @@ int patch_ad1885(struct snd_ac97 * ac97) | |||
1551 | return 0; | 1582 | return 0; |
1552 | } | 1583 | } |
1553 | 1584 | ||
1585 | static int patch_ad1886_specific(struct snd_ac97 * ac97) | ||
1586 | { | ||
1587 | reset_tlv(ac97, "Headphone Playback Volume", | ||
1588 | db_scale_6bit_6db_max); | ||
1589 | return 0; | ||
1590 | } | ||
1591 | |||
1592 | static struct snd_ac97_build_ops patch_ad1886_build_ops = { | ||
1593 | .build_specific = &patch_ad1886_specific, | ||
1594 | #ifdef CONFIG_PM | ||
1595 | .resume = ad18xx_resume | ||
1596 | #endif | ||
1597 | }; | ||
1598 | |||
1554 | int patch_ad1886(struct snd_ac97 * ac97) | 1599 | int patch_ad1886(struct snd_ac97 * ac97) |
1555 | { | 1600 | { |
1556 | patch_ad1881(ac97); | 1601 | patch_ad1881(ac97); |
1557 | /* Presario700 workaround */ | 1602 | /* Presario700 workaround */ |
1558 | /* for Jack Sense/SPDIF Register misetting causing */ | 1603 | /* for Jack Sense/SPDIF Register misetting causing */ |
1559 | snd_ac97_write_cache(ac97, AC97_AD_JACK_SPDIF, 0x0010); | 1604 | snd_ac97_write_cache(ac97, AC97_AD_JACK_SPDIF, 0x0010); |
1605 | ac97->build_ops = &patch_ad1886_build_ops; | ||
1560 | return 0; | 1606 | return 0; |
1561 | } | 1607 | } |
1562 | 1608 | ||
@@ -2015,6 +2061,8 @@ static const struct snd_kcontrol_new snd_ac97_spdif_controls_alc650[] = { | |||
2015 | /* AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 13, 1, 0), */ | 2061 | /* AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 13, 1, 0), */ |
2016 | }; | 2062 | }; |
2017 | 2063 | ||
2064 | static DECLARE_TLV_DB_SCALE(db_scale_5bit_3db_max, -4350, 150, 0); | ||
2065 | |||
2018 | static int patch_alc650_specific(struct snd_ac97 * ac97) | 2066 | static int patch_alc650_specific(struct snd_ac97 * ac97) |
2019 | { | 2067 | { |
2020 | int err; | 2068 | int err; |
@@ -2025,6 +2073,9 @@ static int patch_alc650_specific(struct snd_ac97 * ac97) | |||
2025 | if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc650, ARRAY_SIZE(snd_ac97_spdif_controls_alc650))) < 0) | 2073 | if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc650, ARRAY_SIZE(snd_ac97_spdif_controls_alc650))) < 0) |
2026 | return err; | 2074 | return err; |
2027 | } | 2075 | } |
2076 | if (ac97->id != AC97_ID_ALC650F) | ||
2077 | reset_tlv(ac97, "Master Playback Volume", | ||
2078 | db_scale_5bit_3db_max); | ||
2028 | return 0; | 2079 | return 0; |
2029 | } | 2080 | } |
2030 | 2081 | ||
@@ -2208,7 +2259,8 @@ int patch_alc655(struct snd_ac97 * ac97) | |||
2208 | val &= ~(1 << 1); /* Pin 47 is spdif input pin */ | 2259 | val &= ~(1 << 1); /* Pin 47 is spdif input pin */ |
2209 | else { /* ALC655 */ | 2260 | else { /* ALC655 */ |
2210 | if (ac97->subsystem_vendor == 0x1462 && | 2261 | if (ac97->subsystem_vendor == 0x1462 && |
2211 | ac97->subsystem_device == 0x0131) /* MSI S270 laptop */ | 2262 | (ac97->subsystem_device == 0x0131 || /* MSI S270 laptop */ |
2263 | ac97->subsystem_device == 0x0161)) /* LG K1 Express */ | ||
2212 | val &= ~(1 << 1); /* Pin 47 is EAPD (for internal speaker) */ | 2264 | val &= ~(1 << 1); /* Pin 47 is EAPD (for internal speaker) */ |
2213 | else | 2265 | else |
2214 | val |= (1 << 1); /* Pin 47 is spdif input pin */ | 2266 | val |= (1 << 1); /* Pin 47 is spdif input pin */ |
@@ -2759,6 +2811,10 @@ int patch_vt1616(struct snd_ac97 * ac97) | |||
2759 | */ | 2811 | */ |
2760 | int patch_vt1617a(struct snd_ac97 * ac97) | 2812 | int patch_vt1617a(struct snd_ac97 * ac97) |
2761 | { | 2813 | { |
2814 | /* bring analog power consumption to normal, like WinXP driver | ||
2815 | * for EPIA SP | ||
2816 | */ | ||
2817 | snd_ac97_write_cache(ac97, 0x5c, 0x20); | ||
2762 | ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */ | 2818 | ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */ |
2763 | ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000; | 2819 | ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000; |
2764 | return 0; | 2820 | return 0; |
@@ -2872,3 +2928,41 @@ int patch_lm4550(struct snd_ac97 *ac97) | |||
2872 | ac97->res_table = lm4550_restbl; | 2928 | ac97->res_table = lm4550_restbl; |
2873 | return 0; | 2929 | return 0; |
2874 | } | 2930 | } |
2931 | |||
2932 | /* | ||
2933 | * UCB1400 codec (http://www.semiconductors.philips.com/acrobat_download/datasheets/UCB1400-02.pdf) | ||
2934 | */ | ||
2935 | static const struct snd_kcontrol_new snd_ac97_controls_ucb1400[] = { | ||
2936 | /* enable/disable headphone driver which allows direct connection to | ||
2937 | stereo headphone without the use of external DC blocking | ||
2938 | capacitors */ | ||
2939 | AC97_SINGLE("Headphone Driver", 0x6a, 6, 1, 0), | ||
2940 | /* Filter used to compensate the DC offset is added in the ADC to remove idle | ||
2941 | tones from the audio band. */ | ||
2942 | AC97_SINGLE("DC Filter", 0x6a, 4, 1, 0), | ||
2943 | /* Control smart-low-power mode feature. Allows automatic power down | ||
2944 | of unused blocks in the ADC analog front end and the PLL. */ | ||
2945 | AC97_SINGLE("Smart Low Power Mode", 0x6c, 4, 3, 0), | ||
2946 | }; | ||
2947 | |||
2948 | static int patch_ucb1400_specific(struct snd_ac97 * ac97) | ||
2949 | { | ||
2950 | int idx, err; | ||
2951 | for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_ucb1400); idx++) | ||
2952 | if ((err = snd_ctl_add(ac97->bus->card, snd_ctl_new1(&snd_ac97_controls_ucb1400[idx], ac97))) < 0) | ||
2953 | return err; | ||
2954 | return 0; | ||
2955 | } | ||
2956 | |||
2957 | static struct snd_ac97_build_ops patch_ucb1400_ops = { | ||
2958 | .build_specific = patch_ucb1400_specific, | ||
2959 | }; | ||
2960 | |||
2961 | int patch_ucb1400(struct snd_ac97 * ac97) | ||
2962 | { | ||
2963 | ac97->build_ops = &patch_ucb1400_ops; | ||
2964 | /* enable headphone driver and smart low power mode by default */ | ||
2965 | snd_ac97_write(ac97, 0x6a, 0x0050); | ||
2966 | snd_ac97_write(ac97, 0x6c, 0x0030); | ||
2967 | return 0; | ||
2968 | } | ||
diff --git a/sound/pci/ac97/ac97_patch.h b/sound/pci/ac97/ac97_patch.h index adcaa04586cb..741979217207 100644 --- a/sound/pci/ac97/ac97_patch.h +++ b/sound/pci/ac97/ac97_patch.h | |||
@@ -58,5 +58,6 @@ int patch_cm9780(struct snd_ac97 * ac97); | |||
58 | int patch_vt1616(struct snd_ac97 * ac97); | 58 | int patch_vt1616(struct snd_ac97 * ac97); |
59 | int patch_vt1617a(struct snd_ac97 * ac97); | 59 | int patch_vt1617a(struct snd_ac97 * ac97); |
60 | int patch_it2646(struct snd_ac97 * ac97); | 60 | int patch_it2646(struct snd_ac97 * ac97); |
61 | int patch_ucb1400(struct snd_ac97 * ac97); | ||
61 | int mpatch_si3036(struct snd_ac97 * ac97); | 62 | int mpatch_si3036(struct snd_ac97 * ac97); |
62 | int patch_lm4550(struct snd_ac97 * ac97); | 63 | int patch_lm4550(struct snd_ac97 * ac97); |
diff --git a/sound/pci/ac97/ac97_pcm.c b/sound/pci/ac97/ac97_pcm.c index f684aa2c0067..3758d07182f8 100644 --- a/sound/pci/ac97/ac97_pcm.c +++ b/sound/pci/ac97/ac97_pcm.c | |||
@@ -269,6 +269,7 @@ int snd_ac97_set_rate(struct snd_ac97 *ac97, int reg, unsigned int rate) | |||
269 | return -EINVAL; | 269 | return -EINVAL; |
270 | } | 270 | } |
271 | 271 | ||
272 | snd_ac97_update_power(ac97, reg, 1); | ||
272 | switch (reg) { | 273 | switch (reg) { |
273 | case AC97_PCM_MIC_ADC_RATE: | 274 | case AC97_PCM_MIC_ADC_RATE: |
274 | if ((ac97->regs[AC97_EXTENDED_STATUS] & AC97_EA_VRM) == 0) /* MIC VRA */ | 275 | if ((ac97->regs[AC97_EXTENDED_STATUS] & AC97_EA_VRM) == 0) /* MIC VRA */ |
@@ -606,6 +607,7 @@ int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate, | |||
606 | goto error; | 607 | goto error; |
607 | } | 608 | } |
608 | } | 609 | } |
610 | pcm->cur_dbl = r; | ||
609 | spin_unlock_irq(&pcm->bus->bus_lock); | 611 | spin_unlock_irq(&pcm->bus->bus_lock); |
610 | for (i = 3; i < 12; i++) { | 612 | for (i = 3; i < 12; i++) { |
611 | if (!(slots & (1 << i))) | 613 | if (!(slots & (1 << i))) |
@@ -651,6 +653,21 @@ int snd_ac97_pcm_close(struct ac97_pcm *pcm) | |||
651 | unsigned short slots = pcm->aslots; | 653 | unsigned short slots = pcm->aslots; |
652 | int i, cidx; | 654 | int i, cidx; |
653 | 655 | ||
656 | #ifdef CONFIG_SND_AC97_POWER_SAVE | ||
657 | int r = pcm->cur_dbl; | ||
658 | for (i = 3; i < 12; i++) { | ||
659 | if (!(slots & (1 << i))) | ||
660 | continue; | ||
661 | for (cidx = 0; cidx < 4; cidx++) { | ||
662 | if (pcm->r[r].rslots[cidx] & (1 << i)) { | ||
663 | int reg = get_slot_reg(pcm, cidx, i, r); | ||
664 | snd_ac97_update_power(pcm->r[r].codec[cidx], | ||
665 | reg, 0); | ||
666 | } | ||
667 | } | ||
668 | } | ||
669 | #endif | ||
670 | |||
654 | bus = pcm->bus; | 671 | bus = pcm->bus; |
655 | spin_lock_irq(&pcm->bus->bus_lock); | 672 | spin_lock_irq(&pcm->bus->bus_lock); |
656 | for (i = 3; i < 12; i++) { | 673 | for (i = 3; i < 12; i++) { |
@@ -660,6 +677,7 @@ int snd_ac97_pcm_close(struct ac97_pcm *pcm) | |||
660 | bus->used_slots[pcm->stream][cidx] &= ~(1 << i); | 677 | bus->used_slots[pcm->stream][cidx] &= ~(1 << i); |
661 | } | 678 | } |
662 | pcm->aslots = 0; | 679 | pcm->aslots = 0; |
680 | pcm->cur_dbl = 0; | ||
663 | spin_unlock_irq(&pcm->bus->bus_lock); | 681 | spin_unlock_irq(&pcm->bus->bus_lock); |
664 | return 0; | 682 | return 0; |
665 | } | 683 | } |
diff --git a/sound/pci/ac97/ac97_proc.c b/sound/pci/ac97/ac97_proc.c index 2118df50b9d6..a3fdd7da911c 100644 --- a/sound/pci/ac97/ac97_proc.c +++ b/sound/pci/ac97/ac97_proc.c | |||
@@ -457,14 +457,10 @@ void snd_ac97_proc_init(struct snd_ac97 * ac97) | |||
457 | 457 | ||
458 | void snd_ac97_proc_done(struct snd_ac97 * ac97) | 458 | void snd_ac97_proc_done(struct snd_ac97 * ac97) |
459 | { | 459 | { |
460 | if (ac97->proc_regs) { | 460 | snd_info_free_entry(ac97->proc_regs); |
461 | snd_info_unregister(ac97->proc_regs); | 461 | ac97->proc_regs = NULL; |
462 | ac97->proc_regs = NULL; | 462 | snd_info_free_entry(ac97->proc); |
463 | } | 463 | ac97->proc = NULL; |
464 | if (ac97->proc) { | ||
465 | snd_info_unregister(ac97->proc); | ||
466 | ac97->proc = NULL; | ||
467 | } | ||
468 | } | 464 | } |
469 | 465 | ||
470 | void snd_ac97_bus_proc_init(struct snd_ac97_bus * bus) | 466 | void snd_ac97_bus_proc_init(struct snd_ac97_bus * bus) |
@@ -485,8 +481,6 @@ void snd_ac97_bus_proc_init(struct snd_ac97_bus * bus) | |||
485 | 481 | ||
486 | void snd_ac97_bus_proc_done(struct snd_ac97_bus * bus) | 482 | void snd_ac97_bus_proc_done(struct snd_ac97_bus * bus) |
487 | { | 483 | { |
488 | if (bus->proc) { | 484 | snd_info_free_entry(bus->proc); |
489 | snd_info_unregister(bus->proc); | 485 | bus->proc = NULL; |
490 | bus->proc = NULL; | ||
491 | } | ||
492 | } | 486 | } |
diff --git a/sound/pci/ac97/ak4531_codec.c b/sound/pci/ac97/ak4531_codec.c index 94c26ec05882..c153cb79c518 100644 --- a/sound/pci/ac97/ak4531_codec.c +++ b/sound/pci/ac97/ak4531_codec.c | |||
@@ -27,6 +27,7 @@ | |||
27 | 27 | ||
28 | #include <sound/core.h> | 28 | #include <sound/core.h> |
29 | #include <sound/ak4531_codec.h> | 29 | #include <sound/ak4531_codec.h> |
30 | #include <sound/tlv.h> | ||
30 | 31 | ||
31 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 32 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); |
32 | MODULE_DESCRIPTION("Universal routines for AK4531 codec"); | 33 | MODULE_DESCRIPTION("Universal routines for AK4531 codec"); |
@@ -63,6 +64,14 @@ static void snd_ak4531_dump(struct snd_ak4531 *ak4531) | |||
63 | .info = snd_ak4531_info_single, \ | 64 | .info = snd_ak4531_info_single, \ |
64 | .get = snd_ak4531_get_single, .put = snd_ak4531_put_single, \ | 65 | .get = snd_ak4531_get_single, .put = snd_ak4531_put_single, \ |
65 | .private_value = reg | (shift << 16) | (mask << 24) | (invert << 22) } | 66 | .private_value = reg | (shift << 16) | (mask << 24) | (invert << 22) } |
67 | #define AK4531_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \ | ||
68 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
69 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ | ||
70 | .name = xname, .index = xindex, \ | ||
71 | .info = snd_ak4531_info_single, \ | ||
72 | .get = snd_ak4531_get_single, .put = snd_ak4531_put_single, \ | ||
73 | .private_value = reg | (shift << 16) | (mask << 24) | (invert << 22), \ | ||
74 | .tlv = { .p = (xtlv) } } | ||
66 | 75 | ||
67 | static int snd_ak4531_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 76 | static int snd_ak4531_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
68 | { | 77 | { |
@@ -122,6 +131,14 @@ static int snd_ak4531_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
122 | .info = snd_ak4531_info_double, \ | 131 | .info = snd_ak4531_info_double, \ |
123 | .get = snd_ak4531_get_double, .put = snd_ak4531_put_double, \ | 132 | .get = snd_ak4531_get_double, .put = snd_ak4531_put_double, \ |
124 | .private_value = left_reg | (right_reg << 8) | (left_shift << 16) | (right_shift << 19) | (mask << 24) | (invert << 22) } | 133 | .private_value = left_reg | (right_reg << 8) | (left_shift << 16) | (right_shift << 19) | (mask << 24) | (invert << 22) } |
134 | #define AK4531_DOUBLE_TLV(xname, xindex, left_reg, right_reg, left_shift, right_shift, mask, invert, xtlv) \ | ||
135 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
136 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ | ||
137 | .name = xname, .index = xindex, \ | ||
138 | .info = snd_ak4531_info_double, \ | ||
139 | .get = snd_ak4531_get_double, .put = snd_ak4531_put_double, \ | ||
140 | .private_value = left_reg | (right_reg << 8) | (left_shift << 16) | (right_shift << 19) | (mask << 24) | (invert << 22), \ | ||
141 | .tlv = { .p = (xtlv) } } | ||
125 | 142 | ||
126 | static int snd_ak4531_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 143 | static int snd_ak4531_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
127 | { | 144 | { |
@@ -250,50 +267,62 @@ static int snd_ak4531_put_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl | |||
250 | return change; | 267 | return change; |
251 | } | 268 | } |
252 | 269 | ||
270 | static DECLARE_TLV_DB_SCALE(db_scale_master, -6200, 200, 0); | ||
271 | static DECLARE_TLV_DB_SCALE(db_scale_mono, -2800, 400, 0); | ||
272 | static DECLARE_TLV_DB_SCALE(db_scale_input, -5000, 200, 0); | ||
273 | |||
253 | static struct snd_kcontrol_new snd_ak4531_controls[] = { | 274 | static struct snd_kcontrol_new snd_ak4531_controls[] = { |
254 | 275 | ||
255 | AK4531_DOUBLE("Master Playback Switch", 0, AK4531_LMASTER, AK4531_RMASTER, 7, 7, 1, 1), | 276 | AK4531_DOUBLE_TLV("Master Playback Switch", 0, |
277 | AK4531_LMASTER, AK4531_RMASTER, 7, 7, 1, 1, | ||
278 | db_scale_master), | ||
256 | AK4531_DOUBLE("Master Playback Volume", 0, AK4531_LMASTER, AK4531_RMASTER, 0, 0, 0x1f, 1), | 279 | AK4531_DOUBLE("Master Playback Volume", 0, AK4531_LMASTER, AK4531_RMASTER, 0, 0, 0x1f, 1), |
257 | 280 | ||
258 | AK4531_SINGLE("Master Mono Playback Switch", 0, AK4531_MONO_OUT, 7, 1, 1), | 281 | AK4531_SINGLE_TLV("Master Mono Playback Switch", 0, AK4531_MONO_OUT, 7, 1, 1, |
282 | db_scale_mono), | ||
259 | AK4531_SINGLE("Master Mono Playback Volume", 0, AK4531_MONO_OUT, 0, 0x07, 1), | 283 | AK4531_SINGLE("Master Mono Playback Volume", 0, AK4531_MONO_OUT, 0, 0x07, 1), |
260 | 284 | ||
261 | AK4531_DOUBLE("PCM Switch", 0, AK4531_LVOICE, AK4531_RVOICE, 7, 7, 1, 1), | 285 | AK4531_DOUBLE("PCM Switch", 0, AK4531_LVOICE, AK4531_RVOICE, 7, 7, 1, 1), |
262 | AK4531_DOUBLE("PCM Volume", 0, AK4531_LVOICE, AK4531_RVOICE, 0, 0, 0x1f, 1), | 286 | AK4531_DOUBLE_TLV("PCM Volume", 0, AK4531_LVOICE, AK4531_RVOICE, 0, 0, 0x1f, 1, |
287 | db_scale_input), | ||
263 | AK4531_DOUBLE("PCM Playback Switch", 0, AK4531_OUT_SW2, AK4531_OUT_SW2, 3, 2, 1, 0), | 288 | AK4531_DOUBLE("PCM Playback Switch", 0, AK4531_OUT_SW2, AK4531_OUT_SW2, 3, 2, 1, 0), |
264 | AK4531_DOUBLE("PCM Capture Switch", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 2, 2, 1, 0), | 289 | AK4531_DOUBLE("PCM Capture Switch", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 2, 2, 1, 0), |
265 | 290 | ||
266 | AK4531_DOUBLE("PCM Switch", 1, AK4531_LFM, AK4531_RFM, 7, 7, 1, 1), | 291 | AK4531_DOUBLE("PCM Switch", 1, AK4531_LFM, AK4531_RFM, 7, 7, 1, 1), |
267 | AK4531_DOUBLE("PCM Volume", 1, AK4531_LFM, AK4531_RFM, 0, 0, 0x1f, 1), | 292 | AK4531_DOUBLE_TLV("PCM Volume", 1, AK4531_LFM, AK4531_RFM, 0, 0, 0x1f, 1, |
293 | db_scale_input), | ||
268 | AK4531_DOUBLE("PCM Playback Switch", 1, AK4531_OUT_SW1, AK4531_OUT_SW1, 6, 5, 1, 0), | 294 | AK4531_DOUBLE("PCM Playback Switch", 1, AK4531_OUT_SW1, AK4531_OUT_SW1, 6, 5, 1, 0), |
269 | AK4531_INPUT_SW("PCM Capture Route", 1, AK4531_LIN_SW1, AK4531_RIN_SW1, 6, 5), | 295 | AK4531_INPUT_SW("PCM Capture Route", 1, AK4531_LIN_SW1, AK4531_RIN_SW1, 6, 5), |
270 | 296 | ||
271 | AK4531_DOUBLE("CD Switch", 0, AK4531_LCD, AK4531_RCD, 7, 7, 1, 1), | 297 | AK4531_DOUBLE("CD Switch", 0, AK4531_LCD, AK4531_RCD, 7, 7, 1, 1), |
272 | AK4531_DOUBLE("CD Volume", 0, AK4531_LCD, AK4531_RCD, 0, 0, 0x1f, 1), | 298 | AK4531_DOUBLE_TLV("CD Volume", 0, AK4531_LCD, AK4531_RCD, 0, 0, 0x1f, 1, |
299 | db_scale_input), | ||
273 | AK4531_DOUBLE("CD Playback Switch", 0, AK4531_OUT_SW1, AK4531_OUT_SW1, 2, 1, 1, 0), | 300 | AK4531_DOUBLE("CD Playback Switch", 0, AK4531_OUT_SW1, AK4531_OUT_SW1, 2, 1, 1, 0), |
274 | AK4531_INPUT_SW("CD Capture Route", 0, AK4531_LIN_SW1, AK4531_RIN_SW1, 2, 1), | 301 | AK4531_INPUT_SW("CD Capture Route", 0, AK4531_LIN_SW1, AK4531_RIN_SW1, 2, 1), |
275 | 302 | ||
276 | AK4531_DOUBLE("Line Switch", 0, AK4531_LLINE, AK4531_RLINE, 7, 7, 1, 1), | 303 | AK4531_DOUBLE("Line Switch", 0, AK4531_LLINE, AK4531_RLINE, 7, 7, 1, 1), |
277 | AK4531_DOUBLE("Line Volume", 0, AK4531_LLINE, AK4531_RLINE, 0, 0, 0x1f, 1), | 304 | AK4531_DOUBLE_TLV("Line Volume", 0, AK4531_LLINE, AK4531_RLINE, 0, 0, 0x1f, 1, |
305 | db_scale_input), | ||
278 | AK4531_DOUBLE("Line Playback Switch", 0, AK4531_OUT_SW1, AK4531_OUT_SW1, 4, 3, 1, 0), | 306 | AK4531_DOUBLE("Line Playback Switch", 0, AK4531_OUT_SW1, AK4531_OUT_SW1, 4, 3, 1, 0), |
279 | AK4531_INPUT_SW("Line Capture Route", 0, AK4531_LIN_SW1, AK4531_RIN_SW1, 4, 3), | 307 | AK4531_INPUT_SW("Line Capture Route", 0, AK4531_LIN_SW1, AK4531_RIN_SW1, 4, 3), |
280 | 308 | ||
281 | AK4531_DOUBLE("Aux Switch", 0, AK4531_LAUXA, AK4531_RAUXA, 7, 7, 1, 1), | 309 | AK4531_DOUBLE("Aux Switch", 0, AK4531_LAUXA, AK4531_RAUXA, 7, 7, 1, 1), |
282 | AK4531_DOUBLE("Aux Volume", 0, AK4531_LAUXA, AK4531_RAUXA, 0, 0, 0x1f, 1), | 310 | AK4531_DOUBLE_TLV("Aux Volume", 0, AK4531_LAUXA, AK4531_RAUXA, 0, 0, 0x1f, 1, |
311 | db_scale_input), | ||
283 | AK4531_DOUBLE("Aux Playback Switch", 0, AK4531_OUT_SW2, AK4531_OUT_SW2, 5, 4, 1, 0), | 312 | AK4531_DOUBLE("Aux Playback Switch", 0, AK4531_OUT_SW2, AK4531_OUT_SW2, 5, 4, 1, 0), |
284 | AK4531_INPUT_SW("Aux Capture Route", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 4, 3), | 313 | AK4531_INPUT_SW("Aux Capture Route", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 4, 3), |
285 | 314 | ||
286 | AK4531_SINGLE("Mono Switch", 0, AK4531_MONO1, 7, 1, 1), | 315 | AK4531_SINGLE("Mono Switch", 0, AK4531_MONO1, 7, 1, 1), |
287 | AK4531_SINGLE("Mono Volume", 0, AK4531_MONO1, 0, 0x1f, 1), | 316 | AK4531_SINGLE_TLV("Mono Volume", 0, AK4531_MONO1, 0, 0x1f, 1, db_scale_input), |
288 | AK4531_SINGLE("Mono Playback Switch", 0, AK4531_OUT_SW2, 0, 1, 0), | 317 | AK4531_SINGLE("Mono Playback Switch", 0, AK4531_OUT_SW2, 0, 1, 0), |
289 | AK4531_DOUBLE("Mono Capture Switch", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 0, 0, 1, 0), | 318 | AK4531_DOUBLE("Mono Capture Switch", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 0, 0, 1, 0), |
290 | 319 | ||
291 | AK4531_SINGLE("Mono Switch", 1, AK4531_MONO2, 7, 1, 1), | 320 | AK4531_SINGLE("Mono Switch", 1, AK4531_MONO2, 7, 1, 1), |
292 | AK4531_SINGLE("Mono Volume", 1, AK4531_MONO2, 0, 0x1f, 1), | 321 | AK4531_SINGLE_TLV("Mono Volume", 1, AK4531_MONO2, 0, 0x1f, 1, db_scale_input), |
293 | AK4531_SINGLE("Mono Playback Switch", 1, AK4531_OUT_SW2, 1, 1, 0), | 322 | AK4531_SINGLE("Mono Playback Switch", 1, AK4531_OUT_SW2, 1, 1, 0), |
294 | AK4531_DOUBLE("Mono Capture Switch", 1, AK4531_LIN_SW2, AK4531_RIN_SW2, 1, 1, 1, 0), | 323 | AK4531_DOUBLE("Mono Capture Switch", 1, AK4531_LIN_SW2, AK4531_RIN_SW2, 1, 1, 1, 0), |
295 | 324 | ||
296 | AK4531_SINGLE("Mic Volume", 0, AK4531_MIC, 0, 0x1f, 1), | 325 | AK4531_SINGLE_TLV("Mic Volume", 0, AK4531_MIC, 0, 0x1f, 1, db_scale_input), |
297 | AK4531_SINGLE("Mic Switch", 0, AK4531_MIC, 7, 1, 1), | 326 | AK4531_SINGLE("Mic Switch", 0, AK4531_MIC, 7, 1, 1), |
298 | AK4531_SINGLE("Mic Playback Switch", 0, AK4531_OUT_SW1, 0, 1, 0), | 327 | AK4531_SINGLE("Mic Playback Switch", 0, AK4531_OUT_SW1, 0, 1, 0), |
299 | AK4531_DOUBLE("Mic Capture Switch", 0, AK4531_LIN_SW1, AK4531_RIN_SW1, 0, 0, 1, 0), | 328 | AK4531_DOUBLE("Mic Capture Switch", 0, AK4531_LIN_SW1, AK4531_RIN_SW1, 0, 0, 1, 0), |
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c index 146eed70dce6..9855f528ea78 100644 --- a/sound/pci/ca0106/ca0106_mixer.c +++ b/sound/pci/ca0106/ca0106_mixer.c | |||
@@ -70,9 +70,13 @@ | |||
70 | #include <sound/pcm.h> | 70 | #include <sound/pcm.h> |
71 | #include <sound/ac97_codec.h> | 71 | #include <sound/ac97_codec.h> |
72 | #include <sound/info.h> | 72 | #include <sound/info.h> |
73 | #include <sound/tlv.h> | ||
73 | 74 | ||
74 | #include "ca0106.h" | 75 | #include "ca0106.h" |
75 | 76 | ||
77 | static DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale1, -5175, 25, 1); | ||
78 | static DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale2, -10350, 50, 1); | ||
79 | |||
76 | static int snd_ca0106_shared_spdif_info(struct snd_kcontrol *kcontrol, | 80 | static int snd_ca0106_shared_spdif_info(struct snd_kcontrol *kcontrol, |
77 | struct snd_ctl_elem_info *uinfo) | 81 | struct snd_ctl_elem_info *uinfo) |
78 | { | 82 | { |
@@ -469,18 +473,24 @@ static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol, | |||
469 | #define CA_VOLUME(xname,chid,reg) \ | 473 | #define CA_VOLUME(xname,chid,reg) \ |
470 | { \ | 474 | { \ |
471 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 475 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ |
476 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ | ||
477 | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ | ||
472 | .info = snd_ca0106_volume_info, \ | 478 | .info = snd_ca0106_volume_info, \ |
473 | .get = snd_ca0106_volume_get, \ | 479 | .get = snd_ca0106_volume_get, \ |
474 | .put = snd_ca0106_volume_put, \ | 480 | .put = snd_ca0106_volume_put, \ |
481 | .tlv = { .p = snd_ca0106_db_scale1 }, \ | ||
475 | .private_value = ((chid) << 8) | (reg) \ | 482 | .private_value = ((chid) << 8) | (reg) \ |
476 | } | 483 | } |
477 | 484 | ||
478 | #define I2C_VOLUME(xname,chid) \ | 485 | #define I2C_VOLUME(xname,chid) \ |
479 | { \ | 486 | { \ |
480 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 487 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ |
488 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ | ||
489 | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ | ||
481 | .info = snd_ca0106_i2c_volume_info, \ | 490 | .info = snd_ca0106_i2c_volume_info, \ |
482 | .get = snd_ca0106_i2c_volume_get, \ | 491 | .get = snd_ca0106_i2c_volume_get, \ |
483 | .put = snd_ca0106_i2c_volume_put, \ | 492 | .put = snd_ca0106_i2c_volume_put, \ |
493 | .tlv = { .p = snd_ca0106_db_scale2 }, \ | ||
484 | .private_value = chid \ | 494 | .private_value = chid \ |
485 | } | 495 | } |
486 | 496 | ||
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index 9631456ec3de..1990430a21c1 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <sound/pcm.h> | 33 | #include <sound/pcm.h> |
34 | #include <sound/rawmidi.h> | 34 | #include <sound/rawmidi.h> |
35 | #include <sound/ac97_codec.h> | 35 | #include <sound/ac97_codec.h> |
36 | #include <sound/tlv.h> | ||
36 | #include <sound/opl3.h> | 37 | #include <sound/opl3.h> |
37 | #include <sound/initval.h> | 38 | #include <sound/initval.h> |
38 | 39 | ||
@@ -1054,6 +1055,8 @@ static int snd_cs4281_put_volume(struct snd_kcontrol *kcontrol, | |||
1054 | return change; | 1055 | return change; |
1055 | } | 1056 | } |
1056 | 1057 | ||
1058 | static DECLARE_TLV_DB_SCALE(db_scale_dsp, -4650, 150, 0); | ||
1059 | |||
1057 | static struct snd_kcontrol_new snd_cs4281_fm_vol = | 1060 | static struct snd_kcontrol_new snd_cs4281_fm_vol = |
1058 | { | 1061 | { |
1059 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1062 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -1062,6 +1065,7 @@ static struct snd_kcontrol_new snd_cs4281_fm_vol = | |||
1062 | .get = snd_cs4281_get_volume, | 1065 | .get = snd_cs4281_get_volume, |
1063 | .put = snd_cs4281_put_volume, | 1066 | .put = snd_cs4281_put_volume, |
1064 | .private_value = ((BA0_FMLVC << 16) | BA0_FMRVC), | 1067 | .private_value = ((BA0_FMLVC << 16) | BA0_FMRVC), |
1068 | .tlv = { .p = db_scale_dsp }, | ||
1065 | }; | 1069 | }; |
1066 | 1070 | ||
1067 | static struct snd_kcontrol_new snd_cs4281_pcm_vol = | 1071 | static struct snd_kcontrol_new snd_cs4281_pcm_vol = |
@@ -1072,6 +1076,7 @@ static struct snd_kcontrol_new snd_cs4281_pcm_vol = | |||
1072 | .get = snd_cs4281_get_volume, | 1076 | .get = snd_cs4281_get_volume, |
1073 | .put = snd_cs4281_put_volume, | 1077 | .put = snd_cs4281_put_volume, |
1074 | .private_value = ((BA0_PPLVC << 16) | BA0_PPRVC), | 1078 | .private_value = ((BA0_PPLVC << 16) | BA0_PPRVC), |
1079 | .tlv = { .p = db_scale_dsp }, | ||
1075 | }; | 1080 | }; |
1076 | 1081 | ||
1077 | static void snd_cs4281_mixer_free_ac97_bus(struct snd_ac97_bus *bus) | 1082 | static void snd_cs4281_mixer_free_ac97_bus(struct snd_ac97_bus *bus) |
diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c index 5c9711c0265c..89c402770a1d 100644 --- a/sound/pci/cs46xx/dsp_spos.c +++ b/sound/pci/cs46xx/dsp_spos.c | |||
@@ -868,35 +868,23 @@ int cs46xx_dsp_proc_done (struct snd_cs46xx *chip) | |||
868 | struct dsp_spos_instance * ins = chip->dsp_spos_instance; | 868 | struct dsp_spos_instance * ins = chip->dsp_spos_instance; |
869 | int i; | 869 | int i; |
870 | 870 | ||
871 | if (ins->proc_sym_info_entry) { | 871 | snd_info_free_entry(ins->proc_sym_info_entry); |
872 | snd_info_unregister(ins->proc_sym_info_entry); | 872 | ins->proc_sym_info_entry = NULL; |
873 | ins->proc_sym_info_entry = NULL; | 873 | |
874 | } | 874 | snd_info_free_entry(ins->proc_modules_info_entry); |
875 | 875 | ins->proc_modules_info_entry = NULL; | |
876 | if (ins->proc_modules_info_entry) { | 876 | |
877 | snd_info_unregister(ins->proc_modules_info_entry); | 877 | snd_info_free_entry(ins->proc_parameter_dump_info_entry); |
878 | ins->proc_modules_info_entry = NULL; | 878 | ins->proc_parameter_dump_info_entry = NULL; |
879 | } | 879 | |
880 | 880 | snd_info_free_entry(ins->proc_sample_dump_info_entry); | |
881 | if (ins->proc_parameter_dump_info_entry) { | 881 | ins->proc_sample_dump_info_entry = NULL; |
882 | snd_info_unregister(ins->proc_parameter_dump_info_entry); | 882 | |
883 | ins->proc_parameter_dump_info_entry = NULL; | 883 | snd_info_free_entry(ins->proc_scb_info_entry); |
884 | } | 884 | ins->proc_scb_info_entry = NULL; |
885 | 885 | ||
886 | if (ins->proc_sample_dump_info_entry) { | 886 | snd_info_free_entry(ins->proc_task_info_entry); |
887 | snd_info_unregister(ins->proc_sample_dump_info_entry); | 887 | ins->proc_task_info_entry = NULL; |
888 | ins->proc_sample_dump_info_entry = NULL; | ||
889 | } | ||
890 | |||
891 | if (ins->proc_scb_info_entry) { | ||
892 | snd_info_unregister(ins->proc_scb_info_entry); | ||
893 | ins->proc_scb_info_entry = NULL; | ||
894 | } | ||
895 | |||
896 | if (ins->proc_task_info_entry) { | ||
897 | snd_info_unregister(ins->proc_task_info_entry); | ||
898 | ins->proc_task_info_entry = NULL; | ||
899 | } | ||
900 | 888 | ||
901 | mutex_lock(&chip->spos_mutex); | 889 | mutex_lock(&chip->spos_mutex); |
902 | for (i = 0; i < ins->nscb; ++i) { | 890 | for (i = 0; i < ins->nscb; ++i) { |
@@ -905,10 +893,8 @@ int cs46xx_dsp_proc_done (struct snd_cs46xx *chip) | |||
905 | } | 893 | } |
906 | mutex_unlock(&chip->spos_mutex); | 894 | mutex_unlock(&chip->spos_mutex); |
907 | 895 | ||
908 | if (ins->proc_dsp_dir) { | 896 | snd_info_free_entry(ins->proc_dsp_dir); |
909 | snd_info_unregister (ins->proc_dsp_dir); | 897 | ins->proc_dsp_dir = NULL; |
910 | ins->proc_dsp_dir = NULL; | ||
911 | } | ||
912 | 898 | ||
913 | return 0; | 899 | return 0; |
914 | } | 900 | } |
diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c index 232b337852ff..343f51d5311b 100644 --- a/sound/pci/cs46xx/dsp_spos_scb_lib.c +++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c | |||
@@ -233,7 +233,7 @@ void cs46xx_dsp_proc_free_scb_desc (struct dsp_scb_descriptor * scb) | |||
233 | 233 | ||
234 | snd_printdd("cs46xx_dsp_proc_free_scb_desc: freeing %s\n",scb->scb_name); | 234 | snd_printdd("cs46xx_dsp_proc_free_scb_desc: freeing %s\n",scb->scb_name); |
235 | 235 | ||
236 | snd_info_unregister(scb->proc_info); | 236 | snd_info_free_entry(scb->proc_info); |
237 | scb->proc_info = NULL; | 237 | scb->proc_info = NULL; |
238 | 238 | ||
239 | snd_assert (scb_info != NULL, return); | 239 | snd_assert (scb_info != NULL, return); |
diff --git a/sound/pci/cs5535audio/Makefile b/sound/pci/cs5535audio/Makefile index 2911a8adc1f2..ad947b4c04cc 100644 --- a/sound/pci/cs5535audio/Makefile +++ b/sound/pci/cs5535audio/Makefile | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | snd-cs5535audio-objs := cs5535audio.o cs5535audio_pcm.o | 5 | snd-cs5535audio-objs := cs5535audio.o cs5535audio_pcm.o |
6 | 6 | ||
7 | ifdef CONFIG_PM | 7 | ifeq ($(CONFIG_PM),y) |
8 | snd-cs5535audio-objs += cs5535audio_pm.o | 8 | snd-cs5535audio-objs += cs5535audio_pm.o |
9 | endif | 9 | endif |
10 | 10 | ||
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index 289bcd99c19c..493ec0816bb3 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c | |||
@@ -232,7 +232,7 @@ static int snd_emu10k1_suspend(struct pci_dev *pci, pm_message_t state) | |||
232 | return 0; | 232 | return 0; |
233 | } | 233 | } |
234 | 234 | ||
235 | int snd_emu10k1_resume(struct pci_dev *pci) | 235 | static int snd_emu10k1_resume(struct pci_dev *pci) |
236 | { | 236 | { |
237 | struct snd_card *card = pci_get_drvdata(pci); | 237 | struct snd_card *card = pci_get_drvdata(pci); |
238 | struct snd_emu10k1 *emu = card->private_data; | 238 | struct snd_emu10k1 *emu = card->private_data; |
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 79f24cdf5fbf..be65d4db8e27 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c | |||
@@ -927,6 +927,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { | |||
927 | .ca0151_chip = 1, | 927 | .ca0151_chip = 1, |
928 | .spk71 = 1, | 928 | .spk71 = 1, |
929 | .spdif_bug = 1, | 929 | .spdif_bug = 1, |
930 | .adc_1361t = 1, /* 24 bit capture instead of 16bit */ | ||
930 | .ac97_chip = 1} , | 931 | .ac97_chip = 1} , |
931 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102, | 932 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102, |
932 | .driver = "Audigy2", .name = "Audigy 2 EX [1005]", | 933 | .driver = "Audigy2", .name = "Audigy 2 EX [1005]", |
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index bda8bdf59935..da1610a571b8 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c | |||
@@ -1626,12 +1626,7 @@ static struct pci_driver driver = { | |||
1626 | // initialization of the module | 1626 | // initialization of the module |
1627 | static int __init alsa_card_emu10k1x_init(void) | 1627 | static int __init alsa_card_emu10k1x_init(void) |
1628 | { | 1628 | { |
1629 | int err; | 1629 | return pci_register_driver(&driver); |
1630 | |||
1631 | if ((err = pci_register_driver(&driver)) > 0) | ||
1632 | return err; | ||
1633 | |||
1634 | return 0; | ||
1635 | } | 1630 | } |
1636 | 1631 | ||
1637 | // clean up the module | 1632 | // clean up the module |
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index dfba00230d4d..13cd6ce89811 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/mutex.h> | 35 | #include <linux/mutex.h> |
36 | 36 | ||
37 | #include <sound/core.h> | 37 | #include <sound/core.h> |
38 | #include <sound/tlv.h> | ||
38 | #include <sound/emu10k1.h> | 39 | #include <sound/emu10k1.h> |
39 | 40 | ||
40 | #if 0 /* for testing purposes - digital out -> capture */ | 41 | #if 0 /* for testing purposes - digital out -> capture */ |
@@ -266,6 +267,7 @@ static const u32 treble_table[41][5] = { | |||
266 | { 0x37c4448b, 0xa45ef51d, 0x262f3267, 0x081e36dc, 0xfd8f5d14 } | 267 | { 0x37c4448b, 0xa45ef51d, 0x262f3267, 0x081e36dc, 0xfd8f5d14 } |
267 | }; | 268 | }; |
268 | 269 | ||
270 | /* dB gain = (float) 20 * log10( float(db_table_value) / 0x8000000 ) */ | ||
269 | static const u32 db_table[101] = { | 271 | static const u32 db_table[101] = { |
270 | 0x00000000, 0x01571f82, 0x01674b41, 0x01783a1b, 0x0189f540, | 272 | 0x00000000, 0x01571f82, 0x01674b41, 0x01783a1b, 0x0189f540, |
271 | 0x019c8651, 0x01aff763, 0x01c45306, 0x01d9a446, 0x01eff6b8, | 273 | 0x019c8651, 0x01aff763, 0x01c45306, 0x01d9a446, 0x01eff6b8, |
@@ -290,6 +292,9 @@ static const u32 db_table[101] = { | |||
290 | 0x7fffffff, | 292 | 0x7fffffff, |
291 | }; | 293 | }; |
292 | 294 | ||
295 | /* EMU10k1/EMU10k2 DSP control db gain */ | ||
296 | static DECLARE_TLV_DB_SCALE(snd_emu10k1_db_scale1, -4000, 40, 1); | ||
297 | |||
293 | static const u32 onoff_table[2] = { | 298 | static const u32 onoff_table[2] = { |
294 | 0x00000000, 0x00000001 | 299 | 0x00000000, 0x00000001 |
295 | }; | 300 | }; |
@@ -755,6 +760,11 @@ static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu, | |||
755 | knew.device = gctl->id.device; | 760 | knew.device = gctl->id.device; |
756 | knew.subdevice = gctl->id.subdevice; | 761 | knew.subdevice = gctl->id.subdevice; |
757 | knew.info = snd_emu10k1_gpr_ctl_info; | 762 | knew.info = snd_emu10k1_gpr_ctl_info; |
763 | if (gctl->tlv.p) { | ||
764 | knew.tlv.p = gctl->tlv.p; | ||
765 | knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
766 | SNDRV_CTL_ELEM_ACCESS_TLV_READ; | ||
767 | } | ||
758 | knew.get = snd_emu10k1_gpr_ctl_get; | 768 | knew.get = snd_emu10k1_gpr_ctl_get; |
759 | knew.put = snd_emu10k1_gpr_ctl_put; | 769 | knew.put = snd_emu10k1_gpr_ctl_put; |
760 | memset(nctl, 0, sizeof(*nctl)); | 770 | memset(nctl, 0, sizeof(*nctl)); |
@@ -1013,6 +1023,7 @@ snd_emu10k1_init_mono_control(struct snd_emu10k1_fx8010_control_gpr *ctl, | |||
1013 | ctl->gpr[0] = gpr + 0; ctl->value[0] = defval; | 1023 | ctl->gpr[0] = gpr + 0; ctl->value[0] = defval; |
1014 | ctl->min = 0; | 1024 | ctl->min = 0; |
1015 | ctl->max = 100; | 1025 | ctl->max = 100; |
1026 | ctl->tlv.p = snd_emu10k1_db_scale1; | ||
1016 | ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100; | 1027 | ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100; |
1017 | } | 1028 | } |
1018 | 1029 | ||
@@ -1027,6 +1038,7 @@ snd_emu10k1_init_stereo_control(struct snd_emu10k1_fx8010_control_gpr *ctl, | |||
1027 | ctl->gpr[1] = gpr + 1; ctl->value[1] = defval; | 1038 | ctl->gpr[1] = gpr + 1; ctl->value[1] = defval; |
1028 | ctl->min = 0; | 1039 | ctl->min = 0; |
1029 | ctl->max = 100; | 1040 | ctl->max = 100; |
1041 | ctl->tlv.p = snd_emu10k1_db_scale1; | ||
1030 | ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100; | 1042 | ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100; |
1031 | } | 1043 | } |
1032 | 1044 | ||
diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c index 9905651935fb..4e0f95438f47 100644 --- a/sound/pci/emu10k1/p16v.c +++ b/sound/pci/emu10k1/p16v.c | |||
@@ -100,6 +100,7 @@ | |||
100 | #include <sound/pcm.h> | 100 | #include <sound/pcm.h> |
101 | #include <sound/ac97_codec.h> | 101 | #include <sound/ac97_codec.h> |
102 | #include <sound/info.h> | 102 | #include <sound/info.h> |
103 | #include <sound/tlv.h> | ||
103 | #include <sound/emu10k1.h> | 104 | #include <sound/emu10k1.h> |
104 | #include "p16v.h" | 105 | #include "p16v.h" |
105 | 106 | ||
@@ -784,12 +785,16 @@ static int snd_p16v_capture_channel_put(struct snd_kcontrol *kcontrol, | |||
784 | } | 785 | } |
785 | return change; | 786 | return change; |
786 | } | 787 | } |
788 | static DECLARE_TLV_DB_SCALE(snd_p16v_db_scale1, -5175, 25, 1); | ||
787 | 789 | ||
788 | #define P16V_VOL(xname,xreg,xhl) { \ | 790 | #define P16V_VOL(xname,xreg,xhl) { \ |
789 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 791 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ |
792 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ | ||
793 | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ | ||
790 | .info = snd_p16v_volume_info, \ | 794 | .info = snd_p16v_volume_info, \ |
791 | .get = snd_p16v_volume_get, \ | 795 | .get = snd_p16v_volume_get, \ |
792 | .put = snd_p16v_volume_put, \ | 796 | .put = snd_p16v_volume_put, \ |
797 | .tlv = { .p = snd_p16v_db_scale1 }, \ | ||
793 | .private_value = ((xreg) | ((xhl) << 8)) \ | 798 | .private_value = ((xreg) | ((xhl) << 8)) \ |
794 | } | 799 | } |
795 | 800 | ||
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index cc0f34f68185..3ce5a4e7e31f 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c | |||
@@ -62,6 +62,7 @@ | |||
62 | #include <sound/opl3.h> | 62 | #include <sound/opl3.h> |
63 | #include <sound/mpu401.h> | 63 | #include <sound/mpu401.h> |
64 | #include <sound/initval.h> | 64 | #include <sound/initval.h> |
65 | #include <sound/tlv.h> | ||
65 | 66 | ||
66 | #include <asm/io.h> | 67 | #include <asm/io.h> |
67 | 68 | ||
@@ -1164,6 +1165,14 @@ static int snd_es1938_reg_read(struct es1938 *chip, unsigned char reg) | |||
1164 | return snd_es1938_read(chip, reg); | 1165 | return snd_es1938_read(chip, reg); |
1165 | } | 1166 | } |
1166 | 1167 | ||
1168 | #define ES1938_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \ | ||
1169 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
1170 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,\ | ||
1171 | .name = xname, .index = xindex, \ | ||
1172 | .info = snd_es1938_info_single, \ | ||
1173 | .get = snd_es1938_get_single, .put = snd_es1938_put_single, \ | ||
1174 | .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \ | ||
1175 | .tlv = { .p = xtlv } } | ||
1167 | #define ES1938_SINGLE(xname, xindex, reg, shift, mask, invert) \ | 1176 | #define ES1938_SINGLE(xname, xindex, reg, shift, mask, invert) \ |
1168 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ | 1177 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ |
1169 | .info = snd_es1938_info_single, \ | 1178 | .info = snd_es1938_info_single, \ |
@@ -1217,6 +1226,14 @@ static int snd_es1938_put_single(struct snd_kcontrol *kcontrol, | |||
1217 | return snd_es1938_reg_bits(chip, reg, mask, val) != val; | 1226 | return snd_es1938_reg_bits(chip, reg, mask, val) != val; |
1218 | } | 1227 | } |
1219 | 1228 | ||
1229 | #define ES1938_DOUBLE_TLV(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert, xtlv) \ | ||
1230 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
1231 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,\ | ||
1232 | .name = xname, .index = xindex, \ | ||
1233 | .info = snd_es1938_info_double, \ | ||
1234 | .get = snd_es1938_get_double, .put = snd_es1938_put_double, \ | ||
1235 | .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22), \ | ||
1236 | .tlv = { .p = xtlv } } | ||
1220 | #define ES1938_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \ | 1237 | #define ES1938_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \ |
1221 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ | 1238 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ |
1222 | .info = snd_es1938_info_double, \ | 1239 | .info = snd_es1938_info_double, \ |
@@ -1297,8 +1314,41 @@ static int snd_es1938_put_double(struct snd_kcontrol *kcontrol, | |||
1297 | return change; | 1314 | return change; |
1298 | } | 1315 | } |
1299 | 1316 | ||
1317 | static unsigned int db_scale_master[] = { | ||
1318 | TLV_DB_RANGE_HEAD(2), | ||
1319 | 0, 54, TLV_DB_SCALE_ITEM(-3600, 50, 1), | ||
1320 | 54, 63, TLV_DB_SCALE_ITEM(-900, 100, 0), | ||
1321 | }; | ||
1322 | |||
1323 | static unsigned int db_scale_audio1[] = { | ||
1324 | TLV_DB_RANGE_HEAD(2), | ||
1325 | 0, 8, TLV_DB_SCALE_ITEM(-3300, 300, 1), | ||
1326 | 8, 15, TLV_DB_SCALE_ITEM(-900, 150, 0), | ||
1327 | }; | ||
1328 | |||
1329 | static unsigned int db_scale_audio2[] = { | ||
1330 | TLV_DB_RANGE_HEAD(2), | ||
1331 | 0, 8, TLV_DB_SCALE_ITEM(-3450, 300, 1), | ||
1332 | 8, 15, TLV_DB_SCALE_ITEM(-1050, 150, 0), | ||
1333 | }; | ||
1334 | |||
1335 | static unsigned int db_scale_mic[] = { | ||
1336 | TLV_DB_RANGE_HEAD(2), | ||
1337 | 0, 8, TLV_DB_SCALE_ITEM(-2400, 300, 1), | ||
1338 | 8, 15, TLV_DB_SCALE_ITEM(0, 150, 0), | ||
1339 | }; | ||
1340 | |||
1341 | static unsigned int db_scale_line[] = { | ||
1342 | TLV_DB_RANGE_HEAD(2), | ||
1343 | 0, 8, TLV_DB_SCALE_ITEM(-3150, 300, 1), | ||
1344 | 8, 15, TLV_DB_SCALE_ITEM(-750, 150, 0), | ||
1345 | }; | ||
1346 | |||
1347 | static DECLARE_TLV_DB_SCALE(db_scale_capture, 0, 150, 0); | ||
1348 | |||
1300 | static struct snd_kcontrol_new snd_es1938_controls[] = { | 1349 | static struct snd_kcontrol_new snd_es1938_controls[] = { |
1301 | ES1938_DOUBLE("Master Playback Volume", 0, 0x60, 0x62, 0, 0, 63, 0), | 1350 | ES1938_DOUBLE_TLV("Master Playback Volume", 0, 0x60, 0x62, 0, 0, 63, 0, |
1351 | db_scale_master), | ||
1302 | ES1938_DOUBLE("Master Playback Switch", 0, 0x60, 0x62, 6, 6, 1, 1), | 1352 | ES1938_DOUBLE("Master Playback Switch", 0, 0x60, 0x62, 6, 6, 1, 1), |
1303 | { | 1353 | { |
1304 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1354 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -1309,19 +1359,27 @@ ES1938_DOUBLE("Master Playback Switch", 0, 0x60, 0x62, 6, 6, 1, 1), | |||
1309 | }, | 1359 | }, |
1310 | { | 1360 | { |
1311 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1361 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1362 | .access = (SNDRV_CTL_ELEM_ACCESS_READ | | ||
1363 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
1312 | .name = "Hardware Master Playback Switch", | 1364 | .name = "Hardware Master Playback Switch", |
1313 | .access = SNDRV_CTL_ELEM_ACCESS_READ, | ||
1314 | .info = snd_es1938_info_hw_switch, | 1365 | .info = snd_es1938_info_hw_switch, |
1315 | .get = snd_es1938_get_hw_switch, | 1366 | .get = snd_es1938_get_hw_switch, |
1367 | .tlv = { .p = db_scale_master }, | ||
1316 | }, | 1368 | }, |
1317 | ES1938_SINGLE("Hardware Volume Split", 0, 0x64, 7, 1, 0), | 1369 | ES1938_SINGLE("Hardware Volume Split", 0, 0x64, 7, 1, 0), |
1318 | ES1938_DOUBLE("Line Playback Volume", 0, 0x3e, 0x3e, 4, 0, 15, 0), | 1370 | ES1938_DOUBLE_TLV("Line Playback Volume", 0, 0x3e, 0x3e, 4, 0, 15, 0, |
1371 | db_scale_line), | ||
1319 | ES1938_DOUBLE("CD Playback Volume", 0, 0x38, 0x38, 4, 0, 15, 0), | 1372 | ES1938_DOUBLE("CD Playback Volume", 0, 0x38, 0x38, 4, 0, 15, 0), |
1320 | ES1938_DOUBLE("FM Playback Volume", 0, 0x36, 0x36, 4, 0, 15, 0), | 1373 | ES1938_DOUBLE_TLV("FM Playback Volume", 0, 0x36, 0x36, 4, 0, 15, 0, |
1321 | ES1938_DOUBLE("Mono Playback Volume", 0, 0x6d, 0x6d, 4, 0, 15, 0), | 1374 | db_scale_mic), |
1322 | ES1938_DOUBLE("Mic Playback Volume", 0, 0x1a, 0x1a, 4, 0, 15, 0), | 1375 | ES1938_DOUBLE_TLV("Mono Playback Volume", 0, 0x6d, 0x6d, 4, 0, 15, 0, |
1323 | ES1938_DOUBLE("Aux Playback Volume", 0, 0x3a, 0x3a, 4, 0, 15, 0), | 1376 | db_scale_line), |
1324 | ES1938_DOUBLE("Capture Volume", 0, 0xb4, 0xb4, 4, 0, 15, 0), | 1377 | ES1938_DOUBLE_TLV("Mic Playback Volume", 0, 0x1a, 0x1a, 4, 0, 15, 0, |
1378 | db_scale_mic), | ||
1379 | ES1938_DOUBLE_TLV("Aux Playback Volume", 0, 0x3a, 0x3a, 4, 0, 15, 0, | ||
1380 | db_scale_line), | ||
1381 | ES1938_DOUBLE_TLV("Capture Volume", 0, 0xb4, 0xb4, 4, 0, 15, 0, | ||
1382 | db_scale_capture), | ||
1325 | ES1938_SINGLE("PC Speaker Volume", 0, 0x3c, 0, 7, 0), | 1383 | ES1938_SINGLE("PC Speaker Volume", 0, 0x3c, 0, 7, 0), |
1326 | ES1938_SINGLE("Record Monitor", 0, 0xa8, 3, 1, 0), | 1384 | ES1938_SINGLE("Record Monitor", 0, 0xa8, 3, 1, 0), |
1327 | ES1938_SINGLE("Capture Switch", 0, 0x1c, 4, 1, 1), | 1385 | ES1938_SINGLE("Capture Switch", 0, 0x1c, 4, 1, 1), |
@@ -1332,16 +1390,26 @@ ES1938_SINGLE("Capture Switch", 0, 0x1c, 4, 1, 1), | |||
1332 | .get = snd_es1938_get_mux, | 1390 | .get = snd_es1938_get_mux, |
1333 | .put = snd_es1938_put_mux, | 1391 | .put = snd_es1938_put_mux, |
1334 | }, | 1392 | }, |
1335 | ES1938_DOUBLE("Mono Input Playback Volume", 0, 0x6d, 0x6d, 4, 0, 15, 0), | 1393 | ES1938_DOUBLE_TLV("Mono Input Playback Volume", 0, 0x6d, 0x6d, 4, 0, 15, 0, |
1336 | ES1938_DOUBLE("PCM Capture Volume", 0, 0x69, 0x69, 4, 0, 15, 0), | 1394 | db_scale_line), |
1337 | ES1938_DOUBLE("Mic Capture Volume", 0, 0x68, 0x68, 4, 0, 15, 0), | 1395 | ES1938_DOUBLE_TLV("PCM Capture Volume", 0, 0x69, 0x69, 4, 0, 15, 0, |
1338 | ES1938_DOUBLE("Line Capture Volume", 0, 0x6e, 0x6e, 4, 0, 15, 0), | 1396 | db_scale_audio2), |
1339 | ES1938_DOUBLE("FM Capture Volume", 0, 0x6b, 0x6b, 4, 0, 15, 0), | 1397 | ES1938_DOUBLE_TLV("Mic Capture Volume", 0, 0x68, 0x68, 4, 0, 15, 0, |
1340 | ES1938_DOUBLE("Mono Capture Volume", 0, 0x6f, 0x6f, 4, 0, 15, 0), | 1398 | db_scale_mic), |
1341 | ES1938_DOUBLE("CD Capture Volume", 0, 0x6a, 0x6a, 4, 0, 15, 0), | 1399 | ES1938_DOUBLE_TLV("Line Capture Volume", 0, 0x6e, 0x6e, 4, 0, 15, 0, |
1342 | ES1938_DOUBLE("Aux Capture Volume", 0, 0x6c, 0x6c, 4, 0, 15, 0), | 1400 | db_scale_line), |
1343 | ES1938_DOUBLE("PCM Playback Volume", 0, 0x7c, 0x7c, 4, 0, 15, 0), | 1401 | ES1938_DOUBLE_TLV("FM Capture Volume", 0, 0x6b, 0x6b, 4, 0, 15, 0, |
1344 | ES1938_DOUBLE("PCM Playback Volume", 1, 0x14, 0x14, 4, 0, 15, 0), | 1402 | db_scale_mic), |
1403 | ES1938_DOUBLE_TLV("Mono Capture Volume", 0, 0x6f, 0x6f, 4, 0, 15, 0, | ||
1404 | db_scale_line), | ||
1405 | ES1938_DOUBLE_TLV("CD Capture Volume", 0, 0x6a, 0x6a, 4, 0, 15, 0, | ||
1406 | db_scale_line), | ||
1407 | ES1938_DOUBLE_TLV("Aux Capture Volume", 0, 0x6c, 0x6c, 4, 0, 15, 0, | ||
1408 | db_scale_line), | ||
1409 | ES1938_DOUBLE_TLV("PCM Playback Volume", 0, 0x7c, 0x7c, 4, 0, 15, 0, | ||
1410 | db_scale_audio2), | ||
1411 | ES1938_DOUBLE_TLV("PCM Playback Volume", 1, 0x14, 0x14, 4, 0, 15, 0, | ||
1412 | db_scale_audio1), | ||
1345 | ES1938_SINGLE("3D Control - Level", 0, 0x52, 0, 63, 0), | 1413 | ES1938_SINGLE("3D Control - Level", 0, 0x52, 0, 63, 0), |
1346 | { | 1414 | { |
1347 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1415 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 3c5ab7c2e72d..f3c40385c87d 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c | |||
@@ -1905,7 +1905,7 @@ static void es1968_update_hw_volume(unsigned long private_data) | |||
1905 | /* Figure out which volume control button was pushed, | 1905 | /* Figure out which volume control button was pushed, |
1906 | based on differences from the default register | 1906 | based on differences from the default register |
1907 | values. */ | 1907 | values. */ |
1908 | x = inb(chip->io_port + 0x1c); | 1908 | x = inb(chip->io_port + 0x1c) & 0xee; |
1909 | /* Reset the volume control registers. */ | 1909 | /* Reset the volume control registers. */ |
1910 | outb(0x88, chip->io_port + 0x1c); | 1910 | outb(0x88, chip->io_port + 0x1c); |
1911 | outb(0x88, chip->io_port + 0x1d); | 1911 | outb(0x88, chip->io_port + 0x1d); |
@@ -1921,7 +1921,8 @@ static void es1968_update_hw_volume(unsigned long private_data) | |||
1921 | /* FIXME: we can't call snd_ac97_* functions since here is in tasklet. */ | 1921 | /* FIXME: we can't call snd_ac97_* functions since here is in tasklet. */ |
1922 | spin_lock_irqsave(&chip->ac97_lock, flags); | 1922 | spin_lock_irqsave(&chip->ac97_lock, flags); |
1923 | val = chip->ac97->regs[AC97_MASTER]; | 1923 | val = chip->ac97->regs[AC97_MASTER]; |
1924 | if (x & 1) { | 1924 | switch (x) { |
1925 | case 0x88: | ||
1925 | /* mute */ | 1926 | /* mute */ |
1926 | val ^= 0x8000; | 1927 | val ^= 0x8000; |
1927 | chip->ac97->regs[AC97_MASTER] = val; | 1928 | chip->ac97->regs[AC97_MASTER] = val; |
@@ -1929,26 +1930,31 @@ static void es1968_update_hw_volume(unsigned long private_data) | |||
1929 | outb(AC97_MASTER, chip->io_port + ESM_AC97_INDEX); | 1930 | outb(AC97_MASTER, chip->io_port + ESM_AC97_INDEX); |
1930 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | 1931 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, |
1931 | &chip->master_switch->id); | 1932 | &chip->master_switch->id); |
1932 | } else { | 1933 | break; |
1933 | val &= 0x7fff; | 1934 | case 0xaa: |
1934 | if (((x>>1) & 7) > 4) { | 1935 | /* volume up */ |
1935 | /* volume up */ | 1936 | if ((val & 0x7f) > 0) |
1936 | if ((val & 0xff) > 0) | 1937 | val--; |
1937 | val--; | 1938 | if ((val & 0x7f00) > 0) |
1938 | if ((val & 0xff00) > 0) | 1939 | val -= 0x0100; |
1939 | val -= 0x0100; | 1940 | chip->ac97->regs[AC97_MASTER] = val; |
1940 | } else { | 1941 | outw(val, chip->io_port + ESM_AC97_DATA); |
1941 | /* volume down */ | 1942 | outb(AC97_MASTER, chip->io_port + ESM_AC97_INDEX); |
1942 | if ((val & 0xff) < 0x1f) | 1943 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, |
1943 | val++; | 1944 | &chip->master_volume->id); |
1944 | if ((val & 0xff00) < 0x1f00) | 1945 | break; |
1945 | val += 0x0100; | 1946 | case 0x66: |
1946 | } | 1947 | /* volume down */ |
1948 | if ((val & 0x7f) < 0x1f) | ||
1949 | val++; | ||
1950 | if ((val & 0x7f00) < 0x1f00) | ||
1951 | val += 0x0100; | ||
1947 | chip->ac97->regs[AC97_MASTER] = val; | 1952 | chip->ac97->regs[AC97_MASTER] = val; |
1948 | outw(val, chip->io_port + ESM_AC97_DATA); | 1953 | outw(val, chip->io_port + ESM_AC97_DATA); |
1949 | outb(AC97_MASTER, chip->io_port + ESM_AC97_INDEX); | 1954 | outb(AC97_MASTER, chip->io_port + ESM_AC97_INDEX); |
1950 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | 1955 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, |
1951 | &chip->master_volume->id); | 1956 | &chip->master_volume->id); |
1957 | break; | ||
1952 | } | 1958 | } |
1953 | spin_unlock_irqrestore(&chip->ac97_lock, flags); | 1959 | spin_unlock_irqrestore(&chip->ac97_lock, flags); |
1954 | } | 1960 | } |
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index 13868c985126..bdfda1997d5b 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * The driver for the ForteMedia FM801 based soundcards | 2 | * The driver for the ForteMedia FM801 based soundcards |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> |
4 | * | 4 | * |
5 | * Support FM only card by Andy Shevchenko <andy@smile.org.ua> | ||
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
@@ -28,6 +29,7 @@ | |||
28 | #include <linux/moduleparam.h> | 29 | #include <linux/moduleparam.h> |
29 | #include <sound/core.h> | 30 | #include <sound/core.h> |
30 | #include <sound/pcm.h> | 31 | #include <sound/pcm.h> |
32 | #include <sound/tlv.h> | ||
31 | #include <sound/ac97_codec.h> | 33 | #include <sound/ac97_codec.h> |
32 | #include <sound/mpu401.h> | 34 | #include <sound/mpu401.h> |
33 | #include <sound/opl3.h> | 35 | #include <sound/opl3.h> |
@@ -54,6 +56,7 @@ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card * | |||
54 | * 1 = MediaForte 256-PCS | 56 | * 1 = MediaForte 256-PCS |
55 | * 2 = MediaForte 256-PCPR | 57 | * 2 = MediaForte 256-PCPR |
56 | * 3 = MediaForte 64-PCR | 58 | * 3 = MediaForte 64-PCR |
59 | * 16 = setup tuner only (this is additional bit), i.e. SF-64-PCR FM card | ||
57 | * High 16-bits are video (radio) device number + 1 | 60 | * High 16-bits are video (radio) device number + 1 |
58 | */ | 61 | */ |
59 | static int tea575x_tuner[SNDRV_CARDS]; | 62 | static int tea575x_tuner[SNDRV_CARDS]; |
@@ -158,6 +161,7 @@ struct fm801 { | |||
158 | unsigned int multichannel: 1, /* multichannel support */ | 161 | unsigned int multichannel: 1, /* multichannel support */ |
159 | secondary: 1; /* secondary codec */ | 162 | secondary: 1; /* secondary codec */ |
160 | unsigned char secondary_addr; /* address of the secondary codec */ | 163 | unsigned char secondary_addr; /* address of the secondary codec */ |
164 | unsigned int tea575x_tuner; /* tuner flags */ | ||
161 | 165 | ||
162 | unsigned short ply_ctrl; /* playback control */ | 166 | unsigned short ply_ctrl; /* playback control */ |
163 | unsigned short cap_ctrl; /* capture control */ | 167 | unsigned short cap_ctrl; /* capture control */ |
@@ -318,10 +322,8 @@ static unsigned int channels[] = { | |||
318 | 2, 4, 6 | 322 | 2, 4, 6 |
319 | }; | 323 | }; |
320 | 324 | ||
321 | #define CHANNELS sizeof(channels) / sizeof(channels[0]) | ||
322 | |||
323 | static struct snd_pcm_hw_constraint_list hw_constraints_channels = { | 325 | static struct snd_pcm_hw_constraint_list hw_constraints_channels = { |
324 | .count = CHANNELS, | 326 | .count = ARRAY_SIZE(channels), |
325 | .list = channels, | 327 | .list = channels, |
326 | .mask = 0, | 328 | .mask = 0, |
327 | }; | 329 | }; |
@@ -1052,6 +1054,13 @@ static int snd_fm801_put_single(struct snd_kcontrol *kcontrol, | |||
1052 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_fm801_info_double, \ | 1054 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_fm801_info_double, \ |
1053 | .get = snd_fm801_get_double, .put = snd_fm801_put_double, \ | 1055 | .get = snd_fm801_get_double, .put = snd_fm801_put_double, \ |
1054 | .private_value = reg | (shift_left << 8) | (shift_right << 12) | (mask << 16) | (invert << 24) } | 1056 | .private_value = reg | (shift_left << 8) | (shift_right << 12) | (mask << 16) | (invert << 24) } |
1057 | #define FM801_DOUBLE_TLV(xname, reg, shift_left, shift_right, mask, invert, xtlv) \ | ||
1058 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
1059 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ | ||
1060 | .name = xname, .info = snd_fm801_info_double, \ | ||
1061 | .get = snd_fm801_get_double, .put = snd_fm801_put_double, \ | ||
1062 | .private_value = reg | (shift_left << 8) | (shift_right << 12) | (mask << 16) | (invert << 24), \ | ||
1063 | .tlv = { .p = (xtlv) } } | ||
1055 | 1064 | ||
1056 | static int snd_fm801_info_double(struct snd_kcontrol *kcontrol, | 1065 | static int snd_fm801_info_double(struct snd_kcontrol *kcontrol, |
1057 | struct snd_ctl_elem_info *uinfo) | 1066 | struct snd_ctl_elem_info *uinfo) |
@@ -1148,14 +1157,19 @@ static int snd_fm801_put_mux(struct snd_kcontrol *kcontrol, | |||
1148 | return snd_fm801_update_bits(chip, FM801_REC_SRC, 7, val); | 1157 | return snd_fm801_update_bits(chip, FM801_REC_SRC, 7, val); |
1149 | } | 1158 | } |
1150 | 1159 | ||
1160 | static DECLARE_TLV_DB_SCALE(db_scale_dsp, -3450, 150, 0); | ||
1161 | |||
1151 | #define FM801_CONTROLS ARRAY_SIZE(snd_fm801_controls) | 1162 | #define FM801_CONTROLS ARRAY_SIZE(snd_fm801_controls) |
1152 | 1163 | ||
1153 | static struct snd_kcontrol_new snd_fm801_controls[] __devinitdata = { | 1164 | static struct snd_kcontrol_new snd_fm801_controls[] __devinitdata = { |
1154 | FM801_DOUBLE("Wave Playback Volume", FM801_PCM_VOL, 0, 8, 31, 1), | 1165 | FM801_DOUBLE_TLV("Wave Playback Volume", FM801_PCM_VOL, 0, 8, 31, 1, |
1166 | db_scale_dsp), | ||
1155 | FM801_SINGLE("Wave Playback Switch", FM801_PCM_VOL, 15, 1, 1), | 1167 | FM801_SINGLE("Wave Playback Switch", FM801_PCM_VOL, 15, 1, 1), |
1156 | FM801_DOUBLE("I2S Playback Volume", FM801_I2S_VOL, 0, 8, 31, 1), | 1168 | FM801_DOUBLE_TLV("I2S Playback Volume", FM801_I2S_VOL, 0, 8, 31, 1, |
1169 | db_scale_dsp), | ||
1157 | FM801_SINGLE("I2S Playback Switch", FM801_I2S_VOL, 15, 1, 1), | 1170 | FM801_SINGLE("I2S Playback Switch", FM801_I2S_VOL, 15, 1, 1), |
1158 | FM801_DOUBLE("FM Playback Volume", FM801_FM_VOL, 0, 8, 31, 1), | 1171 | FM801_DOUBLE_TLV("FM Playback Volume", FM801_FM_VOL, 0, 8, 31, 1, |
1172 | db_scale_dsp), | ||
1159 | FM801_SINGLE("FM Playback Switch", FM801_FM_VOL, 15, 1, 1), | 1173 | FM801_SINGLE("FM Playback Switch", FM801_FM_VOL, 15, 1, 1), |
1160 | { | 1174 | { |
1161 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1175 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -1253,6 +1267,9 @@ static int snd_fm801_chip_init(struct fm801 *chip, int resume) | |||
1253 | int id; | 1267 | int id; |
1254 | unsigned short cmdw; | 1268 | unsigned short cmdw; |
1255 | 1269 | ||
1270 | if (chip->tea575x_tuner & 0x0010) | ||
1271 | goto __ac97_ok; | ||
1272 | |||
1256 | /* codec cold reset + AC'97 warm reset */ | 1273 | /* codec cold reset + AC'97 warm reset */ |
1257 | outw((1<<5) | (1<<6), FM801_REG(chip, CODEC_CTRL)); | 1274 | outw((1<<5) | (1<<6), FM801_REG(chip, CODEC_CTRL)); |
1258 | inw(FM801_REG(chip, CODEC_CTRL)); /* flush posting data */ | 1275 | inw(FM801_REG(chip, CODEC_CTRL)); /* flush posting data */ |
@@ -1290,6 +1307,8 @@ static int snd_fm801_chip_init(struct fm801 *chip, int resume) | |||
1290 | wait_for_codec(chip, 0, AC97_VENDOR_ID1, msecs_to_jiffies(750)); | 1307 | wait_for_codec(chip, 0, AC97_VENDOR_ID1, msecs_to_jiffies(750)); |
1291 | } | 1308 | } |
1292 | 1309 | ||
1310 | __ac97_ok: | ||
1311 | |||
1293 | /* init volume */ | 1312 | /* init volume */ |
1294 | outw(0x0808, FM801_REG(chip, PCM_VOL)); | 1313 | outw(0x0808, FM801_REG(chip, PCM_VOL)); |
1295 | outw(0x9f1f, FM801_REG(chip, FM_VOL)); | 1314 | outw(0x9f1f, FM801_REG(chip, FM_VOL)); |
@@ -1298,9 +1317,12 @@ static int snd_fm801_chip_init(struct fm801 *chip, int resume) | |||
1298 | /* I2S control - I2S mode */ | 1317 | /* I2S control - I2S mode */ |
1299 | outw(0x0003, FM801_REG(chip, I2S_MODE)); | 1318 | outw(0x0003, FM801_REG(chip, I2S_MODE)); |
1300 | 1319 | ||
1301 | /* interrupt setup - unmask MPU, PLAYBACK & CAPTURE */ | 1320 | /* interrupt setup */ |
1302 | cmdw = inw(FM801_REG(chip, IRQ_MASK)); | 1321 | cmdw = inw(FM801_REG(chip, IRQ_MASK)); |
1303 | cmdw &= ~0x0083; | 1322 | if (chip->irq < 0) |
1323 | cmdw |= 0x00c3; /* mask everything, no PCM nor MPU */ | ||
1324 | else | ||
1325 | cmdw &= ~0x0083; /* unmask MPU, PLAYBACK & CAPTURE */ | ||
1304 | outw(cmdw, FM801_REG(chip, IRQ_MASK)); | 1326 | outw(cmdw, FM801_REG(chip, IRQ_MASK)); |
1305 | 1327 | ||
1306 | /* interrupt clear */ | 1328 | /* interrupt clear */ |
@@ -1365,20 +1387,23 @@ static int __devinit snd_fm801_create(struct snd_card *card, | |||
1365 | chip->card = card; | 1387 | chip->card = card; |
1366 | chip->pci = pci; | 1388 | chip->pci = pci; |
1367 | chip->irq = -1; | 1389 | chip->irq = -1; |
1390 | chip->tea575x_tuner = tea575x_tuner; | ||
1368 | if ((err = pci_request_regions(pci, "FM801")) < 0) { | 1391 | if ((err = pci_request_regions(pci, "FM801")) < 0) { |
1369 | kfree(chip); | 1392 | kfree(chip); |
1370 | pci_disable_device(pci); | 1393 | pci_disable_device(pci); |
1371 | return err; | 1394 | return err; |
1372 | } | 1395 | } |
1373 | chip->port = pci_resource_start(pci, 0); | 1396 | chip->port = pci_resource_start(pci, 0); |
1374 | if (request_irq(pci->irq, snd_fm801_interrupt, IRQF_DISABLED|IRQF_SHARED, | 1397 | if ((tea575x_tuner & 0x0010) == 0) { |
1375 | "FM801", chip)) { | 1398 | if (request_irq(pci->irq, snd_fm801_interrupt, IRQF_DISABLED|IRQF_SHARED, |
1376 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", chip->irq); | 1399 | "FM801", chip)) { |
1377 | snd_fm801_free(chip); | 1400 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", chip->irq); |
1378 | return -EBUSY; | 1401 | snd_fm801_free(chip); |
1402 | return -EBUSY; | ||
1403 | } | ||
1404 | chip->irq = pci->irq; | ||
1405 | pci_set_master(pci); | ||
1379 | } | 1406 | } |
1380 | chip->irq = pci->irq; | ||
1381 | pci_set_master(pci); | ||
1382 | 1407 | ||
1383 | pci_read_config_byte(pci, PCI_REVISION_ID, &rev); | 1408 | pci_read_config_byte(pci, PCI_REVISION_ID, &rev); |
1384 | if (rev >= 0xb1) /* FM801-AU */ | 1409 | if (rev >= 0xb1) /* FM801-AU */ |
@@ -1394,12 +1419,12 @@ static int __devinit snd_fm801_create(struct snd_card *card, | |||
1394 | snd_card_set_dev(card, &pci->dev); | 1419 | snd_card_set_dev(card, &pci->dev); |
1395 | 1420 | ||
1396 | #ifdef TEA575X_RADIO | 1421 | #ifdef TEA575X_RADIO |
1397 | if (tea575x_tuner > 0 && (tea575x_tuner & 0xffff) < 4) { | 1422 | if (tea575x_tuner > 0 && (tea575x_tuner & 0x000f) < 4) { |
1398 | chip->tea.dev_nr = tea575x_tuner >> 16; | 1423 | chip->tea.dev_nr = tea575x_tuner >> 16; |
1399 | chip->tea.card = card; | 1424 | chip->tea.card = card; |
1400 | chip->tea.freq_fixup = 10700; | 1425 | chip->tea.freq_fixup = 10700; |
1401 | chip->tea.private_data = chip; | 1426 | chip->tea.private_data = chip; |
1402 | chip->tea.ops = &snd_fm801_tea_ops[(tea575x_tuner & 0xffff) - 1]; | 1427 | chip->tea.ops = &snd_fm801_tea_ops[(tea575x_tuner & 0x000f) - 1]; |
1403 | snd_tea575x_init(&chip->tea); | 1428 | snd_tea575x_init(&chip->tea); |
1404 | } | 1429 | } |
1405 | #endif | 1430 | #endif |
@@ -1439,6 +1464,9 @@ static int __devinit snd_card_fm801_probe(struct pci_dev *pci, | |||
1439 | sprintf(card->longname, "%s at 0x%lx, irq %i", | 1464 | sprintf(card->longname, "%s at 0x%lx, irq %i", |
1440 | card->shortname, chip->port, chip->irq); | 1465 | card->shortname, chip->port, chip->irq); |
1441 | 1466 | ||
1467 | if (tea575x_tuner[dev] & 0x0010) | ||
1468 | goto __fm801_tuner_only; | ||
1469 | |||
1442 | if ((err = snd_fm801_pcm(chip, 0, NULL)) < 0) { | 1470 | if ((err = snd_fm801_pcm(chip, 0, NULL)) < 0) { |
1443 | snd_card_free(card); | 1471 | snd_card_free(card); |
1444 | return err; | 1472 | return err; |
@@ -1465,6 +1493,7 @@ static int __devinit snd_card_fm801_probe(struct pci_dev *pci, | |||
1465 | return err; | 1493 | return err; |
1466 | } | 1494 | } |
1467 | 1495 | ||
1496 | __fm801_tuner_only: | ||
1468 | if ((err = snd_card_register(card)) < 0) { | 1497 | if ((err = snd_card_register(card)) < 0) { |
1469 | snd_card_free(card); | 1498 | snd_card_free(card); |
1470 | return err; | 1499 | return err; |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 23201f3eeb12..9c3d7ac08068 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <sound/core.h> | 29 | #include <sound/core.h> |
30 | #include "hda_codec.h" | 30 | #include "hda_codec.h" |
31 | #include <sound/asoundef.h> | 31 | #include <sound/asoundef.h> |
32 | #include <sound/tlv.h> | ||
32 | #include <sound/initval.h> | 33 | #include <sound/initval.h> |
33 | #include "hda_local.h" | 34 | #include "hda_local.h" |
34 | 35 | ||
@@ -50,8 +51,10 @@ struct hda_vendor_id { | |||
50 | /* codec vendor labels */ | 51 | /* codec vendor labels */ |
51 | static struct hda_vendor_id hda_vendor_ids[] = { | 52 | static struct hda_vendor_id hda_vendor_ids[] = { |
52 | { 0x10ec, "Realtek" }, | 53 | { 0x10ec, "Realtek" }, |
54 | { 0x1057, "Motorola" }, | ||
53 | { 0x11d4, "Analog Devices" }, | 55 | { 0x11d4, "Analog Devices" }, |
54 | { 0x13f6, "C-Media" }, | 56 | { 0x13f6, "C-Media" }, |
57 | { 0x14f1, "Conexant" }, | ||
55 | { 0x434d, "C-Media" }, | 58 | { 0x434d, "C-Media" }, |
56 | { 0x8384, "SigmaTel" }, | 59 | { 0x8384, "SigmaTel" }, |
57 | {} /* terminator */ | 60 | {} /* terminator */ |
@@ -841,6 +844,31 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
841 | return change; | 844 | return change; |
842 | } | 845 | } |
843 | 846 | ||
847 | int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, | ||
848 | unsigned int size, unsigned int __user *_tlv) | ||
849 | { | ||
850 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
851 | hda_nid_t nid = get_amp_nid(kcontrol); | ||
852 | int dir = get_amp_direction(kcontrol); | ||
853 | u32 caps, val1, val2; | ||
854 | |||
855 | if (size < 4 * sizeof(unsigned int)) | ||
856 | return -ENOMEM; | ||
857 | caps = query_amp_caps(codec, nid, dir); | ||
858 | val2 = (((caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT) + 1) * 25; | ||
859 | val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT); | ||
860 | val1 = ((int)val1) * ((int)val2); | ||
861 | if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv)) | ||
862 | return -EFAULT; | ||
863 | if (put_user(2 * sizeof(unsigned int), _tlv + 1)) | ||
864 | return -EFAULT; | ||
865 | if (put_user(val1, _tlv + 2)) | ||
866 | return -EFAULT; | ||
867 | if (put_user(val2, _tlv + 3)) | ||
868 | return -EFAULT; | ||
869 | return 0; | ||
870 | } | ||
871 | |||
844 | /* switch */ | 872 | /* switch */ |
845 | int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 873 | int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
846 | { | 874 | { |
@@ -1477,10 +1505,10 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, | |||
1477 | formats |= SNDRV_PCM_FMTBIT_S32_LE; | 1505 | formats |= SNDRV_PCM_FMTBIT_S32_LE; |
1478 | if (val & AC_SUPPCM_BITS_32) | 1506 | if (val & AC_SUPPCM_BITS_32) |
1479 | bps = 32; | 1507 | bps = 32; |
1480 | else if (val & AC_SUPPCM_BITS_20) | ||
1481 | bps = 20; | ||
1482 | else if (val & AC_SUPPCM_BITS_24) | 1508 | else if (val & AC_SUPPCM_BITS_24) |
1483 | bps = 24; | 1509 | bps = 24; |
1510 | else if (val & AC_SUPPCM_BITS_20) | ||
1511 | bps = 20; | ||
1484 | } | 1512 | } |
1485 | } | 1513 | } |
1486 | else if (streams == AC_SUPFMT_FLOAT32) { /* should be exclusive */ | 1514 | else if (streams == AC_SUPFMT_FLOAT32) { /* should be exclusive */ |
@@ -1916,7 +1944,7 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_o | |||
1916 | 1944 | ||
1917 | /* front */ | 1945 | /* front */ |
1918 | snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, 0, format); | 1946 | snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, 0, format); |
1919 | if (mout->hp_nid) | 1947 | if (mout->hp_nid && mout->hp_nid != nids[HDA_FRONT]) |
1920 | /* headphone out will just decode front left/right (stereo) */ | 1948 | /* headphone out will just decode front left/right (stereo) */ |
1921 | snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format); | 1949 | snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format); |
1922 | /* extra outputs copied from front */ | 1950 | /* extra outputs copied from front */ |
@@ -1984,7 +2012,7 @@ static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list) | |||
1984 | * in the order of front, rear, CLFE, side, ... | 2012 | * in the order of front, rear, CLFE, side, ... |
1985 | * | 2013 | * |
1986 | * If more extra outputs (speaker and headphone) are found, the pins are | 2014 | * If more extra outputs (speaker and headphone) are found, the pins are |
1987 | * assisnged to hp_pin and speaker_pins[], respectively. If no line-out jack | 2015 | * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack |
1988 | * is detected, one of speaker of HP pins is assigned as the primary | 2016 | * is detected, one of speaker of HP pins is assigned as the primary |
1989 | * output, i.e. to line_out_pins[0]. So, line_outs is always positive | 2017 | * output, i.e. to line_out_pins[0]. So, line_outs is always positive |
1990 | * if any analog output exists. | 2018 | * if any analog output exists. |
@@ -2046,14 +2074,26 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c | |||
2046 | cfg->speaker_outs++; | 2074 | cfg->speaker_outs++; |
2047 | break; | 2075 | break; |
2048 | case AC_JACK_HP_OUT: | 2076 | case AC_JACK_HP_OUT: |
2049 | cfg->hp_pin = nid; | 2077 | if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins)) |
2078 | continue; | ||
2079 | cfg->hp_pins[cfg->hp_outs] = nid; | ||
2080 | cfg->hp_outs++; | ||
2050 | break; | 2081 | break; |
2051 | case AC_JACK_MIC_IN: | 2082 | case AC_JACK_MIC_IN: { |
2052 | if (loc == AC_JACK_LOC_FRONT) | 2083 | int preferred, alt; |
2053 | cfg->input_pins[AUTO_PIN_FRONT_MIC] = nid; | 2084 | if (loc == AC_JACK_LOC_FRONT) { |
2054 | else | 2085 | preferred = AUTO_PIN_FRONT_MIC; |
2055 | cfg->input_pins[AUTO_PIN_MIC] = nid; | 2086 | alt = AUTO_PIN_MIC; |
2087 | } else { | ||
2088 | preferred = AUTO_PIN_MIC; | ||
2089 | alt = AUTO_PIN_FRONT_MIC; | ||
2090 | } | ||
2091 | if (!cfg->input_pins[preferred]) | ||
2092 | cfg->input_pins[preferred] = nid; | ||
2093 | else if (!cfg->input_pins[alt]) | ||
2094 | cfg->input_pins[alt] = nid; | ||
2056 | break; | 2095 | break; |
2096 | } | ||
2057 | case AC_JACK_LINE_IN: | 2097 | case AC_JACK_LINE_IN: |
2058 | if (loc == AC_JACK_LOC_FRONT) | 2098 | if (loc == AC_JACK_LOC_FRONT) |
2059 | cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid; | 2099 | cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid; |
@@ -2119,8 +2159,10 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c | |||
2119 | cfg->speaker_outs, cfg->speaker_pins[0], | 2159 | cfg->speaker_outs, cfg->speaker_pins[0], |
2120 | cfg->speaker_pins[1], cfg->speaker_pins[2], | 2160 | cfg->speaker_pins[1], cfg->speaker_pins[2], |
2121 | cfg->speaker_pins[3], cfg->speaker_pins[4]); | 2161 | cfg->speaker_pins[3], cfg->speaker_pins[4]); |
2122 | snd_printd(" hp=0x%x, dig_out=0x%x, din_in=0x%x\n", | 2162 | snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", |
2123 | cfg->hp_pin, cfg->dig_out_pin, cfg->dig_in_pin); | 2163 | cfg->hp_outs, cfg->hp_pins[0], |
2164 | cfg->hp_pins[1], cfg->hp_pins[2], | ||
2165 | cfg->hp_pins[3], cfg->hp_pins[4]); | ||
2124 | snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x," | 2166 | snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x," |
2125 | " cd=0x%x, aux=0x%x\n", | 2167 | " cd=0x%x, aux=0x%x\n", |
2126 | cfg->input_pins[AUTO_PIN_MIC], | 2168 | cfg->input_pins[AUTO_PIN_MIC], |
@@ -2141,10 +2183,12 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c | |||
2141 | sizeof(cfg->speaker_pins)); | 2183 | sizeof(cfg->speaker_pins)); |
2142 | cfg->speaker_outs = 0; | 2184 | cfg->speaker_outs = 0; |
2143 | memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); | 2185 | memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); |
2144 | } else if (cfg->hp_pin) { | 2186 | } else if (cfg->hp_outs) { |
2145 | cfg->line_outs = 1; | 2187 | cfg->line_outs = cfg->hp_outs; |
2146 | cfg->line_out_pins[0] = cfg->hp_pin; | 2188 | memcpy(cfg->line_out_pins, cfg->hp_pins, |
2147 | cfg->hp_pin = 0; | 2189 | sizeof(cfg->hp_pins)); |
2190 | cfg->hp_outs = 0; | ||
2191 | memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins)); | ||
2148 | } | 2192 | } |
2149 | } | 2193 | } |
2150 | 2194 | ||
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 40520e9d5a4b..c12bc4e8840f 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -479,7 +479,7 @@ struct hda_codec_ops { | |||
479 | struct hda_amp_info { | 479 | struct hda_amp_info { |
480 | u32 key; /* hash key */ | 480 | u32 key; /* hash key */ |
481 | u32 amp_caps; /* amp capabilities */ | 481 | u32 amp_caps; /* amp capabilities */ |
482 | u16 vol[2]; /* current volume & mute*/ | 482 | u16 vol[2]; /* current volume & mute */ |
483 | u16 status; /* update flag */ | 483 | u16 status; /* update flag */ |
484 | u16 next; /* next link */ | 484 | u16 next; /* next link */ |
485 | }; | 485 | }; |
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 85ad164ada59..97e9af130b71 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -46,11 +46,18 @@ struct hda_gnode { | |||
46 | }; | 46 | }; |
47 | 47 | ||
48 | /* patch-specific record */ | 48 | /* patch-specific record */ |
49 | |||
50 | #define MAX_PCM_VOLS 2 | ||
51 | struct pcm_vol { | ||
52 | struct hda_gnode *node; /* Node for PCM volume */ | ||
53 | unsigned int index; /* connection of PCM volume */ | ||
54 | }; | ||
55 | |||
49 | struct hda_gspec { | 56 | struct hda_gspec { |
50 | struct hda_gnode *dac_node[2]; /* DAC node */ | 57 | struct hda_gnode *dac_node[2]; /* DAC node */ |
51 | struct hda_gnode *out_pin_node[2]; /* Output pin (Line-Out) node */ | 58 | struct hda_gnode *out_pin_node[2]; /* Output pin (Line-Out) node */ |
52 | struct hda_gnode *pcm_vol_node[2]; /* Node for PCM volume */ | 59 | struct pcm_vol pcm_vol[MAX_PCM_VOLS]; /* PCM volumes */ |
53 | unsigned int pcm_vol_index[2]; /* connection of PCM volume */ | 60 | unsigned int pcm_vol_nodes; /* number of PCM volumes */ |
54 | 61 | ||
55 | struct hda_gnode *adc_node; /* ADC node */ | 62 | struct hda_gnode *adc_node; /* ADC node */ |
56 | struct hda_gnode *cap_vol_node; /* Node for capture volume */ | 63 | struct hda_gnode *cap_vol_node; /* Node for capture volume */ |
@@ -285,9 +292,11 @@ static int parse_output_path(struct hda_codec *codec, struct hda_gspec *spec, | |||
285 | return node == spec->dac_node[dac_idx]; | 292 | return node == spec->dac_node[dac_idx]; |
286 | } | 293 | } |
287 | spec->dac_node[dac_idx] = node; | 294 | spec->dac_node[dac_idx] = node; |
288 | if (node->wid_caps & AC_WCAP_OUT_AMP) { | 295 | if ((node->wid_caps & AC_WCAP_OUT_AMP) && |
289 | spec->pcm_vol_node[dac_idx] = node; | 296 | spec->pcm_vol_nodes < MAX_PCM_VOLS) { |
290 | spec->pcm_vol_index[dac_idx] = 0; | 297 | spec->pcm_vol[spec->pcm_vol_nodes].node = node; |
298 | spec->pcm_vol[spec->pcm_vol_nodes].index = 0; | ||
299 | spec->pcm_vol_nodes++; | ||
291 | } | 300 | } |
292 | return 1; /* found */ | 301 | return 1; /* found */ |
293 | } | 302 | } |
@@ -307,13 +316,16 @@ static int parse_output_path(struct hda_codec *codec, struct hda_gspec *spec, | |||
307 | select_input_connection(codec, node, i); | 316 | select_input_connection(codec, node, i); |
308 | unmute_input(codec, node, i); | 317 | unmute_input(codec, node, i); |
309 | unmute_output(codec, node); | 318 | unmute_output(codec, node); |
310 | if (! spec->pcm_vol_node[dac_idx]) { | 319 | if (spec->dac_node[dac_idx] && |
311 | if (node->wid_caps & AC_WCAP_IN_AMP) { | 320 | spec->pcm_vol_nodes < MAX_PCM_VOLS && |
312 | spec->pcm_vol_node[dac_idx] = node; | 321 | !(spec->dac_node[dac_idx]->wid_caps & |
313 | spec->pcm_vol_index[dac_idx] = i; | 322 | AC_WCAP_OUT_AMP)) { |
314 | } else if (node->wid_caps & AC_WCAP_OUT_AMP) { | 323 | if ((node->wid_caps & AC_WCAP_IN_AMP) || |
315 | spec->pcm_vol_node[dac_idx] = node; | 324 | (node->wid_caps & AC_WCAP_OUT_AMP)) { |
316 | spec->pcm_vol_index[dac_idx] = 0; | 325 | int n = spec->pcm_vol_nodes; |
326 | spec->pcm_vol[n].node = node; | ||
327 | spec->pcm_vol[n].index = i; | ||
328 | spec->pcm_vol_nodes++; | ||
317 | } | 329 | } |
318 | } | 330 | } |
319 | return 1; | 331 | return 1; |
@@ -370,7 +382,9 @@ static struct hda_gnode *parse_output_jack(struct hda_codec *codec, | |||
370 | /* set PIN-Out enable */ | 382 | /* set PIN-Out enable */ |
371 | snd_hda_codec_write(codec, node->nid, 0, | 383 | snd_hda_codec_write(codec, node->nid, 0, |
372 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 384 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
373 | AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN); | 385 | AC_PINCTL_OUT_EN | |
386 | ((node->pin_caps & AC_PINCAP_HP_DRV) ? | ||
387 | AC_PINCTL_HP_EN : 0)); | ||
374 | return node; | 388 | return node; |
375 | } | 389 | } |
376 | } | 390 | } |
@@ -461,14 +475,19 @@ static const char *get_input_type(struct hda_gnode *node, unsigned int *pinctl) | |||
461 | return "Front Line"; | 475 | return "Front Line"; |
462 | return "Line"; | 476 | return "Line"; |
463 | case AC_JACK_CD: | 477 | case AC_JACK_CD: |
478 | #if 0 | ||
464 | if (pinctl) | 479 | if (pinctl) |
465 | *pinctl |= AC_PINCTL_VREF_GRD; | 480 | *pinctl |= AC_PINCTL_VREF_GRD; |
481 | #endif | ||
466 | return "CD"; | 482 | return "CD"; |
467 | case AC_JACK_AUX: | 483 | case AC_JACK_AUX: |
468 | if ((location & 0x0f) == AC_JACK_LOC_FRONT) | 484 | if ((location & 0x0f) == AC_JACK_LOC_FRONT) |
469 | return "Front Aux"; | 485 | return "Front Aux"; |
470 | return "Aux"; | 486 | return "Aux"; |
471 | case AC_JACK_MIC_IN: | 487 | case AC_JACK_MIC_IN: |
488 | if (node->pin_caps & | ||
489 | (AC_PINCAP_VREF_80 << AC_PINCAP_VREF_SHIFT)) | ||
490 | *pinctl |= AC_PINCTL_VREF_80; | ||
472 | if ((location & 0x0f) == AC_JACK_LOC_FRONT) | 491 | if ((location & 0x0f) == AC_JACK_LOC_FRONT) |
473 | return "Front Mic"; | 492 | return "Front Mic"; |
474 | return "Mic"; | 493 | return "Mic"; |
@@ -556,6 +575,29 @@ static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec, | |||
556 | return 1; /* found */ | 575 | return 1; /* found */ |
557 | } | 576 | } |
558 | 577 | ||
578 | /* add a capture source element */ | ||
579 | static void add_cap_src(struct hda_gspec *spec, int idx) | ||
580 | { | ||
581 | struct hda_input_mux_item *csrc; | ||
582 | char *buf; | ||
583 | int num, ocap; | ||
584 | |||
585 | num = spec->input_mux.num_items; | ||
586 | csrc = &spec->input_mux.items[num]; | ||
587 | buf = spec->cap_labels[num]; | ||
588 | for (ocap = 0; ocap < num; ocap++) { | ||
589 | if (! strcmp(buf, spec->cap_labels[ocap])) { | ||
590 | /* same label already exists, | ||
591 | * put the index number to be unique | ||
592 | */ | ||
593 | sprintf(buf, "%s %d", spec->cap_labels[ocap], num); | ||
594 | break; | ||
595 | } | ||
596 | } | ||
597 | csrc->index = idx; | ||
598 | spec->input_mux.num_items++; | ||
599 | } | ||
600 | |||
559 | /* | 601 | /* |
560 | * parse input | 602 | * parse input |
561 | */ | 603 | */ |
@@ -576,28 +618,26 @@ static int parse_input_path(struct hda_codec *codec, struct hda_gnode *adc_node) | |||
576 | * if it reaches to a proper input PIN, add the path as the | 618 | * if it reaches to a proper input PIN, add the path as the |
577 | * input path. | 619 | * input path. |
578 | */ | 620 | */ |
621 | /* first, check the direct connections to PIN widgets */ | ||
579 | for (i = 0; i < adc_node->nconns; i++) { | 622 | for (i = 0; i < adc_node->nconns; i++) { |
580 | node = hda_get_node(spec, adc_node->conn_list[i]); | 623 | node = hda_get_node(spec, adc_node->conn_list[i]); |
581 | if (! node) | 624 | if (node && node->type == AC_WID_PIN) { |
582 | continue; | 625 | err = parse_adc_sub_nodes(codec, spec, node); |
583 | err = parse_adc_sub_nodes(codec, spec, node); | 626 | if (err < 0) |
584 | if (err < 0) | 627 | return err; |
585 | return err; | 628 | else if (err > 0) |
586 | else if (err > 0) { | 629 | add_cap_src(spec, i); |
587 | struct hda_input_mux_item *csrc = &spec->input_mux.items[spec->input_mux.num_items]; | 630 | } |
588 | char *buf = spec->cap_labels[spec->input_mux.num_items]; | 631 | } |
589 | int ocap; | 632 | /* ... then check the rests, more complicated connections */ |
590 | for (ocap = 0; ocap < spec->input_mux.num_items; ocap++) { | 633 | for (i = 0; i < adc_node->nconns; i++) { |
591 | if (! strcmp(buf, spec->cap_labels[ocap])) { | 634 | node = hda_get_node(spec, adc_node->conn_list[i]); |
592 | /* same label already exists, | 635 | if (node && node->type != AC_WID_PIN) { |
593 | * put the index number to be unique | 636 | err = parse_adc_sub_nodes(codec, spec, node); |
594 | */ | 637 | if (err < 0) |
595 | sprintf(buf, "%s %d", spec->cap_labels[ocap], | 638 | return err; |
596 | spec->input_mux.num_items); | 639 | else if (err > 0) |
597 | } | 640 | add_cap_src(spec, i); |
598 | } | ||
599 | csrc->index = i; | ||
600 | spec->input_mux.num_items++; | ||
601 | } | 641 | } |
602 | } | 642 | } |
603 | 643 | ||
@@ -647,9 +687,6 @@ static int parse_input(struct hda_codec *codec) | |||
647 | /* | 687 | /* |
648 | * create mixer controls if possible | 688 | * create mixer controls if possible |
649 | */ | 689 | */ |
650 | #define DIR_OUT 0x1 | ||
651 | #define DIR_IN 0x2 | ||
652 | |||
653 | static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, | 690 | static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, |
654 | unsigned int index, const char *type, const char *dir_sfx) | 691 | unsigned int index, const char *type, const char *dir_sfx) |
655 | { | 692 | { |
@@ -722,49 +759,97 @@ static int check_existing_control(struct hda_codec *codec, const char *type, con | |||
722 | /* | 759 | /* |
723 | * build output mixer controls | 760 | * build output mixer controls |
724 | */ | 761 | */ |
725 | static int build_output_controls(struct hda_codec *codec) | 762 | static int create_output_mixers(struct hda_codec *codec, const char **names) |
726 | { | 763 | { |
727 | struct hda_gspec *spec = codec->spec; | 764 | struct hda_gspec *spec = codec->spec; |
728 | static const char *types[2] = { "Master", "Headphone" }; | ||
729 | int i, err; | 765 | int i, err; |
730 | 766 | ||
731 | for (i = 0; i < 2 && spec->pcm_vol_node[i]; i++) { | 767 | for (i = 0; i < spec->pcm_vol_nodes; i++) { |
732 | err = create_mixer(codec, spec->pcm_vol_node[i], | 768 | err = create_mixer(codec, spec->pcm_vol[i].node, |
733 | spec->pcm_vol_index[i], | 769 | spec->pcm_vol[i].index, |
734 | types[i], "Playback"); | 770 | names[i], "Playback"); |
735 | if (err < 0) | 771 | if (err < 0) |
736 | return err; | 772 | return err; |
737 | } | 773 | } |
738 | return 0; | 774 | return 0; |
739 | } | 775 | } |
740 | 776 | ||
777 | static int build_output_controls(struct hda_codec *codec) | ||
778 | { | ||
779 | struct hda_gspec *spec = codec->spec; | ||
780 | static const char *types_speaker[] = { "Speaker", "Headphone" }; | ||
781 | static const char *types_line[] = { "Front", "Headphone" }; | ||
782 | |||
783 | switch (spec->pcm_vol_nodes) { | ||
784 | case 1: | ||
785 | return create_mixer(codec, spec->pcm_vol[0].node, | ||
786 | spec->pcm_vol[0].index, | ||
787 | "Master", "Playback"); | ||
788 | case 2: | ||
789 | if (defcfg_type(spec->out_pin_node[0]) == AC_JACK_SPEAKER) | ||
790 | return create_output_mixers(codec, types_speaker); | ||
791 | else | ||
792 | return create_output_mixers(codec, types_line); | ||
793 | } | ||
794 | return 0; | ||
795 | } | ||
796 | |||
741 | /* create capture volume/switch */ | 797 | /* create capture volume/switch */ |
742 | static int build_input_controls(struct hda_codec *codec) | 798 | static int build_input_controls(struct hda_codec *codec) |
743 | { | 799 | { |
744 | struct hda_gspec *spec = codec->spec; | 800 | struct hda_gspec *spec = codec->spec; |
745 | struct hda_gnode *adc_node = spec->adc_node; | 801 | struct hda_gnode *adc_node = spec->adc_node; |
746 | int err; | 802 | int i, err; |
747 | 803 | static struct snd_kcontrol_new cap_sel = { | |
748 | if (! adc_node) | 804 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
805 | .name = "Capture Source", | ||
806 | .info = capture_source_info, | ||
807 | .get = capture_source_get, | ||
808 | .put = capture_source_put, | ||
809 | }; | ||
810 | |||
811 | if (! adc_node || ! spec->input_mux.num_items) | ||
749 | return 0; /* not found */ | 812 | return 0; /* not found */ |
750 | 813 | ||
814 | spec->cur_cap_src = 0; | ||
815 | select_input_connection(codec, adc_node, | ||
816 | spec->input_mux.items[0].index); | ||
817 | |||
751 | /* create capture volume and switch controls if the ADC has an amp */ | 818 | /* create capture volume and switch controls if the ADC has an amp */ |
752 | err = create_mixer(codec, adc_node, 0, NULL, "Capture"); | 819 | /* do we have only a single item? */ |
820 | if (spec->input_mux.num_items == 1) { | ||
821 | err = create_mixer(codec, adc_node, | ||
822 | spec->input_mux.items[0].index, | ||
823 | NULL, "Capture"); | ||
824 | if (err < 0) | ||
825 | return err; | ||
826 | return 0; | ||
827 | } | ||
753 | 828 | ||
754 | /* create input MUX if multiple sources are available */ | 829 | /* create input MUX if multiple sources are available */ |
755 | if (spec->input_mux.num_items > 1) { | 830 | if ((err = snd_ctl_add(codec->bus->card, |
756 | static struct snd_kcontrol_new cap_sel = { | 831 | snd_ctl_new1(&cap_sel, codec))) < 0) |
757 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 832 | return err; |
758 | .name = "Capture Source", | 833 | |
759 | .info = capture_source_info, | 834 | /* no volume control? */ |
760 | .get = capture_source_get, | 835 | if (! (adc_node->wid_caps & AC_WCAP_IN_AMP) || |
761 | .put = capture_source_put, | 836 | ! (adc_node->amp_in_caps & AC_AMPCAP_NUM_STEPS)) |
762 | }; | 837 | return 0; |
763 | if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&cap_sel, codec))) < 0) | 838 | |
839 | for (i = 0; i < spec->input_mux.num_items; i++) { | ||
840 | struct snd_kcontrol_new knew; | ||
841 | char name[32]; | ||
842 | sprintf(name, "%s Capture Volume", | ||
843 | spec->input_mux.items[i].label); | ||
844 | knew = (struct snd_kcontrol_new) | ||
845 | HDA_CODEC_VOLUME(name, adc_node->nid, | ||
846 | spec->input_mux.items[i].index, | ||
847 | HDA_INPUT); | ||
848 | if ((err = snd_ctl_add(codec->bus->card, | ||
849 | snd_ctl_new1(&knew, codec))) < 0) | ||
764 | return err; | 850 | return err; |
765 | spec->cur_cap_src = 0; | ||
766 | select_input_connection(codec, adc_node, spec->input_mux.items[0].index); | ||
767 | } | 851 | } |
852 | |||
768 | return 0; | 853 | return 0; |
769 | } | 854 | } |
770 | 855 | ||
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 79d63c99f092..e9d4cb4d07e1 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -55,6 +55,7 @@ static char *model; | |||
55 | static int position_fix; | 55 | static int position_fix; |
56 | static int probe_mask = -1; | 56 | static int probe_mask = -1; |
57 | static int single_cmd; | 57 | static int single_cmd; |
58 | static int disable_msi; | ||
58 | 59 | ||
59 | module_param(index, int, 0444); | 60 | module_param(index, int, 0444); |
60 | MODULE_PARM_DESC(index, "Index value for Intel HD audio interface."); | 61 | MODULE_PARM_DESC(index, "Index value for Intel HD audio interface."); |
@@ -68,6 +69,8 @@ module_param(probe_mask, int, 0444); | |||
68 | MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1)."); | 69 | MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1)."); |
69 | module_param(single_cmd, bool, 0444); | 70 | module_param(single_cmd, bool, 0444); |
70 | MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs (for debugging only)."); | 71 | MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs (for debugging only)."); |
72 | module_param(disable_msi, int, 0); | ||
73 | MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)"); | ||
71 | 74 | ||
72 | 75 | ||
73 | /* just for backward compatibility */ | 76 | /* just for backward compatibility */ |
@@ -252,7 +255,7 @@ enum { | |||
252 | struct azx_dev { | 255 | struct azx_dev { |
253 | u32 *bdl; /* virtual address of the BDL */ | 256 | u32 *bdl; /* virtual address of the BDL */ |
254 | dma_addr_t bdl_addr; /* physical address of the BDL */ | 257 | dma_addr_t bdl_addr; /* physical address of the BDL */ |
255 | volatile u32 *posbuf; /* position buffer pointer */ | 258 | u32 *posbuf; /* position buffer pointer */ |
256 | 259 | ||
257 | unsigned int bufsize; /* size of the play buffer in bytes */ | 260 | unsigned int bufsize; /* size of the play buffer in bytes */ |
258 | unsigned int fragsize; /* size of each period in bytes */ | 261 | unsigned int fragsize; /* size of each period in bytes */ |
@@ -271,8 +274,8 @@ struct azx_dev { | |||
271 | /* for sanity check of position buffer */ | 274 | /* for sanity check of position buffer */ |
272 | unsigned int period_intr; | 275 | unsigned int period_intr; |
273 | 276 | ||
274 | unsigned int opened: 1; | 277 | unsigned int opened :1; |
275 | unsigned int running: 1; | 278 | unsigned int running :1; |
276 | }; | 279 | }; |
277 | 280 | ||
278 | /* CORB/RIRB */ | 281 | /* CORB/RIRB */ |
@@ -330,8 +333,9 @@ struct azx { | |||
330 | 333 | ||
331 | /* flags */ | 334 | /* flags */ |
332 | int position_fix; | 335 | int position_fix; |
333 | unsigned int initialized: 1; | 336 | unsigned int initialized :1; |
334 | unsigned int single_cmd: 1; | 337 | unsigned int single_cmd :1; |
338 | unsigned int polling_mode :1; | ||
335 | }; | 339 | }; |
336 | 340 | ||
337 | /* driver types */ | 341 | /* driver types */ |
@@ -516,23 +520,36 @@ static void azx_update_rirb(struct azx *chip) | |||
516 | static unsigned int azx_rirb_get_response(struct hda_codec *codec) | 520 | static unsigned int azx_rirb_get_response(struct hda_codec *codec) |
517 | { | 521 | { |
518 | struct azx *chip = codec->bus->private_data; | 522 | struct azx *chip = codec->bus->private_data; |
519 | int timeout = 50; | 523 | unsigned long timeout; |
520 | 524 | ||
521 | while (chip->rirb.cmds) { | 525 | again: |
522 | if (! --timeout) { | 526 | timeout = jiffies + msecs_to_jiffies(1000); |
523 | snd_printk(KERN_ERR | 527 | do { |
524 | "hda_intel: azx_get_response timeout, " | 528 | if (chip->polling_mode) { |
525 | "switching to single_cmd mode...\n"); | 529 | spin_lock_irq(&chip->reg_lock); |
526 | chip->rirb.rp = azx_readb(chip, RIRBWP); | 530 | azx_update_rirb(chip); |
527 | chip->rirb.cmds = 0; | 531 | spin_unlock_irq(&chip->reg_lock); |
528 | /* switch to single_cmd mode */ | ||
529 | chip->single_cmd = 1; | ||
530 | azx_free_cmd_io(chip); | ||
531 | return -1; | ||
532 | } | 532 | } |
533 | msleep(1); | 533 | if (! chip->rirb.cmds) |
534 | return chip->rirb.res; /* the last value */ | ||
535 | schedule_timeout_interruptible(1); | ||
536 | } while (time_after_eq(timeout, jiffies)); | ||
537 | |||
538 | if (!chip->polling_mode) { | ||
539 | snd_printk(KERN_WARNING "hda_intel: azx_get_response timeout, " | ||
540 | "switching to polling mode...\n"); | ||
541 | chip->polling_mode = 1; | ||
542 | goto again; | ||
534 | } | 543 | } |
535 | return chip->rirb.res; /* the last value */ | 544 | |
545 | snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, " | ||
546 | "switching to single_cmd mode...\n"); | ||
547 | chip->rirb.rp = azx_readb(chip, RIRBWP); | ||
548 | chip->rirb.cmds = 0; | ||
549 | /* switch to single_cmd mode */ | ||
550 | chip->single_cmd = 1; | ||
551 | azx_free_cmd_io(chip); | ||
552 | return -1; | ||
536 | } | 553 | } |
537 | 554 | ||
538 | /* | 555 | /* |
@@ -642,14 +659,14 @@ static int azx_reset(struct azx *chip) | |||
642 | azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | ICH6_GCTL_RESET); | 659 | azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | ICH6_GCTL_RESET); |
643 | 660 | ||
644 | count = 50; | 661 | count = 50; |
645 | while (! azx_readb(chip, GCTL) && --count) | 662 | while (!azx_readb(chip, GCTL) && --count) |
646 | msleep(1); | 663 | msleep(1); |
647 | 664 | ||
648 | /* Brent Chartrand said to wait >= 540us for codecs to intialize */ | 665 | /* Brent Chartrand said to wait >= 540us for codecs to initialize */ |
649 | msleep(1); | 666 | msleep(1); |
650 | 667 | ||
651 | /* check to see if controller is ready */ | 668 | /* check to see if controller is ready */ |
652 | if (! azx_readb(chip, GCTL)) { | 669 | if (!azx_readb(chip, GCTL)) { |
653 | snd_printd("azx_reset: controller not ready!\n"); | 670 | snd_printd("azx_reset: controller not ready!\n"); |
654 | return -EBUSY; | 671 | return -EBUSY; |
655 | } | 672 | } |
@@ -658,7 +675,7 @@ static int azx_reset(struct azx *chip) | |||
658 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) | ICH6_GCTL_UREN); | 675 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) | ICH6_GCTL_UREN); |
659 | 676 | ||
660 | /* detect codecs */ | 677 | /* detect codecs */ |
661 | if (! chip->codec_mask) { | 678 | if (!chip->codec_mask) { |
662 | chip->codec_mask = azx_readw(chip, STATESTS); | 679 | chip->codec_mask = azx_readw(chip, STATESTS); |
663 | snd_printdd("codec_mask = 0x%x\n", chip->codec_mask); | 680 | snd_printdd("codec_mask = 0x%x\n", chip->codec_mask); |
664 | } | 681 | } |
@@ -766,7 +783,7 @@ static void azx_init_chip(struct azx *chip) | |||
766 | azx_int_enable(chip); | 783 | azx_int_enable(chip); |
767 | 784 | ||
768 | /* initialize the codec command I/O */ | 785 | /* initialize the codec command I/O */ |
769 | if (! chip->single_cmd) | 786 | if (!chip->single_cmd) |
770 | azx_init_cmd_io(chip); | 787 | azx_init_cmd_io(chip); |
771 | 788 | ||
772 | /* program the position buffer */ | 789 | /* program the position buffer */ |
@@ -794,7 +811,7 @@ static void azx_init_chip(struct azx *chip) | |||
794 | /* | 811 | /* |
795 | * interrupt handler | 812 | * interrupt handler |
796 | */ | 813 | */ |
797 | static irqreturn_t azx_interrupt(int irq, void* dev_id, struct pt_regs *regs) | 814 | static irqreturn_t azx_interrupt(int irq, void *dev_id, struct pt_regs *regs) |
798 | { | 815 | { |
799 | struct azx *chip = dev_id; | 816 | struct azx *chip = dev_id; |
800 | struct azx_dev *azx_dev; | 817 | struct azx_dev *azx_dev; |
@@ -999,8 +1016,9 @@ static struct snd_pcm_hardware azx_pcm_hw = { | |||
999 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | | 1016 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | |
1000 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 1017 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
1001 | SNDRV_PCM_INFO_MMAP_VALID | | 1018 | SNDRV_PCM_INFO_MMAP_VALID | |
1002 | SNDRV_PCM_INFO_PAUSE /*|*/ | 1019 | /* No full-resume yet implemented */ |
1003 | /*SNDRV_PCM_INFO_RESUME*/), | 1020 | /* SNDRV_PCM_INFO_RESUME |*/ |
1021 | SNDRV_PCM_INFO_PAUSE), | ||
1004 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 1022 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
1005 | .rates = SNDRV_PCM_RATE_48000, | 1023 | .rates = SNDRV_PCM_RATE_48000, |
1006 | .rate_min = 48000, | 1024 | .rate_min = 48000, |
@@ -1178,7 +1196,7 @@ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream) | |||
1178 | if (chip->position_fix == POS_FIX_POSBUF || | 1196 | if (chip->position_fix == POS_FIX_POSBUF || |
1179 | chip->position_fix == POS_FIX_AUTO) { | 1197 | chip->position_fix == POS_FIX_AUTO) { |
1180 | /* use the position buffer */ | 1198 | /* use the position buffer */ |
1181 | pos = *azx_dev->posbuf; | 1199 | pos = le32_to_cpu(*azx_dev->posbuf); |
1182 | if (chip->position_fix == POS_FIX_AUTO && | 1200 | if (chip->position_fix == POS_FIX_AUTO && |
1183 | azx_dev->period_intr == 1 && ! pos) { | 1201 | azx_dev->period_intr == 1 && ! pos) { |
1184 | printk(KERN_WARNING | 1202 | printk(KERN_WARNING |
@@ -1222,7 +1240,12 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec, | |||
1222 | struct snd_pcm *pcm; | 1240 | struct snd_pcm *pcm; |
1223 | struct azx_pcm *apcm; | 1241 | struct azx_pcm *apcm; |
1224 | 1242 | ||
1225 | snd_assert(cpcm->stream[0].substreams || cpcm->stream[1].substreams, return -EINVAL); | 1243 | /* if no substreams are defined for both playback and capture, |
1244 | * it's just a placeholder. ignore it. | ||
1245 | */ | ||
1246 | if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams) | ||
1247 | return 0; | ||
1248 | |||
1226 | snd_assert(cpcm->name, return -EINVAL); | 1249 | snd_assert(cpcm->name, return -EINVAL); |
1227 | 1250 | ||
1228 | err = snd_pcm_new(chip->card, cpcm->name, pcm_dev, | 1251 | err = snd_pcm_new(chip->card, cpcm->name, pcm_dev, |
@@ -1248,7 +1271,8 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec, | |||
1248 | snd_dma_pci_data(chip->pci), | 1271 | snd_dma_pci_data(chip->pci), |
1249 | 1024 * 64, 1024 * 128); | 1272 | 1024 * 64, 1024 * 128); |
1250 | chip->pcm[pcm_dev] = pcm; | 1273 | chip->pcm[pcm_dev] = pcm; |
1251 | chip->pcm_devs = pcm_dev + 1; | 1274 | if (chip->pcm_devs < pcm_dev + 1) |
1275 | chip->pcm_devs = pcm_dev + 1; | ||
1252 | 1276 | ||
1253 | return 0; | 1277 | return 0; |
1254 | } | 1278 | } |
@@ -1326,7 +1350,7 @@ static int __devinit azx_init_stream(struct azx *chip) | |||
1326 | struct azx_dev *azx_dev = &chip->azx_dev[i]; | 1350 | struct azx_dev *azx_dev = &chip->azx_dev[i]; |
1327 | azx_dev->bdl = (u32 *)(chip->bdl.area + off); | 1351 | azx_dev->bdl = (u32 *)(chip->bdl.area + off); |
1328 | azx_dev->bdl_addr = chip->bdl.addr + off; | 1352 | azx_dev->bdl_addr = chip->bdl.addr + off; |
1329 | azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8); | 1353 | azx_dev->posbuf = (u32 __iomem *)(chip->posbuf.area + i * 8); |
1330 | /* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ | 1354 | /* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ |
1331 | azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80); | 1355 | azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80); |
1332 | /* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */ | 1356 | /* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */ |
@@ -1355,6 +1379,10 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state) | |||
1355 | snd_pcm_suspend_all(chip->pcm[i]); | 1379 | snd_pcm_suspend_all(chip->pcm[i]); |
1356 | snd_hda_suspend(chip->bus, state); | 1380 | snd_hda_suspend(chip->bus, state); |
1357 | azx_free_cmd_io(chip); | 1381 | azx_free_cmd_io(chip); |
1382 | if (chip->irq >= 0) | ||
1383 | free_irq(chip->irq, chip); | ||
1384 | if (!disable_msi) | ||
1385 | pci_disable_msi(chip->pci); | ||
1358 | pci_disable_device(pci); | 1386 | pci_disable_device(pci); |
1359 | pci_save_state(pci); | 1387 | pci_save_state(pci); |
1360 | return 0; | 1388 | return 0; |
@@ -1367,6 +1395,12 @@ static int azx_resume(struct pci_dev *pci) | |||
1367 | 1395 | ||
1368 | pci_restore_state(pci); | 1396 | pci_restore_state(pci); |
1369 | pci_enable_device(pci); | 1397 | pci_enable_device(pci); |
1398 | if (!disable_msi) | ||
1399 | pci_enable_msi(pci); | ||
1400 | /* FIXME: need proper error handling */ | ||
1401 | request_irq(pci->irq, azx_interrupt, IRQF_DISABLED|IRQF_SHARED, | ||
1402 | "HDA Intel", chip); | ||
1403 | chip->irq = pci->irq; | ||
1370 | pci_set_master(pci); | 1404 | pci_set_master(pci); |
1371 | azx_init_chip(chip); | 1405 | azx_init_chip(chip); |
1372 | snd_hda_resume(chip->bus); | 1406 | snd_hda_resume(chip->bus); |
@@ -1398,12 +1432,14 @@ static int azx_free(struct azx *chip) | |||
1398 | azx_writel(chip, DPLBASE, 0); | 1432 | azx_writel(chip, DPLBASE, 0); |
1399 | azx_writel(chip, DPUBASE, 0); | 1433 | azx_writel(chip, DPUBASE, 0); |
1400 | 1434 | ||
1401 | /* wait a little for interrupts to finish */ | 1435 | synchronize_irq(chip->irq); |
1402 | msleep(1); | ||
1403 | } | 1436 | } |
1404 | 1437 | ||
1405 | if (chip->irq >= 0) | 1438 | if (chip->irq >= 0) { |
1406 | free_irq(chip->irq, (void*)chip); | 1439 | free_irq(chip->irq, (void*)chip); |
1440 | if (!disable_msi) | ||
1441 | pci_disable_msi(chip->pci); | ||
1442 | } | ||
1407 | if (chip->remap_addr) | 1443 | if (chip->remap_addr) |
1408 | iounmap(chip->remap_addr); | 1444 | iounmap(chip->remap_addr); |
1409 | 1445 | ||
@@ -1434,19 +1470,19 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1434 | struct azx **rchip) | 1470 | struct azx **rchip) |
1435 | { | 1471 | { |
1436 | struct azx *chip; | 1472 | struct azx *chip; |
1437 | int err = 0; | 1473 | int err; |
1438 | static struct snd_device_ops ops = { | 1474 | static struct snd_device_ops ops = { |
1439 | .dev_free = azx_dev_free, | 1475 | .dev_free = azx_dev_free, |
1440 | }; | 1476 | }; |
1441 | 1477 | ||
1442 | *rchip = NULL; | 1478 | *rchip = NULL; |
1443 | 1479 | ||
1444 | if ((err = pci_enable_device(pci)) < 0) | 1480 | err = pci_enable_device(pci); |
1481 | if (err < 0) | ||
1445 | return err; | 1482 | return err; |
1446 | 1483 | ||
1447 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | 1484 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); |
1448 | 1485 | if (!chip) { | |
1449 | if (NULL == chip) { | ||
1450 | snd_printk(KERN_ERR SFX "cannot allocate chip\n"); | 1486 | snd_printk(KERN_ERR SFX "cannot allocate chip\n"); |
1451 | pci_disable_device(pci); | 1487 | pci_disable_device(pci); |
1452 | return -ENOMEM; | 1488 | return -ENOMEM; |
@@ -1472,13 +1508,14 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1472 | } | 1508 | } |
1473 | #endif | 1509 | #endif |
1474 | 1510 | ||
1475 | if ((err = pci_request_regions(pci, "ICH HD audio")) < 0) { | 1511 | err = pci_request_regions(pci, "ICH HD audio"); |
1512 | if (err < 0) { | ||
1476 | kfree(chip); | 1513 | kfree(chip); |
1477 | pci_disable_device(pci); | 1514 | pci_disable_device(pci); |
1478 | return err; | 1515 | return err; |
1479 | } | 1516 | } |
1480 | 1517 | ||
1481 | chip->addr = pci_resource_start(pci,0); | 1518 | chip->addr = pci_resource_start(pci, 0); |
1482 | chip->remap_addr = ioremap_nocache(chip->addr, pci_resource_len(pci,0)); | 1519 | chip->remap_addr = ioremap_nocache(chip->addr, pci_resource_len(pci,0)); |
1483 | if (chip->remap_addr == NULL) { | 1520 | if (chip->remap_addr == NULL) { |
1484 | snd_printk(KERN_ERR SFX "ioremap error\n"); | 1521 | snd_printk(KERN_ERR SFX "ioremap error\n"); |
@@ -1486,6 +1523,9 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1486 | goto errout; | 1523 | goto errout; |
1487 | } | 1524 | } |
1488 | 1525 | ||
1526 | if (!disable_msi) | ||
1527 | pci_enable_msi(pci); | ||
1528 | |||
1489 | if (request_irq(pci->irq, azx_interrupt, IRQF_DISABLED|IRQF_SHARED, | 1529 | if (request_irq(pci->irq, azx_interrupt, IRQF_DISABLED|IRQF_SHARED, |
1490 | "HDA Intel", (void*)chip)) { | 1530 | "HDA Intel", (void*)chip)) { |
1491 | snd_printk(KERN_ERR SFX "unable to grab IRQ %d\n", pci->irq); | 1531 | snd_printk(KERN_ERR SFX "unable to grab IRQ %d\n", pci->irq); |
@@ -1519,7 +1559,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1519 | } | 1559 | } |
1520 | chip->num_streams = chip->playback_streams + chip->capture_streams; | 1560 | chip->num_streams = chip->playback_streams + chip->capture_streams; |
1521 | chip->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev), GFP_KERNEL); | 1561 | chip->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev), GFP_KERNEL); |
1522 | if (! chip->azx_dev) { | 1562 | if (!chip->azx_dev) { |
1523 | snd_printk(KERN_ERR "cannot malloc azx_dev\n"); | 1563 | snd_printk(KERN_ERR "cannot malloc azx_dev\n"); |
1524 | goto errout; | 1564 | goto errout; |
1525 | } | 1565 | } |
@@ -1550,7 +1590,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1550 | chip->initialized = 1; | 1590 | chip->initialized = 1; |
1551 | 1591 | ||
1552 | /* codec detection */ | 1592 | /* codec detection */ |
1553 | if (! chip->codec_mask) { | 1593 | if (!chip->codec_mask) { |
1554 | snd_printk(KERN_ERR SFX "no codecs found!\n"); | 1594 | snd_printk(KERN_ERR SFX "no codecs found!\n"); |
1555 | err = -ENODEV; | 1595 | err = -ENODEV; |
1556 | goto errout; | 1596 | goto errout; |
@@ -1577,16 +1617,16 @@ static int __devinit azx_probe(struct pci_dev *pci, const struct pci_device_id * | |||
1577 | { | 1617 | { |
1578 | struct snd_card *card; | 1618 | struct snd_card *card; |
1579 | struct azx *chip; | 1619 | struct azx *chip; |
1580 | int err = 0; | 1620 | int err; |
1581 | 1621 | ||
1582 | card = snd_card_new(index, id, THIS_MODULE, 0); | 1622 | card = snd_card_new(index, id, THIS_MODULE, 0); |
1583 | if (NULL == card) { | 1623 | if (!card) { |
1584 | snd_printk(KERN_ERR SFX "Error creating card!\n"); | 1624 | snd_printk(KERN_ERR SFX "Error creating card!\n"); |
1585 | return -ENOMEM; | 1625 | return -ENOMEM; |
1586 | } | 1626 | } |
1587 | 1627 | ||
1588 | if ((err = azx_create(card, pci, pci_id->driver_data, | 1628 | err = azx_create(card, pci, pci_id->driver_data, &chip); |
1589 | &chip)) < 0) { | 1629 | if (err < 0) { |
1590 | snd_card_free(card); | 1630 | snd_card_free(card); |
1591 | return err; | 1631 | return err; |
1592 | } | 1632 | } |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 14e8aa2806ed..f9416c36396e 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -30,9 +30,13 @@ | |||
30 | /* mono volume with index (index=0,1,...) (channel=1,2) */ | 30 | /* mono volume with index (index=0,1,...) (channel=1,2) */ |
31 | #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ | 31 | #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ |
32 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ | 32 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ |
33 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ | ||
34 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ | ||
35 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \ | ||
33 | .info = snd_hda_mixer_amp_volume_info, \ | 36 | .info = snd_hda_mixer_amp_volume_info, \ |
34 | .get = snd_hda_mixer_amp_volume_get, \ | 37 | .get = snd_hda_mixer_amp_volume_get, \ |
35 | .put = snd_hda_mixer_amp_volume_put, \ | 38 | .put = snd_hda_mixer_amp_volume_put, \ |
39 | .tlv = { .c = snd_hda_mixer_amp_tlv }, \ | ||
36 | .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) } | 40 | .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) } |
37 | /* stereo volume with index */ | 41 | /* stereo volume with index */ |
38 | #define HDA_CODEC_VOLUME_IDX(xname, xcidx, nid, xindex, direction) \ | 42 | #define HDA_CODEC_VOLUME_IDX(xname, xcidx, nid, xindex, direction) \ |
@@ -63,6 +67,7 @@ | |||
63 | int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); | 67 | int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); |
64 | int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | 68 | int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); |
65 | int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | 69 | int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); |
70 | int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, unsigned int size, unsigned int __user *tlv); | ||
66 | int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); | 71 | int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); |
67 | int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | 72 | int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); |
68 | int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | 73 | int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); |
@@ -224,7 +229,8 @@ struct auto_pin_cfg { | |||
224 | hda_nid_t line_out_pins[5]; /* sorted in the order of Front/Surr/CLFE/Side */ | 229 | hda_nid_t line_out_pins[5]; /* sorted in the order of Front/Surr/CLFE/Side */ |
225 | int speaker_outs; | 230 | int speaker_outs; |
226 | hda_nid_t speaker_pins[5]; | 231 | hda_nid_t speaker_pins[5]; |
227 | hda_nid_t hp_pin; | 232 | int hp_outs; |
233 | hda_nid_t hp_pins[5]; | ||
228 | hda_nid_t input_pins[AUTO_PIN_LAST]; | 234 | hda_nid_t input_pins[AUTO_PIN_LAST]; |
229 | hda_nid_t dig_out_pin; | 235 | hda_nid_t dig_out_pin; |
230 | hda_nid_t dig_in_pin; | 236 | hda_nid_t dig_in_pin; |
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index c2f0fe85bf35..d737f17695a3 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c | |||
@@ -52,10 +52,9 @@ static void print_amp_caps(struct snd_info_buffer *buffer, | |||
52 | struct hda_codec *codec, hda_nid_t nid, int dir) | 52 | struct hda_codec *codec, hda_nid_t nid, int dir) |
53 | { | 53 | { |
54 | unsigned int caps; | 54 | unsigned int caps; |
55 | if (dir == HDA_OUTPUT) | 55 | caps = snd_hda_param_read(codec, nid, |
56 | caps = snd_hda_param_read(codec, nid, AC_PAR_AMP_OUT_CAP); | 56 | dir == HDA_OUTPUT ? |
57 | else | 57 | AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP); |
58 | caps = snd_hda_param_read(codec, nid, AC_PAR_AMP_IN_CAP); | ||
59 | if (caps == -1 || caps == 0) { | 58 | if (caps == -1 || caps == 0) { |
60 | snd_iprintf(buffer, "N/A\n"); | 59 | snd_iprintf(buffer, "N/A\n"); |
61 | return; | 60 | return; |
@@ -74,10 +73,7 @@ static void print_amp_vals(struct snd_info_buffer *buffer, | |||
74 | unsigned int val; | 73 | unsigned int val; |
75 | int i; | 74 | int i; |
76 | 75 | ||
77 | if (dir == HDA_OUTPUT) | 76 | dir = dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT; |
78 | dir = AC_AMP_GET_OUTPUT; | ||
79 | else | ||
80 | dir = AC_AMP_GET_INPUT; | ||
81 | for (i = 0; i < indices; i++) { | 77 | for (i = 0; i < indices; i++) { |
82 | snd_iprintf(buffer, " ["); | 78 | snd_iprintf(buffer, " ["); |
83 | if (stereo) { | 79 | if (stereo) { |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 6823f2bc10b3..511df07fa2a3 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -488,9 +488,13 @@ static struct snd_kcontrol_new ad1986a_mixers[] = { | |||
488 | { | 488 | { |
489 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 489 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
490 | .name = "PCM Playback Volume", | 490 | .name = "PCM Playback Volume", |
491 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
492 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | | ||
493 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, | ||
491 | .info = ad1986a_pcm_amp_vol_info, | 494 | .info = ad1986a_pcm_amp_vol_info, |
492 | .get = ad1986a_pcm_amp_vol_get, | 495 | .get = ad1986a_pcm_amp_vol_get, |
493 | .put = ad1986a_pcm_amp_vol_put, | 496 | .put = ad1986a_pcm_amp_vol_put, |
497 | .tlv = { .c = snd_hda_mixer_amp_tlv }, | ||
494 | .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT) | 498 | .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT) |
495 | }, | 499 | }, |
496 | { | 500 | { |
@@ -637,6 +641,7 @@ static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = { | |||
637 | .info = snd_hda_mixer_amp_volume_info, | 641 | .info = snd_hda_mixer_amp_volume_info, |
638 | .get = snd_hda_mixer_amp_volume_get, | 642 | .get = snd_hda_mixer_amp_volume_get, |
639 | .put = ad1986a_laptop_master_vol_put, | 643 | .put = ad1986a_laptop_master_vol_put, |
644 | .tlv = { .c = snd_hda_mixer_amp_tlv }, | ||
640 | .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT), | 645 | .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT), |
641 | }, | 646 | }, |
642 | { | 647 | { |
@@ -791,6 +796,8 @@ static struct hda_board_config ad1986a_cfg_tbl[] = { | |||
791 | .config = AD1986A_3STACK }, /* ASUS A8N-VM CSM */ | 796 | .config = AD1986A_3STACK }, /* ASUS A8N-VM CSM */ |
792 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x81b3, | 797 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x81b3, |
793 | .config = AD1986A_3STACK }, /* ASUS P5RD2-VM / P5GPL-X SE */ | 798 | .config = AD1986A_3STACK }, /* ASUS P5RD2-VM / P5GPL-X SE */ |
799 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x81cb, | ||
800 | .config = AD1986A_3STACK }, /* ASUS M2NPV-VM */ | ||
794 | { .modelname = "laptop", .config = AD1986A_LAPTOP }, | 801 | { .modelname = "laptop", .config = AD1986A_LAPTOP }, |
795 | { .pci_subvendor = 0x144d, .pci_subdevice = 0xc01e, | 802 | { .pci_subvendor = 0x144d, .pci_subdevice = 0xc01e, |
796 | .config = AD1986A_LAPTOP }, /* FSC V2060 */ | 803 | .config = AD1986A_LAPTOP }, /* FSC V2060 */ |
@@ -803,6 +810,8 @@ static struct hda_board_config ad1986a_cfg_tbl[] = { | |||
803 | .config = AD1986A_LAPTOP_EAPD }, /* Samsung X60 Chane */ | 810 | .config = AD1986A_LAPTOP_EAPD }, /* Samsung X60 Chane */ |
804 | { .pci_subvendor = 0x144d, .pci_subdevice = 0xc024, | 811 | { .pci_subvendor = 0x144d, .pci_subdevice = 0xc024, |
805 | .config = AD1986A_LAPTOP_EAPD }, /* Samsung R65-T2300 Charis */ | 812 | .config = AD1986A_LAPTOP_EAPD }, /* Samsung R65-T2300 Charis */ |
813 | { .pci_subvendor = 0x144d, .pci_subdevice = 0xc026, | ||
814 | .config = AD1986A_LAPTOP_EAPD }, /* Samsung X10-T2300 Culesa */ | ||
806 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1153, | 815 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1153, |
807 | .config = AD1986A_LAPTOP_EAPD }, /* ASUS M9 */ | 816 | .config = AD1986A_LAPTOP_EAPD }, /* ASUS M9 */ |
808 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1213, | 817 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1213, |
@@ -1626,10 +1635,12 @@ static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol, | |||
1626 | { | 1635 | { |
1627 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1636 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1628 | struct ad198x_spec *spec = codec->spec; | 1637 | struct ad198x_spec *spec = codec->spec; |
1629 | if (spec->need_dac_fix) | 1638 | int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, |
1639 | spec->num_channel_mode, | ||
1640 | &spec->multiout.max_channels); | ||
1641 | if (! err && spec->need_dac_fix) | ||
1630 | spec->multiout.num_dacs = spec->multiout.max_channels / 2; | 1642 | spec->multiout.num_dacs = spec->multiout.max_channels / 2; |
1631 | return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, | 1643 | return err; |
1632 | spec->num_channel_mode, &spec->multiout.max_channels); | ||
1633 | } | 1644 | } |
1634 | 1645 | ||
1635 | /* 6-stack mode */ | 1646 | /* 6-stack mode */ |
@@ -2460,7 +2471,7 @@ static void ad1988_auto_init_extra_out(struct hda_codec *codec) | |||
2460 | pin = spec->autocfg.speaker_pins[0]; | 2471 | pin = spec->autocfg.speaker_pins[0]; |
2461 | if (pin) /* connect to front */ | 2472 | if (pin) /* connect to front */ |
2462 | ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); | 2473 | ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); |
2463 | pin = spec->autocfg.hp_pin; | 2474 | pin = spec->autocfg.hp_pins[0]; |
2464 | if (pin) /* connect to front */ | 2475 | if (pin) /* connect to front */ |
2465 | ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); | 2476 | ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); |
2466 | } | 2477 | } |
@@ -2512,7 +2523,7 @@ static int ad1988_parse_auto_config(struct hda_codec *codec) | |||
2512 | (err = ad1988_auto_create_extra_out(codec, | 2523 | (err = ad1988_auto_create_extra_out(codec, |
2513 | spec->autocfg.speaker_pins[0], | 2524 | spec->autocfg.speaker_pins[0], |
2514 | "Speaker")) < 0 || | 2525 | "Speaker")) < 0 || |
2515 | (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pin, | 2526 | (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0], |
2516 | "Headphone")) < 0 || | 2527 | "Headphone")) < 0 || |
2517 | (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) | 2528 | (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) |
2518 | return err; | 2529 | return err; |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 18d105263fea..d08d2e399c8f 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -79,6 +79,7 @@ enum { | |||
79 | ALC262_BASIC, | 79 | ALC262_BASIC, |
80 | ALC262_FUJITSU, | 80 | ALC262_FUJITSU, |
81 | ALC262_HP_BPC, | 81 | ALC262_HP_BPC, |
82 | ALC262_BENQ_ED8, | ||
82 | ALC262_AUTO, | 83 | ALC262_AUTO, |
83 | ALC262_MODEL_LAST /* last tag */ | 84 | ALC262_MODEL_LAST /* last tag */ |
84 | }; | 85 | }; |
@@ -89,6 +90,7 @@ enum { | |||
89 | ALC660_3ST, | 90 | ALC660_3ST, |
90 | ALC861_3ST_DIG, | 91 | ALC861_3ST_DIG, |
91 | ALC861_6ST_DIG, | 92 | ALC861_6ST_DIG, |
93 | ALC861_UNIWILL_M31, | ||
92 | ALC861_AUTO, | 94 | ALC861_AUTO, |
93 | ALC861_MODEL_LAST, | 95 | ALC861_MODEL_LAST, |
94 | }; | 96 | }; |
@@ -97,6 +99,7 @@ enum { | |||
97 | enum { | 99 | enum { |
98 | ALC882_3ST_DIG, | 100 | ALC882_3ST_DIG, |
99 | ALC882_6ST_DIG, | 101 | ALC882_6ST_DIG, |
102 | ALC882_ARIMA, | ||
100 | ALC882_AUTO, | 103 | ALC882_AUTO, |
101 | ALC882_MODEL_LAST, | 104 | ALC882_MODEL_LAST, |
102 | }; | 105 | }; |
@@ -108,6 +111,7 @@ enum { | |||
108 | ALC883_3ST_6ch, | 111 | ALC883_3ST_6ch, |
109 | ALC883_6ST_DIG, | 112 | ALC883_6ST_DIG, |
110 | ALC888_DEMO_BOARD, | 113 | ALC888_DEMO_BOARD, |
114 | ALC883_ACER, | ||
111 | ALC883_AUTO, | 115 | ALC883_AUTO, |
112 | ALC883_MODEL_LAST, | 116 | ALC883_MODEL_LAST, |
113 | }; | 117 | }; |
@@ -153,6 +157,7 @@ struct alc_spec { | |||
153 | /* channel model */ | 157 | /* channel model */ |
154 | const struct hda_channel_mode *channel_mode; | 158 | const struct hda_channel_mode *channel_mode; |
155 | int num_channel_mode; | 159 | int num_channel_mode; |
160 | int need_dac_fix; | ||
156 | 161 | ||
157 | /* PCM information */ | 162 | /* PCM information */ |
158 | struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */ | 163 | struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */ |
@@ -190,6 +195,7 @@ struct alc_config_preset { | |||
190 | hda_nid_t dig_in_nid; | 195 | hda_nid_t dig_in_nid; |
191 | unsigned int num_channel_mode; | 196 | unsigned int num_channel_mode; |
192 | const struct hda_channel_mode *channel_mode; | 197 | const struct hda_channel_mode *channel_mode; |
198 | int need_dac_fix; | ||
193 | unsigned int num_mux_defs; | 199 | unsigned int num_mux_defs; |
194 | const struct hda_input_mux *input_mux; | 200 | const struct hda_input_mux *input_mux; |
195 | void (*unsol_event)(struct hda_codec *, unsigned int); | 201 | void (*unsol_event)(struct hda_codec *, unsigned int); |
@@ -262,9 +268,12 @@ static int alc_ch_mode_put(struct snd_kcontrol *kcontrol, | |||
262 | { | 268 | { |
263 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 269 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
264 | struct alc_spec *spec = codec->spec; | 270 | struct alc_spec *spec = codec->spec; |
265 | return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, | 271 | int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, |
266 | spec->num_channel_mode, | 272 | spec->num_channel_mode, |
267 | &spec->multiout.max_channels); | 273 | &spec->multiout.max_channels); |
274 | if (! err && spec->need_dac_fix) | ||
275 | spec->multiout.num_dacs = spec->multiout.max_channels / 2; | ||
276 | return err; | ||
268 | } | 277 | } |
269 | 278 | ||
270 | /* | 279 | /* |
@@ -544,6 +553,7 @@ static void setup_preset(struct alc_spec *spec, | |||
544 | 553 | ||
545 | spec->channel_mode = preset->channel_mode; | 554 | spec->channel_mode = preset->channel_mode; |
546 | spec->num_channel_mode = preset->num_channel_mode; | 555 | spec->num_channel_mode = preset->num_channel_mode; |
556 | spec->need_dac_fix = preset->need_dac_fix; | ||
547 | 557 | ||
548 | spec->multiout.max_channels = spec->channel_mode[0].channels; | 558 | spec->multiout.max_channels = spec->channel_mode[0].channels; |
549 | 559 | ||
@@ -1348,6 +1358,10 @@ static struct hda_verb alc880_pin_clevo_init_verbs[] = { | |||
1348 | }; | 1358 | }; |
1349 | 1359 | ||
1350 | static struct hda_verb alc880_pin_tcl_S700_init_verbs[] = { | 1360 | static struct hda_verb alc880_pin_tcl_S700_init_verbs[] = { |
1361 | /* change to EAPD mode */ | ||
1362 | {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, | ||
1363 | {0x20, AC_VERB_SET_PROC_COEF, 0x3060}, | ||
1364 | |||
1351 | /* Headphone output */ | 1365 | /* Headphone output */ |
1352 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | 1366 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, |
1353 | /* Front output*/ | 1367 | /* Front output*/ |
@@ -1782,25 +1796,9 @@ static int alc_build_pcms(struct hda_codec *codec) | |||
1782 | } | 1796 | } |
1783 | } | 1797 | } |
1784 | 1798 | ||
1785 | /* If the use of more than one ADC is requested for the current | 1799 | /* SPDIF for stream index #1 */ |
1786 | * model, configure a second analog capture-only PCM. | ||
1787 | */ | ||
1788 | if (spec->num_adc_nids > 1) { | ||
1789 | codec->num_pcms++; | ||
1790 | info++; | ||
1791 | info->name = spec->stream_name_analog; | ||
1792 | /* No playback stream for second PCM */ | ||
1793 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = alc_pcm_null_playback; | ||
1794 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0; | ||
1795 | if (spec->stream_analog_capture) { | ||
1796 | snd_assert(spec->adc_nids, return -EINVAL); | ||
1797 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture); | ||
1798 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[1]; | ||
1799 | } | ||
1800 | } | ||
1801 | |||
1802 | if (spec->multiout.dig_out_nid || spec->dig_in_nid) { | 1800 | if (spec->multiout.dig_out_nid || spec->dig_in_nid) { |
1803 | codec->num_pcms++; | 1801 | codec->num_pcms = 2; |
1804 | info++; | 1802 | info++; |
1805 | info->name = spec->stream_name_digital; | 1803 | info->name = spec->stream_name_digital; |
1806 | if (spec->multiout.dig_out_nid && | 1804 | if (spec->multiout.dig_out_nid && |
@@ -1815,6 +1813,24 @@ static int alc_build_pcms(struct hda_codec *codec) | |||
1815 | } | 1813 | } |
1816 | } | 1814 | } |
1817 | 1815 | ||
1816 | /* If the use of more than one ADC is requested for the current | ||
1817 | * model, configure a second analog capture-only PCM. | ||
1818 | */ | ||
1819 | /* Additional Analaog capture for index #2 */ | ||
1820 | if (spec->num_adc_nids > 1 && spec->stream_analog_capture && | ||
1821 | spec->adc_nids) { | ||
1822 | codec->num_pcms = 3; | ||
1823 | info++; | ||
1824 | info->name = spec->stream_name_analog; | ||
1825 | /* No playback stream for second PCM */ | ||
1826 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = alc_pcm_null_playback; | ||
1827 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0; | ||
1828 | if (spec->stream_analog_capture) { | ||
1829 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture); | ||
1830 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[1]; | ||
1831 | } | ||
1832 | } | ||
1833 | |||
1818 | return 0; | 1834 | return 0; |
1819 | } | 1835 | } |
1820 | 1836 | ||
@@ -2130,7 +2146,10 @@ static struct hda_board_config alc880_cfg_tbl[] = { | |||
2130 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20f, .config = ALC880_3ST }, | 2146 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20f, .config = ALC880_3ST }, |
2131 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe210, .config = ALC880_3ST }, | 2147 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe210, .config = ALC880_3ST }, |
2132 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe211, .config = ALC880_3ST }, | 2148 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe211, .config = ALC880_3ST }, |
2149 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe212, .config = ALC880_3ST }, | ||
2150 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe213, .config = ALC880_3ST }, | ||
2133 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe214, .config = ALC880_3ST }, | 2151 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe214, .config = ALC880_3ST }, |
2152 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe234, .config = ALC880_3ST }, | ||
2134 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe302, .config = ALC880_3ST }, | 2153 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe302, .config = ALC880_3ST }, |
2135 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe303, .config = ALC880_3ST }, | 2154 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe303, .config = ALC880_3ST }, |
2136 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe304, .config = ALC880_3ST }, | 2155 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe304, .config = ALC880_3ST }, |
@@ -2145,6 +2164,7 @@ static struct hda_board_config alc880_cfg_tbl[] = { | |||
2145 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x4040, .config = ALC880_3ST }, | 2164 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x4040, .config = ALC880_3ST }, |
2146 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x4041, .config = ALC880_3ST }, | 2165 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x4041, .config = ALC880_3ST }, |
2147 | /* TCL S700 */ | 2166 | /* TCL S700 */ |
2167 | { .modelname = "tcl", .config = ALC880_TCL_S700 }, | ||
2148 | { .pci_subvendor = 0x19db, .pci_subdevice = 0x4188, .config = ALC880_TCL_S700 }, | 2168 | { .pci_subvendor = 0x19db, .pci_subdevice = 0x4188, .config = ALC880_TCL_S700 }, |
2149 | 2169 | ||
2150 | /* Back 3 jack, front 2 jack (Internal add Aux-In) */ | 2170 | /* Back 3 jack, front 2 jack (Internal add Aux-In) */ |
@@ -2156,8 +2176,13 @@ static struct hda_board_config alc880_cfg_tbl[] = { | |||
2156 | { .modelname = "3stack-digout", .config = ALC880_3ST_DIG }, | 2176 | { .modelname = "3stack-digout", .config = ALC880_3ST_DIG }, |
2157 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe308, .config = ALC880_3ST_DIG }, | 2177 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe308, .config = ALC880_3ST_DIG }, |
2158 | { .pci_subvendor = 0x1025, .pci_subdevice = 0x0070, .config = ALC880_3ST_DIG }, | 2178 | { .pci_subvendor = 0x1025, .pci_subdevice = 0x0070, .config = ALC880_3ST_DIG }, |
2159 | /* Clevo m520G NB */ | 2179 | |
2160 | { .pci_subvendor = 0x1558, .pci_subdevice = 0x0520, .config = ALC880_CLEVO }, | 2180 | /* Clevo laptops */ |
2181 | { .modelname = "clevo", .config = ALC880_CLEVO }, | ||
2182 | { .pci_subvendor = 0x1558, .pci_subdevice = 0x0520, | ||
2183 | .config = ALC880_CLEVO }, /* Clevo m520G NB */ | ||
2184 | { .pci_subvendor = 0x1558, .pci_subdevice = 0x0660, | ||
2185 | .config = ALC880_CLEVO }, /* Clevo m665n */ | ||
2161 | 2186 | ||
2162 | /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/ | 2187 | /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/ |
2163 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe305, .config = ALC880_3ST_DIG }, | 2188 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe305, .config = ALC880_3ST_DIG }, |
@@ -2222,12 +2247,16 @@ static struct hda_board_config alc880_cfg_tbl[] = { | |||
2222 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1113, .config = ALC880_ASUS_DIG }, | 2247 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1113, .config = ALC880_ASUS_DIG }, |
2223 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1173, .config = ALC880_ASUS_DIG }, | 2248 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1173, .config = ALC880_ASUS_DIG }, |
2224 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1993, .config = ALC880_ASUS }, | 2249 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1993, .config = ALC880_ASUS }, |
2250 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x10c2, .config = ALC880_ASUS_DIG }, /* Asus W6A */ | ||
2225 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x10c3, .config = ALC880_ASUS_DIG }, | 2251 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x10c3, .config = ALC880_ASUS_DIG }, |
2226 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1133, .config = ALC880_ASUS }, | 2252 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1133, .config = ALC880_ASUS }, |
2227 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1123, .config = ALC880_ASUS_DIG }, | 2253 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1123, .config = ALC880_ASUS_DIG }, |
2228 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1143, .config = ALC880_ASUS }, | 2254 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1143, .config = ALC880_ASUS }, |
2255 | { .modelname = "asus-w1v", .config = ALC880_ASUS_W1V }, | ||
2229 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x10b3, .config = ALC880_ASUS_W1V }, | 2256 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x10b3, .config = ALC880_ASUS_W1V }, |
2257 | { .modelname = "asus-dig", .config = ALC880_ASUS_DIG }, | ||
2230 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x8181, .config = ALC880_ASUS_DIG }, /* ASUS P4GPL-X */ | 2258 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x8181, .config = ALC880_ASUS_DIG }, /* ASUS P4GPL-X */ |
2259 | { .modelname = "asus-dig2", .config = ALC880_ASUS_DIG2 }, | ||
2231 | { .pci_subvendor = 0x1558, .pci_subdevice = 0x5401, .config = ALC880_ASUS_DIG2 }, | 2260 | { .pci_subvendor = 0x1558, .pci_subdevice = 0x5401, .config = ALC880_ASUS_DIG2 }, |
2232 | 2261 | ||
2233 | { .modelname = "uniwill", .config = ALC880_UNIWILL_DIG }, | 2262 | { .modelname = "uniwill", .config = ALC880_UNIWILL_DIG }, |
@@ -2243,6 +2272,7 @@ static struct hda_board_config alc880_cfg_tbl[] = { | |||
2243 | 2272 | ||
2244 | { .modelname = "lg-lw", .config = ALC880_LG_LW }, | 2273 | { .modelname = "lg-lw", .config = ALC880_LG_LW }, |
2245 | { .pci_subvendor = 0x1854, .pci_subdevice = 0x0018, .config = ALC880_LG_LW }, | 2274 | { .pci_subvendor = 0x1854, .pci_subdevice = 0x0018, .config = ALC880_LG_LW }, |
2275 | { .pci_subvendor = 0x1854, .pci_subdevice = 0x0077, .config = ALC880_LG_LW }, | ||
2246 | 2276 | ||
2247 | #ifdef CONFIG_SND_DEBUG | 2277 | #ifdef CONFIG_SND_DEBUG |
2248 | { .modelname = "test", .config = ALC880_TEST }, | 2278 | { .modelname = "test", .config = ALC880_TEST }, |
@@ -2263,6 +2293,7 @@ static struct alc_config_preset alc880_presets[] = { | |||
2263 | .dac_nids = alc880_dac_nids, | 2293 | .dac_nids = alc880_dac_nids, |
2264 | .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), | 2294 | .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), |
2265 | .channel_mode = alc880_threestack_modes, | 2295 | .channel_mode = alc880_threestack_modes, |
2296 | .need_dac_fix = 1, | ||
2266 | .input_mux = &alc880_capture_source, | 2297 | .input_mux = &alc880_capture_source, |
2267 | }, | 2298 | }, |
2268 | [ALC880_3ST_DIG] = { | 2299 | [ALC880_3ST_DIG] = { |
@@ -2273,6 +2304,7 @@ static struct alc_config_preset alc880_presets[] = { | |||
2273 | .dig_out_nid = ALC880_DIGOUT_NID, | 2304 | .dig_out_nid = ALC880_DIGOUT_NID, |
2274 | .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), | 2305 | .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), |
2275 | .channel_mode = alc880_threestack_modes, | 2306 | .channel_mode = alc880_threestack_modes, |
2307 | .need_dac_fix = 1, | ||
2276 | .input_mux = &alc880_capture_source, | 2308 | .input_mux = &alc880_capture_source, |
2277 | }, | 2309 | }, |
2278 | [ALC880_TCL_S700] = { | 2310 | [ALC880_TCL_S700] = { |
@@ -2365,6 +2397,7 @@ static struct alc_config_preset alc880_presets[] = { | |||
2365 | .dac_nids = alc880_asus_dac_nids, | 2397 | .dac_nids = alc880_asus_dac_nids, |
2366 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), | 2398 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), |
2367 | .channel_mode = alc880_asus_modes, | 2399 | .channel_mode = alc880_asus_modes, |
2400 | .need_dac_fix = 1, | ||
2368 | .input_mux = &alc880_capture_source, | 2401 | .input_mux = &alc880_capture_source, |
2369 | }, | 2402 | }, |
2370 | [ALC880_ASUS_DIG] = { | 2403 | [ALC880_ASUS_DIG] = { |
@@ -2376,6 +2409,7 @@ static struct alc_config_preset alc880_presets[] = { | |||
2376 | .dig_out_nid = ALC880_DIGOUT_NID, | 2409 | .dig_out_nid = ALC880_DIGOUT_NID, |
2377 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), | 2410 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), |
2378 | .channel_mode = alc880_asus_modes, | 2411 | .channel_mode = alc880_asus_modes, |
2412 | .need_dac_fix = 1, | ||
2379 | .input_mux = &alc880_capture_source, | 2413 | .input_mux = &alc880_capture_source, |
2380 | }, | 2414 | }, |
2381 | [ALC880_ASUS_DIG2] = { | 2415 | [ALC880_ASUS_DIG2] = { |
@@ -2387,6 +2421,7 @@ static struct alc_config_preset alc880_presets[] = { | |||
2387 | .dig_out_nid = ALC880_DIGOUT_NID, | 2421 | .dig_out_nid = ALC880_DIGOUT_NID, |
2388 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), | 2422 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), |
2389 | .channel_mode = alc880_asus_modes, | 2423 | .channel_mode = alc880_asus_modes, |
2424 | .need_dac_fix = 1, | ||
2390 | .input_mux = &alc880_capture_source, | 2425 | .input_mux = &alc880_capture_source, |
2391 | }, | 2426 | }, |
2392 | [ALC880_ASUS_W1V] = { | 2427 | [ALC880_ASUS_W1V] = { |
@@ -2398,6 +2433,7 @@ static struct alc_config_preset alc880_presets[] = { | |||
2398 | .dig_out_nid = ALC880_DIGOUT_NID, | 2433 | .dig_out_nid = ALC880_DIGOUT_NID, |
2399 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), | 2434 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), |
2400 | .channel_mode = alc880_asus_modes, | 2435 | .channel_mode = alc880_asus_modes, |
2436 | .need_dac_fix = 1, | ||
2401 | .input_mux = &alc880_capture_source, | 2437 | .input_mux = &alc880_capture_source, |
2402 | }, | 2438 | }, |
2403 | [ALC880_UNIWILL_DIG] = { | 2439 | [ALC880_UNIWILL_DIG] = { |
@@ -2408,6 +2444,7 @@ static struct alc_config_preset alc880_presets[] = { | |||
2408 | .dig_out_nid = ALC880_DIGOUT_NID, | 2444 | .dig_out_nid = ALC880_DIGOUT_NID, |
2409 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), | 2445 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), |
2410 | .channel_mode = alc880_asus_modes, | 2446 | .channel_mode = alc880_asus_modes, |
2447 | .need_dac_fix = 1, | ||
2411 | .input_mux = &alc880_capture_source, | 2448 | .input_mux = &alc880_capture_source, |
2412 | }, | 2449 | }, |
2413 | [ALC880_CLEVO] = { | 2450 | [ALC880_CLEVO] = { |
@@ -2419,6 +2456,7 @@ static struct alc_config_preset alc880_presets[] = { | |||
2419 | .hp_nid = 0x03, | 2456 | .hp_nid = 0x03, |
2420 | .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), | 2457 | .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), |
2421 | .channel_mode = alc880_threestack_modes, | 2458 | .channel_mode = alc880_threestack_modes, |
2459 | .need_dac_fix = 1, | ||
2422 | .input_mux = &alc880_capture_source, | 2460 | .input_mux = &alc880_capture_source, |
2423 | }, | 2461 | }, |
2424 | [ALC880_LG] = { | 2462 | [ALC880_LG] = { |
@@ -2430,6 +2468,7 @@ static struct alc_config_preset alc880_presets[] = { | |||
2430 | .dig_out_nid = ALC880_DIGOUT_NID, | 2468 | .dig_out_nid = ALC880_DIGOUT_NID, |
2431 | .num_channel_mode = ARRAY_SIZE(alc880_lg_ch_modes), | 2469 | .num_channel_mode = ARRAY_SIZE(alc880_lg_ch_modes), |
2432 | .channel_mode = alc880_lg_ch_modes, | 2470 | .channel_mode = alc880_lg_ch_modes, |
2471 | .need_dac_fix = 1, | ||
2433 | .input_mux = &alc880_lg_capture_source, | 2472 | .input_mux = &alc880_lg_capture_source, |
2434 | .unsol_event = alc880_lg_unsol_event, | 2473 | .unsol_event = alc880_lg_unsol_event, |
2435 | .init_hook = alc880_lg_automute, | 2474 | .init_hook = alc880_lg_automute, |
@@ -2714,7 +2753,7 @@ static void alc880_auto_init_extra_out(struct hda_codec *codec) | |||
2714 | pin = spec->autocfg.speaker_pins[0]; | 2753 | pin = spec->autocfg.speaker_pins[0]; |
2715 | if (pin) /* connect to front */ | 2754 | if (pin) /* connect to front */ |
2716 | alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); | 2755 | alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); |
2717 | pin = spec->autocfg.hp_pin; | 2756 | pin = spec->autocfg.hp_pins[0]; |
2718 | if (pin) /* connect to front */ | 2757 | if (pin) /* connect to front */ |
2719 | alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); | 2758 | alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); |
2720 | } | 2759 | } |
@@ -2755,7 +2794,7 @@ static int alc880_parse_auto_config(struct hda_codec *codec) | |||
2755 | (err = alc880_auto_create_extra_out(spec, | 2794 | (err = alc880_auto_create_extra_out(spec, |
2756 | spec->autocfg.speaker_pins[0], | 2795 | spec->autocfg.speaker_pins[0], |
2757 | "Speaker")) < 0 || | 2796 | "Speaker")) < 0 || |
2758 | (err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pin, | 2797 | (err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0], |
2759 | "Headphone")) < 0 || | 2798 | "Headphone")) < 0 || |
2760 | (err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) | 2799 | (err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) |
2761 | return err; | 2800 | return err; |
@@ -3697,7 +3736,7 @@ static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
3697 | return err; | 3736 | return err; |
3698 | } | 3737 | } |
3699 | 3738 | ||
3700 | nid = cfg->hp_pin; | 3739 | nid = cfg->hp_pins[0]; |
3701 | if (nid) { | 3740 | if (nid) { |
3702 | err = alc260_add_playback_controls(spec, nid, "Headphone"); | 3741 | err = alc260_add_playback_controls(spec, nid, "Headphone"); |
3703 | if (err < 0) | 3742 | if (err < 0) |
@@ -3767,7 +3806,7 @@ static void alc260_auto_init_multi_out(struct hda_codec *codec) | |||
3767 | if (nid) | 3806 | if (nid) |
3768 | alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); | 3807 | alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); |
3769 | 3808 | ||
3770 | nid = spec->autocfg.hp_pin; | 3809 | nid = spec->autocfg.hp_pins[0]; |
3771 | if (nid) | 3810 | if (nid) |
3772 | alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); | 3811 | alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); |
3773 | } | 3812 | } |
@@ -3900,7 +3939,8 @@ static struct hda_board_config alc260_cfg_tbl[] = { | |||
3900 | { .pci_subvendor = 0x152d, .pci_subdevice = 0x0729, | 3939 | { .pci_subvendor = 0x152d, .pci_subdevice = 0x0729, |
3901 | .config = ALC260_BASIC }, /* CTL Travel Master U553W */ | 3940 | .config = ALC260_BASIC }, /* CTL Travel Master U553W */ |
3902 | { .modelname = "hp", .config = ALC260_HP }, | 3941 | { .modelname = "hp", .config = ALC260_HP }, |
3903 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3010, .config = ALC260_HP }, | 3942 | { .modelname = "hp-3013", .config = ALC260_HP_3013 }, |
3943 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3010, .config = ALC260_HP_3013 }, | ||
3904 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3011, .config = ALC260_HP }, | 3944 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3011, .config = ALC260_HP }, |
3905 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3012, .config = ALC260_HP_3013 }, | 3945 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3012, .config = ALC260_HP_3013 }, |
3906 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3013, .config = ALC260_HP_3013 }, | 3946 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3013, .config = ALC260_HP_3013 }, |
@@ -4266,6 +4306,13 @@ static struct hda_verb alc882_init_verbs[] = { | |||
4266 | { } | 4306 | { } |
4267 | }; | 4307 | }; |
4268 | 4308 | ||
4309 | static struct hda_verb alc882_eapd_verbs[] = { | ||
4310 | /* change to EAPD mode */ | ||
4311 | {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, | ||
4312 | {0x20, AC_VERB_SET_PROC_COEF, 0x3060}, | ||
4313 | { } | ||
4314 | }; | ||
4315 | |||
4269 | /* | 4316 | /* |
4270 | * generic initialization of ADC, input mixers and output mixers | 4317 | * generic initialization of ADC, input mixers and output mixers |
4271 | */ | 4318 | */ |
@@ -4397,6 +4444,9 @@ static struct hda_board_config alc882_cfg_tbl[] = { | |||
4397 | .config = ALC882_6ST_DIG }, /* Foxconn */ | 4444 | .config = ALC882_6ST_DIG }, /* Foxconn */ |
4398 | { .pci_subvendor = 0x1019, .pci_subdevice = 0x6668, | 4445 | { .pci_subvendor = 0x1019, .pci_subdevice = 0x6668, |
4399 | .config = ALC882_6ST_DIG }, /* ECS to Intel*/ | 4446 | .config = ALC882_6ST_DIG }, /* ECS to Intel*/ |
4447 | { .modelname = "arima", .config = ALC882_ARIMA }, | ||
4448 | { .pci_subvendor = 0x161f, .pci_subdevice = 0x2054, | ||
4449 | .config = ALC882_ARIMA }, /* Arima W820Di1 */ | ||
4400 | { .modelname = "auto", .config = ALC882_AUTO }, | 4450 | { .modelname = "auto", .config = ALC882_AUTO }, |
4401 | {} | 4451 | {} |
4402 | }; | 4452 | }; |
@@ -4411,6 +4461,7 @@ static struct alc_config_preset alc882_presets[] = { | |||
4411 | .dig_in_nid = ALC882_DIGIN_NID, | 4461 | .dig_in_nid = ALC882_DIGIN_NID, |
4412 | .num_channel_mode = ARRAY_SIZE(alc882_ch_modes), | 4462 | .num_channel_mode = ARRAY_SIZE(alc882_ch_modes), |
4413 | .channel_mode = alc882_ch_modes, | 4463 | .channel_mode = alc882_ch_modes, |
4464 | .need_dac_fix = 1, | ||
4414 | .input_mux = &alc882_capture_source, | 4465 | .input_mux = &alc882_capture_source, |
4415 | }, | 4466 | }, |
4416 | [ALC882_6ST_DIG] = { | 4467 | [ALC882_6ST_DIG] = { |
@@ -4424,6 +4475,15 @@ static struct alc_config_preset alc882_presets[] = { | |||
4424 | .channel_mode = alc882_sixstack_modes, | 4475 | .channel_mode = alc882_sixstack_modes, |
4425 | .input_mux = &alc882_capture_source, | 4476 | .input_mux = &alc882_capture_source, |
4426 | }, | 4477 | }, |
4478 | [ALC882_ARIMA] = { | ||
4479 | .mixers = { alc882_base_mixer, alc882_chmode_mixer }, | ||
4480 | .init_verbs = { alc882_init_verbs, alc882_eapd_verbs }, | ||
4481 | .num_dacs = ARRAY_SIZE(alc882_dac_nids), | ||
4482 | .dac_nids = alc882_dac_nids, | ||
4483 | .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes), | ||
4484 | .channel_mode = alc882_sixstack_modes, | ||
4485 | .input_mux = &alc882_capture_source, | ||
4486 | }, | ||
4427 | }; | 4487 | }; |
4428 | 4488 | ||
4429 | 4489 | ||
@@ -4466,7 +4526,7 @@ static void alc882_auto_init_hp_out(struct hda_codec *codec) | |||
4466 | struct alc_spec *spec = codec->spec; | 4526 | struct alc_spec *spec = codec->spec; |
4467 | hda_nid_t pin; | 4527 | hda_nid_t pin; |
4468 | 4528 | ||
4469 | pin = spec->autocfg.hp_pin; | 4529 | pin = spec->autocfg.hp_pins[0]; |
4470 | if (pin) /* connect to front */ | 4530 | if (pin) /* connect to front */ |
4471 | alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); /* use dac 0 */ | 4531 | alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); /* use dac 0 */ |
4472 | } | 4532 | } |
@@ -4999,16 +5059,23 @@ static struct snd_kcontrol_new alc883_capture_mixer[] = { | |||
4999 | */ | 5059 | */ |
5000 | static struct hda_board_config alc883_cfg_tbl[] = { | 5060 | static struct hda_board_config alc883_cfg_tbl[] = { |
5001 | { .modelname = "3stack-dig", .config = ALC883_3ST_2ch_DIG }, | 5061 | { .modelname = "3stack-dig", .config = ALC883_3ST_2ch_DIG }, |
5062 | { .modelname = "3stack-6ch-dig", .config = ALC883_3ST_6ch_DIG }, | ||
5063 | { .pci_subvendor = 0x1019, .pci_subdevice = 0x6668, | ||
5064 | .config = ALC883_3ST_6ch_DIG }, /* ECS to Intel*/ | ||
5065 | { .modelname = "3stack-6ch", .config = ALC883_3ST_6ch }, | ||
5066 | { .pci_subvendor = 0x108e, .pci_subdevice = 0x534d, | ||
5067 | .config = ALC883_3ST_6ch }, | ||
5068 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xd601, | ||
5069 | .config = ALC883_3ST_6ch }, /* D102GGC */ | ||
5002 | { .modelname = "6stack-dig", .config = ALC883_6ST_DIG }, | 5070 | { .modelname = "6stack-dig", .config = ALC883_6ST_DIG }, |
5003 | { .modelname = "6stack-dig-demo", .config = ALC888_DEMO_BOARD }, | ||
5004 | { .pci_subvendor = 0x1462, .pci_subdevice = 0x6668, | 5071 | { .pci_subvendor = 0x1462, .pci_subdevice = 0x6668, |
5005 | .config = ALC883_6ST_DIG }, /* MSI */ | 5072 | .config = ALC883_6ST_DIG }, /* MSI */ |
5006 | { .pci_subvendor = 0x105b, .pci_subdevice = 0x6668, | 5073 | { .pci_subvendor = 0x105b, .pci_subdevice = 0x6668, |
5007 | .config = ALC883_6ST_DIG }, /* Foxconn */ | 5074 | .config = ALC883_6ST_DIG }, /* Foxconn */ |
5008 | { .pci_subvendor = 0x1019, .pci_subdevice = 0x6668, | 5075 | { .modelname = "6stack-dig-demo", .config = ALC888_DEMO_BOARD }, |
5009 | .config = ALC883_3ST_6ch_DIG }, /* ECS to Intel*/ | 5076 | { .modelname = "acer", .config = ALC883_ACER }, |
5010 | { .pci_subvendor = 0x108e, .pci_subdevice = 0x534d, | 5077 | { .pci_subvendor = 0x1025, .pci_subdevice = 0/*0x0102*/, |
5011 | .config = ALC883_3ST_6ch }, | 5078 | .config = ALC883_ACER }, |
5012 | { .modelname = "auto", .config = ALC883_AUTO }, | 5079 | { .modelname = "auto", .config = ALC883_AUTO }, |
5013 | {} | 5080 | {} |
5014 | }; | 5081 | }; |
@@ -5038,6 +5105,7 @@ static struct alc_config_preset alc883_presets[] = { | |||
5038 | .dig_in_nid = ALC883_DIGIN_NID, | 5105 | .dig_in_nid = ALC883_DIGIN_NID, |
5039 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes), | 5106 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes), |
5040 | .channel_mode = alc883_3ST_6ch_modes, | 5107 | .channel_mode = alc883_3ST_6ch_modes, |
5108 | .need_dac_fix = 1, | ||
5041 | .input_mux = &alc883_capture_source, | 5109 | .input_mux = &alc883_capture_source, |
5042 | }, | 5110 | }, |
5043 | [ALC883_3ST_6ch] = { | 5111 | [ALC883_3ST_6ch] = { |
@@ -5049,6 +5117,7 @@ static struct alc_config_preset alc883_presets[] = { | |||
5049 | .adc_nids = alc883_adc_nids, | 5117 | .adc_nids = alc883_adc_nids, |
5050 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes), | 5118 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes), |
5051 | .channel_mode = alc883_3ST_6ch_modes, | 5119 | .channel_mode = alc883_3ST_6ch_modes, |
5120 | .need_dac_fix = 1, | ||
5052 | .input_mux = &alc883_capture_source, | 5121 | .input_mux = &alc883_capture_source, |
5053 | }, | 5122 | }, |
5054 | [ALC883_6ST_DIG] = { | 5123 | [ALC883_6ST_DIG] = { |
@@ -5077,6 +5146,23 @@ static struct alc_config_preset alc883_presets[] = { | |||
5077 | .channel_mode = alc883_sixstack_modes, | 5146 | .channel_mode = alc883_sixstack_modes, |
5078 | .input_mux = &alc883_capture_source, | 5147 | .input_mux = &alc883_capture_source, |
5079 | }, | 5148 | }, |
5149 | [ALC883_ACER] = { | ||
5150 | .mixers = { alc883_base_mixer, | ||
5151 | alc883_chmode_mixer }, | ||
5152 | /* On TravelMate laptops, GPIO 0 enables the internal speaker | ||
5153 | * and the headphone jack. Turn this on and rely on the | ||
5154 | * standard mute methods whenever the user wants to turn | ||
5155 | * these outputs off. | ||
5156 | */ | ||
5157 | .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs }, | ||
5158 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | ||
5159 | .dac_nids = alc883_dac_nids, | ||
5160 | .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), | ||
5161 | .adc_nids = alc883_adc_nids, | ||
5162 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), | ||
5163 | .channel_mode = alc883_3ST_2ch_modes, | ||
5164 | .input_mux = &alc883_capture_source, | ||
5165 | }, | ||
5080 | }; | 5166 | }; |
5081 | 5167 | ||
5082 | 5168 | ||
@@ -5121,7 +5207,7 @@ static void alc883_auto_init_hp_out(struct hda_codec *codec) | |||
5121 | struct alc_spec *spec = codec->spec; | 5207 | struct alc_spec *spec = codec->spec; |
5122 | hda_nid_t pin; | 5208 | hda_nid_t pin; |
5123 | 5209 | ||
5124 | pin = spec->autocfg.hp_pin; | 5210 | pin = spec->autocfg.hp_pins[0]; |
5125 | if (pin) /* connect to front */ | 5211 | if (pin) /* connect to front */ |
5126 | /* use dac 0 */ | 5212 | /* use dac 0 */ |
5127 | alc883_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); | 5213 | alc883_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); |
@@ -5217,8 +5303,10 @@ static int patch_alc883(struct hda_codec *codec) | |||
5217 | spec->stream_digital_playback = &alc883_pcm_digital_playback; | 5303 | spec->stream_digital_playback = &alc883_pcm_digital_playback; |
5218 | spec->stream_digital_capture = &alc883_pcm_digital_capture; | 5304 | spec->stream_digital_capture = &alc883_pcm_digital_capture; |
5219 | 5305 | ||
5220 | spec->adc_nids = alc883_adc_nids; | 5306 | if (! spec->adc_nids && spec->input_mux) { |
5221 | spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids); | 5307 | spec->adc_nids = alc883_adc_nids; |
5308 | spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids); | ||
5309 | } | ||
5222 | 5310 | ||
5223 | codec->patch_ops = alc_patch_ops; | 5311 | codec->patch_ops = alc_patch_ops; |
5224 | if (board_config == ALC883_AUTO) | 5312 | if (board_config == ALC883_AUTO) |
@@ -5481,6 +5569,7 @@ static struct snd_kcontrol_new alc262_fujitsu_mixer[] = { | |||
5481 | .info = snd_hda_mixer_amp_volume_info, | 5569 | .info = snd_hda_mixer_amp_volume_info, |
5482 | .get = snd_hda_mixer_amp_volume_get, | 5570 | .get = snd_hda_mixer_amp_volume_get, |
5483 | .put = alc262_fujitsu_master_vol_put, | 5571 | .put = alc262_fujitsu_master_vol_put, |
5572 | .tlv = { .c = snd_hda_mixer_amp_tlv }, | ||
5484 | .private_value = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT), | 5573 | .private_value = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT), |
5485 | }, | 5574 | }, |
5486 | { | 5575 | { |
@@ -5499,6 +5588,13 @@ static struct snd_kcontrol_new alc262_fujitsu_mixer[] = { | |||
5499 | { } /* end */ | 5588 | { } /* end */ |
5500 | }; | 5589 | }; |
5501 | 5590 | ||
5591 | /* additional init verbs for Benq laptops */ | ||
5592 | static struct hda_verb alc262_EAPD_verbs[] = { | ||
5593 | {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, | ||
5594 | {0x20, AC_VERB_SET_PROC_COEF, 0x3070}, | ||
5595 | {} | ||
5596 | }; | ||
5597 | |||
5502 | /* add playback controls from the parsed DAC table */ | 5598 | /* add playback controls from the parsed DAC table */ |
5503 | static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg) | 5599 | static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg) |
5504 | { | 5600 | { |
@@ -5534,7 +5630,7 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct | |||
5534 | return err; | 5630 | return err; |
5535 | } | 5631 | } |
5536 | } | 5632 | } |
5537 | nid = cfg->hp_pin; | 5633 | nid = cfg->hp_pins[0]; |
5538 | if (nid) { | 5634 | if (nid) { |
5539 | /* spec->multiout.hp_nid = 2; */ | 5635 | /* spec->multiout.hp_nid = 2; */ |
5540 | if (nid == 0x16) { | 5636 | if (nid == 0x16) { |
@@ -5769,6 +5865,7 @@ static struct hda_board_config alc262_cfg_tbl[] = { | |||
5769 | { .modelname = "fujitsu", .config = ALC262_FUJITSU }, | 5865 | { .modelname = "fujitsu", .config = ALC262_FUJITSU }, |
5770 | { .pci_subvendor = 0x10cf, .pci_subdevice = 0x1397, | 5866 | { .pci_subvendor = 0x10cf, .pci_subdevice = 0x1397, |
5771 | .config = ALC262_FUJITSU }, | 5867 | .config = ALC262_FUJITSU }, |
5868 | { .modelname = "hp-bpc", .config = ALC262_HP_BPC }, | ||
5772 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x208c, | 5869 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x208c, |
5773 | .config = ALC262_HP_BPC }, /* xw4400 */ | 5870 | .config = ALC262_HP_BPC }, /* xw4400 */ |
5774 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3014, | 5871 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3014, |
@@ -5777,6 +5874,9 @@ static struct hda_board_config alc262_cfg_tbl[] = { | |||
5777 | .config = ALC262_HP_BPC }, /* xw8400 */ | 5874 | .config = ALC262_HP_BPC }, /* xw8400 */ |
5778 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x12fe, | 5875 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x12fe, |
5779 | .config = ALC262_HP_BPC }, /* xw9400 */ | 5876 | .config = ALC262_HP_BPC }, /* xw9400 */ |
5877 | { .modelname = "benq", .config = ALC262_BENQ_ED8 }, | ||
5878 | { .pci_subvendor = 0x17ff, .pci_subdevice = 0x0560, | ||
5879 | .config = ALC262_BENQ_ED8 }, | ||
5780 | { .modelname = "auto", .config = ALC262_AUTO }, | 5880 | { .modelname = "auto", .config = ALC262_AUTO }, |
5781 | {} | 5881 | {} |
5782 | }; | 5882 | }; |
@@ -5814,6 +5914,16 @@ static struct alc_config_preset alc262_presets[] = { | |||
5814 | .channel_mode = alc262_modes, | 5914 | .channel_mode = alc262_modes, |
5815 | .input_mux = &alc262_HP_capture_source, | 5915 | .input_mux = &alc262_HP_capture_source, |
5816 | }, | 5916 | }, |
5917 | [ALC262_BENQ_ED8] = { | ||
5918 | .mixers = { alc262_base_mixer }, | ||
5919 | .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs }, | ||
5920 | .num_dacs = ARRAY_SIZE(alc262_dac_nids), | ||
5921 | .dac_nids = alc262_dac_nids, | ||
5922 | .hp_nid = 0x03, | ||
5923 | .num_channel_mode = ARRAY_SIZE(alc262_modes), | ||
5924 | .channel_mode = alc262_modes, | ||
5925 | .input_mux = &alc262_capture_source, | ||
5926 | }, | ||
5817 | }; | 5927 | }; |
5818 | 5928 | ||
5819 | static int patch_alc262(struct hda_codec *codec) | 5929 | static int patch_alc262(struct hda_codec *codec) |
@@ -5942,6 +6052,23 @@ static struct hda_channel_mode alc861_threestack_modes[2] = { | |||
5942 | { 2, alc861_threestack_ch2_init }, | 6052 | { 2, alc861_threestack_ch2_init }, |
5943 | { 6, alc861_threestack_ch6_init }, | 6053 | { 6, alc861_threestack_ch6_init }, |
5944 | }; | 6054 | }; |
6055 | /* Set mic1 as input and unmute the mixer */ | ||
6056 | static struct hda_verb alc861_uniwill_m31_ch2_init[] = { | ||
6057 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | ||
6058 | { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/ | ||
6059 | { } /* end */ | ||
6060 | }; | ||
6061 | /* Set mic1 as output and mute mixer */ | ||
6062 | static struct hda_verb alc861_uniwill_m31_ch4_init[] = { | ||
6063 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | ||
6064 | { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/ | ||
6065 | { } /* end */ | ||
6066 | }; | ||
6067 | |||
6068 | static struct hda_channel_mode alc861_uniwill_m31_modes[2] = { | ||
6069 | { 2, alc861_uniwill_m31_ch2_init }, | ||
6070 | { 4, alc861_uniwill_m31_ch4_init }, | ||
6071 | }; | ||
5945 | 6072 | ||
5946 | /* patch-ALC861 */ | 6073 | /* patch-ALC861 */ |
5947 | 6074 | ||
@@ -6020,6 +6147,47 @@ static struct snd_kcontrol_new alc861_3ST_mixer[] = { | |||
6020 | }, | 6147 | }, |
6021 | { } /* end */ | 6148 | { } /* end */ |
6022 | }; | 6149 | }; |
6150 | static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = { | ||
6151 | /* output mixer control */ | ||
6152 | HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT), | ||
6153 | HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT), | ||
6154 | HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT), | ||
6155 | HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT), | ||
6156 | /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */ | ||
6157 | |||
6158 | /* Input mixer control */ | ||
6159 | /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT), | ||
6160 | HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */ | ||
6161 | HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT), | ||
6162 | HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT), | ||
6163 | HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT), | ||
6164 | HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT), | ||
6165 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT), | ||
6166 | HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), | ||
6167 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), | ||
6168 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), | ||
6169 | |||
6170 | /* Capture mixer control */ | ||
6171 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
6172 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
6173 | { | ||
6174 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
6175 | .name = "Capture Source", | ||
6176 | .count = 1, | ||
6177 | .info = alc_mux_enum_info, | ||
6178 | .get = alc_mux_enum_get, | ||
6179 | .put = alc_mux_enum_put, | ||
6180 | }, | ||
6181 | { | ||
6182 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
6183 | .name = "Channel Mode", | ||
6184 | .info = alc_ch_mode_info, | ||
6185 | .get = alc_ch_mode_get, | ||
6186 | .put = alc_ch_mode_put, | ||
6187 | .private_value = ARRAY_SIZE(alc861_uniwill_m31_modes), | ||
6188 | }, | ||
6189 | { } /* end */ | ||
6190 | }; | ||
6023 | 6191 | ||
6024 | /* | 6192 | /* |
6025 | * generic initialization of ADC, input mixers and output mixers | 6193 | * generic initialization of ADC, input mixers and output mixers |
@@ -6148,6 +6316,67 @@ static struct hda_verb alc861_threestack_init_verbs[] = { | |||
6148 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 6316 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, |
6149 | { } | 6317 | { } |
6150 | }; | 6318 | }; |
6319 | |||
6320 | static struct hda_verb alc861_uniwill_m31_init_verbs[] = { | ||
6321 | /* | ||
6322 | * Unmute ADC0 and set the default input to mic-in | ||
6323 | */ | ||
6324 | /* port-A for surround (rear panel) */ | ||
6325 | { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, | ||
6326 | /* port-B for mic-in (rear panel) with vref */ | ||
6327 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | ||
6328 | /* port-C for line-in (rear panel) */ | ||
6329 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, | ||
6330 | /* port-D for Front */ | ||
6331 | { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | ||
6332 | { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 }, | ||
6333 | /* port-E for HP out (front panel) */ | ||
6334 | { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, // this has to be set to VREF80 | ||
6335 | /* route front PCM to HP */ | ||
6336 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x01 }, | ||
6337 | /* port-F for mic-in (front panel) with vref */ | ||
6338 | { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | ||
6339 | /* port-G for CLFE (rear panel) */ | ||
6340 | { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, | ||
6341 | /* port-H for side (rear panel) */ | ||
6342 | { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, | ||
6343 | /* CD-in */ | ||
6344 | { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, | ||
6345 | /* route front mic to ADC1*/ | ||
6346 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
6347 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
6348 | /* Unmute DAC0~3 & spdif out*/ | ||
6349 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
6350 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
6351 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
6352 | {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
6353 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
6354 | |||
6355 | /* Unmute Mixer 14 (mic) 1c (Line in)*/ | ||
6356 | {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
6357 | {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
6358 | {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
6359 | {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
6360 | |||
6361 | /* Unmute Stereo Mixer 15 */ | ||
6362 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
6363 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
6364 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | ||
6365 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, //Output 0~12 step | ||
6366 | |||
6367 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
6368 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
6369 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
6370 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
6371 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
6372 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
6373 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
6374 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
6375 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, // hp used DAC 3 (Front) | ||
6376 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | ||
6377 | { } | ||
6378 | }; | ||
6379 | |||
6151 | /* | 6380 | /* |
6152 | * generic initialization of ADC, input mixers and output mixers | 6381 | * generic initialization of ADC, input mixers and output mixers |
6153 | */ | 6382 | */ |
@@ -6401,7 +6630,7 @@ static void alc861_auto_init_hp_out(struct hda_codec *codec) | |||
6401 | struct alc_spec *spec = codec->spec; | 6630 | struct alc_spec *spec = codec->spec; |
6402 | hda_nid_t pin; | 6631 | hda_nid_t pin; |
6403 | 6632 | ||
6404 | pin = spec->autocfg.hp_pin; | 6633 | pin = spec->autocfg.hp_pins[0]; |
6405 | if (pin) /* connect to front */ | 6634 | if (pin) /* connect to front */ |
6406 | alc861_auto_set_output_and_unmute(codec, pin, PIN_HP, spec->multiout.dac_nids[0]); | 6635 | alc861_auto_set_output_and_unmute(codec, pin, PIN_HP, spec->multiout.dac_nids[0]); |
6407 | } | 6636 | } |
@@ -6436,7 +6665,7 @@ static int alc861_parse_auto_config(struct hda_codec *codec) | |||
6436 | 6665 | ||
6437 | if ((err = alc861_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 || | 6666 | if ((err = alc861_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 || |
6438 | (err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || | 6667 | (err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || |
6439 | (err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pin)) < 0 || | 6668 | (err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0])) < 0 || |
6440 | (err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) | 6669 | (err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) |
6441 | return err; | 6670 | return err; |
6442 | 6671 | ||
@@ -6477,10 +6706,14 @@ static struct hda_board_config alc861_cfg_tbl[] = { | |||
6477 | { .modelname = "3stack", .config = ALC861_3ST }, | 6706 | { .modelname = "3stack", .config = ALC861_3ST }, |
6478 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xd600, | 6707 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xd600, |
6479 | .config = ALC861_3ST }, | 6708 | .config = ALC861_3ST }, |
6709 | { .modelname = "3stack-660", .config = ALC660_3ST }, | ||
6480 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x81e7, | 6710 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x81e7, |
6481 | .config = ALC660_3ST }, | 6711 | .config = ALC660_3ST }, |
6482 | { .modelname = "3stack-dig", .config = ALC861_3ST_DIG }, | 6712 | { .modelname = "3stack-dig", .config = ALC861_3ST_DIG }, |
6483 | { .modelname = "6stack-dig", .config = ALC861_6ST_DIG }, | 6713 | { .modelname = "6stack-dig", .config = ALC861_6ST_DIG }, |
6714 | { .modelname = "uniwill-m31", .config = ALC861_UNIWILL_M31}, | ||
6715 | { .pci_subvendor = 0x1584, .pci_subdevice = 0x9072, | ||
6716 | .config = ALC861_UNIWILL_M31 }, | ||
6484 | { .modelname = "auto", .config = ALC861_AUTO }, | 6717 | { .modelname = "auto", .config = ALC861_AUTO }, |
6485 | {} | 6718 | {} |
6486 | }; | 6719 | }; |
@@ -6493,6 +6726,7 @@ static struct alc_config_preset alc861_presets[] = { | |||
6493 | .dac_nids = alc861_dac_nids, | 6726 | .dac_nids = alc861_dac_nids, |
6494 | .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes), | 6727 | .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes), |
6495 | .channel_mode = alc861_threestack_modes, | 6728 | .channel_mode = alc861_threestack_modes, |
6729 | .need_dac_fix = 1, | ||
6496 | .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), | 6730 | .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), |
6497 | .adc_nids = alc861_adc_nids, | 6731 | .adc_nids = alc861_adc_nids, |
6498 | .input_mux = &alc861_capture_source, | 6732 | .input_mux = &alc861_capture_source, |
@@ -6505,6 +6739,7 @@ static struct alc_config_preset alc861_presets[] = { | |||
6505 | .dig_out_nid = ALC861_DIGOUT_NID, | 6739 | .dig_out_nid = ALC861_DIGOUT_NID, |
6506 | .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes), | 6740 | .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes), |
6507 | .channel_mode = alc861_threestack_modes, | 6741 | .channel_mode = alc861_threestack_modes, |
6742 | .need_dac_fix = 1, | ||
6508 | .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), | 6743 | .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), |
6509 | .adc_nids = alc861_adc_nids, | 6744 | .adc_nids = alc861_adc_nids, |
6510 | .input_mux = &alc861_capture_source, | 6745 | .input_mux = &alc861_capture_source, |
@@ -6528,10 +6763,25 @@ static struct alc_config_preset alc861_presets[] = { | |||
6528 | .dac_nids = alc660_dac_nids, | 6763 | .dac_nids = alc660_dac_nids, |
6529 | .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes), | 6764 | .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes), |
6530 | .channel_mode = alc861_threestack_modes, | 6765 | .channel_mode = alc861_threestack_modes, |
6766 | .need_dac_fix = 1, | ||
6767 | .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), | ||
6768 | .adc_nids = alc861_adc_nids, | ||
6769 | .input_mux = &alc861_capture_source, | ||
6770 | }, | ||
6771 | [ALC861_UNIWILL_M31] = { | ||
6772 | .mixers = { alc861_uniwill_m31_mixer }, | ||
6773 | .init_verbs = { alc861_uniwill_m31_init_verbs }, | ||
6774 | .num_dacs = ARRAY_SIZE(alc861_dac_nids), | ||
6775 | .dac_nids = alc861_dac_nids, | ||
6776 | .dig_out_nid = ALC861_DIGOUT_NID, | ||
6777 | .num_channel_mode = ARRAY_SIZE(alc861_uniwill_m31_modes), | ||
6778 | .channel_mode = alc861_uniwill_m31_modes, | ||
6779 | .need_dac_fix = 1, | ||
6531 | .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), | 6780 | .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), |
6532 | .adc_nids = alc861_adc_nids, | 6781 | .adc_nids = alc861_adc_nids, |
6533 | .input_mux = &alc861_capture_source, | 6782 | .input_mux = &alc861_capture_source, |
6534 | }, | 6783 | }, |
6784 | |||
6535 | }; | 6785 | }; |
6536 | 6786 | ||
6537 | 6787 | ||
diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c index 250242cd6c70..76ec3d75fa9e 100644 --- a/sound/pci/hda/patch_si3054.c +++ b/sound/pci/hda/patch_si3054.c | |||
@@ -298,6 +298,7 @@ struct hda_codec_preset snd_hda_preset_si3054[] = { | |||
298 | { .id = 0x163c3055, .name = "Si3054", .patch = patch_si3054 }, | 298 | { .id = 0x163c3055, .name = "Si3054", .patch = patch_si3054 }, |
299 | { .id = 0x163c3155, .name = "Si3054", .patch = patch_si3054 }, | 299 | { .id = 0x163c3155, .name = "Si3054", .patch = patch_si3054 }, |
300 | { .id = 0x11c13026, .name = "Si3054", .patch = patch_si3054 }, | 300 | { .id = 0x11c13026, .name = "Si3054", .patch = patch_si3054 }, |
301 | { .id = 0x10573057, .name = "Si3054", .patch = patch_si3054 }, | ||
301 | {} | 302 | {} |
302 | }; | 303 | }; |
303 | 304 | ||
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index ea99083a1024..731b7b97ee71 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -36,15 +36,15 @@ | |||
36 | 36 | ||
37 | #define NUM_CONTROL_ALLOC 32 | 37 | #define NUM_CONTROL_ALLOC 32 |
38 | #define STAC_HP_EVENT 0x37 | 38 | #define STAC_HP_EVENT 0x37 |
39 | #define STAC_UNSOL_ENABLE (AC_USRSP_EN | STAC_HP_EVENT) | ||
40 | 39 | ||
41 | #define STAC_REF 0 | 40 | #define STAC_REF 0 |
42 | #define STAC_D945GTP3 1 | 41 | #define STAC_D945GTP3 1 |
43 | #define STAC_D945GTP5 2 | 42 | #define STAC_D945GTP5 2 |
44 | #define STAC_MACMINI 3 | 43 | #define STAC_MACMINI 3 |
45 | #define STAC_D965_2112 4 | 44 | #define STAC_922X_MODELS 4 /* number of 922x models */ |
46 | #define STAC_D965_284B 5 | 45 | #define STAC_D965_3ST 4 |
47 | #define STAC_922X_MODELS 6 /* number of 922x models */ | 46 | #define STAC_D965_5ST 5 |
47 | #define STAC_927X_MODELS 6 /* number of 922x models */ | ||
48 | 48 | ||
49 | struct sigmatel_spec { | 49 | struct sigmatel_spec { |
50 | struct snd_kcontrol_new *mixers[4]; | 50 | struct snd_kcontrol_new *mixers[4]; |
@@ -73,6 +73,7 @@ struct sigmatel_spec { | |||
73 | hda_nid_t *pin_nids; | 73 | hda_nid_t *pin_nids; |
74 | unsigned int num_pins; | 74 | unsigned int num_pins; |
75 | unsigned int *pin_configs; | 75 | unsigned int *pin_configs; |
76 | unsigned int *bios_pin_configs; | ||
76 | 77 | ||
77 | /* codec specific stuff */ | 78 | /* codec specific stuff */ |
78 | struct hda_verb *init; | 79 | struct hda_verb *init; |
@@ -110,24 +111,10 @@ static hda_nid_t stac922x_adc_nids[2] = { | |||
110 | 0x06, 0x07, | 111 | 0x06, 0x07, |
111 | }; | 112 | }; |
112 | 113 | ||
113 | static hda_nid_t stac9227_adc_nids[2] = { | ||
114 | 0x07, 0x08, | ||
115 | }; | ||
116 | |||
117 | #if 0 | ||
118 | static hda_nid_t d965_2112_dac_nids[3] = { | ||
119 | 0x02, 0x03, 0x05, | ||
120 | }; | ||
121 | #endif | ||
122 | |||
123 | static hda_nid_t stac922x_mux_nids[2] = { | 114 | static hda_nid_t stac922x_mux_nids[2] = { |
124 | 0x12, 0x13, | 115 | 0x12, 0x13, |
125 | }; | 116 | }; |
126 | 117 | ||
127 | static hda_nid_t stac9227_mux_nids[2] = { | ||
128 | 0x15, 0x16, | ||
129 | }; | ||
130 | |||
131 | static hda_nid_t stac927x_adc_nids[3] = { | 118 | static hda_nid_t stac927x_adc_nids[3] = { |
132 | 0x07, 0x08, 0x09 | 119 | 0x07, 0x08, 0x09 |
133 | }; | 120 | }; |
@@ -136,8 +123,17 @@ static hda_nid_t stac927x_mux_nids[3] = { | |||
136 | 0x15, 0x16, 0x17 | 123 | 0x15, 0x16, 0x17 |
137 | }; | 124 | }; |
138 | 125 | ||
126 | static hda_nid_t stac9205_adc_nids[2] = { | ||
127 | 0x12, 0x13 | ||
128 | }; | ||
129 | |||
130 | static hda_nid_t stac9205_mux_nids[2] = { | ||
131 | 0x19, 0x1a | ||
132 | }; | ||
133 | |||
139 | static hda_nid_t stac9200_pin_nids[8] = { | 134 | static hda_nid_t stac9200_pin_nids[8] = { |
140 | 0x08, 0x09, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, | 135 | 0x08, 0x09, 0x0d, 0x0e, |
136 | 0x0f, 0x10, 0x11, 0x12, | ||
141 | }; | 137 | }; |
142 | 138 | ||
143 | static hda_nid_t stac922x_pin_nids[10] = { | 139 | static hda_nid_t stac922x_pin_nids[10] = { |
@@ -151,6 +147,13 @@ static hda_nid_t stac927x_pin_nids[14] = { | |||
151 | 0x14, 0x21, 0x22, 0x23, | 147 | 0x14, 0x21, 0x22, 0x23, |
152 | }; | 148 | }; |
153 | 149 | ||
150 | static hda_nid_t stac9205_pin_nids[12] = { | ||
151 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | ||
152 | 0x0f, 0x14, 0x16, 0x17, 0x18, | ||
153 | 0x21, 0x22, | ||
154 | |||
155 | }; | ||
156 | |||
154 | static int stac92xx_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 157 | static int stac92xx_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
155 | { | 158 | { |
156 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 159 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
@@ -190,25 +193,23 @@ static struct hda_verb stac922x_core_init[] = { | |||
190 | {} | 193 | {} |
191 | }; | 194 | }; |
192 | 195 | ||
193 | static struct hda_verb stac9227_core_init[] = { | 196 | static struct hda_verb d965_core_init[] = { |
194 | /* set master volume and direct control */ | 197 | /* set master volume and direct control */ |
195 | { 0x16, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 198 | { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, |
196 | /* unmute node 0x1b */ | 199 | /* unmute node 0x1b */ |
197 | { 0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 200 | { 0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, |
201 | /* select node 0x03 as DAC */ | ||
202 | { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
198 | {} | 203 | {} |
199 | }; | 204 | }; |
200 | 205 | ||
201 | static struct hda_verb d965_2112_core_init[] = { | 206 | static struct hda_verb stac927x_core_init[] = { |
202 | /* set master volume and direct control */ | 207 | /* set master volume and direct control */ |
203 | { 0x16, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 208 | { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, |
204 | /* unmute node 0x1b */ | ||
205 | { 0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
206 | /* select node 0x03 as DAC */ | ||
207 | { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
208 | {} | 209 | {} |
209 | }; | 210 | }; |
210 | 211 | ||
211 | static struct hda_verb stac927x_core_init[] = { | 212 | static struct hda_verb stac9205_core_init[] = { |
212 | /* set master volume and direct control */ | 213 | /* set master volume and direct control */ |
213 | { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 214 | { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, |
214 | {} | 215 | {} |
@@ -277,6 +278,21 @@ static snd_kcontrol_new_t stac927x_mixer[] = { | |||
277 | { } /* end */ | 278 | { } /* end */ |
278 | }; | 279 | }; |
279 | 280 | ||
281 | static snd_kcontrol_new_t stac9205_mixer[] = { | ||
282 | { | ||
283 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
284 | .name = "Input Source", | ||
285 | .count = 1, | ||
286 | .info = stac92xx_mux_enum_info, | ||
287 | .get = stac92xx_mux_enum_get, | ||
288 | .put = stac92xx_mux_enum_put, | ||
289 | }, | ||
290 | HDA_CODEC_VOLUME("InMux Capture Volume", 0x19, 0x0, HDA_OUTPUT), | ||
291 | HDA_CODEC_VOLUME("InVol Capture Volume", 0x1b, 0x0, HDA_INPUT), | ||
292 | HDA_CODEC_MUTE("ADCMux Capture Switch", 0x1d, 0x0, HDA_OUTPUT), | ||
293 | { } /* end */ | ||
294 | }; | ||
295 | |||
280 | static int stac92xx_build_controls(struct hda_codec *codec) | 296 | static int stac92xx_build_controls(struct hda_codec *codec) |
281 | { | 297 | { |
282 | struct sigmatel_spec *spec = codec->spec; | 298 | struct sigmatel_spec *spec = codec->spec; |
@@ -341,38 +357,67 @@ static unsigned int d945gtp5_pin_configs[10] = { | |||
341 | 0x02a19320, 0x40000100, | 357 | 0x02a19320, 0x40000100, |
342 | }; | 358 | }; |
343 | 359 | ||
344 | static unsigned int d965_2112_pin_configs[10] = { | ||
345 | 0x0221401f, 0x40000100, 0x40000100, 0x01014011, | ||
346 | 0x01a19021, 0x01813024, 0x01452130, 0x40000100, | ||
347 | 0x02a19320, 0x40000100, | ||
348 | }; | ||
349 | |||
350 | static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = { | 360 | static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = { |
351 | [STAC_REF] = ref922x_pin_configs, | 361 | [STAC_REF] = ref922x_pin_configs, |
352 | [STAC_D945GTP3] = d945gtp3_pin_configs, | 362 | [STAC_D945GTP3] = d945gtp3_pin_configs, |
353 | [STAC_D945GTP5] = d945gtp5_pin_configs, | 363 | [STAC_D945GTP5] = d945gtp5_pin_configs, |
354 | [STAC_MACMINI] = d945gtp5_pin_configs, | 364 | [STAC_MACMINI] = d945gtp5_pin_configs, |
355 | [STAC_D965_2112] = d965_2112_pin_configs, | ||
356 | }; | 365 | }; |
357 | 366 | ||
358 | static struct hda_board_config stac922x_cfg_tbl[] = { | 367 | static struct hda_board_config stac922x_cfg_tbl[] = { |
368 | { .modelname = "5stack", .config = STAC_D945GTP5 }, | ||
369 | { .modelname = "3stack", .config = STAC_D945GTP3 }, | ||
359 | { .modelname = "ref", | 370 | { .modelname = "ref", |
360 | .pci_subvendor = PCI_VENDOR_ID_INTEL, | 371 | .pci_subvendor = PCI_VENDOR_ID_INTEL, |
361 | .pci_subdevice = 0x2668, /* DFI LanParty */ | 372 | .pci_subdevice = 0x2668, /* DFI LanParty */ |
362 | .config = STAC_REF }, /* SigmaTel reference board */ | 373 | .config = STAC_REF }, /* SigmaTel reference board */ |
374 | /* Intel 945G based systems */ | ||
363 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | 375 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, |
364 | .pci_subdevice = 0x0101, | 376 | .pci_subdevice = 0x0101, |
365 | .config = STAC_D945GTP3 }, /* Intel D945GTP - 3 Stack */ | 377 | .config = STAC_D945GTP3 }, /* Intel D945GTP - 3 Stack */ |
366 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | 378 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, |
367 | .pci_subdevice = 0x0202, | 379 | .pci_subdevice = 0x0202, |
368 | .config = STAC_D945GTP3 }, /* Intel D945GNT - 3 Stack, 9221 A1 */ | 380 | .config = STAC_D945GTP3 }, /* Intel D945GNT - 3 Stack */ |
369 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | 381 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, |
370 | .pci_subdevice = 0x0b0b, | 382 | .pci_subdevice = 0x0606, |
371 | .config = STAC_D945GTP3 }, /* Intel D945PSN - 3 Stack, 9221 A1 */ | 383 | .config = STAC_D945GTP3 }, /* Intel D945GTP - 3 Stack */ |
384 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
385 | .pci_subdevice = 0x0601, | ||
386 | .config = STAC_D945GTP3 }, /* Intel D945GTP - 3 Stack */ | ||
387 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
388 | .pci_subdevice = 0x0111, | ||
389 | .config = STAC_D945GTP3 }, /* Intel D945GZP - 3 Stack */ | ||
390 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
391 | .pci_subdevice = 0x1115, | ||
392 | .config = STAC_D945GTP3 }, /* Intel D945GPM - 3 Stack */ | ||
393 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
394 | .pci_subdevice = 0x1116, | ||
395 | .config = STAC_D945GTP3 }, /* Intel D945GBO - 3 Stack */ | ||
396 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
397 | .pci_subdevice = 0x1117, | ||
398 | .config = STAC_D945GTP3 }, /* Intel D945GPM - 3 Stack */ | ||
399 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
400 | .pci_subdevice = 0x1118, | ||
401 | .config = STAC_D945GTP3 }, /* Intel D945GPM - 3 Stack */ | ||
402 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
403 | .pci_subdevice = 0x1119, | ||
404 | .config = STAC_D945GTP3 }, /* Intel D945GPM - 3 Stack */ | ||
405 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
406 | .pci_subdevice = 0x8826, | ||
407 | .config = STAC_D945GTP3 }, /* Intel D945GPM - 3 Stack */ | ||
408 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
409 | .pci_subdevice = 0x5049, | ||
410 | .config = STAC_D945GTP3 }, /* Intel D945GCZ - 3 Stack */ | ||
411 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
412 | .pci_subdevice = 0x5055, | ||
413 | .config = STAC_D945GTP3 }, /* Intel D945GCZ - 3 Stack */ | ||
414 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
415 | .pci_subdevice = 0x5048, | ||
416 | .config = STAC_D945GTP3 }, /* Intel D945GPB - 3 Stack */ | ||
417 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
418 | .pci_subdevice = 0x0110, | ||
419 | .config = STAC_D945GTP3 }, /* Intel D945GLR - 3 Stack */ | ||
372 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | 420 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, |
373 | .pci_subdevice = 0x0707, | ||
374 | .config = STAC_D945GTP5 }, /* Intel D945PSV - 5 Stack */ | ||
375 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
376 | .pci_subdevice = 0x0404, | 421 | .pci_subdevice = 0x0404, |
377 | .config = STAC_D945GTP5 }, /* Intel D945GTP - 5 Stack */ | 422 | .config = STAC_D945GTP5 }, /* Intel D945GTP - 5 Stack */ |
378 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | 423 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, |
@@ -384,44 +429,214 @@ static struct hda_board_config stac922x_cfg_tbl[] = { | |||
384 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | 429 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, |
385 | .pci_subdevice = 0x0417, | 430 | .pci_subdevice = 0x0417, |
386 | .config = STAC_D945GTP5 }, /* Intel D975XBK - 5 Stack */ | 431 | .config = STAC_D945GTP5 }, /* Intel D975XBK - 5 Stack */ |
432 | /* Intel 945P based systems */ | ||
433 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
434 | .pci_subdevice = 0x0b0b, | ||
435 | .config = STAC_D945GTP3 }, /* Intel D945PSN - 3 Stack */ | ||
436 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
437 | .pci_subdevice = 0x0112, | ||
438 | .config = STAC_D945GTP3 }, /* Intel D945PLN - 3 Stack */ | ||
439 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
440 | .pci_subdevice = 0x0d0d, | ||
441 | .config = STAC_D945GTP3 }, /* Intel D945PLM - 3 Stack */ | ||
442 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
443 | .pci_subdevice = 0x0909, | ||
444 | .config = STAC_D945GTP3 }, /* Intel D945PAW - 3 Stack */ | ||
445 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
446 | .pci_subdevice = 0x0505, | ||
447 | .config = STAC_D945GTP3 }, /* Intel D945PLM - 3 Stack */ | ||
448 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
449 | .pci_subdevice = 0x0707, | ||
450 | .config = STAC_D945GTP5 }, /* Intel D945PSV - 5 Stack */ | ||
451 | /* other systems */ | ||
387 | { .pci_subvendor = 0x8384, | 452 | { .pci_subvendor = 0x8384, |
388 | .pci_subdevice = 0x7680, | 453 | .pci_subdevice = 0x7680, |
389 | .config = STAC_MACMINI }, /* Apple Mac Mini (early 2006) */ | 454 | .config = STAC_MACMINI }, /* Apple Mac Mini (early 2006) */ |
455 | {} /* terminator */ | ||
456 | }; | ||
457 | |||
458 | static unsigned int ref927x_pin_configs[14] = { | ||
459 | 0x02214020, 0x02a19080, 0x0181304e, 0x01014010, | ||
460 | 0x01a19040, 0x01011012, 0x01016011, 0x0101201f, | ||
461 | 0x183301f0, 0x18a001f0, 0x18a001f0, 0x01442070, | ||
462 | 0x01c42190, 0x40000100, | ||
463 | }; | ||
464 | |||
465 | static unsigned int d965_3st_pin_configs[14] = { | ||
466 | 0x0221401f, 0x02a19120, 0x40000100, 0x01014011, | ||
467 | 0x01a19021, 0x01813024, 0x40000100, 0x40000100, | ||
468 | 0x40000100, 0x40000100, 0x40000100, 0x40000100, | ||
469 | 0x40000100, 0x40000100 | ||
470 | }; | ||
471 | |||
472 | static unsigned int d965_5st_pin_configs[14] = { | ||
473 | 0x02214020, 0x02a19080, 0x0181304e, 0x01014010, | ||
474 | 0x01a19040, 0x01011012, 0x01016011, 0x40000100, | ||
475 | 0x40000100, 0x40000100, 0x40000100, 0x01442070, | ||
476 | 0x40000100, 0x40000100 | ||
477 | }; | ||
478 | |||
479 | static unsigned int *stac927x_brd_tbl[STAC_927X_MODELS] = { | ||
480 | [STAC_REF] = ref927x_pin_configs, | ||
481 | [STAC_D965_3ST] = d965_3st_pin_configs, | ||
482 | [STAC_D965_5ST] = d965_5st_pin_configs, | ||
483 | }; | ||
484 | |||
485 | static struct hda_board_config stac927x_cfg_tbl[] = { | ||
486 | { .modelname = "5stack", .config = STAC_D965_5ST }, | ||
487 | { .modelname = "3stack", .config = STAC_D965_3ST }, | ||
488 | { .modelname = "ref", | ||
489 | .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
490 | .pci_subdevice = 0x2668, /* DFI LanParty */ | ||
491 | .config = STAC_REF }, /* SigmaTel reference board */ | ||
492 | /* Intel 946 based systems */ | ||
493 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
494 | .pci_subdevice = 0x3d01, | ||
495 | .config = STAC_D965_3ST }, /* D946 configuration */ | ||
496 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
497 | .pci_subdevice = 0xa301, | ||
498 | .config = STAC_D965_3ST }, /* Intel D946GZT - 3 stack */ | ||
499 | /* 965 based 3 stack systems */ | ||
500 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
501 | .pci_subdevice = 0x2116, | ||
502 | .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ | ||
503 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
504 | .pci_subdevice = 0x2115, | ||
505 | .config = STAC_D965_3ST }, /* Intel DQ965WC - 3 Stack */ | ||
506 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
507 | .pci_subdevice = 0x2114, | ||
508 | .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ | ||
509 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
510 | .pci_subdevice = 0x2113, | ||
511 | .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ | ||
390 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | 512 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, |
391 | .pci_subdevice = 0x2112, | 513 | .pci_subdevice = 0x2112, |
392 | .config = STAC_D965_2112 }, | 514 | .config = STAC_D965_3ST }, /* Intel DG965MS - 3 Stack */ |
515 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
516 | .pci_subdevice = 0x2111, | ||
517 | .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ | ||
518 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
519 | .pci_subdevice = 0x2110, | ||
520 | .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ | ||
521 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
522 | .pci_subdevice = 0x2009, | ||
523 | .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ | ||
524 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
525 | .pci_subdevice = 0x2008, | ||
526 | .config = STAC_D965_3ST }, /* Intel DQ965GF - 3 Stack */ | ||
527 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
528 | .pci_subdevice = 0x2007, | ||
529 | .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ | ||
530 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
531 | .pci_subdevice = 0x2006, | ||
532 | .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ | ||
533 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
534 | .pci_subdevice = 0x2005, | ||
535 | .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ | ||
536 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
537 | .pci_subdevice = 0x2004, | ||
538 | .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ | ||
539 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
540 | .pci_subdevice = 0x2003, | ||
541 | .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ | ||
542 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
543 | .pci_subdevice = 0x2002, | ||
544 | .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ | ||
545 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
546 | .pci_subdevice = 0x2001, | ||
547 | .config = STAC_D965_3ST }, /* Intel DQ965GF - 3 Stack */ | ||
548 | /* 965 based 5 stack systems */ | ||
549 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
550 | .pci_subdevice = 0x2301, | ||
551 | .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */ | ||
552 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
553 | .pci_subdevice = 0x2302, | ||
554 | .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */ | ||
555 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
556 | .pci_subdevice = 0x2303, | ||
557 | .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */ | ||
393 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | 558 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, |
394 | .pci_subdevice = 0x284b, | 559 | .pci_subdevice = 0x2304, |
395 | .config = STAC_D965_284B }, | 560 | .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */ |
561 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
562 | .pci_subdevice = 0x2305, | ||
563 | .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */ | ||
564 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
565 | .pci_subdevice = 0x2501, | ||
566 | .config = STAC_D965_5ST }, /* Intel DG965MQ - 5 Stack */ | ||
567 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
568 | .pci_subdevice = 0x2502, | ||
569 | .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */ | ||
570 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
571 | .pci_subdevice = 0x2503, | ||
572 | .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */ | ||
573 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
574 | .pci_subdevice = 0x2504, | ||
575 | .config = STAC_D965_5ST }, /* Intel DQ965GF - 5 Stack */ | ||
396 | {} /* terminator */ | 576 | {} /* terminator */ |
397 | }; | 577 | }; |
398 | 578 | ||
399 | static unsigned int ref927x_pin_configs[14] = { | 579 | static unsigned int ref9205_pin_configs[12] = { |
400 | 0x01813122, 0x01a19021, 0x01014010, 0x01016011, | 580 | 0x40000100, 0x40000100, 0x01016011, 0x01014010, |
401 | 0x01012012, 0x01011014, 0x40000100, 0x40000100, | 581 | 0x01813122, 0x01a19021, 0x40000100, 0x40000100, |
402 | 0x40000100, 0x40000100, 0x40000100, 0x01441030, | 582 | 0x40000100, 0x40000100, 0x01441030, 0x01c41030 |
403 | 0x01c41030, 0x40000100, | ||
404 | }; | 583 | }; |
405 | 584 | ||
406 | static unsigned int *stac927x_brd_tbl[] = { | 585 | static unsigned int *stac9205_brd_tbl[] = { |
407 | ref927x_pin_configs, | 586 | ref9205_pin_configs, |
408 | }; | 587 | }; |
409 | 588 | ||
410 | static struct hda_board_config stac927x_cfg_tbl[] = { | 589 | static struct hda_board_config stac9205_cfg_tbl[] = { |
411 | { .modelname = "ref", | 590 | { .modelname = "ref", |
412 | .pci_subvendor = PCI_VENDOR_ID_INTEL, | 591 | .pci_subvendor = PCI_VENDOR_ID_INTEL, |
413 | .pci_subdevice = 0x2668, /* DFI LanParty */ | 592 | .pci_subdevice = 0x2668, /* DFI LanParty */ |
414 | .config = STAC_REF }, /* SigmaTel reference board */ | 593 | .config = STAC_REF }, /* SigmaTel reference board */ |
594 | /* Dell laptops have BIOS problem */ | ||
595 | { .pci_subvendor = PCI_VENDOR_ID_DELL, .pci_subdevice = 0x01b5, | ||
596 | .config = STAC_REF }, /* Dell Inspiron 630m */ | ||
597 | { .pci_subvendor = PCI_VENDOR_ID_DELL, .pci_subdevice = 0x01c2, | ||
598 | .config = STAC_REF }, /* Dell Latitude D620 */ | ||
599 | { .pci_subvendor = PCI_VENDOR_ID_DELL, .pci_subdevice = 0x01cb, | ||
600 | .config = STAC_REF }, /* Dell Latitude 120L */ | ||
415 | {} /* terminator */ | 601 | {} /* terminator */ |
416 | }; | 602 | }; |
417 | 603 | ||
604 | static int stac92xx_save_bios_config_regs(struct hda_codec *codec) | ||
605 | { | ||
606 | int i; | ||
607 | struct sigmatel_spec *spec = codec->spec; | ||
608 | |||
609 | if (! spec->bios_pin_configs) { | ||
610 | spec->bios_pin_configs = kcalloc(spec->num_pins, | ||
611 | sizeof(*spec->bios_pin_configs), GFP_KERNEL); | ||
612 | if (! spec->bios_pin_configs) | ||
613 | return -ENOMEM; | ||
614 | } | ||
615 | |||
616 | for (i = 0; i < spec->num_pins; i++) { | ||
617 | hda_nid_t nid = spec->pin_nids[i]; | ||
618 | unsigned int pin_cfg; | ||
619 | |||
620 | pin_cfg = snd_hda_codec_read(codec, nid, 0, | ||
621 | AC_VERB_GET_CONFIG_DEFAULT, 0x00); | ||
622 | snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x bios pin config %8.8x\n", | ||
623 | nid, pin_cfg); | ||
624 | spec->bios_pin_configs[i] = pin_cfg; | ||
625 | } | ||
626 | |||
627 | return 0; | ||
628 | } | ||
629 | |||
418 | static void stac92xx_set_config_regs(struct hda_codec *codec) | 630 | static void stac92xx_set_config_regs(struct hda_codec *codec) |
419 | { | 631 | { |
420 | int i; | 632 | int i; |
421 | struct sigmatel_spec *spec = codec->spec; | 633 | struct sigmatel_spec *spec = codec->spec; |
422 | unsigned int pin_cfg; | 634 | unsigned int pin_cfg; |
423 | 635 | ||
424 | for (i=0; i < spec->num_pins; i++) { | 636 | if (! spec->pin_nids || ! spec->pin_configs) |
637 | return; | ||
638 | |||
639 | for (i = 0; i < spec->num_pins; i++) { | ||
425 | snd_hda_codec_write(codec, spec->pin_nids[i], 0, | 640 | snd_hda_codec_write(codec, spec->pin_nids[i], 0, |
426 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_0, | 641 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_0, |
427 | spec->pin_configs[i] & 0x000000ff); | 642 | spec->pin_configs[i] & 0x000000ff); |
@@ -795,11 +1010,29 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, | |||
795 | return 0; | 1010 | return 0; |
796 | } | 1011 | } |
797 | 1012 | ||
1013 | /* create volume control/switch for the given prefx type */ | ||
1014 | static int create_controls(struct sigmatel_spec *spec, const char *pfx, hda_nid_t nid, int chs) | ||
1015 | { | ||
1016 | char name[32]; | ||
1017 | int err; | ||
1018 | |||
1019 | sprintf(name, "%s Playback Volume", pfx); | ||
1020 | err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, name, | ||
1021 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); | ||
1022 | if (err < 0) | ||
1023 | return err; | ||
1024 | sprintf(name, "%s Playback Switch", pfx); | ||
1025 | err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, name, | ||
1026 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); | ||
1027 | if (err < 0) | ||
1028 | return err; | ||
1029 | return 0; | ||
1030 | } | ||
1031 | |||
798 | /* add playback controls from the parsed DAC table */ | 1032 | /* add playback controls from the parsed DAC table */ |
799 | static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, | 1033 | static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, |
800 | const struct auto_pin_cfg *cfg) | 1034 | const struct auto_pin_cfg *cfg) |
801 | { | 1035 | { |
802 | char name[32]; | ||
803 | static const char *chname[4] = { | 1036 | static const char *chname[4] = { |
804 | "Front", "Surround", NULL /*CLFE*/, "Side" | 1037 | "Front", "Surround", NULL /*CLFE*/, "Side" |
805 | }; | 1038 | }; |
@@ -814,26 +1047,15 @@ static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, | |||
814 | 1047 | ||
815 | if (i == 2) { | 1048 | if (i == 2) { |
816 | /* Center/LFE */ | 1049 | /* Center/LFE */ |
817 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, "Center Playback Volume", | 1050 | err = create_controls(spec, "Center", nid, 1); |
818 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0) | 1051 | if (err < 0) |
819 | return err; | ||
820 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, "LFE Playback Volume", | ||
821 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) | ||
822 | return err; | ||
823 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, "Center Playback Switch", | ||
824 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0) | ||
825 | return err; | 1052 | return err; |
826 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, "LFE Playback Switch", | 1053 | err = create_controls(spec, "LFE", nid, 2); |
827 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) | 1054 | if (err < 0) |
828 | return err; | 1055 | return err; |
829 | } else { | 1056 | } else { |
830 | sprintf(name, "%s Playback Volume", chname[i]); | 1057 | err = create_controls(spec, chname[i], nid, 3); |
831 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, name, | 1058 | if (err < 0) |
832 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | ||
833 | return err; | ||
834 | sprintf(name, "%s Playback Switch", chname[i]); | ||
835 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, name, | ||
836 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | ||
837 | return err; | 1059 | return err; |
838 | } | 1060 | } |
839 | } | 1061 | } |
@@ -849,39 +1071,85 @@ static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, | |||
849 | return 0; | 1071 | return 0; |
850 | } | 1072 | } |
851 | 1073 | ||
852 | /* add playback controls for HP output */ | 1074 | static int check_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid) |
853 | static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, struct auto_pin_cfg *cfg) | ||
854 | { | 1075 | { |
855 | struct sigmatel_spec *spec = codec->spec; | 1076 | int i; |
856 | hda_nid_t pin = cfg->hp_pin; | ||
857 | hda_nid_t nid; | ||
858 | int i, err; | ||
859 | unsigned int wid_caps; | ||
860 | 1077 | ||
861 | if (! pin) | 1078 | for (i = 0; i < spec->multiout.num_dacs; i++) { |
862 | return 0; | 1079 | if (spec->multiout.dac_nids[i] == nid) |
1080 | return 1; | ||
1081 | } | ||
1082 | if (spec->multiout.hp_nid == nid) | ||
1083 | return 1; | ||
1084 | return 0; | ||
1085 | } | ||
863 | 1086 | ||
864 | wid_caps = get_wcaps(codec, pin); | 1087 | static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid) |
865 | if (wid_caps & AC_WCAP_UNSOL_CAP) | 1088 | { |
866 | spec->hp_detect = 1; | 1089 | if (!spec->multiout.hp_nid) |
1090 | spec->multiout.hp_nid = nid; | ||
1091 | else if (spec->multiout.num_dacs > 4) { | ||
1092 | printk(KERN_WARNING "stac92xx: No space for DAC 0x%x\n", nid); | ||
1093 | return 1; | ||
1094 | } else { | ||
1095 | spec->multiout.dac_nids[spec->multiout.num_dacs] = nid; | ||
1096 | spec->multiout.num_dacs++; | ||
1097 | } | ||
1098 | return 0; | ||
1099 | } | ||
867 | 1100 | ||
868 | nid = snd_hda_codec_read(codec, pin, 0, AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | 1101 | /* add playback controls for Speaker and HP outputs */ |
869 | for (i = 0; i < cfg->line_outs; i++) { | 1102 | static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, |
870 | if (! spec->multiout.dac_nids[i]) | 1103 | struct auto_pin_cfg *cfg) |
1104 | { | ||
1105 | struct sigmatel_spec *spec = codec->spec; | ||
1106 | hda_nid_t nid; | ||
1107 | int i, old_num_dacs, err; | ||
1108 | |||
1109 | old_num_dacs = spec->multiout.num_dacs; | ||
1110 | for (i = 0; i < cfg->hp_outs; i++) { | ||
1111 | unsigned int wid_caps = get_wcaps(codec, cfg->hp_pins[i]); | ||
1112 | if (wid_caps & AC_WCAP_UNSOL_CAP) | ||
1113 | spec->hp_detect = 1; | ||
1114 | nid = snd_hda_codec_read(codec, cfg->hp_pins[i], 0, | ||
1115 | AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | ||
1116 | if (check_in_dac_nids(spec, nid)) | ||
1117 | nid = 0; | ||
1118 | if (! nid) | ||
871 | continue; | 1119 | continue; |
872 | if (spec->multiout.dac_nids[i] == nid) | 1120 | add_spec_dacs(spec, nid); |
873 | return 0; | 1121 | } |
1122 | for (i = 0; i < cfg->speaker_outs; i++) { | ||
1123 | nid = snd_hda_codec_read(codec, cfg->speaker_pins[0], 0, | ||
1124 | AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | ||
1125 | if (check_in_dac_nids(spec, nid)) | ||
1126 | nid = 0; | ||
1127 | if (check_in_dac_nids(spec, nid)) | ||
1128 | nid = 0; | ||
1129 | if (! nid) | ||
1130 | continue; | ||
1131 | add_spec_dacs(spec, nid); | ||
874 | } | 1132 | } |
875 | 1133 | ||
876 | spec->multiout.hp_nid = nid; | 1134 | for (i = old_num_dacs; i < spec->multiout.num_dacs; i++) { |
877 | 1135 | static const char *pfxs[] = { | |
878 | /* control HP volume/switch on the output mixer amp */ | 1136 | "Speaker", "External Speaker", "Speaker2", |
879 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, "Headphone Playback Volume", | 1137 | }; |
880 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | 1138 | err = create_controls(spec, pfxs[i - old_num_dacs], |
881 | return err; | 1139 | spec->multiout.dac_nids[i], 3); |
882 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, "Headphone Playback Switch", | 1140 | if (err < 0) |
883 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | 1141 | return err; |
884 | return err; | 1142 | } |
1143 | if (spec->multiout.hp_nid) { | ||
1144 | const char *pfx; | ||
1145 | if (old_num_dacs == spec->multiout.num_dacs) | ||
1146 | pfx = "Master"; | ||
1147 | else | ||
1148 | pfx = "Headphone"; | ||
1149 | err = create_controls(spec, pfx, spec->multiout.hp_nid, 3); | ||
1150 | if (err < 0) | ||
1151 | return err; | ||
1152 | } | ||
885 | 1153 | ||
886 | return 0; | 1154 | return 0; |
887 | } | 1155 | } |
@@ -895,23 +1163,28 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const | |||
895 | int i, j, k; | 1163 | int i, j, k; |
896 | 1164 | ||
897 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 1165 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
898 | int index = -1; | 1166 | int index; |
899 | if (cfg->input_pins[i]) { | 1167 | |
900 | imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; | 1168 | if (!cfg->input_pins[i]) |
901 | 1169 | continue; | |
902 | for (j=0; j<spec->num_muxes; j++) { | 1170 | index = -1; |
903 | int num_cons = snd_hda_get_connections(codec, spec->mux_nids[j], con_lst, HDA_MAX_NUM_INPUTS); | 1171 | for (j = 0; j < spec->num_muxes; j++) { |
904 | for (k=0; k<num_cons; k++) | 1172 | int num_cons; |
905 | if (con_lst[k] == cfg->input_pins[i]) { | 1173 | num_cons = snd_hda_get_connections(codec, |
906 | index = k; | 1174 | spec->mux_nids[j], |
907 | break; | 1175 | con_lst, |
908 | } | 1176 | HDA_MAX_NUM_INPUTS); |
909 | if (index >= 0) | 1177 | for (k = 0; k < num_cons; k++) |
910 | break; | 1178 | if (con_lst[k] == cfg->input_pins[i]) { |
911 | } | 1179 | index = k; |
912 | imux->items[imux->num_items].index = index; | 1180 | goto found; |
913 | imux->num_items++; | 1181 | } |
914 | } | 1182 | } |
1183 | continue; | ||
1184 | found: | ||
1185 | imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; | ||
1186 | imux->items[imux->num_items].index = index; | ||
1187 | imux->num_items++; | ||
915 | } | 1188 | } |
916 | 1189 | ||
917 | if (imux->num_items == 1) { | 1190 | if (imux->num_items == 1) { |
@@ -944,11 +1217,20 @@ static void stac92xx_auto_init_multi_out(struct hda_codec *codec) | |||
944 | static void stac92xx_auto_init_hp_out(struct hda_codec *codec) | 1217 | static void stac92xx_auto_init_hp_out(struct hda_codec *codec) |
945 | { | 1218 | { |
946 | struct sigmatel_spec *spec = codec->spec; | 1219 | struct sigmatel_spec *spec = codec->spec; |
947 | hda_nid_t pin; | 1220 | int i; |
948 | 1221 | ||
949 | pin = spec->autocfg.hp_pin; | 1222 | for (i = 0; i < spec->autocfg.hp_outs; i++) { |
950 | if (pin) /* connect to front */ | 1223 | hda_nid_t pin; |
951 | stac92xx_auto_set_pinctl(codec, pin, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN); | 1224 | pin = spec->autocfg.hp_pins[i]; |
1225 | if (pin) /* connect to front */ | ||
1226 | stac92xx_auto_set_pinctl(codec, pin, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN); | ||
1227 | } | ||
1228 | for (i = 0; i < spec->autocfg.speaker_outs; i++) { | ||
1229 | hda_nid_t pin; | ||
1230 | pin = spec->autocfg.speaker_pins[i]; | ||
1231 | if (pin) /* connect to front */ | ||
1232 | stac92xx_auto_set_pinctl(codec, pin, AC_PINCTL_OUT_EN); | ||
1233 | } | ||
952 | } | 1234 | } |
953 | 1235 | ||
954 | static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in) | 1236 | static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in) |
@@ -994,7 +1276,7 @@ static int stac9200_auto_create_hp_ctls(struct hda_codec *codec, | |||
994 | struct auto_pin_cfg *cfg) | 1276 | struct auto_pin_cfg *cfg) |
995 | { | 1277 | { |
996 | struct sigmatel_spec *spec = codec->spec; | 1278 | struct sigmatel_spec *spec = codec->spec; |
997 | hda_nid_t pin = cfg->hp_pin; | 1279 | hda_nid_t pin = cfg->hp_pins[0]; |
998 | unsigned int wid_caps; | 1280 | unsigned int wid_caps; |
999 | 1281 | ||
1000 | if (! pin) | 1282 | if (! pin) |
@@ -1007,6 +1289,57 @@ static int stac9200_auto_create_hp_ctls(struct hda_codec *codec, | |||
1007 | return 0; | 1289 | return 0; |
1008 | } | 1290 | } |
1009 | 1291 | ||
1292 | /* add playback controls for LFE output */ | ||
1293 | static int stac9200_auto_create_lfe_ctls(struct hda_codec *codec, | ||
1294 | struct auto_pin_cfg *cfg) | ||
1295 | { | ||
1296 | struct sigmatel_spec *spec = codec->spec; | ||
1297 | int err; | ||
1298 | hda_nid_t lfe_pin = 0x0; | ||
1299 | int i; | ||
1300 | |||
1301 | /* | ||
1302 | * search speaker outs and line outs for a mono speaker pin | ||
1303 | * with an amp. If one is found, add LFE controls | ||
1304 | * for it. | ||
1305 | */ | ||
1306 | for (i = 0; i < spec->autocfg.speaker_outs && lfe_pin == 0x0; i++) { | ||
1307 | hda_nid_t pin = spec->autocfg.speaker_pins[i]; | ||
1308 | unsigned long wcaps = get_wcaps(codec, pin); | ||
1309 | wcaps &= (AC_WCAP_STEREO | AC_WCAP_OUT_AMP); | ||
1310 | if (wcaps == AC_WCAP_OUT_AMP) | ||
1311 | /* found a mono speaker with an amp, must be lfe */ | ||
1312 | lfe_pin = pin; | ||
1313 | } | ||
1314 | |||
1315 | /* if speaker_outs is 0, then speakers may be in line_outs */ | ||
1316 | if (lfe_pin == 0 && spec->autocfg.speaker_outs == 0) { | ||
1317 | for (i = 0; i < spec->autocfg.line_outs && lfe_pin == 0x0; i++) { | ||
1318 | hda_nid_t pin = spec->autocfg.line_out_pins[i]; | ||
1319 | unsigned long cfg; | ||
1320 | cfg = snd_hda_codec_read(codec, pin, 0, | ||
1321 | AC_VERB_GET_CONFIG_DEFAULT, | ||
1322 | 0x00); | ||
1323 | if (get_defcfg_device(cfg) == AC_JACK_SPEAKER) { | ||
1324 | unsigned long wcaps = get_wcaps(codec, pin); | ||
1325 | wcaps &= (AC_WCAP_STEREO | AC_WCAP_OUT_AMP); | ||
1326 | if (wcaps == AC_WCAP_OUT_AMP) | ||
1327 | /* found a mono speaker with an amp, | ||
1328 | must be lfe */ | ||
1329 | lfe_pin = pin; | ||
1330 | } | ||
1331 | } | ||
1332 | } | ||
1333 | |||
1334 | if (lfe_pin) { | ||
1335 | err = create_controls(spec, "LFE", lfe_pin, 1); | ||
1336 | if (err < 0) | ||
1337 | return err; | ||
1338 | } | ||
1339 | |||
1340 | return 0; | ||
1341 | } | ||
1342 | |||
1010 | static int stac9200_parse_auto_config(struct hda_codec *codec) | 1343 | static int stac9200_parse_auto_config(struct hda_codec *codec) |
1011 | { | 1344 | { |
1012 | struct sigmatel_spec *spec = codec->spec; | 1345 | struct sigmatel_spec *spec = codec->spec; |
@@ -1021,6 +1354,9 @@ static int stac9200_parse_auto_config(struct hda_codec *codec) | |||
1021 | if ((err = stac9200_auto_create_hp_ctls(codec, &spec->autocfg)) < 0) | 1354 | if ((err = stac9200_auto_create_hp_ctls(codec, &spec->autocfg)) < 0) |
1022 | return err; | 1355 | return err; |
1023 | 1356 | ||
1357 | if ((err = stac9200_auto_create_lfe_ctls(codec, &spec->autocfg)) < 0) | ||
1358 | return err; | ||
1359 | |||
1024 | if (spec->autocfg.dig_out_pin) | 1360 | if (spec->autocfg.dig_out_pin) |
1025 | spec->multiout.dig_out_nid = 0x05; | 1361 | spec->multiout.dig_out_nid = 0x05; |
1026 | if (spec->autocfg.dig_in_pin) | 1362 | if (spec->autocfg.dig_in_pin) |
@@ -1073,6 +1409,15 @@ static void stac922x_gpio_mute(struct hda_codec *codec, int pin, int muted) | |||
1073 | AC_VERB_SET_GPIO_DATA, gpiostate); | 1409 | AC_VERB_SET_GPIO_DATA, gpiostate); |
1074 | } | 1410 | } |
1075 | 1411 | ||
1412 | static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, | ||
1413 | unsigned int event) | ||
1414 | { | ||
1415 | if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) | ||
1416 | snd_hda_codec_write(codec, nid, 0, | ||
1417 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
1418 | (AC_USRSP_EN | event)); | ||
1419 | } | ||
1420 | |||
1076 | static int stac92xx_init(struct hda_codec *codec) | 1421 | static int stac92xx_init(struct hda_codec *codec) |
1077 | { | 1422 | { |
1078 | struct sigmatel_spec *spec = codec->spec; | 1423 | struct sigmatel_spec *spec = codec->spec; |
@@ -1084,9 +1429,10 @@ static int stac92xx_init(struct hda_codec *codec) | |||
1084 | /* set up pins */ | 1429 | /* set up pins */ |
1085 | if (spec->hp_detect) { | 1430 | if (spec->hp_detect) { |
1086 | /* Enable unsolicited responses on the HP widget */ | 1431 | /* Enable unsolicited responses on the HP widget */ |
1087 | snd_hda_codec_write(codec, cfg->hp_pin, 0, | 1432 | for (i = 0; i < cfg->hp_outs; i++) |
1088 | AC_VERB_SET_UNSOLICITED_ENABLE, | 1433 | enable_pin_detect(codec, cfg->hp_pins[i], |
1089 | STAC_UNSOL_ENABLE); | 1434 | STAC_HP_EVENT); |
1435 | stac92xx_auto_init_hp_out(codec); | ||
1090 | /* fake event to set up pins */ | 1436 | /* fake event to set up pins */ |
1091 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | 1437 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); |
1092 | } else { | 1438 | } else { |
@@ -1131,6 +1477,9 @@ static void stac92xx_free(struct hda_codec *codec) | |||
1131 | kfree(spec->kctl_alloc); | 1477 | kfree(spec->kctl_alloc); |
1132 | } | 1478 | } |
1133 | 1479 | ||
1480 | if (spec->bios_pin_configs) | ||
1481 | kfree(spec->bios_pin_configs); | ||
1482 | |||
1134 | kfree(spec); | 1483 | kfree(spec); |
1135 | } | 1484 | } |
1136 | 1485 | ||
@@ -1139,6 +1488,8 @@ static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, | |||
1139 | { | 1488 | { |
1140 | unsigned int pin_ctl = snd_hda_codec_read(codec, nid, | 1489 | unsigned int pin_ctl = snd_hda_codec_read(codec, nid, |
1141 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); | 1490 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); |
1491 | if (flag == AC_PINCTL_OUT_EN && (pin_ctl & AC_PINCTL_IN_EN)) | ||
1492 | return; | ||
1142 | snd_hda_codec_write(codec, nid, 0, | 1493 | snd_hda_codec_write(codec, nid, 0, |
1143 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 1494 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
1144 | pin_ctl | flag); | 1495 | pin_ctl | flag); |
@@ -1154,33 +1505,57 @@ static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid, | |||
1154 | pin_ctl & ~flag); | 1505 | pin_ctl & ~flag); |
1155 | } | 1506 | } |
1156 | 1507 | ||
1157 | static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | 1508 | static int get_pin_presence(struct hda_codec *codec, hda_nid_t nid) |
1509 | { | ||
1510 | if (!nid) | ||
1511 | return 0; | ||
1512 | if (snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0x00) | ||
1513 | & (1 << 31)) | ||
1514 | return 1; | ||
1515 | return 0; | ||
1516 | } | ||
1517 | |||
1518 | static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res) | ||
1158 | { | 1519 | { |
1159 | struct sigmatel_spec *spec = codec->spec; | 1520 | struct sigmatel_spec *spec = codec->spec; |
1160 | struct auto_pin_cfg *cfg = &spec->autocfg; | 1521 | struct auto_pin_cfg *cfg = &spec->autocfg; |
1161 | int i, presence; | 1522 | int i, presence; |
1162 | 1523 | ||
1163 | if ((res >> 26) != STAC_HP_EVENT) | 1524 | presence = 0; |
1164 | return; | 1525 | for (i = 0; i < cfg->hp_outs; i++) { |
1165 | 1526 | presence = get_pin_presence(codec, cfg->hp_pins[i]); | |
1166 | presence = snd_hda_codec_read(codec, cfg->hp_pin, 0, | 1527 | if (presence) |
1167 | AC_VERB_GET_PIN_SENSE, 0x00) >> 31; | 1528 | break; |
1529 | } | ||
1168 | 1530 | ||
1169 | if (presence) { | 1531 | if (presence) { |
1170 | /* disable lineouts, enable hp */ | 1532 | /* disable lineouts, enable hp */ |
1171 | for (i = 0; i < cfg->line_outs; i++) | 1533 | for (i = 0; i < cfg->line_outs; i++) |
1172 | stac92xx_reset_pinctl(codec, cfg->line_out_pins[i], | 1534 | stac92xx_reset_pinctl(codec, cfg->line_out_pins[i], |
1173 | AC_PINCTL_OUT_EN); | 1535 | AC_PINCTL_OUT_EN); |
1174 | stac92xx_set_pinctl(codec, cfg->hp_pin, AC_PINCTL_OUT_EN); | 1536 | for (i = 0; i < cfg->speaker_outs; i++) |
1537 | stac92xx_reset_pinctl(codec, cfg->speaker_pins[i], | ||
1538 | AC_PINCTL_OUT_EN); | ||
1175 | } else { | 1539 | } else { |
1176 | /* enable lineouts, disable hp */ | 1540 | /* enable lineouts, disable hp */ |
1177 | for (i = 0; i < cfg->line_outs; i++) | 1541 | for (i = 0; i < cfg->line_outs; i++) |
1178 | stac92xx_set_pinctl(codec, cfg->line_out_pins[i], | 1542 | stac92xx_set_pinctl(codec, cfg->line_out_pins[i], |
1179 | AC_PINCTL_OUT_EN); | 1543 | AC_PINCTL_OUT_EN); |
1180 | stac92xx_reset_pinctl(codec, cfg->hp_pin, AC_PINCTL_OUT_EN); | 1544 | for (i = 0; i < cfg->speaker_outs; i++) |
1545 | stac92xx_set_pinctl(codec, cfg->speaker_pins[i], | ||
1546 | AC_PINCTL_OUT_EN); | ||
1181 | } | 1547 | } |
1182 | } | 1548 | } |
1183 | 1549 | ||
1550 | static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | ||
1551 | { | ||
1552 | switch (res >> 26) { | ||
1553 | case STAC_HP_EVENT: | ||
1554 | stac92xx_hp_detect(codec, res); | ||
1555 | break; | ||
1556 | } | ||
1557 | } | ||
1558 | |||
1184 | #ifdef CONFIG_PM | 1559 | #ifdef CONFIG_PM |
1185 | static int stac92xx_resume(struct hda_codec *codec) | 1560 | static int stac92xx_resume(struct hda_codec *codec) |
1186 | { | 1561 | { |
@@ -1188,6 +1563,7 @@ static int stac92xx_resume(struct hda_codec *codec) | |||
1188 | int i; | 1563 | int i; |
1189 | 1564 | ||
1190 | stac92xx_init(codec); | 1565 | stac92xx_init(codec); |
1566 | stac92xx_set_config_regs(codec); | ||
1191 | for (i = 0; i < spec->num_mixers; i++) | 1567 | for (i = 0; i < spec->num_mixers; i++) |
1192 | snd_hda_resume_ctls(codec, spec->mixers[i]); | 1568 | snd_hda_resume_ctls(codec, spec->mixers[i]); |
1193 | if (spec->multiout.dig_out_nid) | 1569 | if (spec->multiout.dig_out_nid) |
@@ -1220,12 +1596,18 @@ static int patch_stac9200(struct hda_codec *codec) | |||
1220 | return -ENOMEM; | 1596 | return -ENOMEM; |
1221 | 1597 | ||
1222 | codec->spec = spec; | 1598 | codec->spec = spec; |
1599 | spec->num_pins = 8; | ||
1600 | spec->pin_nids = stac9200_pin_nids; | ||
1223 | spec->board_config = snd_hda_check_board_config(codec, stac9200_cfg_tbl); | 1601 | spec->board_config = snd_hda_check_board_config(codec, stac9200_cfg_tbl); |
1224 | if (spec->board_config < 0) | 1602 | if (spec->board_config < 0) { |
1225 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9200, using BIOS defaults\n"); | 1603 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9200, using BIOS defaults\n"); |
1226 | else { | 1604 | err = stac92xx_save_bios_config_regs(codec); |
1227 | spec->num_pins = 8; | 1605 | if (err < 0) { |
1228 | spec->pin_nids = stac9200_pin_nids; | 1606 | stac92xx_free(codec); |
1607 | return err; | ||
1608 | } | ||
1609 | spec->pin_configs = spec->bios_pin_configs; | ||
1610 | } else { | ||
1229 | spec->pin_configs = stac9200_brd_tbl[spec->board_config]; | 1611 | spec->pin_configs = stac9200_brd_tbl[spec->board_config]; |
1230 | stac92xx_set_config_regs(codec); | 1612 | stac92xx_set_config_regs(codec); |
1231 | } | 1613 | } |
@@ -1261,13 +1643,19 @@ static int patch_stac922x(struct hda_codec *codec) | |||
1261 | return -ENOMEM; | 1643 | return -ENOMEM; |
1262 | 1644 | ||
1263 | codec->spec = spec; | 1645 | codec->spec = spec; |
1646 | spec->num_pins = 10; | ||
1647 | spec->pin_nids = stac922x_pin_nids; | ||
1264 | spec->board_config = snd_hda_check_board_config(codec, stac922x_cfg_tbl); | 1648 | spec->board_config = snd_hda_check_board_config(codec, stac922x_cfg_tbl); |
1265 | if (spec->board_config < 0) | 1649 | if (spec->board_config < 0) { |
1266 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, " | 1650 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, " |
1267 | "using BIOS defaults\n"); | 1651 | "using BIOS defaults\n"); |
1268 | else if (stac922x_brd_tbl[spec->board_config] != NULL) { | 1652 | err = stac92xx_save_bios_config_regs(codec); |
1269 | spec->num_pins = 10; | 1653 | if (err < 0) { |
1270 | spec->pin_nids = stac922x_pin_nids; | 1654 | stac92xx_free(codec); |
1655 | return err; | ||
1656 | } | ||
1657 | spec->pin_configs = spec->bios_pin_configs; | ||
1658 | } else if (stac922x_brd_tbl[spec->board_config] != NULL) { | ||
1271 | spec->pin_configs = stac922x_brd_tbl[spec->board_config]; | 1659 | spec->pin_configs = stac922x_brd_tbl[spec->board_config]; |
1272 | stac92xx_set_config_regs(codec); | 1660 | stac92xx_set_config_regs(codec); |
1273 | } | 1661 | } |
@@ -1281,25 +1669,6 @@ static int patch_stac922x(struct hda_codec *codec) | |||
1281 | 1669 | ||
1282 | spec->multiout.dac_nids = spec->dac_nids; | 1670 | spec->multiout.dac_nids = spec->dac_nids; |
1283 | 1671 | ||
1284 | switch (spec->board_config) { | ||
1285 | case STAC_D965_2112: | ||
1286 | spec->adc_nids = stac9227_adc_nids; | ||
1287 | spec->mux_nids = stac9227_mux_nids; | ||
1288 | #if 0 | ||
1289 | spec->multiout.dac_nids = d965_2112_dac_nids; | ||
1290 | spec->multiout.num_dacs = ARRAY_SIZE(d965_2112_dac_nids); | ||
1291 | #endif | ||
1292 | spec->init = d965_2112_core_init; | ||
1293 | spec->mixer = stac9227_mixer; | ||
1294 | break; | ||
1295 | case STAC_D965_284B: | ||
1296 | spec->adc_nids = stac9227_adc_nids; | ||
1297 | spec->mux_nids = stac9227_mux_nids; | ||
1298 | spec->init = stac9227_core_init; | ||
1299 | spec->mixer = stac9227_mixer; | ||
1300 | break; | ||
1301 | } | ||
1302 | |||
1303 | err = stac92xx_parse_auto_config(codec, 0x08, 0x09); | 1672 | err = stac92xx_parse_auto_config(codec, 0x08, 0x09); |
1304 | if (err < 0) { | 1673 | if (err < 0) { |
1305 | stac92xx_free(codec); | 1674 | stac92xx_free(codec); |
@@ -1324,26 +1693,94 @@ static int patch_stac927x(struct hda_codec *codec) | |||
1324 | return -ENOMEM; | 1693 | return -ENOMEM; |
1325 | 1694 | ||
1326 | codec->spec = spec; | 1695 | codec->spec = spec; |
1696 | spec->num_pins = 14; | ||
1697 | spec->pin_nids = stac927x_pin_nids; | ||
1327 | spec->board_config = snd_hda_check_board_config(codec, stac927x_cfg_tbl); | 1698 | spec->board_config = snd_hda_check_board_config(codec, stac927x_cfg_tbl); |
1328 | if (spec->board_config < 0) | 1699 | if (spec->board_config < 0) { |
1329 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC927x, using BIOS defaults\n"); | 1700 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC927x, using BIOS defaults\n"); |
1330 | else { | 1701 | err = stac92xx_save_bios_config_regs(codec); |
1331 | spec->num_pins = 14; | 1702 | if (err < 0) { |
1332 | spec->pin_nids = stac927x_pin_nids; | 1703 | stac92xx_free(codec); |
1704 | return err; | ||
1705 | } | ||
1706 | spec->pin_configs = spec->bios_pin_configs; | ||
1707 | } else if (stac927x_brd_tbl[spec->board_config] != NULL) { | ||
1333 | spec->pin_configs = stac927x_brd_tbl[spec->board_config]; | 1708 | spec->pin_configs = stac927x_brd_tbl[spec->board_config]; |
1334 | stac92xx_set_config_regs(codec); | 1709 | stac92xx_set_config_regs(codec); |
1335 | } | 1710 | } |
1336 | 1711 | ||
1337 | spec->adc_nids = stac927x_adc_nids; | 1712 | switch (spec->board_config) { |
1338 | spec->mux_nids = stac927x_mux_nids; | 1713 | case STAC_D965_3ST: |
1714 | spec->adc_nids = stac927x_adc_nids; | ||
1715 | spec->mux_nids = stac927x_mux_nids; | ||
1716 | spec->num_muxes = 3; | ||
1717 | spec->init = d965_core_init; | ||
1718 | spec->mixer = stac9227_mixer; | ||
1719 | break; | ||
1720 | case STAC_D965_5ST: | ||
1721 | spec->adc_nids = stac927x_adc_nids; | ||
1722 | spec->mux_nids = stac927x_mux_nids; | ||
1723 | spec->num_muxes = 3; | ||
1724 | spec->init = d965_core_init; | ||
1725 | spec->mixer = stac9227_mixer; | ||
1726 | break; | ||
1727 | default: | ||
1728 | spec->adc_nids = stac927x_adc_nids; | ||
1729 | spec->mux_nids = stac927x_mux_nids; | ||
1730 | spec->num_muxes = 3; | ||
1731 | spec->init = stac927x_core_init; | ||
1732 | spec->mixer = stac927x_mixer; | ||
1733 | } | ||
1734 | |||
1735 | spec->multiout.dac_nids = spec->dac_nids; | ||
1736 | |||
1737 | err = stac92xx_parse_auto_config(codec, 0x1e, 0x20); | ||
1738 | if (err < 0) { | ||
1739 | stac92xx_free(codec); | ||
1740 | return err; | ||
1741 | } | ||
1742 | |||
1743 | codec->patch_ops = stac92xx_patch_ops; | ||
1744 | |||
1745 | return 0; | ||
1746 | } | ||
1747 | |||
1748 | static int patch_stac9205(struct hda_codec *codec) | ||
1749 | { | ||
1750 | struct sigmatel_spec *spec; | ||
1751 | int err; | ||
1752 | |||
1753 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1754 | if (spec == NULL) | ||
1755 | return -ENOMEM; | ||
1756 | |||
1757 | codec->spec = spec; | ||
1758 | spec->num_pins = 14; | ||
1759 | spec->pin_nids = stac9205_pin_nids; | ||
1760 | spec->board_config = snd_hda_check_board_config(codec, stac9205_cfg_tbl); | ||
1761 | if (spec->board_config < 0) { | ||
1762 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9205, using BIOS defaults\n"); | ||
1763 | err = stac92xx_save_bios_config_regs(codec); | ||
1764 | if (err < 0) { | ||
1765 | stac92xx_free(codec); | ||
1766 | return err; | ||
1767 | } | ||
1768 | spec->pin_configs = spec->bios_pin_configs; | ||
1769 | } else { | ||
1770 | spec->pin_configs = stac9205_brd_tbl[spec->board_config]; | ||
1771 | stac92xx_set_config_regs(codec); | ||
1772 | } | ||
1773 | |||
1774 | spec->adc_nids = stac9205_adc_nids; | ||
1775 | spec->mux_nids = stac9205_mux_nids; | ||
1339 | spec->num_muxes = 3; | 1776 | spec->num_muxes = 3; |
1340 | 1777 | ||
1341 | spec->init = stac927x_core_init; | 1778 | spec->init = stac9205_core_init; |
1342 | spec->mixer = stac927x_mixer; | 1779 | spec->mixer = stac9205_mixer; |
1343 | 1780 | ||
1344 | spec->multiout.dac_nids = spec->dac_nids; | 1781 | spec->multiout.dac_nids = spec->dac_nids; |
1345 | 1782 | ||
1346 | err = stac92xx_parse_auto_config(codec, 0x1e, 0x20); | 1783 | err = stac92xx_parse_auto_config(codec, 0x1f, 0x20); |
1347 | if (err < 0) { | 1784 | if (err < 0) { |
1348 | stac92xx_free(codec); | 1785 | stac92xx_free(codec); |
1349 | return err; | 1786 | return err; |
@@ -1355,10 +1792,10 @@ static int patch_stac927x(struct hda_codec *codec) | |||
1355 | } | 1792 | } |
1356 | 1793 | ||
1357 | /* | 1794 | /* |
1358 | * STAC 7661(?) hack | 1795 | * STAC9872 hack |
1359 | */ | 1796 | */ |
1360 | 1797 | ||
1361 | /* static config for Sony VAIO FE550G */ | 1798 | /* static config for Sony VAIO FE550G and Sony VAIO AR */ |
1362 | static hda_nid_t vaio_dacs[] = { 0x2 }; | 1799 | static hda_nid_t vaio_dacs[] = { 0x2 }; |
1363 | #define VAIO_HP_DAC 0x5 | 1800 | #define VAIO_HP_DAC 0x5 |
1364 | static hda_nid_t vaio_adcs[] = { 0x8 /*,0x6*/ }; | 1801 | static hda_nid_t vaio_adcs[] = { 0x8 /*,0x6*/ }; |
@@ -1389,6 +1826,23 @@ static struct hda_verb vaio_init[] = { | |||
1389 | {} | 1826 | {} |
1390 | }; | 1827 | }; |
1391 | 1828 | ||
1829 | static struct hda_verb vaio_ar_init[] = { | ||
1830 | {0x0a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP <- 0x2 */ | ||
1831 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Speaker <- 0x5 */ | ||
1832 | {0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */ | ||
1833 | {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */ | ||
1834 | /* {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },*/ /* Optical Out */ | ||
1835 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */ | ||
1836 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x2}, /* mic-sel: 0a,0d,14,02 */ | ||
1837 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */ | ||
1838 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */ | ||
1839 | /* {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},*/ /* Optical Out */ | ||
1840 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* capture sw/vol -> 0x8 */ | ||
1841 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* CD-in -> 0x6 */ | ||
1842 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */ | ||
1843 | {} | ||
1844 | }; | ||
1845 | |||
1392 | /* bind volumes of both NID 0x02 and 0x05 */ | 1846 | /* bind volumes of both NID 0x02 and 0x05 */ |
1393 | static int vaio_master_vol_put(struct snd_kcontrol *kcontrol, | 1847 | static int vaio_master_vol_put(struct snd_kcontrol *kcontrol, |
1394 | struct snd_ctl_elem_value *ucontrol) | 1848 | struct snd_ctl_elem_value *ucontrol) |
@@ -1434,6 +1888,38 @@ static struct snd_kcontrol_new vaio_mixer[] = { | |||
1434 | .info = snd_hda_mixer_amp_volume_info, | 1888 | .info = snd_hda_mixer_amp_volume_info, |
1435 | .get = snd_hda_mixer_amp_volume_get, | 1889 | .get = snd_hda_mixer_amp_volume_get, |
1436 | .put = vaio_master_vol_put, | 1890 | .put = vaio_master_vol_put, |
1891 | .tlv = { .c = snd_hda_mixer_amp_tlv }, | ||
1892 | .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), | ||
1893 | }, | ||
1894 | { | ||
1895 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1896 | .name = "Master Playback Switch", | ||
1897 | .info = snd_hda_mixer_amp_switch_info, | ||
1898 | .get = snd_hda_mixer_amp_switch_get, | ||
1899 | .put = vaio_master_sw_put, | ||
1900 | .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), | ||
1901 | }, | ||
1902 | /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ | ||
1903 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), | ||
1904 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), | ||
1905 | { | ||
1906 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1907 | .name = "Capture Source", | ||
1908 | .count = 1, | ||
1909 | .info = stac92xx_mux_enum_info, | ||
1910 | .get = stac92xx_mux_enum_get, | ||
1911 | .put = stac92xx_mux_enum_put, | ||
1912 | }, | ||
1913 | {} | ||
1914 | }; | ||
1915 | |||
1916 | static struct snd_kcontrol_new vaio_ar_mixer[] = { | ||
1917 | { | ||
1918 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1919 | .name = "Master Playback Volume", | ||
1920 | .info = snd_hda_mixer_amp_volume_info, | ||
1921 | .get = snd_hda_mixer_amp_volume_get, | ||
1922 | .put = vaio_master_vol_put, | ||
1437 | .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), | 1923 | .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), |
1438 | }, | 1924 | }, |
1439 | { | 1925 | { |
@@ -1447,6 +1933,8 @@ static struct snd_kcontrol_new vaio_mixer[] = { | |||
1447 | /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ | 1933 | /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ |
1448 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), | 1934 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), |
1449 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), | 1935 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), |
1936 | /*HDA_CODEC_MUTE("Optical Out Switch", 0x10, 0, HDA_OUTPUT), | ||
1937 | HDA_CODEC_VOLUME("Optical Out Volume", 0x10, 0, HDA_OUTPUT),*/ | ||
1450 | { | 1938 | { |
1451 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1939 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1452 | .name = "Capture Source", | 1940 | .name = "Capture Source", |
@@ -1458,7 +1946,7 @@ static struct snd_kcontrol_new vaio_mixer[] = { | |||
1458 | {} | 1946 | {} |
1459 | }; | 1947 | }; |
1460 | 1948 | ||
1461 | static struct hda_codec_ops stac7661_patch_ops = { | 1949 | static struct hda_codec_ops stac9872_patch_ops = { |
1462 | .build_controls = stac92xx_build_controls, | 1950 | .build_controls = stac92xx_build_controls, |
1463 | .build_pcms = stac92xx_build_pcms, | 1951 | .build_pcms = stac92xx_build_pcms, |
1464 | .init = stac92xx_init, | 1952 | .init = stac92xx_init, |
@@ -1468,23 +1956,34 @@ static struct hda_codec_ops stac7661_patch_ops = { | |||
1468 | #endif | 1956 | #endif |
1469 | }; | 1957 | }; |
1470 | 1958 | ||
1471 | enum { STAC7661_VAIO }; | 1959 | enum { /* FE and SZ series. id=0x83847661 and subsys=0x104D0700 or 104D1000. */ |
1472 | 1960 | CXD9872RD_VAIO, | |
1473 | static struct hda_board_config stac7661_cfg_tbl[] = { | 1961 | /* Unknown. id=0x83847662 and subsys=0x104D1200 or 104D1000. */ |
1474 | { .modelname = "vaio", .config = STAC7661_VAIO }, | 1962 | STAC9872AK_VAIO, |
1963 | /* Unknown. id=0x83847661 and subsys=0x104D1200. */ | ||
1964 | STAC9872K_VAIO, | ||
1965 | /* AR Series. id=0x83847664 and subsys=104D1300 */ | ||
1966 | CXD9872AKD_VAIO | ||
1967 | }; | ||
1968 | |||
1969 | static struct hda_board_config stac9872_cfg_tbl[] = { | ||
1970 | { .modelname = "vaio", .config = CXD9872RD_VAIO }, | ||
1971 | { .modelname = "vaio-ar", .config = CXD9872AKD_VAIO }, | ||
1475 | { .pci_subvendor = 0x104d, .pci_subdevice = 0x81e6, | 1972 | { .pci_subvendor = 0x104d, .pci_subdevice = 0x81e6, |
1476 | .config = STAC7661_VAIO }, | 1973 | .config = CXD9872RD_VAIO }, |
1477 | { .pci_subvendor = 0x104d, .pci_subdevice = 0x81ef, | 1974 | { .pci_subvendor = 0x104d, .pci_subdevice = 0x81ef, |
1478 | .config = STAC7661_VAIO }, | 1975 | .config = CXD9872RD_VAIO }, |
1976 | { .pci_subvendor = 0x104d, .pci_subdevice = 0x81fd, | ||
1977 | .config = CXD9872AKD_VAIO }, | ||
1479 | {} | 1978 | {} |
1480 | }; | 1979 | }; |
1481 | 1980 | ||
1482 | static int patch_stac7661(struct hda_codec *codec) | 1981 | static int patch_stac9872(struct hda_codec *codec) |
1483 | { | 1982 | { |
1484 | struct sigmatel_spec *spec; | 1983 | struct sigmatel_spec *spec; |
1485 | int board_config; | 1984 | int board_config; |
1486 | 1985 | ||
1487 | board_config = snd_hda_check_board_config(codec, stac7661_cfg_tbl); | 1986 | board_config = snd_hda_check_board_config(codec, stac9872_cfg_tbl); |
1488 | if (board_config < 0) | 1987 | if (board_config < 0) |
1489 | /* unknown config, let generic-parser do its job... */ | 1988 | /* unknown config, let generic-parser do its job... */ |
1490 | return snd_hda_parse_generic_codec(codec); | 1989 | return snd_hda_parse_generic_codec(codec); |
@@ -1495,7 +1994,9 @@ static int patch_stac7661(struct hda_codec *codec) | |||
1495 | 1994 | ||
1496 | codec->spec = spec; | 1995 | codec->spec = spec; |
1497 | switch (board_config) { | 1996 | switch (board_config) { |
1498 | case STAC7661_VAIO: | 1997 | case CXD9872RD_VAIO: |
1998 | case STAC9872AK_VAIO: | ||
1999 | case STAC9872K_VAIO: | ||
1499 | spec->mixer = vaio_mixer; | 2000 | spec->mixer = vaio_mixer; |
1500 | spec->init = vaio_init; | 2001 | spec->init = vaio_init; |
1501 | spec->multiout.max_channels = 2; | 2002 | spec->multiout.max_channels = 2; |
@@ -1507,9 +2008,22 @@ static int patch_stac7661(struct hda_codec *codec) | |||
1507 | spec->input_mux = &vaio_mux; | 2008 | spec->input_mux = &vaio_mux; |
1508 | spec->mux_nids = vaio_mux_nids; | 2009 | spec->mux_nids = vaio_mux_nids; |
1509 | break; | 2010 | break; |
2011 | |||
2012 | case CXD9872AKD_VAIO: | ||
2013 | spec->mixer = vaio_ar_mixer; | ||
2014 | spec->init = vaio_ar_init; | ||
2015 | spec->multiout.max_channels = 2; | ||
2016 | spec->multiout.num_dacs = ARRAY_SIZE(vaio_dacs); | ||
2017 | spec->multiout.dac_nids = vaio_dacs; | ||
2018 | spec->multiout.hp_nid = VAIO_HP_DAC; | ||
2019 | spec->num_adcs = ARRAY_SIZE(vaio_adcs); | ||
2020 | spec->adc_nids = vaio_adcs; | ||
2021 | spec->input_mux = &vaio_mux; | ||
2022 | spec->mux_nids = vaio_mux_nids; | ||
2023 | break; | ||
1510 | } | 2024 | } |
1511 | 2025 | ||
1512 | codec->patch_ops = stac7661_patch_ops; | 2026 | codec->patch_ops = stac9872_patch_ops; |
1513 | return 0; | 2027 | return 0; |
1514 | } | 2028 | } |
1515 | 2029 | ||
@@ -1525,12 +2039,12 @@ struct hda_codec_preset snd_hda_preset_sigmatel[] = { | |||
1525 | { .id = 0x83847681, .name = "STAC9220D/9223D A2", .patch = patch_stac922x }, | 2039 | { .id = 0x83847681, .name = "STAC9220D/9223D A2", .patch = patch_stac922x }, |
1526 | { .id = 0x83847682, .name = "STAC9221 A2", .patch = patch_stac922x }, | 2040 | { .id = 0x83847682, .name = "STAC9221 A2", .patch = patch_stac922x }, |
1527 | { .id = 0x83847683, .name = "STAC9221D A2", .patch = patch_stac922x }, | 2041 | { .id = 0x83847683, .name = "STAC9221D A2", .patch = patch_stac922x }, |
1528 | { .id = 0x83847618, .name = "STAC9227", .patch = patch_stac922x }, | 2042 | { .id = 0x83847618, .name = "STAC9227", .patch = patch_stac927x }, |
1529 | { .id = 0x83847619, .name = "STAC9227", .patch = patch_stac922x }, | 2043 | { .id = 0x83847619, .name = "STAC9227", .patch = patch_stac927x }, |
1530 | { .id = 0x83847616, .name = "STAC9228", .patch = patch_stac922x }, | 2044 | { .id = 0x83847616, .name = "STAC9228", .patch = patch_stac927x }, |
1531 | { .id = 0x83847617, .name = "STAC9228", .patch = patch_stac922x }, | 2045 | { .id = 0x83847617, .name = "STAC9228", .patch = patch_stac927x }, |
1532 | { .id = 0x83847614, .name = "STAC9229", .patch = patch_stac922x }, | 2046 | { .id = 0x83847614, .name = "STAC9229", .patch = patch_stac927x }, |
1533 | { .id = 0x83847615, .name = "STAC9229", .patch = patch_stac922x }, | 2047 | { .id = 0x83847615, .name = "STAC9229", .patch = patch_stac927x }, |
1534 | { .id = 0x83847620, .name = "STAC9274", .patch = patch_stac927x }, | 2048 | { .id = 0x83847620, .name = "STAC9274", .patch = patch_stac927x }, |
1535 | { .id = 0x83847621, .name = "STAC9274D", .patch = patch_stac927x }, | 2049 | { .id = 0x83847621, .name = "STAC9274D", .patch = patch_stac927x }, |
1536 | { .id = 0x83847622, .name = "STAC9273X", .patch = patch_stac927x }, | 2050 | { .id = 0x83847622, .name = "STAC9273X", .patch = patch_stac927x }, |
@@ -1541,6 +2055,20 @@ struct hda_codec_preset snd_hda_preset_sigmatel[] = { | |||
1541 | { .id = 0x83847627, .name = "STAC9271D", .patch = patch_stac927x }, | 2055 | { .id = 0x83847627, .name = "STAC9271D", .patch = patch_stac927x }, |
1542 | { .id = 0x83847628, .name = "STAC9274X5NH", .patch = patch_stac927x }, | 2056 | { .id = 0x83847628, .name = "STAC9274X5NH", .patch = patch_stac927x }, |
1543 | { .id = 0x83847629, .name = "STAC9274D5NH", .patch = patch_stac927x }, | 2057 | { .id = 0x83847629, .name = "STAC9274D5NH", .patch = patch_stac927x }, |
1544 | { .id = 0x83847661, .name = "STAC7661", .patch = patch_stac7661 }, | 2058 | /* The following does not take into account .id=0x83847661 when subsys = |
2059 | * 104D0C00 which is STAC9225s. Because of this, some SZ Notebooks are | ||
2060 | * currently not fully supported. | ||
2061 | */ | ||
2062 | { .id = 0x83847661, .name = "CXD9872RD/K", .patch = patch_stac9872 }, | ||
2063 | { .id = 0x83847662, .name = "STAC9872AK", .patch = patch_stac9872 }, | ||
2064 | { .id = 0x83847664, .name = "CXD9872AKD", .patch = patch_stac9872 }, | ||
2065 | { .id = 0x838476a0, .name = "STAC9205", .patch = patch_stac9205 }, | ||
2066 | { .id = 0x838476a1, .name = "STAC9205D", .patch = patch_stac9205 }, | ||
2067 | { .id = 0x838476a2, .name = "STAC9204", .patch = patch_stac9205 }, | ||
2068 | { .id = 0x838476a3, .name = "STAC9204D", .patch = patch_stac9205 }, | ||
2069 | { .id = 0x838476a4, .name = "STAC9255", .patch = patch_stac9205 }, | ||
2070 | { .id = 0x838476a5, .name = "STAC9255D", .patch = patch_stac9205 }, | ||
2071 | { .id = 0x838476a6, .name = "STAC9254", .patch = patch_stac9205 }, | ||
2072 | { .id = 0x838476a7, .name = "STAC9254D", .patch = patch_stac9205 }, | ||
1545 | {} /* terminator */ | 2073 | {} /* terminator */ |
1546 | }; | 2074 | }; |
diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c index 9492f3d2455b..9e76cebd2d22 100644 --- a/sound/pci/ice1712/aureon.c +++ b/sound/pci/ice1712/aureon.c | |||
@@ -60,6 +60,7 @@ | |||
60 | #include "ice1712.h" | 60 | #include "ice1712.h" |
61 | #include "envy24ht.h" | 61 | #include "envy24ht.h" |
62 | #include "aureon.h" | 62 | #include "aureon.h" |
63 | #include <sound/tlv.h> | ||
63 | 64 | ||
64 | /* WM8770 registers */ | 65 | /* WM8770 registers */ |
65 | #define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */ | 66 | #define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */ |
@@ -660,6 +661,12 @@ static int aureon_ac97_mmute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
660 | return change; | 661 | return change; |
661 | } | 662 | } |
662 | 663 | ||
664 | static DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1); | ||
665 | static DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1); | ||
666 | static DECLARE_TLV_DB_SCALE(db_scale_wm_adc, -1200, 100, 0); | ||
667 | static DECLARE_TLV_DB_SCALE(db_scale_ac97_master, -4650, 150, 0); | ||
668 | static DECLARE_TLV_DB_SCALE(db_scale_ac97_gain, -3450, 150, 0); | ||
669 | |||
663 | /* | 670 | /* |
664 | * Logarithmic volume values for WM8770 | 671 | * Logarithmic volume values for WM8770 |
665 | * Computed as 20 * Log10(255 / x) | 672 | * Computed as 20 * Log10(255 / x) |
@@ -1409,10 +1416,13 @@ static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = { | |||
1409 | }, | 1416 | }, |
1410 | { | 1417 | { |
1411 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1418 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1419 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
1420 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
1412 | .name = "Master Playback Volume", | 1421 | .name = "Master Playback Volume", |
1413 | .info = wm_master_vol_info, | 1422 | .info = wm_master_vol_info, |
1414 | .get = wm_master_vol_get, | 1423 | .get = wm_master_vol_get, |
1415 | .put = wm_master_vol_put | 1424 | .put = wm_master_vol_put, |
1425 | .tlv = { .p = db_scale_wm_dac } | ||
1416 | }, | 1426 | }, |
1417 | { | 1427 | { |
1418 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1428 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -1424,11 +1434,14 @@ static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = { | |||
1424 | }, | 1434 | }, |
1425 | { | 1435 | { |
1426 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1436 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1437 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
1438 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
1427 | .name = "Front Playback Volume", | 1439 | .name = "Front Playback Volume", |
1428 | .info = wm_vol_info, | 1440 | .info = wm_vol_info, |
1429 | .get = wm_vol_get, | 1441 | .get = wm_vol_get, |
1430 | .put = wm_vol_put, | 1442 | .put = wm_vol_put, |
1431 | .private_value = (2 << 8) | 0 | 1443 | .private_value = (2 << 8) | 0, |
1444 | .tlv = { .p = db_scale_wm_dac } | ||
1432 | }, | 1445 | }, |
1433 | { | 1446 | { |
1434 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1447 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -1440,11 +1453,14 @@ static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = { | |||
1440 | }, | 1453 | }, |
1441 | { | 1454 | { |
1442 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1455 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1456 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
1457 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
1443 | .name = "Rear Playback Volume", | 1458 | .name = "Rear Playback Volume", |
1444 | .info = wm_vol_info, | 1459 | .info = wm_vol_info, |
1445 | .get = wm_vol_get, | 1460 | .get = wm_vol_get, |
1446 | .put = wm_vol_put, | 1461 | .put = wm_vol_put, |
1447 | .private_value = (2 << 8) | 2 | 1462 | .private_value = (2 << 8) | 2, |
1463 | .tlv = { .p = db_scale_wm_dac } | ||
1448 | }, | 1464 | }, |
1449 | { | 1465 | { |
1450 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1466 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -1456,11 +1472,14 @@ static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = { | |||
1456 | }, | 1472 | }, |
1457 | { | 1473 | { |
1458 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1474 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1475 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
1476 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
1459 | .name = "Center Playback Volume", | 1477 | .name = "Center Playback Volume", |
1460 | .info = wm_vol_info, | 1478 | .info = wm_vol_info, |
1461 | .get = wm_vol_get, | 1479 | .get = wm_vol_get, |
1462 | .put = wm_vol_put, | 1480 | .put = wm_vol_put, |
1463 | .private_value = (1 << 8) | 4 | 1481 | .private_value = (1 << 8) | 4, |
1482 | .tlv = { .p = db_scale_wm_dac } | ||
1464 | }, | 1483 | }, |
1465 | { | 1484 | { |
1466 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1485 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -1472,11 +1491,14 @@ static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = { | |||
1472 | }, | 1491 | }, |
1473 | { | 1492 | { |
1474 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1493 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1494 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
1495 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
1475 | .name = "LFE Playback Volume", | 1496 | .name = "LFE Playback Volume", |
1476 | .info = wm_vol_info, | 1497 | .info = wm_vol_info, |
1477 | .get = wm_vol_get, | 1498 | .get = wm_vol_get, |
1478 | .put = wm_vol_put, | 1499 | .put = wm_vol_put, |
1479 | .private_value = (1 << 8) | 5 | 1500 | .private_value = (1 << 8) | 5, |
1501 | .tlv = { .p = db_scale_wm_dac } | ||
1480 | }, | 1502 | }, |
1481 | { | 1503 | { |
1482 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1504 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -1488,11 +1510,14 @@ static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = { | |||
1488 | }, | 1510 | }, |
1489 | { | 1511 | { |
1490 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1512 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1513 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
1514 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
1491 | .name = "Side Playback Volume", | 1515 | .name = "Side Playback Volume", |
1492 | .info = wm_vol_info, | 1516 | .info = wm_vol_info, |
1493 | .get = wm_vol_get, | 1517 | .get = wm_vol_get, |
1494 | .put = wm_vol_put, | 1518 | .put = wm_vol_put, |
1495 | .private_value = (2 << 8) | 6 | 1519 | .private_value = (2 << 8) | 6, |
1520 | .tlv = { .p = db_scale_wm_dac } | ||
1496 | } | 1521 | } |
1497 | }; | 1522 | }; |
1498 | 1523 | ||
@@ -1506,10 +1531,13 @@ static struct snd_kcontrol_new wm_controls[] __devinitdata = { | |||
1506 | }, | 1531 | }, |
1507 | { | 1532 | { |
1508 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1533 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1534 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
1535 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
1509 | .name = "PCM Playback Volume", | 1536 | .name = "PCM Playback Volume", |
1510 | .info = wm_pcm_vol_info, | 1537 | .info = wm_pcm_vol_info, |
1511 | .get = wm_pcm_vol_get, | 1538 | .get = wm_pcm_vol_get, |
1512 | .put = wm_pcm_vol_put | 1539 | .put = wm_pcm_vol_put, |
1540 | .tlv = { .p = db_scale_wm_pcm } | ||
1513 | }, | 1541 | }, |
1514 | { | 1542 | { |
1515 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1543 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -1520,10 +1548,13 @@ static struct snd_kcontrol_new wm_controls[] __devinitdata = { | |||
1520 | }, | 1548 | }, |
1521 | { | 1549 | { |
1522 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1550 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1551 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
1552 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
1523 | .name = "Capture Volume", | 1553 | .name = "Capture Volume", |
1524 | .info = wm_adc_vol_info, | 1554 | .info = wm_adc_vol_info, |
1525 | .get = wm_adc_vol_get, | 1555 | .get = wm_adc_vol_get, |
1526 | .put = wm_adc_vol_put | 1556 | .put = wm_adc_vol_put, |
1557 | .tlv = { .p = db_scale_wm_adc } | ||
1527 | }, | 1558 | }, |
1528 | { | 1559 | { |
1529 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1560 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -1567,11 +1598,14 @@ static struct snd_kcontrol_new ac97_controls[] __devinitdata = { | |||
1567 | }, | 1598 | }, |
1568 | { | 1599 | { |
1569 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1600 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1601 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
1602 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
1570 | .name = "AC97 Playback Volume", | 1603 | .name = "AC97 Playback Volume", |
1571 | .info = aureon_ac97_vol_info, | 1604 | .info = aureon_ac97_vol_info, |
1572 | .get = aureon_ac97_vol_get, | 1605 | .get = aureon_ac97_vol_get, |
1573 | .put = aureon_ac97_vol_put, | 1606 | .put = aureon_ac97_vol_put, |
1574 | .private_value = AC97_MASTER|AUREON_AC97_STEREO | 1607 | .private_value = AC97_MASTER|AUREON_AC97_STEREO, |
1608 | .tlv = { .p = db_scale_ac97_master } | ||
1575 | }, | 1609 | }, |
1576 | { | 1610 | { |
1577 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1611 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -1583,11 +1617,14 @@ static struct snd_kcontrol_new ac97_controls[] __devinitdata = { | |||
1583 | }, | 1617 | }, |
1584 | { | 1618 | { |
1585 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1619 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1620 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
1621 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
1586 | .name = "CD Playback Volume", | 1622 | .name = "CD Playback Volume", |
1587 | .info = aureon_ac97_vol_info, | 1623 | .info = aureon_ac97_vol_info, |
1588 | .get = aureon_ac97_vol_get, | 1624 | .get = aureon_ac97_vol_get, |
1589 | .put = aureon_ac97_vol_put, | 1625 | .put = aureon_ac97_vol_put, |
1590 | .private_value = AC97_CD|AUREON_AC97_STEREO | 1626 | .private_value = AC97_CD|AUREON_AC97_STEREO, |
1627 | .tlv = { .p = db_scale_ac97_gain } | ||
1591 | }, | 1628 | }, |
1592 | { | 1629 | { |
1593 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1630 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -1599,11 +1636,14 @@ static struct snd_kcontrol_new ac97_controls[] __devinitdata = { | |||
1599 | }, | 1636 | }, |
1600 | { | 1637 | { |
1601 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1638 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1639 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
1640 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
1602 | .name = "Aux Playback Volume", | 1641 | .name = "Aux Playback Volume", |
1603 | .info = aureon_ac97_vol_info, | 1642 | .info = aureon_ac97_vol_info, |
1604 | .get = aureon_ac97_vol_get, | 1643 | .get = aureon_ac97_vol_get, |
1605 | .put = aureon_ac97_vol_put, | 1644 | .put = aureon_ac97_vol_put, |
1606 | .private_value = AC97_AUX|AUREON_AC97_STEREO | 1645 | .private_value = AC97_AUX|AUREON_AC97_STEREO, |
1646 | .tlv = { .p = db_scale_ac97_gain } | ||
1607 | }, | 1647 | }, |
1608 | { | 1648 | { |
1609 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1649 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -1615,11 +1655,14 @@ static struct snd_kcontrol_new ac97_controls[] __devinitdata = { | |||
1615 | }, | 1655 | }, |
1616 | { | 1656 | { |
1617 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1657 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1658 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
1659 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
1618 | .name = "Line Playback Volume", | 1660 | .name = "Line Playback Volume", |
1619 | .info = aureon_ac97_vol_info, | 1661 | .info = aureon_ac97_vol_info, |
1620 | .get = aureon_ac97_vol_get, | 1662 | .get = aureon_ac97_vol_get, |
1621 | .put = aureon_ac97_vol_put, | 1663 | .put = aureon_ac97_vol_put, |
1622 | .private_value = AC97_LINE|AUREON_AC97_STEREO | 1664 | .private_value = AC97_LINE|AUREON_AC97_STEREO, |
1665 | .tlv = { .p = db_scale_ac97_gain } | ||
1623 | }, | 1666 | }, |
1624 | { | 1667 | { |
1625 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1668 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -1631,11 +1674,14 @@ static struct snd_kcontrol_new ac97_controls[] __devinitdata = { | |||
1631 | }, | 1674 | }, |
1632 | { | 1675 | { |
1633 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1676 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1677 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
1678 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
1634 | .name = "Mic Playback Volume", | 1679 | .name = "Mic Playback Volume", |
1635 | .info = aureon_ac97_vol_info, | 1680 | .info = aureon_ac97_vol_info, |
1636 | .get = aureon_ac97_vol_get, | 1681 | .get = aureon_ac97_vol_get, |
1637 | .put = aureon_ac97_vol_put, | 1682 | .put = aureon_ac97_vol_put, |
1638 | .private_value = AC97_MIC | 1683 | .private_value = AC97_MIC, |
1684 | .tlv = { .p = db_scale_ac97_gain } | ||
1639 | }, | 1685 | }, |
1640 | { | 1686 | { |
1641 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1687 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -1657,11 +1703,14 @@ static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = { | |||
1657 | }, | 1703 | }, |
1658 | { | 1704 | { |
1659 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1705 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1706 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
1707 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
1660 | .name = "AC97 Playback Volume", | 1708 | .name = "AC97 Playback Volume", |
1661 | .info = aureon_ac97_vol_info, | 1709 | .info = aureon_ac97_vol_info, |
1662 | .get = aureon_ac97_vol_get, | 1710 | .get = aureon_ac97_vol_get, |
1663 | .put = aureon_ac97_vol_put, | 1711 | .put = aureon_ac97_vol_put, |
1664 | .private_value = AC97_MASTER|AUREON_AC97_STEREO | 1712 | .private_value = AC97_MASTER|AUREON_AC97_STEREO, |
1713 | .tlv = { .p = db_scale_ac97_master } | ||
1665 | }, | 1714 | }, |
1666 | { | 1715 | { |
1667 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1716 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -1673,11 +1722,14 @@ static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = { | |||
1673 | }, | 1722 | }, |
1674 | { | 1723 | { |
1675 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1724 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1725 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
1726 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
1676 | .name = "CD Playback Volume", | 1727 | .name = "CD Playback Volume", |
1677 | .info = aureon_ac97_vol_info, | 1728 | .info = aureon_ac97_vol_info, |
1678 | .get = aureon_ac97_vol_get, | 1729 | .get = aureon_ac97_vol_get, |
1679 | .put = aureon_ac97_vol_put, | 1730 | .put = aureon_ac97_vol_put, |
1680 | .private_value = AC97_AUX|AUREON_AC97_STEREO | 1731 | .private_value = AC97_AUX|AUREON_AC97_STEREO, |
1732 | .tlv = { .p = db_scale_ac97_gain } | ||
1681 | }, | 1733 | }, |
1682 | { | 1734 | { |
1683 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1735 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -1685,15 +1737,18 @@ static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = { | |||
1685 | .info = aureon_ac97_mute_info, | 1737 | .info = aureon_ac97_mute_info, |
1686 | .get = aureon_ac97_mute_get, | 1738 | .get = aureon_ac97_mute_get, |
1687 | .put = aureon_ac97_mute_put, | 1739 | .put = aureon_ac97_mute_put, |
1688 | .private_value = AC97_CD, | 1740 | .private_value = AC97_CD |
1689 | }, | 1741 | }, |
1690 | { | 1742 | { |
1691 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1743 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1744 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
1745 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
1692 | .name = "Phono Playback Volume", | 1746 | .name = "Phono Playback Volume", |
1693 | .info = aureon_ac97_vol_info, | 1747 | .info = aureon_ac97_vol_info, |
1694 | .get = aureon_ac97_vol_get, | 1748 | .get = aureon_ac97_vol_get, |
1695 | .put = aureon_ac97_vol_put, | 1749 | .put = aureon_ac97_vol_put, |
1696 | .private_value = AC97_CD|AUREON_AC97_STEREO | 1750 | .private_value = AC97_CD|AUREON_AC97_STEREO, |
1751 | .tlv = { .p = db_scale_ac97_gain } | ||
1697 | }, | 1752 | }, |
1698 | { | 1753 | { |
1699 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1754 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -1705,11 +1760,14 @@ static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = { | |||
1705 | }, | 1760 | }, |
1706 | { | 1761 | { |
1707 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1762 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1763 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
1764 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
1708 | .name = "Line Playback Volume", | 1765 | .name = "Line Playback Volume", |
1709 | .info = aureon_ac97_vol_info, | 1766 | .info = aureon_ac97_vol_info, |
1710 | .get = aureon_ac97_vol_get, | 1767 | .get = aureon_ac97_vol_get, |
1711 | .put = aureon_ac97_vol_put, | 1768 | .put = aureon_ac97_vol_put, |
1712 | .private_value = AC97_LINE|AUREON_AC97_STEREO | 1769 | .private_value = AC97_LINE|AUREON_AC97_STEREO, |
1770 | .tlv = { .p = db_scale_ac97_gain } | ||
1713 | }, | 1771 | }, |
1714 | { | 1772 | { |
1715 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1773 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -1721,11 +1779,14 @@ static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = { | |||
1721 | }, | 1779 | }, |
1722 | { | 1780 | { |
1723 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1781 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1782 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
1783 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
1724 | .name = "Mic Playback Volume", | 1784 | .name = "Mic Playback Volume", |
1725 | .info = aureon_ac97_vol_info, | 1785 | .info = aureon_ac97_vol_info, |
1726 | .get = aureon_ac97_vol_get, | 1786 | .get = aureon_ac97_vol_get, |
1727 | .put = aureon_ac97_vol_put, | 1787 | .put = aureon_ac97_vol_put, |
1728 | .private_value = AC97_MIC | 1788 | .private_value = AC97_MIC, |
1789 | .tlv = { .p = db_scale_ac97_gain } | ||
1729 | }, | 1790 | }, |
1730 | { | 1791 | { |
1731 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1792 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -1744,11 +1805,14 @@ static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = { | |||
1744 | }, | 1805 | }, |
1745 | { | 1806 | { |
1746 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1807 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1808 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
1809 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
1747 | .name = "Aux Playback Volume", | 1810 | .name = "Aux Playback Volume", |
1748 | .info = aureon_ac97_vol_info, | 1811 | .info = aureon_ac97_vol_info, |
1749 | .get = aureon_ac97_vol_get, | 1812 | .get = aureon_ac97_vol_get, |
1750 | .put = aureon_ac97_vol_put, | 1813 | .put = aureon_ac97_vol_put, |
1751 | .private_value = AC97_VIDEO|AUREON_AC97_STEREO | 1814 | .private_value = AC97_VIDEO|AUREON_AC97_STEREO, |
1815 | .tlv = { .p = db_scale_ac97_gain } | ||
1752 | }, | 1816 | }, |
1753 | { | 1817 | { |
1754 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1818 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index bf20858d9f19..dc69392eafa3 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c | |||
@@ -62,6 +62,7 @@ | |||
62 | #include <sound/cs8427.h> | 62 | #include <sound/cs8427.h> |
63 | #include <sound/info.h> | 63 | #include <sound/info.h> |
64 | #include <sound/initval.h> | 64 | #include <sound/initval.h> |
65 | #include <sound/tlv.h> | ||
65 | 66 | ||
66 | #include <sound/asoundef.h> | 67 | #include <sound/asoundef.h> |
67 | 68 | ||
@@ -1377,6 +1378,7 @@ static int snd_ice1712_pro_mixer_volume_put(struct snd_kcontrol *kcontrol, struc | |||
1377 | return change; | 1378 | return change; |
1378 | } | 1379 | } |
1379 | 1380 | ||
1381 | static DECLARE_TLV_DB_SCALE(db_scale_playback, -14400, 150, 0); | ||
1380 | 1382 | ||
1381 | static struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] __devinitdata = { | 1383 | static struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] __devinitdata = { |
1382 | { | 1384 | { |
@@ -1390,12 +1392,15 @@ static struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] __devinitdata | |||
1390 | }, | 1392 | }, |
1391 | { | 1393 | { |
1392 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1394 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1395 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
1396 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
1393 | .name = "Multi Playback Volume", | 1397 | .name = "Multi Playback Volume", |
1394 | .info = snd_ice1712_pro_mixer_volume_info, | 1398 | .info = snd_ice1712_pro_mixer_volume_info, |
1395 | .get = snd_ice1712_pro_mixer_volume_get, | 1399 | .get = snd_ice1712_pro_mixer_volume_get, |
1396 | .put = snd_ice1712_pro_mixer_volume_put, | 1400 | .put = snd_ice1712_pro_mixer_volume_put, |
1397 | .private_value = 0, | 1401 | .private_value = 0, |
1398 | .count = 10, | 1402 | .count = 10, |
1403 | .tlv = { .p = db_scale_playback } | ||
1399 | }, | 1404 | }, |
1400 | }; | 1405 | }; |
1401 | 1406 | ||
@@ -1420,11 +1425,14 @@ static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_switch __devinitd | |||
1420 | 1425 | ||
1421 | static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_volume __devinitdata = { | 1426 | static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_volume __devinitdata = { |
1422 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1427 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1428 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
1429 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
1423 | .name = "H/W Multi Capture Volume", | 1430 | .name = "H/W Multi Capture Volume", |
1424 | .info = snd_ice1712_pro_mixer_volume_info, | 1431 | .info = snd_ice1712_pro_mixer_volume_info, |
1425 | .get = snd_ice1712_pro_mixer_volume_get, | 1432 | .get = snd_ice1712_pro_mixer_volume_get, |
1426 | .put = snd_ice1712_pro_mixer_volume_put, | 1433 | .put = snd_ice1712_pro_mixer_volume_put, |
1427 | .private_value = 10, | 1434 | .private_value = 10, |
1435 | .tlv = { .p = db_scale_playback } | ||
1428 | }; | 1436 | }; |
1429 | 1437 | ||
1430 | static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_volume __devinitdata = { | 1438 | static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_volume __devinitdata = { |
@@ -1857,7 +1865,7 @@ static int snd_ice1712_pro_internal_clock_put(struct snd_kcontrol *kcontrol, | |||
1857 | { | 1865 | { |
1858 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 1866 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
1859 | static unsigned int xrate[13] = { | 1867 | static unsigned int xrate[13] = { |
1860 | 8000, 9600, 11025, 12000, 1600, 22050, 24000, | 1868 | 8000, 9600, 11025, 12000, 16000, 22050, 24000, |
1861 | 32000, 44100, 48000, 64000, 88200, 96000 | 1869 | 32000, 44100, 48000, 64000, 88200, 96000 |
1862 | }; | 1870 | }; |
1863 | unsigned char oval; | 1871 | unsigned char oval; |
@@ -1924,7 +1932,7 @@ static int snd_ice1712_pro_internal_clock_default_get(struct snd_kcontrol *kcont | |||
1924 | { | 1932 | { |
1925 | int val; | 1933 | int val; |
1926 | static unsigned int xrate[13] = { | 1934 | static unsigned int xrate[13] = { |
1927 | 8000, 9600, 11025, 12000, 1600, 22050, 24000, | 1935 | 8000, 9600, 11025, 12000, 16000, 22050, 24000, |
1928 | 32000, 44100, 48000, 64000, 88200, 96000 | 1936 | 32000, 44100, 48000, 64000, 88200, 96000 |
1929 | }; | 1937 | }; |
1930 | 1938 | ||
@@ -1941,7 +1949,7 @@ static int snd_ice1712_pro_internal_clock_default_put(struct snd_kcontrol *kcont | |||
1941 | struct snd_ctl_elem_value *ucontrol) | 1949 | struct snd_ctl_elem_value *ucontrol) |
1942 | { | 1950 | { |
1943 | static unsigned int xrate[13] = { | 1951 | static unsigned int xrate[13] = { |
1944 | 8000, 9600, 11025, 12000, 1600, 22050, 24000, | 1952 | 8000, 9600, 11025, 12000, 16000, 22050, 24000, |
1945 | 32000, 44100, 48000, 64000, 88200, 96000 | 1953 | 32000, 44100, 48000, 64000, 88200, 96000 |
1946 | }; | 1954 | }; |
1947 | unsigned char oval; | 1955 | unsigned char oval; |
diff --git a/sound/pci/ice1712/phase.c b/sound/pci/ice1712/phase.c index 502da1c8b5f7..e08d73f4ff85 100644 --- a/sound/pci/ice1712/phase.c +++ b/sound/pci/ice1712/phase.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include "ice1712.h" | 46 | #include "ice1712.h" |
47 | #include "envy24ht.h" | 47 | #include "envy24ht.h" |
48 | #include "phase.h" | 48 | #include "phase.h" |
49 | #include <sound/tlv.h> | ||
49 | 50 | ||
50 | /* WM8770 registers */ | 51 | /* WM8770 registers */ |
51 | #define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */ | 52 | #define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */ |
@@ -696,6 +697,9 @@ static int phase28_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ct | |||
696 | return 0; | 697 | return 0; |
697 | } | 698 | } |
698 | 699 | ||
700 | static DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1); | ||
701 | static DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1); | ||
702 | |||
699 | static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = { | 703 | static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = { |
700 | { | 704 | { |
701 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 705 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -706,10 +710,13 @@ static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = { | |||
706 | }, | 710 | }, |
707 | { | 711 | { |
708 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 712 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
713 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
714 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
709 | .name = "Master Playback Volume", | 715 | .name = "Master Playback Volume", |
710 | .info = wm_master_vol_info, | 716 | .info = wm_master_vol_info, |
711 | .get = wm_master_vol_get, | 717 | .get = wm_master_vol_get, |
712 | .put = wm_master_vol_put | 718 | .put = wm_master_vol_put, |
719 | .tlv = { .p = db_scale_wm_dac } | ||
713 | }, | 720 | }, |
714 | { | 721 | { |
715 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 722 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -721,11 +728,14 @@ static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = { | |||
721 | }, | 728 | }, |
722 | { | 729 | { |
723 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 730 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
731 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
732 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
724 | .name = "Front Playback Volume", | 733 | .name = "Front Playback Volume", |
725 | .info = wm_vol_info, | 734 | .info = wm_vol_info, |
726 | .get = wm_vol_get, | 735 | .get = wm_vol_get, |
727 | .put = wm_vol_put, | 736 | .put = wm_vol_put, |
728 | .private_value = (2 << 8) | 0 | 737 | .private_value = (2 << 8) | 0, |
738 | .tlv = { .p = db_scale_wm_dac } | ||
729 | }, | 739 | }, |
730 | { | 740 | { |
731 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 741 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -737,11 +747,14 @@ static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = { | |||
737 | }, | 747 | }, |
738 | { | 748 | { |
739 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 749 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
750 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
751 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
740 | .name = "Rear Playback Volume", | 752 | .name = "Rear Playback Volume", |
741 | .info = wm_vol_info, | 753 | .info = wm_vol_info, |
742 | .get = wm_vol_get, | 754 | .get = wm_vol_get, |
743 | .put = wm_vol_put, | 755 | .put = wm_vol_put, |
744 | .private_value = (2 << 8) | 2 | 756 | .private_value = (2 << 8) | 2, |
757 | .tlv = { .p = db_scale_wm_dac } | ||
745 | }, | 758 | }, |
746 | { | 759 | { |
747 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 760 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -753,11 +766,14 @@ static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = { | |||
753 | }, | 766 | }, |
754 | { | 767 | { |
755 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 768 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
769 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
770 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
756 | .name = "Center Playback Volume", | 771 | .name = "Center Playback Volume", |
757 | .info = wm_vol_info, | 772 | .info = wm_vol_info, |
758 | .get = wm_vol_get, | 773 | .get = wm_vol_get, |
759 | .put = wm_vol_put, | 774 | .put = wm_vol_put, |
760 | .private_value = (1 << 8) | 4 | 775 | .private_value = (1 << 8) | 4, |
776 | .tlv = { .p = db_scale_wm_dac } | ||
761 | }, | 777 | }, |
762 | { | 778 | { |
763 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 779 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -769,11 +785,14 @@ static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = { | |||
769 | }, | 785 | }, |
770 | { | 786 | { |
771 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 787 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
788 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
789 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
772 | .name = "LFE Playback Volume", | 790 | .name = "LFE Playback Volume", |
773 | .info = wm_vol_info, | 791 | .info = wm_vol_info, |
774 | .get = wm_vol_get, | 792 | .get = wm_vol_get, |
775 | .put = wm_vol_put, | 793 | .put = wm_vol_put, |
776 | .private_value = (1 << 8) | 5 | 794 | .private_value = (1 << 8) | 5, |
795 | .tlv = { .p = db_scale_wm_dac } | ||
777 | }, | 796 | }, |
778 | { | 797 | { |
779 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 798 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -785,11 +804,14 @@ static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = { | |||
785 | }, | 804 | }, |
786 | { | 805 | { |
787 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 806 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
807 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
808 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
788 | .name = "Side Playback Volume", | 809 | .name = "Side Playback Volume", |
789 | .info = wm_vol_info, | 810 | .info = wm_vol_info, |
790 | .get = wm_vol_get, | 811 | .get = wm_vol_get, |
791 | .put = wm_vol_put, | 812 | .put = wm_vol_put, |
792 | .private_value = (2 << 8) | 6 | 813 | .private_value = (2 << 8) | 6, |
814 | .tlv = { .p = db_scale_wm_dac } | ||
793 | } | 815 | } |
794 | }; | 816 | }; |
795 | 817 | ||
@@ -803,10 +825,13 @@ static struct snd_kcontrol_new wm_controls[] __devinitdata = { | |||
803 | }, | 825 | }, |
804 | { | 826 | { |
805 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 827 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
828 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
829 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
806 | .name = "PCM Playback Volume", | 830 | .name = "PCM Playback Volume", |
807 | .info = wm_pcm_vol_info, | 831 | .info = wm_pcm_vol_info, |
808 | .get = wm_pcm_vol_get, | 832 | .get = wm_pcm_vol_get, |
809 | .put = wm_pcm_vol_put | 833 | .put = wm_pcm_vol_put, |
834 | .tlv = { .p = db_scale_wm_pcm } | ||
810 | }, | 835 | }, |
811 | { | 836 | { |
812 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 837 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
diff --git a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c index 0efcad9260a5..6c74c2d2e7f3 100644 --- a/sound/pci/ice1712/pontis.c +++ b/sound/pci/ice1712/pontis.c | |||
@@ -31,6 +31,7 @@ | |||
31 | 31 | ||
32 | #include <sound/core.h> | 32 | #include <sound/core.h> |
33 | #include <sound/info.h> | 33 | #include <sound/info.h> |
34 | #include <sound/tlv.h> | ||
34 | 35 | ||
35 | #include "ice1712.h" | 36 | #include "ice1712.h" |
36 | #include "envy24ht.h" | 37 | #include "envy24ht.h" |
@@ -564,6 +565,8 @@ static int pontis_gpio_data_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el | |||
564 | return changed; | 565 | return changed; |
565 | } | 566 | } |
566 | 567 | ||
568 | static DECLARE_TLV_DB_SCALE(db_scale_volume, -6400, 50, 1); | ||
569 | |||
567 | /* | 570 | /* |
568 | * mixers | 571 | * mixers |
569 | */ | 572 | */ |
@@ -571,17 +574,23 @@ static int pontis_gpio_data_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el | |||
571 | static struct snd_kcontrol_new pontis_controls[] __devinitdata = { | 574 | static struct snd_kcontrol_new pontis_controls[] __devinitdata = { |
572 | { | 575 | { |
573 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 576 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
577 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
578 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
574 | .name = "PCM Playback Volume", | 579 | .name = "PCM Playback Volume", |
575 | .info = wm_dac_vol_info, | 580 | .info = wm_dac_vol_info, |
576 | .get = wm_dac_vol_get, | 581 | .get = wm_dac_vol_get, |
577 | .put = wm_dac_vol_put, | 582 | .put = wm_dac_vol_put, |
583 | .tlv = { .p = db_scale_volume }, | ||
578 | }, | 584 | }, |
579 | { | 585 | { |
580 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 586 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
587 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
588 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
581 | .name = "Capture Volume", | 589 | .name = "Capture Volume", |
582 | .info = wm_adc_vol_info, | 590 | .info = wm_adc_vol_info, |
583 | .get = wm_adc_vol_get, | 591 | .get = wm_adc_vol_get, |
584 | .put = wm_adc_vol_put, | 592 | .put = wm_adc_vol_put, |
593 | .tlv = { .p = db_scale_volume }, | ||
585 | }, | 594 | }, |
586 | { | 595 | { |
587 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 596 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
diff --git a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c index fdb5cb8fac97..41b2605daa3a 100644 --- a/sound/pci/ice1712/prodigy192.c +++ b/sound/pci/ice1712/prodigy192.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include "envy24ht.h" | 35 | #include "envy24ht.h" |
36 | #include "prodigy192.h" | 36 | #include "prodigy192.h" |
37 | #include "stac946x.h" | 37 | #include "stac946x.h" |
38 | #include <sound/tlv.h> | ||
38 | 39 | ||
39 | static inline void stac9460_put(struct snd_ice1712 *ice, int reg, unsigned char val) | 40 | static inline void stac9460_put(struct snd_ice1712 *ice, int reg, unsigned char val) |
40 | { | 41 | { |
@@ -356,6 +357,9 @@ static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl | |||
356 | } | 357 | } |
357 | #endif | 358 | #endif |
358 | 359 | ||
360 | static DECLARE_TLV_DB_SCALE(db_scale_dac, -19125, 75, 0); | ||
361 | static DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0); | ||
362 | |||
359 | /* | 363 | /* |
360 | * mixers | 364 | * mixers |
361 | */ | 365 | */ |
@@ -368,14 +372,18 @@ static struct snd_kcontrol_new stac_controls[] __devinitdata = { | |||
368 | .get = stac9460_dac_mute_get, | 372 | .get = stac9460_dac_mute_get, |
369 | .put = stac9460_dac_mute_put, | 373 | .put = stac9460_dac_mute_put, |
370 | .private_value = 1, | 374 | .private_value = 1, |
375 | .tlv = { .p = db_scale_dac } | ||
371 | }, | 376 | }, |
372 | { | 377 | { |
373 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 378 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
379 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
380 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
374 | .name = "Master Playback Volume", | 381 | .name = "Master Playback Volume", |
375 | .info = stac9460_dac_vol_info, | 382 | .info = stac9460_dac_vol_info, |
376 | .get = stac9460_dac_vol_get, | 383 | .get = stac9460_dac_vol_get, |
377 | .put = stac9460_dac_vol_put, | 384 | .put = stac9460_dac_vol_put, |
378 | .private_value = 1, | 385 | .private_value = 1, |
386 | .tlv = { .p = db_scale_dac } | ||
379 | }, | 387 | }, |
380 | { | 388 | { |
381 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 389 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -387,11 +395,14 @@ static struct snd_kcontrol_new stac_controls[] __devinitdata = { | |||
387 | }, | 395 | }, |
388 | { | 396 | { |
389 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 397 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
398 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
399 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
390 | .name = "DAC Volume", | 400 | .name = "DAC Volume", |
391 | .count = 6, | 401 | .count = 6, |
392 | .info = stac9460_dac_vol_info, | 402 | .info = stac9460_dac_vol_info, |
393 | .get = stac9460_dac_vol_get, | 403 | .get = stac9460_dac_vol_get, |
394 | .put = stac9460_dac_vol_put, | 404 | .put = stac9460_dac_vol_put, |
405 | .tlv = { .p = db_scale_dac } | ||
395 | }, | 406 | }, |
396 | { | 407 | { |
397 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 408 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -404,11 +415,14 @@ static struct snd_kcontrol_new stac_controls[] __devinitdata = { | |||
404 | }, | 415 | }, |
405 | { | 416 | { |
406 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 417 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
418 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
419 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
407 | .name = "ADC Volume", | 420 | .name = "ADC Volume", |
408 | .count = 1, | 421 | .count = 1, |
409 | .info = stac9460_adc_vol_info, | 422 | .info = stac9460_adc_vol_info, |
410 | .get = stac9460_adc_vol_get, | 423 | .get = stac9460_adc_vol_get, |
411 | .put = stac9460_adc_vol_put, | 424 | .put = stac9460_adc_vol_put, |
425 | .tlv = { .p = db_scale_adc } | ||
412 | }, | 426 | }, |
413 | #if 0 | 427 | #if 0 |
414 | { | 428 | { |
diff --git a/sound/pci/ice1712/revo.c b/sound/pci/ice1712/revo.c index fec9440cb310..bf98ea34feb0 100644 --- a/sound/pci/ice1712/revo.c +++ b/sound/pci/ice1712/revo.c | |||
@@ -87,16 +87,33 @@ static void revo_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate) | |||
87 | * initialize the chips on M-Audio Revolution cards | 87 | * initialize the chips on M-Audio Revolution cards |
88 | */ | 88 | */ |
89 | 89 | ||
90 | static unsigned int revo71_num_stereo_front[] = {2}; | 90 | #define AK_DAC(xname,xch) { .name = xname, .num_channels = xch } |
91 | static char *revo71_channel_names_front[] = {"PCM Playback Volume"}; | ||
92 | 91 | ||
93 | static unsigned int revo71_num_stereo_surround[] = {1, 1, 2, 2}; | 92 | static struct snd_akm4xxx_dac_channel revo71_front[] = { |
94 | static char *revo71_channel_names_surround[] = {"PCM Center Playback Volume", "PCM LFE Playback Volume", | 93 | AK_DAC("PCM Playback Volume", 2) |
95 | "PCM Side Playback Volume", "PCM Rear Playback Volume"}; | 94 | }; |
95 | |||
96 | static struct snd_akm4xxx_dac_channel revo71_surround[] = { | ||
97 | AK_DAC("PCM Center Playback Volume", 1), | ||
98 | AK_DAC("PCM LFE Playback Volume", 1), | ||
99 | AK_DAC("PCM Side Playback Volume", 2), | ||
100 | AK_DAC("PCM Rear Playback Volume", 2), | ||
101 | }; | ||
96 | 102 | ||
97 | static unsigned int revo51_num_stereo[] = {2, 1, 1, 2}; | 103 | static struct snd_akm4xxx_dac_channel revo51_dac[] = { |
98 | static char *revo51_channel_names[] = {"PCM Playback Volume", "PCM Center Playback Volume", | 104 | AK_DAC("PCM Playback Volume", 2), |
99 | "PCM LFE Playback Volume", "PCM Rear Playback Volume"}; | 105 | AK_DAC("PCM Center Playback Volume", 1), |
106 | AK_DAC("PCM LFE Playback Volume", 1), | ||
107 | AK_DAC("PCM Rear Playback Volume", 2), | ||
108 | }; | ||
109 | |||
110 | static struct snd_akm4xxx_adc_channel revo51_adc[] = { | ||
111 | { | ||
112 | .name = "PCM Capture Volume", | ||
113 | .switch_name = "PCM Capture Switch", | ||
114 | .num_channels = 2 | ||
115 | }, | ||
116 | }; | ||
100 | 117 | ||
101 | static struct snd_akm4xxx akm_revo_front __devinitdata = { | 118 | static struct snd_akm4xxx akm_revo_front __devinitdata = { |
102 | .type = SND_AK4381, | 119 | .type = SND_AK4381, |
@@ -104,8 +121,7 @@ static struct snd_akm4xxx akm_revo_front __devinitdata = { | |||
104 | .ops = { | 121 | .ops = { |
105 | .set_rate_val = revo_set_rate_val | 122 | .set_rate_val = revo_set_rate_val |
106 | }, | 123 | }, |
107 | .num_stereo = revo71_num_stereo_front, | 124 | .dac_info = revo71_front, |
108 | .channel_names = revo71_channel_names_front | ||
109 | }; | 125 | }; |
110 | 126 | ||
111 | static struct snd_ak4xxx_private akm_revo_front_priv __devinitdata = { | 127 | static struct snd_ak4xxx_private akm_revo_front_priv __devinitdata = { |
@@ -127,8 +143,7 @@ static struct snd_akm4xxx akm_revo_surround __devinitdata = { | |||
127 | .ops = { | 143 | .ops = { |
128 | .set_rate_val = revo_set_rate_val | 144 | .set_rate_val = revo_set_rate_val |
129 | }, | 145 | }, |
130 | .num_stereo = revo71_num_stereo_surround, | 146 | .dac_info = revo71_surround, |
131 | .channel_names = revo71_channel_names_surround | ||
132 | }; | 147 | }; |
133 | 148 | ||
134 | static struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = { | 149 | static struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = { |
@@ -149,8 +164,7 @@ static struct snd_akm4xxx akm_revo51 __devinitdata = { | |||
149 | .ops = { | 164 | .ops = { |
150 | .set_rate_val = revo_set_rate_val | 165 | .set_rate_val = revo_set_rate_val |
151 | }, | 166 | }, |
152 | .num_stereo = revo51_num_stereo, | 167 | .dac_info = revo51_dac, |
153 | .channel_names = revo51_channel_names | ||
154 | }; | 168 | }; |
155 | 169 | ||
156 | static struct snd_ak4xxx_private akm_revo51_priv __devinitdata = { | 170 | static struct snd_ak4xxx_private akm_revo51_priv __devinitdata = { |
@@ -159,7 +173,25 @@ static struct snd_ak4xxx_private akm_revo51_priv __devinitdata = { | |||
159 | .data_mask = VT1724_REVO_CDOUT, | 173 | .data_mask = VT1724_REVO_CDOUT, |
160 | .clk_mask = VT1724_REVO_CCLK, | 174 | .clk_mask = VT1724_REVO_CCLK, |
161 | .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2, | 175 | .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2, |
162 | .cs_addr = 0, | 176 | .cs_addr = VT1724_REVO_CS1 | VT1724_REVO_CS2, |
177 | .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2, | ||
178 | .add_flags = VT1724_REVO_CCLK, /* high at init */ | ||
179 | .mask_flags = 0, | ||
180 | }; | ||
181 | |||
182 | static struct snd_akm4xxx akm_revo51_adc __devinitdata = { | ||
183 | .type = SND_AK5365, | ||
184 | .num_adcs = 2, | ||
185 | .adc_info = revo51_adc, | ||
186 | }; | ||
187 | |||
188 | static struct snd_ak4xxx_private akm_revo51_adc_priv __devinitdata = { | ||
189 | .caddr = 2, | ||
190 | .cif = 0, | ||
191 | .data_mask = VT1724_REVO_CDOUT, | ||
192 | .clk_mask = VT1724_REVO_CCLK, | ||
193 | .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2, | ||
194 | .cs_addr = VT1724_REVO_CS0 | VT1724_REVO_CS2, | ||
163 | .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2, | 195 | .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2, |
164 | .add_flags = VT1724_REVO_CCLK, /* high at init */ | 196 | .add_flags = VT1724_REVO_CCLK, /* high at init */ |
165 | .mask_flags = 0, | 197 | .mask_flags = 0, |
@@ -202,9 +234,13 @@ static int __devinit revo_init(struct snd_ice1712 *ice) | |||
202 | snd_ice1712_gpio_write_bits(ice, VT1724_REVO_MUTE, VT1724_REVO_MUTE); | 234 | snd_ice1712_gpio_write_bits(ice, VT1724_REVO_MUTE, VT1724_REVO_MUTE); |
203 | break; | 235 | break; |
204 | case VT1724_SUBDEVICE_REVOLUTION51: | 236 | case VT1724_SUBDEVICE_REVOLUTION51: |
205 | ice->akm_codecs = 1; | 237 | ice->akm_codecs = 2; |
206 | if ((err = snd_ice1712_akm4xxx_init(ak, &akm_revo51, &akm_revo51_priv, ice)) < 0) | 238 | if ((err = snd_ice1712_akm4xxx_init(ak, &akm_revo51, &akm_revo51_priv, ice)) < 0) |
207 | return err; | 239 | return err; |
240 | err = snd_ice1712_akm4xxx_init(ak + 1, &akm_revo51_adc, | ||
241 | &akm_revo51_adc_priv, ice); | ||
242 | if (err < 0) | ||
243 | return err; | ||
208 | /* unmute all codecs - needed! */ | 244 | /* unmute all codecs - needed! */ |
209 | snd_ice1712_gpio_write_bits(ice, VT1724_REVO_MUTE, VT1724_REVO_MUTE); | 245 | snd_ice1712_gpio_write_bits(ice, VT1724_REVO_MUTE, VT1724_REVO_MUTE); |
210 | break; | 246 | break; |
diff --git a/sound/pci/ice1712/revo.h b/sound/pci/ice1712/revo.h index dea52ea219df..efbb86ec3289 100644 --- a/sound/pci/ice1712/revo.h +++ b/sound/pci/ice1712/revo.h | |||
@@ -42,7 +42,7 @@ extern struct snd_ice1712_card_info snd_vt1724_revo_cards[]; | |||
42 | #define VT1724_REVO_CCLK 0x02 | 42 | #define VT1724_REVO_CCLK 0x02 |
43 | #define VT1724_REVO_CDIN 0x04 /* not used */ | 43 | #define VT1724_REVO_CDIN 0x04 /* not used */ |
44 | #define VT1724_REVO_CDOUT 0x08 | 44 | #define VT1724_REVO_CDOUT 0x08 |
45 | #define VT1724_REVO_CS0 0x10 /* not used */ | 45 | #define VT1724_REVO_CS0 0x10 /* AK5365 chipselect for Rev. 5.1 */ |
46 | #define VT1724_REVO_CS1 0x20 /* front AKM4381 chipselect */ | 46 | #define VT1724_REVO_CS1 0x20 /* front AKM4381 chipselect */ |
47 | #define VT1724_REVO_CS2 0x40 /* surround AKM4355 chipselect */ | 47 | #define VT1724_REVO_CS2 0x40 /* surround AKM4355 chipselect */ |
48 | #define VT1724_REVO_MUTE (1<<22) /* 0 = all mute, 1 = normal operation */ | 48 | #define VT1724_REVO_MUTE (1<<22) /* 0 = all mute, 1 = normal operation */ |
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 6874263f1681..72dbaedcbdf5 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c | |||
@@ -2251,6 +2251,16 @@ static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing) | |||
2251 | /* ACLink on, 2 channels */ | 2251 | /* ACLink on, 2 channels */ |
2252 | cnt = igetdword(chip, ICHREG(GLOB_CNT)); | 2252 | cnt = igetdword(chip, ICHREG(GLOB_CNT)); |
2253 | cnt &= ~(ICH_ACLINK | ICH_PCM_246_MASK); | 2253 | cnt &= ~(ICH_ACLINK | ICH_PCM_246_MASK); |
2254 | #ifdef CONFIG_SND_AC97_POWER_SAVE | ||
2255 | /* do cold reset - the full ac97 powerdown may leave the controller | ||
2256 | * in a warm state but actually it cannot communicate with the codec. | ||
2257 | */ | ||
2258 | iputdword(chip, ICHREG(GLOB_CNT), cnt & ~ICH_AC97COLD); | ||
2259 | cnt = igetdword(chip, ICHREG(GLOB_CNT)); | ||
2260 | udelay(10); | ||
2261 | iputdword(chip, ICHREG(GLOB_CNT), cnt | ICH_AC97COLD); | ||
2262 | msleep(1); | ||
2263 | #else | ||
2254 | /* finish cold or do warm reset */ | 2264 | /* finish cold or do warm reset */ |
2255 | cnt |= (cnt & ICH_AC97COLD) == 0 ? ICH_AC97COLD : ICH_AC97WARM; | 2265 | cnt |= (cnt & ICH_AC97COLD) == 0 ? ICH_AC97COLD : ICH_AC97WARM; |
2256 | iputdword(chip, ICHREG(GLOB_CNT), cnt); | 2266 | iputdword(chip, ICHREG(GLOB_CNT), cnt); |
@@ -2265,6 +2275,7 @@ static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing) | |||
2265 | return -EIO; | 2275 | return -EIO; |
2266 | 2276 | ||
2267 | __ok: | 2277 | __ok: |
2278 | #endif | ||
2268 | if (probing) { | 2279 | if (probing) { |
2269 | /* wait for any codec ready status. | 2280 | /* wait for any codec ready status. |
2270 | * Once it becomes ready it should remain ready | 2281 | * Once it becomes ready it should remain ready |
@@ -2485,7 +2496,7 @@ static int intel8x0_resume(struct pci_dev *pci) | |||
2485 | card->shortname, chip); | 2496 | card->shortname, chip); |
2486 | chip->irq = pci->irq; | 2497 | chip->irq = pci->irq; |
2487 | synchronize_irq(chip->irq); | 2498 | synchronize_irq(chip->irq); |
2488 | snd_intel8x0_chip_init(chip, 1); | 2499 | snd_intel8x0_chip_init(chip, 0); |
2489 | 2500 | ||
2490 | /* re-initialize mixer stuff */ | 2501 | /* re-initialize mixer stuff */ |
2491 | if (chip->device_type == DEVICE_INTEL_ICH4) { | 2502 | if (chip->device_type == DEVICE_INTEL_ICH4) { |
@@ -2615,6 +2626,7 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip) | |||
2615 | /* not 48000Hz, tuning the clock.. */ | 2626 | /* not 48000Hz, tuning the clock.. */ |
2616 | chip->ac97_bus->clock = (chip->ac97_bus->clock * 48000) / pos; | 2627 | chip->ac97_bus->clock = (chip->ac97_bus->clock * 48000) / pos; |
2617 | printk(KERN_INFO "intel8x0: clocking to %d\n", chip->ac97_bus->clock); | 2628 | printk(KERN_INFO "intel8x0: clocking to %d\n", chip->ac97_bus->clock); |
2629 | snd_ac97_update_power(chip->ac97[0], AC97_PCM_FRONT_DAC_RATE, 0); | ||
2618 | } | 2630 | } |
2619 | 2631 | ||
2620 | #ifdef CONFIG_PROC_FS | 2632 | #ifdef CONFIG_PROC_FS |
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 91850281f89b..268e2f7241ea 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c | |||
@@ -1045,6 +1045,8 @@ static int intel8x0m_suspend(struct pci_dev *pci, pm_message_t state) | |||
1045 | for (i = 0; i < chip->pcm_devs; i++) | 1045 | for (i = 0; i < chip->pcm_devs; i++) |
1046 | snd_pcm_suspend_all(chip->pcm[i]); | 1046 | snd_pcm_suspend_all(chip->pcm[i]); |
1047 | snd_ac97_suspend(chip->ac97); | 1047 | snd_ac97_suspend(chip->ac97); |
1048 | if (chip->irq >= 0) | ||
1049 | free_irq(chip->irq, chip); | ||
1048 | pci_disable_device(pci); | 1050 | pci_disable_device(pci); |
1049 | pci_save_state(pci); | 1051 | pci_save_state(pci); |
1050 | return 0; | 1052 | return 0; |
@@ -1058,6 +1060,9 @@ static int intel8x0m_resume(struct pci_dev *pci) | |||
1058 | pci_restore_state(pci); | 1060 | pci_restore_state(pci); |
1059 | pci_enable_device(pci); | 1061 | pci_enable_device(pci); |
1060 | pci_set_master(pci); | 1062 | pci_set_master(pci); |
1063 | request_irq(pci->irq, snd_intel8x0_interrupt, IRQF_DISABLED|IRQF_SHARED, | ||
1064 | card->shortname, chip); | ||
1065 | chip->irq = pci->irq; | ||
1061 | snd_intel8x0_chip_init(chip, 0); | 1066 | snd_intel8x0_chip_init(chip, 0); |
1062 | snd_ac97_resume(chip->ac97); | 1067 | snd_ac97_resume(chip->ac97); |
1063 | 1068 | ||
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index cc43ecd67906..216aee5f93e7 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c | |||
@@ -1109,13 +1109,13 @@ static long long snd_mixart_BA0_llseek(struct snd_info_entry *entry, | |||
1109 | offset = offset & ~3; /* 4 bytes aligned */ | 1109 | offset = offset & ~3; /* 4 bytes aligned */ |
1110 | 1110 | ||
1111 | switch(orig) { | 1111 | switch(orig) { |
1112 | case 0: /* SEEK_SET */ | 1112 | case SEEK_SET: |
1113 | file->f_pos = offset; | 1113 | file->f_pos = offset; |
1114 | break; | 1114 | break; |
1115 | case 1: /* SEEK_CUR */ | 1115 | case SEEK_CUR: |
1116 | file->f_pos += offset; | 1116 | file->f_pos += offset; |
1117 | break; | 1117 | break; |
1118 | case 2: /* SEEK_END, offset is negative */ | 1118 | case SEEK_END: /* offset is negative */ |
1119 | file->f_pos = MIXART_BA0_SIZE + offset; | 1119 | file->f_pos = MIXART_BA0_SIZE + offset; |
1120 | break; | 1120 | break; |
1121 | default: | 1121 | default: |
@@ -1135,13 +1135,13 @@ static long long snd_mixart_BA1_llseek(struct snd_info_entry *entry, | |||
1135 | offset = offset & ~3; /* 4 bytes aligned */ | 1135 | offset = offset & ~3; /* 4 bytes aligned */ |
1136 | 1136 | ||
1137 | switch(orig) { | 1137 | switch(orig) { |
1138 | case 0: /* SEEK_SET */ | 1138 | case SEEK_SET: |
1139 | file->f_pos = offset; | 1139 | file->f_pos = offset; |
1140 | break; | 1140 | break; |
1141 | case 1: /* SEEK_CUR */ | 1141 | case SEEK_CUR: |
1142 | file->f_pos += offset; | 1142 | file->f_pos += offset; |
1143 | break; | 1143 | break; |
1144 | case 2: /* SEEK_END, offset is negative */ | 1144 | case SEEK_END: /* offset is negative */ |
1145 | file->f_pos = MIXART_BA1_SIZE + offset; | 1145 | file->f_pos = MIXART_BA1_SIZE + offset; |
1146 | break; | 1146 | break; |
1147 | default: | 1147 | default: |
diff --git a/sound/pci/mixart/mixart_mixer.c b/sound/pci/mixart/mixart_mixer.c index ed47b732c103..13de0f71d4b7 100644 --- a/sound/pci/mixart/mixart_mixer.c +++ b/sound/pci/mixart/mixart_mixer.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include "mixart_core.h" | 31 | #include "mixart_core.h" |
32 | #include "mixart_hwdep.h" | 32 | #include "mixart_hwdep.h" |
33 | #include <sound/control.h> | 33 | #include <sound/control.h> |
34 | #include <sound/tlv.h> | ||
34 | #include "mixart_mixer.h" | 35 | #include "mixart_mixer.h" |
35 | 36 | ||
36 | static u32 mixart_analog_level[256] = { | 37 | static u32 mixart_analog_level[256] = { |
@@ -388,12 +389,17 @@ static int mixart_analog_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
388 | return changed; | 389 | return changed; |
389 | } | 390 | } |
390 | 391 | ||
392 | static DECLARE_TLV_DB_SCALE(db_scale_analog, -9600, 50, 0); | ||
393 | |||
391 | static struct snd_kcontrol_new mixart_control_analog_level = { | 394 | static struct snd_kcontrol_new mixart_control_analog_level = { |
392 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 395 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
396 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
397 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
393 | /* name will be filled later */ | 398 | /* name will be filled later */ |
394 | .info = mixart_analog_vol_info, | 399 | .info = mixart_analog_vol_info, |
395 | .get = mixart_analog_vol_get, | 400 | .get = mixart_analog_vol_get, |
396 | .put = mixart_analog_vol_put, | 401 | .put = mixart_analog_vol_put, |
402 | .tlv = { .p = db_scale_analog }, | ||
397 | }; | 403 | }; |
398 | 404 | ||
399 | /* shared */ | 405 | /* shared */ |
@@ -866,14 +872,19 @@ static int mixart_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem | |||
866 | return changed; | 872 | return changed; |
867 | } | 873 | } |
868 | 874 | ||
875 | static DECLARE_TLV_DB_SCALE(db_scale_digital, -10950, 50, 0); | ||
876 | |||
869 | static struct snd_kcontrol_new snd_mixart_pcm_vol = | 877 | static struct snd_kcontrol_new snd_mixart_pcm_vol = |
870 | { | 878 | { |
871 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 879 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
880 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
881 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
872 | /* name will be filled later */ | 882 | /* name will be filled later */ |
873 | /* count will be filled later */ | 883 | /* count will be filled later */ |
874 | .info = mixart_digital_vol_info, /* shared */ | 884 | .info = mixart_digital_vol_info, /* shared */ |
875 | .get = mixart_pcm_vol_get, | 885 | .get = mixart_pcm_vol_get, |
876 | .put = mixart_pcm_vol_put, | 886 | .put = mixart_pcm_vol_put, |
887 | .tlv = { .p = db_scale_digital }, | ||
877 | }; | 888 | }; |
878 | 889 | ||
879 | 890 | ||
@@ -984,10 +995,13 @@ static int mixart_monitor_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
984 | 995 | ||
985 | static struct snd_kcontrol_new mixart_control_monitor_vol = { | 996 | static struct snd_kcontrol_new mixart_control_monitor_vol = { |
986 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 997 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
998 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
999 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
987 | .name = "Monitoring Volume", | 1000 | .name = "Monitoring Volume", |
988 | .info = mixart_digital_vol_info, /* shared */ | 1001 | .info = mixart_digital_vol_info, /* shared */ |
989 | .get = mixart_monitor_vol_get, | 1002 | .get = mixart_monitor_vol_get, |
990 | .put = mixart_monitor_vol_put, | 1003 | .put = mixart_monitor_vol_put, |
1004 | .tlv = { .p = db_scale_digital }, | ||
991 | }; | 1005 | }; |
992 | 1006 | ||
993 | /* | 1007 | /* |
diff --git a/sound/pci/pcxhr/pcxhr_mixer.c b/sound/pci/pcxhr/pcxhr_mixer.c index 94e63a1e90d9..b133ad9e095e 100644 --- a/sound/pci/pcxhr/pcxhr_mixer.c +++ b/sound/pci/pcxhr/pcxhr_mixer.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include "pcxhr_hwdep.h" | 31 | #include "pcxhr_hwdep.h" |
32 | #include "pcxhr_core.h" | 32 | #include "pcxhr_core.h" |
33 | #include <sound/control.h> | 33 | #include <sound/control.h> |
34 | #include <sound/tlv.h> | ||
34 | #include <sound/asoundef.h> | 35 | #include <sound/asoundef.h> |
35 | #include "pcxhr_mixer.h" | 36 | #include "pcxhr_mixer.h" |
36 | 37 | ||
@@ -43,6 +44,9 @@ | |||
43 | #define PCXHR_ANALOG_PLAYBACK_LEVEL_MAX 128 /* 0.0 dB */ | 44 | #define PCXHR_ANALOG_PLAYBACK_LEVEL_MAX 128 /* 0.0 dB */ |
44 | #define PCXHR_ANALOG_PLAYBACK_ZERO_LEVEL 104 /* -24.0 dB ( 0.0 dB - fix level +24.0 dB ) */ | 45 | #define PCXHR_ANALOG_PLAYBACK_ZERO_LEVEL 104 /* -24.0 dB ( 0.0 dB - fix level +24.0 dB ) */ |
45 | 46 | ||
47 | static DECLARE_TLV_DB_SCALE(db_scale_analog_capture, -9600, 50, 0); | ||
48 | static DECLARE_TLV_DB_SCALE(db_scale_analog_playback, -12800, 100, 0); | ||
49 | |||
46 | static int pcxhr_update_analog_audio_level(struct snd_pcxhr *chip, int is_capture, int channel) | 50 | static int pcxhr_update_analog_audio_level(struct snd_pcxhr *chip, int is_capture, int channel) |
47 | { | 51 | { |
48 | int err, vol; | 52 | int err, vol; |
@@ -130,10 +134,13 @@ static int pcxhr_analog_vol_put(struct snd_kcontrol *kcontrol, | |||
130 | 134 | ||
131 | static struct snd_kcontrol_new pcxhr_control_analog_level = { | 135 | static struct snd_kcontrol_new pcxhr_control_analog_level = { |
132 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 136 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
137 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
138 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
133 | /* name will be filled later */ | 139 | /* name will be filled later */ |
134 | .info = pcxhr_analog_vol_info, | 140 | .info = pcxhr_analog_vol_info, |
135 | .get = pcxhr_analog_vol_get, | 141 | .get = pcxhr_analog_vol_get, |
136 | .put = pcxhr_analog_vol_put, | 142 | .put = pcxhr_analog_vol_put, |
143 | /* tlv will be filled later */ | ||
137 | }; | 144 | }; |
138 | 145 | ||
139 | /* shared */ | 146 | /* shared */ |
@@ -188,6 +195,7 @@ static struct snd_kcontrol_new pcxhr_control_output_switch = { | |||
188 | #define PCXHR_DIGITAL_LEVEL_MAX 0x1ff /* +18 dB */ | 195 | #define PCXHR_DIGITAL_LEVEL_MAX 0x1ff /* +18 dB */ |
189 | #define PCXHR_DIGITAL_ZERO_LEVEL 0x1b7 /* 0 dB */ | 196 | #define PCXHR_DIGITAL_ZERO_LEVEL 0x1b7 /* 0 dB */ |
190 | 197 | ||
198 | static DECLARE_TLV_DB_SCALE(db_scale_digital, -10950, 50, 0); | ||
191 | 199 | ||
192 | #define MORE_THAN_ONE_STREAM_LEVEL 0x000001 | 200 | #define MORE_THAN_ONE_STREAM_LEVEL 0x000001 |
193 | #define VALID_STREAM_PAN_LEVEL_MASK 0x800000 | 201 | #define VALID_STREAM_PAN_LEVEL_MASK 0x800000 |
@@ -343,11 +351,14 @@ static int pcxhr_pcm_vol_put(struct snd_kcontrol *kcontrol, | |||
343 | static struct snd_kcontrol_new snd_pcxhr_pcm_vol = | 351 | static struct snd_kcontrol_new snd_pcxhr_pcm_vol = |
344 | { | 352 | { |
345 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 353 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
354 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
355 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
346 | /* name will be filled later */ | 356 | /* name will be filled later */ |
347 | /* count will be filled later */ | 357 | /* count will be filled later */ |
348 | .info = pcxhr_digital_vol_info, /* shared */ | 358 | .info = pcxhr_digital_vol_info, /* shared */ |
349 | .get = pcxhr_pcm_vol_get, | 359 | .get = pcxhr_pcm_vol_get, |
350 | .put = pcxhr_pcm_vol_put, | 360 | .put = pcxhr_pcm_vol_put, |
361 | .tlv = { .p = db_scale_digital }, | ||
351 | }; | 362 | }; |
352 | 363 | ||
353 | 364 | ||
@@ -433,10 +444,13 @@ static int pcxhr_monitor_vol_put(struct snd_kcontrol *kcontrol, | |||
433 | 444 | ||
434 | static struct snd_kcontrol_new pcxhr_control_monitor_vol = { | 445 | static struct snd_kcontrol_new pcxhr_control_monitor_vol = { |
435 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 446 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
447 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
448 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
436 | .name = "Monitoring Volume", | 449 | .name = "Monitoring Volume", |
437 | .info = pcxhr_digital_vol_info, /* shared */ | 450 | .info = pcxhr_digital_vol_info, /* shared */ |
438 | .get = pcxhr_monitor_vol_get, | 451 | .get = pcxhr_monitor_vol_get, |
439 | .put = pcxhr_monitor_vol_put, | 452 | .put = pcxhr_monitor_vol_put, |
453 | .tlv = { .p = db_scale_digital }, | ||
440 | }; | 454 | }; |
441 | 455 | ||
442 | /* | 456 | /* |
@@ -928,6 +942,7 @@ int pcxhr_create_mixer(struct pcxhr_mgr *mgr) | |||
928 | temp = pcxhr_control_analog_level; | 942 | temp = pcxhr_control_analog_level; |
929 | temp.name = "Master Playback Volume"; | 943 | temp.name = "Master Playback Volume"; |
930 | temp.private_value = 0; /* playback */ | 944 | temp.private_value = 0; /* playback */ |
945 | temp.tlv.p = db_scale_analog_playback; | ||
931 | if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) | 946 | if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) |
932 | return err; | 947 | return err; |
933 | /* output mute controls */ | 948 | /* output mute controls */ |
@@ -963,6 +978,7 @@ int pcxhr_create_mixer(struct pcxhr_mgr *mgr) | |||
963 | temp = pcxhr_control_analog_level; | 978 | temp = pcxhr_control_analog_level; |
964 | temp.name = "Master Capture Volume"; | 979 | temp.name = "Master Capture Volume"; |
965 | temp.private_value = 1; /* capture */ | 980 | temp.private_value = 1; /* capture */ |
981 | temp.tlv.p = db_scale_analog_capture; | ||
966 | if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) | 982 | if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) |
967 | return err; | 983 | return err; |
968 | 984 | ||
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index f435fcd6dca9..fe210c853442 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c | |||
@@ -673,9 +673,13 @@ static struct lbuspath lbus_rec_path = { | |||
673 | #define FIRMWARE_VERSIONS 1 | 673 | #define FIRMWARE_VERSIONS 1 |
674 | static union firmware_version firmware_versions[] = { | 674 | static union firmware_version firmware_versions[] = { |
675 | { | 675 | { |
676 | .firmware.ASIC = 3,.firmware.CODEC = 2, | 676 | .firmware = { |
677 | .firmware.AUXDSP = 3,.firmware.PROG = 773, | 677 | .ASIC = 3, |
678 | }, | 678 | .CODEC = 2, |
679 | .AUXDSP = 3, | ||
680 | .PROG = 773, | ||
681 | }, | ||
682 | }, | ||
679 | }; | 683 | }; |
680 | 684 | ||
681 | static u32 atoh(unsigned char *in, unsigned int len) | 685 | static u32 atoh(unsigned char *in, unsigned int len) |
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index e5a52da77b85..d3e07de433b0 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c | |||
@@ -726,22 +726,36 @@ static int hdsp_get_iobox_version (struct hdsp *hdsp) | |||
726 | } | 726 | } |
727 | 727 | ||
728 | 728 | ||
729 | static int hdsp_check_for_firmware (struct hdsp *hdsp, int show_err) | 729 | #ifdef HDSP_FW_LOADER |
730 | static int __devinit hdsp_request_fw_loader(struct hdsp *hdsp); | ||
731 | #endif | ||
732 | |||
733 | static int hdsp_check_for_firmware (struct hdsp *hdsp, int load_on_demand) | ||
730 | { | 734 | { |
731 | if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0; | 735 | if (hdsp->io_type == H9652 || hdsp->io_type == H9632) |
736 | return 0; | ||
732 | if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { | 737 | if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { |
733 | snd_printk(KERN_ERR "Hammerfall-DSP: firmware not present.\n"); | ||
734 | hdsp->state &= ~HDSP_FirmwareLoaded; | 738 | hdsp->state &= ~HDSP_FirmwareLoaded; |
735 | if (! show_err) | 739 | if (! load_on_demand) |
736 | return -EIO; | 740 | return -EIO; |
741 | snd_printk(KERN_ERR "Hammerfall-DSP: firmware not present.\n"); | ||
737 | /* try to load firmware */ | 742 | /* try to load firmware */ |
738 | if (hdsp->state & HDSP_FirmwareCached) { | 743 | if (! (hdsp->state & HDSP_FirmwareCached)) { |
739 | if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) | 744 | #ifdef HDSP_FW_LOADER |
740 | snd_printk(KERN_ERR "Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n"); | 745 | if (! hdsp_request_fw_loader(hdsp)) |
741 | } else { | 746 | return 0; |
742 | snd_printk(KERN_ERR "Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n"); | 747 | #endif |
748 | snd_printk(KERN_ERR | ||
749 | "Hammerfall-DSP: No firmware loaded nor " | ||
750 | "cached, please upload firmware.\n"); | ||
751 | return -EIO; | ||
752 | } | ||
753 | if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) { | ||
754 | snd_printk(KERN_ERR | ||
755 | "Hammerfall-DSP: Firmware loading from " | ||
756 | "cache failed, please upload manually.\n"); | ||
757 | return -EIO; | ||
743 | } | 758 | } |
744 | return -EIO; | ||
745 | } | 759 | } |
746 | return 0; | 760 | return 0; |
747 | } | 761 | } |
@@ -3181,8 +3195,16 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) | |||
3181 | return; | 3195 | return; |
3182 | } | 3196 | } |
3183 | } else { | 3197 | } else { |
3184 | snd_iprintf(buffer, "No firmware loaded nor cached, please upload firmware.\n"); | 3198 | int err = -EINVAL; |
3185 | return; | 3199 | #ifdef HDSP_FW_LOADER |
3200 | err = hdsp_request_fw_loader(hdsp); | ||
3201 | #endif | ||
3202 | if (err < 0) { | ||
3203 | snd_iprintf(buffer, | ||
3204 | "No firmware loaded nor cached, " | ||
3205 | "please upload firmware.\n"); | ||
3206 | return; | ||
3207 | } | ||
3186 | } | 3208 | } |
3187 | } | 3209 | } |
3188 | 3210 | ||
@@ -3851,7 +3873,7 @@ static int snd_hdsp_trigger(struct snd_pcm_substream *substream, int cmd) | |||
3851 | if (hdsp_check_for_iobox (hdsp)) | 3873 | if (hdsp_check_for_iobox (hdsp)) |
3852 | return -EIO; | 3874 | return -EIO; |
3853 | 3875 | ||
3854 | if (hdsp_check_for_firmware(hdsp, 1)) | 3876 | if (hdsp_check_for_firmware(hdsp, 0)) /* no auto-loading in trigger */ |
3855 | return -EIO; | 3877 | return -EIO; |
3856 | 3878 | ||
3857 | spin_lock(&hdsp->lock); | 3879 | spin_lock(&hdsp->lock); |
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 4930cc6b054d..ebbe12d78d8c 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <sound/core.h> | 40 | #include <sound/core.h> |
41 | #include <sound/info.h> | 41 | #include <sound/info.h> |
42 | #include <sound/control.h> | 42 | #include <sound/control.h> |
43 | #include <sound/tlv.h> | ||
43 | #include <sound/trident.h> | 44 | #include <sound/trident.h> |
44 | #include <sound/asoundef.h> | 45 | #include <sound/asoundef.h> |
45 | 46 | ||
@@ -2627,6 +2628,8 @@ static int snd_trident_vol_control_get(struct snd_kcontrol *kcontrol, | |||
2627 | return 0; | 2628 | return 0; |
2628 | } | 2629 | } |
2629 | 2630 | ||
2631 | static DECLARE_TLV_DB_SCALE(db_scale_gvol, -6375, 25, 0); | ||
2632 | |||
2630 | static int snd_trident_vol_control_put(struct snd_kcontrol *kcontrol, | 2633 | static int snd_trident_vol_control_put(struct snd_kcontrol *kcontrol, |
2631 | struct snd_ctl_elem_value *ucontrol) | 2634 | struct snd_ctl_elem_value *ucontrol) |
2632 | { | 2635 | { |
@@ -2653,6 +2656,7 @@ static struct snd_kcontrol_new snd_trident_vol_music_control __devinitdata = | |||
2653 | .get = snd_trident_vol_control_get, | 2656 | .get = snd_trident_vol_control_get, |
2654 | .put = snd_trident_vol_control_put, | 2657 | .put = snd_trident_vol_control_put, |
2655 | .private_value = 16, | 2658 | .private_value = 16, |
2659 | .tlv = { .p = db_scale_gvol }, | ||
2656 | }; | 2660 | }; |
2657 | 2661 | ||
2658 | static struct snd_kcontrol_new snd_trident_vol_wave_control __devinitdata = | 2662 | static struct snd_kcontrol_new snd_trident_vol_wave_control __devinitdata = |
@@ -2663,6 +2667,7 @@ static struct snd_kcontrol_new snd_trident_vol_wave_control __devinitdata = | |||
2663 | .get = snd_trident_vol_control_get, | 2667 | .get = snd_trident_vol_control_get, |
2664 | .put = snd_trident_vol_control_put, | 2668 | .put = snd_trident_vol_control_put, |
2665 | .private_value = 0, | 2669 | .private_value = 0, |
2670 | .tlv = { .p = db_scale_gvol }, | ||
2666 | }; | 2671 | }; |
2667 | 2672 | ||
2668 | /*--------------------------------------------------------------------------- | 2673 | /*--------------------------------------------------------------------------- |
@@ -2730,6 +2735,7 @@ static struct snd_kcontrol_new snd_trident_pcm_vol_control __devinitdata = | |||
2730 | .info = snd_trident_pcm_vol_control_info, | 2735 | .info = snd_trident_pcm_vol_control_info, |
2731 | .get = snd_trident_pcm_vol_control_get, | 2736 | .get = snd_trident_pcm_vol_control_get, |
2732 | .put = snd_trident_pcm_vol_control_put, | 2737 | .put = snd_trident_pcm_vol_control_put, |
2738 | /* FIXME: no tlv yet */ | ||
2733 | }; | 2739 | }; |
2734 | 2740 | ||
2735 | /*--------------------------------------------------------------------------- | 2741 | /*--------------------------------------------------------------------------- |
@@ -2839,6 +2845,8 @@ static int snd_trident_pcm_rvol_control_put(struct snd_kcontrol *kcontrol, | |||
2839 | return change; | 2845 | return change; |
2840 | } | 2846 | } |
2841 | 2847 | ||
2848 | static DECLARE_TLV_DB_SCALE(db_scale_crvol, -3175, 25, 1); | ||
2849 | |||
2842 | static struct snd_kcontrol_new snd_trident_pcm_rvol_control __devinitdata = | 2850 | static struct snd_kcontrol_new snd_trident_pcm_rvol_control __devinitdata = |
2843 | { | 2851 | { |
2844 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2852 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -2848,6 +2856,7 @@ static struct snd_kcontrol_new snd_trident_pcm_rvol_control __devinitdata = | |||
2848 | .info = snd_trident_pcm_rvol_control_info, | 2856 | .info = snd_trident_pcm_rvol_control_info, |
2849 | .get = snd_trident_pcm_rvol_control_get, | 2857 | .get = snd_trident_pcm_rvol_control_get, |
2850 | .put = snd_trident_pcm_rvol_control_put, | 2858 | .put = snd_trident_pcm_rvol_control_put, |
2859 | .tlv = { .p = db_scale_crvol }, | ||
2851 | }; | 2860 | }; |
2852 | 2861 | ||
2853 | /*--------------------------------------------------------------------------- | 2862 | /*--------------------------------------------------------------------------- |
@@ -2903,6 +2912,7 @@ static struct snd_kcontrol_new snd_trident_pcm_cvol_control __devinitdata = | |||
2903 | .info = snd_trident_pcm_cvol_control_info, | 2912 | .info = snd_trident_pcm_cvol_control_info, |
2904 | .get = snd_trident_pcm_cvol_control_get, | 2913 | .get = snd_trident_pcm_cvol_control_get, |
2905 | .put = snd_trident_pcm_cvol_control_put, | 2914 | .put = snd_trident_pcm_cvol_control_put, |
2915 | .tlv = { .p = db_scale_crvol }, | ||
2906 | }; | 2916 | }; |
2907 | 2917 | ||
2908 | static void snd_trident_notify_pcm_change1(struct snd_card *card, | 2918 | static void snd_trident_notify_pcm_change1(struct snd_card *card, |
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 08da9234efb3..6db3d4cc4d8d 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c | |||
@@ -59,6 +59,7 @@ | |||
59 | #include <sound/pcm.h> | 59 | #include <sound/pcm.h> |
60 | #include <sound/pcm_params.h> | 60 | #include <sound/pcm_params.h> |
61 | #include <sound/info.h> | 61 | #include <sound/info.h> |
62 | #include <sound/tlv.h> | ||
62 | #include <sound/ac97_codec.h> | 63 | #include <sound/ac97_codec.h> |
63 | #include <sound/mpu401.h> | 64 | #include <sound/mpu401.h> |
64 | #include <sound/initval.h> | 65 | #include <sound/initval.h> |
@@ -1277,7 +1278,18 @@ static int snd_via82xx_pcm_close(struct snd_pcm_substream *substream) | |||
1277 | if (! ratep->used) | 1278 | if (! ratep->used) |
1278 | ratep->rate = 0; | 1279 | ratep->rate = 0; |
1279 | spin_unlock_irq(&ratep->lock); | 1280 | spin_unlock_irq(&ratep->lock); |
1280 | 1281 | if (! ratep->rate) { | |
1282 | if (! viadev->direction) { | ||
1283 | snd_ac97_update_power(chip->ac97, | ||
1284 | AC97_PCM_FRONT_DAC_RATE, 0); | ||
1285 | snd_ac97_update_power(chip->ac97, | ||
1286 | AC97_PCM_SURR_DAC_RATE, 0); | ||
1287 | snd_ac97_update_power(chip->ac97, | ||
1288 | AC97_PCM_LFE_DAC_RATE, 0); | ||
1289 | } else | ||
1290 | snd_ac97_update_power(chip->ac97, | ||
1291 | AC97_PCM_LR_ADC_RATE, 0); | ||
1292 | } | ||
1281 | viadev->substream = NULL; | 1293 | viadev->substream = NULL; |
1282 | return 0; | 1294 | return 0; |
1283 | } | 1295 | } |
@@ -1687,21 +1699,29 @@ static int snd_via8233_pcmdxs_volume_put(struct snd_kcontrol *kcontrol, | |||
1687 | return change; | 1699 | return change; |
1688 | } | 1700 | } |
1689 | 1701 | ||
1702 | static DECLARE_TLV_DB_SCALE(db_scale_dxs, -9450, 150, 1); | ||
1703 | |||
1690 | static struct snd_kcontrol_new snd_via8233_pcmdxs_volume_control __devinitdata = { | 1704 | static struct snd_kcontrol_new snd_via8233_pcmdxs_volume_control __devinitdata = { |
1691 | .name = "PCM Playback Volume", | 1705 | .name = "PCM Playback Volume", |
1692 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1706 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1707 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
1708 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
1693 | .info = snd_via8233_dxs_volume_info, | 1709 | .info = snd_via8233_dxs_volume_info, |
1694 | .get = snd_via8233_pcmdxs_volume_get, | 1710 | .get = snd_via8233_pcmdxs_volume_get, |
1695 | .put = snd_via8233_pcmdxs_volume_put, | 1711 | .put = snd_via8233_pcmdxs_volume_put, |
1712 | .tlv = { .p = db_scale_dxs } | ||
1696 | }; | 1713 | }; |
1697 | 1714 | ||
1698 | static struct snd_kcontrol_new snd_via8233_dxs_volume_control __devinitdata = { | 1715 | static struct snd_kcontrol_new snd_via8233_dxs_volume_control __devinitdata = { |
1699 | .name = "VIA DXS Playback Volume", | 1716 | .name = "VIA DXS Playback Volume", |
1700 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1717 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1718 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
1719 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
1701 | .count = 4, | 1720 | .count = 4, |
1702 | .info = snd_via8233_dxs_volume_info, | 1721 | .info = snd_via8233_dxs_volume_info, |
1703 | .get = snd_via8233_dxs_volume_get, | 1722 | .get = snd_via8233_dxs_volume_get, |
1704 | .put = snd_via8233_dxs_volume_put, | 1723 | .put = snd_via8233_dxs_volume_put, |
1724 | .tlv = { .p = db_scale_dxs } | ||
1705 | }; | 1725 | }; |
1706 | 1726 | ||
1707 | /* | 1727 | /* |
@@ -2393,6 +2413,7 @@ static int __devinit check_dxs_list(struct pci_dev *pci, int revision) | |||
2393 | { .subvendor = 0x16f3, .subdevice = 0x6405, .action = VIA_DXS_SRC }, /* Jetway K8M8MS */ | 2413 | { .subvendor = 0x16f3, .subdevice = 0x6405, .action = VIA_DXS_SRC }, /* Jetway K8M8MS */ |
2394 | { .subvendor = 0x1734, .subdevice = 0x1078, .action = VIA_DXS_SRC }, /* FSC Amilo L7300 */ | 2414 | { .subvendor = 0x1734, .subdevice = 0x1078, .action = VIA_DXS_SRC }, /* FSC Amilo L7300 */ |
2395 | { .subvendor = 0x1734, .subdevice = 0x1093, .action = VIA_DXS_SRC }, /* FSC */ | 2415 | { .subvendor = 0x1734, .subdevice = 0x1093, .action = VIA_DXS_SRC }, /* FSC */ |
2416 | { .subvendor = 0x1734, .subdevice = 0x10ab, .action = VIA_DXS_SRC }, /* FSC */ | ||
2396 | { .subvendor = 0x1849, .subdevice = 0x3059, .action = VIA_DXS_NO_VRA }, /* ASRock K7VM2 */ | 2417 | { .subvendor = 0x1849, .subdevice = 0x3059, .action = VIA_DXS_NO_VRA }, /* ASRock K7VM2 */ |
2397 | { .subvendor = 0x1849, .subdevice = 0x9739, .action = VIA_DXS_SRC }, /* ASRock mobo(?) */ | 2418 | { .subvendor = 0x1849, .subdevice = 0x9739, .action = VIA_DXS_SRC }, /* ASRock mobo(?) */ |
2398 | { .subvendor = 0x1849, .subdevice = 0x9761, .action = VIA_DXS_SRC }, /* ASRock mobo(?) */ | 2419 | { .subvendor = 0x1849, .subdevice = 0x9761, .action = VIA_DXS_SRC }, /* ASRock mobo(?) */ |
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c index 9c03c6b4e490..e7cd8acab59a 100644 --- a/sound/pci/vx222/vx222.c +++ b/sound/pci/vx222/vx222.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/moduleparam.h> | 26 | #include <linux/moduleparam.h> |
27 | #include <sound/core.h> | 27 | #include <sound/core.h> |
28 | #include <sound/initval.h> | 28 | #include <sound/initval.h> |
29 | #include <sound/tlv.h> | ||
29 | #include "vx222.h" | 30 | #include "vx222.h" |
30 | 31 | ||
31 | #define CARD_NAME "VX222" | 32 | #define CARD_NAME "VX222" |
@@ -72,6 +73,9 @@ MODULE_DEVICE_TABLE(pci, snd_vx222_ids); | |||
72 | /* | 73 | /* |
73 | */ | 74 | */ |
74 | 75 | ||
76 | static DECLARE_TLV_DB_SCALE(db_scale_old_vol, -11350, 50, 0); | ||
77 | static DECLARE_TLV_DB_SCALE(db_scale_akm, -7350, 50, 0); | ||
78 | |||
75 | static struct snd_vx_hardware vx222_old_hw = { | 79 | static struct snd_vx_hardware vx222_old_hw = { |
76 | 80 | ||
77 | .name = "VX222/Old", | 81 | .name = "VX222/Old", |
@@ -81,6 +85,7 @@ static struct snd_vx_hardware vx222_old_hw = { | |||
81 | .num_ins = 1, | 85 | .num_ins = 1, |
82 | .num_outs = 1, | 86 | .num_outs = 1, |
83 | .output_level_max = VX_ANALOG_OUT_LEVEL_MAX, | 87 | .output_level_max = VX_ANALOG_OUT_LEVEL_MAX, |
88 | .output_level_db_scale = db_scale_old_vol, | ||
84 | }; | 89 | }; |
85 | 90 | ||
86 | static struct snd_vx_hardware vx222_v2_hw = { | 91 | static struct snd_vx_hardware vx222_v2_hw = { |
@@ -92,6 +97,7 @@ static struct snd_vx_hardware vx222_v2_hw = { | |||
92 | .num_ins = 1, | 97 | .num_ins = 1, |
93 | .num_outs = 1, | 98 | .num_outs = 1, |
94 | .output_level_max = VX2_AKM_LEVEL_MAX, | 99 | .output_level_max = VX2_AKM_LEVEL_MAX, |
100 | .output_level_db_scale = db_scale_akm, | ||
95 | }; | 101 | }; |
96 | 102 | ||
97 | static struct snd_vx_hardware vx222_mic_hw = { | 103 | static struct snd_vx_hardware vx222_mic_hw = { |
@@ -103,6 +109,7 @@ static struct snd_vx_hardware vx222_mic_hw = { | |||
103 | .num_ins = 1, | 109 | .num_ins = 1, |
104 | .num_outs = 1, | 110 | .num_outs = 1, |
105 | .output_level_max = VX2_AKM_LEVEL_MAX, | 111 | .output_level_max = VX2_AKM_LEVEL_MAX, |
112 | .output_level_db_scale = db_scale_akm, | ||
106 | }; | 113 | }; |
107 | 114 | ||
108 | 115 | ||
diff --git a/sound/pci/vx222/vx222_ops.c b/sound/pci/vx222/vx222_ops.c index 9b6d345b83a6..5e51950e05f9 100644 --- a/sound/pci/vx222/vx222_ops.c +++ b/sound/pci/vx222/vx222_ops.c | |||
@@ -28,6 +28,7 @@ | |||
28 | 28 | ||
29 | #include <sound/core.h> | 29 | #include <sound/core.h> |
30 | #include <sound/control.h> | 30 | #include <sound/control.h> |
31 | #include <sound/tlv.h> | ||
31 | #include <asm/io.h> | 32 | #include <asm/io.h> |
32 | #include "vx222.h" | 33 | #include "vx222.h" |
33 | 34 | ||
@@ -845,6 +846,8 @@ static void vx2_set_input_level(struct snd_vx222 *chip) | |||
845 | 846 | ||
846 | #define MIC_LEVEL_MAX 0xff | 847 | #define MIC_LEVEL_MAX 0xff |
847 | 848 | ||
849 | static DECLARE_TLV_DB_SCALE(db_scale_mic, -6450, 50, 0); | ||
850 | |||
848 | /* | 851 | /* |
849 | * controls API for input levels | 852 | * controls API for input levels |
850 | */ | 853 | */ |
@@ -922,18 +925,24 @@ static int vx_mic_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v | |||
922 | 925 | ||
923 | static struct snd_kcontrol_new vx_control_input_level = { | 926 | static struct snd_kcontrol_new vx_control_input_level = { |
924 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 927 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
928 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
929 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
925 | .name = "Capture Volume", | 930 | .name = "Capture Volume", |
926 | .info = vx_input_level_info, | 931 | .info = vx_input_level_info, |
927 | .get = vx_input_level_get, | 932 | .get = vx_input_level_get, |
928 | .put = vx_input_level_put, | 933 | .put = vx_input_level_put, |
934 | .tlv = { .p = db_scale_mic }, | ||
929 | }; | 935 | }; |
930 | 936 | ||
931 | static struct snd_kcontrol_new vx_control_mic_level = { | 937 | static struct snd_kcontrol_new vx_control_mic_level = { |
932 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 938 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
939 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
940 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
933 | .name = "Mic Capture Volume", | 941 | .name = "Mic Capture Volume", |
934 | .info = vx_mic_level_info, | 942 | .info = vx_mic_level_info, |
935 | .get = vx_mic_level_get, | 943 | .get = vx_mic_level_get, |
936 | .put = vx_mic_level_put, | 944 | .put = vx_mic_level_put, |
945 | .tlv = { .p = db_scale_mic }, | ||
937 | }; | 946 | }; |
938 | 947 | ||
939 | /* | 948 | /* |
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index a55b5fd7da64..24f6fc52f898 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <sound/core.h> | 36 | #include <sound/core.h> |
37 | #include <sound/control.h> | 37 | #include <sound/control.h> |
38 | #include <sound/info.h> | 38 | #include <sound/info.h> |
39 | #include <sound/tlv.h> | ||
39 | #include <sound/ymfpci.h> | 40 | #include <sound/ymfpci.h> |
40 | #include <sound/asoundef.h> | 41 | #include <sound/asoundef.h> |
41 | #include <sound/mpu401.h> | 42 | #include <sound/mpu401.h> |
@@ -1477,11 +1478,15 @@ static int snd_ymfpci_put_single(struct snd_kcontrol *kcontrol, | |||
1477 | return change; | 1478 | return change; |
1478 | } | 1479 | } |
1479 | 1480 | ||
1481 | static DECLARE_TLV_DB_LINEAR(db_scale_native, TLV_DB_GAIN_MUTE, 0); | ||
1482 | |||
1480 | #define YMFPCI_DOUBLE(xname, xindex, reg) \ | 1483 | #define YMFPCI_DOUBLE(xname, xindex, reg) \ |
1481 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ | 1484 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ |
1485 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ | ||
1482 | .info = snd_ymfpci_info_double, \ | 1486 | .info = snd_ymfpci_info_double, \ |
1483 | .get = snd_ymfpci_get_double, .put = snd_ymfpci_put_double, \ | 1487 | .get = snd_ymfpci_get_double, .put = snd_ymfpci_put_double, \ |
1484 | .private_value = reg } | 1488 | .private_value = reg, \ |
1489 | .tlv = { .p = db_scale_native } } | ||
1485 | 1490 | ||
1486 | static int snd_ymfpci_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1491 | static int snd_ymfpci_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
1487 | { | 1492 | { |