summaryrefslogtreecommitdiff
path: root/linux/drivers/media/video/ivtv/ivtvfb.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux/drivers/media/video/ivtv/ivtvfb.c')
-rw-r--r--linux/drivers/media/video/ivtv/ivtvfb.c89
1 files changed, 46 insertions, 43 deletions
diff --git a/linux/drivers/media/video/ivtv/ivtvfb.c b/linux/drivers/media/video/ivtv/ivtvfb.c
index bdedff281..1ac3af3fc 100644
--- a/linux/drivers/media/video/ivtv/ivtvfb.c
+++ b/linux/drivers/media/video/ivtv/ivtvfb.c
@@ -275,7 +275,6 @@ static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv,
int size_in_bytes)
{
DEFINE_WAIT(wait);
- int ret = 0;
int got_sig = 0;
mutex_lock(&itv->udma.lock);
@@ -316,7 +315,7 @@ static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv,
return -EINTR;
}
- return ret;
+ return 0;
}
static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source,
@@ -369,11 +368,20 @@ static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf,
- size_t count, loff_t *ppos)
+ size_t count, loff_t *ppos)
+{
+#else
+static ssize_t ivtvfb_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
{
+ struct inode *inode = file->f_dentry->d_inode;
+ int fbidx = iminor(inode);
+ struct fb_info *info = registered_fb[fbidx];
+#endif
unsigned long p = *ppos;
void *dst;
int err = 0;
+ int dma_err;
unsigned long total_size;
struct ivtv *itv = (struct ivtv *) info->par;
unsigned long dma_offset =
@@ -400,7 +408,6 @@ static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf,
if (count + p > total_size) {
if (!err)
err = -ENOSPC;
-
count = total_size - p;
}
@@ -409,39 +416,34 @@ static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf,
if (info->fbops->fb_sync)
info->fbops->fb_sync(info);
- if (!access_ok(VERIFY_READ, buf, count)) {
- IVTVFB_WARN("Invalid userspace pointer 0x%08lx\n",
- (unsigned long)buf);
- err = -EFAULT;
- }
-
- if (!err) {
- /* If transfer size > threshold and both src/dst
- addresses are aligned, use DMA */
- if (count >= 4096 &&
- ((unsigned long)buf & 3) == ((unsigned long)dst & 3)) {
- /* Odd address = can't DMA. Align */
- if ((unsigned long)dst & 3) {
- lead = 4 - ((unsigned long)dst & 3);
- memcpy(dst, buf, lead);
- buf += lead;
- dst += lead;
- }
- /* DMA resolution is 32 bits */
- if ((count - lead) & 3)
- tail = (count - lead) & 3;
- /* DMA the data */
- dma_size = count - lead - tail;
- err = ivtvfb_prep_dec_dma_to_device(itv,
- p + lead + dma_offset, (void *)buf, dma_size);
- dst += dma_size;
- buf += dma_size;
- /* Copy any leftover data */
- if (tail)
- memcpy(dst, buf, tail);
- } else {
- memcpy(dst, buf, count);
+ /* If transfer size > threshold and both src/dst
+ addresses are aligned, use DMA */
+ if (count >= 4096 &&
+ ((unsigned long)buf & 3) == ((unsigned long)dst & 3)) {
+ /* Odd address = can't DMA. Align */
+ if ((unsigned long)dst & 3) {
+ lead = 4 - ((unsigned long)dst & 3);
+ if (copy_from_user(dst, buf, lead))
+ return -EFAULT;
+ buf += lead;
+ dst += lead;
}
+ /* DMA resolution is 32 bits */
+ if ((count - lead) & 3)
+ tail = (count - lead) & 3;
+ /* DMA the data */
+ dma_size = count - lead - tail;
+ dma_err = ivtvfb_prep_dec_dma_to_device(itv,
+ p + lead + dma_offset, (void __user *)buf, dma_size);
+ if (dma_err)
+ return dma_err;
+ dst += dma_size;
+ buf += dma_size;
+ /* Copy any leftover data */
+ if (tail && copy_from_user(dst, buf, tail))
+ return -EFAULT;
+ } else if (copy_from_user(dst, buf, count)) {
+ return -EFAULT;
}
if (!err)
@@ -449,7 +451,6 @@ static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf,
return (err) ? err : count;
}
-#endif
static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
{
@@ -465,9 +466,12 @@ static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long ar
vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT |
FB_VBLANK_HAVE_VSYNC;
trace = read_reg(0x028c0) >> 16;
- if (itv->is_50hz && trace > 312) trace -= 312;
- else if (itv->is_60hz && trace > 262) trace -= 262;
- if (trace == 1) vblank.flags |= FB_VBLANK_VSYNCING;
+ if (itv->is_50hz && trace > 312)
+ trace -= 312;
+ else if (itv->is_60hz && trace > 262)
+ trace -= 262;
+ if (trace == 1)
+ vblank.flags |= FB_VBLANK_VSYNCING;
vblank.count = itv->last_vsync_field;
vblank.vcount = trace;
vblank.hcount = 0;
@@ -478,7 +482,8 @@ static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long ar
case FBIO_WAITFORVSYNC:
prepare_to_wait(&itv->vsync_waitq, &wait, TASK_INTERRUPTIBLE);
- if (!schedule_timeout(msecs_to_jiffies(50))) rc = -ETIMEDOUT;
+ if (!schedule_timeout(msecs_to_jiffies(50)))
+ rc = -ETIMEDOUT;
finish_wait(&itv->vsync_waitq, &wait);
return rc;
@@ -911,9 +916,7 @@ static int ivtvfb_blank(int blank_mode, struct fb_info *info)
static struct fb_ops ivtvfb_ops = {
.owner = THIS_MODULE,
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
.fb_write = ivtvfb_write,
-#endif
.fb_check_var = ivtvfb_check_var,
.fb_set_par = ivtvfb_set_par,
.fb_setcolreg = ivtvfb_setcolreg,