diff options
author | Takashi Iwai <tiwai@suse.de> | 2005-08-16 10:52:24 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2005-08-30 02:46:26 -0400 |
commit | 1cfe43d21bc5ff751e95b6a62410e05956c09e38 (patch) | |
tree | 8809519d9ad946a9fc5a1535ce171df64fdf8d97 /sound/pci | |
parent | 65d11d95515db3efb629202104cfc672476618b5 (diff) |
[ALSA] intel8x0 - Fix PM
Intel8x0 driver
Fixed the PCM resume of intel8x0.
Restores the requested register setting.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/intel8x0.c | 39 |
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 | ||
394 | typedef struct _snd_intel8x0 intel8x0_t; | 395 | typedef 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 | ||
1042 | static int snd_intel8x0_pcm_prepare(snd_pcm_substream_t * substream) | 1054 | static 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 */ |