aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/ctxfi/ctatc.c
diff options
context:
space:
mode:
authorWai Yew CHAY <wychay@ctl.creative.com>2009-06-22 08:52:34 -0400
committerTakashi Iwai <tiwai@suse.de>2009-06-22 08:53:51 -0400
commit29959a09cc1aabd2d5f4f03afc0305de6bd29248 (patch)
treee7e4ed3d33995ab9e83ae378bb9d42fce63f8fde /sound/pci/ctxfi/ctatc.c
parenta8f4310be59a2e7fc80fba945bcb32b18f4ad54f (diff)
ALSA: ctxfi - Add PM support
Added the suspend/resume support to ctxfi driver. The team tested on the following seems ok: AMD Athlon 64 3500+ / ASUS A8N-E / 512MB DDR ATI / Radeon X1300 20k1 & 20k2 cards Signed-off-by: Wai Yew CHAY <wychay@ctl.creative.com> Singed-off-by: Ryan RICHARDS <ryan_richards@creativelabs.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/ctxfi/ctatc.c')
-rw-r--r--sound/pci/ctxfi/ctatc.c181
1 files changed, 133 insertions, 48 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
1119static int ct_atc_destroy(struct ct_atc *atc) 1110static 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
1184static 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
1326static int __devinit atc_get_resources(struct ct_atc *atc) 1329static 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
1432static void __devinit 1429static void
1433atc_connect_dai(struct src_mgr *src_mgr, struct dai *dai, 1430atc_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
1471static void __devinit atc_connect_resources(struct ct_atc *atc) 1468static 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
1515static 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
1536static 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
1548static 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
1569static 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
1517static struct ct_atc atc_preset __devinitdata = { 1592static 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)