summaryrefslogtreecommitdiff
path: root/sound/isa/sb/emu8000_pcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/isa/sb/emu8000_pcm.c')
-rw-r--r--sound/isa/sb/emu8000_pcm.c126
1 files changed, 41 insertions, 85 deletions
diff --git a/sound/isa/sb/emu8000_pcm.c b/sound/isa/sb/emu8000_pcm.c
index c8afc4347c54..656a655d618d 100644
--- a/sound/isa/sb/emu8000_pcm.c
+++ b/sound/isa/sb/emu8000_pcm.c
@@ -182,30 +182,32 @@ static inline int emu8k_get_curpos(struct snd_emu8k_pcm *rec, int ch)
*/
static void emu8k_pcm_timer_func(struct timer_list *t)
{
- struct snd_emu8k_pcm *rec = from_timer(rec, t, timer);
+ struct snd_emu8k_pcm *rec = timer_container_of(rec, t, timer);
int ptr, delta;
+ bool period_elapsed = false;
+
+ scoped_guard(spinlock, &rec->timer_lock) {
+ /* update the current pointer */
+ ptr = emu8k_get_curpos(rec, 0);
+ if (ptr < rec->last_ptr)
+ delta = ptr + rec->buf_size - rec->last_ptr;
+ else
+ delta = ptr - rec->last_ptr;
+ rec->period_pos += delta;
+ rec->last_ptr = ptr;
+
+ /* reprogram timer */
+ mod_timer(&rec->timer, jiffies + 1);
- spin_lock(&rec->timer_lock);
- /* update the current pointer */
- ptr = emu8k_get_curpos(rec, 0);
- if (ptr < rec->last_ptr)
- delta = ptr + rec->buf_size - rec->last_ptr;
- else
- delta = ptr - rec->last_ptr;
- rec->period_pos += delta;
- rec->last_ptr = ptr;
-
- /* reprogram timer */
- mod_timer(&rec->timer, jiffies + 1);
+ /* update period */
+ if (rec->period_pos >= (int)rec->period_size) {
+ rec->period_pos %= rec->period_size;
+ period_elapsed = true;
+ }
+ }
- /* update period */
- if (rec->period_pos >= (int)rec->period_size) {
- rec->period_pos %= rec->period_size;
- spin_unlock(&rec->timer_lock);
+ if (period_elapsed)
snd_pcm_period_elapsed(rec->substream);
- return;
- }
- spin_unlock(&rec->timer_lock);
}
@@ -321,7 +323,6 @@ static void setup_voice(struct snd_emu8k_pcm *rec, int ch)
*/
static void start_voice(struct snd_emu8k_pcm *rec, int ch)
{
- unsigned long flags;
struct snd_emu8000 *hw = rec->emu;
unsigned int temp, aux;
int pt = calc_pitch_target(rec->pitch);
@@ -343,12 +344,11 @@ static void start_voice(struct snd_emu8k_pcm *rec, int ch)
EMU8000_CPF_WRITE(hw, ch, pt << 16);
/* start timer */
- spin_lock_irqsave(&rec->timer_lock, flags);
+ guard(spinlock_irqsave)(&rec->timer_lock);
if (! rec->timer_running) {
mod_timer(&rec->timer, jiffies + 1);
rec->timer_running = 1;
}
- spin_unlock_irqrestore(&rec->timer_lock, flags);
}
/*
@@ -356,18 +356,16 @@ static void start_voice(struct snd_emu8k_pcm *rec, int ch)
*/
static void stop_voice(struct snd_emu8k_pcm *rec, int ch)
{
- unsigned long flags;
struct snd_emu8000 *hw = rec->emu;
EMU8000_DCYSUSV_WRITE(hw, ch, 0x807F);
/* stop timer */
- spin_lock_irqsave(&rec->timer_lock, flags);
+ guard(spinlock_irqsave)(&rec->timer_lock);
if (rec->timer_running) {
- del_timer(&rec->timer);
+ timer_delete(&rec->timer);
rec->timer_running = 0;
}
- spin_unlock_irqrestore(&rec->timer_lock, flags);
}
static int emu8k_pcm_trigger(struct snd_pcm_substream *subs, int cmd)
@@ -409,39 +407,25 @@ do { \
return -EAGAIN;\
} while (0)
-enum {
- COPY_USER, COPY_KERNEL, FILL_SILENCE,
-};
-
-#define GET_VAL(sval, buf, mode) \
+#define GET_VAL(sval, iter) \
do { \
- switch (mode) { \
- case FILL_SILENCE: \
+ if (!iter) \
sval = 0; \
- break; \
- case COPY_KERNEL: \
- sval = *buf++; \
- break; \
- default: \
- if (get_user(sval, (unsigned short __user *)buf)) \
- return -EFAULT; \
- buf++; \
- break; \
- } \
+ else if (copy_from_iter(&sval, 2, iter) != 2) \
+ return -EFAULT; \
} while (0)
#ifdef USE_NONINTERLEAVE
-#define LOOP_WRITE(rec, offset, _buf, count, mode) \
+#define LOOP_WRITE(rec, offset, iter, count) \
do { \
struct snd_emu8000 *emu = (rec)->emu; \
- unsigned short *buf = (__force unsigned short *)(_buf); \
snd_emu8000_write_wait(emu, 1); \
EMU8000_SMALW_WRITE(emu, offset); \
while (count > 0) { \
unsigned short sval; \
CHECK_SCHEDULER(); \
- GET_VAL(sval, buf, mode); \
+ GET_VAL(sval, iter); \
EMU8000_SMLD_WRITE(emu, sval); \
count--; \
} \
@@ -450,27 +434,14 @@ enum {
/* copy one channel block */
static int emu8k_pcm_copy(struct snd_pcm_substream *subs,
int voice, unsigned long pos,
- void __user *src, unsigned long count)
+ struct iov_iter *src, unsigned long count)
{
struct snd_emu8k_pcm *rec = subs->runtime->private_data;
/* convert to word unit */
pos = (pos << 1) + rec->loop_start[voice];
count <<= 1;
- LOOP_WRITE(rec, pos, src, count, COPY_USER);
- return 0;
-}
-
-static int emu8k_pcm_copy_kernel(struct snd_pcm_substream *subs,
- int voice, unsigned long pos,
- void *src, unsigned long count)
-{
- struct snd_emu8k_pcm *rec = subs->runtime->private_data;
-
- /* convert to word unit */
- pos = (pos << 1) + rec->loop_start[voice];
- count <<= 1;
- LOOP_WRITE(rec, pos, src, count, COPY_KERNEL);
+ LOOP_WRITE(rec, pos, src, count);
return 0;
}
@@ -483,16 +454,15 @@ static int emu8k_pcm_silence(struct snd_pcm_substream *subs,
/* convert to word unit */
pos = (pos << 1) + rec->loop_start[voice];
count <<= 1;
- LOOP_WRITE(rec, pos, NULL, count, FILL_SILENCE);
+ LOOP_WRITE(rec, pos, NULL, count);
return 0;
}
#else /* interleave */
-#define LOOP_WRITE(rec, pos, _buf, count, mode) \
+#define LOOP_WRITE(rec, pos, iter, count) \
do { \
struct snd_emu8000 *emu = rec->emu; \
- unsigned short *buf = (__force unsigned short *)(_buf); \
snd_emu8000_write_wait(emu, 1); \
EMU8000_SMALW_WRITE(emu, pos + rec->loop_start[0]); \
if (rec->voices > 1) \
@@ -500,11 +470,11 @@ static int emu8k_pcm_silence(struct snd_pcm_substream *subs,
while (count > 0) { \
unsigned short sval; \
CHECK_SCHEDULER(); \
- GET_VAL(sval, buf, mode); \
+ GET_VAL(sval, iter); \
EMU8000_SMLD_WRITE(emu, sval); \
if (rec->voices > 1) { \
CHECK_SCHEDULER(); \
- GET_VAL(sval, buf, mode); \
+ GET_VAL(sval, iter); \
EMU8000_SMRD_WRITE(emu, sval); \
} \
count--; \
@@ -518,27 +488,14 @@ static int emu8k_pcm_silence(struct snd_pcm_substream *subs,
*/
static int emu8k_pcm_copy(struct snd_pcm_substream *subs,
int voice, unsigned long pos,
- void __user *src, unsigned long count)
-{
- struct snd_emu8k_pcm *rec = subs->runtime->private_data;
-
- /* convert to frames */
- pos = bytes_to_frames(subs->runtime, pos);
- count = bytes_to_frames(subs->runtime, count);
- LOOP_WRITE(rec, pos, src, count, COPY_USER);
- return 0;
-}
-
-static int emu8k_pcm_copy_kernel(struct snd_pcm_substream *subs,
- int voice, unsigned long pos,
- void *src, unsigned long count)
+ struct iov_iter *src, unsigned long count)
{
struct snd_emu8k_pcm *rec = subs->runtime->private_data;
/* convert to frames */
pos = bytes_to_frames(subs->runtime, pos);
count = bytes_to_frames(subs->runtime, count);
- LOOP_WRITE(rec, pos, src, count, COPY_KERNEL);
+ LOOP_WRITE(rec, pos, src, count);
return 0;
}
@@ -550,7 +507,7 @@ static int emu8k_pcm_silence(struct snd_pcm_substream *subs,
/* convert to frames */
pos = bytes_to_frames(subs->runtime, pos);
count = bytes_to_frames(subs->runtime, count);
- LOOP_WRITE(rec, pos, NULL, count, FILL_SILENCE);
+ LOOP_WRITE(rec, pos, NULL, count);
return 0;
}
#endif
@@ -666,8 +623,7 @@ static const struct snd_pcm_ops emu8k_pcm_ops = {
.prepare = emu8k_pcm_prepare,
.trigger = emu8k_pcm_trigger,
.pointer = emu8k_pcm_pointer,
- .copy_user = emu8k_pcm_copy,
- .copy_kernel = emu8k_pcm_copy_kernel,
+ .copy = emu8k_pcm_copy,
.fill_silence = emu8k_pcm_silence,
};