Commit da10fb31 authored by Gerd Knorr's avatar Gerd Knorr Committed by Linus Torvalds

[PATCH] v4l: w9966 update

This patch updates the Winbond w9966cf parport webcam driver.
parent 4adae09a
......@@ -173,10 +173,27 @@ static inline int w9966_i2c_getscl(struct w9966_dev* cam);
static int w9966_i2c_wbyte(struct w9966_dev* cam, int data);
static int w9966_i2c_rbyte(struct w9966_dev* cam);
static int w9966_v4l_open(struct video_device *vdev, int mode);
static void w9966_v4l_close(struct video_device *vdev);
static int w9966_v4l_ioctl(struct video_device *vdev, unsigned int cmd, void *arg);
static long w9966_v4l_read(struct video_device *vdev, char *buf, unsigned long count, int noblock);
static int w9966_v4l_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, void *arg);
static int w9966_v4l_read(struct file *file, char *buf,
size_t count, loff_t *ppos);
static struct file_operations w9966_fops = {
owner: THIS_MODULE,
open: video_exclusive_open,
release: video_exclusive_release,
ioctl: video_generic_ioctl,
read: w9966_v4l_read,
llseek: no_llseek,
};
static struct video_device w9966_template = {
owner: THIS_MODULE,
name: W9966_DRIVERNAME,
type: VID_TYPE_CAPTURE | VID_TYPE_SCALES,
hardware: VID_HARDWARE_W9966,
fops: &w9966_fops,
kernel_ioctl: w9966_v4l_ioctl,
};
/*
* Private function defines
......@@ -309,16 +326,8 @@ static int w9966_init(struct w9966_dev* cam, struct parport* port)
w9966_pdev_release(cam);
// Fill in the video_device struct and register us to v4l
memset(&cam->vdev, 0, sizeof(struct video_device));
strcpy(cam->vdev.name, W9966_DRIVERNAME);
cam->vdev.type = VID_TYPE_CAPTURE | VID_TYPE_SCALES;
cam->vdev.hardware = VID_HARDWARE_W9966;
cam->vdev.open = &w9966_v4l_open;
cam->vdev.close = &w9966_v4l_close;
cam->vdev.read = &w9966_v4l_read;
cam->vdev.ioctl = &w9966_v4l_ioctl;
memcpy(&cam->vdev, &w9966_template, sizeof(struct video_device));
cam->vdev.priv = (void*)cam;
cam->vdev.owner = THIS_MODULE;
if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) == -1)
return -1;
......@@ -691,101 +700,67 @@ static int w9966_wReg_i2c(struct w9966_dev* cam, int reg, int data)
* Video4linux interfacing
*/
static int w9966_v4l_open(struct video_device *vdev, int flags)
{
return 0;
}
static void w9966_v4l_close(struct video_device *vdev)
{
}
static int w9966_v4l_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
static int w9966_v4l_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, void *arg)
{
struct video_device *vdev = video_devdata(file);
struct w9966_dev *cam = (struct w9966_dev*)vdev->priv;
switch(cmd)
{
case VIDIOCGCAP:
{
struct video_capability vcap = {
W9966_DRIVERNAME, // name
VID_TYPE_CAPTURE | VID_TYPE_SCALES, // type
1, 0, // vid, aud channels
W9966_WND_MAX_W, // max w
W9966_WND_MAX_H, // max h
2, 1 // min w, min h
static struct video_capability vcap = {
name: W9966_DRIVERNAME,
type: VID_TYPE_CAPTURE | VID_TYPE_SCALES,
channels: 1,
audios: 0,
maxwidth: W9966_WND_MAX_W,
maxheight: W9966_WND_MAX_H,
minwidth: 2,
minheight: 1,
};
if(copy_to_user(arg, &vcap, sizeof(vcap)) != 0)
return -EFAULT;
struct video_capability *cap = arg;
*cap = vcap;
return 0;
}
case VIDIOCGCHAN:
{
struct video_channel vch;
if(copy_from_user(&vch, arg, sizeof(vch)) != 0)
return -EFAULT;
if(vch.channel != 0) // We only support one channel (#0)
struct video_channel *vch = arg;
if(vch->channel != 0) // We only support one channel (#0)
return -EINVAL;
strcpy(vch.name, "CCD-input");
vch.flags = 0; // We have no tuner or audio
vch.tuners = 0;
vch.type = VIDEO_TYPE_CAMERA;
vch.norm = 0; // ???
if(copy_to_user(arg, &vch, sizeof(vch)) != 0)
return -EFAULT;
memset(vch,0,sizeof(*vch));
strcpy(vch->name, "CCD-input");
vch->type = VIDEO_TYPE_CAMERA;
return 0;
}
case VIDIOCSCHAN:
{
struct video_channel vch;
if(copy_from_user(&vch, arg, sizeof(vch) ) != 0)
return -EFAULT;
if(vch.channel != 0)
struct video_channel *vch = arg;
if(vch->channel != 0)
return -EINVAL;
return 0;
}
case VIDIOCGTUNER:
{
struct video_tuner vtune;
if(copy_from_user(&vtune, arg, sizeof(vtune)) != 0)
return -EFAULT;
if(vtune.tuner != 0);
struct video_tuner *vtune = arg;
if(vtune->tuner != 0);
return -EINVAL;
strcpy(vtune.name, "no tuner");
vtune.rangelow = 0;
vtune.rangehigh = 0;
vtune.flags = VIDEO_TUNER_NORM;
vtune.mode = VIDEO_MODE_AUTO;
vtune.signal = 0xffff;
if(copy_to_user(arg, &vtune, sizeof(vtune)) != 0)
return -EFAULT;
strcpy(vtune->name, "no tuner");
vtune->rangelow = 0;
vtune->rangehigh = 0;
vtune->flags = VIDEO_TUNER_NORM;
vtune->mode = VIDEO_MODE_AUTO;
vtune->signal = 0xffff;
return 0;
}
case VIDIOCSTUNER:
{
struct video_tuner vtune;
if (copy_from_user(&vtune, arg, sizeof(vtune)) != 0)
return -EFAULT;
if (vtune.tuner != 0)
struct video_tuner *vtune = arg;
if (vtune->tuner != 0)
return -EINVAL;
if (vtune.mode != VIDEO_MODE_AUTO)
if (vtune->mode != VIDEO_MODE_AUTO)
return -EINVAL;
return 0;
}
case VIDIOCGPICT:
......@@ -798,25 +773,20 @@ static int w9966_v4l_ioctl(struct video_device *vdev, unsigned int cmd, void *ar
0x8000, // whiteness
16, VIDEO_PALETTE_YUV422// bpp, palette format
};
if(copy_to_user(arg, &vpic, sizeof(vpic)) != 0)
return -EFAULT;
struct video_picture *pic = arg;
*pic = vpic;
return 0;
}
case VIDIOCSPICT:
{
struct video_picture vpic;
if(copy_from_user(&vpic, arg, sizeof(vpic)) != 0)
return -EFAULT;
if (vpic.depth != 16 || vpic.palette != VIDEO_PALETTE_YUV422)
struct video_picture *vpic = arg;
if (vpic->depth != 16 || vpic->palette != VIDEO_PALETTE_YUV422)
return -EINVAL;
cam->brightness = vpic.brightness >> 8;
cam->hue = (vpic.hue >> 8) - 128;
cam->color = vpic.colour >> 9;
cam->contrast = vpic.contrast >> 9;
cam->brightness = vpic->brightness >> 8;
cam->hue = (vpic->hue >> 8) - 128;
cam->color = vpic->colour >> 9;
cam->contrast = vpic->contrast >> 9;
w9966_pdev_claim(cam);
......@@ -827,7 +797,7 @@ static int w9966_v4l_ioctl(struct video_device *vdev, unsigned int cmd, void *ar
w9966_wReg_i2c(cam, 0x0d, cam->hue) == -1
) {
w9966_pdev_release(cam);
return -EFAULT;
return -EIO;
}
w9966_pdev_release(cam);
......@@ -836,42 +806,35 @@ static int w9966_v4l_ioctl(struct video_device *vdev, unsigned int cmd, void *ar
case VIDIOCSWIN:
{
int ret;
struct video_window vwin;
struct video_window *vwin = arg;
if (copy_from_user(&vwin, arg, sizeof(vwin)) != 0)
return -EFAULT;
if (vwin.flags != 0)
if (vwin->flags != 0)
return -EINVAL;
if (vwin.clipcount != 0)
if (vwin->clipcount != 0)
return -EINVAL;
if (vwin.width < 2 || vwin.width > W9966_WND_MAX_W)
if (vwin->width < 2 || vwin->width > W9966_WND_MAX_W)
return -EINVAL;
if (vwin.height < 1 || vwin.height > W9966_WND_MAX_H)
if (vwin->height < 1 || vwin->height > W9966_WND_MAX_H)
return -EINVAL;
// Update camera regs
w9966_pdev_claim(cam);
ret = w9966_setup(cam, 0, 0, 1023, 1023, vwin.width, vwin.height);
ret = w9966_setup(cam, 0, 0, 1023, 1023, vwin->width, vwin->height);
w9966_pdev_release(cam);
if (ret != 0) {
DPRINTF("VIDIOCSWIN: w9966_setup() failed.\n");
return -EFAULT;
return -EIO;
}
return 0;
}
case VIDIOCGWIN:
{
struct video_window vwin;
memset(&vwin, 0, sizeof(vwin));
vwin.width = cam->width;
vwin.height = cam->height;
if(copy_to_user(arg, &vwin, sizeof(vwin)) != 0)
return -EFAULT;
struct video_window *vwin = arg;
memset(vwin, 0, sizeof(*vwin));
vwin->width = cam->width;
vwin->height = cam->height;
return 0;
}
// Unimplemented
......@@ -891,8 +854,10 @@ static int w9966_v4l_ioctl(struct video_device *vdev, unsigned int cmd, void *ar
}
// Capture data
static long w9966_v4l_read(struct video_device *vdev, char *buf, unsigned long count, int noblock)
static int w9966_v4l_read(struct file *file, char *buf,
size_t count, loff_t *ppos)
{
struct video_device *vdev = video_devdata(file);
struct w9966_dev *cam = (struct w9966_dev *)vdev->priv;
unsigned char addr = 0xa0; // ECP, read, CCD-transfer, 00000
unsigned char* dest = (unsigned char*)buf;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment