aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/pci/intel8x0.c39
1 files changed, 31 insertions, 8 deletions
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index d7af3e474432..390b6c8f9a10 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -389,6 +389,7 @@ typedef struct {
389 struct ac97_pcm *pcm; 389 struct ac97_pcm *pcm;
390 int pcm_open_flag; 390 int pcm_open_flag;
391 unsigned int page_attr_changed: 1; 391 unsigned int page_attr_changed: 1;
392 unsigned int suspended: 1;
392} ichdev_t; 393} ichdev_t;
393 394
394typedef struct _snd_intel8x0 intel8x0_t; 395typedef struct _snd_intel8x0 intel8x0_t;
@@ -862,12 +863,16 @@ static int snd_intel8x0_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
862 unsigned long port = ichdev->reg_offset; 863 unsigned long port = ichdev->reg_offset;
863 864
864 switch (cmd) { 865 switch (cmd) {
865 case SNDRV_PCM_TRIGGER_START:
866 case SNDRV_PCM_TRIGGER_RESUME: 866 case SNDRV_PCM_TRIGGER_RESUME:
867 ichdev->suspended = 0;
868 /* fallthru */
869 case SNDRV_PCM_TRIGGER_START:
867 val = ICH_IOCE | ICH_STARTBM; 870 val = ICH_IOCE | ICH_STARTBM;
868 break; 871 break;
869 case SNDRV_PCM_TRIGGER_STOP:
870 case SNDRV_PCM_TRIGGER_SUSPEND: 872 case SNDRV_PCM_TRIGGER_SUSPEND:
873 ichdev->suspended = 1;
874 /* fallthru */
875 case SNDRV_PCM_TRIGGER_STOP:
871 val = 0; 876 val = 0;
872 break; 877 break;
873 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 878 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
@@ -899,9 +904,11 @@ static int snd_intel8x0_ali_trigger(snd_pcm_substream_t *substream, int cmd)
899 904
900 val = igetdword(chip, ICHREG(ALI_DMACR)); 905 val = igetdword(chip, ICHREG(ALI_DMACR));
901 switch (cmd) { 906 switch (cmd) {
907 case SNDRV_PCM_TRIGGER_RESUME:
908 ichdev->suspended = 0;
909 /* fallthru */
902 case SNDRV_PCM_TRIGGER_START: 910 case SNDRV_PCM_TRIGGER_START:
903 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 911 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
904 case SNDRV_PCM_TRIGGER_RESUME:
905 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 912 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
906 /* clear FIFO for synchronization of channels */ 913 /* clear FIFO for synchronization of channels */
907 fifo = igetdword(chip, fiforeg[ichdev->ali_slot / 4]); 914 fifo = igetdword(chip, fiforeg[ichdev->ali_slot / 4]);
@@ -913,9 +920,11 @@ static int snd_intel8x0_ali_trigger(snd_pcm_substream_t *substream, int cmd)
913 val &= ~(1 << (ichdev->ali_slot + 16)); /* clear PAUSE flag */ 920 val &= ~(1 << (ichdev->ali_slot + 16)); /* clear PAUSE flag */
914 iputdword(chip, ICHREG(ALI_DMACR), val | (1 << ichdev->ali_slot)); /* start DMA */ 921 iputdword(chip, ICHREG(ALI_DMACR), val | (1 << ichdev->ali_slot)); /* start DMA */
915 break; 922 break;
923 case SNDRV_PCM_TRIGGER_SUSPEND:
924 ichdev->suspended = 1;
925 /* fallthru */
916 case SNDRV_PCM_TRIGGER_STOP: 926 case SNDRV_PCM_TRIGGER_STOP:
917 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 927 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
918 case SNDRV_PCM_TRIGGER_SUSPEND:
919 iputdword(chip, ICHREG(ALI_DMACR), val | (1 << (ichdev->ali_slot + 16))); /* pause */ 928 iputdword(chip, ICHREG(ALI_DMACR), val | (1 << (ichdev->ali_slot + 16))); /* pause */
920 iputbyte(chip, port + ICH_REG_OFF_CR, 0); 929 iputbyte(chip, port + ICH_REG_OFF_CR, 0);
921 while (igetbyte(chip, port + ICH_REG_OFF_CR)) 930 while (igetbyte(chip, port + ICH_REG_OFF_CR))
@@ -994,6 +1003,8 @@ static void snd_intel8x0_setup_pcm_out(intel8x0_t *chip,
994{ 1003{
995 unsigned int cnt; 1004 unsigned int cnt;
996 int dbl = runtime->rate > 48000; 1005 int dbl = runtime->rate > 48000;
1006
1007 spin_lock_irq(&chip->reg_lock);
997 switch (chip->device_type) { 1008 switch (chip->device_type) {
998 case DEVICE_ALI: 1009 case DEVICE_ALI:
999 cnt = igetdword(chip, ICHREG(ALI_SCR)); 1010 cnt = igetdword(chip, ICHREG(ALI_SCR));
@@ -1037,6 +1048,7 @@ static void snd_intel8x0_setup_pcm_out(intel8x0_t *chip,
1037 iputdword(chip, ICHREG(GLOB_CNT), cnt); 1048 iputdword(chip, ICHREG(GLOB_CNT), cnt);
1038 break; 1049 break;
1039 } 1050 }
1051 spin_unlock_irq(&chip->reg_lock);
1040} 1052}
1041 1053
1042static int snd_intel8x0_pcm_prepare(snd_pcm_substream_t * substream) 1054static int snd_intel8x0_pcm_prepare(snd_pcm_substream_t * substream)
@@ -1048,15 +1060,12 @@ static int snd_intel8x0_pcm_prepare(snd_pcm_substream_t * substream)
1048 ichdev->physbuf = runtime->dma_addr; 1060 ichdev->physbuf = runtime->dma_addr;
1049 ichdev->size = snd_pcm_lib_buffer_bytes(substream); 1061 ichdev->size = snd_pcm_lib_buffer_bytes(substream);
1050 ichdev->fragsize = snd_pcm_lib_period_bytes(substream); 1062 ichdev->fragsize = snd_pcm_lib_period_bytes(substream);
1051 spin_lock_irq(&chip->reg_lock);
1052 if (ichdev->ichd == ICHD_PCMOUT) { 1063 if (ichdev->ichd == ICHD_PCMOUT) {
1053 snd_intel8x0_setup_pcm_out(chip, runtime); 1064 snd_intel8x0_setup_pcm_out(chip, runtime);
1054 if (chip->device_type == DEVICE_INTEL_ICH4) { 1065 if (chip->device_type == DEVICE_INTEL_ICH4)
1055 ichdev->pos_shift = (runtime->sample_bits > 16) ? 2 : 1; 1066 ichdev->pos_shift = (runtime->sample_bits > 16) ? 2 : 1;
1056 }
1057 } 1067 }
1058 snd_intel8x0_setup_periods(chip, ichdev); 1068 snd_intel8x0_setup_periods(chip, ichdev);
1059 spin_unlock_irq(&chip->reg_lock);
1060 return 0; 1069 return 0;
1061} 1070}
1062 1071
@@ -2424,6 +2433,20 @@ static int intel8x0_resume(snd_card_t *card)
2424 } 2433 }
2425 } 2434 }
2426 2435
2436 /* resume status */
2437 for (i = 0; i < chip->bdbars_count; i++) {
2438 ichdev_t *ichdev = &chip->ichd[i];
2439 unsigned long port = ichdev->reg_offset;
2440 if (! ichdev->substream || ! ichdev->suspended)
2441 continue;
2442 if (ichdev->ichd == ICHD_PCMOUT)
2443 snd_intel8x0_setup_pcm_out(chip, ichdev->substream->runtime);
2444 iputdword(chip, port + ICH_REG_OFF_BDBAR, ichdev->bdbar_addr);
2445 iputbyte(chip, port + ICH_REG_OFF_LVI, ichdev->lvi);
2446 iputbyte(chip, port + ICH_REG_OFF_CIV, ichdev->civ);
2447 iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI);
2448 }
2449
2427 return 0; 2450 return 0;
2428} 2451}
2429#endif /* CONFIG_PM */ 2452#endif /* CONFIG_PM */