@@ -422,16 +422,28 @@ do { \
return -EAGAIN;\
} while (0)
+static inline int get_val(unsigned short *sval, unsigned short __user *buf,
+ bool in_kernel)
+{
+ if (!buf)
+ *sval = 0;
+ else if (in_kernel)
+ *sval = *(unsigned short *)buf;
+ else if (get_user(*sval, buf))
+ return -EFAULT;
+ return 0;
+}
#ifdef USE_NONINTERLEAVE
/* copy one channel block */
-static int emu8k_transfer_block(struct snd_emu8000 *emu, int offset, unsigned short *buf, int count)
+static int emu8k_transfer_block(struct snd_emu8000 *emu, int offset,
+ unsigned short *buf, int count, bool in_kernel)
{
EMU8000_SMALW_WRITE(emu, offset);
while (count > 0) {
unsigned short sval;
CHECK_SCHEDULER();
- if (get_user(sval, buf))
+ if (get_val(&sval, buf, in_kernel))
return -EFAULT;
EMU8000_SMLD_WRITE(emu, sval);
buf++;
@@ -455,48 +467,18 @@ static int emu8k_pcm_copy(struct snd_pcm_substream *subs,
int i, err;
count /= rec->voices;
for (i = 0; i < rec->voices; i++) {
- err = emu8k_transfer_block(emu, pos + rec->loop_start[i], buf, count);
+ err = emu8k_transfer_block(emu,
+ pos + rec->loop_start[i],
+ buf, count, in_kernel);
if (err < 0)
return err;
- buf += count;
+ if (buf)
+ buf += count;
}
return 0;
} else {
- return emu8k_transfer_block(emu, pos + rec->loop_start[voice], src, count);
- }
-}
-
-/* make a channel block silence */
-static int emu8k_silence_block(struct snd_emu8000 *emu, int offset, int count)
-{
- EMU8000_SMALW_WRITE(emu, offset);
- while (count > 0) {
- CHECK_SCHEDULER();
- EMU8000_SMLD_WRITE(emu, 0);
- count--;
- }
- return 0;
-}
-
-static int emu8k_pcm_silence(struct snd_pcm_substream *subs,
- int voice,
- snd_pcm_uframes_t pos,
- snd_pcm_uframes_t count)
-{
- struct snd_emu8k_pcm *rec = subs->runtime->private_data;
- struct snd_emu8000 *emu = rec->emu;
-
- snd_emu8000_write_wait(emu, 1);
- if (voice == -1 && rec->voices == 1)
- voice = 0;
- if (voice == -1) {
- int err;
- err = emu8k_silence_block(emu, pos + rec->loop_start[0], count / 2);
- if (err < 0)
- return err;
- return emu8k_silence_block(emu, pos + rec->loop_start[1], count / 2);
- } else {
- return emu8k_silence_block(emu, pos + rec->loop_start[voice], count);
+ return emu8k_transfer_block(emu, pos + rec->loop_start[voice],
+ src, count, in_kernel);
}
}
@@ -510,7 +492,8 @@ static int emu8k_pcm_copy(struct snd_pcm_substream *subs,
int voice,
snd_pcm_uframes_t pos,
void __user *src,
- snd_pcm_uframes_t count)
+ snd_pcm_uframes_t count,
+ bool in_kernel)
{
struct snd_emu8k_pcm *rec = subs->runtime->private_data;
struct snd_emu8000 *emu = rec->emu;
@@ -524,39 +507,18 @@ static int emu8k_pcm_copy(struct snd_pcm_substream *subs,
while (count-- > 0) {
unsigned short sval;
CHECK_SCHEDULER();
- if (get_user(sval, buf))
+ if (get_val(&sval, buf, in_kernel))
return -EFAULT;
EMU8000_SMLD_WRITE(emu, sval);
- buf++;
+ if (buf)
+ buf++;
if (rec->voices > 1) {
CHECK_SCHEDULER();
- if (get_user(sval, buf))
+ if (get_val(&sval, buf, in_kernel))
return -EFAULT;
EMU8000_SMRD_WRITE(emu, sval);
- buf++;
- }
- }
- return 0;
-}
-
-static int emu8k_pcm_silence(struct snd_pcm_substream *subs,
- int voice,
- snd_pcm_uframes_t pos,
- snd_pcm_uframes_t count)
-{
- struct snd_emu8k_pcm *rec = subs->runtime->private_data;
- struct snd_emu8000 *emu = rec->emu;
-
- snd_emu8000_write_wait(emu, 1);
- EMU8000_SMALW_WRITE(emu, rec->loop_start[0] + pos);
- if (rec->voices > 1)
- EMU8000_SMARW_WRITE(emu, rec->loop_start[1] + pos);
- while (count-- > 0) {
- CHECK_SCHEDULER();
- EMU8000_SMLD_WRITE(emu, 0);
- if (rec->voices > 1) {
- CHECK_SCHEDULER();
- EMU8000_SMRD_WRITE(emu, 0);
+ if (buf)
+ buf++;
}
}
return 0;
@@ -674,8 +636,7 @@ static struct snd_pcm_ops emu8k_pcm_ops = {
.prepare = emu8k_pcm_prepare,
.trigger = emu8k_pcm_trigger,
.pointer = emu8k_pcm_pointer,
- .copy = emu8k_pcm_copy,
- .silence = emu8k_pcm_silence,
+ .copy_silence = emu8k_pcm_copy,
};
Replace the copy and the silence ops with the new merged ops. We could reduce the redundant silence code by that. Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/isa/sb/emu8000_pcm.c | 99 ++++++++++++++-------------------------------- 1 file changed, 30 insertions(+), 69 deletions(-)