diff options
author | Takashi Iwai <tiwai@suse.de> | 2006-08-21 12:44:31 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2006-09-23 04:42:51 -0400 |
commit | 2f3482fbbd5dac7d0e86fe5b7ac5c1e51d52b084 (patch) | |
tree | a7f8c3192208f840e6af7322efc0e565221120ca /sound/pci/ac97/ac97_codec.c | |
parent | 7376d013fc6d3a45d748e0ce758ca9412b01b9dd (diff) |
[ALSA] Add TLV support to AC97 codec driver
Added the TLV support to AC97 codec driver for addition of
dB range information.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/pci/ac97/ac97_codec.c')
-rw-r--r-- | sound/pci/ac97/ac97_codec.c | 54 |
1 files changed, 47 insertions, 7 deletions
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index e5d062d640df..c47f43dbd664 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> |
@@ -1182,6 +1183,32 @@ static int snd_ac97_cmute_new_stereo(struct snd_card *card, char *name, int reg, | |||
1182 | } | 1183 | } |
1183 | 1184 | ||
1184 | /* | 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 | /* | ||
1185 | * create a volume for normal stereo/mono controls | 1212 | * create a volume for normal stereo/mono controls |
1186 | */ | 1213 | */ |
1187 | 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, |
@@ -1203,6 +1230,10 @@ static int snd_ac97_cvol_new(struct snd_card *card, char *name, int reg, unsigne | |||
1203 | tmp.index = ac97->num; | 1230 | tmp.index = ac97->num; |
1204 | kctl = snd_ctl_new1(&tmp, ac97); | 1231 | kctl = snd_ctl_new1(&tmp, ac97); |
1205 | } | 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)); | ||
1206 | err = snd_ctl_add(card, kctl); | 1237 | err = snd_ctl_add(card, kctl); |
1207 | if (err < 0) | 1238 | if (err < 0) |
1208 | return err; | 1239 | return err; |
@@ -1282,6 +1313,7 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) | |||
1282 | 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); |
1283 | kctl->private_value &= ~(0xff << 16); | 1314 | kctl->private_value &= ~(0xff << 16); |
1284 | kctl->private_value |= (int)max << 16; | 1315 | kctl->private_value |= (int)max << 16; |
1316 | set_tlv_db_scale(kctl, find_db_scale(max)); | ||
1285 | 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); |
1286 | } | 1318 | } |
1287 | 1319 | ||
@@ -1295,6 +1327,7 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) | |||
1295 | 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); |
1296 | kctl->private_value &= ~(0xff << 16); | 1328 | kctl->private_value &= ~(0xff << 16); |
1297 | kctl->private_value |= (int)max << 16; | 1329 | kctl->private_value |= (int)max << 16; |
1330 | set_tlv_db_scale(kctl, find_db_scale(max)); | ||
1298 | 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); |
1299 | } | 1332 | } |
1300 | 1333 | ||
@@ -1342,8 +1375,9 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) | |||
1342 | ((ac97->flags & AC97_HAS_PC_BEEP) || | 1375 | ((ac97->flags & AC97_HAS_PC_BEEP) || |
1343 | snd_ac97_try_volume_mix(ac97, AC97_PC_BEEP))) { | 1376 | snd_ac97_try_volume_mix(ac97, AC97_PC_BEEP))) { |
1344 | for (idx = 0; idx < 2; idx++) | 1377 | for (idx = 0; idx < 2; idx++) |
1345 | 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) |
1346 | return err; | 1379 | return err; |
1380 | set_tlv_db_scale(kctl, db_scale_4bit); | ||
1347 | snd_ac97_write_cache(ac97, AC97_PC_BEEP, | 1381 | snd_ac97_write_cache(ac97, AC97_PC_BEEP, |
1348 | snd_ac97_read(ac97, AC97_PC_BEEP) | 0x801e); | 1382 | snd_ac97_read(ac97, AC97_PC_BEEP) | 0x801e); |
1349 | } | 1383 | } |
@@ -1410,22 +1444,26 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) | |||
1410 | else | 1444 | else |
1411 | init_val = 0x9f1f; | 1445 | init_val = 0x9f1f; |
1412 | for (idx = 0; idx < 2; idx++) | 1446 | for (idx = 0; idx < 2; idx++) |
1413 | 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) |
1414 | return err; | 1448 | return err; |
1449 | set_tlv_db_scale(kctl, db_scale_5bit); | ||
1415 | ac97->spec.ad18xx.pcmreg[0] = init_val; | 1450 | ac97->spec.ad18xx.pcmreg[0] = init_val; |
1416 | if (ac97->scaps & AC97_SCAP_SURROUND_DAC) { | 1451 | if (ac97->scaps & AC97_SCAP_SURROUND_DAC) { |
1417 | for (idx = 0; idx < 2; idx++) | 1452 | for (idx = 0; idx < 2; idx++) |
1418 | 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) |
1419 | return err; | 1454 | return err; |
1455 | set_tlv_db_scale(kctl, db_scale_5bit); | ||
1420 | ac97->spec.ad18xx.pcmreg[1] = init_val; | 1456 | ac97->spec.ad18xx.pcmreg[1] = init_val; |
1421 | } | 1457 | } |
1422 | if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC) { | 1458 | if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC) { |
1423 | for (idx = 0; idx < 2; idx++) | 1459 | for (idx = 0; idx < 2; idx++) |
1424 | 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) |
1425 | return err; | 1461 | return err; |
1462 | set_tlv_db_scale(kctl, db_scale_5bit); | ||
1426 | for (idx = 0; idx < 2; idx++) | 1463 | for (idx = 0; idx < 2; idx++) |
1427 | 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) |
1428 | return err; | 1465 | return err; |
1466 | set_tlv_db_scale(kctl, db_scale_5bit); | ||
1429 | ac97->spec.ad18xx.pcmreg[2] = init_val; | 1467 | ac97->spec.ad18xx.pcmreg[2] = init_val; |
1430 | } | 1468 | } |
1431 | snd_ac97_write_cache(ac97, AC97_PCM, init_val); | 1469 | snd_ac97_write_cache(ac97, AC97_PCM, init_val); |
@@ -1453,16 +1491,18 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) | |||
1453 | if (err < 0) | 1491 | if (err < 0) |
1454 | return err; | 1492 | return err; |
1455 | } | 1493 | } |
1456 | 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) |
1457 | return err; | 1495 | return err; |
1496 | set_tlv_db_scale(kctl, db_scale_rec_gain); | ||
1458 | snd_ac97_write_cache(ac97, AC97_REC_SEL, 0x0000); | 1497 | snd_ac97_write_cache(ac97, AC97_REC_SEL, 0x0000); |
1459 | snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x0000); | 1498 | snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x0000); |
1460 | } | 1499 | } |
1461 | /* build MIC Capture controls */ | 1500 | /* build MIC Capture controls */ |
1462 | if (snd_ac97_try_volume_mix(ac97, AC97_REC_GAIN_MIC)) { | 1501 | if (snd_ac97_try_volume_mix(ac97, AC97_REC_GAIN_MIC)) { |
1463 | for (idx = 0; idx < 2; idx++) | 1502 | for (idx = 0; idx < 2; idx++) |
1464 | 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) |
1465 | return err; | 1504 | return err; |
1505 | set_tlv_db_scale(kctl, db_scale_rec_gain); | ||
1466 | snd_ac97_write_cache(ac97, AC97_REC_GAIN_MIC, 0x0000); | 1506 | snd_ac97_write_cache(ac97, AC97_REC_GAIN_MIC, 0x0000); |
1467 | } | 1507 | } |
1468 | 1508 | ||