diff options
Diffstat (limited to 'sound/pci/intel8x0.c')
| -rw-r--r-- | sound/pci/intel8x0.c | 57 |
1 files changed, 49 insertions, 8 deletions
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index d7af3e474432..7b548416dcef 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 | ||
| @@ -1817,6 +1826,18 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { | |||
| 1817 | }, | 1826 | }, |
| 1818 | { | 1827 | { |
| 1819 | .subvendor = 0x103c, | 1828 | .subvendor = 0x103c, |
| 1829 | .subdevice = 0x0934, | ||
| 1830 | .name = "HP nx8220", | ||
| 1831 | .type = AC97_TUNE_MUTE_LED | ||
| 1832 | }, | ||
| 1833 | { | ||
| 1834 | .subvendor = 0x103c, | ||
| 1835 | .subdevice = 0x099c, | ||
| 1836 | .name = "HP nx6110", /* AD1981B */ | ||
| 1837 | .type = AC97_TUNE_HP_ONLY | ||
| 1838 | }, | ||
| 1839 | { | ||
| 1840 | .subvendor = 0x103c, | ||
| 1820 | .subdevice = 0x129d, | 1841 | .subdevice = 0x129d, |
| 1821 | .name = "HP xw8000", | 1842 | .name = "HP xw8000", |
| 1822 | .type = AC97_TUNE_HP_ONLY | 1843 | .type = AC97_TUNE_HP_ONLY |
| @@ -1870,6 +1891,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { | |||
| 1870 | .type = AC97_TUNE_HP_ONLY | 1891 | .type = AC97_TUNE_HP_ONLY |
| 1871 | }, | 1892 | }, |
| 1872 | { | 1893 | { |
| 1894 | .subvendor = 0x10cf, | ||
| 1895 | .subdevice = 0x12ec, | ||
| 1896 | .name = "Fujitsu-Siemens 4010", | ||
| 1897 | .type = AC97_TUNE_HP_ONLY | ||
| 1898 | }, | ||
| 1899 | { | ||
| 1873 | .subvendor = 0x10f1, | 1900 | .subvendor = 0x10f1, |
| 1874 | .subdevice = 0x2665, | 1901 | .subdevice = 0x2665, |
| 1875 | .name = "Fujitsu-Siemens Celsius", /* AD1981? */ | 1902 | .name = "Fujitsu-Siemens Celsius", /* AD1981? */ |
| @@ -2424,6 +2451,20 @@ static int intel8x0_resume(snd_card_t *card) | |||
| 2424 | } | 2451 | } |
| 2425 | } | 2452 | } |
| 2426 | 2453 | ||
| 2454 | /* resume status */ | ||
| 2455 | for (i = 0; i < chip->bdbars_count; i++) { | ||
| 2456 | ichdev_t *ichdev = &chip->ichd[i]; | ||
| 2457 | unsigned long port = ichdev->reg_offset; | ||
| 2458 | if (! ichdev->substream || ! ichdev->suspended) | ||
| 2459 | continue; | ||
| 2460 | if (ichdev->ichd == ICHD_PCMOUT) | ||
| 2461 | snd_intel8x0_setup_pcm_out(chip, ichdev->substream->runtime); | ||
| 2462 | iputdword(chip, port + ICH_REG_OFF_BDBAR, ichdev->bdbar_addr); | ||
| 2463 | iputbyte(chip, port + ICH_REG_OFF_LVI, ichdev->lvi); | ||
| 2464 | iputbyte(chip, port + ICH_REG_OFF_CIV, ichdev->civ); | ||
| 2465 | iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI); | ||
| 2466 | } | ||
| 2467 | |||
| 2427 | return 0; | 2468 | return 0; |
| 2428 | } | 2469 | } |
| 2429 | #endif /* CONFIG_PM */ | 2470 | #endif /* CONFIG_PM */ |
