diff options
| -rw-r--r-- | sound/pci/ctxfi/ctatc.c | 181 | ||||
| -rw-r--r-- | sound/pci/ctxfi/ctatc.h | 7 | ||||
| -rw-r--r-- | sound/pci/ctxfi/cthardware.h | 4 | ||||
| -rw-r--r-- | sound/pci/ctxfi/cthw20k1.c | 83 | ||||
| -rw-r--r-- | sound/pci/ctxfi/cthw20k2.c | 65 | ||||
| -rw-r--r-- | sound/pci/ctxfi/ctmixer.c | 92 | ||||
| -rw-r--r-- | sound/pci/ctxfi/ctmixer.h | 3 | ||||
| -rw-r--r-- | sound/pci/ctxfi/ctpcm.c | 4 | ||||
| -rw-r--r-- | sound/pci/ctxfi/xfi.c | 22 |
9 files changed, 354 insertions, 107 deletions
diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c index 32e3c26e969e..a49c76647307 100644 --- a/sound/pci/ctxfi/ctatc.c +++ b/sound/pci/ctxfi/ctatc.c | |||
| @@ -261,13 +261,8 @@ static int atc_pcm_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm) | |||
| 261 | int device = apcm->substream->pcm->device; | 261 | int device = apcm->substream->pcm->device; |
| 262 | unsigned int pitch; | 262 | unsigned int pitch; |
| 263 | 263 | ||
| 264 | if (NULL != apcm->src) { | ||
| 265 | /* Prepared pcm playback */ | ||
| 266 | return 0; | ||
| 267 | } | ||
| 268 | |||
| 269 | /* first release old resources */ | 264 | /* first release old resources */ |
| 270 | atc->pcm_release_resources(atc, apcm); | 265 | atc_pcm_release_resources(atc, apcm); |
| 271 | 266 | ||
| 272 | /* Get SRC resource */ | 267 | /* Get SRC resource */ |
| 273 | desc.multi = apcm->substream->runtime->channels; | 268 | desc.multi = apcm->substream->runtime->channels; |
| @@ -661,10 +656,7 @@ static int atc_pcm_capture_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm) | |||
| 661 | unsigned int pitch; | 656 | unsigned int pitch; |
| 662 | int mix_base = 0, imp_base = 0; | 657 | int mix_base = 0, imp_base = 0; |
| 663 | 658 | ||
| 664 | if (NULL != apcm->src) { | 659 | atc_pcm_release_resources(atc, apcm); |
| 665 | /* Prepared pcm capture */ | ||
| 666 | return 0; | ||
| 667 | } | ||
| 668 | 660 | ||
| 669 | /* Get needed resources. */ | 661 | /* Get needed resources. */ |
| 670 | err = atc_pcm_capture_get_resources(atc, apcm); | 662 | err = atc_pcm_capture_get_resources(atc, apcm); |
| @@ -867,7 +859,7 @@ spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm) | |||
| 867 | struct dao *dao = container_of(atc->daios[SPDIFOO], struct dao, daio); | 859 | struct dao *dao = container_of(atc->daios[SPDIFOO], struct dao, daio); |
| 868 | unsigned int rate = apcm->substream->runtime->rate; | 860 | unsigned int rate = apcm->substream->runtime->rate; |
| 869 | unsigned int status; | 861 | unsigned int status; |
| 870 | int err; | 862 | int err = 0; |
| 871 | unsigned char iec958_con_fs; | 863 | unsigned char iec958_con_fs; |
| 872 | 864 | ||
| 873 | switch (rate) { | 865 | switch (rate) { |
| @@ -908,8 +900,7 @@ spdif_passthru_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm) | |||
| 908 | int err; | 900 | int err; |
| 909 | int i; | 901 | int i; |
| 910 | 902 | ||
| 911 | if (NULL != apcm->src) | 903 | atc_pcm_release_resources(atc, apcm); |
| 912 | return 0; | ||
| 913 | 904 | ||
| 914 | /* Configure SPDIFOO and PLL to passthrough mode; | 905 | /* Configure SPDIFOO and PLL to passthrough mode; |
| 915 | * determine pll_rate. */ | 906 | * determine pll_rate. */ |
| @@ -1116,32 +1107,20 @@ static int atc_spdif_out_passthru(struct ct_atc *atc, unsigned char state) | |||
| 1116 | return err; | 1107 | return err; |
| 1117 | } | 1108 | } |
| 1118 | 1109 | ||
| 1119 | static int ct_atc_destroy(struct ct_atc *atc) | 1110 | static int atc_release_resources(struct ct_atc *atc) |
| 1120 | { | 1111 | { |
| 1121 | struct daio_mgr *daio_mgr; | 1112 | int i; |
| 1122 | struct dao *dao; | 1113 | struct daio_mgr *daio_mgr = NULL; |
| 1123 | struct dai *dai; | 1114 | struct dao *dao = NULL; |
| 1124 | struct daio *daio; | 1115 | struct dai *dai = NULL; |
| 1125 | struct sum_mgr *sum_mgr; | 1116 | struct daio *daio = NULL; |
| 1126 | struct src_mgr *src_mgr; | 1117 | struct sum_mgr *sum_mgr = NULL; |
| 1127 | struct srcimp_mgr *srcimp_mgr; | 1118 | struct src_mgr *src_mgr = NULL; |
| 1128 | struct srcimp *srcimp; | 1119 | struct srcimp_mgr *srcimp_mgr = NULL; |
| 1129 | struct ct_mixer *mixer; | 1120 | struct srcimp *srcimp = NULL; |
| 1130 | int i = 0; | 1121 | struct ct_mixer *mixer = NULL; |
| 1131 | 1122 | ||
| 1132 | if (NULL == atc) | 1123 | /* disconnect internal mixer objects */ |
| 1133 | return 0; | ||
| 1134 | |||
| 1135 | if (atc->timer) { | ||
| 1136 | ct_timer_free(atc->timer); | ||
| 1137 | atc->timer = NULL; | ||
| 1138 | } | ||
| 1139 | |||
| 1140 | /* Stop hardware and disable all interrupts */ | ||
| 1141 | if (NULL != atc->hw) | ||
| 1142 | ((struct hw *)atc->hw)->card_stop(atc->hw); | ||
| 1143 | |||
| 1144 | /* Destroy internal mixer objects */ | ||
| 1145 | if (NULL != atc->mixer) { | 1124 | if (NULL != atc->mixer) { |
| 1146 | mixer = atc->mixer; | 1125 | mixer = atc->mixer; |
| 1147 | mixer->set_input_left(mixer, MIX_LINE_IN, NULL); | 1126 | mixer->set_input_left(mixer, MIX_LINE_IN, NULL); |
| @@ -1150,7 +1129,6 @@ static int ct_atc_destroy(struct ct_atc *atc) | |||
| 1150 | mixer->set_input_right(mixer, MIX_MIC_IN, NULL); | 1129 | mixer->set_input_right(mixer, MIX_MIC_IN, NULL); |
| 1151 | mixer->set_input_left(mixer, MIX_SPDIF_IN, NULL); | 1130 | mixer->set_input_left(mixer, MIX_SPDIF_IN, NULL); |
| 1152 | mixer->set_input_right(mixer, MIX_SPDIF_IN, NULL); | 1131 | mixer->set_input_right(mixer, MIX_SPDIF_IN, NULL); |
| 1153 | ct_mixer_destroy(atc->mixer); | ||
| 1154 | } | 1132 | } |
| 1155 | 1133 | ||
| 1156 | if (NULL != atc->daios) { | 1134 | if (NULL != atc->daios) { |
| @@ -1168,6 +1146,7 @@ static int ct_atc_destroy(struct ct_atc *atc) | |||
| 1168 | daio_mgr->put_daio(daio_mgr, daio); | 1146 | daio_mgr->put_daio(daio_mgr, daio); |
| 1169 | } | 1147 | } |
| 1170 | kfree(atc->daios); | 1148 | kfree(atc->daios); |
| 1149 | atc->daios = NULL; | ||
| 1171 | } | 1150 | } |
| 1172 | 1151 | ||
| 1173 | if (NULL != atc->pcm) { | 1152 | if (NULL != atc->pcm) { |
| @@ -1176,6 +1155,7 @@ static int ct_atc_destroy(struct ct_atc *atc) | |||
| 1176 | sum_mgr->put_sum(sum_mgr, atc->pcm[i]); | 1155 | sum_mgr->put_sum(sum_mgr, atc->pcm[i]); |
| 1177 | 1156 | ||
| 1178 | kfree(atc->pcm); | 1157 | kfree(atc->pcm); |
| 1158 | atc->pcm = NULL; | ||
| 1179 | } | 1159 | } |
| 1180 | 1160 | ||
| 1181 | if (NULL != atc->srcs) { | 1161 | if (NULL != atc->srcs) { |
| @@ -1184,6 +1164,7 @@ static int ct_atc_destroy(struct ct_atc *atc) | |||
| 1184 | src_mgr->put_src(src_mgr, atc->srcs[i]); | 1164 | src_mgr->put_src(src_mgr, atc->srcs[i]); |
| 1185 | 1165 | ||
| 1186 | kfree(atc->srcs); | 1166 | kfree(atc->srcs); |
| 1167 | atc->srcs = NULL; | ||
| 1187 | } | 1168 | } |
| 1188 | 1169 | ||
| 1189 | if (NULL != atc->srcimps) { | 1170 | if (NULL != atc->srcimps) { |
| @@ -1194,8 +1175,30 @@ static int ct_atc_destroy(struct ct_atc *atc) | |||
| 1194 | srcimp_mgr->put_srcimp(srcimp_mgr, atc->srcimps[i]); | 1175 | srcimp_mgr->put_srcimp(srcimp_mgr, atc->srcimps[i]); |
| 1195 | } | 1176 | } |
| 1196 | kfree(atc->srcimps); | 1177 | kfree(atc->srcimps); |
| 1178 | atc->srcimps = NULL; | ||
| 1179 | } | ||
| 1180 | |||
| 1181 | return 0; | ||
| 1182 | } | ||
| 1183 | |||
| 1184 | static int ct_atc_destroy(struct ct_atc *atc) | ||
| 1185 | { | ||
| 1186 | int i = 0; | ||
| 1187 | |||
| 1188 | if (NULL == atc) | ||
| 1189 | return 0; | ||
| 1190 | |||
| 1191 | if (atc->timer) { | ||
| 1192 | ct_timer_free(atc->timer); | ||
| 1193 | atc->timer = NULL; | ||
| 1197 | } | 1194 | } |
| 1198 | 1195 | ||
| 1196 | atc_release_resources(atc); | ||
| 1197 | |||
| 1198 | /* Destroy internal mixer objects */ | ||
| 1199 | if (NULL != atc->mixer) | ||
| 1200 | ct_mixer_destroy(atc->mixer); | ||
| 1201 | |||
| 1199 | for (i = 0; i < NUM_RSCTYP; i++) { | 1202 | for (i = 0; i < NUM_RSCTYP; i++) { |
| 1200 | if ((NULL != rsc_mgr_funcs[i].destroy) && | 1203 | if ((NULL != rsc_mgr_funcs[i].destroy) && |
| 1201 | (NULL != atc->rsc_mgrs[i])) | 1204 | (NULL != atc->rsc_mgrs[i])) |
| @@ -1323,7 +1326,7 @@ static int __devinit atc_create_hw_devs(struct ct_atc *atc) | |||
| 1323 | return 0; | 1326 | return 0; |
| 1324 | } | 1327 | } |
| 1325 | 1328 | ||
| 1326 | static int __devinit atc_get_resources(struct ct_atc *atc) | 1329 | static int atc_get_resources(struct ct_atc *atc) |
| 1327 | { | 1330 | { |
| 1328 | struct daio_desc da_desc = {0}; | 1331 | struct daio_desc da_desc = {0}; |
| 1329 | struct daio_mgr *daio_mgr; | 1332 | struct daio_mgr *daio_mgr; |
| @@ -1420,16 +1423,10 @@ static int __devinit atc_get_resources(struct ct_atc *atc) | |||
| 1420 | atc->n_pcm++; | 1423 | atc->n_pcm++; |
| 1421 | } | 1424 | } |
| 1422 | 1425 | ||
| 1423 | err = ct_mixer_create(atc, (struct ct_mixer **)&atc->mixer); | ||
| 1424 | if (err) { | ||
| 1425 | printk(KERN_ERR "ctxfi: Failed to create mixer obj!!!\n"); | ||
| 1426 | return err; | ||
| 1427 | } | ||
| 1428 | |||
| 1429 | return 0; | 1426 | return 0; |
| 1430 | } | 1427 | } |
| 1431 | 1428 | ||
| 1432 | static void __devinit | 1429 | static void |
| 1433 | atc_connect_dai(struct src_mgr *src_mgr, struct dai *dai, | 1430 | atc_connect_dai(struct src_mgr *src_mgr, struct dai *dai, |
| 1434 | struct src **srcs, struct srcimp **srcimps) | 1431 | struct src **srcs, struct srcimp **srcimps) |
| 1435 | { | 1432 | { |
| @@ -1468,7 +1465,7 @@ atc_connect_dai(struct src_mgr *src_mgr, struct dai *dai, | |||
| 1468 | src_mgr->commit_write(src_mgr); /* Synchronously enable SRCs */ | 1465 | src_mgr->commit_write(src_mgr); /* Synchronously enable SRCs */ |
| 1469 | } | 1466 | } |
| 1470 | 1467 | ||
| 1471 | static void __devinit atc_connect_resources(struct ct_atc *atc) | 1468 | static void atc_connect_resources(struct ct_atc *atc) |
| 1472 | { | 1469 | { |
| 1473 | struct dai *dai; | 1470 | struct dai *dai; |
| 1474 | struct dao *dao; | 1471 | struct dao *dao; |
| @@ -1514,6 +1511,84 @@ static void __devinit atc_connect_resources(struct ct_atc *atc) | |||
| 1514 | } | 1511 | } |
| 1515 | } | 1512 | } |
| 1516 | 1513 | ||
| 1514 | #ifdef CONFIG_PM | ||
| 1515 | static int atc_suspend(struct ct_atc *atc, pm_message_t state) | ||
| 1516 | { | ||
| 1517 | int i; | ||
| 1518 | struct hw *hw = atc->hw; | ||
| 1519 | |||
| 1520 | snd_power_change_state(atc->card, SNDRV_CTL_POWER_D3hot); | ||
| 1521 | |||
| 1522 | for (i = FRONT; i < NUM_PCMS; i++) { | ||
| 1523 | if (!atc->pcms[i]) | ||
| 1524 | continue; | ||
| 1525 | |||
| 1526 | snd_pcm_suspend_all(atc->pcms[i]); | ||
| 1527 | } | ||
| 1528 | |||
| 1529 | atc_release_resources(atc); | ||
| 1530 | |||
| 1531 | hw->suspend(hw, state); | ||
| 1532 | |||
| 1533 | return 0; | ||
| 1534 | } | ||
| 1535 | |||
| 1536 | static int atc_hw_resume(struct ct_atc *atc) | ||
| 1537 | { | ||
| 1538 | struct hw *hw = atc->hw; | ||
| 1539 | struct card_conf info = {0}; | ||
| 1540 | |||
| 1541 | /* Re-initialize card hardware. */ | ||
| 1542 | info.rsr = atc->rsr; | ||
| 1543 | info.msr = atc->msr; | ||
| 1544 | info.vm_pgt_phys = atc_get_ptp_phys(atc, 0); | ||
| 1545 | return hw->resume(hw, &info); | ||
| 1546 | } | ||
| 1547 | |||
| 1548 | static int atc_resources_resume(struct ct_atc *atc) | ||
| 1549 | { | ||
| 1550 | struct ct_mixer *mixer; | ||
| 1551 | int err = 0; | ||
| 1552 | |||
| 1553 | /* Get resources */ | ||
| 1554 | err = atc_get_resources(atc); | ||
| 1555 | if (err < 0) { | ||
| 1556 | atc_release_resources(atc); | ||
| 1557 | return err; | ||
| 1558 | } | ||
| 1559 | |||
| 1560 | /* Build topology */ | ||
| 1561 | atc_connect_resources(atc); | ||
| 1562 | |||
| 1563 | mixer = atc->mixer; | ||
| 1564 | mixer->resume(mixer); | ||
| 1565 | |||
| 1566 | return 0; | ||
| 1567 | } | ||
| 1568 | |||
| 1569 | static int atc_resume(struct ct_atc *atc) | ||
| 1570 | { | ||
| 1571 | int err = 0; | ||
| 1572 | |||
| 1573 | /* Do hardware resume. */ | ||
| 1574 | err = atc_hw_resume(atc); | ||
| 1575 | if (err < 0) { | ||
| 1576 | printk(KERN_ERR "ctxfi: pci_enable_device failed, " | ||
| 1577 | "disabling device\n"); | ||
| 1578 | snd_card_disconnect(atc->card); | ||
| 1579 | return err; | ||
| 1580 | } | ||
| 1581 | |||
| 1582 | err = atc_resources_resume(atc); | ||
| 1583 | if (err < 0) | ||
| 1584 | return err; | ||
| 1585 | |||
| 1586 | snd_power_change_state(atc->card, SNDRV_CTL_POWER_D0); | ||
| 1587 | |||
| 1588 | return 0; | ||
| 1589 | } | ||
| 1590 | #endif | ||
| 1591 | |||
| 1517 | static struct ct_atc atc_preset __devinitdata = { | 1592 | static struct ct_atc atc_preset __devinitdata = { |
| 1518 | .map_audio_buffer = ct_map_audio_buffer, | 1593 | .map_audio_buffer = ct_map_audio_buffer, |
| 1519 | .unmap_audio_buffer = ct_unmap_audio_buffer, | 1594 | .unmap_audio_buffer = ct_unmap_audio_buffer, |
| @@ -1542,6 +1617,10 @@ static struct ct_atc atc_preset __devinitdata = { | |||
| 1542 | .spdif_out_set_status = atc_spdif_out_set_status, | 1617 | .spdif_out_set_status = atc_spdif_out_set_status, |
| 1543 | .spdif_out_passthru = atc_spdif_out_passthru, | 1618 | .spdif_out_passthru = atc_spdif_out_passthru, |
| 1544 | .have_digit_io_switch = atc_have_digit_io_switch, | 1619 | .have_digit_io_switch = atc_have_digit_io_switch, |
| 1620 | #ifdef CONFIG_PM | ||
| 1621 | .suspend = atc_suspend, | ||
| 1622 | .resume = atc_resume, | ||
| 1623 | #endif | ||
| 1545 | }; | 1624 | }; |
| 1546 | 1625 | ||
| 1547 | /** | 1626 | /** |
| @@ -1600,6 +1679,12 @@ int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci, | |||
| 1600 | if (err < 0) | 1679 | if (err < 0) |
| 1601 | goto error1; | 1680 | goto error1; |
| 1602 | 1681 | ||
| 1682 | err = ct_mixer_create(atc, (struct ct_mixer **)&atc->mixer); | ||
| 1683 | if (err) { | ||
| 1684 | printk(KERN_ERR "ctxfi: Failed to create mixer obj!!!\n"); | ||
| 1685 | goto error1; | ||
| 1686 | } | ||
| 1687 | |||
| 1603 | /* Get resources */ | 1688 | /* Get resources */ |
| 1604 | err = atc_get_resources(atc); | 1689 | err = atc_get_resources(atc); |
| 1605 | if (err < 0) | 1690 | if (err < 0) |
diff --git a/sound/pci/ctxfi/ctatc.h b/sound/pci/ctxfi/ctatc.h index 9fe620ea5f3f..9fd8a5708943 100644 --- a/sound/pci/ctxfi/ctatc.h +++ b/sound/pci/ctxfi/ctatc.h | |||
| @@ -136,6 +136,13 @@ struct ct_atc { | |||
| 136 | unsigned char n_pcm; | 136 | unsigned char n_pcm; |
| 137 | 137 | ||
| 138 | struct ct_timer *timer; | 138 | struct ct_timer *timer; |
| 139 | |||
| 140 | #ifdef CONFIG_PM | ||
| 141 | int (*suspend)(struct ct_atc *atc, pm_message_t state); | ||
| 142 | int (*resume)(struct ct_atc *atc); | ||
| 143 | #define NUM_PCMS (NUM_CTALSADEVS - 1) | ||
| 144 | struct snd_pcm *pcms[NUM_PCMS]; | ||
| 145 | #endif | ||
| 139 | }; | 146 | }; |
| 140 | 147 | ||
| 141 | 148 | ||
diff --git a/sound/pci/ctxfi/cthardware.h b/sound/pci/ctxfi/cthardware.h index a4c2cad80f3a..af55405f5dec 100644 --- a/sound/pci/ctxfi/cthardware.h +++ b/sound/pci/ctxfi/cthardware.h | |||
| @@ -64,6 +64,10 @@ struct hw { | |||
| 64 | int (*card_init)(struct hw *hw, struct card_conf *info); | 64 | int (*card_init)(struct hw *hw, struct card_conf *info); |
| 65 | int (*card_stop)(struct hw *hw); | 65 | int (*card_stop)(struct hw *hw); |
| 66 | int (*pll_init)(struct hw *hw, unsigned int rsr); | 66 | int (*pll_init)(struct hw *hw, unsigned int rsr); |
| 67 | #ifdef CONFIG_PM | ||
| 68 | int (*suspend)(struct hw *hw, pm_message_t state); | ||
| 69 | int (*resume)(struct hw *hw, struct card_conf *info); | ||
| 70 | #endif | ||
| 67 | int (*is_adc_source_selected)(struct hw *hw, enum ADCSRC source); | 71 | int (*is_adc_source_selected)(struct hw *hw, enum ADCSRC source); |
| 68 | int (*select_adc_source)(struct hw *hw, enum ADCSRC source); | 72 | int (*select_adc_source)(struct hw *hw, enum ADCSRC source); |
| 69 | int (*have_digit_io_switch)(struct hw *hw); | 73 | int (*have_digit_io_switch)(struct hw *hw); |
diff --git a/sound/pci/ctxfi/cthw20k1.c b/sound/pci/ctxfi/cthw20k1.c index cb69d9ddfbe3..ad3e1d144464 100644 --- a/sound/pci/ctxfi/cthw20k1.c +++ b/sound/pci/ctxfi/cthw20k1.c | |||
| @@ -1911,9 +1911,17 @@ static int hw_card_start(struct hw *hw) | |||
| 1911 | goto error1; | 1911 | goto error1; |
| 1912 | } | 1912 | } |
| 1913 | 1913 | ||
| 1914 | err = pci_request_regions(pci, "XFi"); | 1914 | if (!hw->io_base) { |
| 1915 | if (err < 0) | 1915 | err = pci_request_regions(pci, "XFi"); |
| 1916 | goto error1; | 1916 | if (err < 0) |
| 1917 | goto error1; | ||
| 1918 | |||
| 1919 | if (hw->model == CTUAA) | ||
| 1920 | hw->io_base = pci_resource_start(pci, 5); | ||
| 1921 | else | ||
| 1922 | hw->io_base = pci_resource_start(pci, 0); | ||
| 1923 | |||
| 1924 | } | ||
| 1917 | 1925 | ||
| 1918 | /* Switch to X-Fi mode from UAA mode if neeeded */ | 1926 | /* Switch to X-Fi mode from UAA mode if neeeded */ |
| 1919 | if (hw->model == CTUAA) { | 1927 | if (hw->model == CTUAA) { |
| @@ -1921,18 +1929,17 @@ static int hw_card_start(struct hw *hw) | |||
| 1921 | if (err) | 1929 | if (err) |
| 1922 | goto error2; | 1930 | goto error2; |
| 1923 | 1931 | ||
| 1924 | hw->io_base = pci_resource_start(pci, 5); | ||
| 1925 | } else { | ||
| 1926 | hw->io_base = pci_resource_start(pci, 0); | ||
| 1927 | } | 1932 | } |
| 1928 | 1933 | ||
| 1929 | err = request_irq(pci->irq, ct_20k1_interrupt, IRQF_SHARED, | 1934 | if (hw->irq < 0) { |
| 1930 | "ctxfi", hw); | 1935 | err = request_irq(pci->irq, ct_20k1_interrupt, IRQF_SHARED, |
| 1931 | if (err < 0) { | 1936 | "ctxfi", hw); |
| 1932 | printk(KERN_ERR "XFi: Cannot get irq %d\n", pci->irq); | 1937 | if (err < 0) { |
| 1933 | goto error2; | 1938 | printk(KERN_ERR "XFi: Cannot get irq %d\n", pci->irq); |
| 1939 | goto error2; | ||
| 1940 | } | ||
| 1941 | hw->irq = pci->irq; | ||
| 1934 | } | 1942 | } |
| 1935 | hw->irq = pci->irq; | ||
| 1936 | 1943 | ||
| 1937 | pci_set_master(pci); | 1944 | pci_set_master(pci); |
| 1938 | 1945 | ||
| @@ -1948,6 +1955,15 @@ error1: | |||
| 1948 | 1955 | ||
| 1949 | static int hw_card_stop(struct hw *hw) | 1956 | static int hw_card_stop(struct hw *hw) |
| 1950 | { | 1957 | { |
| 1958 | unsigned int data; | ||
| 1959 | |||
| 1960 | /* disable transport bus master and queueing of request */ | ||
| 1961 | hw_write_20kx(hw, TRNCTL, 0x00); | ||
| 1962 | |||
| 1963 | /* disable pll */ | ||
| 1964 | data = hw_read_20kx(hw, PLLCTL); | ||
| 1965 | hw_write_20kx(hw, PLLCTL, (data & (~(0x0F<<12)))); | ||
| 1966 | |||
| 1951 | /* TODO: Disable interrupt and so on... */ | 1967 | /* TODO: Disable interrupt and so on... */ |
| 1952 | if (hw->irq >= 0) | 1968 | if (hw->irq >= 0) |
| 1953 | synchronize_irq(hw->irq); | 1969 | synchronize_irq(hw->irq); |
| @@ -1987,11 +2003,9 @@ static int hw_card_init(struct hw *hw, struct card_conf *info) | |||
| 1987 | struct trn_conf trn_info = {0}; | 2003 | struct trn_conf trn_info = {0}; |
| 1988 | 2004 | ||
| 1989 | /* Get PCI io port base address and do Hendrix switch if needed. */ | 2005 | /* Get PCI io port base address and do Hendrix switch if needed. */ |
| 1990 | if (!hw->io_base) { | 2006 | err = hw_card_start(hw); |
| 1991 | err = hw_card_start(hw); | 2007 | if (err) |
| 1992 | if (err) | 2008 | return err; |
| 1993 | return err; | ||
| 1994 | } | ||
| 1995 | 2009 | ||
| 1996 | /* PLL init */ | 2010 | /* PLL init */ |
| 1997 | err = hw_pll_init(hw, info->rsr); | 2011 | err = hw_pll_init(hw, info->rsr); |
| @@ -2064,6 +2078,37 @@ static int hw_card_init(struct hw *hw, struct card_conf *info) | |||
| 2064 | return 0; | 2078 | return 0; |
| 2065 | } | 2079 | } |
| 2066 | 2080 | ||
| 2081 | #ifdef CONFIG_PM | ||
| 2082 | static int hw_suspend(struct hw *hw, pm_message_t state) | ||
| 2083 | { | ||
| 2084 | struct pci_dev *pci = hw->pci; | ||
| 2085 | |||
| 2086 | hw_card_stop(hw); | ||
| 2087 | |||
| 2088 | if (hw->model == CTUAA) { | ||
| 2089 | /* Switch to UAA config space. */ | ||
| 2090 | pci_write_config_dword(pci, UAA_CFG_SPACE_FLAG, 0x0); | ||
| 2091 | } | ||
| 2092 | |||
| 2093 | pci_disable_device(pci); | ||
| 2094 | pci_save_state(pci); | ||
| 2095 | pci_set_power_state(pci, pci_choose_state(pci, state)); | ||
| 2096 | |||
| 2097 | return 0; | ||
| 2098 | } | ||
| 2099 | |||
| 2100 | static int hw_resume(struct hw *hw, struct card_conf *info) | ||
| 2101 | { | ||
| 2102 | struct pci_dev *pci = hw->pci; | ||
| 2103 | |||
| 2104 | pci_set_power_state(pci, PCI_D0); | ||
| 2105 | pci_restore_state(pci); | ||
| 2106 | |||
| 2107 | /* Re-initialize card hardware. */ | ||
| 2108 | return hw_card_init(hw, info); | ||
| 2109 | } | ||
| 2110 | #endif | ||
| 2111 | |||
| 2067 | static u32 hw_read_20kx(struct hw *hw, u32 reg) | 2112 | static u32 hw_read_20kx(struct hw *hw, u32 reg) |
| 2068 | { | 2113 | { |
| 2069 | u32 value; | 2114 | u32 value; |
| @@ -2128,6 +2173,10 @@ static struct hw ct20k1_preset __devinitdata = { | |||
| 2128 | .is_adc_source_selected = hw_is_adc_input_selected, | 2173 | .is_adc_source_selected = hw_is_adc_input_selected, |
| 2129 | .select_adc_source = hw_adc_input_select, | 2174 | .select_adc_source = hw_adc_input_select, |
| 2130 | .have_digit_io_switch = hw_have_digit_io_switch, | 2175 | .have_digit_io_switch = hw_have_digit_io_switch, |
| 2176 | #ifdef CONFIG_PM | ||
| 2177 | .suspend = hw_suspend, | ||
| 2178 | .resume = hw_resume, | ||
| 2179 | #endif | ||
| 2131 | 2180 | ||
| 2132 | .src_rsc_get_ctrl_blk = src_get_rsc_ctrl_blk, | 2181 | .src_rsc_get_ctrl_blk = src_get_rsc_ctrl_blk, |
| 2133 | .src_rsc_put_ctrl_blk = src_put_rsc_ctrl_blk, | 2182 | .src_rsc_put_ctrl_blk = src_put_rsc_ctrl_blk, |
diff --git a/sound/pci/ctxfi/cthw20k2.c b/sound/pci/ctxfi/cthw20k2.c index 4493a51c6b01..dec46d04b041 100644 --- a/sound/pci/ctxfi/cthw20k2.c +++ b/sound/pci/ctxfi/cthw20k2.c | |||
| @@ -1860,16 +1860,18 @@ static int hw_card_start(struct hw *hw) | |||
| 1860 | goto error1; | 1860 | goto error1; |
| 1861 | } | 1861 | } |
| 1862 | 1862 | ||
| 1863 | err = pci_request_regions(pci, "XFi"); | 1863 | if (!hw->io_base) { |
| 1864 | if (err < 0) | 1864 | err = pci_request_regions(pci, "XFi"); |
| 1865 | goto error1; | 1865 | if (err < 0) |
| 1866 | goto error1; | ||
| 1866 | 1867 | ||
| 1867 | hw->io_base = pci_resource_start(hw->pci, 2); | 1868 | hw->io_base = pci_resource_start(hw->pci, 2); |
| 1868 | hw->mem_base = (unsigned long)ioremap(hw->io_base, | 1869 | hw->mem_base = (unsigned long)ioremap(hw->io_base, |
| 1869 | pci_resource_len(hw->pci, 2)); | 1870 | pci_resource_len(hw->pci, 2)); |
| 1870 | if (NULL == (void *)hw->mem_base) { | 1871 | if (NULL == (void *)hw->mem_base) { |
| 1871 | err = -ENOENT; | 1872 | err = -ENOENT; |
| 1872 | goto error2; | 1873 | goto error2; |
| 1874 | } | ||
| 1873 | } | 1875 | } |
| 1874 | 1876 | ||
| 1875 | /* Switch to 20k2 mode from UAA mode. */ | 1877 | /* Switch to 20k2 mode from UAA mode. */ |
| @@ -1901,6 +1903,15 @@ error1: | |||
| 1901 | 1903 | ||
| 1902 | static int hw_card_stop(struct hw *hw) | 1904 | static int hw_card_stop(struct hw *hw) |
| 1903 | { | 1905 | { |
| 1906 | unsigned int data; | ||
| 1907 | |||
| 1908 | /* disable transport bus master and queueing of request */ | ||
| 1909 | hw_write_20kx(hw, TRANSPORT_CTL, 0x00); | ||
| 1910 | |||
| 1911 | /* disable pll */ | ||
| 1912 | data = hw_read_20kx(hw, PLL_ENB); | ||
| 1913 | hw_write_20kx(hw, PLL_ENB, (data & (~0x07))); | ||
| 1914 | |||
| 1904 | /* TODO: Disable interrupt and so on... */ | 1915 | /* TODO: Disable interrupt and so on... */ |
| 1905 | return 0; | 1916 | return 0; |
| 1906 | } | 1917 | } |
| @@ -1939,11 +1950,9 @@ static int hw_card_init(struct hw *hw, struct card_conf *info) | |||
| 1939 | 1950 | ||
| 1940 | /* Get PCI io port/memory base address and | 1951 | /* Get PCI io port/memory base address and |
| 1941 | * do 20kx core switch if needed. */ | 1952 | * do 20kx core switch if needed. */ |
| 1942 | if (!hw->io_base) { | 1953 | err = hw_card_start(hw); |
| 1943 | err = hw_card_start(hw); | 1954 | if (err) |
| 1944 | if (err) | 1955 | return err; |
| 1945 | return err; | ||
| 1946 | } | ||
| 1947 | 1956 | ||
| 1948 | /* PLL init */ | 1957 | /* PLL init */ |
| 1949 | err = hw_pll_init(hw, info->rsr); | 1958 | err = hw_pll_init(hw, info->rsr); |
| @@ -2006,6 +2015,32 @@ static int hw_card_init(struct hw *hw, struct card_conf *info) | |||
| 2006 | return 0; | 2015 | return 0; |
| 2007 | } | 2016 | } |
| 2008 | 2017 | ||
| 2018 | #ifdef CONFIG_PM | ||
| 2019 | static int hw_suspend(struct hw *hw, pm_message_t state) | ||
| 2020 | { | ||
| 2021 | struct pci_dev *pci = hw->pci; | ||
| 2022 | |||
| 2023 | hw_card_stop(hw); | ||
| 2024 | |||
| 2025 | pci_disable_device(pci); | ||
| 2026 | pci_save_state(pci); | ||
| 2027 | pci_set_power_state(pci, pci_choose_state(pci, state)); | ||
| 2028 | |||
| 2029 | return 0; | ||
| 2030 | } | ||
| 2031 | |||
| 2032 | static int hw_resume(struct hw *hw, struct card_conf *info) | ||
| 2033 | { | ||
| 2034 | struct pci_dev *pci = hw->pci; | ||
| 2035 | |||
| 2036 | pci_set_power_state(pci, PCI_D0); | ||
| 2037 | pci_restore_state(pci); | ||
| 2038 | |||
| 2039 | /* Re-initialize card hardware. */ | ||
| 2040 | return hw_card_init(hw, info); | ||
| 2041 | } | ||
| 2042 | #endif | ||
| 2043 | |||
| 2009 | static u32 hw_read_20kx(struct hw *hw, u32 reg) | 2044 | static u32 hw_read_20kx(struct hw *hw, u32 reg) |
| 2010 | { | 2045 | { |
| 2011 | return readl((void *)(hw->mem_base + reg)); | 2046 | return readl((void *)(hw->mem_base + reg)); |
| @@ -2025,6 +2060,10 @@ static struct hw ct20k2_preset __devinitdata = { | |||
| 2025 | .is_adc_source_selected = hw_is_adc_input_selected, | 2060 | .is_adc_source_selected = hw_is_adc_input_selected, |
| 2026 | .select_adc_source = hw_adc_input_select, | 2061 | .select_adc_source = hw_adc_input_select, |
| 2027 | .have_digit_io_switch = hw_have_digit_io_switch, | 2062 | .have_digit_io_switch = hw_have_digit_io_switch, |
| 2063 | #ifdef CONFIG_PM | ||
| 2064 | .suspend = hw_suspend, | ||
| 2065 | .resume = hw_resume, | ||
| 2066 | #endif | ||
| 2028 | 2067 | ||
| 2029 | .src_rsc_get_ctrl_blk = src_get_rsc_ctrl_blk, | 2068 | .src_rsc_get_ctrl_blk = src_get_rsc_ctrl_blk, |
| 2030 | .src_rsc_put_ctrl_blk = src_put_rsc_ctrl_blk, | 2069 | .src_rsc_put_ctrl_blk = src_put_rsc_ctrl_blk, |
diff --git a/sound/pci/ctxfi/ctmixer.c b/sound/pci/ctxfi/ctmixer.c index 666722d9de41..f26d7cd9db9f 100644 --- a/sound/pci/ctxfi/ctmixer.c +++ b/sound/pci/ctxfi/ctmixer.c | |||
| @@ -462,6 +462,43 @@ do_digit_io_switch(struct ct_atc *atc, int state) | |||
| 462 | return; | 462 | return; |
| 463 | } | 463 | } |
| 464 | 464 | ||
| 465 | static void do_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type, int state) | ||
| 466 | { | ||
| 467 | struct ct_mixer *mixer = atc->mixer; | ||
| 468 | |||
| 469 | /* Do changes in mixer. */ | ||
| 470 | if ((SWH_CAPTURE_START <= type) && (SWH_CAPTURE_END >= type)) { | ||
| 471 | if (state) { | ||
| 472 | ct_mixer_recording_select(mixer, | ||
| 473 | get_amixer_index(type)); | ||
| 474 | } else { | ||
| 475 | ct_mixer_recording_unselect(mixer, | ||
| 476 | get_amixer_index(type)); | ||
| 477 | } | ||
| 478 | } | ||
| 479 | /* Do changes out of mixer. */ | ||
| 480 | if (state && (MIXER_LINEIN_C_S == type || MIXER_MIC_C_S == type)) | ||
| 481 | do_line_mic_switch(atc, type); | ||
| 482 | else if (MIXER_WAVEF_P_S == type) | ||
| 483 | atc->line_front_unmute(atc, state); | ||
| 484 | else if (MIXER_WAVES_P_S == type) | ||
| 485 | atc->line_surround_unmute(atc, state); | ||
| 486 | else if (MIXER_WAVEC_P_S == type) | ||
| 487 | atc->line_clfe_unmute(atc, state); | ||
| 488 | else if (MIXER_WAVER_P_S == type) | ||
| 489 | 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) | ||
| 493 | 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) | ||
| 497 | do_digit_io_switch(atc, state); | ||
| 498 | |||
| 499 | return; | ||
| 500 | } | ||
| 501 | |||
| 465 | static int ct_alsa_mix_switch_info(struct snd_kcontrol *kcontrol, | 502 | static int ct_alsa_mix_switch_info(struct snd_kcontrol *kcontrol, |
| 466 | struct snd_ctl_elem_info *uinfo) | 503 | struct snd_ctl_elem_info *uinfo) |
| 467 | { | 504 | { |
| @@ -498,35 +535,7 @@ static int ct_alsa_mix_switch_put(struct snd_kcontrol *kcontrol, | |||
| 498 | return 0; | 535 | return 0; |
| 499 | 536 | ||
| 500 | set_switch_state(mixer, type, state); | 537 | set_switch_state(mixer, type, state); |
| 501 | /* Do changes in mixer. */ | 538 | do_switch(atc, type, state); |
| 502 | if ((SWH_CAPTURE_START <= type) && (SWH_CAPTURE_END >= type)) { | ||
| 503 | if (state) { | ||
| 504 | ct_mixer_recording_select(mixer, | ||
| 505 | get_amixer_index(type)); | ||
| 506 | } else { | ||
| 507 | ct_mixer_recording_unselect(mixer, | ||
| 508 | get_amixer_index(type)); | ||
| 509 | } | ||
| 510 | } | ||
| 511 | /* Do changes out of mixer. */ | ||
| 512 | if (state && (MIXER_LINEIN_C_S == type || MIXER_MIC_C_S == type)) | ||
| 513 | do_line_mic_switch(atc, type); | ||
| 514 | else if (MIXER_WAVEF_P_S == type) | ||
| 515 | atc->line_front_unmute(atc, state); | ||
| 516 | else if (MIXER_WAVES_P_S == type) | ||
| 517 | atc->line_surround_unmute(atc, state); | ||
| 518 | else if (MIXER_WAVEC_P_S == type) | ||
| 519 | atc->line_clfe_unmute(atc, state); | ||
| 520 | else if (MIXER_WAVER_P_S == type) | ||
| 521 | atc->line_rear_unmute(atc, state); | ||
| 522 | else if (MIXER_LINEIN_P_S == type) | ||
| 523 | atc->line_in_unmute(atc, state); | ||
| 524 | else if (MIXER_SPDIFO_P_S == type) | ||
| 525 | atc->spdif_out_unmute(atc, state); | ||
| 526 | else if (MIXER_SPDIFI_P_S == type) | ||
| 527 | atc->spdif_in_unmute(atc, state); | ||
| 528 | else if (MIXER_DIGITAL_IO_S == type) | ||
| 529 | do_digit_io_switch(atc, state); | ||
| 530 | 539 | ||
| 531 | return 1; | 540 | return 1; |
| 532 | } | 541 | } |
| @@ -1039,6 +1048,28 @@ mixer_set_input_right(struct ct_mixer *mixer, | |||
| 1039 | return 0; | 1048 | return 0; |
| 1040 | } | 1049 | } |
| 1041 | 1050 | ||
| 1051 | #ifdef CONFIG_PM | ||
| 1052 | static int mixer_resume(struct ct_mixer *mixer) | ||
| 1053 | { | ||
| 1054 | int i, state; | ||
| 1055 | struct amixer *amixer; | ||
| 1056 | |||
| 1057 | /* resume topology and volume gain. */ | ||
| 1058 | for (i = 0; i < NUM_CT_AMIXERS*CHN_NUM; i++) { | ||
| 1059 | amixer = mixer->amixers[i]; | ||
| 1060 | amixer->ops->commit_write(amixer); | ||
| 1061 | } | ||
| 1062 | |||
| 1063 | /* resume switch state. */ | ||
| 1064 | for (i = SWH_MIXER_START; i <= SWH_MIXER_END; i++) { | ||
| 1065 | state = get_switch_state(mixer, i); | ||
| 1066 | do_switch(mixer->atc, i, state); | ||
| 1067 | } | ||
| 1068 | |||
| 1069 | return 0; | ||
| 1070 | } | ||
| 1071 | #endif | ||
| 1072 | |||
| 1042 | int ct_mixer_destroy(struct ct_mixer *mixer) | 1073 | int ct_mixer_destroy(struct ct_mixer *mixer) |
| 1043 | { | 1074 | { |
| 1044 | struct sum_mgr *sum_mgr = (struct sum_mgr *)mixer->atc->rsc_mgrs[SUM]; | 1075 | struct sum_mgr *sum_mgr = (struct sum_mgr *)mixer->atc->rsc_mgrs[SUM]; |
| @@ -1087,6 +1118,9 @@ int ct_mixer_create(struct ct_atc *atc, struct ct_mixer **rmixer) | |||
| 1087 | mixer->get_output_ports = mixer_get_output_ports; | 1118 | mixer->get_output_ports = mixer_get_output_ports; |
| 1088 | mixer->set_input_left = mixer_set_input_left; | 1119 | mixer->set_input_left = mixer_set_input_left; |
| 1089 | mixer->set_input_right = mixer_set_input_right; | 1120 | mixer->set_input_right = mixer_set_input_right; |
| 1121 | #ifdef CONFIG_PM | ||
| 1122 | mixer->resume = mixer_resume; | ||
| 1123 | #endif | ||
| 1090 | 1124 | ||
| 1091 | /* Allocate chip resources for mixer obj */ | 1125 | /* Allocate chip resources for mixer obj */ |
| 1092 | err = ct_mixer_get_resources(mixer); | 1126 | err = ct_mixer_get_resources(mixer); |
diff --git a/sound/pci/ctxfi/ctmixer.h b/sound/pci/ctxfi/ctmixer.h index e2d96ebde746..b009e989e77d 100644 --- a/sound/pci/ctxfi/ctmixer.h +++ b/sound/pci/ctxfi/ctmixer.h | |||
| @@ -56,6 +56,9 @@ struct ct_mixer { | |||
| 56 | enum MIXER_PORT_T type, struct rsc *rsc); | 56 | enum MIXER_PORT_T type, struct rsc *rsc); |
| 57 | int (*set_input_right)(struct ct_mixer *mixer, | 57 | int (*set_input_right)(struct ct_mixer *mixer, |
| 58 | enum MIXER_PORT_T type, struct rsc *rsc); | 58 | enum MIXER_PORT_T type, struct rsc *rsc); |
| 59 | #ifdef CONFIG_PM | ||
| 60 | int (*resume)(struct ct_mixer *mixer); | ||
| 61 | #endif | ||
| 59 | }; | 62 | }; |
| 60 | 63 | ||
| 61 | int ct_alsa_mix_create(struct ct_atc *atc, | 64 | int ct_alsa_mix_create(struct ct_atc *atc, |
diff --git a/sound/pci/ctxfi/ctpcm.c b/sound/pci/ctxfi/ctpcm.c index 9e5c0c4da726..60ea23180acb 100644 --- a/sound/pci/ctxfi/ctpcm.c +++ b/sound/pci/ctxfi/ctpcm.c | |||
| @@ -422,5 +422,9 @@ int ct_alsa_pcm_create(struct ct_atc *atc, | |||
| 422 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, | 422 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, |
| 423 | snd_dma_pci_data(atc->pci), 128*1024, 128*1024); | 423 | snd_dma_pci_data(atc->pci), 128*1024, 128*1024); |
| 424 | 424 | ||
| 425 | #ifdef CONFIG_PM | ||
| 426 | atc->pcms[device] = pcm; | ||
| 427 | #endif | ||
| 428 | |||
| 425 | return 0; | 429 | return 0; |
| 426 | } | 430 | } |
diff --git a/sound/pci/ctxfi/xfi.c b/sound/pci/ctxfi/xfi.c index 2d3dd89af151..76541748e7bc 100644 --- a/sound/pci/ctxfi/xfi.c +++ b/sound/pci/ctxfi/xfi.c | |||
| @@ -121,11 +121,33 @@ static void __devexit ct_card_remove(struct pci_dev *pci) | |||
| 121 | pci_set_drvdata(pci, NULL); | 121 | pci_set_drvdata(pci, NULL); |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | #ifdef CONFIG_PM | ||
| 125 | static int ct_card_suspend(struct pci_dev *pci, pm_message_t state) | ||
| 126 | { | ||
| 127 | struct snd_card *card = pci_get_drvdata(pci); | ||
| 128 | struct ct_atc *atc = card->private_data; | ||
| 129 | |||
| 130 | return atc->suspend(atc, state); | ||
| 131 | } | ||
| 132 | |||
| 133 | static int ct_card_resume(struct pci_dev *pci) | ||
| 134 | { | ||
| 135 | struct snd_card *card = pci_get_drvdata(pci); | ||
| 136 | struct ct_atc *atc = card->private_data; | ||
| 137 | |||
| 138 | return atc->resume(atc); | ||
| 139 | } | ||
| 140 | #endif | ||
| 141 | |||
| 124 | static struct pci_driver ct_driver = { | 142 | static struct pci_driver ct_driver = { |
| 125 | .name = "SB-XFi", | 143 | .name = "SB-XFi", |
| 126 | .id_table = ct_pci_dev_ids, | 144 | .id_table = ct_pci_dev_ids, |
| 127 | .probe = ct_card_probe, | 145 | .probe = ct_card_probe, |
| 128 | .remove = __devexit_p(ct_card_remove), | 146 | .remove = __devexit_p(ct_card_remove), |
| 147 | #ifdef CONFIG_PM | ||
| 148 | .suspend = ct_card_suspend, | ||
| 149 | .resume = ct_card_resume, | ||
| 150 | #endif | ||
| 129 | }; | 151 | }; |
| 130 | 152 | ||
| 131 | static int __init ct_card_init(void) | 153 | static int __init ct_card_init(void) |
