#include <sound/core.h>
#include <sound/emu10k1.h>
-#define chip_t emu10k1_t
-
static void snd_emu10k1_pcm_interrupt(emu10k1_t *emu, emu10k1_voice_t *voice)
{
emu10k1_pcm_t *epcm;
{
emu10k1_t *emu = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
+ emu10k1_pcm_t *epcm = runtime->private_data;
int err;
if ((err = snd_emu10k1_pcm_channel_alloc(epcm, params_channels(hw_params))) < 0)
if (runtime->private_data == NULL)
return 0;
- epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
+ epcm = runtime->private_data;
if (epcm->extra) {
snd_emu10k1_voice_free(epcm->emu, epcm->extra);
epcm->extra = NULL;
{
emu10k1_t *emu = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
+ emu10k1_pcm_t *epcm = runtime->private_data;
unsigned int start_addr, end_addr;
start_addr = epcm->start_addr;
{
emu10k1_t *emu = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
+ emu10k1_pcm_t *epcm = runtime->private_data;
int idx;
snd_emu10k1_ptr_write(emu, epcm->capture_bs_reg, 0, 0);
snd_emu10k1_ptr_write(emu, ADCCR, 0, 0);
break;
case CAPTURE_EFX:
- snd_emu10k1_ptr_write(emu, FXWC, 0, 0);
+ if (emu->audigy) {
+ snd_emu10k1_ptr_write(emu, A_FXWC1, 0, 0);
+ snd_emu10k1_ptr_write(emu, A_FXWC2, 0, 0);
+ } else
+ snd_emu10k1_ptr_write(emu, FXWC, 0, 0);
break;
default:
break;
{
emu10k1_t *emu = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
- unsigned long flags;
+ emu10k1_pcm_t *epcm = runtime->private_data;
int result = 0;
// printk("trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n", (int)emu, cmd, substream->ops->pointer(substream));
- spin_lock_irqsave(&emu->reg_lock, flags);
+ spin_lock(&emu->reg_lock);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
snd_emu10k1_playback_invalidate_cache(emu, epcm->extra); /* do we need this? */
result = -EINVAL;
break;
}
- spin_unlock_irqrestore(&emu->reg_lock, flags);
+ spin_unlock(&emu->reg_lock);
return result;
}
{
emu10k1_t *emu = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
- unsigned long flags;
+ emu10k1_pcm_t *epcm = runtime->private_data;
int result = 0;
// printk("trigger - emu10k1 = %p, cmd = %i, pointer = %i\n", emu, cmd, substream->ops->pointer(substream));
- spin_lock_irqsave(&emu->reg_lock, flags);
+ spin_lock(&emu->reg_lock);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
outl(epcm->capture_ipr, emu->port + IPR);
snd_emu10k1_ptr_write(emu, ADCCR, 0, epcm->capture_cr_val);
break;
case CAPTURE_EFX:
- snd_emu10k1_ptr_write(emu, FXWC, 0, epcm->capture_cr_val);
+ 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);
+ } else
+ snd_emu10k1_ptr_write(emu, FXWC, 0, epcm->capture_cr_val);
break;
default:
break;
snd_emu10k1_ptr_write(emu, ADCCR, 0, 0);
break;
case CAPTURE_EFX:
- snd_emu10k1_ptr_write(emu, FXWC, 0, 0);
+ if (emu->audigy) {
+ snd_emu10k1_ptr_write(emu, A_FXWC1, 0, 0);
+ snd_emu10k1_ptr_write(emu, A_FXWC2, 0, 0);
+ } else
+ snd_emu10k1_ptr_write(emu, FXWC, 0, 0);
break;
default:
break;
default:
result = -EINVAL;
}
- spin_unlock_irqrestore(&emu->reg_lock, flags);
+ spin_unlock(&emu->reg_lock);
return result;
}
{
emu10k1_t *emu = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
+ emu10k1_pcm_t *epcm = runtime->private_data;
unsigned int ptr;
if (!epcm->running)
{
emu10k1_t *emu = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
+ emu10k1_pcm_t *epcm = runtime->private_data;
unsigned int ptr;
if (!epcm->running)
static void snd_emu10k1_pcm_free_substream(snd_pcm_runtime_t *runtime)
{
- emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return);
+ emu10k1_pcm_t *epcm = runtime->private_data;
if (epcm)
- snd_magic_kfree(epcm);
+ kfree(epcm);
}
static int snd_emu10k1_playback_open(snd_pcm_substream_t * substream)
snd_pcm_runtime_t *runtime = substream->runtime;
int i, err;
- epcm = snd_magic_kcalloc(emu10k1_pcm_t, 0, GFP_KERNEL);
+ epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
if (epcm == NULL)
return -ENOMEM;
epcm->emu = emu;
runtime->private_free = snd_emu10k1_pcm_free_substream;
runtime->hw = snd_emu10k1_playback;
if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) {
- snd_magic_kfree(epcm);
+ kfree(epcm);
return err;
}
if ((err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX)) < 0) {
- snd_magic_kfree(epcm);
+ kfree(epcm);
return err;
}
mix = &emu->pcm_mixer[substream->number];
snd_pcm_runtime_t *runtime = substream->runtime;
emu10k1_pcm_t *epcm;
- epcm = snd_magic_kcalloc(emu10k1_pcm_t, 0, GFP_KERNEL);
+ epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
if (epcm == NULL)
return -ENOMEM;
epcm->emu = emu;
runtime->hw = snd_emu10k1_capture;
emu->capture_interrupt = snd_emu10k1_pcm_ac97adc_interrupt;
emu->pcm_capture_substream = substream;
- snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_capture_period_sizes);
+ snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_capture_period_sizes);
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_capture_rates);
return 0;
}
emu10k1_pcm_t *epcm;
snd_pcm_runtime_t *runtime = substream->runtime;
- epcm = snd_magic_kcalloc(emu10k1_pcm_t, 0, GFP_KERNEL);
+ epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
if (epcm == NULL)
return -ENOMEM;
epcm->emu = emu;
runtime->hw.channels_min = 1;
emu->capture_mic_interrupt = snd_emu10k1_pcm_ac97mic_interrupt;
emu->pcm_capture_mic_substream = substream;
- snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_capture_period_sizes);
+ snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_capture_period_sizes);
return 0;
}
emu10k1_t *emu = snd_pcm_substream_chip(substream);
emu10k1_pcm_t *epcm;
snd_pcm_runtime_t *runtime = substream->runtime;
- unsigned long flags;
int nefx = emu->audigy ? 64 : 32;
int idx;
- epcm = snd_magic_kcalloc(emu10k1_pcm_t, 0, GFP_KERNEL);
+ epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
if (epcm == NULL)
return -ENOMEM;
epcm->emu = emu;
runtime->hw = snd_emu10k1_capture;
runtime->hw.rates = SNDRV_PCM_RATE_48000;
runtime->hw.rate_min = runtime->hw.rate_max = 48000;
- spin_lock_irqsave(&emu->reg_lock, flags);
+ spin_lock_irq(&emu->reg_lock);
runtime->hw.channels_min = runtime->hw.channels_max = 0;
for (idx = 0; idx < nefx; idx++) {
if (emu->efx_voices_mask[idx/32] & (1 << (idx%32))) {
}
epcm->capture_cr_val = emu->efx_voices_mask[0];
epcm->capture_cr_val2 = emu->efx_voices_mask[1];
- spin_unlock_irqrestore(&emu->reg_lock, flags);
+ spin_unlock_irq(&emu->reg_lock);
emu->capture_efx_interrupt = snd_emu10k1_pcm_efx_interrupt;
emu->pcm_capture_efx_substream = substream;
- snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_capture_period_sizes);
+ snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_capture_period_sizes);
return 0;
}
static void snd_emu10k1_pcm_free(snd_pcm_t *pcm)
{
- emu10k1_t *emu = snd_magic_cast(emu10k1_t, pcm->private_data, return);
+ emu10k1_t *emu = pcm->private_data;
emu->pcm = NULL;
snd_pcm_lib_preallocate_free_for_all(pcm);
}
static void snd_emu10k1_pcm_mic_free(snd_pcm_t *pcm)
{
- emu10k1_t *emu = snd_magic_cast(emu10k1_t, pcm->private_data, return);
+ emu10k1_t *emu = pcm->private_data;
emu->pcm_mic = NULL;
snd_pcm_lib_preallocate_free_for_all(pcm);
}
static int snd_emu10k1_pcm_efx_voices_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
- unsigned long flags;
int nefx = emu->audigy ? 64 : 32;
int idx;
- spin_lock_irqsave(&emu->reg_lock, flags);
+ spin_lock_irq(&emu->reg_lock);
for (idx = 0; idx < nefx; idx++)
ucontrol->value.integer.value[idx] = (emu->efx_voices_mask[idx / 32] & (1 << (idx % 32))) ? 1 : 0;
- spin_unlock_irqrestore(&emu->reg_lock, flags);
+ spin_unlock_irq(&emu->reg_lock);
return 0;
}
static int snd_emu10k1_pcm_efx_voices_mask_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
- unsigned long flags;
unsigned int nval[2], bits;
int nefx = emu->audigy ? 64 : 32;
int change, idx;
}
if (bits != 1 && bits != 2 && bits != 4 && bits != 8)
return -EINVAL;
- spin_lock_irqsave(&emu->reg_lock, flags);
+ spin_lock_irq(&emu->reg_lock);
change = (nval[0] != emu->efx_voices_mask[0]) ||
(nval[1] != emu->efx_voices_mask[1]);
emu->efx_voices_mask[0] = nval[0];
emu->efx_voices_mask[1] = nval[1];
- spin_unlock_irqrestore(&emu->reg_lock, flags);
+ spin_unlock_irq(&emu->reg_lock);
return change;
}
.pointer = snd_emu10k1_capture_pointer,
};
+
+/* EFX playback */
+
+#define INITIAL_TRAM_SHIFT 14
+#define INITIAL_TRAM_POS(size) ((((size) / 2) - INITIAL_TRAM_SHIFT) - 1)
+
+static void snd_emu10k1_fx8010_playback_irq(emu10k1_t *emu, void *private_data)
+{
+ snd_pcm_substream_t *substream = private_data;
+ snd_pcm_period_elapsed(substream);
+}
+
+static void snd_emu10k1_fx8010_playback_tram_poke1(unsigned short *dst_left,
+ unsigned short *dst_right,
+ unsigned short *src,
+ 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);
+ if ((tram_shift & 1) == 0) {
+ while (count--) {
+ *dst_left-- = *src++;
+ *dst_right-- = *src++;
+ }
+ } else {
+ while (count--) {
+ *dst_right-- = *src++;
+ *dst_left-- = *src++;
+ }
+ }
+}
+
+static void fx8010_pb_trans_copy(snd_pcm_substream_t *substream,
+ snd_pcm_indirect_t *rec, size_t bytes)
+{
+ emu10k1_t *emu = snd_pcm_substream_chip(substream);
+ snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+ unsigned int tram_size = pcm->buffer_size;
+ unsigned short *src = (unsigned short *)(substream->runtime->dma_area + rec->sw_data);
+ unsigned int frames = bytes >> 2, count;
+ unsigned int tram_pos = pcm->tram_pos;
+ unsigned int tram_shift = pcm->tram_shift;
+
+ while (frames > tram_pos) {
+ count = tram_pos + 1;
+ snd_emu10k1_fx8010_playback_tram_poke1((unsigned short *)emu->fx8010.etram_pages.area + tram_pos,
+ (unsigned short *)emu->fx8010.etram_pages.area + tram_pos + tram_size / 2,
+ src, count, tram_shift);
+ src += count * 2;
+ frames -= count;
+ tram_pos = (tram_size / 2) - 1;
+ tram_shift++;
+ }
+ snd_emu10k1_fx8010_playback_tram_poke1((unsigned short *)emu->fx8010.etram_pages.area + tram_pos,
+ (unsigned short *)emu->fx8010.etram_pages.area + tram_pos + tram_size / 2,
+ src, frames, tram_shift++);
+ tram_pos -= frames;
+ pcm->tram_pos = tram_pos;
+ pcm->tram_shift = tram_shift;
+}
+
+static int snd_emu10k1_fx8010_playback_transfer(snd_pcm_substream_t *substream)
+{
+ emu10k1_t *emu = snd_pcm_substream_chip(substream);
+ snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+
+ snd_pcm_indirect_playback_transfer(substream, &pcm->pcm_rec, fx8010_pb_trans_copy);
+ return 0;
+}
+
+static int snd_emu10k1_fx8010_playback_hw_params(snd_pcm_substream_t * substream,
+ snd_pcm_hw_params_t * hw_params)
+{
+ return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
+}
+
+static int snd_emu10k1_fx8010_playback_hw_free(snd_pcm_substream_t * substream)
+{
+ emu10k1_t *emu = snd_pcm_substream_chip(substream);
+ snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+ unsigned int i;
+
+ for (i = 0; i < pcm->channels; i++)
+ snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + 0x80 + pcm->etram[i], 0, 0);
+ snd_pcm_lib_free_pages(substream);
+ return 0;
+}
+
+static int snd_emu10k1_fx8010_playback_prepare(snd_pcm_substream_t * substream)
+{
+ emu10k1_t *emu = snd_pcm_substream_chip(substream);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ snd_emu10k1_fx8010_pcm_t *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);
+ 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);
+ pcm->tram_pos = INITIAL_TRAM_POS(pcm->buffer_size);
+ pcm->tram_shift = 0;
+ snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_running, 0, 0); /* reset */
+ snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 0); /* reset */
+ snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_size, 0, runtime->buffer_size);
+ snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_ptr, 0, 0); /* reset ptr number */
+ snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_count, 0, runtime->period_size);
+ snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_tmpcount, 0, runtime->period_size);
+ for (i = 0; i < pcm->channels; i++)
+ snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + 0x80 + pcm->etram[i], 0, (TANKMEMADDRREG_READ|TANKMEMADDRREG_ALIGN) + i * (runtime->buffer_size / pcm->channels));
+ return 0;
+}
+
+static int snd_emu10k1_fx8010_playback_trigger(snd_pcm_substream_t * substream, int cmd)
+{
+ emu10k1_t *emu = snd_pcm_substream_chip(substream);
+ snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+ int result = 0;
+
+ spin_lock(&emu->reg_lock);
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ /* follow thru */
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+#ifdef EMU10K1_SET_AC3_IEC958
+ {
+ int i;
+ for (i = 0; i < 3; i++) {
+ unsigned int bits;
+ bits = SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
+ SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS |
+ 0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT | SPCS_NOTAUDIODATA;
+ snd_emu10k1_ptr_write(emu, SPCS0 + i, 0, bits);
+ }
+ }
+#endif
+ result = snd_emu10k1_fx8010_register_irq_handler(emu, snd_emu10k1_fx8010_playback_irq, pcm->gpr_running, substream, &pcm->irq);
+ if (result < 0)
+ goto __err;
+ snd_emu10k1_fx8010_playback_transfer(substream); /* roll the ball */
+ snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 1);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ snd_emu10k1_fx8010_unregister_irq_handler(emu, pcm->irq); pcm->irq = NULL;
+ snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 0);
+ pcm->tram_pos = INITIAL_TRAM_POS(pcm->buffer_size);
+ pcm->tram_shift = 0;
+ break;
+ default:
+ result = -EINVAL;
+ break;
+ }
+ __err:
+ spin_unlock(&emu->reg_lock);
+ return result;
+}
+
+static snd_pcm_uframes_t snd_emu10k1_fx8010_playback_pointer(snd_pcm_substream_t * substream)
+{
+ emu10k1_t *emu = snd_pcm_substream_chip(substream);
+ snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+ size_t ptr; /* byte pointer */
+
+ if (!snd_emu10k1_ptr_read(emu, emu->gpr_base + pcm->gpr_trigger, 0))
+ return 0;
+ ptr = snd_emu10k1_ptr_read(emu, emu->gpr_base + pcm->gpr_ptr, 0) << 2;
+ return snd_pcm_indirect_playback_pointer(substream, &pcm->pcm_rec, ptr);
+}
+
+static snd_pcm_hardware_t snd_emu10k1_fx8010_playback =
+{
+ .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+ /* SNDRV_PCM_INFO_MMAP_VALID | */ SNDRV_PCM_INFO_PAUSE),
+ .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_48000,
+ .rate_min = 48000,
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 1,
+ .buffer_bytes_max = (128*1024),
+ .period_bytes_min = 1024,
+ .period_bytes_max = (128*1024),
+ .periods_min = 1,
+ .periods_max = 1024,
+ .fifo_size = 0,
+};
+
+static int snd_emu10k1_fx8010_playback_open(snd_pcm_substream_t * substream)
+{
+ emu10k1_t *emu = snd_pcm_substream_chip(substream);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+
+ runtime->hw = snd_emu10k1_fx8010_playback;
+ runtime->hw.channels_min = runtime->hw.channels_max = pcm->channels;
+ runtime->hw.period_bytes_max = (pcm->buffer_size * 2) / 2;
+ spin_lock_irq(&emu->reg_lock);
+ if (pcm->valid == 0) {
+ spin_unlock_irq(&emu->reg_lock);
+ return -ENODEV;
+ }
+ pcm->opened = 1;
+ spin_unlock_irq(&emu->reg_lock);
+ return 0;
+}
+
+static int snd_emu10k1_fx8010_playback_close(snd_pcm_substream_t * substream)
+{
+ emu10k1_t *emu = snd_pcm_substream_chip(substream);
+ snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+
+ spin_lock_irq(&emu->reg_lock);
+ pcm->opened = 0;
+ spin_unlock_irq(&emu->reg_lock);
+ return 0;
+}
+
+static snd_pcm_ops_t snd_emu10k1_fx8010_playback_ops = {
+ .open = snd_emu10k1_fx8010_playback_open,
+ .close = snd_emu10k1_fx8010_playback_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_emu10k1_fx8010_playback_hw_params,
+ .hw_free = snd_emu10k1_fx8010_playback_hw_free,
+ .prepare = snd_emu10k1_fx8010_playback_prepare,
+ .trigger = snd_emu10k1_fx8010_playback_trigger,
+ .pointer = snd_emu10k1_fx8010_playback_pointer,
+ .ack = snd_emu10k1_fx8010_playback_transfer,
+};
+
static void snd_emu10k1_pcm_efx_free(snd_pcm_t *pcm)
{
- emu10k1_t *emu = snd_magic_cast(emu10k1_t, pcm->private_data, return);
+ emu10k1_t *emu = pcm->private_data;
emu->pcm_efx = NULL;
snd_pcm_lib_preallocate_free_for_all(pcm);
}
if (rpcm)
*rpcm = NULL;
- if ((err = snd_pcm_new(emu->card, "emu10k1 efx", device, 0, 1, &pcm)) < 0)
+ if ((err = snd_pcm_new(emu->card, "emu10k1 efx", device, 8, 1, &pcm)) < 0)
return err;
pcm->private_data = emu;
pcm->private_free = snd_emu10k1_pcm_efx_free;
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1_fx8010_playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_efx_ops);
pcm->info_flags = 0;