aboutsummaryrefslogtreecommitdiff
path: root/sound/pci/emu10k1/emupcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/emu10k1/emupcm.c')
-rw-r--r--sound/pci/emu10k1/emupcm.c97
1 files changed, 80 insertions, 17 deletions
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
index cf9276ddad4..f82481bd254 100644
--- a/sound/pci/emu10k1/emupcm.c
+++ b/sound/pci/emu10k1/emupcm.c
@@ -44,7 +44,8 @@ static void snd_emu10k1_pcm_interrupt(struct snd_emu10k1 *emu,
if (epcm->substream == NULL)
return;
#if 0
- printk("IRQ: position = 0x%x, period = 0x%x, size = 0x%x\n",
+ dev_dbg(emu->card->dev,
+ "IRQ: position = 0x%x, period = 0x%x, size = 0x%x\n",
epcm->substream->runtime->hw->pointer(emu, epcm->substream),
snd_pcm_lib_period_bytes(epcm->substream),
snd_pcm_lib_buffer_bytes(epcm->substream));
@@ -146,7 +147,11 @@ static int snd_emu10k1_pcm_channel_alloc(struct snd_emu10k1_pcm * epcm, int voic
1,
&epcm->extra);
if (err < 0) {
- /* printk("pcm_channel_alloc: failed extra: voices=%d, frame=%d\n", voices, frame); */
+ /*
+ dev_dbg(emu->card->dev, "pcm_channel_alloc: "
+ "failed extra: voices=%d, frame=%d\n",
+ voices, frame);
+ */
for (i = 0; i < voices; i++) {
snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]);
epcm->voices[i] = NULL;
@@ -328,7 +333,7 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
evoice->epcm->ccca_start_addr = start_addr + ccis;
if (extra) {
start_addr += ccis;
- end_addr += ccis;
+ end_addr += ccis + emu->delay_pcm_irq;
}
if (stereo && !extra) {
snd_emu10k1_ptr_write(emu, CPF, voice, CPF_STEREO_MASK);
@@ -356,7 +361,9 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
/* Assumption that PT is already 0 so no harm overwriting */
snd_emu10k1_ptr_write(emu, PTRX, voice, (send_amount[0] << 8) | send_amount[1]);
snd_emu10k1_ptr_write(emu, DSL, voice, end_addr | (send_amount[3] << 24));
- snd_emu10k1_ptr_write(emu, PSST, voice, start_addr | (send_amount[2] << 24));
+ snd_emu10k1_ptr_write(emu, PSST, voice,
+ (start_addr + (extra ? emu->delay_pcm_irq : 0)) |
+ (send_amount[2] << 24));
if (emu->card_capabilities->emu_model)
pitch_target = PITCH_48000; /* Disable interpolators on emu1010 card */
else
@@ -728,6 +735,23 @@ static void snd_emu10k1_playback_stop_voice(struct snd_emu10k1 *emu, struct snd_
snd_emu10k1_ptr_write(emu, IP, voice, 0);
}
+static inline void snd_emu10k1_playback_mangle_extra(struct snd_emu10k1 *emu,
+ struct snd_emu10k1_pcm *epcm,
+ struct snd_pcm_substream *substream,
+ struct snd_pcm_runtime *runtime)
+{
+ unsigned int ptr, period_pos;
+
+ /* try to sychronize the current position for the interrupt
+ source voice */
+ period_pos = runtime->status->hw_ptr - runtime->hw_ptr_interrupt;
+ period_pos %= runtime->period_size;
+ ptr = snd_emu10k1_ptr_read(emu, CCCA, epcm->extra->number);
+ ptr &= ~0x00ffffff;
+ ptr |= epcm->ccca_start_addr + period_pos;
+ snd_emu10k1_ptr_write(emu, CCCA, epcm->extra->number, ptr);
+}
+
static int snd_emu10k1_playback_trigger(struct snd_pcm_substream *substream,
int cmd)
{
@@ -737,7 +761,11 @@ static int snd_emu10k1_playback_trigger(struct snd_pcm_substream *substream,
struct snd_emu10k1_pcm_mixer *mix;
int result = 0;
- /* printk("trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n", (int)emu, cmd, substream->ops->pointer(substream)); */
+ /*
+ dev_dbg(emu->card->dev,
+ "trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n",
+ (int)emu, cmd, substream->ops->pointer(substream))
+ */
spin_lock(&emu->reg_lock);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -746,6 +774,8 @@ static int snd_emu10k1_playback_trigger(struct snd_pcm_substream *substream,
/* follow thru */
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
case SNDRV_PCM_TRIGGER_RESUME:
+ if (cmd == SNDRV_PCM_TRIGGER_PAUSE_RELEASE)
+ snd_emu10k1_playback_mangle_extra(emu, epcm, substream, runtime);
mix = &emu->pcm_mixer[substream->number];
snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 1, 0, mix);
snd_emu10k1_playback_prepare_voice(emu, epcm->voices[1], 0, 0, mix);
@@ -786,7 +816,10 @@ static int snd_emu10k1_capture_trigger(struct snd_pcm_substream *substream,
/* hmm this should cause full and half full interrupt to be raised? */
outl(epcm->capture_ipr, emu->port + IPR);
snd_emu10k1_intr_enable(emu, epcm->capture_inte);
- /* printk("adccr = 0x%x, adcbs = 0x%x\n", epcm->adccr, epcm->adcbs); */
+ /*
+ dev_dbg(emu->card->dev, "adccr = 0x%x, adcbs = 0x%x\n",
+ epcm->adccr, epcm->adcbs);
+ */
switch (epcm->type) {
case CAPTURE_AC97ADC:
snd_emu10k1_ptr_write(emu, ADCCR, 0, epcm->capture_cr_val);
@@ -795,7 +828,10 @@ static int snd_emu10k1_capture_trigger(struct snd_pcm_substream *substream,
if (emu->audigy) {
snd_emu10k1_ptr_write(emu, A_FXWC1, 0, epcm->capture_cr_val);
snd_emu10k1_ptr_write(emu, A_FXWC2, 0, epcm->capture_cr_val2);
- snd_printdd("cr_val=0x%x, cr_val2=0x%x\n", epcm->capture_cr_val, epcm->capture_cr_val2);
+ dev_dbg(emu->card->dev,
+ "cr_val=0x%x, cr_val2=0x%x\n",
+ epcm->capture_cr_val,
+ epcm->capture_cr_val2);
} else
snd_emu10k1_ptr_write(emu, FXWC, 0, epcm->capture_cr_val);
break;
@@ -857,7 +893,12 @@ static snd_pcm_uframes_t snd_emu10k1_playback_pointer(struct snd_pcm_substream *
ptr -= runtime->buffer_size;
}
#endif
- /* printk("ptr = 0x%x, buffer_size = 0x%x, period_size = 0x%x\n", ptr, runtime->buffer_size, runtime->period_size); */
+ /*
+ dev_dbg(emu->card->dev,
+ "ptr = 0x%lx, buffer_size = 0x%lx, period_size = 0x%lx\n",
+ (long)ptr, (long)runtime->buffer_size,
+ (long)runtime->period_size);
+ */
return ptr;
}
@@ -1091,7 +1132,7 @@ static int snd_emu10k1_playback_open(struct snd_pcm_substream *substream)
struct snd_emu10k1_pcm *epcm;
struct snd_emu10k1_pcm_mixer *mix;
struct snd_pcm_runtime *runtime = substream->runtime;
- int i, err;
+ int i, err, sample_rate;
epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
if (epcm == NULL)
@@ -1110,6 +1151,15 @@ static int snd_emu10k1_playback_open(struct snd_pcm_substream *substream)
kfree(epcm);
return err;
}
+ if (emu->card_capabilities->emu_model && emu->emu1010.internal_clock == 0)
+ sample_rate = 44100;
+ else
+ sample_rate = 48000;
+ err = snd_pcm_hw_rule_noresample(runtime, sample_rate);
+ if (err < 0) {
+ kfree(epcm);
+ return err;
+ }
mix = &emu->pcm_mixer[substream->number];
for (i = 0; i < 4; i++)
mix->send_routing[0][i] = mix->send_routing[1][i] = mix->send_routing[2][i] = i;
@@ -1269,7 +1319,7 @@ static int snd_emu10k1_capture_efx_open(struct snd_pcm_substream *substream)
runtime->hw.channels_min =
runtime->hw.channels_max = 16;
break;
- };
+ }
#endif
#if 0
/* For 96kHz */
@@ -1350,7 +1400,7 @@ static struct snd_pcm_ops snd_emu10k1_efx_playback_ops = {
.page = snd_pcm_sgbuf_ops_page,
};
-int __devinit snd_emu10k1_pcm(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm)
+int snd_emu10k1_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
struct snd_pcm_substream *substream;
@@ -1385,7 +1435,8 @@ int __devinit snd_emu10k1_pcm(struct snd_emu10k1 * emu, int device, struct snd_p
return 0;
}
-int __devinit snd_emu10k1_pcm_multi(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm)
+int snd_emu10k1_pcm_multi(struct snd_emu10k1 *emu, int device,
+ struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
struct snd_pcm_substream *substream;
@@ -1428,7 +1479,8 @@ static struct snd_pcm_ops snd_emu10k1_capture_mic_ops = {
.pointer = snd_emu10k1_capture_pointer,
};
-int __devinit snd_emu10k1_pcm_mic(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm)
+int snd_emu10k1_pcm_mic(struct snd_emu10k1 *emu, int device,
+ struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
int err;
@@ -1546,7 +1598,12 @@ static void snd_emu10k1_fx8010_playback_tram_poke1(unsigned short *dst_left,
unsigned int count,
unsigned int tram_shift)
{
- /* printk("tram_poke1: dst_left = 0x%p, dst_right = 0x%p, src = 0x%p, count = 0x%x\n", dst_left, dst_right, src, count); */
+ /*
+ dev_dbg(emu->card->dev,
+ "tram_poke1: dst_left = 0x%p, dst_right = 0x%p, "
+ "src = 0x%p, count = 0x%x\n",
+ dst_left, dst_right, src, count);
+ */
if ((tram_shift & 1) == 0) {
while (count--) {
*dst_left-- = *src++;
@@ -1623,7 +1680,12 @@ static int snd_emu10k1_fx8010_playback_prepare(struct snd_pcm_substream *substre
struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number];
unsigned int i;
- /* printk("prepare: etram_pages = 0x%p, dma_area = 0x%x, buffer_size = 0x%x (0x%x)\n", emu->fx8010.etram_pages, runtime->dma_area, runtime->buffer_size, runtime->buffer_size << 2); */
+ /*
+ dev_dbg(emu->card->dev, "prepare: etram_pages = 0x%p, dma_area = 0x%x, "
+ "buffer_size = 0x%x (0x%x)\n",
+ emu->fx8010.etram_pages, runtime->dma_area,
+ runtime->buffer_size, runtime->buffer_size << 2);
+ */
memset(&pcm->pcm_rec, 0, sizeof(pcm->pcm_rec));
pcm->pcm_rec.hw_buffer_size = pcm->buffer_size * 2; /* byte size */
pcm->pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
@@ -1713,7 +1775,7 @@ static struct snd_pcm_hardware snd_emu10k1_fx8010_playback =
.buffer_bytes_max = (128*1024),
.period_bytes_min = 1024,
.period_bytes_max = (128*1024),
- .periods_min = 1,
+ .periods_min = 2,
.periods_max = 1024,
.fifo_size = 0,
};
@@ -1760,7 +1822,8 @@ static struct snd_pcm_ops snd_emu10k1_fx8010_playback_ops = {
.ack = snd_emu10k1_fx8010_playback_transfer,
};
-int __devinit snd_emu10k1_pcm_efx(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm)
+int snd_emu10k1_pcm_efx(struct snd_emu10k1 *emu, int device,
+ struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
struct snd_kcontrol *kctl;