diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/core/pcm_native.c | 4 | ||||
-rw-r--r-- | sound/pci/emu10k1/emu10k1.c | 4 | ||||
-rw-r--r-- | sound/pci/emu10k1/emupcm.c | 30 | ||||
-rw-r--r-- | sound/pci/emu10k1/memory.c | 4 |
4 files changed, 37 insertions, 5 deletions
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index a3b2a6479246..134fc6c2e08d 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
@@ -978,6 +978,10 @@ static int snd_pcm_do_pause(struct snd_pcm_substream *substream, int push) | |||
978 | { | 978 | { |
979 | if (substream->runtime->trigger_master != substream) | 979 | if (substream->runtime->trigger_master != substream) |
980 | return 0; | 980 | return 0; |
981 | /* some drivers might use hw_ptr to recover from the pause - | ||
982 | update the hw_ptr now */ | ||
983 | if (push) | ||
984 | snd_pcm_update_hw_ptr(substream); | ||
981 | /* The jiffies check in snd_pcm_update_hw_ptr*() is done by | 985 | /* The jiffies check in snd_pcm_update_hw_ptr*() is done by |
982 | * a delta betwen the current jiffies, this gives a large enough | 986 | * a delta betwen the current jiffies, this gives a large enough |
983 | * delta, effectively to skip the check once. | 987 | * delta, effectively to skip the check once. |
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index 4203782d7cb7..aff8387c45cf 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c | |||
@@ -52,6 +52,7 @@ static int max_synth_voices[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 64}; | |||
52 | static int max_buffer_size[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 128}; | 52 | static int max_buffer_size[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 128}; |
53 | static int enable_ir[SNDRV_CARDS]; | 53 | static int enable_ir[SNDRV_CARDS]; |
54 | static uint subsystem[SNDRV_CARDS]; /* Force card subsystem model */ | 54 | static uint subsystem[SNDRV_CARDS]; /* Force card subsystem model */ |
55 | static uint delay_pcm_irq[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; | ||
55 | 56 | ||
56 | module_param_array(index, int, NULL, 0444); | 57 | module_param_array(index, int, NULL, 0444); |
57 | MODULE_PARM_DESC(index, "Index value for the EMU10K1 soundcard."); | 58 | MODULE_PARM_DESC(index, "Index value for the EMU10K1 soundcard."); |
@@ -73,6 +74,8 @@ module_param_array(enable_ir, bool, NULL, 0444); | |||
73 | MODULE_PARM_DESC(enable_ir, "Enable IR."); | 74 | MODULE_PARM_DESC(enable_ir, "Enable IR."); |
74 | module_param_array(subsystem, uint, NULL, 0444); | 75 | module_param_array(subsystem, uint, NULL, 0444); |
75 | MODULE_PARM_DESC(subsystem, "Force card subsystem model."); | 76 | MODULE_PARM_DESC(subsystem, "Force card subsystem model."); |
77 | module_param_array(delay_pcm_irq, uint, NULL, 0444); | ||
78 | MODULE_PARM_DESC(delay_pcm_irq, "Delay PCM interrupt by specified number of samples (default 0)."); | ||
76 | /* | 79 | /* |
77 | * Class 0401: 1102:0008 (rev 00) Subsystem: 1102:1001 -> Audigy2 Value Model:SB0400 | 80 | * Class 0401: 1102:0008 (rev 00) Subsystem: 1102:1001 -> Audigy2 Value Model:SB0400 |
78 | */ | 81 | */ |
@@ -127,6 +130,7 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci, | |||
127 | &emu)) < 0) | 130 | &emu)) < 0) |
128 | goto error; | 131 | goto error; |
129 | card->private_data = emu; | 132 | card->private_data = emu; |
133 | emu->delay_pcm_irq = delay_pcm_irq[dev] & 0x1f; | ||
130 | if ((err = snd_emu10k1_pcm(emu, 0, NULL)) < 0) | 134 | if ((err = snd_emu10k1_pcm(emu, 0, NULL)) < 0) |
131 | goto error; | 135 | goto error; |
132 | if ((err = snd_emu10k1_pcm_mic(emu, 1, NULL)) < 0) | 136 | if ((err = snd_emu10k1_pcm_mic(emu, 1, NULL)) < 0) |
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c index 55b83ef73c63..622bace148e3 100644 --- a/sound/pci/emu10k1/emupcm.c +++ b/sound/pci/emu10k1/emupcm.c | |||
@@ -332,7 +332,7 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu, | |||
332 | evoice->epcm->ccca_start_addr = start_addr + ccis; | 332 | evoice->epcm->ccca_start_addr = start_addr + ccis; |
333 | if (extra) { | 333 | if (extra) { |
334 | start_addr += ccis; | 334 | start_addr += ccis; |
335 | end_addr += ccis; | 335 | end_addr += ccis + emu->delay_pcm_irq; |
336 | } | 336 | } |
337 | if (stereo && !extra) { | 337 | if (stereo && !extra) { |
338 | snd_emu10k1_ptr_write(emu, CPF, voice, CPF_STEREO_MASK); | 338 | snd_emu10k1_ptr_write(emu, CPF, voice, CPF_STEREO_MASK); |
@@ -360,7 +360,9 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu, | |||
360 | /* Assumption that PT is already 0 so no harm overwriting */ | 360 | /* Assumption that PT is already 0 so no harm overwriting */ |
361 | snd_emu10k1_ptr_write(emu, PTRX, voice, (send_amount[0] << 8) | send_amount[1]); | 361 | snd_emu10k1_ptr_write(emu, PTRX, voice, (send_amount[0] << 8) | send_amount[1]); |
362 | snd_emu10k1_ptr_write(emu, DSL, voice, end_addr | (send_amount[3] << 24)); | 362 | snd_emu10k1_ptr_write(emu, DSL, voice, end_addr | (send_amount[3] << 24)); |
363 | snd_emu10k1_ptr_write(emu, PSST, voice, start_addr | (send_amount[2] << 24)); | 363 | snd_emu10k1_ptr_write(emu, PSST, voice, |
364 | (start_addr + (extra ? emu->delay_pcm_irq : 0)) | | ||
365 | (send_amount[2] << 24)); | ||
364 | if (emu->card_capabilities->emu_model) | 366 | if (emu->card_capabilities->emu_model) |
365 | pitch_target = PITCH_48000; /* Disable interpolators on emu1010 card */ | 367 | pitch_target = PITCH_48000; /* Disable interpolators on emu1010 card */ |
366 | else | 368 | else |
@@ -732,6 +734,23 @@ static void snd_emu10k1_playback_stop_voice(struct snd_emu10k1 *emu, struct snd_ | |||
732 | snd_emu10k1_ptr_write(emu, IP, voice, 0); | 734 | snd_emu10k1_ptr_write(emu, IP, voice, 0); |
733 | } | 735 | } |
734 | 736 | ||
737 | static inline void snd_emu10k1_playback_mangle_extra(struct snd_emu10k1 *emu, | ||
738 | struct snd_emu10k1_pcm *epcm, | ||
739 | struct snd_pcm_substream *substream, | ||
740 | struct snd_pcm_runtime *runtime) | ||
741 | { | ||
742 | unsigned int ptr, period_pos; | ||
743 | |||
744 | /* try to sychronize the current position for the interrupt | ||
745 | source voice */ | ||
746 | period_pos = runtime->status->hw_ptr - runtime->hw_ptr_interrupt; | ||
747 | period_pos %= runtime->period_size; | ||
748 | ptr = snd_emu10k1_ptr_read(emu, CCCA, epcm->extra->number); | ||
749 | ptr &= ~0x00ffffff; | ||
750 | ptr |= epcm->ccca_start_addr + period_pos; | ||
751 | snd_emu10k1_ptr_write(emu, CCCA, epcm->extra->number, ptr); | ||
752 | } | ||
753 | |||
735 | static int snd_emu10k1_playback_trigger(struct snd_pcm_substream *substream, | 754 | static int snd_emu10k1_playback_trigger(struct snd_pcm_substream *substream, |
736 | int cmd) | 755 | int cmd) |
737 | { | 756 | { |
@@ -753,6 +772,8 @@ static int snd_emu10k1_playback_trigger(struct snd_pcm_substream *substream, | |||
753 | /* follow thru */ | 772 | /* follow thru */ |
754 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 773 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
755 | case SNDRV_PCM_TRIGGER_RESUME: | 774 | case SNDRV_PCM_TRIGGER_RESUME: |
775 | if (cmd == SNDRV_PCM_TRIGGER_PAUSE_RELEASE) | ||
776 | snd_emu10k1_playback_mangle_extra(emu, epcm, substream, runtime); | ||
756 | mix = &emu->pcm_mixer[substream->number]; | 777 | mix = &emu->pcm_mixer[substream->number]; |
757 | snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 1, 0, mix); | 778 | snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 1, 0, mix); |
758 | snd_emu10k1_playback_prepare_voice(emu, epcm->voices[1], 0, 0, mix); | 779 | snd_emu10k1_playback_prepare_voice(emu, epcm->voices[1], 0, 0, mix); |
@@ -869,8 +890,9 @@ static snd_pcm_uframes_t snd_emu10k1_playback_pointer(struct snd_pcm_substream * | |||
869 | #endif | 890 | #endif |
870 | /* | 891 | /* |
871 | printk(KERN_DEBUG | 892 | printk(KERN_DEBUG |
872 | "ptr = 0x%x, buffer_size = 0x%x, period_size = 0x%x\n", | 893 | "ptr = 0x%lx, buffer_size = 0x%lx, period_size = 0x%lx\n", |
873 | ptr, runtime->buffer_size, runtime->period_size); | 894 | (long)ptr, (long)runtime->buffer_size, |
895 | (long)runtime->period_size); | ||
874 | */ | 896 | */ |
875 | return ptr; | 897 | return ptr; |
876 | } | 898 | } |
diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c index ffb1ddb8dc28..957a311514c8 100644 --- a/sound/pci/emu10k1/memory.c +++ b/sound/pci/emu10k1/memory.c | |||
@@ -310,8 +310,10 @@ snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *subst | |||
310 | if (snd_BUG_ON(!hdr)) | 310 | if (snd_BUG_ON(!hdr)) |
311 | return NULL; | 311 | return NULL; |
312 | 312 | ||
313 | idx = runtime->period_size >= runtime->buffer_size ? | ||
314 | (emu->delay_pcm_irq * 2) : 0; | ||
313 | mutex_lock(&hdr->block_mutex); | 315 | mutex_lock(&hdr->block_mutex); |
314 | blk = search_empty(emu, runtime->dma_bytes); | 316 | blk = search_empty(emu, runtime->dma_bytes + idx); |
315 | if (blk == NULL) { | 317 | if (blk == NULL) { |
316 | mutex_unlock(&hdr->block_mutex); | 318 | mutex_unlock(&hdr->block_mutex); |
317 | return NULL; | 319 | return NULL; |