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:
parent
e2964cd7ef
commit
9d0fdc602d
1 changed files with 16 additions and 58 deletions
|
@ -409,39 +409,25 @@ do { \
|
||||||
return -EAGAIN;\
|
return -EAGAIN;\
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
enum {
|
#define GET_VAL(sval, iter) \
|
||||||
COPY_USER, COPY_KERNEL, FILL_SILENCE,
|
|
||||||
};
|
|
||||||
|
|
||||||
#define GET_VAL(sval, buf, mode) \
|
|
||||||
do { \
|
do { \
|
||||||
switch (mode) { \
|
if (!iter) \
|
||||||
case FILL_SILENCE: \
|
|
||||||
sval = 0; \
|
sval = 0; \
|
||||||
break; \
|
else if (copy_from_iter(&sval, 2, iter) != 2) \
|
||||||
case COPY_KERNEL: \
|
return -EFAULT; \
|
||||||
sval = *buf++; \
|
|
||||||
break; \
|
|
||||||
default: \
|
|
||||||
if (get_user(sval, (unsigned short __user *)buf)) \
|
|
||||||
return -EFAULT; \
|
|
||||||
buf++; \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#ifdef USE_NONINTERLEAVE
|
#ifdef USE_NONINTERLEAVE
|
||||||
|
|
||||||
#define LOOP_WRITE(rec, offset, _buf, count, mode) \
|
#define LOOP_WRITE(rec, offset, iter, count) \
|
||||||
do { \
|
do { \
|
||||||
struct snd_emu8000 *emu = (rec)->emu; \
|
struct snd_emu8000 *emu = (rec)->emu; \
|
||||||
unsigned short *buf = (__force unsigned short *)(_buf); \
|
|
||||||
snd_emu8000_write_wait(emu, 1); \
|
snd_emu8000_write_wait(emu, 1); \
|
||||||
EMU8000_SMALW_WRITE(emu, offset); \
|
EMU8000_SMALW_WRITE(emu, offset); \
|
||||||
while (count > 0) { \
|
while (count > 0) { \
|
||||||
unsigned short sval; \
|
unsigned short sval; \
|
||||||
CHECK_SCHEDULER(); \
|
CHECK_SCHEDULER(); \
|
||||||
GET_VAL(sval, buf, mode); \
|
GET_VAL(sval, iter); \
|
||||||
EMU8000_SMLD_WRITE(emu, sval); \
|
EMU8000_SMLD_WRITE(emu, sval); \
|
||||||
count--; \
|
count--; \
|
||||||
} \
|
} \
|
||||||
|
@ -450,27 +436,14 @@ enum {
|
||||||
/* copy one channel block */
|
/* copy one channel block */
|
||||||
static int emu8k_pcm_copy(struct snd_pcm_substream *subs,
|
static int emu8k_pcm_copy(struct snd_pcm_substream *subs,
|
||||||
int voice, unsigned long pos,
|
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;
|
struct snd_emu8k_pcm *rec = subs->runtime->private_data;
|
||||||
|
|
||||||
/* convert to word unit */
|
/* convert to word unit */
|
||||||
pos = (pos << 1) + rec->loop_start[voice];
|
pos = (pos << 1) + rec->loop_start[voice];
|
||||||
count <<= 1;
|
count <<= 1;
|
||||||
LOOP_WRITE(rec, pos, src, count, COPY_USER);
|
LOOP_WRITE(rec, pos, src, count);
|
||||||
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);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,16 +456,15 @@ static int emu8k_pcm_silence(struct snd_pcm_substream *subs,
|
||||||
/* convert to word unit */
|
/* convert to word unit */
|
||||||
pos = (pos << 1) + rec->loop_start[voice];
|
pos = (pos << 1) + rec->loop_start[voice];
|
||||||
count <<= 1;
|
count <<= 1;
|
||||||
LOOP_WRITE(rec, pos, NULL, count, FILL_SILENCE);
|
LOOP_WRITE(rec, pos, USER_SOCKPTR(NULL), count);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* interleave */
|
#else /* interleave */
|
||||||
|
|
||||||
#define LOOP_WRITE(rec, pos, _buf, count, mode) \
|
#define LOOP_WRITE(rec, pos, iter, count) \
|
||||||
do { \
|
do { \
|
||||||
struct snd_emu8000 *emu = rec->emu; \
|
struct snd_emu8000 *emu = rec->emu; \
|
||||||
unsigned short *buf = (__force unsigned short *)(_buf); \
|
|
||||||
snd_emu8000_write_wait(emu, 1); \
|
snd_emu8000_write_wait(emu, 1); \
|
||||||
EMU8000_SMALW_WRITE(emu, pos + rec->loop_start[0]); \
|
EMU8000_SMALW_WRITE(emu, pos + rec->loop_start[0]); \
|
||||||
if (rec->voices > 1) \
|
if (rec->voices > 1) \
|
||||||
|
@ -500,11 +472,11 @@ static int emu8k_pcm_silence(struct snd_pcm_substream *subs,
|
||||||
while (count > 0) { \
|
while (count > 0) { \
|
||||||
unsigned short sval; \
|
unsigned short sval; \
|
||||||
CHECK_SCHEDULER(); \
|
CHECK_SCHEDULER(); \
|
||||||
GET_VAL(sval, buf, mode); \
|
GET_VAL(sval, iter); \
|
||||||
EMU8000_SMLD_WRITE(emu, sval); \
|
EMU8000_SMLD_WRITE(emu, sval); \
|
||||||
if (rec->voices > 1) { \
|
if (rec->voices > 1) { \
|
||||||
CHECK_SCHEDULER(); \
|
CHECK_SCHEDULER(); \
|
||||||
GET_VAL(sval, buf, mode); \
|
GET_VAL(sval, iter); \
|
||||||
EMU8000_SMRD_WRITE(emu, sval); \
|
EMU8000_SMRD_WRITE(emu, sval); \
|
||||||
} \
|
} \
|
||||||
count--; \
|
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,
|
static int emu8k_pcm_copy(struct snd_pcm_substream *subs,
|
||||||
int voice, unsigned long pos,
|
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;
|
struct snd_emu8k_pcm *rec = subs->runtime->private_data;
|
||||||
|
|
||||||
/* convert to frames */
|
/* convert to frames */
|
||||||
pos = bytes_to_frames(subs->runtime, pos);
|
pos = bytes_to_frames(subs->runtime, pos);
|
||||||
count = bytes_to_frames(subs->runtime, count);
|
count = bytes_to_frames(subs->runtime, count);
|
||||||
LOOP_WRITE(rec, pos, src, count, COPY_USER);
|
LOOP_WRITE(rec, pos, src, count);
|
||||||
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);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -550,7 +509,7 @@ static int emu8k_pcm_silence(struct snd_pcm_substream *subs,
|
||||||
/* convert to frames */
|
/* convert to frames */
|
||||||
pos = bytes_to_frames(subs->runtime, pos);
|
pos = bytes_to_frames(subs->runtime, pos);
|
||||||
count = bytes_to_frames(subs->runtime, count);
|
count = bytes_to_frames(subs->runtime, count);
|
||||||
LOOP_WRITE(rec, pos, NULL, count, FILL_SILENCE);
|
LOOP_WRITE(rec, pos, NULL, count);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -666,8 +625,7 @@ static const struct snd_pcm_ops emu8k_pcm_ops = {
|
||||||
.prepare = emu8k_pcm_prepare,
|
.prepare = emu8k_pcm_prepare,
|
||||||
.trigger = emu8k_pcm_trigger,
|
.trigger = emu8k_pcm_trigger,
|
||||||
.pointer = emu8k_pcm_pointer,
|
.pointer = emu8k_pcm_pointer,
|
||||||
.copy_user = emu8k_pcm_copy,
|
.copy = emu8k_pcm_copy,
|
||||||
.copy_kernel = emu8k_pcm_copy_kernel,
|
|
||||||
.fill_silence = emu8k_pcm_silence,
|
.fill_silence = emu8k_pcm_silence,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue