Commit 74454601 authored by Jaroslav Kysela's avatar Jaroslav Kysela

ALSA CVS update

CS46xx driver,EMU10K1/EMU10K2 driver,PCM Midlevel
Clean up of indirect PCM data transfer with helper functions.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent bd698bf5
......@@ -24,6 +24,7 @@
*/
#include "pcm.h"
#include "pcm-indirect.h"
#include "rawmidi.h"
#include "ac97_codec.h"
#include "cs46xx_dsp_spos.h"
......@@ -1650,14 +1651,7 @@ typedef struct _snd_cs46xx_pcm_t {
unsigned int ctl;
unsigned int shift; /* Shift count to trasform frames in bytes */
unsigned int sw_bufsize;
unsigned int sw_data; /* Offset to next dst (or src) in sw ring buffer */
unsigned int sw_io;
int sw_ready; /* Bytes ready to be transferred to/from hw */
unsigned int hw_data; /* Offset to next dst (or src) in hw ring buffer */
unsigned int hw_io; /* Ring buffer hw pointer */
int hw_ready; /* Bytes ready for play (or captured) in hw ring buffer */
size_t appl_ptr; /* Last seen appl_ptr */
snd_pcm_indirect_t pcm_rec;
snd_pcm_substream_t *substream;
pcm_channel_descriptor_t * pcm_channel;
......@@ -1695,14 +1689,7 @@ struct _snd_cs46xx {
unsigned int ctl;
unsigned int shift; /* Shift count to trasform frames in bytes */
unsigned int sw_bufsize;
unsigned int sw_data; /* Offset to next dst (or src) in sw ring buffer */
unsigned int sw_io;
int sw_ready; /* Bytes ready to be transferred to/from hw */
unsigned int hw_data; /* Offset to next dst (or src) in hw ring buffer */
unsigned int hw_io; /* Ring buffer hw pointer */
int hw_ready; /* Bytes ready for play (or captured) in hw ring buffer */
size_t appl_ptr; /* Last seen appl_ptr */
snd_pcm_indirect_t pcm_rec;
snd_pcm_substream_t *substream;
} capt;
......
......@@ -30,6 +30,7 @@
#include <sound/hwdep.h>
#include <sound/ac97_codec.h>
#include <sound/util_mem.h>
#include <sound/pcm-indirect.h>
#include <linux/interrupt.h>
#include <asm/io.h>
......@@ -887,10 +888,7 @@ typedef struct {
unsigned char gpr_trigger; /* GPR containing trigger (activate) information (host) */
unsigned char gpr_running; /* GPR containing info if PCM is running (FX8010) */
unsigned char etram[32]; /* external TRAM address & data */
unsigned int sw_data, hw_data;
unsigned int sw_io, hw_io;
unsigned int sw_ready, hw_ready;
unsigned int appl_ptr;
snd_pcm_indirect_t pcm_rec;
unsigned int tram_pos;
unsigned int tram_shift;
snd_emu10k1_fx8010_irq_t *irq;
......
/*
* Helper functions for indirect PCM data transfer
*
* Copyright (c) by Takashi Iwai <tiwai@suse.de>
* Jaroslav Kysela <perex@suse.cz>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __SOUND_PCM_INDIRECT_H
#define __SOUND_PCM_INDIRECT_H
#include <sound/pcm.h>
typedef struct sndrv_pcm_indirect {
unsigned int hw_buffer_size; /* Byte size of hardware buffer */
unsigned int hw_queue_size; /* Max queue size of hw buffer (0 = buffer size) */
unsigned int hw_data; /* Offset to next dst (or src) in hw ring buffer */
unsigned int hw_io; /* Ring buffer hw pointer */
int hw_ready; /* Bytes ready for play (or captured) in hw ring buffer */
unsigned int sw_buffer_size; /* Byte size of software buffer */
unsigned int sw_data; /* Offset to next dst (or src) in sw ring buffer */
unsigned int sw_io; /* Current software pointer in bytes */
int sw_ready; /* Bytes ready to be transferred to/from hw */
size_t appl_ptr; /* Last seen appl_ptr */
} snd_pcm_indirect_t;
typedef void (*snd_pcm_indirect_copy_t)(snd_pcm_substream_t *substream,
snd_pcm_indirect_t *rec, size_t bytes);
/*
* helper function for playback ack callback
*/
static inline void
snd_pcm_indirect_playback_transfer(snd_pcm_substream_t *substream,
snd_pcm_indirect_t *rec,
snd_pcm_indirect_copy_t copy)
{
snd_pcm_runtime_t *runtime = substream->runtime;
snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr;
snd_pcm_sframes_t diff = appl_ptr - rec->appl_ptr;
snd_pcm_uframes_t qsize;
if (diff) {
if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
diff += runtime->boundary;
rec->sw_ready += frames_to_bytes(runtime, diff);
rec->appl_ptr = appl_ptr;
}
qsize = rec->hw_queue_size ? rec->hw_queue_size : rec->hw_buffer_size;
while (rec->hw_ready < qsize && rec->sw_ready > 0) {
size_t hw_to_end = rec->hw_buffer_size - rec->hw_data;
size_t sw_to_end = rec->sw_buffer_size - rec->sw_data;
size_t bytes = rec->hw_buffer_size - rec->hw_ready;
if (rec->sw_ready < (int)bytes)
bytes = rec->sw_ready;
if (hw_to_end < bytes)
bytes = hw_to_end;
if (sw_to_end < bytes)
bytes = sw_to_end;
if (! bytes)
break;
copy(substream, rec, bytes);
rec->hw_data += bytes;
if ((int)rec->hw_data == rec->hw_buffer_size)
rec->hw_data = 0;
rec->sw_data += bytes;
if (rec->sw_data == rec->sw_buffer_size)
rec->sw_data = 0;
rec->hw_ready += bytes;
rec->sw_ready -= bytes;
}
}
/*
* helper function for playback pointer callback
* ptr = current byte pointer
*/
static inline snd_pcm_uframes_t
snd_pcm_indirect_playback_pointer(snd_pcm_substream_t *substream,
snd_pcm_indirect_t *rec, size_t ptr)
{
ssize_t bytes = ptr - rec->hw_io;
if (bytes < 0)
bytes += rec->hw_buffer_size;
rec->hw_io = ptr;
rec->hw_ready -= bytes;
rec->sw_io += bytes;
if (rec->sw_io >= rec->sw_buffer_size)
rec->sw_io -= rec->sw_buffer_size;
if (substream->ops->ack)
substream->ops->ack(substream);
return bytes_to_frames(substream->runtime, rec->sw_io);
}
/*
* helper function for capture ack callback
*/
static inline void
snd_pcm_indirect_capture_transfer(snd_pcm_substream_t *substream,
snd_pcm_indirect_t *rec,
snd_pcm_indirect_copy_t copy)
{
snd_pcm_runtime_t *runtime = substream->runtime;
snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr;
snd_pcm_sframes_t diff = appl_ptr - rec->appl_ptr;
if (diff) {
if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
diff += runtime->boundary;
rec->sw_ready -= frames_to_bytes(runtime, diff);
rec->appl_ptr = appl_ptr;
}
while (rec->hw_ready > 0 &&
rec->sw_ready < (int)rec->sw_buffer_size) {
size_t hw_to_end = rec->hw_buffer_size - rec->hw_data;
size_t sw_to_end = rec->sw_buffer_size - rec->sw_data;
size_t bytes = rec->sw_buffer_size - rec->sw_ready;
if (rec->hw_ready < (int)bytes)
bytes = rec->hw_ready;
if (hw_to_end < bytes)
bytes = hw_to_end;
if (sw_to_end < bytes)
bytes = sw_to_end;
if (! bytes)
break;
copy(substream, rec, bytes);
rec->hw_data += bytes;
if ((int)rec->hw_data == rec->hw_buffer_size)
rec->hw_data = 0;
rec->sw_data += bytes;
if (rec->sw_data == rec->sw_buffer_size)
rec->sw_data = 0;
rec->hw_ready -= bytes;
rec->sw_ready += bytes;
}
}
/*
* helper function for capture pointer callback,
* ptr = current byte pointer
*/
static inline snd_pcm_uframes_t
snd_pcm_indirect_capture_pointer(snd_pcm_substream_t *substream,
snd_pcm_indirect_t *rec, size_t ptr)
{
ssize_t bytes = ptr - rec->hw_io;
if (bytes < 0)
bytes += rec->hw_buffer_size;
rec->hw_io = ptr;
rec->hw_ready += bytes;
rec->sw_io += bytes;
if (rec->sw_io >= rec->sw_buffer_size)
rec->sw_io -= rec->sw_buffer_size;
if (substream->ops->ack)
substream->ops->ack(substream);
return bytes_to_frames(substream->runtime, rec->sw_io);
}
#endif /* __SOUND_PCM_INDIRECT_H */
......@@ -688,84 +688,35 @@ static void snd_cs46xx_set_capture_sample_rate(cs46xx_t *chip, unsigned int rate
* PCM part
*/
static void snd_cs46xx_pb_trans_copy(snd_pcm_substream_t *substream,
snd_pcm_indirect_t *rec, size_t bytes)
{
snd_pcm_runtime_t *runtime = substream->runtime;
cs46xx_pcm_t * cpcm = runtime->private_data;
memcpy(cpcm->hw_buf.area + rec->hw_data, runtime->dma_area + rec->sw_data, bytes);
}
static int snd_cs46xx_playback_transfer(snd_pcm_substream_t *substream)
{
/* cs46xx_t *chip = snd_pcm_substream_chip(substream); */
snd_pcm_runtime_t *runtime = substream->runtime;
cs46xx_pcm_t * cpcm = runtime->private_data;
snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr;
snd_pcm_sframes_t diff = appl_ptr - cpcm->appl_ptr;
int buffer_size = runtime->period_size * CS46XX_FRAGS << cpcm->shift;
if (diff) {
if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
diff += runtime->boundary;
cpcm->sw_ready += diff * (1 << cpcm->shift);
cpcm->appl_ptr = appl_ptr;
}
while (cpcm->hw_ready < buffer_size &&
cpcm->sw_ready > 0) {
size_t hw_to_end = buffer_size - cpcm->hw_data;
size_t sw_to_end = cpcm->sw_bufsize - cpcm->sw_data;
size_t bytes = buffer_size - cpcm->hw_ready;
if (cpcm->sw_ready < (int)bytes)
bytes = cpcm->sw_ready;
if (hw_to_end < bytes)
bytes = hw_to_end;
if (sw_to_end < bytes)
bytes = sw_to_end;
memcpy(cpcm->hw_buf.area + cpcm->hw_data,
runtime->dma_area + cpcm->sw_data,
bytes);
cpcm->hw_data += bytes;
if ((int)cpcm->hw_data == buffer_size)
cpcm->hw_data = 0;
cpcm->sw_data += bytes;
if (cpcm->sw_data == cpcm->sw_bufsize)
cpcm->sw_data = 0;
cpcm->hw_ready += bytes;
cpcm->sw_ready -= bytes;
}
snd_pcm_indirect_playback_transfer(substream, &cpcm->pcm_rec, snd_cs46xx_pb_trans_copy);
return 0;
}
static int snd_cs46xx_capture_transfer(snd_pcm_substream_t *substream)
static void snd_cs46xx_cp_trans_copy(snd_pcm_substream_t *substream,
snd_pcm_indirect_t *rec, size_t bytes)
{
cs46xx_t *chip = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr;
snd_pcm_sframes_t diff = appl_ptr - chip->capt.appl_ptr;
int buffer_size = runtime->period_size * CS46XX_FRAGS << chip->capt.shift;
if (diff) {
if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
diff += runtime->boundary;
chip->capt.sw_ready -= diff * (1 << chip->capt.shift);
chip->capt.appl_ptr = appl_ptr;
}
while (chip->capt.hw_ready > 0 &&
chip->capt.sw_ready < (int)chip->capt.sw_bufsize) {
size_t hw_to_end = buffer_size - chip->capt.hw_data;
size_t sw_to_end = chip->capt.sw_bufsize - chip->capt.sw_data;
size_t bytes = chip->capt.sw_bufsize - chip->capt.sw_ready;
if (chip->capt.hw_ready < (int)bytes)
bytes = chip->capt.hw_ready;
if (hw_to_end < bytes)
bytes = hw_to_end;
if (sw_to_end < bytes)
bytes = sw_to_end;
memcpy(runtime->dma_area + chip->capt.sw_data,
chip->capt.hw_buf.area + chip->capt.hw_data,
bytes);
chip->capt.hw_data += bytes;
if ((int)chip->capt.hw_data == buffer_size)
chip->capt.hw_data = 0;
chip->capt.sw_data += bytes;
if (chip->capt.sw_data == chip->capt.sw_bufsize)
chip->capt.sw_data = 0;
chip->capt.hw_ready -= bytes;
chip->capt.sw_ready += bytes;
}
memcpy(runtime->dma_area + rec->sw_data,
chip->capt.hw_buf.area + rec->hw_data, bytes);
}
static int snd_cs46xx_capture_transfer(snd_pcm_substream_t *substream)
{
cs46xx_t *chip = snd_pcm_substream_chip(substream);
snd_pcm_indirect_capture_transfer(substream, &chip->capt.pcm_rec, snd_cs46xx_cp_trans_copy);
return 0;
}
......@@ -790,8 +741,6 @@ static snd_pcm_uframes_t snd_cs46xx_playback_indirect_pointer(snd_pcm_substream_
cs46xx_t *chip = snd_pcm_substream_chip(substream);
size_t ptr;
cs46xx_pcm_t *cpcm = substream->runtime->private_data;
ssize_t bytes;
int buffer_size = substream->runtime->period_size * CS46XX_FRAGS << cpcm->shift;
#ifdef CONFIG_SND_CS46XX_NEW_DSP
snd_assert (cpcm->pcm_channel,return -ENXIO);
......@@ -800,18 +749,7 @@ static snd_pcm_uframes_t snd_cs46xx_playback_indirect_pointer(snd_pcm_substream_
ptr = snd_cs46xx_peek(chip, BA1_PBA);
#endif
ptr -= cpcm->hw_buf.addr;
bytes = ptr - cpcm->hw_io;
if (bytes < 0)
bytes += buffer_size;
cpcm->hw_io = ptr;
cpcm->hw_ready -= bytes;
cpcm->sw_io += bytes;
if (cpcm->sw_io >= cpcm->sw_bufsize)
cpcm->sw_io -= cpcm->sw_bufsize;
snd_cs46xx_playback_transfer(substream);
return cpcm->sw_io >> cpcm->shift;
return snd_pcm_indirect_playback_pointer(substream, &cpcm->pcm_rec, ptr);
}
static snd_pcm_uframes_t snd_cs46xx_capture_direct_pointer(snd_pcm_substream_t * substream)
......@@ -825,18 +763,7 @@ static snd_pcm_uframes_t snd_cs46xx_capture_indirect_pointer(snd_pcm_substream_t
{
cs46xx_t *chip = snd_pcm_substream_chip(substream);
size_t ptr = snd_cs46xx_peek(chip, BA1_CBA) - chip->capt.hw_buf.addr;
ssize_t bytes = ptr - chip->capt.hw_io;
int buffer_size = substream->runtime->period_size * CS46XX_FRAGS << chip->capt.shift;
if (bytes < 0)
bytes += buffer_size;
chip->capt.hw_io = ptr;
chip->capt.hw_ready += bytes;
chip->capt.sw_io += bytes;
if (chip->capt.sw_io >= chip->capt.sw_bufsize)
chip->capt.sw_io -= chip->capt.sw_bufsize;
snd_cs46xx_capture_transfer(substream);
return chip->capt.sw_io >> chip->capt.shift;
return snd_pcm_indirect_capture_pointer(substream, &chip->capt.pcm_rec, ptr);
}
static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
......@@ -1143,10 +1070,9 @@ static int snd_cs46xx_playback_prepare(snd_pcm_substream_t * substream)
pfie |= 0x00004000;
}
cpcm->sw_bufsize = snd_pcm_lib_buffer_bytes(substream);
cpcm->sw_data = cpcm->sw_io = cpcm->sw_ready = 0;
cpcm->hw_data = cpcm->hw_io = cpcm->hw_ready = 0;
cpcm->appl_ptr = 0;
memset(&cpcm->pcm_rec, 0, sizeof(cpcm->pcm_rec));
cpcm->pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
cpcm->pcm_rec.hw_buffer_size = runtime->period_size * CS46XX_FRAGS << cpcm->shift;
#ifdef CONFIG_SND_CS46XX_NEW_DSP
......@@ -1223,10 +1149,9 @@ static int snd_cs46xx_capture_prepare(snd_pcm_substream_t * substream)
snd_cs46xx_poke(chip, BA1_CBA, chip->capt.hw_buf.addr);
chip->capt.shift = 2;
chip->capt.sw_bufsize = snd_pcm_lib_buffer_bytes(substream);
chip->capt.sw_data = chip->capt.sw_io = chip->capt.sw_ready = 0;
chip->capt.hw_data = chip->capt.hw_io = chip->capt.hw_ready = 0;
chip->capt.appl_ptr = 0;
memset(&chip->capt.pcm_rec, 0, sizeof(chip->capt.pcm_rec));
chip->capt.pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
chip->capt.pcm_rec.hw_buffer_size = runtime->period_size * CS46XX_FRAGS << 2;
snd_cs46xx_set_capture_sample_rate(chip, runtime->rate);
return 0;
......
......@@ -1167,70 +1167,41 @@ static void snd_emu10k1_fx8010_playback_tram_poke1(unsigned short *dst_left,
}
}
static void snd_emu10k1_fx8010_playback_tram_poke(emu10k1_t *emu,
unsigned int *tram_pos,
unsigned int *tram_shift,
unsigned int tram_size,
unsigned short *src,
unsigned int frames)
static void fx8010_pb_trans_copy(snd_pcm_substream_t *substream,
snd_pcm_indirect_t *rec, size_t bytes)
{
unsigned int count;
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);
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)++;
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;
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_pcm_runtime_t *runtime = substream->runtime;
snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr;
snd_pcm_sframes_t diff = appl_ptr - pcm->appl_ptr;
snd_pcm_uframes_t buffer_size = pcm->buffer_size / 2;
if (diff) {
if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
diff += runtime->boundary;
pcm->sw_ready += diff;
pcm->appl_ptr = appl_ptr;
}
while (pcm->hw_ready < buffer_size &&
pcm->sw_ready > 0) {
size_t hw_to_end = buffer_size - pcm->hw_data;
size_t sw_to_end = (runtime->buffer_size << 2) - pcm->sw_data;
size_t tframes = buffer_size - pcm->hw_ready;
if (pcm->sw_ready < tframes)
tframes = pcm->sw_ready;
if (hw_to_end < tframes)
tframes = hw_to_end;
if (sw_to_end < tframes)
tframes = sw_to_end;
snd_emu10k1_fx8010_playback_tram_poke(emu, &pcm->tram_pos, &pcm->tram_shift,
pcm->buffer_size,
(unsigned short *)(runtime->dma_area + (pcm->sw_data << 2)),
tframes);
pcm->hw_data += tframes;
if (pcm->hw_data == buffer_size)
pcm->hw_data = 0;
pcm->sw_data += tframes;
if (pcm->sw_data == runtime->buffer_size)
pcm->sw_data = 0;
pcm->hw_ready += tframes;
pcm->sw_ready -= tframes;
}
snd_pcm_indirect_playback_transfer(substream, &pcm->pcm_rec, fx8010_pb_trans_copy);
return 0;
}
......@@ -1260,11 +1231,11 @@ static int snd_emu10k1_fx8010_playback_prepare(snd_pcm_substream_t * substream)
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);
pcm->sw_data = pcm->sw_io = pcm->sw_ready = 0;
pcm->hw_data = pcm->hw_io = pcm->hw_ready = 0;
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;
pcm->appl_ptr = 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);
......@@ -1325,24 +1296,13 @@ static int snd_emu10k1_fx8010_playback_trigger(snd_pcm_substream_t * substream,
static snd_pcm_uframes_t snd_emu10k1_fx8010_playback_pointer(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];
size_t ptr;
snd_pcm_sframes_t frames;
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);
frames = ptr - pcm->hw_io;
if (frames < 0)
frames += runtime->buffer_size;
pcm->hw_io = ptr;
pcm->hw_ready -= frames;
pcm->sw_io += frames;
if (pcm->sw_io >= runtime->buffer_size)
pcm->sw_io -= runtime->buffer_size;
snd_emu10k1_fx8010_playback_transfer(substream);
return pcm->sw_io;
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 =
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment