ALSA: emu8000: Convert to generic PCM copy ops
This patch converts the SB Emu8000 driver code to use the new unified PCM copy callback. The conversion is a bit complicated because of many open code in emu8000_pcm.c. GET_VAL() and LOOP_WRITE() macros were rewritten / simplified with copy_from_iter(). As copy_from_iter() updates the internal offset value, we can drop the corresponding part, too. Link: https://lore.kernel.org/r/20230815190136.8987-7-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Родитель
e2964cd7ef
Коммит
9d0fdc602d
|
@ -409,39 +409,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 +436,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 +456,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, USER_SOCKPTR(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 +472,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 +490,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 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_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 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 +509,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 +625,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,
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче