diff options
Diffstat (limited to 'sound/pci/ctxfi')
-rw-r--r-- | sound/pci/ctxfi/ct20k2reg.h | 1 | ||||
-rw-r--r-- | sound/pci/ctxfi/ctatc.c | 107 | ||||
-rw-r--r-- | sound/pci/ctxfi/ctatc.h | 8 | ||||
-rw-r--r-- | sound/pci/ctxfi/ctdaio.c | 23 | ||||
-rw-r--r-- | sound/pci/ctxfi/ctdaio.h | 1 | ||||
-rw-r--r-- | sound/pci/ctxfi/cthardware.h | 14 | ||||
-rw-r--r-- | sound/pci/ctxfi/cthw20k1.c | 15 | ||||
-rw-r--r-- | sound/pci/ctxfi/cthw20k2.c | 337 | ||||
-rw-r--r-- | sound/pci/ctxfi/ctmixer.c | 145 | ||||
-rw-r--r-- | sound/pci/ctxfi/xfi.c | 6 |
10 files changed, 466 insertions, 191 deletions
diff --git a/sound/pci/ctxfi/ct20k2reg.h b/sound/pci/ctxfi/ct20k2reg.h index e0394e3996e..ca501ba03d6 100644 --- a/sound/pci/ctxfi/ct20k2reg.h +++ b/sound/pci/ctxfi/ct20k2reg.h | |||
@@ -55,6 +55,7 @@ | |||
55 | /* GPIO Registers */ | 55 | /* GPIO Registers */ |
56 | #define GPIO_DATA 0x1B7020 | 56 | #define GPIO_DATA 0x1B7020 |
57 | #define GPIO_CTRL 0x1B7024 | 57 | #define GPIO_CTRL 0x1B7024 |
58 | #define GPIO_EXT_DATA 0x1B70A0 | ||
58 | 59 | ||
59 | /* Virtual memory registers */ | 60 | /* Virtual memory registers */ |
60 | #define VMEM_PTPAL 0x1C6300 /* 0x1C6300 + (16 * Chn) */ | 61 | #define VMEM_PTPAL 0x1C6300 /* 0x1C6300 + (16 * Chn) */ |
diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c index 13f33c0719d..d8a4423539c 100644 --- a/sound/pci/ctxfi/ctatc.c +++ b/sound/pci/ctxfi/ctatc.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include "ctatc.h" | 18 | #include "ctatc.h" |
19 | #include "ctpcm.h" | 19 | #include "ctpcm.h" |
20 | #include "ctmixer.h" | 20 | #include "ctmixer.h" |
21 | #include "cthardware.h" | ||
22 | #include "ctsrc.h" | 21 | #include "ctsrc.h" |
23 | #include "ctamixer.h" | 22 | #include "ctamixer.h" |
24 | #include "ctdaio.h" | 23 | #include "ctdaio.h" |
@@ -30,7 +29,6 @@ | |||
30 | #include <sound/asoundef.h> | 29 | #include <sound/asoundef.h> |
31 | 30 | ||
32 | #define MONO_SUM_SCALE 0x19a8 /* 2^(-0.5) in 14-bit floating format */ | 31 | #define MONO_SUM_SCALE 0x19a8 /* 2^(-0.5) in 14-bit floating format */ |
33 | #define DAIONUM 7 | ||
34 | #define MAX_MULTI_CHN 8 | 32 | #define MAX_MULTI_CHN 8 |
35 | 33 | ||
36 | #define IEC958_DEFAULT_CON ((IEC958_AES0_NONAUDIO \ | 34 | #define IEC958_DEFAULT_CON ((IEC958_AES0_NONAUDIO \ |
@@ -53,6 +51,8 @@ static struct snd_pci_quirk __devinitdata subsys_20k1_list[] = { | |||
53 | static struct snd_pci_quirk __devinitdata subsys_20k2_list[] = { | 51 | static struct snd_pci_quirk __devinitdata subsys_20k2_list[] = { |
54 | SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB0760, | 52 | SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB0760, |
55 | "SB0760", CTSB0760), | 53 | "SB0760", CTSB0760), |
54 | SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB1270, | ||
55 | "SB1270", CTSB1270), | ||
56 | SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB08801, | 56 | SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB08801, |
57 | "SB0880", CTSB0880), | 57 | "SB0880", CTSB0880), |
58 | SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB08802, | 58 | SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB08802, |
@@ -75,6 +75,7 @@ static const char *ct_subsys_name[NUM_CTCARDS] = { | |||
75 | [CTSB0760] = "SB076x", | 75 | [CTSB0760] = "SB076x", |
76 | [CTHENDRIX] = "Hendrix", | 76 | [CTHENDRIX] = "Hendrix", |
77 | [CTSB0880] = "SB0880", | 77 | [CTSB0880] = "SB0880", |
78 | [CTSB1270] = "SB1270", | ||
78 | [CT20K2_UNKNOWN] = "Unknown", | 79 | [CT20K2_UNKNOWN] = "Unknown", |
79 | }; | 80 | }; |
80 | 81 | ||
@@ -459,12 +460,12 @@ static void setup_src_node_conf(struct ct_atc *atc, struct ct_atc_pcm *apcm, | |||
459 | apcm->substream->runtime->rate); | 460 | apcm->substream->runtime->rate); |
460 | *n_srcc = 0; | 461 | *n_srcc = 0; |
461 | 462 | ||
462 | if (1 == atc->msr) { | 463 | if (1 == atc->msr) { /* FIXME: do we really need SRC here if pitch==1 */ |
463 | *n_srcc = apcm->substream->runtime->channels; | 464 | *n_srcc = apcm->substream->runtime->channels; |
464 | conf[0].pitch = pitch; | 465 | conf[0].pitch = pitch; |
465 | conf[0].mix_msr = conf[0].imp_msr = conf[0].msr = 1; | 466 | conf[0].mix_msr = conf[0].imp_msr = conf[0].msr = 1; |
466 | conf[0].vo = 1; | 467 | conf[0].vo = 1; |
467 | } else if (2 == atc->msr) { | 468 | } else if (2 <= atc->msr) { |
468 | if (0x8000000 < pitch) { | 469 | if (0x8000000 < pitch) { |
469 | /* Need two-stage SRCs, SRCIMPs and | 470 | /* Need two-stage SRCs, SRCIMPs and |
470 | * AMIXERs for converting format */ | 471 | * AMIXERs for converting format */ |
@@ -970,11 +971,39 @@ static int atc_select_mic_in(struct ct_atc *atc) | |||
970 | return 0; | 971 | return 0; |
971 | } | 972 | } |
972 | 973 | ||
973 | static int atc_have_digit_io_switch(struct ct_atc *atc) | 974 | static struct capabilities atc_capabilities(struct ct_atc *atc) |
974 | { | 975 | { |
975 | struct hw *hw = atc->hw; | 976 | struct hw *hw = atc->hw; |
976 | 977 | ||
977 | return hw->have_digit_io_switch(hw); | 978 | return hw->capabilities(hw); |
979 | } | ||
980 | |||
981 | static int atc_output_switch_get(struct ct_atc *atc) | ||
982 | { | ||
983 | struct hw *hw = atc->hw; | ||
984 | |||
985 | return hw->output_switch_get(hw); | ||
986 | } | ||
987 | |||
988 | static int atc_output_switch_put(struct ct_atc *atc, int position) | ||
989 | { | ||
990 | struct hw *hw = atc->hw; | ||
991 | |||
992 | return hw->output_switch_put(hw, position); | ||
993 | } | ||
994 | |||
995 | static int atc_mic_source_switch_get(struct ct_atc *atc) | ||
996 | { | ||
997 | struct hw *hw = atc->hw; | ||
998 | |||
999 | return hw->mic_source_switch_get(hw); | ||
1000 | } | ||
1001 | |||
1002 | static int atc_mic_source_switch_put(struct ct_atc *atc, int position) | ||
1003 | { | ||
1004 | struct hw *hw = atc->hw; | ||
1005 | |||
1006 | return hw->mic_source_switch_put(hw, position); | ||
978 | } | 1007 | } |
979 | 1008 | ||
980 | static int atc_select_digit_io(struct ct_atc *atc) | 1009 | static int atc_select_digit_io(struct ct_atc *atc) |
@@ -1045,6 +1074,11 @@ static int atc_line_in_unmute(struct ct_atc *atc, unsigned char state) | |||
1045 | return atc_daio_unmute(atc, state, LINEIM); | 1074 | return atc_daio_unmute(atc, state, LINEIM); |
1046 | } | 1075 | } |
1047 | 1076 | ||
1077 | static int atc_mic_unmute(struct ct_atc *atc, unsigned char state) | ||
1078 | { | ||
1079 | return atc_daio_unmute(atc, state, MIC); | ||
1080 | } | ||
1081 | |||
1048 | static int atc_spdif_out_unmute(struct ct_atc *atc, unsigned char state) | 1082 | static int atc_spdif_out_unmute(struct ct_atc *atc, unsigned char state) |
1049 | { | 1083 | { |
1050 | return atc_daio_unmute(atc, state, SPDIFOO); | 1084 | return atc_daio_unmute(atc, state, SPDIFOO); |
@@ -1331,17 +1365,20 @@ static int atc_get_resources(struct ct_atc *atc) | |||
1331 | struct srcimp_mgr *srcimp_mgr; | 1365 | struct srcimp_mgr *srcimp_mgr; |
1332 | struct sum_desc sum_dsc = {0}; | 1366 | struct sum_desc sum_dsc = {0}; |
1333 | struct sum_mgr *sum_mgr; | 1367 | struct sum_mgr *sum_mgr; |
1334 | int err, i; | 1368 | int err, i, num_srcs, num_daios; |
1335 | 1369 | ||
1336 | atc->daios = kzalloc(sizeof(void *)*(DAIONUM), GFP_KERNEL); | 1370 | num_daios = ((atc->model == CTSB1270) ? 8 : 7); |
1371 | num_srcs = ((atc->model == CTSB1270) ? 6 : 4); | ||
1372 | |||
1373 | atc->daios = kzalloc(sizeof(void *)*num_daios, GFP_KERNEL); | ||
1337 | if (!atc->daios) | 1374 | if (!atc->daios) |
1338 | return -ENOMEM; | 1375 | return -ENOMEM; |
1339 | 1376 | ||
1340 | atc->srcs = kzalloc(sizeof(void *)*(2*2), GFP_KERNEL); | 1377 | atc->srcs = kzalloc(sizeof(void *)*num_srcs, GFP_KERNEL); |
1341 | if (!atc->srcs) | 1378 | if (!atc->srcs) |
1342 | return -ENOMEM; | 1379 | return -ENOMEM; |
1343 | 1380 | ||
1344 | atc->srcimps = kzalloc(sizeof(void *)*(2*2), GFP_KERNEL); | 1381 | atc->srcimps = kzalloc(sizeof(void *)*num_srcs, GFP_KERNEL); |
1345 | if (!atc->srcimps) | 1382 | if (!atc->srcimps) |
1346 | return -ENOMEM; | 1383 | return -ENOMEM; |
1347 | 1384 | ||
@@ -1351,8 +1388,9 @@ static int atc_get_resources(struct ct_atc *atc) | |||
1351 | 1388 | ||
1352 | daio_mgr = (struct daio_mgr *)atc->rsc_mgrs[DAIO]; | 1389 | daio_mgr = (struct daio_mgr *)atc->rsc_mgrs[DAIO]; |
1353 | da_desc.msr = atc->msr; | 1390 | da_desc.msr = atc->msr; |
1354 | for (i = 0, atc->n_daio = 0; i < DAIONUM-1; i++) { | 1391 | for (i = 0, atc->n_daio = 0; i < num_daios; i++) { |
1355 | da_desc.type = i; | 1392 | da_desc.type = (atc->model != CTSB073X) ? i : |
1393 | ((i == SPDIFIO) ? SPDIFI1 : i); | ||
1356 | err = daio_mgr->get_daio(daio_mgr, &da_desc, | 1394 | err = daio_mgr->get_daio(daio_mgr, &da_desc, |
1357 | (struct daio **)&atc->daios[i]); | 1395 | (struct daio **)&atc->daios[i]); |
1358 | if (err) { | 1396 | if (err) { |
@@ -1362,23 +1400,12 @@ static int atc_get_resources(struct ct_atc *atc) | |||
1362 | } | 1400 | } |
1363 | atc->n_daio++; | 1401 | atc->n_daio++; |
1364 | } | 1402 | } |
1365 | if (atc->model == CTSB073X) | ||
1366 | da_desc.type = SPDIFI1; | ||
1367 | else | ||
1368 | da_desc.type = SPDIFIO; | ||
1369 | err = daio_mgr->get_daio(daio_mgr, &da_desc, | ||
1370 | (struct daio **)&atc->daios[i]); | ||
1371 | if (err) { | ||
1372 | printk(KERN_ERR "ctxfi: Failed to get S/PDIF-in resource!!!\n"); | ||
1373 | return err; | ||
1374 | } | ||
1375 | atc->n_daio++; | ||
1376 | 1403 | ||
1377 | src_mgr = atc->rsc_mgrs[SRC]; | 1404 | src_mgr = atc->rsc_mgrs[SRC]; |
1378 | src_dsc.multi = 1; | 1405 | src_dsc.multi = 1; |
1379 | src_dsc.msr = atc->msr; | 1406 | src_dsc.msr = atc->msr; |
1380 | src_dsc.mode = ARCRW; | 1407 | src_dsc.mode = ARCRW; |
1381 | for (i = 0, atc->n_src = 0; i < (2*2); i++) { | 1408 | for (i = 0, atc->n_src = 0; i < num_srcs; i++) { |
1382 | err = src_mgr->get_src(src_mgr, &src_dsc, | 1409 | err = src_mgr->get_src(src_mgr, &src_dsc, |
1383 | (struct src **)&atc->srcs[i]); | 1410 | (struct src **)&atc->srcs[i]); |
1384 | if (err) | 1411 | if (err) |
@@ -1388,8 +1415,8 @@ static int atc_get_resources(struct ct_atc *atc) | |||
1388 | } | 1415 | } |
1389 | 1416 | ||
1390 | srcimp_mgr = atc->rsc_mgrs[SRCIMP]; | 1417 | srcimp_mgr = atc->rsc_mgrs[SRCIMP]; |
1391 | srcimp_dsc.msr = 8; /* SRCIMPs for S/PDIFIn SRT */ | 1418 | srcimp_dsc.msr = 8; |
1392 | for (i = 0, atc->n_srcimp = 0; i < (2*1); i++) { | 1419 | for (i = 0, atc->n_srcimp = 0; i < num_srcs; i++) { |
1393 | err = srcimp_mgr->get_srcimp(srcimp_mgr, &srcimp_dsc, | 1420 | err = srcimp_mgr->get_srcimp(srcimp_mgr, &srcimp_dsc, |
1394 | (struct srcimp **)&atc->srcimps[i]); | 1421 | (struct srcimp **)&atc->srcimps[i]); |
1395 | if (err) | 1422 | if (err) |
@@ -1397,15 +1424,6 @@ static int atc_get_resources(struct ct_atc *atc) | |||
1397 | 1424 | ||
1398 | atc->n_srcimp++; | 1425 | atc->n_srcimp++; |
1399 | } | 1426 | } |
1400 | srcimp_dsc.msr = 8; /* SRCIMPs for LINE/MICIn SRT */ | ||
1401 | for (i = 0; i < (2*1); i++) { | ||
1402 | err = srcimp_mgr->get_srcimp(srcimp_mgr, &srcimp_dsc, | ||
1403 | (struct srcimp **)&atc->srcimps[2*1+i]); | ||
1404 | if (err) | ||
1405 | return err; | ||
1406 | |||
1407 | atc->n_srcimp++; | ||
1408 | } | ||
1409 | 1427 | ||
1410 | sum_mgr = atc->rsc_mgrs[SUM]; | 1428 | sum_mgr = atc->rsc_mgrs[SUM]; |
1411 | sum_dsc.msr = atc->msr; | 1429 | sum_dsc.msr = atc->msr; |
@@ -1488,6 +1506,18 @@ static void atc_connect_resources(struct ct_atc *atc) | |||
1488 | src = atc->srcs[3]; | 1506 | src = atc->srcs[3]; |
1489 | mixer->set_input_right(mixer, MIX_LINE_IN, &src->rsc); | 1507 | mixer->set_input_right(mixer, MIX_LINE_IN, &src->rsc); |
1490 | 1508 | ||
1509 | if (atc->model == CTSB1270) { | ||
1510 | /* Titanium HD has a dedicated ADC for the Mic. */ | ||
1511 | dai = container_of(atc->daios[MIC], struct dai, daio); | ||
1512 | atc_connect_dai(atc->rsc_mgrs[SRC], dai, | ||
1513 | (struct src **)&atc->srcs[4], | ||
1514 | (struct srcimp **)&atc->srcimps[4]); | ||
1515 | src = atc->srcs[4]; | ||
1516 | mixer->set_input_left(mixer, MIX_MIC_IN, &src->rsc); | ||
1517 | src = atc->srcs[5]; | ||
1518 | mixer->set_input_right(mixer, MIX_MIC_IN, &src->rsc); | ||
1519 | } | ||
1520 | |||
1491 | dai = container_of(atc->daios[SPDIFIO], struct dai, daio); | 1521 | dai = container_of(atc->daios[SPDIFIO], struct dai, daio); |
1492 | atc_connect_dai(atc->rsc_mgrs[SRC], dai, | 1522 | atc_connect_dai(atc->rsc_mgrs[SRC], dai, |
1493 | (struct src **)&atc->srcs[0], | 1523 | (struct src **)&atc->srcs[0], |
@@ -1606,12 +1636,17 @@ static struct ct_atc atc_preset __devinitdata = { | |||
1606 | .line_clfe_unmute = atc_line_clfe_unmute, | 1636 | .line_clfe_unmute = atc_line_clfe_unmute, |
1607 | .line_rear_unmute = atc_line_rear_unmute, | 1637 | .line_rear_unmute = atc_line_rear_unmute, |
1608 | .line_in_unmute = atc_line_in_unmute, | 1638 | .line_in_unmute = atc_line_in_unmute, |
1639 | .mic_unmute = atc_mic_unmute, | ||
1609 | .spdif_out_unmute = atc_spdif_out_unmute, | 1640 | .spdif_out_unmute = atc_spdif_out_unmute, |
1610 | .spdif_in_unmute = atc_spdif_in_unmute, | 1641 | .spdif_in_unmute = atc_spdif_in_unmute, |
1611 | .spdif_out_get_status = atc_spdif_out_get_status, | 1642 | .spdif_out_get_status = atc_spdif_out_get_status, |
1612 | .spdif_out_set_status = atc_spdif_out_set_status, | 1643 | .spdif_out_set_status = atc_spdif_out_set_status, |
1613 | .spdif_out_passthru = atc_spdif_out_passthru, | 1644 | .spdif_out_passthru = atc_spdif_out_passthru, |
1614 | .have_digit_io_switch = atc_have_digit_io_switch, | 1645 | .capabilities = atc_capabilities, |
1646 | .output_switch_get = atc_output_switch_get, | ||
1647 | .output_switch_put = atc_output_switch_put, | ||
1648 | .mic_source_switch_get = atc_mic_source_switch_get, | ||
1649 | .mic_source_switch_put = atc_mic_source_switch_put, | ||
1615 | #ifdef CONFIG_PM | 1650 | #ifdef CONFIG_PM |
1616 | .suspend = atc_suspend, | 1651 | .suspend = atc_suspend, |
1617 | .resume = atc_resume, | 1652 | .resume = atc_resume, |
diff --git a/sound/pci/ctxfi/ctatc.h b/sound/pci/ctxfi/ctatc.h index 7167c0185d5..3a0def656af 100644 --- a/sound/pci/ctxfi/ctatc.h +++ b/sound/pci/ctxfi/ctatc.h | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <sound/core.h> | 25 | #include <sound/core.h> |
26 | 26 | ||
27 | #include "ctvmem.h" | 27 | #include "ctvmem.h" |
28 | #include "cthardware.h" | ||
28 | #include "ctresource.h" | 29 | #include "ctresource.h" |
29 | 30 | ||
30 | enum CTALSADEVS { /* Types of alsa devices */ | 31 | enum CTALSADEVS { /* Types of alsa devices */ |
@@ -115,12 +116,17 @@ struct ct_atc { | |||
115 | int (*line_clfe_unmute)(struct ct_atc *atc, unsigned char state); | 116 | int (*line_clfe_unmute)(struct ct_atc *atc, unsigned char state); |
116 | int (*line_rear_unmute)(struct ct_atc *atc, unsigned char state); | 117 | int (*line_rear_unmute)(struct ct_atc *atc, unsigned char state); |
117 | int (*line_in_unmute)(struct ct_atc *atc, unsigned char state); | 118 | int (*line_in_unmute)(struct ct_atc *atc, unsigned char state); |
119 | int (*mic_unmute)(struct ct_atc *atc, unsigned char state); | ||
118 | int (*spdif_out_unmute)(struct ct_atc *atc, unsigned char state); | 120 | int (*spdif_out_unmute)(struct ct_atc *atc, unsigned char state); |
119 | int (*spdif_in_unmute)(struct ct_atc *atc, unsigned char state); | 121 | int (*spdif_in_unmute)(struct ct_atc *atc, unsigned char state); |
120 | int (*spdif_out_get_status)(struct ct_atc *atc, unsigned int *status); | 122 | int (*spdif_out_get_status)(struct ct_atc *atc, unsigned int *status); |
121 | int (*spdif_out_set_status)(struct ct_atc *atc, unsigned int status); | 123 | int (*spdif_out_set_status)(struct ct_atc *atc, unsigned int status); |
122 | int (*spdif_out_passthru)(struct ct_atc *atc, unsigned char state); | 124 | int (*spdif_out_passthru)(struct ct_atc *atc, unsigned char state); |
123 | int (*have_digit_io_switch)(struct ct_atc *atc); | 125 | struct capabilities (*capabilities)(struct ct_atc *atc); |
126 | int (*output_switch_get)(struct ct_atc *atc); | ||
127 | int (*output_switch_put)(struct ct_atc *atc, int position); | ||
128 | int (*mic_source_switch_get)(struct ct_atc *atc); | ||
129 | int (*mic_source_switch_put)(struct ct_atc *atc, int position); | ||
124 | 130 | ||
125 | /* Don't touch! Used for internal object. */ | 131 | /* Don't touch! Used for internal object. */ |
126 | void *rsc_mgrs[NUM_RSCTYP]; /* chip resource managers */ | 132 | void *rsc_mgrs[NUM_RSCTYP]; /* chip resource managers */ |
diff --git a/sound/pci/ctxfi/ctdaio.c b/sound/pci/ctxfi/ctdaio.c index 47d9ea97de0..0c00eb4088e 100644 --- a/sound/pci/ctxfi/ctdaio.c +++ b/sound/pci/ctxfi/ctdaio.c | |||
@@ -22,20 +22,9 @@ | |||
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
24 | 24 | ||
25 | #define DAIO_RESOURCE_NUM NUM_DAIOTYP | ||
26 | #define DAIO_OUT_MAX SPDIFOO | 25 | #define DAIO_OUT_MAX SPDIFOO |
27 | 26 | ||
28 | union daio_usage { | 27 | struct daio_usage { |
29 | struct { | ||
30 | unsigned short lineo1:1; | ||
31 | unsigned short lineo2:1; | ||
32 | unsigned short lineo3:1; | ||
33 | unsigned short lineo4:1; | ||
34 | unsigned short spdifoo:1; | ||
35 | unsigned short lineim:1; | ||
36 | unsigned short spdifio:1; | ||
37 | unsigned short spdifi1:1; | ||
38 | } bf; | ||
39 | unsigned short data; | 28 | unsigned short data; |
40 | }; | 29 | }; |
41 | 30 | ||
@@ -61,6 +50,7 @@ struct daio_rsc_idx idx_20k2[NUM_DAIOTYP] = { | |||
61 | [LINEO3] = {.left = 0x50, .right = 0x51}, | 50 | [LINEO3] = {.left = 0x50, .right = 0x51}, |
62 | [LINEO4] = {.left = 0x70, .right = 0x71}, | 51 | [LINEO4] = {.left = 0x70, .right = 0x71}, |
63 | [LINEIM] = {.left = 0x45, .right = 0xc5}, | 52 | [LINEIM] = {.left = 0x45, .right = 0xc5}, |
53 | [MIC] = {.left = 0x55, .right = 0xd5}, | ||
64 | [SPDIFOO] = {.left = 0x00, .right = 0x01}, | 54 | [SPDIFOO] = {.left = 0x00, .right = 0x01}, |
65 | [SPDIFIO] = {.left = 0x05, .right = 0x85}, | 55 | [SPDIFIO] = {.left = 0x05, .right = 0x85}, |
66 | }; | 56 | }; |
@@ -138,6 +128,7 @@ static unsigned int daio_device_index(enum DAIOTYP type, struct hw *hw) | |||
138 | case LINEO3: return 5; | 128 | case LINEO3: return 5; |
139 | case LINEO4: return 6; | 129 | case LINEO4: return 6; |
140 | case LINEIM: return 4; | 130 | case LINEIM: return 4; |
131 | case MIC: return 5; | ||
141 | default: return -EINVAL; | 132 | default: return -EINVAL; |
142 | } | 133 | } |
143 | default: | 134 | default: |
@@ -519,17 +510,17 @@ static int dai_rsc_uninit(struct dai *dai) | |||
519 | 510 | ||
520 | static int daio_mgr_get_rsc(struct rsc_mgr *mgr, enum DAIOTYP type) | 511 | static int daio_mgr_get_rsc(struct rsc_mgr *mgr, enum DAIOTYP type) |
521 | { | 512 | { |
522 | if (((union daio_usage *)mgr->rscs)->data & (0x1 << type)) | 513 | if (((struct daio_usage *)mgr->rscs)->data & (0x1 << type)) |
523 | return -ENOENT; | 514 | return -ENOENT; |
524 | 515 | ||
525 | ((union daio_usage *)mgr->rscs)->data |= (0x1 << type); | 516 | ((struct daio_usage *)mgr->rscs)->data |= (0x1 << type); |
526 | 517 | ||
527 | return 0; | 518 | return 0; |
528 | } | 519 | } |
529 | 520 | ||
530 | static int daio_mgr_put_rsc(struct rsc_mgr *mgr, enum DAIOTYP type) | 521 | static int daio_mgr_put_rsc(struct rsc_mgr *mgr, enum DAIOTYP type) |
531 | { | 522 | { |
532 | ((union daio_usage *)mgr->rscs)->data &= ~(0x1 << type); | 523 | ((struct daio_usage *)mgr->rscs)->data &= ~(0x1 << type); |
533 | 524 | ||
534 | return 0; | 525 | return 0; |
535 | } | 526 | } |
@@ -712,7 +703,7 @@ int daio_mgr_create(void *hw, struct daio_mgr **rdaio_mgr) | |||
712 | if (!daio_mgr) | 703 | if (!daio_mgr) |
713 | return -ENOMEM; | 704 | return -ENOMEM; |
714 | 705 | ||
715 | err = rsc_mgr_init(&daio_mgr->mgr, DAIO, DAIO_RESOURCE_NUM, hw); | 706 | err = rsc_mgr_init(&daio_mgr->mgr, DAIO, NUM_DAIOTYP, hw); |
716 | if (err) | 707 | if (err) |
717 | goto error1; | 708 | goto error1; |
718 | 709 | ||
diff --git a/sound/pci/ctxfi/ctdaio.h b/sound/pci/ctxfi/ctdaio.h index 0f52ce571ee..85ccb6ee1ab 100644 --- a/sound/pci/ctxfi/ctdaio.h +++ b/sound/pci/ctxfi/ctdaio.h | |||
@@ -33,6 +33,7 @@ enum DAIOTYP { | |||
33 | SPDIFOO, /* S/PDIF Out (Flexijack/Optical) */ | 33 | SPDIFOO, /* S/PDIF Out (Flexijack/Optical) */ |
34 | LINEIM, | 34 | LINEIM, |
35 | SPDIFIO, /* S/PDIF In (Flexijack/Optical) on the card */ | 35 | SPDIFIO, /* S/PDIF In (Flexijack/Optical) on the card */ |
36 | MIC, /* Dedicated mic on Titanium HD */ | ||
36 | SPDIFI1, /* S/PDIF In on internal Drive Bay */ | 37 | SPDIFI1, /* S/PDIF In on internal Drive Bay */ |
37 | NUM_DAIOTYP | 38 | NUM_DAIOTYP |
38 | }; | 39 | }; |
diff --git a/sound/pci/ctxfi/cthardware.h b/sound/pci/ctxfi/cthardware.h index af55405f5de..908315bec3b 100644 --- a/sound/pci/ctxfi/cthardware.h +++ b/sound/pci/ctxfi/cthardware.h | |||
@@ -39,6 +39,7 @@ enum CTCARDS { | |||
39 | CT20K2_MODEL_FIRST = CTSB0760, | 39 | CT20K2_MODEL_FIRST = CTSB0760, |
40 | CTHENDRIX, | 40 | CTHENDRIX, |
41 | CTSB0880, | 41 | CTSB0880, |
42 | CTSB1270, | ||
42 | CT20K2_UNKNOWN, | 43 | CT20K2_UNKNOWN, |
43 | NUM_CTCARDS /* This should always be the last */ | 44 | NUM_CTCARDS /* This should always be the last */ |
44 | }; | 45 | }; |
@@ -60,6 +61,13 @@ struct card_conf { | |||
60 | unsigned int msr; /* master sample rate in rsrs */ | 61 | unsigned int msr; /* master sample rate in rsrs */ |
61 | }; | 62 | }; |
62 | 63 | ||
64 | struct capabilities { | ||
65 | unsigned int digit_io_switch:1; | ||
66 | unsigned int dedicated_mic:1; | ||
67 | unsigned int output_switch:1; | ||
68 | unsigned int mic_source_switch:1; | ||
69 | }; | ||
70 | |||
63 | struct hw { | 71 | struct hw { |
64 | int (*card_init)(struct hw *hw, struct card_conf *info); | 72 | int (*card_init)(struct hw *hw, struct card_conf *info); |
65 | int (*card_stop)(struct hw *hw); | 73 | int (*card_stop)(struct hw *hw); |
@@ -70,7 +78,11 @@ struct hw { | |||
70 | #endif | 78 | #endif |
71 | int (*is_adc_source_selected)(struct hw *hw, enum ADCSRC source); | 79 | int (*is_adc_source_selected)(struct hw *hw, enum ADCSRC source); |
72 | int (*select_adc_source)(struct hw *hw, enum ADCSRC source); | 80 | int (*select_adc_source)(struct hw *hw, enum ADCSRC source); |
73 | int (*have_digit_io_switch)(struct hw *hw); | 81 | struct capabilities (*capabilities)(struct hw *hw); |
82 | int (*output_switch_get)(struct hw *hw); | ||
83 | int (*output_switch_put)(struct hw *hw, int position); | ||
84 | int (*mic_source_switch_get)(struct hw *hw); | ||
85 | int (*mic_source_switch_put)(struct hw *hw, int position); | ||
74 | 86 | ||
75 | /* SRC operations */ | 87 | /* SRC operations */ |
76 | int (*src_rsc_get_ctrl_blk)(void **rblk); | 88 | int (*src_rsc_get_ctrl_blk)(void **rblk); |
diff --git a/sound/pci/ctxfi/cthw20k1.c b/sound/pci/ctxfi/cthw20k1.c index a5c957db5ce..a7df19791f5 100644 --- a/sound/pci/ctxfi/cthw20k1.c +++ b/sound/pci/ctxfi/cthw20k1.c | |||
@@ -1777,10 +1777,17 @@ static int hw_adc_init(struct hw *hw, const struct adc_conf *info) | |||
1777 | return adc_init_SBx(hw, info->input, info->mic20db); | 1777 | return adc_init_SBx(hw, info->input, info->mic20db); |
1778 | } | 1778 | } |
1779 | 1779 | ||
1780 | static int hw_have_digit_io_switch(struct hw *hw) | 1780 | static struct capabilities hw_capabilities(struct hw *hw) |
1781 | { | 1781 | { |
1782 | struct capabilities cap; | ||
1783 | |||
1782 | /* SB073x and Vista compatible cards have no digit IO switch */ | 1784 | /* SB073x and Vista compatible cards have no digit IO switch */ |
1783 | return !(hw->model == CTSB073X || hw->model == CTUAA); | 1785 | cap.digit_io_switch = !(hw->model == CTSB073X || hw->model == CTUAA); |
1786 | cap.dedicated_mic = 0; | ||
1787 | cap.output_switch = 0; | ||
1788 | cap.mic_source_switch = 0; | ||
1789 | |||
1790 | return cap; | ||
1784 | } | 1791 | } |
1785 | 1792 | ||
1786 | #define CTLBITS(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d)) | 1793 | #define CTLBITS(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d)) |
@@ -1933,7 +1940,7 @@ static int hw_card_start(struct hw *hw) | |||
1933 | 1940 | ||
1934 | if (hw->irq < 0) { | 1941 | if (hw->irq < 0) { |
1935 | err = request_irq(pci->irq, ct_20k1_interrupt, IRQF_SHARED, | 1942 | err = request_irq(pci->irq, ct_20k1_interrupt, IRQF_SHARED, |
1936 | "ctxfi", hw); | 1943 | KBUILD_MODNAME, hw); |
1937 | if (err < 0) { | 1944 | if (err < 0) { |
1938 | printk(KERN_ERR "XFi: Cannot get irq %d\n", pci->irq); | 1945 | printk(KERN_ERR "XFi: Cannot get irq %d\n", pci->irq); |
1939 | goto error2; | 1946 | goto error2; |
@@ -2172,7 +2179,7 @@ static struct hw ct20k1_preset __devinitdata = { | |||
2172 | .pll_init = hw_pll_init, | 2179 | .pll_init = hw_pll_init, |
2173 | .is_adc_source_selected = hw_is_adc_input_selected, | 2180 | .is_adc_source_selected = hw_is_adc_input_selected, |
2174 | .select_adc_source = hw_adc_input_select, | 2181 | .select_adc_source = hw_adc_input_select, |
2175 | .have_digit_io_switch = hw_have_digit_io_switch, | 2182 | .capabilities = hw_capabilities, |
2176 | #ifdef CONFIG_PM | 2183 | #ifdef CONFIG_PM |
2177 | .suspend = hw_suspend, | 2184 | .suspend = hw_suspend, |
2178 | .resume = hw_resume, | 2185 | .resume = hw_resume, |
diff --git a/sound/pci/ctxfi/cthw20k2.c b/sound/pci/ctxfi/cthw20k2.c index 5364164674e..d6c54b524bf 100644 --- a/sound/pci/ctxfi/cthw20k2.c +++ b/sound/pci/ctxfi/cthw20k2.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * @File cthw20k2.c | 8 | * @File cthw20k2.c |
9 | * | 9 | * |
10 | * @Brief | 10 | * @Brief |
11 | * This file contains the implementation of hardware access methord for 20k2. | 11 | * This file contains the implementation of hardware access method for 20k2. |
12 | * | 12 | * |
13 | * @Author Liu Chun | 13 | * @Author Liu Chun |
14 | * @Date May 14 2008 | 14 | * @Date May 14 2008 |
@@ -38,6 +38,8 @@ struct hw20k2 { | |||
38 | unsigned char dev_id; | 38 | unsigned char dev_id; |
39 | unsigned char addr_size; | 39 | unsigned char addr_size; |
40 | unsigned char data_size; | 40 | unsigned char data_size; |
41 | |||
42 | int mic_source; | ||
41 | }; | 43 | }; |
42 | 44 | ||
43 | static u32 hw_read_20kx(struct hw *hw, u32 reg); | 45 | static u32 hw_read_20kx(struct hw *hw, u32 reg); |
@@ -1163,7 +1165,12 @@ static int hw_daio_init(struct hw *hw, const struct daio_conf *info) | |||
1163 | hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x01010101); | 1165 | hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x01010101); |
1164 | hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0); | 1166 | hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0); |
1165 | } else if (2 == info->msr) { | 1167 | } else if (2 == info->msr) { |
1166 | hw_write_20kx(hw, AUDIO_IO_MCLK, 0x11111111); | 1168 | if (hw->model != CTSB1270) { |
1169 | hw_write_20kx(hw, AUDIO_IO_MCLK, 0x11111111); | ||
1170 | } else { | ||
1171 | /* PCM4220 on Titanium HD is different. */ | ||
1172 | hw_write_20kx(hw, AUDIO_IO_MCLK, 0x11011111); | ||
1173 | } | ||
1167 | /* Specify all playing 96khz | 1174 | /* Specify all playing 96khz |
1168 | * EA [0] - Enabled | 1175 | * EA [0] - Enabled |
1169 | * RTA [4:5] - 96kHz | 1176 | * RTA [4:5] - 96kHz |
@@ -1175,6 +1182,10 @@ static int hw_daio_init(struct hw *hw, const struct daio_conf *info) | |||
1175 | * RTD [28:29] - 96kHz */ | 1182 | * RTD [28:29] - 96kHz */ |
1176 | hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x11111111); | 1183 | hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x11111111); |
1177 | hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0); | 1184 | hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0); |
1185 | } else if ((4 == info->msr) && (hw->model == CTSB1270)) { | ||
1186 | hw_write_20kx(hw, AUDIO_IO_MCLK, 0x21011111); | ||
1187 | hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x21212121); | ||
1188 | hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0); | ||
1178 | } else { | 1189 | } else { |
1179 | printk(KERN_ALERT "ctxfi: ERROR!!! Invalid sampling rate!!!\n"); | 1190 | printk(KERN_ALERT "ctxfi: ERROR!!! Invalid sampling rate!!!\n"); |
1180 | return -EINVAL; | 1191 | return -EINVAL; |
@@ -1182,6 +1193,8 @@ static int hw_daio_init(struct hw *hw, const struct daio_conf *info) | |||
1182 | 1193 | ||
1183 | for (i = 0; i < 8; i++) { | 1194 | for (i = 0; i < 8; i++) { |
1184 | if (i <= 3) { | 1195 | if (i <= 3) { |
1196 | /* This comment looks wrong since loop is over 4 */ | ||
1197 | /* channels and emu20k2 supports 4 spdif IOs. */ | ||
1185 | /* 1st 3 channels are SPDIFs (SB0960) */ | 1198 | /* 1st 3 channels are SPDIFs (SB0960) */ |
1186 | if (i == 3) | 1199 | if (i == 3) |
1187 | data = 0x1001001; | 1200 | data = 0x1001001; |
@@ -1206,12 +1219,16 @@ static int hw_daio_init(struct hw *hw, const struct daio_conf *info) | |||
1206 | 1219 | ||
1207 | hw_write_20kx(hw, AUDIO_IO_TX_CSTAT_H+(0x40*i), 0x0B); | 1220 | hw_write_20kx(hw, AUDIO_IO_TX_CSTAT_H+(0x40*i), 0x0B); |
1208 | } else { | 1221 | } else { |
1222 | /* Again, loop is over 4 channels not 5. */ | ||
1209 | /* Next 5 channels are I2S (SB0960) */ | 1223 | /* Next 5 channels are I2S (SB0960) */ |
1210 | data = 0x11; | 1224 | data = 0x11; |
1211 | hw_write_20kx(hw, AUDIO_IO_RX_CTL+(0x40*i), data); | 1225 | hw_write_20kx(hw, AUDIO_IO_RX_CTL+(0x40*i), data); |
1212 | if (2 == info->msr) { | 1226 | if (2 == info->msr) { |
1213 | /* Four channels per sample period */ | 1227 | /* Four channels per sample period */ |
1214 | data |= 0x1000; | 1228 | data |= 0x1000; |
1229 | } else if (4 == info->msr) { | ||
1230 | /* FIXME: check this against the chip spec */ | ||
1231 | data |= 0x2000; | ||
1215 | } | 1232 | } |
1216 | hw_write_20kx(hw, AUDIO_IO_TX_CTL+(0x40*i), data); | 1233 | hw_write_20kx(hw, AUDIO_IO_TX_CTL+(0x40*i), data); |
1217 | } | 1234 | } |
@@ -1299,21 +1316,18 @@ static int hw_pll_init(struct hw *hw, unsigned int rsr) | |||
1299 | 1316 | ||
1300 | pllenb = 0xB; | 1317 | pllenb = 0xB; |
1301 | hw_write_20kx(hw, PLL_ENB, pllenb); | 1318 | hw_write_20kx(hw, PLL_ENB, pllenb); |
1302 | pllctl = 0x20D00000; | 1319 | pllctl = 0x20C00000; |
1303 | set_field(&pllctl, PLLCTL_FD, 16 - 4); | 1320 | set_field(&pllctl, PLLCTL_B, 0); |
1321 | set_field(&pllctl, PLLCTL_FD, 48000 == rsr ? 16 - 4 : 147 - 4); | ||
1322 | set_field(&pllctl, PLLCTL_RD, 48000 == rsr ? 1 - 1 : 10 - 1); | ||
1304 | hw_write_20kx(hw, PLL_CTL, pllctl); | 1323 | hw_write_20kx(hw, PLL_CTL, pllctl); |
1305 | mdelay(40); | 1324 | mdelay(40); |
1325 | |||
1306 | pllctl = hw_read_20kx(hw, PLL_CTL); | 1326 | pllctl = hw_read_20kx(hw, PLL_CTL); |
1307 | set_field(&pllctl, PLLCTL_B, 0); | 1327 | set_field(&pllctl, PLLCTL_FD, 48000 == rsr ? 16 - 2 : 147 - 2); |
1308 | if (48000 == rsr) { | ||
1309 | set_field(&pllctl, PLLCTL_FD, 16 - 2); | ||
1310 | set_field(&pllctl, PLLCTL_RD, 1 - 1); /* 3000*16/1 = 48000 */ | ||
1311 | } else { /* 44100 */ | ||
1312 | set_field(&pllctl, PLLCTL_FD, 147 - 2); | ||
1313 | set_field(&pllctl, PLLCTL_RD, 10 - 1); /* 3000*147/10 = 44100 */ | ||
1314 | } | ||
1315 | hw_write_20kx(hw, PLL_CTL, pllctl); | 1328 | hw_write_20kx(hw, PLL_CTL, pllctl); |
1316 | mdelay(40); | 1329 | mdelay(40); |
1330 | |||
1317 | for (i = 0; i < 1000; i++) { | 1331 | for (i = 0; i < 1000; i++) { |
1318 | pllstat = hw_read_20kx(hw, PLL_STAT); | 1332 | pllstat = hw_read_20kx(hw, PLL_STAT); |
1319 | if (get_field(pllstat, PLLSTAT_PD)) | 1333 | if (get_field(pllstat, PLLSTAT_PD)) |
@@ -1557,7 +1571,7 @@ static int hw20k2_i2c_write(struct hw *hw, u16 addr, u32 data) | |||
1557 | 1571 | ||
1558 | hw_write_20kx(hw, I2C_IF_STATUS, i2c_status); | 1572 | hw_write_20kx(hw, I2C_IF_STATUS, i2c_status); |
1559 | hw20k2_i2c_wait_data_ready(hw); | 1573 | hw20k2_i2c_wait_data_ready(hw); |
1560 | /* Dummy write to trigger the write oprtation */ | 1574 | /* Dummy write to trigger the write operation */ |
1561 | hw_write_20kx(hw, I2C_IF_WDATA, 0); | 1575 | hw_write_20kx(hw, I2C_IF_WDATA, 0); |
1562 | hw20k2_i2c_wait_data_ready(hw); | 1576 | hw20k2_i2c_wait_data_ready(hw); |
1563 | 1577 | ||
@@ -1568,6 +1582,30 @@ static int hw20k2_i2c_write(struct hw *hw, u16 addr, u32 data) | |||
1568 | return 0; | 1582 | return 0; |
1569 | } | 1583 | } |
1570 | 1584 | ||
1585 | static void hw_dac_stop(struct hw *hw) | ||
1586 | { | ||
1587 | u32 data; | ||
1588 | data = hw_read_20kx(hw, GPIO_DATA); | ||
1589 | data &= 0xFFFFFFFD; | ||
1590 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1591 | mdelay(10); | ||
1592 | } | ||
1593 | |||
1594 | static void hw_dac_start(struct hw *hw) | ||
1595 | { | ||
1596 | u32 data; | ||
1597 | data = hw_read_20kx(hw, GPIO_DATA); | ||
1598 | data |= 0x2; | ||
1599 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1600 | mdelay(50); | ||
1601 | } | ||
1602 | |||
1603 | static void hw_dac_reset(struct hw *hw) | ||
1604 | { | ||
1605 | hw_dac_stop(hw); | ||
1606 | hw_dac_start(hw); | ||
1607 | } | ||
1608 | |||
1571 | static int hw_dac_init(struct hw *hw, const struct dac_conf *info) | 1609 | static int hw_dac_init(struct hw *hw, const struct dac_conf *info) |
1572 | { | 1610 | { |
1573 | int err; | 1611 | int err; |
@@ -1594,6 +1632,21 @@ static int hw_dac_init(struct hw *hw, const struct dac_conf *info) | |||
1594 | 0x00000000 /* Vol Control B4 */ | 1632 | 0x00000000 /* Vol Control B4 */ |
1595 | }; | 1633 | }; |
1596 | 1634 | ||
1635 | if (hw->model == CTSB1270) { | ||
1636 | hw_dac_stop(hw); | ||
1637 | data = hw_read_20kx(hw, GPIO_DATA); | ||
1638 | data &= ~0x0600; | ||
1639 | if (1 == info->msr) | ||
1640 | data |= 0x0000; /* Single Speed Mode 0-50kHz */ | ||
1641 | else if (2 == info->msr) | ||
1642 | data |= 0x0200; /* Double Speed Mode 50-100kHz */ | ||
1643 | else | ||
1644 | data |= 0x0600; /* Quad Speed Mode 100-200kHz */ | ||
1645 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1646 | hw_dac_start(hw); | ||
1647 | return 0; | ||
1648 | } | ||
1649 | |||
1597 | /* Set DAC reset bit as output */ | 1650 | /* Set DAC reset bit as output */ |
1598 | data = hw_read_20kx(hw, GPIO_CTRL); | 1651 | data = hw_read_20kx(hw, GPIO_CTRL); |
1599 | data |= 0x02; | 1652 | data |= 0x02; |
@@ -1606,22 +1659,8 @@ static int hw_dac_init(struct hw *hw, const struct dac_conf *info) | |||
1606 | for (i = 0; i < 2; i++) { | 1659 | for (i = 0; i < 2; i++) { |
1607 | /* Reset DAC twice just in-case the chip | 1660 | /* Reset DAC twice just in-case the chip |
1608 | * didn't initialized properly */ | 1661 | * didn't initialized properly */ |
1609 | data = hw_read_20kx(hw, GPIO_DATA); | 1662 | hw_dac_reset(hw); |
1610 | /* GPIO data bit 1 */ | 1663 | hw_dac_reset(hw); |
1611 | data &= 0xFFFFFFFD; | ||
1612 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1613 | mdelay(10); | ||
1614 | data |= 0x2; | ||
1615 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1616 | mdelay(50); | ||
1617 | |||
1618 | /* Reset the 2nd time */ | ||
1619 | data &= 0xFFFFFFFD; | ||
1620 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1621 | mdelay(10); | ||
1622 | data |= 0x2; | ||
1623 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1624 | mdelay(50); | ||
1625 | 1664 | ||
1626 | if (hw20k2_i2c_read(hw, CS4382_MC1, &cs_read.mode_control_1)) | 1665 | if (hw20k2_i2c_read(hw, CS4382_MC1, &cs_read.mode_control_1)) |
1627 | continue; | 1666 | continue; |
@@ -1725,7 +1764,11 @@ End: | |||
1725 | static int hw_is_adc_input_selected(struct hw *hw, enum ADCSRC type) | 1764 | static int hw_is_adc_input_selected(struct hw *hw, enum ADCSRC type) |
1726 | { | 1765 | { |
1727 | u32 data; | 1766 | u32 data; |
1728 | 1767 | if (hw->model == CTSB1270) { | |
1768 | /* Titanium HD has two ADC chips, one for line in and one */ | ||
1769 | /* for MIC. We don't need to switch the ADC input. */ | ||
1770 | return 1; | ||
1771 | } | ||
1729 | data = hw_read_20kx(hw, GPIO_DATA); | 1772 | data = hw_read_20kx(hw, GPIO_DATA); |
1730 | switch (type) { | 1773 | switch (type) { |
1731 | case ADC_MICIN: | 1774 | case ADC_MICIN: |
@@ -1742,35 +1785,47 @@ static int hw_is_adc_input_selected(struct hw *hw, enum ADCSRC type) | |||
1742 | 1785 | ||
1743 | #define MIC_BOOST_0DB 0xCF | 1786 | #define MIC_BOOST_0DB 0xCF |
1744 | #define MIC_BOOST_STEPS_PER_DB 2 | 1787 | #define MIC_BOOST_STEPS_PER_DB 2 |
1745 | #define MIC_BOOST_20DB (MIC_BOOST_0DB + 20 * MIC_BOOST_STEPS_PER_DB) | 1788 | |
1789 | static void hw_wm8775_input_select(struct hw *hw, u8 input, s8 gain_in_db) | ||
1790 | { | ||
1791 | u32 adcmc, gain; | ||
1792 | |||
1793 | if (input > 3) | ||
1794 | input = 3; | ||
1795 | |||
1796 | adcmc = ((u32)1 << input) | 0x100; /* Link L+R gain... */ | ||
1797 | |||
1798 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, adcmc), | ||
1799 | MAKE_WM8775_DATA(adcmc)); | ||
1800 | |||
1801 | if (gain_in_db < -103) | ||
1802 | gain_in_db = -103; | ||
1803 | if (gain_in_db > 24) | ||
1804 | gain_in_db = 24; | ||
1805 | |||
1806 | gain = gain_in_db * MIC_BOOST_STEPS_PER_DB + MIC_BOOST_0DB; | ||
1807 | |||
1808 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCL, gain), | ||
1809 | MAKE_WM8775_DATA(gain)); | ||
1810 | /* ...so there should be no need for the following. */ | ||
1811 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCR, gain), | ||
1812 | MAKE_WM8775_DATA(gain)); | ||
1813 | } | ||
1746 | 1814 | ||
1747 | static int hw_adc_input_select(struct hw *hw, enum ADCSRC type) | 1815 | static int hw_adc_input_select(struct hw *hw, enum ADCSRC type) |
1748 | { | 1816 | { |
1749 | u32 data; | 1817 | u32 data; |
1750 | |||
1751 | data = hw_read_20kx(hw, GPIO_DATA); | 1818 | data = hw_read_20kx(hw, GPIO_DATA); |
1752 | switch (type) { | 1819 | switch (type) { |
1753 | case ADC_MICIN: | 1820 | case ADC_MICIN: |
1754 | data |= (0x1 << 14); | 1821 | data |= (0x1 << 14); |
1755 | hw_write_20kx(hw, GPIO_DATA, data); | 1822 | hw_write_20kx(hw, GPIO_DATA, data); |
1756 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x101), | 1823 | hw_wm8775_input_select(hw, 0, 20); /* Mic, 20dB */ |
1757 | MAKE_WM8775_DATA(0x101)); /* Mic-in */ | ||
1758 | hw20k2_i2c_write(hw, | ||
1759 | MAKE_WM8775_ADDR(WM8775_AADCL, MIC_BOOST_20DB), | ||
1760 | MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */ | ||
1761 | hw20k2_i2c_write(hw, | ||
1762 | MAKE_WM8775_ADDR(WM8775_AADCR, MIC_BOOST_20DB), | ||
1763 | MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */ | ||
1764 | break; | 1824 | break; |
1765 | case ADC_LINEIN: | 1825 | case ADC_LINEIN: |
1766 | data &= ~(0x1 << 14); | 1826 | data &= ~(0x1 << 14); |
1767 | hw_write_20kx(hw, GPIO_DATA, data); | 1827 | hw_write_20kx(hw, GPIO_DATA, data); |
1768 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x102), | 1828 | hw_wm8775_input_select(hw, 1, 0); /* Line-in, 0dB */ |
1769 | MAKE_WM8775_DATA(0x102)); /* Line-in */ | ||
1770 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCL, 0xCF), | ||
1771 | MAKE_WM8775_DATA(0xCF)); /* No boost */ | ||
1772 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCR, 0xCF), | ||
1773 | MAKE_WM8775_DATA(0xCF)); /* No boost */ | ||
1774 | break; | 1829 | break; |
1775 | default: | 1830 | default: |
1776 | break; | 1831 | break; |
@@ -1782,7 +1837,7 @@ static int hw_adc_input_select(struct hw *hw, enum ADCSRC type) | |||
1782 | static int hw_adc_init(struct hw *hw, const struct adc_conf *info) | 1837 | static int hw_adc_init(struct hw *hw, const struct adc_conf *info) |
1783 | { | 1838 | { |
1784 | int err; | 1839 | int err; |
1785 | u32 mux = 2, data, ctl; | 1840 | u32 data, ctl; |
1786 | 1841 | ||
1787 | /* Set ADC reset bit as output */ | 1842 | /* Set ADC reset bit as output */ |
1788 | data = hw_read_20kx(hw, GPIO_CTRL); | 1843 | data = hw_read_20kx(hw, GPIO_CTRL); |
@@ -1796,19 +1851,42 @@ static int hw_adc_init(struct hw *hw, const struct adc_conf *info) | |||
1796 | goto error; | 1851 | goto error; |
1797 | } | 1852 | } |
1798 | 1853 | ||
1799 | /* Make ADC in normal operation */ | 1854 | /* Reset the ADC (reset is active low). */ |
1800 | data = hw_read_20kx(hw, GPIO_DATA); | 1855 | data = hw_read_20kx(hw, GPIO_DATA); |
1801 | data &= ~(0x1 << 15); | 1856 | data &= ~(0x1 << 15); |
1857 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1858 | |||
1859 | if (hw->model == CTSB1270) { | ||
1860 | /* Set up the PCM4220 ADC on Titanium HD */ | ||
1861 | data &= ~0x0C; | ||
1862 | if (1 == info->msr) | ||
1863 | data |= 0x00; /* Single Speed Mode 32-50kHz */ | ||
1864 | else if (2 == info->msr) | ||
1865 | data |= 0x08; /* Double Speed Mode 50-108kHz */ | ||
1866 | else | ||
1867 | data |= 0x04; /* Quad Speed Mode 108kHz-216kHz */ | ||
1868 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1869 | } | ||
1870 | |||
1802 | mdelay(10); | 1871 | mdelay(10); |
1872 | /* Return the ADC to normal operation. */ | ||
1803 | data |= (0x1 << 15); | 1873 | data |= (0x1 << 15); |
1804 | hw_write_20kx(hw, GPIO_DATA, data); | 1874 | hw_write_20kx(hw, GPIO_DATA, data); |
1805 | mdelay(50); | 1875 | mdelay(50); |
1806 | 1876 | ||
1877 | /* I2C write to register offset 0x0B to set ADC LRCLK polarity */ | ||
1878 | /* invert bit, interface format to I2S, word length to 24-bit, */ | ||
1879 | /* enable ADC high pass filter. Fixes bug 5323? */ | ||
1880 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_IC, 0x26), | ||
1881 | MAKE_WM8775_DATA(0x26)); | ||
1882 | |||
1807 | /* Set the master mode (256fs) */ | 1883 | /* Set the master mode (256fs) */ |
1808 | if (1 == info->msr) { | 1884 | if (1 == info->msr) { |
1885 | /* slave mode, 128x oversampling 256fs */ | ||
1809 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_MMC, 0x02), | 1886 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_MMC, 0x02), |
1810 | MAKE_WM8775_DATA(0x02)); | 1887 | MAKE_WM8775_DATA(0x02)); |
1811 | } else if (2 == info->msr) { | 1888 | } else if ((2 == info->msr) || (4 == info->msr)) { |
1889 | /* slave mode, 64x oversampling, 256fs */ | ||
1812 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_MMC, 0x0A), | 1890 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_MMC, 0x0A), |
1813 | MAKE_WM8775_DATA(0x0A)); | 1891 | MAKE_WM8775_DATA(0x0A)); |
1814 | } else { | 1892 | } else { |
@@ -1818,55 +1896,113 @@ static int hw_adc_init(struct hw *hw, const struct adc_conf *info) | |||
1818 | goto error; | 1896 | goto error; |
1819 | } | 1897 | } |
1820 | 1898 | ||
1821 | /* Configure GPIO bit 14 change to line-in/mic-in */ | 1899 | if (hw->model != CTSB1270) { |
1822 | ctl = hw_read_20kx(hw, GPIO_CTRL); | 1900 | /* Configure GPIO bit 14 change to line-in/mic-in */ |
1823 | ctl |= 0x1 << 14; | 1901 | ctl = hw_read_20kx(hw, GPIO_CTRL); |
1824 | hw_write_20kx(hw, GPIO_CTRL, ctl); | 1902 | ctl |= 0x1 << 14; |
1825 | 1903 | hw_write_20kx(hw, GPIO_CTRL, ctl); | |
1826 | /* Check using Mic-in or Line-in */ | 1904 | hw_adc_input_select(hw, ADC_LINEIN); |
1827 | data = hw_read_20kx(hw, GPIO_DATA); | ||
1828 | |||
1829 | if (mux == 1) { | ||
1830 | /* Configures GPIO data to select Mic-in */ | ||
1831 | data |= 0x1 << 14; | ||
1832 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1833 | |||
1834 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x101), | ||
1835 | MAKE_WM8775_DATA(0x101)); /* Mic-in */ | ||
1836 | hw20k2_i2c_write(hw, | ||
1837 | MAKE_WM8775_ADDR(WM8775_AADCL, MIC_BOOST_20DB), | ||
1838 | MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */ | ||
1839 | hw20k2_i2c_write(hw, | ||
1840 | MAKE_WM8775_ADDR(WM8775_AADCR, MIC_BOOST_20DB), | ||
1841 | MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */ | ||
1842 | } else if (mux == 2) { | ||
1843 | /* Configures GPIO data to select Line-in */ | ||
1844 | data &= ~(0x1 << 14); | ||
1845 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1846 | |||
1847 | /* Setup ADC */ | ||
1848 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x102), | ||
1849 | MAKE_WM8775_DATA(0x102)); /* Line-in */ | ||
1850 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCL, 0xCF), | ||
1851 | MAKE_WM8775_DATA(0xCF)); /* No boost */ | ||
1852 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCR, 0xCF), | ||
1853 | MAKE_WM8775_DATA(0xCF)); /* No boost */ | ||
1854 | } else { | 1905 | } else { |
1855 | printk(KERN_ALERT "ctxfi: ERROR!!! Invalid input mux!!!\n"); | 1906 | hw_wm8775_input_select(hw, 0, 0); |
1856 | err = -EINVAL; | ||
1857 | goto error; | ||
1858 | } | 1907 | } |
1859 | 1908 | ||
1860 | return 0; | 1909 | return 0; |
1861 | |||
1862 | error: | 1910 | error: |
1863 | hw20k2_i2c_uninit(hw); | 1911 | hw20k2_i2c_uninit(hw); |
1864 | return err; | 1912 | return err; |
1865 | } | 1913 | } |
1866 | 1914 | ||
1867 | static int hw_have_digit_io_switch(struct hw *hw) | 1915 | static struct capabilities hw_capabilities(struct hw *hw) |
1868 | { | 1916 | { |
1869 | return 0; | 1917 | struct capabilities cap; |
1918 | |||
1919 | cap.digit_io_switch = 0; | ||
1920 | cap.dedicated_mic = hw->model == CTSB1270; | ||
1921 | cap.output_switch = hw->model == CTSB1270; | ||
1922 | cap.mic_source_switch = hw->model == CTSB1270; | ||
1923 | |||
1924 | return cap; | ||
1925 | } | ||
1926 | |||
1927 | static int hw_output_switch_get(struct hw *hw) | ||
1928 | { | ||
1929 | u32 data = hw_read_20kx(hw, GPIO_EXT_DATA); | ||
1930 | |||
1931 | switch (data & 0x30) { | ||
1932 | case 0x00: | ||
1933 | return 0; | ||
1934 | case 0x10: | ||
1935 | return 1; | ||
1936 | case 0x20: | ||
1937 | return 2; | ||
1938 | default: | ||
1939 | return 3; | ||
1940 | } | ||
1941 | } | ||
1942 | |||
1943 | static int hw_output_switch_put(struct hw *hw, int position) | ||
1944 | { | ||
1945 | u32 data; | ||
1946 | |||
1947 | if (position == hw_output_switch_get(hw)) | ||
1948 | return 0; | ||
1949 | |||
1950 | /* Mute line and headphones (intended for anti-pop). */ | ||
1951 | data = hw_read_20kx(hw, GPIO_DATA); | ||
1952 | data |= (0x03 << 11); | ||
1953 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1954 | |||
1955 | data = hw_read_20kx(hw, GPIO_EXT_DATA) & ~0x30; | ||
1956 | switch (position) { | ||
1957 | case 0: | ||
1958 | break; | ||
1959 | case 1: | ||
1960 | data |= 0x10; | ||
1961 | break; | ||
1962 | default: | ||
1963 | data |= 0x20; | ||
1964 | } | ||
1965 | hw_write_20kx(hw, GPIO_EXT_DATA, data); | ||
1966 | |||
1967 | /* Unmute line and headphones. */ | ||
1968 | data = hw_read_20kx(hw, GPIO_DATA); | ||
1969 | data &= ~(0x03 << 11); | ||
1970 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1971 | |||
1972 | return 1; | ||
1973 | } | ||
1974 | |||
1975 | static int hw_mic_source_switch_get(struct hw *hw) | ||
1976 | { | ||
1977 | struct hw20k2 *hw20k2 = (struct hw20k2 *)hw; | ||
1978 | |||
1979 | return hw20k2->mic_source; | ||
1980 | } | ||
1981 | |||
1982 | static int hw_mic_source_switch_put(struct hw *hw, int position) | ||
1983 | { | ||
1984 | struct hw20k2 *hw20k2 = (struct hw20k2 *)hw; | ||
1985 | |||
1986 | if (position == hw20k2->mic_source) | ||
1987 | return 0; | ||
1988 | |||
1989 | switch (position) { | ||
1990 | case 0: | ||
1991 | hw_wm8775_input_select(hw, 0, 0); /* Mic, 0dB */ | ||
1992 | break; | ||
1993 | case 1: | ||
1994 | hw_wm8775_input_select(hw, 1, 0); /* FP Mic, 0dB */ | ||
1995 | break; | ||
1996 | case 2: | ||
1997 | hw_wm8775_input_select(hw, 3, 0); /* Aux Ext, 0dB */ | ||
1998 | break; | ||
1999 | default: | ||
2000 | return 0; | ||
2001 | } | ||
2002 | |||
2003 | hw20k2->mic_source = position; | ||
2004 | |||
2005 | return 1; | ||
1870 | } | 2006 | } |
1871 | 2007 | ||
1872 | static irqreturn_t ct_20k2_interrupt(int irq, void *dev_id) | 2008 | static irqreturn_t ct_20k2_interrupt(int irq, void *dev_id) |
@@ -1925,7 +2061,7 @@ static int hw_card_start(struct hw *hw) | |||
1925 | 2061 | ||
1926 | if (hw->irq < 0) { | 2062 | if (hw->irq < 0) { |
1927 | err = request_irq(pci->irq, ct_20k2_interrupt, IRQF_SHARED, | 2063 | err = request_irq(pci->irq, ct_20k2_interrupt, IRQF_SHARED, |
1928 | "ctxfi", hw); | 2064 | KBUILD_MODNAME, hw); |
1929 | if (err < 0) { | 2065 | if (err < 0) { |
1930 | printk(KERN_ERR "XFi: Cannot get irq %d\n", pci->irq); | 2066 | printk(KERN_ERR "XFi: Cannot get irq %d\n", pci->irq); |
1931 | goto error2; | 2067 | goto error2; |
@@ -2023,13 +2159,16 @@ static int hw_card_init(struct hw *hw, struct card_conf *info) | |||
2023 | /* Reset all SRC pending interrupts */ | 2159 | /* Reset all SRC pending interrupts */ |
2024 | hw_write_20kx(hw, SRC_IP, 0); | 2160 | hw_write_20kx(hw, SRC_IP, 0); |
2025 | 2161 | ||
2026 | /* TODO: detect the card ID and configure GPIO accordingly. */ | 2162 | if (hw->model != CTSB1270) { |
2027 | /* Configures GPIO (0xD802 0x98028) */ | 2163 | /* TODO: detect the card ID and configure GPIO accordingly. */ |
2028 | /*hw_write_20kx(hw, GPIO_CTRL, 0x7F07);*/ | 2164 | /* Configures GPIO (0xD802 0x98028) */ |
2029 | /* Configures GPIO (SB0880) */ | 2165 | /*hw_write_20kx(hw, GPIO_CTRL, 0x7F07);*/ |
2030 | /*hw_write_20kx(hw, GPIO_CTRL, 0xFF07);*/ | 2166 | /* Configures GPIO (SB0880) */ |
2031 | hw_write_20kx(hw, GPIO_CTRL, 0xD802); | 2167 | /*hw_write_20kx(hw, GPIO_CTRL, 0xFF07);*/ |
2032 | 2168 | hw_write_20kx(hw, GPIO_CTRL, 0xD802); | |
2169 | } else { | ||
2170 | hw_write_20kx(hw, GPIO_CTRL, 0x9E5F); | ||
2171 | } | ||
2033 | /* Enable audio ring */ | 2172 | /* Enable audio ring */ |
2034 | hw_write_20kx(hw, MIXER_AR_ENABLE, 0x01); | 2173 | hw_write_20kx(hw, MIXER_AR_ENABLE, 0x01); |
2035 | 2174 | ||
@@ -2106,7 +2245,11 @@ static struct hw ct20k2_preset __devinitdata = { | |||
2106 | .pll_init = hw_pll_init, | 2245 | .pll_init = hw_pll_init, |
2107 | .is_adc_source_selected = hw_is_adc_input_selected, | 2246 | .is_adc_source_selected = hw_is_adc_input_selected, |
2108 | .select_adc_source = hw_adc_input_select, | 2247 | .select_adc_source = hw_adc_input_select, |
2109 | .have_digit_io_switch = hw_have_digit_io_switch, | 2248 | .capabilities = hw_capabilities, |
2249 | .output_switch_get = hw_output_switch_get, | ||
2250 | .output_switch_put = hw_output_switch_put, | ||
2251 | .mic_source_switch_get = hw_mic_source_switch_get, | ||
2252 | .mic_source_switch_put = hw_mic_source_switch_put, | ||
2110 | #ifdef CONFIG_PM | 2253 | #ifdef CONFIG_PM |
2111 | .suspend = hw_suspend, | 2254 | .suspend = hw_suspend, |
2112 | .resume = hw_resume, | 2255 | .resume = hw_resume, |
diff --git a/sound/pci/ctxfi/ctmixer.c b/sound/pci/ctxfi/ctmixer.c index c3519ff42fb..0cc13eeef8d 100644 --- a/sound/pci/ctxfi/ctmixer.c +++ b/sound/pci/ctxfi/ctmixer.c | |||
@@ -86,9 +86,7 @@ enum CTALSA_MIXER_CTL { | |||
86 | MIXER_LINEIN_C_S, | 86 | MIXER_LINEIN_C_S, |
87 | MIXER_MIC_C_S, | 87 | MIXER_MIC_C_S, |
88 | MIXER_SPDIFI_C_S, | 88 | MIXER_SPDIFI_C_S, |
89 | MIXER_LINEIN_P_S, | ||
90 | MIXER_SPDIFO_P_S, | 89 | MIXER_SPDIFO_P_S, |
91 | MIXER_SPDIFI_P_S, | ||
92 | MIXER_WAVEF_P_S, | 90 | MIXER_WAVEF_P_S, |
93 | MIXER_WAVER_P_S, | 91 | MIXER_WAVER_P_S, |
94 | MIXER_WAVEC_P_S, | 92 | MIXER_WAVEC_P_S, |
@@ -137,11 +135,11 @@ ct_kcontrol_init_table[NUM_CTALSA_MIXERS] = { | |||
137 | }, | 135 | }, |
138 | [MIXER_LINEIN_P] = { | 136 | [MIXER_LINEIN_P] = { |
139 | .ctl = 1, | 137 | .ctl = 1, |
140 | .name = "Line-in Playback Volume", | 138 | .name = "Line Playback Volume", |
141 | }, | 139 | }, |
142 | [MIXER_LINEIN_C] = { | 140 | [MIXER_LINEIN_C] = { |
143 | .ctl = 1, | 141 | .ctl = 1, |
144 | .name = "Line-in Capture Volume", | 142 | .name = "Line Capture Volume", |
145 | }, | 143 | }, |
146 | [MIXER_MIC_P] = { | 144 | [MIXER_MIC_P] = { |
147 | .ctl = 1, | 145 | .ctl = 1, |
@@ -153,15 +151,15 @@ ct_kcontrol_init_table[NUM_CTALSA_MIXERS] = { | |||
153 | }, | 151 | }, |
154 | [MIXER_SPDIFI_P] = { | 152 | [MIXER_SPDIFI_P] = { |
155 | .ctl = 1, | 153 | .ctl = 1, |
156 | .name = "S/PDIF-in Playback Volume", | 154 | .name = "IEC958 Playback Volume", |
157 | }, | 155 | }, |
158 | [MIXER_SPDIFI_C] = { | 156 | [MIXER_SPDIFI_C] = { |
159 | .ctl = 1, | 157 | .ctl = 1, |
160 | .name = "S/PDIF-in Capture Volume", | 158 | .name = "IEC958 Capture Volume", |
161 | }, | 159 | }, |
162 | [MIXER_SPDIFO_P] = { | 160 | [MIXER_SPDIFO_P] = { |
163 | .ctl = 1, | 161 | .ctl = 1, |
164 | .name = "S/PDIF-out Playback Volume", | 162 | .name = "Digital Playback Volume", |
165 | }, | 163 | }, |
166 | [MIXER_WAVEF_P] = { | 164 | [MIXER_WAVEF_P] = { |
167 | .ctl = 1, | 165 | .ctl = 1, |
@@ -179,14 +177,13 @@ ct_kcontrol_init_table[NUM_CTALSA_MIXERS] = { | |||
179 | .ctl = 1, | 177 | .ctl = 1, |
180 | .name = "Surround Playback Volume", | 178 | .name = "Surround Playback Volume", |
181 | }, | 179 | }, |
182 | |||
183 | [MIXER_PCM_C_S] = { | 180 | [MIXER_PCM_C_S] = { |
184 | .ctl = 1, | 181 | .ctl = 1, |
185 | .name = "PCM Capture Switch", | 182 | .name = "PCM Capture Switch", |
186 | }, | 183 | }, |
187 | [MIXER_LINEIN_C_S] = { | 184 | [MIXER_LINEIN_C_S] = { |
188 | .ctl = 1, | 185 | .ctl = 1, |
189 | .name = "Line-in Capture Switch", | 186 | .name = "Line Capture Switch", |
190 | }, | 187 | }, |
191 | [MIXER_MIC_C_S] = { | 188 | [MIXER_MIC_C_S] = { |
192 | .ctl = 1, | 189 | .ctl = 1, |
@@ -194,19 +191,11 @@ ct_kcontrol_init_table[NUM_CTALSA_MIXERS] = { | |||
194 | }, | 191 | }, |
195 | [MIXER_SPDIFI_C_S] = { | 192 | [MIXER_SPDIFI_C_S] = { |
196 | .ctl = 1, | 193 | .ctl = 1, |
197 | .name = "S/PDIF-in Capture Switch", | 194 | .name = "IEC958 Capture Switch", |
198 | }, | ||
199 | [MIXER_LINEIN_P_S] = { | ||
200 | .ctl = 1, | ||
201 | .name = "Line-in Playback Switch", | ||
202 | }, | 195 | }, |
203 | [MIXER_SPDIFO_P_S] = { | 196 | [MIXER_SPDIFO_P_S] = { |
204 | .ctl = 1, | 197 | .ctl = 1, |
205 | .name = "S/PDIF-out Playback Switch", | 198 | .name = "Digital Playback Switch", |
206 | }, | ||
207 | [MIXER_SPDIFI_P_S] = { | ||
208 | .ctl = 1, | ||
209 | .name = "S/PDIF-in Playback Switch", | ||
210 | }, | 199 | }, |
211 | [MIXER_WAVEF_P_S] = { | 200 | [MIXER_WAVEF_P_S] = { |
212 | .ctl = 1, | 201 | .ctl = 1, |
@@ -236,6 +225,8 @@ ct_mixer_recording_select(struct ct_mixer *mixer, enum CT_AMIXER_CTL type); | |||
236 | static void | 225 | static void |
237 | ct_mixer_recording_unselect(struct ct_mixer *mixer, enum CT_AMIXER_CTL type); | 226 | ct_mixer_recording_unselect(struct ct_mixer *mixer, enum CT_AMIXER_CTL type); |
238 | 227 | ||
228 | /* FIXME: this static looks like it would fail if more than one card was */ | ||
229 | /* installed. */ | ||
239 | static struct snd_kcontrol *kctls[2] = {NULL}; | 230 | static struct snd_kcontrol *kctls[2] = {NULL}; |
240 | 231 | ||
241 | static enum CT_AMIXER_CTL get_amixer_index(enum CTALSA_MIXER_CTL alsa_index) | 232 | static enum CT_AMIXER_CTL get_amixer_index(enum CTALSA_MIXER_CTL alsa_index) |
@@ -420,6 +411,77 @@ static struct snd_kcontrol_new vol_ctl = { | |||
420 | .tlv = { .p = ct_vol_db_scale }, | 411 | .tlv = { .p = ct_vol_db_scale }, |
421 | }; | 412 | }; |
422 | 413 | ||
414 | static int output_switch_info(struct snd_kcontrol *kcontrol, | ||
415 | struct snd_ctl_elem_info *info) | ||
416 | { | ||
417 | static const char *const names[3] = { | ||
418 | "FP Headphones", "Headphones", "Speakers" | ||
419 | }; | ||
420 | |||
421 | return snd_ctl_enum_info(info, 1, 3, names); | ||
422 | } | ||
423 | |||
424 | static int output_switch_get(struct snd_kcontrol *kcontrol, | ||
425 | struct snd_ctl_elem_value *ucontrol) | ||
426 | { | ||
427 | struct ct_atc *atc = snd_kcontrol_chip(kcontrol); | ||
428 | ucontrol->value.enumerated.item[0] = atc->output_switch_get(atc); | ||
429 | return 0; | ||
430 | } | ||
431 | |||
432 | static int output_switch_put(struct snd_kcontrol *kcontrol, | ||
433 | struct snd_ctl_elem_value *ucontrol) | ||
434 | { | ||
435 | struct ct_atc *atc = snd_kcontrol_chip(kcontrol); | ||
436 | if (ucontrol->value.enumerated.item[0] > 2) | ||
437 | return -EINVAL; | ||
438 | return atc->output_switch_put(atc, ucontrol->value.enumerated.item[0]); | ||
439 | } | ||
440 | |||
441 | static struct snd_kcontrol_new output_ctl = { | ||
442 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
443 | .name = "Analog Output Playback Enum", | ||
444 | .info = output_switch_info, | ||
445 | .get = output_switch_get, | ||
446 | .put = output_switch_put, | ||
447 | }; | ||
448 | |||
449 | static int mic_source_switch_info(struct snd_kcontrol *kcontrol, | ||
450 | struct snd_ctl_elem_info *info) | ||
451 | { | ||
452 | static const char *const names[3] = { | ||
453 | "Mic", "FP Mic", "Aux" | ||
454 | }; | ||
455 | |||
456 | return snd_ctl_enum_info(info, 1, 3, names); | ||
457 | } | ||
458 | |||
459 | static int mic_source_switch_get(struct snd_kcontrol *kcontrol, | ||
460 | struct snd_ctl_elem_value *ucontrol) | ||
461 | { | ||
462 | struct ct_atc *atc = snd_kcontrol_chip(kcontrol); | ||
463 | ucontrol->value.enumerated.item[0] = atc->mic_source_switch_get(atc); | ||
464 | return 0; | ||
465 | } | ||
466 | |||
467 | static int mic_source_switch_put(struct snd_kcontrol *kcontrol, | ||
468 | struct snd_ctl_elem_value *ucontrol) | ||
469 | { | ||
470 | struct ct_atc *atc = snd_kcontrol_chip(kcontrol); | ||
471 | if (ucontrol->value.enumerated.item[0] > 2) | ||
472 | return -EINVAL; | ||
473 | return atc->mic_source_switch_put(atc, | ||
474 | ucontrol->value.enumerated.item[0]); | ||
475 | } | ||
476 | |||
477 | static struct snd_kcontrol_new mic_source_ctl = { | ||
478 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
479 | .name = "Mic Source Capture Enum", | ||
480 | .info = mic_source_switch_info, | ||
481 | .get = mic_source_switch_get, | ||
482 | .put = mic_source_switch_put, | ||
483 | }; | ||
484 | |||
423 | static void | 485 | static void |
424 | do_line_mic_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type) | 486 | do_line_mic_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type) |
425 | { | 487 | { |
@@ -465,6 +527,7 @@ do_digit_io_switch(struct ct_atc *atc, int state) | |||
465 | static void do_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type, int state) | 527 | static void do_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type, int state) |
466 | { | 528 | { |
467 | struct ct_mixer *mixer = atc->mixer; | 529 | struct ct_mixer *mixer = atc->mixer; |
530 | struct capabilities cap = atc->capabilities(atc); | ||
468 | 531 | ||
469 | /* Do changes in mixer. */ | 532 | /* Do changes in mixer. */ |
470 | if ((SWH_CAPTURE_START <= type) && (SWH_CAPTURE_END >= type)) { | 533 | if ((SWH_CAPTURE_START <= type) && (SWH_CAPTURE_END >= type)) { |
@@ -477,8 +540,17 @@ static void do_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type, int state) | |||
477 | } | 540 | } |
478 | } | 541 | } |
479 | /* Do changes out of mixer. */ | 542 | /* Do changes out of mixer. */ |
480 | if (state && (MIXER_LINEIN_C_S == type || MIXER_MIC_C_S == type)) | 543 | if (!cap.dedicated_mic && |
481 | do_line_mic_switch(atc, type); | 544 | (MIXER_LINEIN_C_S == type || MIXER_MIC_C_S == type)) { |
545 | if (state) | ||
546 | do_line_mic_switch(atc, type); | ||
547 | atc->line_in_unmute(atc, state); | ||
548 | } else if (cap.dedicated_mic && (MIXER_LINEIN_C_S == type)) | ||
549 | atc->line_in_unmute(atc, state); | ||
550 | else if (cap.dedicated_mic && (MIXER_MIC_C_S == type)) | ||
551 | atc->mic_unmute(atc, state); | ||
552 | else if (MIXER_SPDIFI_C_S == type) | ||
553 | atc->spdif_in_unmute(atc, state); | ||
482 | else if (MIXER_WAVEF_P_S == type) | 554 | else if (MIXER_WAVEF_P_S == type) |
483 | atc->line_front_unmute(atc, state); | 555 | atc->line_front_unmute(atc, state); |
484 | else if (MIXER_WAVES_P_S == type) | 556 | else if (MIXER_WAVES_P_S == type) |
@@ -487,12 +559,8 @@ static void do_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type, int state) | |||
487 | atc->line_clfe_unmute(atc, state); | 559 | atc->line_clfe_unmute(atc, state); |
488 | else if (MIXER_WAVER_P_S == type) | 560 | else if (MIXER_WAVER_P_S == type) |
489 | atc->line_rear_unmute(atc, state); | 561 | atc->line_rear_unmute(atc, state); |
490 | else if (MIXER_LINEIN_P_S == type) | ||
491 | atc->line_in_unmute(atc, state); | ||
492 | else if (MIXER_SPDIFO_P_S == type) | 562 | else if (MIXER_SPDIFO_P_S == type) |
493 | atc->spdif_out_unmute(atc, state); | 563 | atc->spdif_out_unmute(atc, state); |
494 | else if (MIXER_SPDIFI_P_S == type) | ||
495 | atc->spdif_in_unmute(atc, state); | ||
496 | else if (MIXER_DIGITAL_IO_S == type) | 564 | else if (MIXER_DIGITAL_IO_S == type) |
497 | do_digit_io_switch(atc, state); | 565 | do_digit_io_switch(atc, state); |
498 | 566 | ||
@@ -671,6 +739,7 @@ static int ct_mixer_kcontrols_create(struct ct_mixer *mixer) | |||
671 | { | 739 | { |
672 | enum CTALSA_MIXER_CTL type; | 740 | enum CTALSA_MIXER_CTL type; |
673 | struct ct_atc *atc = mixer->atc; | 741 | struct ct_atc *atc = mixer->atc; |
742 | struct capabilities cap = atc->capabilities(atc); | ||
674 | int err; | 743 | int err; |
675 | 744 | ||
676 | /* Create snd kcontrol instances on demand */ | 745 | /* Create snd kcontrol instances on demand */ |
@@ -684,8 +753,8 @@ static int ct_mixer_kcontrols_create(struct ct_mixer *mixer) | |||
684 | } | 753 | } |
685 | } | 754 | } |
686 | 755 | ||
687 | ct_kcontrol_init_table[MIXER_DIGITAL_IO_S].ctl = | 756 | ct_kcontrol_init_table[MIXER_DIGITAL_IO_S].ctl = cap.digit_io_switch; |
688 | atc->have_digit_io_switch(atc); | 757 | |
689 | for (type = SWH_MIXER_START; type <= SWH_MIXER_END; type++) { | 758 | for (type = SWH_MIXER_START; type <= SWH_MIXER_END; type++) { |
690 | if (ct_kcontrol_init_table[type].ctl) { | 759 | if (ct_kcontrol_init_table[type].ctl) { |
691 | swh_ctl.name = ct_kcontrol_init_table[type].name; | 760 | swh_ctl.name = ct_kcontrol_init_table[type].name; |
@@ -708,6 +777,17 @@ static int ct_mixer_kcontrols_create(struct ct_mixer *mixer) | |||
708 | if (err) | 777 | if (err) |
709 | return err; | 778 | return err; |
710 | 779 | ||
780 | if (cap.output_switch) { | ||
781 | err = ct_mixer_kcontrol_new(mixer, &output_ctl); | ||
782 | if (err) | ||
783 | return err; | ||
784 | } | ||
785 | |||
786 | if (cap.mic_source_switch) { | ||
787 | err = ct_mixer_kcontrol_new(mixer, &mic_source_ctl); | ||
788 | if (err) | ||
789 | return err; | ||
790 | } | ||
711 | atc->line_front_unmute(atc, 1); | 791 | atc->line_front_unmute(atc, 1); |
712 | set_switch_state(mixer, MIXER_WAVEF_P_S, 1); | 792 | set_switch_state(mixer, MIXER_WAVEF_P_S, 1); |
713 | atc->line_surround_unmute(atc, 0); | 793 | atc->line_surround_unmute(atc, 0); |
@@ -719,13 +799,12 @@ static int ct_mixer_kcontrols_create(struct ct_mixer *mixer) | |||
719 | atc->spdif_out_unmute(atc, 0); | 799 | atc->spdif_out_unmute(atc, 0); |
720 | set_switch_state(mixer, MIXER_SPDIFO_P_S, 0); | 800 | set_switch_state(mixer, MIXER_SPDIFO_P_S, 0); |
721 | atc->line_in_unmute(atc, 0); | 801 | atc->line_in_unmute(atc, 0); |
722 | set_switch_state(mixer, MIXER_LINEIN_P_S, 0); | 802 | if (cap.dedicated_mic) |
803 | atc->mic_unmute(atc, 0); | ||
723 | atc->spdif_in_unmute(atc, 0); | 804 | atc->spdif_in_unmute(atc, 0); |
724 | set_switch_state(mixer, MIXER_SPDIFI_P_S, 0); | 805 | set_switch_state(mixer, MIXER_PCM_C_S, 0); |
725 | 806 | set_switch_state(mixer, MIXER_LINEIN_C_S, 0); | |
726 | set_switch_state(mixer, MIXER_PCM_C_S, 1); | 807 | set_switch_state(mixer, MIXER_SPDIFI_C_S, 0); |
727 | set_switch_state(mixer, MIXER_LINEIN_C_S, 1); | ||
728 | set_switch_state(mixer, MIXER_SPDIFI_C_S, 1); | ||
729 | 808 | ||
730 | return 0; | 809 | return 0; |
731 | } | 810 | } |
diff --git a/sound/pci/ctxfi/xfi.c b/sound/pci/ctxfi/xfi.c index f42e7e1a107..b259aa03a3a 100644 --- a/sound/pci/ctxfi/xfi.c +++ b/sound/pci/ctxfi/xfi.c | |||
@@ -80,11 +80,11 @@ ct_card_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) | |||
80 | "are 48000 and 44100, Value 48000 is assumed.\n"); | 80 | "are 48000 and 44100, Value 48000 is assumed.\n"); |
81 | reference_rate = 48000; | 81 | reference_rate = 48000; |
82 | } | 82 | } |
83 | if ((multiple != 1) && (multiple != 2)) { | 83 | if ((multiple != 1) && (multiple != 2) && (multiple != 4)) { |
84 | printk(KERN_ERR "ctxfi: Invalid multiple value %u!!!\n", | 84 | printk(KERN_ERR "ctxfi: Invalid multiple value %u!!!\n", |
85 | multiple); | 85 | multiple); |
86 | printk(KERN_ERR "ctxfi: The valid values for multiple are " | 86 | printk(KERN_ERR "ctxfi: The valid values for multiple are " |
87 | "1 and 2, Value 2 is assumed.\n"); | 87 | "1, 2 and 4, Value 2 is assumed.\n"); |
88 | multiple = 2; | 88 | multiple = 2; |
89 | } | 89 | } |
90 | err = ct_atc_create(card, pci, reference_rate, multiple, | 90 | err = ct_atc_create(card, pci, reference_rate, multiple, |
@@ -143,7 +143,7 @@ static int ct_card_resume(struct pci_dev *pci) | |||
143 | #endif | 143 | #endif |
144 | 144 | ||
145 | static struct pci_driver ct_driver = { | 145 | static struct pci_driver ct_driver = { |
146 | .name = "SB-XFi", | 146 | .name = KBUILD_MODNAME, |
147 | .id_table = ct_pci_dev_ids, | 147 | .id_table = ct_pci_dev_ids, |
148 | .probe = ct_card_probe, | 148 | .probe = ct_card_probe, |
149 | .remove = __devexit_p(ct_card_remove), | 149 | .remove = __devexit_p(ct_card_remove), |