aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2006-08-21 12:44:31 -0400
committerJaroslav Kysela <perex@suse.cz>2006-09-23 04:42:51 -0400
commit2f3482fbbd5dac7d0e86fe5b7ac5c1e51d52b084 (patch)
treea7f8c3192208f840e6af7322efc0e565221120ca /sound/pci
parent7376d013fc6d3a45d748e0ce758ca9412b01b9dd (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')
-rw-r--r--sound/pci/ac97/ac97_codec.c54
-rw-r--r--sound/pci/ac97/ac97_patch.c39
2 files changed, 86 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 */
1188static DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0);
1189static DECLARE_TLV_DB_SCALE(db_scale_5bit, -4650, 150, 0);
1190static DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
1191static DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
1192static DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
1193
1194static 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
1204static 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 */
1187static int snd_ac97_cvol_new(struct snd_card *card, char *name, int reg, unsigned int lo_max, 1214static 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
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index 37c6be481c4a..392f6ccace5d 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 */
56static 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 */
55static int ac97_update_bits_page(struct snd_ac97 *ac97, unsigned short reg, unsigned short mask, unsigned short value, unsigned short page) 70static int ac97_update_bits_page(struct snd_ac97 *ac97, unsigned short reg, unsigned short mask, unsigned short value, unsigned short page)
56{ 71{
@@ -1522,12 +1537,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 */ 1537 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 8, 1, 1), /* inverted */
1523}; 1538};
1524 1539
1540static DECLARE_TLV_DB_SCALE(db_scale_6bit_6db_max, -8850, 150, 0);
1541
1525static int patch_ad1885_specific(struct snd_ac97 * ac97) 1542static int patch_ad1885_specific(struct snd_ac97 * ac97)
1526{ 1543{
1527 int err; 1544 int err;
1528 1545
1529 if ((err = patch_build_controls(ac97, snd_ac97_controls_ad1885, ARRAY_SIZE(snd_ac97_controls_ad1885))) < 0) 1546 if ((err = patch_build_controls(ac97, snd_ac97_controls_ad1885, ARRAY_SIZE(snd_ac97_controls_ad1885))) < 0)
1530 return err; 1547 return err;
1548 reset_tlv(ac97, "Headphone Playback Volume",
1549 db_scale_6bit_6db_max);
1531 return 0; 1550 return 0;
1532} 1551}
1533 1552
@@ -1551,12 +1570,27 @@ int patch_ad1885(struct snd_ac97 * ac97)
1551 return 0; 1570 return 0;
1552} 1571}
1553 1572
1573static int patch_ad1886_specific(struct snd_ac97 * ac97)
1574{
1575 reset_tlv(ac97, "Headphone Playback Volume",
1576 db_scale_6bit_6db_max);
1577 return 0;
1578}
1579
1580static struct snd_ac97_build_ops patch_ad1886_build_ops = {
1581 .build_specific = &patch_ad1886_specific,
1582#ifdef CONFIG_PM
1583 .resume = ad18xx_resume
1584#endif
1585};
1586
1554int patch_ad1886(struct snd_ac97 * ac97) 1587int patch_ad1886(struct snd_ac97 * ac97)
1555{ 1588{
1556 patch_ad1881(ac97); 1589 patch_ad1881(ac97);
1557 /* Presario700 workaround */ 1590 /* Presario700 workaround */
1558 /* for Jack Sense/SPDIF Register misetting causing */ 1591 /* for Jack Sense/SPDIF Register misetting causing */
1559 snd_ac97_write_cache(ac97, AC97_AD_JACK_SPDIF, 0x0010); 1592 snd_ac97_write_cache(ac97, AC97_AD_JACK_SPDIF, 0x0010);
1593 ac97->build_ops = &patch_ad1886_build_ops;
1560 return 0; 1594 return 0;
1561} 1595}
1562 1596
@@ -2015,6 +2049,8 @@ static const struct snd_kcontrol_new snd_ac97_spdif_controls_alc650[] = {
2015 /* AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 13, 1, 0), */ 2049 /* AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 13, 1, 0), */
2016}; 2050};
2017 2051
2052static DECLARE_TLV_DB_SCALE(db_scale_5bit_3db_max, -4350, 150, 0);
2053
2018static int patch_alc650_specific(struct snd_ac97 * ac97) 2054static int patch_alc650_specific(struct snd_ac97 * ac97)
2019{ 2055{
2020 int err; 2056 int err;
@@ -2025,6 +2061,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) 2061 if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc650, ARRAY_SIZE(snd_ac97_spdif_controls_alc650))) < 0)
2026 return err; 2062 return err;
2027 } 2063 }
2064 if (ac97->id != AC97_ID_ALC650F)
2065 reset_tlv(ac97, "Master Playback Volume",
2066 db_scale_5bit_3db_max);
2028 return 0; 2067 return 0;
2029} 2068}
2030 2069