diff options
Diffstat (limited to 'drivers/media/video')
98 files changed, 1264 insertions, 1266 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index ad9e6f9..bdbc9d3 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -646,7 +646,7 @@ config VIDEO_PMS config VIDEO_BWQCAM tristate "Quickcam BW Video For Linux" - depends on PARPORT && VIDEO_V4L1 + depends on PARPORT && VIDEO_V4L2 help Say Y have if you the black and white version of the QuickCam camera. See the next option for the color version. @@ -656,7 +656,7 @@ config VIDEO_BWQCAM config VIDEO_CQCAM tristate "QuickCam Colour Video For Linux (EXPERIMENTAL)" - depends on EXPERIMENTAL && PARPORT && VIDEO_V4L1 + depends on EXPERIMENTAL && PARPORT && VIDEO_V4L2 help This is the video4linux driver for the colour version of the Connectix QuickCam. If you have one of these cameras, say Y here, diff --git a/drivers/media/video/ak881x.c b/drivers/media/video/ak881x.c index 35390d4..1573392 100644 --- a/drivers/media/video/ak881x.c +++ b/drivers/media/video/ak881x.c @@ -11,6 +11,7 @@ #include <linux/i2c.h> #include <linux/init.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <linux/videodev2.h> #include <media/ak881x.h> @@ -141,7 +142,7 @@ static int ak881x_s_mbus_fmt(struct v4l2_subdev *sd, return ak881x_try_g_mbus_fmt(sd, mf); } -static int ak881x_enum_mbus_fmt(struct v4l2_subdev *sd, int index, +static int ak881x_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index, enum v4l2_mbus_pixelcode *code) { if (index) diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c index 3c9e754..935e0c9 100644 --- a/drivers/media/video/bw-qcam.c +++ b/drivers/media/video/bw-qcam.c @@ -66,19 +66,58 @@ OTHER DEALINGS IN THE SOFTWARE. #include <linux/delay.h> #include <linux/errno.h> #include <linux/fs.h> -#include <linux/init.h> #include <linux/kernel.h> #include <linux/slab.h> #include <linux/mm.h> #include <linux/parport.h> #include <linux/sched.h> -#include <linux/videodev.h> -#include <media/v4l2-common.h> -#include <media/v4l2-ioctl.h> +#include <linux/version.h> +#include <linux/videodev2.h> #include <linux/mutex.h> #include <asm/uaccess.h> - -#include "bw-qcam.h" +#include <media/v4l2-common.h> +#include <media/v4l2-ioctl.h> +#include <media/v4l2-device.h> + +/* One from column A... */ +#define QC_NOTSET 0 +#define QC_UNIDIR 1 +#define QC_BIDIR 2 +#define QC_SERIAL 3 + +/* ... and one from column B */ +#define QC_ANY 0x00 +#define QC_FORCE_UNIDIR 0x10 +#define QC_FORCE_BIDIR 0x20 +#define QC_FORCE_SERIAL 0x30 +/* in the port_mode member */ + +#define QC_MODE_MASK 0x07 +#define QC_FORCE_MASK 0x70 + +#define MAX_HEIGHT 243 +#define MAX_WIDTH 336 + +/* Bit fields for status flags */ +#define QC_PARAM_CHANGE 0x01 /* Camera status change has occurred */ + +struct qcam { + struct v4l2_device v4l2_dev; + struct video_device vdev; + struct pardevice *pdev; + struct parport *pport; + struct mutex lock; + int width, height; + int bpp; + int mode; + int contrast, brightness, whitebal; + int port_mode; + int transfer_scale; + int top, left; + int status; + unsigned int saved_bits; + unsigned long in_use; +}; static unsigned int maxpoll = 250; /* Maximum busy-loop count for qcam I/O */ static unsigned int yieldlines = 4; /* Yield after this many during capture */ @@ -93,22 +132,26 @@ module_param(video_nr, int, 0); * immediately attempt to initialize qcam */ module_param(force_init, int, 0); -static inline int read_lpstatus(struct qcam_device *q) +#define MAX_CAMS 4 +static struct qcam *qcams[MAX_CAMS]; +static unsigned int num_cams; + +static inline int read_lpstatus(struct qcam *q) { return parport_read_status(q->pport); } -static inline int read_lpdata(struct qcam_device *q) +static inline int read_lpdata(struct qcam *q) { return parport_read_data(q->pport); } -static inline void write_lpdata(struct qcam_device *q, int d) +static inline void write_lpdata(struct qcam *q, int d) { parport_write_data(q->pport, d); } -static inline void write_lpcontrol(struct qcam_device *q, int d) +static void write_lpcontrol(struct qcam *q, int d) { if (d & 0x20) { /* Set bidirectional mode to reverse (data in) */ @@ -124,126 +167,11 @@ static inline void write_lpcontrol(struct qcam_device *q, int d) parport_write_control(q->pport, d); } -static int qc_waithand(struct qcam_device *q, int val); -static int qc_command(struct qcam_device *q, int command); -static int qc_readparam(struct qcam_device *q); -static int qc_setscanmode(struct qcam_device *q); -static int qc_readbytes(struct qcam_device *q, char buffer[]); - -static struct video_device qcam_template; - -static int qc_calibrate(struct qcam_device *q) -{ - /* - * Bugfix by Hanno Mueller hmueller@kabel.de, Mai 21 96 - * The white balance is an individiual value for each - * quickcam. - */ - - int value; - int count = 0; - - qc_command(q, 27); /* AutoAdjustOffset */ - qc_command(q, 0); /* Dummy Parameter, ignored by the camera */ - - /* GetOffset (33) will read 255 until autocalibration */ - /* is finished. After that, a value of 1-254 will be */ - /* returned. */ - - do { - qc_command(q, 33); - value = qc_readparam(q); - mdelay(1); - schedule(); - count++; - } while (value == 0xff && count < 2048); - - q->whitebal = value; - return value; -} - -/* Initialize the QuickCam driver control structure. This is where - * defaults are set for people who don't have a config file.*/ - -static struct qcam_device *qcam_init(struct parport *port) -{ - struct qcam_device *q; - - q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL); - if (q == NULL) - return NULL; - - q->pport = port; - q->pdev = parport_register_device(port, "bw-qcam", NULL, NULL, - NULL, 0, NULL); - if (q->pdev == NULL) { - printk(KERN_ERR "bw-qcam: couldn't register for %s.\n", - port->name); - kfree(q); - return NULL; - } - - memcpy(&q->vdev, &qcam_template, sizeof(qcam_template)); - - mutex_init(&q->lock); - - q->port_mode = (QC_ANY | QC_NOTSET); - q->width = 320; - q->height = 240; - q->bpp = 4; - q->transfer_scale = 2; - q->contrast = 192; - q->brightness = 180; - q->whitebal = 105; - q->top = 1; - q->left = 14; - q->mode = -1; - q->status = QC_PARAM_CHANGE; - return q; -} - - -/* qc_command is probably a bit of a misnomer -- it's used to send - * bytes *to* the camera. Generally, these bytes are either commands - * or arguments to commands, so the name fits, but it still bugs me a - * bit. See the documentation for a list of commands. */ - -static int qc_command(struct qcam_device *q, int command) -{ - int n1, n2; - int cmd; - - write_lpdata(q, command); - write_lpcontrol(q, 6); - - n1 = qc_waithand(q, 1); - - write_lpcontrol(q, 0xe); - n2 = qc_waithand(q, 0); - - cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4); - return cmd; -} - -static int qc_readparam(struct qcam_device *q) -{ - int n1, n2; - int cmd; - - write_lpcontrol(q, 6); - n1 = qc_waithand(q, 1); - - write_lpcontrol(q, 0xe); - n2 = qc_waithand(q, 0); - - cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4); - return cmd; -} /* qc_waithand busy-waits for a handshake signal from the QuickCam. * Almost all communication with the camera requires handshaking. */ -static int qc_waithand(struct qcam_device *q, int val) +static int qc_waithand(struct qcam *q, int val) { int status; int runs = 0; @@ -286,7 +214,7 @@ static int qc_waithand(struct qcam_device *q, int val) * (bit 3 of status register). It also returns the last value read, * since this data is useful. */ -static unsigned int qc_waithand2(struct qcam_device *q, int val) +static unsigned int qc_waithand2(struct qcam *q, int val) { unsigned int status; int runs = 0; @@ -309,6 +237,43 @@ static unsigned int qc_waithand2(struct qcam_device *q, int val) return status; } +/* qc_command is probably a bit of a misnomer -- it's used to send + * bytes *to* the camera. Generally, these bytes are either commands + * or arguments to commands, so the name fits, but it still bugs me a + * bit. See the documentation for a list of commands. */ + +static int qc_command(struct qcam *q, int command) +{ + int n1, n2; + int cmd; + + write_lpdata(q, command); + write_lpcontrol(q, 6); + + n1 = qc_waithand(q, 1); + + write_lpcontrol(q, 0xe); + n2 = qc_waithand(q, 0); + + cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4); + return cmd; +} + +static int qc_readparam(struct qcam *q) +{ + int n1, n2; + int cmd; + + write_lpcontrol(q, 6); + n1 = qc_waithand(q, 1); + + write_lpcontrol(q, 0xe); + n2 = qc_waithand(q, 0); + + cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4); + return cmd; +} + /* Try to detect a QuickCam. It appears to flash the upper 4 bits of the status register at 5-10 Hz. This is only used in the autoprobe @@ -317,7 +282,7 @@ static unsigned int qc_waithand2(struct qcam_device *q, int val) almost completely safe, while their method screws up my printer if I plug it in before the camera. */ -static int qc_detect(struct qcam_device *q) +static int qc_detect(struct qcam *q) { int reg, lastreg; int count = 0; @@ -358,41 +323,6 @@ static int qc_detect(struct qcam_device *q) } } - -/* Reset the QuickCam. This uses the same sequence the Windows - * QuickPic program uses. Someone with a bi-directional port should - * check that bi-directional mode is detected right, and then - * implement bi-directional mode in qc_readbyte(). */ - -static void qc_reset(struct qcam_device *q) -{ - switch (q->port_mode & QC_FORCE_MASK) { - case QC_FORCE_UNIDIR: - q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR; - break; - - case QC_FORCE_BIDIR: - q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR; - break; - - case QC_ANY: - write_lpcontrol(q, 0x20); - write_lpdata(q, 0x75); - - if (read_lpdata(q) != 0x75) - q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR; - else - q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR; - break; - } - - write_lpcontrol(q, 0xb); - udelay(250); - write_lpcontrol(q, 0xe); - qc_setscanmode(q); /* in case port_mode changed */ -} - - /* Decide which scan mode to use. There's no real requirement that * the scanmode match the resolution in q->height and q-> width -- the * camera takes the picture at the resolution specified in the @@ -402,7 +332,7 @@ static void qc_reset(struct qcam_device *q) * returned. If the scan is smaller, then the rest of the image * returned contains garbage. */ -static int qc_setscanmode(struct qcam_device *q) +static int qc_setscanmode(struct qcam *q) { int old_mode = q->mode; @@ -442,10 +372,45 @@ static int qc_setscanmode(struct qcam_device *q) } +/* Reset the QuickCam. This uses the same sequence the Windows + * QuickPic program uses. Someone with a bi-directional port should + * check that bi-directional mode is detected right, and then + * implement bi-directional mode in qc_readbyte(). */ + +static void qc_reset(struct qcam *q) +{ + switch (q->port_mode & QC_FORCE_MASK) { + case QC_FORCE_UNIDIR: + q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR; + break; + + case QC_FORCE_BIDIR: + q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR; + break; + + case QC_ANY: + write_lpcontrol(q, 0x20); + write_lpdata(q, 0x75); + + if (read_lpdata(q) != 0x75) + q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR; + else + q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR; + break; + } + + write_lpcontrol(q, 0xb); + udelay(250); + write_lpcontrol(q, 0xe); + qc_setscanmode(q); /* in case port_mode changed */ +} + + + /* Reset the QuickCam and program for brightness, contrast, * white-balance, and resolution. */ -static void qc_set(struct qcam_device *q) +static void qc_set(struct qcam *q) { int val; int val2; @@ -499,7 +464,7 @@ static void qc_set(struct qcam_device *q) the supplied buffer. It returns the number of bytes read, or -1 on error. */ -static inline int qc_readbytes(struct qcam_device *q, char buffer[]) +static inline int qc_readbytes(struct qcam *q, char buffer[]) { int ret = 1; unsigned int hi, lo; @@ -590,7 +555,7 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[]) * n=2^(bit depth)-1. Ask me for more details if you don't understand * this. */ -static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long len) +static long qc_capture(struct qcam *q, char __user *buf, unsigned long len) { int i, j, k, yield; int bytes; @@ -674,171 +639,206 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le * Video4linux interfacing */ -static long qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg) +static int qcam_querycap(struct file *file, void *priv, + struct v4l2_capability *vcap) { - struct video_device *dev = video_devdata(file); - struct qcam_device *qcam = (struct qcam_device *)dev; - - switch (cmd) { - case VIDIOCGCAP: - { - struct video_capability *b = arg; - strcpy(b->name, "Quickcam"); - b->type = VID_TYPE_CAPTURE|VID_TYPE_SCALES|VID_TYPE_MONOCHROME; - b->channels = 1; - b->audios = 0; - b->maxwidth = 320; - b->maxheight = 240; - b->minwidth = 80; - b->minheight = 60; - return 0; - } - case VIDIOCGCHAN: - { - struct video_channel *v = arg; - if (v->channel != 0) - return -EINVAL; - v->flags = 0; - v->tuners = 0; - /* Good question.. its composite or SVHS so.. */ - v->type = VIDEO_TYPE_CAMERA; - strcpy(v->name, "Camera"); - return 0; - } - case VIDIOCSCHAN: - { - struct video_channel *v = arg; - if (v->channel != 0) - return -EINVAL; - return 0; - } - case VIDIOCGTUNER: - { - struct video_tuner *v = arg; - if (v->tuner) - return -EINVAL; - strcpy(v->name, "Format"); - v->rangelow = 0; - v->rangehigh = 0; - v->flags = 0; - v->mode = VIDEO_MODE_AUTO; - return 0; - } - case VIDIOCSTUNER: - { - struct video_tuner *v = arg; - if (v->tuner) - return -EINVAL; - if (v->mode != VIDEO_MODE_AUTO) - return -EINVAL; - return 0; - } - case VIDIOCGPICT: - { - struct video_picture *p = arg; - p->colour = 0x8000; - p->hue = 0x8000; - p->brightness = qcam->brightness << 8; - p->contrast = qcam->contrast << 8; - p->whiteness = qcam->whitebal << 8; - p->depth = qcam->bpp; - p->palette = VIDEO_PALETTE_GREY; - return 0; - } - case VIDIOCSPICT: - { - struct video_picture *p = arg; - if (p->palette != VIDEO_PALETTE_GREY) - return -EINVAL; - if (p->depth != 4 && p->depth != 6) - return -EINVAL; - - /* - * Now load the camera. - */ - - qcam->brightness = p->brightness >> 8; - qcam->contrast = p->contrast >> 8; - qcam->whitebal = p->whiteness >> 8; - qcam->bpp = p->depth; - - mutex_lock(&qcam->lock); - qc_setscanmode(qcam); - mutex_unlock(&qcam->lock); - qcam->status |= QC_PARAM_CHANGE; + struct qcam *qcam = video_drvdata(file); - return 0; - } - case VIDIOCSWIN: - { - struct video_window *vw = arg; - if (vw->flags) - return -EINVAL; - if (vw->clipcount) - return -EINVAL; - if (vw->height < 60 || vw->height > 240) - return -EINVAL; - if (vw->width < 80 || vw->width > 320) - return -EINVAL; - - qcam->width = 320; - qcam->height = 240; - qcam->transfer_scale = 4; - - if (vw->width >= 160 && vw->height >= 120) - qcam->transfer_scale = 2; - if (vw->width >= 320 && vw->height >= 240) { - qcam->width = 320; - qcam->height = 240; - qcam->transfer_scale = 1; - } - mutex_lock(&qcam->lock); - qc_setscanmode(qcam); - mutex_unlock(&qcam->lock); + strlcpy(vcap->driver, qcam->v4l2_dev.name, sizeof(vcap->driver)); + strlcpy(vcap->card, "B&W Quickcam", sizeof(vcap->card)); + strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info)); + vcap->version = KERNEL_VERSION(0, 0, 2); + vcap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE; + return 0; +} - /* We must update the camera before we grab. We could - just have changed the grab size */ - qcam->status |= QC_PARAM_CHANGE; +static int qcam_enum_input(struct file *file, void *fh, struct v4l2_input *vin) +{ + if (vin->index > 0) + return -EINVAL; + strlcpy(vin->name, "Camera", sizeof(vin->name)); + vin->type = V4L2_INPUT_TYPE_CAMERA; + vin->audioset = 0; + vin->tuner = 0; + vin->std = 0; + vin->status = 0; + return 0; +} - /* Ok we figured out what to use from our wide choice */ - return 0; - } - case VIDIOCGWIN: - { - struct video_window *vw = arg; +static int qcam_g_input(struct file *file, void *fh, unsigned int *inp) +{ + *inp = 0; + return 0; +} - memset(vw, 0, sizeof(*vw)); - vw->width = qcam->width / qcam->transfer_scale; - vw->height = qcam->height / qcam->transfer_scale; - return 0; - } - case VIDIOCKEY: - return 0; - case VIDIOCCAPTURE: - case VIDIOCGFBUF: - case VIDIOCSFBUF: - case VIDIOCGFREQ: - case VIDIOCSFREQ: - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: - return -EINVAL; +static int qcam_s_input(struct file *file, void *fh, unsigned int inp) +{ + return (inp > 0) ? -EINVAL : 0; +} + +static int qcam_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *qc) +{ + switch (qc->id) { + case V4L2_CID_BRIGHTNESS: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 180); + case V4L2_CID_CONTRAST: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 192); + case V4L2_CID_GAMMA: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 105); + } + return -EINVAL; +} + +static int qcam_g_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct qcam *qcam = video_drvdata(file); + int ret = 0; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = qcam->brightness; + break; + case V4L2_CID_CONTRAST: + ctrl->value = qcam->contrast; + break; + case V4L2_CID_GAMMA: + ctrl->value = qcam->whitebal; + break; default: - return -ENOIOCTLCMD; + ret = -EINVAL; + break; } + return ret; +} + +static int qcam_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct qcam *qcam = video_drvdata(file); + int ret = 0; + + mutex_lock(&qcam->lock); + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + qcam->brightness = ctrl->value; + break; + case V4L2_CID_CONTRAST: + qcam->contrast = ctrl->value; + break; + case V4L2_CID_GAMMA: + qcam->whitebal = ctrl->value; + break; + default: + ret = -EINVAL; + break; + } + if (ret == 0) { + qc_setscanmode(qcam); + qcam->status |= QC_PARAM_CHANGE; + } + mutex_unlock(&qcam->lock); + return ret; +} + +static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) +{ + struct qcam *qcam = video_drvdata(file); + struct v4l2_pix_format *pix = &fmt->fmt.pix; + + pix->width = qcam->width / qcam->transfer_scale; + pix->height = qcam->height / qcam->transfer_scale; + pix->pixelformat = (qcam->bpp == 4) ? V4L2_PIX_FMT_Y4 : V4L2_PIX_FMT_Y6; + pix->field = V4L2_FIELD_NONE; + pix->bytesperline = qcam->width; + pix->sizeimage = qcam->width * qcam->height; + /* Just a guess */ + pix->colorspace = V4L2_COLORSPACE_SRGB; + return 0; +} + +static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) +{ + struct v4l2_pix_format *pix = &fmt->fmt.pix; + + if (pix->height <= 60 || pix->width <= 80) { + pix->height = 60; + pix->width = 80; + } else if (pix->height <= 120 || pix->width <= 160) { + pix->height = 120; + pix->width = 160; + } else { + pix->height = 240; + pix->width = 320; + } + if (pix->pixelformat != V4L2_PIX_FMT_Y4 && + pix->pixelformat != V4L2_PIX_FMT_Y6) + pix->pixelformat = V4L2_PIX_FMT_Y4; + pix->field = V4L2_FIELD_NONE; + pix->bytesperline = pix->width; + pix->sizeimage = pix->width * pix->height; + /* Just a guess */ + pix->colorspace = V4L2_COLORSPACE_SRGB; + return 0; +} + +static int qcam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) +{ + struct qcam *qcam = video_drvdata(file); + struct v4l2_pix_format *pix = &fmt->fmt.pix; + int ret = qcam_try_fmt_vid_cap(file, fh, fmt); + + if (ret) + return ret; + qcam->width = 320; + qcam->height = 240; + if (pix->height == 60) + qcam->transfer_scale = 4; + else if (pix->height == 120) + qcam->transfer_scale = 2; + else + qcam->transfer_scale = 1; + if (pix->pixelformat == V4L2_PIX_FMT_Y6) + qcam->bpp = 6; + else + qcam->bpp = 4; + + mutex_lock(&qcam->lock); + qc_setscanmode(qcam); + /* We must update the camera before we grab. We could + just have changed the grab size */ + qcam->status |= QC_PARAM_CHANGE; + mutex_unlock(&qcam->lock); return 0; } -static long qcam_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) +static int qcam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt) { - return video_usercopy(file, cmd, arg, qcam_do_ioctl); + static struct v4l2_fmtdesc formats[] = { + { 0, 0, 0, + "4-Bit Monochrome", V4L2_PIX_FMT_Y4, + { 0, 0, 0, 0 } + }, + { 0, 0, 0, + "6-Bit Monochrome", V4L2_PIX_FMT_Y6, + { 0, 0, 0, 0 } + }, + }; + enum v4l2_buf_type type = fmt->type; + + if (fmt->index > 1) + return -EINVAL; + + *fmt = formats[fmt->index]; + fmt->type = type; + return 0; } static ssize_t qcam_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct video_device *v = video_devdata(file); - struct qcam_device *qcam = (struct qcam_device *)v; + struct qcam *qcam = video_drvdata(file); int len; parport_claim_or_block(qcam->pdev); @@ -858,43 +858,112 @@ static ssize_t qcam_read(struct file *file, char __user *buf, return len; } -static int qcam_exclusive_open(struct file *file) +static const struct v4l2_file_operations qcam_fops = { + .owner = THIS_MODULE, + .ioctl = video_ioctl2, + .read = qcam_read, +}; + +static const struct v4l2_ioctl_ops qcam_ioctl_ops = { + .vidioc_querycap = qcam_querycap, + .vidioc_g_input = qcam_g_input, + .vidioc_s_input = qcam_s_input, + .vidioc_enum_input = qcam_enum_input, + .vidioc_queryctrl = qcam_queryctrl, + .vidioc_g_ctrl = qcam_g_ctrl, + .vidioc_s_ctrl = qcam_s_ctrl, + .vidioc_enum_fmt_vid_cap = qcam_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = qcam_g_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = qcam_s_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = qcam_try_fmt_vid_cap, +}; + +/* Initialize the QuickCam driver control structure. This is where + * defaults are set for people who don't have a config file.*/ + +static struct qcam *qcam_init(struct parport *port) { - struct video_device *dev = video_devdata(file); - struct qcam_device *qcam = (struct qcam_device *)dev; + struct qcam *qcam; + struct v4l2_device *v4l2_dev; + + qcam = kzalloc(sizeof(struct qcam), GFP_KERNEL); + if (qcam == NULL) + return NULL; + + v4l2_dev = &qcam->v4l2_dev; + strlcpy(v4l2_dev->name, "bw-qcam", sizeof(v4l2_dev->name)); - return test_and_set_bit(0, &qcam->in_use) ? -EBUSY : 0; + if (v4l2_device_register(NULL, v4l2_dev) < 0) { + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + return NULL; + } + + qcam->pport = port; + qcam->pdev = parport_register_device(port, "bw-qcam", NULL, NULL, + NULL, 0, NULL); + if (qcam->pdev == NULL) { + v4l2_err(v4l2_dev, "couldn't register for %s.\n", port->name); + kfree(qcam); + return NULL; + } + + strlcpy(qcam->vdev.name, "Connectix QuickCam", sizeof(qcam->vdev.name)); + qcam->vdev.v4l2_dev = v4l2_dev; + qcam->vdev.fops = &qcam_fops; + qcam->vdev.ioctl_ops = &qcam_ioctl_ops; + qcam->vdev.release = video_device_release_empty; + video_set_drvdata(&qcam->vdev, qcam); + + mutex_init(&qcam->lock); + + qcam->port_mode = (QC_ANY | QC_NOTSET); + qcam->width = 320; + qcam->height = 240; + qcam->bpp = 4; + qcam->transfer_scale = 2; + qcam->contrast = 192; + qcam->brightness = 180; + qcam->whitebal = 105; + qcam->top = 1; + qcam->left = 14; + qcam->mode = -1; + qcam->status = QC_PARAM_CHANGE; + return qcam; } -static int qcam_exclusive_release(struct file *file) +static int qc_calibrate(struct qcam *q) { - struct video_device *dev = video_devdata(file); - struct qcam_device *qcam = (struct qcam_device *)dev; + /* + * Bugfix by Hanno Mueller hmueller@kabel.de, Mai 21 96 + * The white balance is an individual value for each + * quickcam. + */ - clear_bit(0, &qcam->in_use); - return 0; -} + int value; + int count = 0; -static const struct v4l2_file_operations qcam_fops = { - .owner = THIS_MODULE, - .open = qcam_exclusive_open, - .release = qcam_exclusive_release, - .ioctl = qcam_ioctl, - .read = qcam_read, -}; -static struct video_device qcam_template = { - .name = "Connectix Quickcam", - .fops = &qcam_fops, - .release = video_device_release_empty, -}; + qc_command(q, 27); /* AutoAdjustOffset */ + qc_command(q, 0); /* Dummy Parameter, ignored by the camera */ -#define MAX_CAMS 4 -static struct qcam_device *qcams[MAX_CAMS]; -static unsigned int num_cams; + /* GetOffset (33) will read 255 until autocalibration */ + /* is finished. After that, a value of 1-254 will be */ + /* returned. */ + + do { + qc_command(q, 33); + value = qc_readparam(q); + mdelay(1); + schedule(); + count++; + } while (value == 0xff && count < 2048); + + q->whitebal = value; + return value; +} static int init_bwqcam(struct parport *port) { - struct qcam_device *qcam; + struct qcam *qcam; if (num_cams == MAX_CAMS) { printk(KERN_ERR "Too many Quickcams (max %d)\n", MAX_CAMS); @@ -919,7 +988,7 @@ static int init_bwqcam(struct parport *port) parport_release(qcam->pdev); - printk(KERN_INFO "Connectix Quickcam on %s\n", qcam->pport->name); + v4l2_info(&qcam->v4l2_dev, "Connectix Quickcam on %s\n", qcam->pport->name); if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { parport_unregister_device(qcam->pdev); @@ -932,7 +1001,7 @@ static int init_bwqcam(struct parport *port) return 0; } -static void close_bwqcam(struct qcam_device *qcam) +static void close_bwqcam(struct qcam *qcam) { video_unregister_device(&qcam->vdev); parport_unregister_device(qcam->pdev); @@ -983,7 +1052,7 @@ static void bwqcam_detach(struct parport *port) { int i; for (i = 0; i < num_cams; i++) { - struct qcam_device *qcam = qcams[i]; + struct qcam *qcam = qcams[i]; if (qcam && qcam->pdev->port == port) { qcams[i] = NULL; close_bwqcam(qcam); diff --git a/drivers/media/video/bw-qcam.h b/drivers/media/video/bw-qcam.h deleted file mode 100644 index 8a60c5d..0000000 --- a/drivers/media/video/bw-qcam.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Video4Linux bw-qcam driver - * - * Derived from code.. - */ - -/****************************************************************** - -Copyright (C) 1996 by Scott Laird - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL SCOTT LAIRD BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -******************************************************************/ - -/* One from column A... */ -#define QC_NOTSET 0 -#define QC_UNIDIR 1 -#define QC_BIDIR 2 -#define QC_SERIAL 3 - -/* ... and one from column B */ -#define QC_ANY 0x00 -#define QC_FORCE_UNIDIR 0x10 -#define QC_FORCE_BIDIR 0x20 -#define QC_FORCE_SERIAL 0x30 -/* in the port_mode member */ - -#define QC_MODE_MASK 0x07 -#define QC_FORCE_MASK 0x70 - -#define MAX_HEIGHT 243 -#define MAX_WIDTH 336 - -/* Bit fields for status flags */ -#define QC_PARAM_CHANGE 0x01 /* Camera status change has occurred */ - -struct qcam_device { - struct video_device vdev; - struct pardevice *pdev; - struct parport *pport; - struct mutex lock; - int width, height; - int bpp; - int mode; - int contrast, brightness, whitebal; - int port_mode; - int transfer_scale; - int top, left; - int status; - unsigned int saved_bits; - unsigned long in_use; -}; diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c index 8f1dd88..6e4b196 100644 --- a/drivers/media/video/c-qcam.c +++ b/drivers/media/video/c-qcam.c @@ -33,15 +33,17 @@ #include <linux/mm.h> #include <linux/parport.h> #include <linux/sched.h> -#include <linux/videodev.h> -#include <media/v4l2-common.h> -#include <media/v4l2-ioctl.h> #include <linux/mutex.h> #include <linux/jiffies.h> - +#include <linux/version.h> +#include <linux/videodev2.h> #include <asm/uaccess.h> +#include <media/v4l2-device.h> +#include <media/v4l2-common.h> +#include <media/v4l2-ioctl.h> -struct qcam_device { +struct qcam { + struct v4l2_device v4l2_dev; struct video_device vdev; struct pardevice *pdev; struct parport *pport; @@ -51,7 +53,6 @@ struct qcam_device { int contrast, brightness, whitebal; int top, left; unsigned int bidirectional; - unsigned long in_use; struct mutex lock; }; @@ -68,33 +69,45 @@ struct qcam_device { #define QC_DECIMATION_2 2 #define QC_DECIMATION_4 4 -#define BANNER "Colour QuickCam for Video4Linux v0.05" +#define BANNER "Colour QuickCam for Video4Linux v0.06" static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 }; static int probe = 2; static int force_rgb; static int video_nr = -1; -static inline void qcam_set_ack(struct qcam_device *qcam, unsigned int i) +/* FIXME: parport=auto would never have worked, surely? --RR */ +MODULE_PARM_DESC(parport, "parport=<auto|n[,n]...> for port detection method\n" + "probe=<0|1|2> for camera detection method\n" + "force_rgb=<0|1> for RGB data format (default BGR)"); +module_param_array(parport, int, NULL, 0); +module_param(probe, int, 0); +module_param(force_rgb, bool, 0); +module_param(video_nr, int, 0); + +static struct qcam *qcams[MAX_CAMS]; +static unsigned int num_cams; + +static inline void qcam_set_ack(struct qcam *qcam, unsigned int i) { /* note: the QC specs refer to the PCAck pin by voltage, not software level. PC ports have builtin inverters. */ parport_frob_control(qcam->pport, 8, i ? 8 : 0); } -static inline unsigned int qcam_ready1(struct qcam_device *qcam) +static inline unsigned int qcam_ready1(struct qcam *qcam) { return (parport_read_status(qcam->pport) & 0x8) ? 1 : 0; } -static inline unsigned int qcam_ready2(struct qcam_device *qcam) +static inline unsigned int qcam_ready2(struct qcam *qcam) { return (parport_read_data(qcam->pport) & 0x1) ? 1 : 0; } -static unsigned int qcam_await_ready1(struct qcam_device *qcam, - int value) +static unsigned int qcam_await_ready1(struct qcam *qcam, int value) { + struct v4l2_device *v4l2_dev = &qcam->v4l2_dev; unsigned long oldjiffies = jiffies; unsigned int i; @@ -112,14 +125,15 @@ static unsigned int qcam_await_ready1(struct qcam_device *qcam, } /* Probably somebody pulled the plug out. Not much we can do. */ - printk(KERN_ERR "c-qcam: ready1 timeout (%d) %x %x\n", value, + v4l2_err(v4l2_dev, "ready1 timeout (%d) %x %x\n", value, parport_read_status(qcam->pport), parport_read_control(qcam->pport)); return 1; } -static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value) +static unsigned int qcam_await_ready2(struct qcam *qcam, int value) { + struct v4l2_device *v4l2_dev = &qcam->v4l2_dev; unsigned long oldjiffies = jiffies; unsigned int i; @@ -137,14 +151,14 @@ static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value) } /* Probably somebody pulled the plug out. Not much we can do. */ - printk(KERN_ERR "c-qcam: ready2 timeout (%d) %x %x %x\n", value, + v4l2_err(v4l2_dev, "ready2 timeout (%d) %x %x %x\n", value, parport_read_status(qcam->pport), parport_read_control(qcam->pport), parport_read_data(qcam->pport)); return 1; } -static int qcam_read_data(struct qcam_device *qcam) +static int qcam_read_data(struct qcam *qcam) { unsigned int idata; @@ -159,21 +173,22 @@ static int qcam_read_data(struct qcam_device *qcam) return idata; } -static int qcam_write_data(struct qcam_device *qcam, unsigned int data) +static int qcam_write_data(struct qcam *qcam, unsigned int data) { + struct v4l2_device *v4l2_dev = &qcam->v4l2_dev; unsigned int idata; parport_write_data(qcam->pport, data); idata = qcam_read_data(qcam); if (data != idata) { - printk(KERN_WARNING "cqcam: sent %x but received %x\n", data, + v4l2_warn(v4l2_dev, "sent %x but received %x\n", data, idata); return 1; } return 0; } -static inline int qcam_set(struct qcam_device *qcam, unsigned int cmd, unsigned int data) +static inline int qcam_set(struct qcam *qcam, unsigned int cmd, unsigned int data) { if (qcam_write_data(qcam, cmd)) return -1; @@ -182,14 +197,14 @@ static inline int qcam_set(struct qcam_device *qcam, unsigned int cmd, unsigned return 0; } -static inline int qcam_get(struct qcam_device *qcam, unsigned int cmd) +static inline int qcam_get(struct qcam *qcam, unsigned int cmd) { if (qcam_write_data(qcam, cmd)) return -1; return qcam_read_data(qcam); } -static int qc_detect(struct qcam_device *qcam) +static int qc_detect(struct qcam *qcam) { unsigned int stat, ostat, i, count = 0; @@ -246,7 +261,7 @@ static int qc_detect(struct qcam_device *qcam) return 0; } -static void qc_reset(struct qcam_device *qcam) +static void qc_reset(struct qcam *qcam) { parport_write_control(qcam->pport, 0xc); parport_write_control(qcam->pport, 0x8); @@ -258,55 +273,55 @@ static void qc_reset(struct qcam_device *qcam) /* Reset the QuickCam and program for brightness, contrast, * white-balance, and resolution. */ -static void qc_setup(struct qcam_device *q) +static void qc_setup(struct qcam *qcam) { - qc_reset(q); + qc_reset(qcam); /* Set the brightness. */ - qcam_set(q, 11, q->brightness); + qcam_set(qcam, 11, qcam->brightness); /* Set the height and width. These refer to the actual CCD area *before* applying the selected decimation. */ - qcam_set(q, 17, q->ccd_height); - qcam_set(q, 19, q->ccd_width / 2); + qcam_set(qcam, 17, qcam->ccd_height); + qcam_set(qcam, 19, qcam->ccd_width / 2); /* Set top and left. */ - qcam_set(q, 0xd, q->top); - qcam_set(q, 0xf, q->left); + qcam_set(qcam, 0xd, qcam->top); + qcam_set(qcam, 0xf, qcam->left); /* Set contrast and white balance. */ - qcam_set(q, 0x19, q->contrast); - qcam_set(q, 0x1f, q->whitebal); + qcam_set(qcam, 0x19, qcam->contrast); + qcam_set(qcam, 0x1f, qcam->whitebal); /* Set the speed. */ - qcam_set(q, 45, 2); + qcam_set(qcam, 45, 2); } /* Read some bytes from the camera and put them in the buffer. nbytes should be a multiple of 3, because bidirectional mode gives us three bytes at a time. */ -static unsigned int qcam_read_bytes(struct qcam_device *q, unsigned char *buf, unsigned int nbytes) +static unsigned int qcam_read_bytes(struct qcam *qcam, unsigned char *buf, unsigned int nbytes) { unsigned int bytes = 0; - qcam_set_ack(q, 0); - if (q->bidirectional) { + qcam_set_ack(qcam, 0); + if (qcam->bidirectional) { /* It's a bidirectional port */ while (bytes < nbytes) { unsigned int lo1, hi1, lo2, hi2; unsigned char r, g, b; - if (qcam_await_ready2(q, 1)) + if (qcam_await_ready2(qcam, 1)) return bytes; - lo1 = parport_read_data(q->pport) >> 1; - hi1 = ((parport_read_status(q->pport) >> 3) & 0x1f) ^ 0x10; - qcam_set_ack(q, 1); - if (qcam_await_ready2(q, 0)) + lo1 = parport_read_data(qcam->pport) >> 1; + hi1 = ((parport_read_status(qcam->pport) >> 3) & 0x1f) ^ 0x10; + qcam_set_ack(qcam, 1); + if (qcam_await_ready2(qcam, 0)) return bytes; - lo2 = parport_read_data(q->pport) >> 1; - hi2 = ((parport_read_status(q->pport) >> 3) & 0x1f) ^ 0x10; - qcam_set_ack(q, 0); + lo2 = parport_read_data(qcam->pport) >> 1; + hi2 = ((parport_read_status(qcam->pport) >> 3) & 0x1f) ^ 0x10; + qcam_set_ack(qcam, 0); r = lo1 | ((hi1 & 1) << 7); g = ((hi1 & 0x1e) << 3) | ((hi2 & 0x1e) >> 1); b = lo2 | ((hi2 & 1) << 7); @@ -328,14 +343,14 @@ static unsigned int qcam_read_bytes(struct qcam_device *q, unsigned char *buf, u while (bytes < nbytes) { unsigned int hi, lo; - if (qcam_await_ready1(q, 1)) + if (qcam_await_ready1(qcam, 1)) return bytes; - hi = (parport_read_status(q->pport) & 0xf0); - qcam_set_ack(q, 1); - if (qcam_await_ready1(q, 0)) + hi = (parport_read_status(qcam->pport) & 0xf0); + qcam_set_ack(qcam, 1); + if (qcam_await_ready1(qcam, 0)) return bytes; - lo = (parport_read_status(q->pport) & 0xf0); - qcam_set_ack(q, 0); + lo = (parport_read_status(qcam->pport) & 0xf0); + qcam_set_ack(qcam, 0); /* flip some bits */ rgb[(i = bytes++ % 3)] = (hi | (lo >> 4)) ^ 0x88; if (i >= 2) { @@ -361,10 +376,11 @@ get_fragment: #define BUFSZ 150 -static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long len) +static long qc_capture(struct qcam *qcam, char __user *buf, unsigned long len) { + struct v4l2_device *v4l2_dev = &qcam->v4l2_dev; unsigned lines, pixelsperline, bitsperxfer; - unsigned int is_bi_dir = q->bidirectional; + unsigned int is_bi_dir = qcam->bidirectional; size_t wantlen, outptr = 0; char tmpbuf[BUFSZ]; @@ -373,10 +389,10 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le /* Wait for camera to become ready */ for (;;) { - int i = qcam_get(q, 41); + int i = qcam_get(qcam, 41); if (i == -1) { - qc_setup(q); + qc_setup(qcam); return -EIO; } if ((i & 0x80) == 0) @@ -384,25 +400,25 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le schedule(); } - if (qcam_set(q, 7, (q->mode | (is_bi_dir ? 1 : 0)) + 1)) + if (qcam_set(qcam, 7, (qcam->mode | (is_bi_dir ? 1 : 0)) + 1)) return -EIO; - lines = q->height; - pixelsperline = q->width; + lines = qcam->height; + pixelsperline = qcam->width; bitsperxfer = (is_bi_dir) ? 24 : 8; if (is_bi_dir) { /* Turn the port around */ - parport_data_reverse(q->pport); + parport_data_reverse(qcam->pport); mdelay(3); - qcam_set_ack(q, 0); - if (qcam_await_ready1(q, 1)) { - qc_setup(q); + qcam_set_ack(qcam, 0); + if (qcam_await_ready1(qcam, 1)) { + qc_setup(qcam); return -EIO; } - qcam_set_ack(q, 1); - if (qcam_await_ready1(q, 0)) { - qc_setup(q); + qcam_set_ack(qcam, 1); + if (qcam_await_ready1(qcam, 0)) { + qc_setup(qcam); return -EIO; } } @@ -413,7 +429,7 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le size_t t, s; s = (wantlen > BUFSZ) ? BUFSZ : wantlen; - t = qcam_read_bytes(q, tmpbuf, s); + t = qcam_read_bytes(qcam, tmpbuf, s); if (outptr < len) { size_t sz = len - outptr; @@ -432,10 +448,10 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le len = outptr; if (wantlen) { - printk(KERN_ERR "qcam: short read.\n"); + v4l2_err(v4l2_dev, "short read.\n"); if (is_bi_dir) - parport_data_forward(q->pport); - qc_setup(q); + parport_data_forward(qcam->pport); + qc_setup(qcam); return len; } @@ -443,49 +459,49 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le int l; do { - l = qcam_read_bytes(q, tmpbuf, 3); + l = qcam_read_bytes(qcam, tmpbuf, 3); cond_resched(); } while (l && (tmpbuf[0] == 0x7e || tmpbuf[1] == 0x7e || tmpbuf[2] == 0x7e)); if (force_rgb) { if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf) - printk(KERN_ERR "qcam: bad EOF\n"); + v4l2_err(v4l2_dev, "bad EOF\n"); } else { if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe) - printk(KERN_ERR "qcam: bad EOF\n"); + v4l2_err(v4l2_dev, "bad EOF\n"); } - qcam_set_ack(q, 0); - if (qcam_await_ready1(q, 1)) { - printk(KERN_ERR "qcam: no ack after EOF\n"); - parport_data_forward(q->pport); - qc_setup(q); + qcam_set_ack(qcam, 0); + if (qcam_await_ready1(qcam, 1)) { + v4l2_err(v4l2_dev, "no ack after EOF\n"); + parport_data_forward(qcam->pport); + qc_setup(qcam); return len; } - parport_data_forward(q->pport); + parport_data_forward(qcam->pport); mdelay(3); - qcam_set_ack(q, 1); - if (qcam_await_ready1(q, 0)) { - printk(KERN_ERR "qcam: no ack to port turnaround\n"); - qc_setup(q); + qcam_set_ack(qcam, 1); + if (qcam_await_ready1(qcam, 0)) { + v4l2_err(v4l2_dev, "no ack to port turnaround\n"); + qc_setup(qcam); return len; } } else { int l; do { - l = qcam_read_bytes(q, tmpbuf, 1); + l = qcam_read_bytes(qcam, tmpbuf, 1); cond_resched(); } while (l && tmpbuf[0] == 0x7e); - l = qcam_read_bytes(q, tmpbuf + 1, 2); + l = qcam_read_bytes(qcam, tmpbuf + 1, 2); if (force_rgb) { if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf) - printk(KERN_ERR "qcam: bad EOF\n"); + v4l2_err(v4l2_dev, "bad EOF\n"); } else { if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe) - printk(KERN_ERR "qcam: bad EOF\n"); + v4l2_err(v4l2_dev, "bad EOF\n"); } } - qcam_write_data(q, 0); + qcam_write_data(qcam, 0); return len; } @@ -493,184 +509,202 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le * Video4linux interfacing */ -static long qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg) +static int qcam_querycap(struct file *file, void *priv, + struct v4l2_capability *vcap) { - struct video_device *dev = video_devdata(file); - struct qcam_device *qcam = (struct qcam_device *)dev; + struct qcam *qcam = video_drvdata(file); - switch (cmd) { - case VIDIOCGCAP: - { - struct video_capability *b = arg; + strlcpy(vcap->driver, qcam->v4l2_dev.name, sizeof(vcap->driver)); + strlcpy(vcap->card, "Color Quickcam", sizeof(vcap->card)); + strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info)); + vcap->version = KERNEL_VERSION(0, 0, 3); + vcap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE; + return 0; +} - strcpy(b->name, "Quickcam"); - b->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES; - b->channels = 1; - b->audios = 0; - b->maxwidth = 320; - b->maxheight = 240; - b->minwidth = 80; - b->minheight = 60; - return 0; - } - case VIDIOCGCHAN: - { - struct video_channel *v = arg; - - if (v->channel != 0) - return -EINVAL; - v->flags = 0; - v->tuners = 0; - /* Good question.. its composite or SVHS so.. */ - v->type = VIDEO_TYPE_CAMERA; - strcpy(v->name, "Camera"); - return 0; - } - case VIDIOCSCHAN: - { - struct video_channel *v = arg; +static int qcam_enum_input(struct file *file, void *fh, struct v4l2_input *vin) +{ + if (vin->index > 0) + return -EINVAL; + strlcpy(vin->name, "Camera", sizeof(vin->name)); + vin->type = V4L2_INPUT_TYPE_CAMERA; + vin->audioset = 0; + vin->tuner = 0; + vin->std = 0; + vin->status = 0; + return 0; +} - if (v->channel != 0) - return -EINVAL; - return 0; - } - case VIDIOCGTUNER: - { - struct video_tuner *v = arg; - - if (v->tuner) - return -EINVAL; - memset(v, 0, sizeof(*v)); - strcpy(v->name, "Format"); - v->mode = VIDEO_MODE_AUTO; - return 0; +static int qcam_g_input(struct file *file, void *fh, unsigned int *inp) +{ + *inp = 0; + return 0; +} + +static int qcam_s_input(struct file *file, void *fh, unsigned int inp) +{ + return (inp > 0) ? -EINVAL : 0; +} + +static int qcam_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *qc) +{ + switch (qc->id) { + case V4L2_CID_BRIGHTNESS: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 240); + case V4L2_CID_CONTRAST: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 192); + case V4L2_CID_GAMMA: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128); } - case VIDIOCSTUNER: - { - struct video_tuner *v = arg; - - if (v->tuner) - return -EINVAL; - if (v->mode != VIDEO_MODE_AUTO) - return -EINVAL; - return 0; + return -EINVAL; +} + +static int qcam_g_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct qcam *qcam = video_drvdata(file); + int ret = 0; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = qcam->brightness; + break; + case V4L2_CID_CONTRAST: + ctrl->value = qcam->contrast; + break; + case V4L2_CID_GAMMA: + ctrl->value = qcam->whitebal; + break; + default: + ret = -EINVAL; + break; } - case VIDIOCGPICT: - { - struct video_picture *p = arg; - - p->colour = 0x8000; - p->hue = 0x8000; - p->brightness = qcam->brightness << 8; - p->contrast = qcam->contrast << 8; - p->whiteness = qcam->whitebal << 8; - p->depth = 24; - p->palette = VIDEO_PALETTE_RGB24; - return 0; + return ret; +} + +static int qcam_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct qcam *qcam = video_drvdata(file); + int ret = 0; + + mutex_lock(&qcam->lock); + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + qcam->brightness = ctrl->value; + break; + case V4L2_CID_CONTRAST: + qcam->contrast = ctrl->value; + break; + case V4L2_CID_GAMMA: + qcam->whitebal = ctrl->value; + break; + default: + ret = -EINVAL; + break; } - case VIDIOCSPICT: - { - struct video_picture *p = arg; - - /* - * Sanity check args - */ - if (p->depth != 24 || p->palette != VIDEO_PALETTE_RGB24) - return -EINVAL; - - /* - * Now load the camera. - */ - qcam->brightness = p->brightness >> 8; - qcam->contrast = p->contrast >> 8; - qcam->whitebal = p->whiteness >> 8; - - mutex_lock(&qcam->lock); + if (ret == 0) { parport_claim_or_block(qcam->pdev); qc_setup(qcam); parport_release(qcam->pdev); - mutex_unlock(&qcam->lock); - return 0; } - case VIDIOCSWIN: - { - struct video_window *vw = arg; - - if (vw->flags) - return -EINVAL; - if (vw->clipcount) - return -EINVAL; - if (vw->height < 60 || vw->height > 240) - return -EINVAL; - if (vw->width < 80 || vw->width > 320) - return -EINVAL; - - qcam->width = 80; - qcam->height = 60; - qcam->mode = QC_DECIMATION_4; + mutex_unlock(&qcam->lock); + return ret; +} - if (vw->width >= 160 && vw->height >= 120) { - qcam->width = 160; - qcam->height = 120; - qcam->mode = QC_DECIMATION_2; - } - if (vw->width >= 320 && vw->height >= 240) { - qcam->width = 320; - qcam->height = 240; - qcam->mode = QC_DECIMATION_1; - } - qcam->mode |= QC_MILLIONS; -#if 0 - if (vw->width >= 640 && vw->height >= 480) { - qcam->width = 640; - qcam->height = 480; - qcam->mode = QC_BILLIONS | QC_DECIMATION_1; - } -#endif - /* Ok we figured out what to use from our - wide choice */ - mutex_lock(&qcam->lock); - parport_claim_or_block(qcam->pdev); - qc_setup(qcam); - parport_release(qcam->pdev); - mutex_unlock(&qcam->lock); - return 0; - } - case VIDIOCGWIN: - { - struct video_window *vw = arg; - memset(vw, 0, sizeof(*vw)); - vw->width = qcam->width; - vw->height = qcam->height; - return 0; +static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) +{ + struct qcam *qcam = video_drvdata(file); + struct v4l2_pix_format *pix = &fmt->fmt.pix; + + pix->width = qcam->width; + pix->height = qcam->height; + pix->pixelformat = V4L2_PIX_FMT_RGB24; + pix->field = V4L2_FIELD_NONE; + pix->bytesperline = 3 * qcam->width; + pix->sizeimage = 3 * qcam->width * qcam->height; + /* Just a guess */ + pix->colorspace = V4L2_COLORSPACE_SRGB; + return 0; +} + +static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) +{ + struct v4l2_pix_format *pix = &fmt->fmt.pix; + + if (pix->height < 60 || pix->width < 80) { + pix->height = 60; + pix->width = 80; + } else if (pix->height < 120 || pix->width < 160) { + pix->height = 120; + pix->width = 160; + } else { + pix->height = 240; + pix->width = 320; } - case VIDIOCKEY: - return 0; - case VIDIOCCAPTURE: - case VIDIOCGFBUF: - case VIDIOCSFBUF: - case VIDIOCGFREQ: - case VIDIOCSFREQ: - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: - return -EINVAL; + pix->pixelformat = V4L2_PIX_FMT_RGB24; + pix->field = V4L2_FIELD_NONE; + pix->bytesperline = 3 * pix->width; + pix->sizeimage = 3 * pix->width * pix->height; + /* Just a guess */ + pix->colorspace = V4L2_COLORSPACE_SRGB; + return 0; +} + +static int qcam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) +{ + struct qcam *qcam = video_drvdata(file); + struct v4l2_pix_format *pix = &fmt->fmt.pix; + int ret = qcam_try_fmt_vid_cap(file, fh, fmt); + + if (ret) + return ret; + switch (pix->height) { + case 60: + qcam->mode = QC_DECIMATION_4; + break; + case 120: + qcam->mode = QC_DECIMATION_2; + break; default: - return -ENOIOCTLCMD; + qcam->mode = QC_DECIMATION_1; + break; } + + mutex_lock(&qcam->lock); + qcam->mode |= QC_MILLIONS; + qcam->height = pix->height; + qcam->width = pix->width; + parport_claim_or_block(qcam->pdev); + qc_setup(qcam); + parport_release(qcam->pdev); + mutex_unlock(&qcam->lock); return 0; } -static long qcam_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) +static int qcam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt) { - return video_usercopy(file, cmd, arg, qcam_do_ioctl); + static struct v4l2_fmtdesc formats[] = { + { 0, 0, 0, + "RGB 8:8:8", V4L2_PIX_FMT_RGB24, + { 0, 0, 0, 0 } + }, + }; + enum v4l2_buf_type type = fmt->type; + + if (fmt->index > 0) + return -EINVAL; + + *fmt = formats[fmt->index]; + fmt->type = type; + return 0; } static ssize_t qcam_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct video_device *v = video_devdata(file); - struct qcam_device *qcam = (struct qcam_device *)v; + struct qcam *qcam = video_drvdata(file); int len; mutex_lock(&qcam->lock); @@ -682,81 +716,80 @@ static ssize_t qcam_read(struct file *file, char __user *buf, return len; } -static int qcam_exclusive_open(struct file *file) -{ - struct video_device *dev = video_devdata(file); - struct qcam_device *qcam = (struct qcam_device *)dev; - - return test_and_set_bit(0, &qcam->in_use) ? -EBUSY : 0; -} - -static int qcam_exclusive_release(struct file *file) -{ - struct video_device *dev = video_devdata(file); - struct qcam_device *qcam = (struct qcam_device *)dev; - - clear_bit(0, &qcam->in_use); - return 0; -} - -/* video device template */ static const struct v4l2_file_operations qcam_fops = { .owner = THIS_MODULE, - .open = qcam_exclusive_open, - .release = qcam_exclusive_release, - .ioctl = qcam_ioctl, + .ioctl = video_ioctl2, .read = qcam_read, }; -static struct video_device qcam_template = { - .name = "Colour QuickCam", - .fops = &qcam_fops, - .release = video_device_release_empty, +static const struct v4l2_ioctl_ops qcam_ioctl_ops = { + .vidioc_querycap = qcam_querycap, + .vidioc_g_input = qcam_g_input, + .vidioc_s_input = qcam_s_input, + .vidioc_enum_input = qcam_enum_input, + .vidioc_queryctrl = qcam_queryctrl, + .vidioc_g_ctrl = qcam_g_ctrl, + .vidioc_s_ctrl = qcam_s_ctrl, + .vidioc_enum_fmt_vid_cap = qcam_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = qcam_g_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = qcam_s_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = qcam_try_fmt_vid_cap, }; /* Initialize the QuickCam driver control structure. */ -static struct qcam_device *qcam_init(struct parport *port) +static struct qcam *qcam_init(struct parport *port) { - struct qcam_device *q; + struct qcam *qcam; + struct v4l2_device *v4l2_dev; - q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL); - if (q == NULL) + qcam = kzalloc(sizeof(*qcam), GFP_KERNEL); + if (qcam == NULL) return NULL; - q->pport = port; - q->pdev = parport_register_device(port, "c-qcam", NULL, NULL, + v4l2_dev = &qcam->v4l2_dev; + strlcpy(v4l2_dev->name, "c-qcam", sizeof(v4l2_dev->name)); + + if (v4l2_device_register(NULL, v4l2_dev) < 0) { + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + return NULL; + } + + qcam->pport = port; + qcam->pdev = parport_register_device(port, "c-qcam", NULL, NULL, NULL, 0, NULL); - q->bidirectional = (q->pport->modes & PARPORT_MODE_TRISTATE) ? 1 : 0; + qcam->bidirectional = (qcam->pport->modes & PARPORT_MODE_TRISTATE) ? 1 : 0; - if (q->pdev == NULL) { - printk(KERN_ERR "c-qcam: couldn't register for %s.\n", - port->name); - kfree(q); + if (qcam->pdev == NULL) { + v4l2_err(v4l2_dev, "couldn't register for %s.\n", port->name); + kfree(qcam); return NULL; } - memcpy(&q->vdev, &qcam_template, sizeof(qcam_template)); - - mutex_init(&q->lock); - q->width = q->ccd_width = 320; - q->height = q->ccd_height = 240; - q->mode = QC_MILLIONS | QC_DECIMATION_1; - q->contrast = 192; - q->brightness = 240; - q->whitebal = 128; - q->top = 1; - q->left = 14; - return q; + strlcpy(qcam->vdev.name, "Colour QuickCam", sizeof(qcam->vdev.name)); + qcam->vdev.v4l2_dev = v4l2_dev; + qcam->vdev.fops = &qcam_fops; + qcam->vdev.ioctl_ops = &qcam_ioctl_ops; + qcam->vdev.release = video_device_release_empty; + video_set_drvdata(&qcam->vdev, qcam); + + mutex_init(&qcam->lock); + qcam->width = qcam->ccd_width = 320; + qcam->height = qcam->ccd_height = 240; + qcam->mode = QC_MILLIONS | QC_DECIMATION_1; + qcam->contrast = 192; + qcam->brightness = 240; + qcam->whitebal = 128; + qcam->top = 1; + qcam->left = 14; + return qcam; } -static struct qcam_device *qcams[MAX_CAMS]; -static unsigned int num_cams; - static int init_cqcam(struct parport *port) { - struct qcam_device *qcam; + struct qcam *qcam; + struct v4l2_device *v4l2_dev; if (parport[0] != -1) { /* The user gave specific instructions */ @@ -777,6 +810,8 @@ static int init_cqcam(struct parport *port) if (qcam == NULL) return -ENODEV; + v4l2_dev = &qcam->v4l2_dev; + parport_claim_or_block(qcam->pdev); qc_reset(qcam); @@ -793,14 +828,14 @@ static int init_cqcam(struct parport *port) parport_release(qcam->pdev); if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { - printk(KERN_ERR "Unable to register Colour QuickCam on %s\n", + v4l2_err(v4l2_dev, "Unable to register Colour QuickCam on %s\n", qcam->pport->name); parport_unregister_device(qcam->pdev); kfree(qcam); return -ENODEV; } - printk(KERN_INFO "%s: Colour QuickCam found on %s\n", + v4l2_info(v4l2_dev, "%s: Colour QuickCam found on %s\n", video_device_node_name(&qcam->vdev), qcam->pport->name); qcams[num_cams++] = qcam; @@ -808,7 +843,7 @@ static int init_cqcam(struct parport *port) return 0; } -static void close_cqcam(struct qcam_device *qcam) +static void close_cqcam(struct qcam *qcam) { video_unregister_device(&qcam->vdev); parport_unregister_device(qcam->pdev); @@ -833,7 +868,7 @@ static struct parport_driver cqcam_driver = { static int __init cqcam_init(void) { - printk(BANNER "\n"); + printk(KERN_INFO BANNER "\n"); return parport_register_driver(&cqcam_driver); } @@ -852,14 +887,5 @@ MODULE_AUTHOR("Philip Blundell <philb@gnu.org>"); MODULE_DESCRIPTION(BANNER); MODULE_LICENSE("GPL"); -/* FIXME: parport=auto would never have worked, surely? --RR */ -MODULE_PARM_DESC(parport, "parport=<auto|n[,n]...> for port detection method\n" - "probe=<0|1|2> for camera detection method\n" - "force_rgb=<0|1> for RGB data format (default BGR)"); -module_param_array(parport, int, NULL, 0); -module_param(probe, int, 0); -module_param(force_rgb, bool, 0); -module_param(video_nr, int, 0); - module_init(cqcam_init); module_exit(cqcam_cleanup); diff --git a/drivers/media/video/cx18/cx18-alsa-main.c b/drivers/media/video/cx18/cx18-alsa-main.c index b5d7cbf..d50d69d 100644 --- a/drivers/media/video/cx18/cx18-alsa-main.c +++ b/drivers/media/video/cx18/cx18-alsa-main.c @@ -1,7 +1,7 @@ /* * ALSA interface to cx18 PCM capture streams * - * Copyright (C) 2009 Andy Walls <awalls@radix.net> + * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net> * Copyright (C) 2009 Devin Heitmueller <dheitmueller@kernellabs.com> * * Portions of this work were sponsored by ONELAN Limited. diff --git a/drivers/media/video/cx18/cx18-alsa-mixer.c b/drivers/media/video/cx18/cx18-alsa-mixer.c index ef21114..341bddc 100644 --- a/drivers/media/video/cx18/cx18-alsa-mixer.c +++ b/drivers/media/video/cx18/cx18-alsa-mixer.c @@ -2,7 +2,7 @@ * ALSA mixer controls for the * ALSA interface to cx18 PCM capture streams * - * Copyright (C) 2009 Andy Walls <awalls@radix.net> + * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/cx18/cx18-alsa-mixer.h b/drivers/media/video/cx18/cx18-alsa-mixer.h index 2d418db..ec92387 100644 --- a/drivers/media/video/cx18/cx18-alsa-mixer.h +++ b/drivers/media/video/cx18/cx18-alsa-mixer.h @@ -2,7 +2,7 @@ * ALSA mixer controls for the * ALSA interface to cx18 PCM capture streams * - * Copyright (C) 2009 Andy Walls <awalls@radix.net> + * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/cx18/cx18-alsa-pcm.c b/drivers/media/video/cx18/cx18-alsa-pcm.c index 2bd312d..8f55692 100644 --- a/drivers/media/video/cx18/cx18-alsa-pcm.c +++ b/drivers/media/video/cx18/cx18-alsa-pcm.c @@ -2,7 +2,7 @@ * ALSA PCM device for the * ALSA interface to cx18 PCM capture streams * - * Copyright (C) 2009 Andy Walls <awalls@radix.net> + * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net> * Copyright (C) 2009 Devin Heitmueller <dheitmueller@kernellabs.com> * * Portions of this work were sponsored by ONELAN Limited. diff --git a/drivers/media/video/cx18/cx18-alsa-pcm.h b/drivers/media/video/cx18/cx18-alsa-pcm.h index 325662c..d26e51f 100644 --- a/drivers/media/video/cx18/cx18-alsa-pcm.h +++ b/drivers/media/video/cx18/cx18-alsa-pcm.h @@ -2,7 +2,7 @@ * ALSA PCM device for the * ALSA interface to cx18 PCM capture streams * - * Copyright (C) 2009 Andy Walls <awalls@radix.net> + * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/cx18/cx18-alsa.h b/drivers/media/video/cx18/cx18-alsa.h index 88a1cde..447da37 100644 --- a/drivers/media/video/cx18/cx18-alsa.h +++ b/drivers/media/video/cx18/cx18-alsa.h @@ -1,7 +1,7 @@ /* * ALSA interface to cx18 PCM capture streams * - * Copyright (C) 2009 Andy Walls <awalls@radix.net> + * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/cx18/cx18-av-audio.c b/drivers/media/video/cx18/cx18-av-audio.c index 9e30983..43d09a2 100644 --- a/drivers/media/video/cx18/cx18-av-audio.c +++ b/drivers/media/video/cx18/cx18-av-audio.c @@ -4,7 +4,7 @@ * Derived from cx25840-audio.c * * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> - * Copyright (C) 2008 Andy Walls <awalls@radix.net> + * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index 0e5006b..a41951c 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c @@ -4,7 +4,7 @@ * Derived from cx25840-core.c * * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> - * Copyright (C) 2008 Andy Walls <awalls@radix.net> + * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -1021,86 +1021,74 @@ static int cx18_av_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) return -EINVAL; } -static int cx18_av_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) -{ - if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) - return -EINVAL; - return cx18_av_g_sliced_fmt(sd, &fmt->fmt.sliced); -} - -static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +static int cx18_av_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt) { struct cx18_av_state *state = to_cx18_av_state(sd); struct cx18 *cx = v4l2_get_subdevdata(sd); - - struct v4l2_pix_format *pix; int HSC, VSC, Vsrc, Hsrc, filter, Vlines; int is_50Hz = !(state->std & V4L2_STD_525_60); - switch (fmt->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - pix = &(fmt->fmt.pix); + if (fmt->code != V4L2_MBUS_FMT_FIXED) + return -EINVAL; - Vsrc = (cx18_av_read(cx, 0x476) & 0x3f) << 4; - Vsrc |= (cx18_av_read(cx, 0x475) & 0xf0) >> 4; + fmt->field = V4L2_FIELD_INTERLACED; + fmt->colorspace = V4L2_COLORSPACE_SMPTE170M; - Hsrc = (cx18_av_read(cx, 0x472) & 0x3f) << 4; - Hsrc |= (cx18_av_read(cx, 0x471) & 0xf0) >> 4; + Vsrc = (cx18_av_read(cx, 0x476) & 0x3f) << 4; + Vsrc |= (cx18_av_read(cx, 0x475) & 0xf0) >> 4; - /* - * This adjustment reflects the excess of vactive, set in - * cx18_av_std_setup(), above standard values: - * - * 480 + 1 for 60 Hz systems - * 576 + 3 for 50 Hz systems - */ - Vlines = pix->height + (is_50Hz ? 3 : 1); - - /* - * Invalid height and width scaling requests are: - * 1. width less than 1/16 of the source width - * 2. width greater than the source width - * 3. height less than 1/8 of the source height - * 4. height greater than the source height - */ - if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) || - (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) { - CX18_ERR_DEV(sd, "%dx%d is not a valid size!\n", - pix->width, pix->height); - return -ERANGE; - } + Hsrc = (cx18_av_read(cx, 0x472) & 0x3f) << 4; + Hsrc |= (cx18_av_read(cx, 0x471) & 0xf0) >> 4; - HSC = (Hsrc * (1 << 20)) / pix->width - (1 << 20); - VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9)); - VSC &= 0x1fff; + /* + * This adjustment reflects the excess of vactive, set in + * cx18_av_std_setup(), above standard values: + * + * 480 + 1 for 60 Hz systems + * 576 + 3 for 50 Hz systems + */ + Vlines = fmt->height + (is_50Hz ? 3 : 1); - if (pix->width >= 385) - filter = 0; - else if (pix->width > 192) - filter = 1; - else if (pix->width > 96) - filter = 2; - else - filter = 3; + /* + * Invalid height and width scaling requests are: + * 1. width less than 1/16 of the source width + * 2. width greater than the source width + * 3. height less than 1/8 of the source height + * 4. height greater than the source height + */ + if ((fmt->width * 16 < Hsrc) || (Hsrc < fmt->width) || + (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) { + CX18_ERR_DEV(sd, "%dx%d is not a valid size!\n", + fmt->width, fmt->height); + return -ERANGE; + } - CX18_DEBUG_INFO_DEV(sd, - "decoder set size %dx%d -> scale %ux%u\n", - pix->width, pix->height, HSC, VSC); - - /* HSCALE=HSC */ - cx18_av_write(cx, 0x418, HSC & 0xff); - cx18_av_write(cx, 0x419, (HSC >> 8) & 0xff); - cx18_av_write(cx, 0x41a, HSC >> 16); - /* VSCALE=VSC */ - cx18_av_write(cx, 0x41c, VSC & 0xff); - cx18_av_write(cx, 0x41d, VSC >> 8); - /* VS_INTRLACE=1 VFILT=filter */ - cx18_av_write(cx, 0x41e, 0x8 | filter); - break; + HSC = (Hsrc * (1 << 20)) / fmt->width - (1 << 20); + VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9)); + VSC &= 0x1fff; - default: - return -EINVAL; - } + if (fmt->width >= 385) + filter = 0; + else if (fmt->width > 192) + filter = 1; + else if (fmt->width > 96) + filter = 2; + else + filter = 3; + + CX18_DEBUG_INFO_DEV(sd, + "decoder set size %dx%d -> scale %ux%u\n", + fmt->width, fmt->height, HSC, VSC); + + /* HSCALE=HSC */ + cx18_av_write(cx, 0x418, HSC & 0xff); + cx18_av_write(cx, 0x419, (HSC >> 8) & 0xff); + cx18_av_write(cx, 0x41a, HSC >> 16); + /* VSCALE=VSC */ + cx18_av_write(cx, 0x41c, VSC & 0xff); + cx18_av_write(cx, 0x41d, VSC >> 8); + /* VS_INTRLACE=1 VFILT=filter */ + cx18_av_write(cx, 0x41e, 0x8 | filter); return 0; } @@ -1398,8 +1386,7 @@ static const struct v4l2_subdev_audio_ops cx18_av_audio_ops = { static const struct v4l2_subdev_video_ops cx18_av_video_ops = { .s_routing = cx18_av_s_video_routing, .s_stream = cx18_av_s_stream, - .g_fmt = cx18_av_g_fmt, - .s_fmt = cx18_av_s_fmt, + .s_mbus_fmt = cx18_av_s_mbus_fmt, }; static const struct v4l2_subdev_vbi_ops cx18_av_vbi_ops = { diff --git a/drivers/media/video/cx18/cx18-av-core.h b/drivers/media/video/cx18/cx18-av-core.h index c106967..1956991 100644 --- a/drivers/media/video/cx18/cx18-av-core.h +++ b/drivers/media/video/cx18/cx18-av-core.h @@ -4,7 +4,7 @@ * Derived from cx25840-core.h * * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> - * Copyright (C) 2008 Andy Walls <awalls@radix.net> + * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/drivers/media/video/cx18/cx18-av-firmware.c b/drivers/media/video/cx18/cx18-av-firmware.c index b9e8cc5..280aa4d 100644 --- a/drivers/media/video/cx18/cx18-av-firmware.c +++ b/drivers/media/video/cx18/cx18-av-firmware.c @@ -2,7 +2,7 @@ * cx18 ADEC firmware functions * * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> - * Copyright (C) 2008 Andy Walls <awalls@radix.net> + * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index 74e122b..6b805af 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c @@ -4,7 +4,7 @@ * Derived from ivtv-cards.c * * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> - * Copyright (C) 2008 Andy Walls <awalls@radix.net> + * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/cx18/cx18-cards.h b/drivers/media/video/cx18/cx18-cards.h index 796e517..3e75006 100644 --- a/drivers/media/video/cx18/cx18-cards.h +++ b/drivers/media/video/cx18/cx18-cards.h @@ -4,7 +4,7 @@ * Derived from ivtv-cards.c * * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> - * Copyright (C) 2008 Andy Walls <awalls@radix.net> + * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/cx18/cx18-controls.c b/drivers/media/video/cx18/cx18-controls.c index 4b4b465..67043c7 100644 --- a/drivers/media/video/cx18/cx18-controls.c +++ b/drivers/media/video/cx18/cx18-controls.c @@ -297,14 +297,13 @@ int cx18_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c) if (p.video_encoding != cx->params.video_encoding) { int is_mpeg1 = p.video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1; - struct v4l2_format fmt; + struct v4l2_mbus_framefmt fmt; /* fix videodecoder resolution */ - fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - fmt.fmt.pix.width = cx->params.width - / (is_mpeg1 ? 2 : 1); - fmt.fmt.pix.height = cx->params.height; - v4l2_subdev_call(cx->sd_av, video, s_fmt, &fmt); + fmt.width = cx->params.width / (is_mpeg1 ? 2 : 1); + fmt.height = cx->params.height; + fmt.code = V4L2_MBUS_FMT_FIXED; + v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &fmt); } priv.cx = cx; priv.s = &cx->streams[id->type]; diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index c95a86b..df60f27 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -4,7 +4,7 @@ * Derived from ivtv-driver.c * * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> - * Copyright (C) 2008 Andy Walls <awalls@radix.net> + * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index b9728e8..9bc51a9 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -4,7 +4,7 @@ * Derived from ivtv-driver.h * * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> - * Copyright (C) 2008 Andy Walls <awalls@radix.net> + * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c index 0ae2c2e..6d19f04 100644 --- a/drivers/media/video/cx18/cx18-dvb.c +++ b/drivers/media/video/cx18/cx18-dvb.c @@ -2,7 +2,7 @@ * cx18 functions for DVB support * * Copyright (c) 2008 Steven Toth <stoth@linuxtv.org> - * Copyright (C) 2008 Andy Walls <awalls@radix.net> + * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c index e12a150..9f23b90 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/video/cx18/cx18-fileops.c @@ -4,7 +4,7 @@ * Derived from ivtv-fileops.c * * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> - * Copyright (C) 2008 Andy Walls <awalls@radix.net> + * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/cx18/cx18-firmware.c b/drivers/media/video/cx18/cx18-firmware.c index 83cd559..1b3fb50 100644 --- a/drivers/media/video/cx18/cx18-firmware.c +++ b/drivers/media/video/cx18/cx18-firmware.c @@ -2,7 +2,7 @@ * cx18 firmware functions * * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> - * Copyright (C) 2008 Andy Walls <awalls@radix.net> + * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/cx18/cx18-gpio.c b/drivers/media/video/cx18/cx18-gpio.c index 86a204b..5374aeb 100644 --- a/drivers/media/video/cx18/cx18-gpio.c +++ b/drivers/media/video/cx18/cx18-gpio.c @@ -4,7 +4,7 @@ * Derived from ivtv-gpio.c * * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> - * Copyright (C) 2008 Andy Walls <awalls@radix.net> + * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/cx18/cx18-gpio.h b/drivers/media/video/cx18/cx18-gpio.h index f9a5ca3..4aea2ef 100644 --- a/drivers/media/video/cx18/cx18-gpio.h +++ b/drivers/media/video/cx18/cx18-gpio.h @@ -4,7 +4,7 @@ * Derived from ivtv-gpio.h * * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> - * Copyright (C) 2008 Andy Walls <awalls@radix.net> + * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c index cfa1f28..809f7d3 100644 --- a/drivers/media/video/cx18/cx18-i2c.c +++ b/drivers/media/video/cx18/cx18-i2c.c @@ -4,7 +4,7 @@ * Derived from ivtv-i2c.c * * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> - * Copyright (C) 2008 Andy Walls <awalls@radix.net> + * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/cx18/cx18-io.c b/drivers/media/video/cx18/cx18-io.c index ec5b3d7..49b9dbd 100644 --- a/drivers/media/video/cx18/cx18-io.c +++ b/drivers/media/video/cx18/cx18-io.c @@ -2,7 +2,7 @@ * cx18 driver PCI memory mapped IO access routines * * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> - * Copyright (C) 2008 Andy Walls <awalls@radix.net> + * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/cx18/cx18-io.h b/drivers/media/video/cx18/cx18-io.h index 2635b3a..18974d8 100644 --- a/drivers/media/video/cx18/cx18-io.h +++ b/drivers/media/video/cx18/cx18-io.h @@ -2,7 +2,7 @@ * cx18 driver PCI memory mapped IO access routines * * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> - * Copyright (C) 2008 Andy Walls <awalls@radix.net> + * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,7 +28,7 @@ /* * Readback and retry of MMIO access for reliability: * The concept was suggested by Steve Toth <stoth@linuxtv.org>. - * The implmentation is the fault of Andy Walls <awalls@radix.net>. + * The implmentation is the fault of Andy Walls <awalls@md.metrocast.net>. * * *write* functions are implied to retry the mmio unless suffixed with _noretry * *read* functions never retry the mmio (it never helps to do so) diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index 2530fc5..20eaf38 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c @@ -4,7 +4,7 @@ * Derived from ivtv-ioctl.c * * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> - * Copyright (C) 2008 Andy Walls <awalls@radix.net> + * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -274,6 +274,7 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh, { struct cx18_open_id *id = fh; struct cx18 *cx = id->cx; + struct v4l2_mbus_framefmt mbus_fmt; int ret; int w, h; @@ -293,9 +294,10 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh, if (atomic_read(&cx->ana_capturing) > 0) return -EBUSY; - cx->params.width = w; - cx->params.height = h; - v4l2_subdev_call(cx->sd_av, video, s_fmt, fmt); + mbus_fmt.width = cx->params.width = w; + mbus_fmt.height = cx->params.height = h; + mbus_fmt.code = V4L2_MBUS_FMT_FIXED; + v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &mbus_fmt); return cx18_g_fmt_vid_cap(file, fh, fmt); } diff --git a/drivers/media/video/cx18/cx18-ioctl.h b/drivers/media/video/cx18/cx18-ioctl.h index e2ca0d1..dcb2559 100644 --- a/drivers/media/video/cx18/cx18-ioctl.h +++ b/drivers/media/video/cx18/cx18-ioctl.h @@ -4,7 +4,7 @@ * Derived from ivtv-ioctl.h * * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> - * Copyright (C) 2008 Andy Walls <awalls@radix.net> + * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/cx18/cx18-irq.c b/drivers/media/video/cx18/cx18-irq.c index af2f504..80edfe9 100644 --- a/drivers/media/video/cx18/cx18-irq.c +++ b/drivers/media/video/cx18/cx18-irq.c @@ -2,7 +2,7 @@ * cx18 interrupt handling * * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> - * Copyright (C) 2008 Andy Walls <awalls@radix.net> + * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/cx18/cx18-irq.h b/drivers/media/video/cx18/cx18-irq.h index 91f0b52..30e7eaf 100644 --- a/drivers/media/video/cx18/cx18-irq.h +++ b/drivers/media/video/cx18/cx18-irq.h @@ -2,7 +2,7 @@ * cx18 interrupt handling * * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> - * Copyright (C) 2008 Andy Walls <awalls@radix.net> + * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c index 6dcce29..956aa19 100644 --- a/drivers/media/video/cx18/cx18-mailbox.c +++ b/drivers/media/video/cx18/cx18-mailbox.c @@ -2,7 +2,7 @@ * cx18 mailbox functions * * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> - * Copyright (C) 2008 Andy Walls <awalls@radix.net> + * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/cx18/cx18-mailbox.h b/drivers/media/video/cx18/cx18-mailbox.h index 33a3491..077952f 100644 --- a/drivers/media/video/cx18/cx18-mailbox.h +++ b/drivers/media/video/cx18/cx18-mailbox.h @@ -2,7 +2,7 @@ * cx18 mailbox functions * * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> - * Copyright (C) 2008 Andy Walls <awalls@radix.net> + * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c index aefc8c8..8884537 100644 --- a/drivers/media/video/cx18/cx18-queue.c +++ b/drivers/media/video/cx18/cx18-queue.c @@ -4,7 +4,7 @@ * Derived from ivtv-queue.c * * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> - * Copyright (C) 2008 Andy Walls <awalls@radix.net> + * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/cx18/cx18-queue.h b/drivers/media/video/cx18/cx18-queue.h index 88a6d34..4201ddc 100644 --- a/drivers/media/video/cx18/cx18-queue.h +++ b/drivers/media/video/cx18/cx18-queue.h @@ -4,7 +4,7 @@ * Derived from ivtv-queue.h * * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> - * Copyright (C) 2008 Andy Walls <awalls@radix.net> + * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/cx18/cx18-scb.c b/drivers/media/video/cx18/cx18-scb.c index 34b4d03..85cc596 100644 --- a/drivers/media/video/cx18/cx18-scb.c +++ b/drivers/media/video/cx18/cx18-scb.c @@ -2,7 +2,7 @@ * cx18 System Control Block initialization * * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> - * Copyright (C) 2008 Andy Walls <awalls@radix.net> + * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/cx18/cx18-scb.h b/drivers/media/video/cx18/cx18-scb.h index 368f23d..0887765 100644 --- a/drivers/media/video/cx18/cx18-scb.h +++ b/drivers/media/video/cx18/cx18-scb.h @@ -2,7 +2,7 @@ * cx18 System Control Block initialization * * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> - * Copyright (C) 2008 Andy Walls <awalls@radix.net> + * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index f5c9126..9045f1e 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c @@ -4,7 +4,7 @@ * Derived from ivtv-streams.c * * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> - * Copyright (C) 2008 Andy Walls <awalls@radix.net> + * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/cx18/cx18-streams.h b/drivers/media/video/cx18/cx18-streams.h index 0bff0fa..77412be 100644 --- a/drivers/media/video/cx18/cx18-streams.h +++ b/drivers/media/video/cx18/cx18-streams.h @@ -4,7 +4,7 @@ * Derived from ivtv-streams.h * * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> - * Copyright (C) 2008 Andy Walls <awalls@radix.net> + * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c index 2782709..e760145 100644 --- a/drivers/media/video/cx231xx/cx231xx-video.c +++ b/drivers/media/video/cx231xx/cx231xx-video.c @@ -993,6 +993,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct cx231xx *dev = fh->dev; int rc; struct cx231xx_fmt *fmt; + struct v4l2_mbus_framefmt mbus_fmt; rc = check_dev(dev); if (rc < 0) @@ -1026,7 +1027,9 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, dev->format = fmt; get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); - call_all(dev, video, s_fmt, f); + v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED); + call_all(dev, video, s_mbus_fmt, &mbus_fmt); + v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt); /* Set the correct alternate setting for this resolution */ cx231xx_resolution_set(dev); diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c index 022b480..2bf44ef 100644 --- a/drivers/media/video/cx2341x.c +++ b/drivers/media/video/cx2341x.c @@ -1113,7 +1113,6 @@ invalid: void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix) { int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1; - int temporal = p->video_temporal_filter; /* Stream */ printk(KERN_INFO "%s: Stream: %s", @@ -1179,14 +1178,11 @@ void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix) V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE), p->video_spatial_filter); - if (p->width != 720 || p->height != (p->is_50hz ? 576 : 480)) - temporal = 0; - printk(KERN_INFO "%s: Temporal Filter: %s, %d\n", prefix, cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE), - temporal); + p->video_temporal_filter); printk(KERN_INFO "%s: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n", prefix, diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 9e14608..0a199d7 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -991,6 +991,8 @@ static int dvb_register(struct cx23885_tsport *port) ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port, &dev->pci->dev, adapter_nr, 0, cx23885_dvb_fe_ioctl_override); + if (!ret) + return ret; /* init CI & MAC */ switch (dev->board) { diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c index 4172cb3..d4746e0 100644 --- a/drivers/media/video/cx23885/cx23885-i2c.c +++ b/drivers/media/video/cx23885/cx23885-i2c.c @@ -365,7 +365,17 @@ int cx23885_i2c_register(struct cx23885_i2c *bus) memset(&info, 0, sizeof(struct i2c_board_info)); strlcpy(info.type, "ir_video", I2C_NAME_SIZE); - i2c_new_probed_device(&bus->i2c_adap, &info, addr_list); + /* + * We can't call i2c_new_probed_device() because it uses + * quick writes for probing and the IR receiver device only + * replies to reads. + */ + if (i2c_smbus_xfer(&bus->i2c_adap, addr_list[0], 0, + I2C_SMBUS_READ, 0, I2C_SMBUS_QUICK, + NULL) >= 0) { + info.addr = addr_list[0]; + i2c_new_device(&bus->i2c_adap, &info); + } } return bus->i2c_rc; diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c index 8d306d8..5de6ba9 100644 --- a/drivers/media/video/cx23885/cx23885-input.c +++ b/drivers/media/video/cx23885/cx23885-input.c @@ -5,7 +5,7 @@ * * Most of this file is * - * Copyright (C) 2009 Andy Walls <awalls@radix.net> + * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net> * * However, the cx23885_input_{init,fini} functions contained herein are * derived from Linux kernel files linux/media/video/.../...-input.c marked as: diff --git a/drivers/media/video/cx23885/cx23885-input.h b/drivers/media/video/cx23885/cx23885-input.h index 3572cb1..75ef15d 100644 --- a/drivers/media/video/cx23885/cx23885-input.h +++ b/drivers/media/video/cx23885/cx23885-input.h @@ -3,7 +3,7 @@ * * Infrared remote control input device * - * Copyright (C) 2009 Andy Walls <awalls@radix.net> + * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/drivers/media/video/cx23885/cx23885-ioctl.c b/drivers/media/video/cx23885/cx23885-ioctl.c index dfb4627..44812ca 100644 --- a/drivers/media/video/cx23885/cx23885-ioctl.c +++ b/drivers/media/video/cx23885/cx23885-ioctl.c @@ -3,7 +3,7 @@ * * Various common ioctl() support functions * - * Copyright (c) 2009 Andy Walls <awalls@radix.net> + * Copyright (c) 2009 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/cx23885/cx23885-ioctl.h b/drivers/media/video/cx23885/cx23885-ioctl.h index 80b0f49..315be0c 100644 --- a/drivers/media/video/cx23885/cx23885-ioctl.h +++ b/drivers/media/video/cx23885/cx23885-ioctl.h @@ -3,7 +3,7 @@ * * Various common ioctl() support functions * - * Copyright (c) 2009 Andy Walls <awalls@radix.net> + * Copyright (c) 2009 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/video/cx23885/cx23885-ir.c b/drivers/media/video/cx23885/cx23885-ir.c index 6ae982c..9a677eb 100644 --- a/drivers/media/video/cx23885/cx23885-ir.c +++ b/drivers/media/video/cx23885/cx23885-ir.c @@ -3,7 +3,7 @@ * * Infrared device support routines - non-input, non-vl42_subdev routines * - * Copyright (C) 2009 Andy Walls <awalls@radix.net> + * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/drivers/media/video/cx23885/cx23885-ir.h b/drivers/media/video/cx23885/cx23885-ir.h index 9b8a6d5..0c9d8bd 100644 --- a/drivers/media/video/cx23885/cx23885-ir.h +++ b/drivers/media/video/cx23885/cx23885-ir.h @@ -3,7 +3,7 @@ * * Infrared device support routines - non-input, non-vl42_subdev routines * - * Copyright (C) 2009 Andy Walls <awalls@radix.net> + * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index 543b854..4e44dcd 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c @@ -976,6 +976,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, { struct cx23885_fh *fh = priv; struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; + struct v4l2_mbus_framefmt mbus_fmt; int err; dprintk(2, "%s()\n", __func__); @@ -989,7 +990,9 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, fh->vidq.field = f->fmt.pix.field; dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); - call_all(dev, video, s_fmt, f); + v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED); + call_all(dev, video, s_mbus_fmt, &mbus_fmt); + v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt); return 0; } diff --git a/drivers/media/video/cx23885/cx23888-ir.c b/drivers/media/video/cx23885/cx23888-ir.c index ad728d7..f63d378 100644 --- a/drivers/media/video/cx23885/cx23888-ir.c +++ b/drivers/media/video/cx23885/cx23888-ir.c @@ -3,7 +3,7 @@ * * CX23888 Integrated Consumer Infrared Controller * - * Copyright (C) 2009 Andy Walls <awalls@radix.net> + * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/drivers/media/video/cx23885/cx23888-ir.h b/drivers/media/video/cx23885/cx23888-ir.h index 3d446f9..d2de41c 100644 --- a/drivers/media/video/cx23885/cx23888-ir.h +++ b/drivers/media/video/cx23885/cx23888-ir.h @@ -3,7 +3,7 @@ * * CX23888 Integrated Consumer Infrared Controller * - * Copyright (C) 2009 Andy Walls <awalls@radix.net> + * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 8b6fb35..bb4872b 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -1014,75 +1014,59 @@ static int cx25840_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) /* ----------------------------------------------------------------------- */ -static int cx25840_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) -{ - switch (fmt->type) { - case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: - return cx25840_g_sliced_fmt(sd, &fmt->fmt.sliced); - default: - return -EINVAL; - } - return 0; -} - -static int cx25840_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +static int cx25840_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt) { struct cx25840_state *state = to_state(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); - struct v4l2_pix_format *pix; int HSC, VSC, Vsrc, Hsrc, filter, Vlines; int is_50Hz = !(state->std & V4L2_STD_525_60); - switch (fmt->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - pix = &(fmt->fmt.pix); - - Vsrc = (cx25840_read(client, 0x476) & 0x3f) << 4; - Vsrc |= (cx25840_read(client, 0x475) & 0xf0) >> 4; - - Hsrc = (cx25840_read(client, 0x472) & 0x3f) << 4; - Hsrc |= (cx25840_read(client, 0x471) & 0xf0) >> 4; + if (fmt->code != V4L2_MBUS_FMT_FIXED) + return -EINVAL; - Vlines = pix->height + (is_50Hz ? 4 : 7); + fmt->field = V4L2_FIELD_INTERLACED; + fmt->colorspace = V4L2_COLORSPACE_SMPTE170M; - if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) || - (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) { - v4l_err(client, "%dx%d is not a valid size!\n", - pix->width, pix->height); - return -ERANGE; - } + Vsrc = (cx25840_read(client, 0x476) & 0x3f) << 4; + Vsrc |= (cx25840_read(client, 0x475) & 0xf0) >> 4; - HSC = (Hsrc * (1 << 20)) / pix->width - (1 << 20); - VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9)); - VSC &= 0x1fff; + Hsrc = (cx25840_read(client, 0x472) & 0x3f) << 4; + Hsrc |= (cx25840_read(client, 0x471) & 0xf0) >> 4; - if (pix->width >= 385) - filter = 0; - else if (pix->width > 192) - filter = 1; - else if (pix->width > 96) - filter = 2; - else - filter = 3; - - v4l_dbg(1, cx25840_debug, client, "decoder set size %dx%d -> scale %ux%u\n", - pix->width, pix->height, HSC, VSC); - - /* HSCALE=HSC */ - cx25840_write(client, 0x418, HSC & 0xff); - cx25840_write(client, 0x419, (HSC >> 8) & 0xff); - cx25840_write(client, 0x41a, HSC >> 16); - /* VSCALE=VSC */ - cx25840_write(client, 0x41c, VSC & 0xff); - cx25840_write(client, 0x41d, VSC >> 8); - /* VS_INTRLACE=1 VFILT=filter */ - cx25840_write(client, 0x41e, 0x8 | filter); - break; + Vlines = fmt->height + (is_50Hz ? 4 : 7); - default: - return -EINVAL; + if ((fmt->width * 16 < Hsrc) || (Hsrc < fmt->width) || + (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) { + v4l_err(client, "%dx%d is not a valid size!\n", + fmt->width, fmt->height); + return -ERANGE; } + HSC = (Hsrc * (1 << 20)) / fmt->width - (1 << 20); + VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9)); + VSC &= 0x1fff; + + if (fmt->width >= 385) + filter = 0; + else if (fmt->width > 192) + filter = 1; + else if (fmt->width > 96) + filter = 2; + else + filter = 3; + + v4l_dbg(1, cx25840_debug, client, "decoder set size %dx%d -> scale %ux%u\n", + fmt->width, fmt->height, HSC, VSC); + + /* HSCALE=HSC */ + cx25840_write(client, 0x418, HSC & 0xff); + cx25840_write(client, 0x419, (HSC >> 8) & 0xff); + cx25840_write(client, 0x41a, HSC >> 16); + /* VSCALE=VSC */ + cx25840_write(client, 0x41c, VSC & 0xff); + cx25840_write(client, 0x41d, VSC >> 8); + /* VS_INTRLACE=1 VFILT=filter */ + cx25840_write(client, 0x41e, 0x8 | filter); return 0; } @@ -1627,8 +1611,7 @@ static const struct v4l2_subdev_audio_ops cx25840_audio_ops = { static const struct v4l2_subdev_video_ops cx25840_video_ops = { .s_routing = cx25840_s_video_routing, - .g_fmt = cx25840_g_fmt, - .s_fmt = cx25840_s_fmt, + .s_mbus_fmt = cx25840_s_mbus_fmt, .s_stream = cx25840_s_stream, }; diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index ee1ca39..fb39f11 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c @@ -188,10 +188,24 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) 0x18, 0x6b, 0x71, I2C_CLIENT_END }; + const unsigned short *addrp; memset(&info, 0, sizeof(struct i2c_board_info)); strlcpy(info.type, "ir_video", I2C_NAME_SIZE); - i2c_new_probed_device(&core->i2c_adap, &info, addr_list); + /* + * We can't call i2c_new_probed_device() because it uses + * quick writes for probing and at least some R receiver + * devices only reply to reads. + */ + for (addrp = addr_list; *addrp != I2C_CLIENT_END; addrp++) { + if (i2c_smbus_xfer(&core->i2c_adap, *addrp, 0, + I2C_SMBUS_READ, 0, + I2C_SMBUS_QUICK, NULL) >= 0) { + info.addr = *addrp; + i2c_new_device(&core->i2c_adap, &info); + break; + } + } } return core->i2c_rc; } diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 331e1ca..44c63cbd 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -1186,8 +1186,7 @@ int em28xx_register_extension(struct em28xx_ops *ops) mutex_lock(&em28xx_devlist_mutex); list_add_tail(&ops->next, &em28xx_extension_devlist); list_for_each_entry(dev, &em28xx_devlist, devlist) { - if (dev) - ops->init(dev); + ops->init(dev); } printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name); mutex_unlock(&em28xx_devlist_mutex); @@ -1201,10 +1200,8 @@ void em28xx_unregister_extension(struct em28xx_ops *ops) mutex_lock(&em28xx_devlist_mutex); list_for_each_entry(dev, &em28xx_devlist, devlist) { - if (dev) - ops->fini(dev); + ops->fini(dev); } - printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name); list_del(&ops->next); mutex_unlock(&em28xx_devlist_mutex); diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 785eeb4..95354a3 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -1453,9 +1453,7 @@ static const struct usb_device_id device_table[] __devinitconst = { {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)}, {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)}, {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)}, -#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)}, -#endif {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)}, #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)}, diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index bb923ef..176c5b3 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -3022,16 +3022,18 @@ static const __devinitdata struct usb_device_id device_table[] = { /* {USB_DEVICE(0x0c45, 0x60c2), BS(SN9C105, P1030xC)}, */ /* {USB_DEVICE(0x0c45, 0x60c8), BS(SN9C105, OM6802)}, */ /* {USB_DEVICE(0x0c45, 0x60cc), BS(SN9C105, HV7131GP)}, */ + {USB_DEVICE(0x0c45, 0x60ce), BS(SN9C105, SP80708)}, {USB_DEVICE(0x0c45, 0x60ec), BS(SN9C105, MO4000)}, /* {USB_DEVICE(0x0c45, 0x60ef), BS(SN9C105, ICM105C)}, */ /* {USB_DEVICE(0x0c45, 0x60fa), BS(SN9C105, OV7648)}, */ +/* {USB_DEVICE(0x0c45, 0x60f2), BS(SN9C105, OV7660)}, */ {USB_DEVICE(0x0c45, 0x60fb), BS(SN9C105, OV7660)}, #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0c45, 0x60fc), BS(SN9C105, HV7131R)}, {USB_DEVICE(0x0c45, 0x60fe), BS(SN9C105, OV7630)}, #endif {USB_DEVICE(0x0c45, 0x6100), BS(SN9C120, MI0360)}, /*sn9c128*/ -/* {USB_DEVICE(0x0c45, 0x6102), BS(SN9C120, P1030xC)}, */ +/* {USB_DEVICE(0x0c45, 0x6102), BS(SN9C120, PO2030N)}, * / GC0305*/ /* {USB_DEVICE(0x0c45, 0x6108), BS(SN9C120, OM6802)}, */ {USB_DEVICE(0x0c45, 0x610a), BS(SN9C120, OV7648)}, /*sn9c128*/ {USB_DEVICE(0x0c45, 0x610b), BS(SN9C120, OV7660)}, /*sn9c128*/ @@ -3058,6 +3060,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0c45, 0x613c), BS(SN9C120, HV7131R)}, {USB_DEVICE(0x0c45, 0x613e), BS(SN9C120, OV7630)}, {USB_DEVICE(0x0c45, 0x6142), BS(SN9C120, PO2030N)}, /*sn9c120b*/ + /* or GC0305 / GC0307 */ {USB_DEVICE(0x0c45, 0x6143), BS(SN9C120, SP80708)}, /*sn9c120b*/ {USB_DEVICE(0x0c45, 0x6148), BS(SN9C120, OM6802)}, /*sn9c120b*/ {USB_DEVICE(0x0c45, 0x614a), BS(SN9C120, ADCM1700)}, /*sn9c120b*/ diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c index 7cfccfd..c338f3f 100644 --- a/drivers/media/video/hdpvr/hdpvr-video.c +++ b/drivers/media/video/hdpvr/hdpvr-video.c @@ -366,7 +366,7 @@ static int hdpvr_open(struct file *file) dev = (struct hdpvr_device *)video_get_drvdata(video_devdata(file)); if (!dev) { - v4l2_err(&dev->v4l2_dev, "open failing with with ENODEV\n"); + pr_err("open failing with with ENODEV\n"); retval = -ENODEV; goto err; } diff --git a/drivers/media/video/ivtv/ivtv-controls.c b/drivers/media/video/ivtv/ivtv-controls.c index b59475bf..b588e30 100644 --- a/drivers/media/video/ivtv/ivtv-controls.c +++ b/drivers/media/video/ivtv/ivtv-controls.c @@ -267,13 +267,13 @@ int ivtv_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c) if (p.video_encoding != itv->params.video_encoding) { int is_mpeg1 = p.video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1; - struct v4l2_format fmt; + struct v4l2_mbus_framefmt fmt; /* fix videodecoder resolution */ - fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - fmt.fmt.pix.width = itv->params.width / (is_mpeg1 ? 2 : 1); - fmt.fmt.pix.height = itv->params.height; - v4l2_subdev_call(itv->sd_video, video, s_fmt, &fmt); + fmt.width = itv->params.width / (is_mpeg1 ? 2 : 1); + fmt.height = itv->params.height; + fmt.code = V4L2_MBUS_FMT_FIXED; + v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &fmt); } err = cx2341x_update(itv, ivtv_api_func, &itv->params, &p); if (!err && itv->params.stream_vbi_fmt != p.stream_vbi_fmt) diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index abf4109..3c2cc27 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c @@ -823,6 +823,12 @@ static void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts) IVTV_DEBUG_FILE("close() of %s\n", s->name); + if (id->type == IVTV_DEC_STREAM_TYPE_YUV && + test_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags)) { + /* Restore registers we've changed & clean up any mess */ + ivtv_yuv_close(itv); + } + /* Stop decoding */ if (test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { IVTV_DEBUG_INFO("close stopping decode\n"); @@ -832,10 +838,7 @@ static void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts) } clear_bit(IVTV_F_S_APPL_IO, &s->s_flags); clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags); - if (id->type == IVTV_DEC_STREAM_TYPE_YUV && test_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags)) { - /* Restore registers we've changed & clean up any mess we've made */ - ivtv_yuv_close(itv); - } + if (itv->output_mode == OUT_UDMA_YUV && id->yuv_frames) itv->output_mode = OUT_NONE; diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index fa9f0d9..11ac2fa 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c @@ -569,6 +569,7 @@ static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f struct ivtv_open_id *id = fh; struct ivtv *itv = id->itv; struct cx2341x_mpeg_params *p = &itv->params; + struct v4l2_mbus_framefmt mbus_fmt; int ret = ivtv_try_fmt_vid_cap(file, fh, fmt); int w = fmt->fmt.pix.width; int h = fmt->fmt.pix.height; @@ -586,7 +587,10 @@ static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f p->height = h; if (p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) fmt->fmt.pix.width /= 2; - v4l2_subdev_call(itv->sd_video, video, s_fmt, fmt); + mbus_fmt.width = fmt->fmt.pix.width; + mbus_fmt.height = h; + mbus_fmt.code = V4L2_MBUS_FMT_FIXED; + v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &mbus_fmt); return ivtv_g_fmt_vid_cap(file, fh, fmt); } diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index de4288c..9ecacab 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c @@ -618,12 +618,17 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s) struct ivtv *itv = s->itv; struct cx2341x_mpeg_params *p = &itv->params; int datatype; + u16 width; + u16 height; if (s->vdev == NULL) return -EINVAL; IVTV_DEBUG_INFO("Setting some initial decoder settings\n"); + width = p->width; + height = p->height; + /* set audio mode to left/stereo for dual/stereo mode. */ ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); @@ -646,7 +651,14 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s) 2 = yuv_from_host */ switch (s->type) { case IVTV_DEC_STREAM_TYPE_YUV: - datatype = itv->output_mode == OUT_PASSTHROUGH ? 1 : 2; + if (itv->output_mode == OUT_PASSTHROUGH) { + datatype = 1; + } else { + /* Fake size to avoid switching video standard */ + datatype = 2; + width = 720; + height = itv->is_out_50hz ? 576 : 480; + } IVTV_DEBUG_INFO("Setup DEC YUV Stream data[0] = %d\n", datatype); break; case IVTV_DEC_STREAM_TYPE_MPG: @@ -655,9 +667,13 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s) break; } if (ivtv_vapi(itv, CX2341X_DEC_SET_DECODER_SOURCE, 4, datatype, - p->width, p->height, p->audio_properties)) { + width, height, p->audio_properties)) { IVTV_DEBUG_WARN("Couldn't initialize decoder source\n"); } + + /* Decoder sometimes dies here, so wait a moment */ + ivtv_msleep_timeout(10, 0); + return 0; } @@ -697,6 +713,9 @@ int ivtv_start_v4l2_decode_stream(struct ivtv_stream *s, int gop_offset) /* start playback */ ivtv_vapi(itv, CX2341X_DEC_START_PLAYBACK, 2, gop_offset, 0); + /* Let things settle before we actually start */ + ivtv_msleep_timeout(10, 0); + /* Clear the following Interrupt mask bits for decoding */ ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_DECODE); IVTV_DEBUG_IRQ("IRQ Mask is now: 0x%08x\n", itv->irqmask); diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c index 49e1a28..9ff3425 100644 --- a/drivers/media/video/ivtv/ivtvfb.c +++ b/drivers/media/video/ivtv/ivtvfb.c @@ -1066,7 +1066,11 @@ static int ivtvfb_init_io(struct ivtv *itv) } mutex_unlock(&itv->serialize_lock); - ivtvfb_get_framebuffer(itv, &oi->video_rbase, &oi->video_buffer_size); + if (ivtvfb_get_framebuffer(itv, &oi->video_rbase, + &oi->video_buffer_size) < 0) { + IVTVFB_ERR("Firmware failed to respond\n"); + return -EIO; + } /* The osd buffer size depends on the number of video buffers allocated on the PVR350 itself. For now we'll hardcode the smallest osd buffer @@ -1158,8 +1162,11 @@ static int ivtvfb_init_card(struct ivtv *itv) } /* Find & setup the OSD buffer */ - if ((rc = ivtvfb_init_io(itv))) + rc = ivtvfb_init_io(itv); + if (rc) { + ivtvfb_release_buffers(itv); return rc; + } /* Set the startup video mode information */ if ((rc = ivtvfb_init_vidmode(itv))) { @@ -1210,6 +1217,7 @@ static int ivtvfb_callback_cleanup(struct device *dev, void *p) { struct v4l2_device *v4l2_dev = dev_get_drvdata(dev); struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev); + struct osd_info *oi = itv->osd_info; if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) { @@ -1218,7 +1226,7 @@ static int ivtvfb_callback_cleanup(struct device *dev, void *p) return 0; } IVTVFB_INFO("Unregister framebuffer %d\n", itv->instance); - ivtvfb_blank(FB_BLANK_POWERDOWN, &itv->osd_info->ivtvfb_info); + ivtvfb_blank(FB_BLANK_VSYNC_SUSPEND, &oi->ivtvfb_info); ivtvfb_release_buffers(itv); itv->osd_video_pbase = 0; } diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index e3b9a8a..79f096d 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c @@ -701,13 +701,13 @@ static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = { #endif }; -static int mt9m001_enum_fmt(struct v4l2_subdev *sd, int index, +static int mt9m001_enum_fmt(struct v4l2_subdev *sd, unsigned int index, enum v4l2_mbus_pixelcode *code) { struct i2c_client *client = sd->priv; struct mt9m001 *mt9m001 = to_mt9m001(client); - if ((unsigned int)index >= mt9m001->num_fmts) + if (index >= mt9m001->num_fmts) return -EINVAL; *code = mt9m001->fmts[index].code; diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c index e42162c..fbd0fc7 100644 --- a/drivers/media/video/mt9m111.c +++ b/drivers/media/video/mt9m111.c @@ -999,10 +999,10 @@ static struct v4l2_subdev_core_ops mt9m111_subdev_core_ops = { #endif }; -static int mt9m111_enum_fmt(struct v4l2_subdev *sd, int index, +static int mt9m111_enum_fmt(struct v4l2_subdev *sd, unsigned int index, enum v4l2_mbus_pixelcode *code) { - if ((unsigned int)index >= ARRAY_SIZE(mt9m111_colour_fmts)) + if (index >= ARRAY_SIZE(mt9m111_colour_fmts)) return -EINVAL; *code = mt9m111_colour_fmts[index].code; diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c index 9f5ff25..a9a28b2 100644 --- a/drivers/media/video/mt9t031.c +++ b/drivers/media/video/mt9t031.c @@ -798,7 +798,7 @@ static struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = { #endif }; -static int mt9t031_enum_fmt(struct v4l2_subdev *sd, int index, +static int mt9t031_enum_fmt(struct v4l2_subdev *sd, unsigned int index, enum v4l2_mbus_pixelcode *code) { if (index) diff --git a/drivers/media/video/mt9t112.c b/drivers/media/video/mt9t112.c index aa4fce9..e4bf1db 100644 --- a/drivers/media/video/mt9t112.c +++ b/drivers/media/video/mt9t112.c @@ -1017,10 +1017,10 @@ static int mt9t112_try_fmt(struct v4l2_subdev *sd, return 0; } -static int mt9t112_enum_fmt(struct v4l2_subdev *sd, int index, +static int mt9t112_enum_fmt(struct v4l2_subdev *sd, unsigned int index, enum v4l2_mbus_pixelcode *code) { - if ((unsigned int)index >= ARRAY_SIZE(mt9t112_cfmts)) + if (index >= ARRAY_SIZE(mt9t112_cfmts)) return -EINVAL; *code = mt9t112_cfmts[index].code; diff --git a/drivers/media/video/mt9v011.c b/drivers/media/video/mt9v011.c index 72e55be..f5e778d 100644 --- a/drivers/media/video/mt9v011.c +++ b/drivers/media/video/mt9v011.c @@ -392,27 +392,25 @@ static int mt9v011_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) return 0; } -static int mt9v011_enum_fmt(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt) +static int mt9v011_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index, + enum v4l2_mbus_pixelcode *code) { - if (fmt->index > 0) + if (index > 0) return -EINVAL; - fmt->flags = 0; - strcpy(fmt->description, "8 bpp Bayer GRGR..BGBG"); - fmt->pixelformat = V4L2_PIX_FMT_SGRBG8; - + *code = V4L2_MBUS_FMT_SGRBG8_1X8; return 0; } -static int mt9v011_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +static int mt9v011_try_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt) { - struct v4l2_pix_format *pix = &fmt->fmt.pix; - - if (pix->pixelformat != V4L2_PIX_FMT_SGRBG8) + if (fmt->code != V4L2_MBUS_FMT_SGRBG8_1X8) return -EINVAL; - v4l_bound_align_image(&pix->width, 48, 639, 1, - &pix->height, 32, 480, 1, 0); + v4l_bound_align_image(&fmt->width, 48, 639, 1, + &fmt->height, 32, 480, 1, 0); + fmt->field = V4L2_FIELD_NONE; + fmt->colorspace = V4L2_COLORSPACE_SRGB; return 0; } @@ -455,18 +453,17 @@ static int mt9v011_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) return 0; } -static int mt9v011_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +static int mt9v011_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt) { - struct v4l2_pix_format *pix = &fmt->fmt.pix; struct mt9v011 *core = to_mt9v011(sd); int rc; - rc = mt9v011_try_fmt(sd, fmt); + rc = mt9v011_try_mbus_fmt(sd, fmt); if (rc < 0) return -EINVAL; - core->width = pix->width; - core->height = pix->height; + core->width = fmt->width; + core->height = fmt->height; set_res(sd); @@ -549,9 +546,9 @@ static const struct v4l2_subdev_core_ops mt9v011_core_ops = { }; static const struct v4l2_subdev_video_ops mt9v011_video_ops = { - .enum_fmt = mt9v011_enum_fmt, - .try_fmt = mt9v011_try_fmt, - .s_fmt = mt9v011_s_fmt, + .enum_mbus_fmt = mt9v011_enum_mbus_fmt, + .try_mbus_fmt = mt9v011_try_mbus_fmt, + .s_mbus_fmt = mt9v011_s_mbus_fmt, .g_parm = mt9v011_g_parm, .s_parm = mt9v011_s_parm, }; diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index fb44ff0..e7cd23c 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c @@ -838,13 +838,13 @@ static struct v4l2_subdev_core_ops mt9v022_subdev_core_ops = { #endif }; -static int mt9v022_enum_fmt(struct v4l2_subdev *sd, int index, +static int mt9v022_enum_fmt(struct v4l2_subdev *sd, unsigned int index, enum v4l2_mbus_pixelcode *code) { struct i2c_client *client = sd->priv; struct mt9v022 *mt9v022 = to_mt9v022(client); - if ((unsigned int)index >= mt9v022->num_fmts) + if (index >= mt9v022->num_fmts) return -EINVAL; *code = mt9v022->fmts[index].code; diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c index d477e30..a9be14c 100644 --- a/drivers/media/video/mx3_camera.c +++ b/drivers/media/video/mx3_camera.c @@ -672,7 +672,7 @@ static bool mx3_camera_packing_supported(const struct soc_mbus_pixelfmt *fmt) fmt->packing == SOC_MBUS_PACKING_EXTEND16); } -static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx, +static int mx3_camera_get_formats(struct soc_camera_device *icd, unsigned int idx, struct soc_camera_format_xlate *xlate) { struct v4l2_subdev *sd = soc_camera_to_subdev(icd); @@ -689,7 +689,7 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx, fmt = soc_mbus_get_fmtdesc(code); if (!fmt) { dev_err(icd->dev.parent, - "Invalid format code #%d: %d\n", idx, code); + "Invalid format code #%u: %d\n", idx, code); return 0; } diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c index 4c0ab49..e7db0554 100644 --- a/drivers/media/video/omap/omap_vout.c +++ b/drivers/media/video/omap/omap_vout.c @@ -2371,12 +2371,11 @@ static int __init omap_vout_create_video_devices(struct platform_device *pdev) for (k = 0; k < pdev->num_resources; k++) { - vout = kmalloc(sizeof(struct omap_vout_device), GFP_KERNEL); + vout = kzalloc(sizeof(struct omap_vout_device), GFP_KERNEL); if (!vout) { dev_err(&pdev->dev, ": could not allocate memory\n"); return -ENOMEM; } - memset(vout, 0, sizeof(struct omap_vout_device)); vout->vid = k; vid_dev->vouts[k] = vout; diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c index c33acc9..34034a7 100644 --- a/drivers/media/video/ov772x.c +++ b/drivers/media/video/ov772x.c @@ -1092,10 +1092,10 @@ static struct v4l2_subdev_core_ops ov772x_subdev_core_ops = { #endif }; -static int ov772x_enum_fmt(struct v4l2_subdev *sd, int index, +static int ov772x_enum_fmt(struct v4l2_subdev *sd, unsigned int index, enum v4l2_mbus_pixelcode *code) { - if ((unsigned int)index >= ARRAY_SIZE(ov772x_cfmts)) + if (index >= ARRAY_SIZE(ov772x_cfmts)) return -EINVAL; *code = ov772x_cfmts[index].code; diff --git a/drivers/media/video/ov9640.c b/drivers/media/video/ov9640.c index 035e9ec..7ce9e05 100644 --- a/drivers/media/video/ov9640.c +++ b/drivers/media/video/ov9640.c @@ -614,10 +614,10 @@ static int ov9640_try_fmt(struct v4l2_subdev *sd, return 0; } -static int ov9640_enum_fmt(struct v4l2_subdev *sd, int index, +static int ov9640_enum_fmt(struct v4l2_subdev *sd, unsigned int index, enum v4l2_mbus_pixelcode *code) { - if ((unsigned int)index >= ARRAY_SIZE(ov9640_codes)) + if (index >= ARRAY_SIZE(ov9640_codes)) return -EINVAL; *code = ov9640_codes[index]; diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index 6bc16c1..3092abf 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -117,6 +117,7 @@ static const struct pvr2_device_desc pvr2_device_24xxx = { static const struct pvr2_device_client_desc pvr2_cli_gotview_2[] = { { .module_id = PVR2_CLIENT_ID_CX25840 }, { .module_id = PVR2_CLIENT_ID_TUNER }, + { .module_id = PVR2_CLIENT_ID_DEMOD }, }; static const struct pvr2_device_desc pvr2_device_gotview_2 = { diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/drivers/media/video/pvrusb2/pvrusb2-devattr.h index e5b9594..273c8d4 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.h @@ -177,6 +177,11 @@ struct pvr2_device_desc { unsigned int flag_has_composite:1; /* Has composite input */ unsigned int flag_has_svideo:1; /* Has s-video input */ unsigned int flag_fx2_16kb:1; /* 16KB FX2 firmware OK here */ + + /* If this driver is considered experimental, i.e. not all aspects + are working correctly and/or it is untested, mark that fact + with this flag. */ + unsigned int flag_is_experimental:1; }; extern struct usb_device_id pvr2_device_table[]; diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 301ef19..70ea578 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2459,6 +2459,19 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, hdw,hdw_desc->description); pvr2_trace(PVR2_TRACE_INFO, "Hardware description: %s", hdw_desc->description); + if (hdw_desc->flag_is_experimental) { + pvr2_trace(PVR2_TRACE_INFO, "**********"); + pvr2_trace(PVR2_TRACE_INFO, + "WARNING: Support for this device (%s) is" + " experimental.", hdw_desc->description); + pvr2_trace(PVR2_TRACE_INFO, + "Important functionality might not be" + " entirely working."); + pvr2_trace(PVR2_TRACE_INFO, + "Please consider contacting the driver author to" + " help with further stabilization of the driver."); + pvr2_trace(PVR2_TRACE_INFO, "**********"); + } if (!hdw) goto fail; init_timer(&hdw->quiescent_timer); @@ -3056,14 +3069,14 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw) } if (hdw->res_hor_dirty || hdw->res_ver_dirty || hdw->force_dirty) { - struct v4l2_format fmt; + struct v4l2_mbus_framefmt fmt; memset(&fmt, 0, sizeof(fmt)); - fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - fmt.fmt.pix.width = hdw->res_hor_val; - fmt.fmt.pix.height = hdw->res_ver_val; + fmt.width = hdw->res_hor_val; + fmt.height = hdw->res_ver_val; + fmt.code = V4L2_MBUS_FMT_FIXED; pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_size(%dx%d)", - fmt.fmt.pix.width, fmt.fmt.pix.height); - v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_fmt, &fmt); + fmt.width, fmt.height); + v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_mbus_fmt, &fmt); } if (hdw->srate_dirty || hdw->force_dirty) { @@ -4084,12 +4097,20 @@ void pvr2_hdw_device_reset(struct pvr2_hdw *hdw) void pvr2_hdw_cpureset_assert(struct pvr2_hdw *hdw,int val) { - char da[1]; + char *da; unsigned int pipe; int ret; if (!hdw->usb_dev) return; + da = kmalloc(16, GFP_KERNEL); + + if (da == NULL) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Unable to allocate memory to control CPU reset"); + return; + } + pvr2_trace(PVR2_TRACE_INIT,"cpureset_assert(%d)",val); da[0] = val ? 0x01 : 0x00; @@ -4103,6 +4124,8 @@ void pvr2_hdw_cpureset_assert(struct pvr2_hdw *hdw,int val) "cpureset_assert(%d) error=%d",val,ret); pvr2_hdw_render_useless(hdw); } + + kfree(da); } diff --git a/drivers/media/video/pvrusb2/pvrusb2-main.c b/drivers/media/video/pvrusb2/pvrusb2-main.c index eeacd0f..2254194 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-main.c +++ b/drivers/media/video/pvrusb2/pvrusb2-main.c @@ -153,12 +153,12 @@ static void __exit pvr_exit(void) usb_deregister(&pvr_driver); + pvr2_context_global_done(); + #ifdef CONFIG_VIDEO_PVRUSB2_SYSFS pvr2_sysfs_class_destroy(class_ptr); #endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */ - pvr2_context_global_done(); - pvr2_trace(PVR2_TRACE_INIT,"pvr_exit complete"); } diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index 71f5056..3d7e5aa 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -74,7 +74,7 @@ struct pvr2_sysfs_ctl_item { int ctl_id; struct pvr2_sysfs *chptr; struct pvr2_sysfs_ctl_item *item_next; - struct attribute *attr_gen[7]; + struct attribute *attr_gen[8]; struct attribute_group grp; int created_ok; char name[80]; @@ -511,6 +511,7 @@ static void pvr2_sysfs_release(struct device *class_dev) static void class_dev_destroy(struct pvr2_sysfs *sfp) { + struct device *dev; if (!sfp->class_dev) return; #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC pvr2_sysfs_tear_down_debugifc(sfp); @@ -542,6 +543,9 @@ static void class_dev_destroy(struct pvr2_sysfs *sfp) } pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev); dev_set_drvdata(sfp->class_dev, NULL); + dev = sfp->class_dev->parent; + sfp->class_dev->parent = NULL; + put_device(dev); device_unregister(sfp->class_dev); sfp->class_dev = NULL; } @@ -631,10 +635,11 @@ static void class_dev_create(struct pvr2_sysfs *sfp, pvr2_sysfs_trace("Creating class_dev id=%p",class_dev); class_dev->class = &class_ptr->class; + dev_set_name(class_dev, "%s", pvr2_hdw_get_device_identifier(sfp->channel.hdw)); - class_dev->parent = &usb_dev->dev; + class_dev->parent = get_device(&usb_dev->dev); sfp->class_dev = class_dev; dev_set_drvdata(class_dev, sfp); @@ -775,7 +780,8 @@ struct pvr2_sysfs_class *pvr2_sysfs_class_create(void) struct pvr2_sysfs_class *clp; clp = kzalloc(sizeof(*clp),GFP_KERNEL); if (!clp) return clp; - pvr2_sysfs_trace("Creating pvr2_sysfs_class id=%p",clp); + pvr2_sysfs_trace("Creating and registering pvr2_sysfs_class id=%p", + clp); clp->class.name = "pvrusb2"; clp->class.class_release = pvr2_sysfs_class_release; clp->class.dev_release = pvr2_sysfs_release; @@ -791,6 +797,7 @@ struct pvr2_sysfs_class *pvr2_sysfs_class_create(void) void pvr2_sysfs_class_destroy(struct pvr2_sysfs_class *clp) { + pvr2_sysfs_trace("Unregistering pvr2_sysfs_class id=%p", clp); class_unregister(&clp->class); } diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 5ffa0d2..aaafa03 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -883,6 +883,17 @@ static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) { struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw; enum pvr2_config cfg = dip->config; + char msg[80]; + unsigned int mcnt; + + /* Construct the unregistration message *before* we actually + perform the unregistration step. By doing it this way we don't + have to worry about potentially touching deleted resources. */ + mcnt = scnprintf(msg, sizeof(msg) - 1, + "pvrusb2: unregistered device %s [%s]", + video_device_node_name(&dip->devbase), + pvr2_config_get_name(cfg)); + msg[mcnt] = 0; pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1); @@ -894,9 +905,7 @@ static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) are gone. */ video_unregister_device(&dip->devbase); - printk(KERN_INFO "pvrusb2: unregistered device %s [%s]\n", - video_device_node_name(&dip->devbase), - pvr2_config_get_name(cfg)); + printk(KERN_INFO "%s\n", msg); } diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index 7fe70e7..fb242f6 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c @@ -1247,7 +1247,7 @@ static bool pxa_camera_packing_supported(const struct soc_mbus_pixelfmt *fmt) fmt->packing == SOC_MBUS_PACKING_EXTEND16); } -static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, +static int pxa_camera_get_formats(struct soc_camera_device *icd, unsigned int idx, struct soc_camera_format_xlate *xlate) { struct v4l2_subdev *sd = soc_camera_to_subdev(icd); @@ -1264,7 +1264,7 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, fmt = soc_mbus_get_fmtdesc(code); if (!fmt) { - dev_err(dev, "Invalid format code #%d: %d\n", idx, code); + dev_err(dev, "Invalid format code #%u: %d\n", idx, code); return 0; } diff --git a/drivers/media/video/rj54n1cb0c.c b/drivers/media/video/rj54n1cb0c.c index 2c3b58c..47fd207 100644 --- a/drivers/media/video/rj54n1cb0c.c +++ b/drivers/media/video/rj54n1cb0c.c @@ -481,10 +481,10 @@ static int reg_write_multiple(struct i2c_client *client, return 0; } -static int rj54n1_enum_fmt(struct v4l2_subdev *sd, int index, +static int rj54n1_enum_fmt(struct v4l2_subdev *sd, unsigned int index, enum v4l2_mbus_pixelcode *code) { - if ((unsigned int)index >= ARRAY_SIZE(rj54n1_colour_fmts)) + if (index >= ARRAY_SIZE(rj54n1_colour_fmts)) return -EINVAL; *code = rj54n1_colour_fmts[index].code; diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index 53b6fcd..76da743 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -1117,13 +1117,6 @@ static int saa711x_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f return 0; } -static int saa711x_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) -{ - if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) - return -EINVAL; - return saa711x_g_sliced_fmt(sd, &fmt->fmt.sliced); -} - static int saa711x_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt) { saa711x_set_lcr(sd, NULL); @@ -1136,12 +1129,13 @@ static int saa711x_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f return 0; } -static int saa711x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +static int saa711x_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt) { - if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + if (fmt->code != V4L2_MBUS_FMT_FIXED) return -EINVAL; - - return saa711x_set_size(sd, fmt->fmt.pix.width, fmt->fmt.pix.height); + fmt->field = V4L2_FIELD_INTERLACED; + fmt->colorspace = V4L2_COLORSPACE_SMPTE170M; + return saa711x_set_size(sd, fmt->width, fmt->height); } /* Decode the sliced VBI data stream as created by the saa7115. @@ -1556,8 +1550,7 @@ static const struct v4l2_subdev_audio_ops saa711x_audio_ops = { static const struct v4l2_subdev_video_ops saa711x_video_ops = { .s_routing = saa711x_s_routing, .s_crystal_freq = saa711x_s_crystal_freq, - .g_fmt = saa711x_g_fmt, - .s_fmt = saa711x_s_fmt, + .s_mbus_fmt = saa711x_s_mbus_fmt, .s_stream = saa711x_s_stream, .querystd = saa711x_querystd, .g_input_status = saa711x_g_input_status, diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c index 87986ad..79fffcf 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/video/saa7127.c @@ -645,13 +645,6 @@ static int saa7127_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f return 0; } -static int saa7127_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) -{ - if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) - return -EINVAL; - return saa7127_g_sliced_fmt(sd, &fmt->fmt.sliced); -} - static int saa7127_s_vbi_data(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data) { switch (data->id) { @@ -731,7 +724,6 @@ static const struct v4l2_subdev_core_ops saa7127_core_ops = { }; static const struct v4l2_subdev_video_ops saa7127_video_ops = { - .g_fmt = saa7127_g_fmt, .s_std_output = saa7127_s_std_output, .s_routing = saa7127_s_routing, .s_stream = saa7127_s_stream, diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c index 1eabff6..40fd31c 100644 --- a/drivers/media/video/saa7134/saa6752hs.c +++ b/drivers/media/video/saa7134/saa6752hs.c @@ -846,24 +846,28 @@ static int saa6752hs_g_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_control return 0; } -static int saa6752hs_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +static int saa6752hs_g_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f) { struct saa6752hs_state *h = to_state(sd); if (h->video_format == SAA6752HS_VF_UNKNOWN) h->video_format = SAA6752HS_VF_D1; - f->fmt.pix.width = - v4l2_format_table[h->video_format].fmt.pix.width; - f->fmt.pix.height = - v4l2_format_table[h->video_format].fmt.pix.height; + f->width = v4l2_format_table[h->video_format].fmt.pix.width; + f->height = v4l2_format_table[h->video_format].fmt.pix.height; + f->code = V4L2_MBUS_FMT_FIXED; + f->field = V4L2_FIELD_INTERLACED; + f->colorspace = V4L2_COLORSPACE_SMPTE170M; return 0; } -static int saa6752hs_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +static int saa6752hs_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f) { struct saa6752hs_state *h = to_state(sd); int dist_352, dist_480, dist_720; + if (f->code != V4L2_MBUS_FMT_FIXED) + return -EINVAL; + /* FIXME: translate and round width/height into EMPRESS subsample type: @@ -876,28 +880,30 @@ static int saa6752hs_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) D1 | 720x576 | 720x480 */ - dist_352 = abs(f->fmt.pix.width - 352); - dist_480 = abs(f->fmt.pix.width - 480); - dist_720 = abs(f->fmt.pix.width - 720); + dist_352 = abs(f->width - 352); + dist_480 = abs(f->width - 480); + dist_720 = abs(f->width - 720); if (dist_720 < dist_480) { - f->fmt.pix.width = 720; - f->fmt.pix.height = 576; + f->width = 720; + f->height = 576; h->video_format = SAA6752HS_VF_D1; } else if (dist_480 < dist_352) { - f->fmt.pix.width = 480; - f->fmt.pix.height = 576; + f->width = 480; + f->height = 576; h->video_format = SAA6752HS_VF_2_3_D1; } else { - f->fmt.pix.width = 352; - if (abs(f->fmt.pix.height - 576) < - abs(f->fmt.pix.height - 288)) { - f->fmt.pix.height = 576; + f->width = 352; + if (abs(f->height - 576) < + abs(f->height - 288)) { + f->height = 576; h->video_format = SAA6752HS_VF_1_2_D1; } else { - f->fmt.pix.height = 288; + f->height = 288; h->video_format = SAA6752HS_VF_SIF; } } + f->field = V4L2_FIELD_INTERLACED; + f->colorspace = V4L2_COLORSPACE_SMPTE170M; return 0; } @@ -932,8 +938,8 @@ static const struct v4l2_subdev_core_ops saa6752hs_core_ops = { }; static const struct v4l2_subdev_video_ops saa6752hs_video_ops = { - .s_fmt = saa6752hs_s_fmt, - .g_fmt = saa6752hs_g_fmt, + .s_mbus_fmt = saa6752hs_s_mbus_fmt, + .g_mbus_fmt = saa6752hs_g_mbus_fmt, }; static const struct v4l2_subdev_ops saa6752hs_ops = { diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 72700d4e..07f6bb8 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -3897,6 +3897,40 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x01, }, }, + [SAA7134_BOARD_AVERMEDIA_M733A] = { + .name = "Avermedia PCI M733A", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tuner_config = 0, + .gpiomask = 0x020200000, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = TV, + .gpio = 0x00200000, + }, + .mute = { + .name = name_mute, + .amux = TV, + .gpio = 0x01, + }, + }, [SAA7134_BOARD_BEHOLD_401] = { /* Beholder Intl. Ltd. 2008 */ /*Dmitry Belimov <d.belimov@gmail.com> */ @@ -5822,6 +5856,18 @@ struct pci_device_id saa7134_pci_tbl[] = { .driver_data = SAA7134_BOARD_AVERMEDIA_M135A, }, { .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1461, /* Avermedia Technologies Inc */ + .subdevice = 0x4155, + .driver_data = SAA7134_BOARD_AVERMEDIA_M733A, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1461, /* Avermedia Technologies Inc */ + .subdevice = 0x4255, + .driver_data = SAA7134_BOARD_AVERMEDIA_M733A, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7130, .subvendor = PCI_VENDOR_ID_PHILIPS, .subdevice = 0x2004, @@ -6786,6 +6832,7 @@ static int saa7134_tda8290_callback(struct saa7134_dev *dev, switch (dev->board) { case SAA7134_BOARD_HAUPPAUGE_HVR1150: case SAA7134_BOARD_HAUPPAUGE_HVR1120: + case SAA7134_BOARD_AVERMEDIA_M733A: /* tda8290 + tda18271 */ ret = saa7134_tda8290_18271_callback(dev, command, arg); break; @@ -7087,6 +7134,14 @@ int saa7134_board_init1(struct saa7134_dev *dev) saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x0000C000, 0x0000C000); saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0000C000, 0x0000C000); break; + case SAA7134_BOARD_AVERMEDIA_M733A: + saa7134_set_gpio(dev, 1, 1); + msleep(10); + saa7134_set_gpio(dev, 1, 0); + msleep(10); + saa7134_set_gpio(dev, 1, 1); + dev->has_remote = SAA7134_REMOTE_GPIO; + break; } return 0; } diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index ea877a5..e763f9f 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -223,9 +223,11 @@ static int empress_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { struct saa7134_dev *dev = file->private_data; + struct v4l2_mbus_framefmt mbus_fmt; - saa_call_all(dev, video, g_fmt, f); + saa_call_all(dev, video, g_mbus_fmt, &mbus_fmt); + v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt); f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets; @@ -236,8 +238,11 @@ static int empress_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { struct saa7134_dev *dev = file->private_data; + struct v4l2_mbus_framefmt mbus_fmt; - saa_call_all(dev, video, s_fmt, f); + v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED); + saa_call_all(dev, video, s_mbus_fmt, &mbus_fmt); + v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt); f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets; diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index e5565e2..0b336ca 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -141,8 +141,8 @@ static int get_key_flydvb_trio(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) struct saa7134_dev *dev = ir->c->adapter->algo_data; if (dev == NULL) { - dprintk("get_key_flydvb_trio: " - "gir->c->adapter->algo_data is NULL!\n"); + i2cdprintk("get_key_flydvb_trio: " + "ir->c->adapter->algo_data is NULL!\n"); return -EIO; } @@ -195,8 +195,8 @@ static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, u32 *ir_key, /* <dev> is needed to access GPIO. Used by the saa_readl macro. */ struct saa7134_dev *dev = ir->c->adapter->algo_data; if (dev == NULL) { - dprintk("get_key_msi_tvanywhere_plus: " - "gir->c->adapter->algo_data is NULL!\n"); + i2cdprintk("get_key_msi_tvanywhere_plus: " + "ir->c->adapter->algo_data is NULL!\n"); return -EIO; } @@ -657,12 +657,19 @@ int saa7134_input_init1(struct saa7134_dev *dev) saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); break; case SAA7134_BOARD_AVERMEDIA_M135A: - ir_codes = RC_MAP_AVERMEDIA_M135A_RM_JX; + ir_codes = RC_MAP_AVERMEDIA_M135A; mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ mask_keyup = 0x0040000; mask_keycode = 0xffff; raw_decode = 1; break; + case SAA7134_BOARD_AVERMEDIA_M733A: + ir_codes = RC_MAP_AVERMEDIA_M733A_RM_K6; + mask_keydown = 0x0040000; + mask_keyup = 0x0040000; + mask_keycode = 0xffff; + raw_decode = 1; + break; case SAA7134_BOARD_AVERMEDIA_777: case SAA7134_BOARD_AVERMEDIA_A16AR: ir_codes = RC_MAP_AVERMEDIA; @@ -815,7 +822,6 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keyup = 0x020000; polling = 50; /* ms */ break; - break; } if (NULL == ir_codes) { printk("%s: Oops: IR config error [card=%d]\n", diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 3962534..756a1ca 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -303,6 +303,7 @@ struct saa7134_format { #define SAA7134_BOARD_HAWELL_HW_404M7 177 #define SAA7134_BOARD_BEHOLD_H7 178 #define SAA7134_BOARD_BEHOLD_A7 179 +#define SAA7134_BOARD_AVERMEDIA_M733A 180 #define SAA7134_MAXBOARDS 32 #define SAA7134_INPUT_MAX 8 diff --git a/drivers/media/video/saa717x.c b/drivers/media/video/saa717x.c index d521c64..78d6995 100644 --- a/drivers/media/video/saa717x.c +++ b/drivers/media/video/saa717x.c @@ -1199,28 +1199,32 @@ static int saa717x_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register * } #endif -static int saa717x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +static int saa717x_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt) { - struct v4l2_pix_format *pix; int prescale, h_scale, v_scale; - pix = &fmt->fmt.pix; v4l2_dbg(1, debug, sd, "decoder set size\n"); + if (fmt->code != V4L2_MBUS_FMT_FIXED) + return -EINVAL; + /* FIXME need better bounds checking here */ - if (pix->width < 1 || pix->width > 1440) + if (fmt->width < 1 || fmt->width > 1440) return -EINVAL; - if (pix->height < 1 || pix->height > 960) + if (fmt->height < 1 || fmt->height > 960) return -EINVAL; + fmt->field = V4L2_FIELD_INTERLACED; + fmt->colorspace = V4L2_COLORSPACE_SMPTE170M; + /* scaling setting */ /* NTSC and interlace only */ - prescale = SAA717X_NTSC_WIDTH / pix->width; + prescale = SAA717X_NTSC_WIDTH / fmt->width; if (prescale == 0) prescale = 1; - h_scale = 1024 * SAA717X_NTSC_WIDTH / prescale / pix->width; + h_scale = 1024 * SAA717X_NTSC_WIDTH / prescale / fmt->width; /* interlace */ - v_scale = 512 * 2 * SAA717X_NTSC_HEIGHT / pix->height; + v_scale = 512 * 2 * SAA717X_NTSC_HEIGHT / fmt->height; /* Horizontal prescaling etc */ set_h_prescale(sd, 0, prescale); @@ -1241,19 +1245,19 @@ static int saa717x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) /* set video output size */ /* video number of pixels at output */ /* TASK A */ - saa717x_write(sd, 0x5C, (u8)(pix->width & 0xFF)); - saa717x_write(sd, 0x5D, (u8)((pix->width >> 8) & 0xFF)); + saa717x_write(sd, 0x5C, (u8)(fmt->width & 0xFF)); + saa717x_write(sd, 0x5D, (u8)((fmt->width >> 8) & 0xFF)); /* TASK B */ - saa717x_write(sd, 0x9C, (u8)(pix->width & 0xFF)); - saa717x_write(sd, 0x9D, (u8)((pix->width >> 8) & 0xFF)); + saa717x_write(sd, 0x9C, (u8)(fmt->width & 0xFF)); + saa717x_write(sd, 0x9D, (u8)((fmt->width >> 8) & 0xFF)); /* video number of lines at output */ /* TASK A */ - saa717x_write(sd, 0x5E, (u8)(pix->height & 0xFF)); - saa717x_write(sd, 0x5F, (u8)((pix->height >> 8) & 0xFF)); + saa717x_write(sd, 0x5E, (u8)(fmt->height & 0xFF)); + saa717x_write(sd, 0x5F, (u8)((fmt->height >> 8) & 0xFF)); /* TASK B */ - saa717x_write(sd, 0x9E, (u8)(pix->height & 0xFF)); - saa717x_write(sd, 0x9F, (u8)((pix->height >> 8) & 0xFF)); + saa717x_write(sd, 0x9E, (u8)(fmt->height & 0xFF)); + saa717x_write(sd, 0x9F, (u8)((fmt->height >> 8) & 0xFF)); return 0; } @@ -1403,7 +1407,7 @@ static const struct v4l2_subdev_tuner_ops saa717x_tuner_ops = { static const struct v4l2_subdev_video_ops saa717x_video_ops = { .s_routing = saa717x_s_video_routing, - .s_fmt = saa717x_s_fmt, + .s_mbus_fmt = saa717x_s_mbus_fmt, .s_stream = saa717x_s_stream, }; diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 4ac3b48..961bfa2 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c @@ -878,7 +878,7 @@ static bool sh_mobile_ceu_packing_supported(const struct soc_mbus_pixelfmt *fmt) static int client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect); -static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, +static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int idx, struct soc_camera_format_xlate *xlate) { struct v4l2_subdev *sd = soc_camera_to_subdev(icd); @@ -897,7 +897,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, fmt = soc_mbus_get_fmtdesc(code); if (!fmt) { dev_err(icd->dev.parent, - "Invalid format code #%d: %d\n", idx, code); + "Invalid format code #%u: %d\n", idx, code); return -EINVAL; } diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h index 522ba3f..b6643ca 100644 --- a/drivers/media/video/sn9c102/sn9c102_devtable.h +++ b/drivers/media/video/sn9c102/sn9c102_devtable.h @@ -62,8 +62,8 @@ static const struct usb_device_id sn9c102_id_table[] = { #if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE { SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), }, /* { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), }, HV7131R */ -#endif { SN9C102_USB_DEVICE(0x0c45, 0x602e, BRIDGE_SN9C102), }, +#endif { SN9C102_USB_DEVICE(0x0c45, 0x6030, BRIDGE_SN9C102), }, /* SN9C103 */ { SN9C102_USB_DEVICE(0x0c45, 0x6080, BRIDGE_SN9C103), }, diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index db1ca0e..475757b 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -200,7 +200,8 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd) { struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - int i, fmts = 0, raw_fmts = 0, ret; + unsigned int i, fmts = 0, raw_fmts = 0; + int ret; enum v4l2_mbus_pixelcode code; while (!v4l2_subdev_call(sd, video, enum_mbus_fmt, raw_fmts, &code)) diff --git a/drivers/media/video/soc_camera_platform.c b/drivers/media/video/soc_camera_platform.c index 10b003a..248c986 100644 --- a/drivers/media/video/soc_camera_platform.c +++ b/drivers/media/video/soc_camera_platform.c @@ -71,7 +71,7 @@ static int soc_camera_platform_try_fmt(struct v4l2_subdev *sd, static struct v4l2_subdev_core_ops platform_subdev_core_ops; -static int soc_camera_platform_enum_fmt(struct v4l2_subdev *sd, int index, +static int soc_camera_platform_enum_fmt(struct v4l2_subdev *sd, unsigned int index, enum v4l2_mbus_pixelcode *code) { struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd); diff --git a/drivers/media/video/tvp514x.c b/drivers/media/video/tvp514x.c index e826114..71c73fa 100644 --- a/drivers/media/video/tvp514x.c +++ b/drivers/media/video/tvp514x.c @@ -88,9 +88,6 @@ static int tvp514x_s_stream(struct v4l2_subdev *sd, int enable); * @pdata: Board specific * @ver: Chip version * @streaming: TVP5146/47 decoder streaming - enabled or disabled. - * @pix: Current pixel format - * @num_fmts: Number of formats - * @fmt_list: Format list * @current_std: Current standard * @num_stds: Number of standards * @std_list: Standards list @@ -105,13 +102,9 @@ struct tvp514x_decoder { int ver; int streaming; - struct v4l2_pix_format pix; - int num_fmts; - const struct v4l2_fmtdesc *fmt_list; - enum tvp514x_std current_std; int num_stds; - struct tvp514x_std_info *std_list; + const struct tvp514x_std_info *std_list; /* Input and Output Routing parameters */ u32 input; u32 output; @@ -203,27 +196,12 @@ static struct tvp514x_reg tvp514x_reg_list_default[] = { }; /** - * List of image formats supported by TVP5146/47 decoder - * Currently we are using 8 bit mode only, but can be - * extended to 10/20 bit mode. - */ -static const struct v4l2_fmtdesc tvp514x_fmt_list[] = { - { - .index = 0, - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, - .flags = 0, - .description = "8-bit UYVY 4:2:2 Format", - .pixelformat = V4L2_PIX_FMT_UYVY, - }, -}; - -/** * Supported standards - * * Currently supports two standards only, need to add support for rest of the * modes, like SECAM, etc... */ -static struct tvp514x_std_info tvp514x_std_list[] = { +static const struct tvp514x_std_info tvp514x_std_list[] = { /* Standard: STD_NTSC_MJ */ [STD_NTSC_MJ] = { .width = NTSC_NUM_ACTIVE_PIXELS, @@ -366,13 +344,13 @@ static int tvp514x_write_regs(struct v4l2_subdev *sd, } /** - * tvp514x_get_current_std() : Get the current standard detected by TVP5146/47 + * tvp514x_query_current_std() : Query the current standard detected by TVP5146/47 * @sd: ptr to v4l2_subdev struct * - * Get current standard detected by TVP5146/47, STD_INVALID if there is no + * Returns the current standard detected by TVP5146/47, STD_INVALID if there is no * standard detected. */ -static enum tvp514x_std tvp514x_get_current_std(struct v4l2_subdev *sd) +static enum tvp514x_std tvp514x_query_current_std(struct v4l2_subdev *sd) { u8 std, std_status; @@ -518,7 +496,7 @@ static int tvp514x_detect(struct v4l2_subdev *sd, * @std_id: standard V4L2 std_id ioctl enum * * Returns the current standard detected by TVP5146/47. If no active input is - * detected, returns -EINVAL + * detected then *std_id is set to 0 and the function returns 0. */ static int tvp514x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id) { @@ -530,10 +508,12 @@ static int tvp514x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id) if (std_id == NULL) return -EINVAL; - /* get the current standard */ - current_std = tvp514x_get_current_std(sd); + *std_id = V4L2_STD_UNKNOWN; + + /* query the current standard */ + current_std = tvp514x_query_current_std(sd); if (current_std == STD_INVALID) - return -EINVAL; + return 0; input_sel = decoder->input; @@ -575,12 +555,11 @@ static int tvp514x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id) /* check whether signal is locked */ sync_lock_status = tvp514x_read_reg(sd, REG_STATUS1); if (lock_mask != (sync_lock_status & lock_mask)) - return -EINVAL; /* No input detected */ + return 0; /* No input detected */ - decoder->current_std = current_std; *std_id = decoder->std_list[current_std].standard.id; - v4l2_dbg(1, debug, sd, "Current STD: %s", + v4l2_dbg(1, debug, sd, "Current STD: %s\n", decoder->std_list[current_std].standard.name); return 0; } @@ -614,7 +593,7 @@ static int tvp514x_s_std(struct v4l2_subdev *sd, v4l2_std_id std_id) decoder->tvp514x_regs[REG_VIDEO_STD].val = decoder->std_list[i].video_std; - v4l2_dbg(1, debug, sd, "Standard set to: %s", + v4l2_dbg(1, debug, sd, "Standard set to: %s\n", decoder->std_list[i].standard.name); return 0; } @@ -637,7 +616,6 @@ static int tvp514x_s_routing(struct v4l2_subdev *sd, int err; enum tvp514x_input input_sel; enum tvp514x_output output_sel; - enum tvp514x_std current_std = STD_INVALID; u8 sync_lock_status, lock_mask; int try_count = LOCK_RETRY_COUNT; @@ -721,11 +699,6 @@ static int tvp514x_s_routing(struct v4l2_subdev *sd, /* Allow decoder to sync up with new input */ msleep(LOCK_RETRY_DELAY); - /* get the current standard for future reference */ - current_std = tvp514x_get_current_std(sd); - if (current_std == STD_INVALID) - continue; - sync_lock_status = tvp514x_read_reg(sd, REG_STATUS1); if (lock_mask == (sync_lock_status & lock_mask)) @@ -733,15 +706,13 @@ static int tvp514x_s_routing(struct v4l2_subdev *sd, break; } - if ((current_std == STD_INVALID) || (try_count < 0)) + if (try_count < 0) return -EINVAL; - decoder->current_std = current_std; decoder->input = input; decoder->output = output; - v4l2_dbg(1, debug, sd, "Input set to: %d, std : %d", - input_sel, current_std); + v4l2_dbg(1, debug, sd, "Input set to: %d\n", input_sel); return 0; } @@ -794,7 +765,7 @@ tvp514x_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qctrl) return err; } - v4l2_dbg(1, debug, sd, "Query Control:%s: Min - %d, Max - %d, Def - %d", + v4l2_dbg(1, debug, sd, "Query Control:%s: Min - %d, Max - %d, Def - %d\n", qctrl->name, qctrl->minimum, qctrl->maximum, qctrl->default_value); @@ -851,7 +822,7 @@ tvp514x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) return -EINVAL; } - v4l2_dbg(1, debug, sd, "Get Control: ID - %d - %d", + v4l2_dbg(1, debug, sd, "Get Control: ID - %d - %d\n", ctrl->id, ctrl->value); return 0; } @@ -951,7 +922,7 @@ tvp514x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) return err; } - v4l2_dbg(1, debug, sd, "Set Control: ID - %d - %d", + v4l2_dbg(1, debug, sd, "Set Control: ID - %d - %d\n", ctrl->id, ctrl->value); return err; @@ -967,44 +938,33 @@ tvp514x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) static int tvp514x_enum_fmt_cap(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt) { - struct tvp514x_decoder *decoder = to_decoder(sd); - int index; - - if (fmt == NULL) - return -EINVAL; - - index = fmt->index; - if ((index >= decoder->num_fmts) || (index < 0)) - /* Index out of bound */ + if (fmt == NULL || fmt->index) return -EINVAL; if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) /* only capture is supported */ return -EINVAL; - memcpy(fmt, &decoder->fmt_list[index], - sizeof(struct v4l2_fmtdesc)); - - v4l2_dbg(1, debug, sd, "Current FMT: index - %d (%s)", - decoder->fmt_list[index].index, - decoder->fmt_list[index].description); + /* only one format */ + fmt->flags = 0; + strlcpy(fmt->description, "8-bit UYVY 4:2:2 Format", + sizeof(fmt->description)); + fmt->pixelformat = V4L2_PIX_FMT_UYVY; return 0; } /** - * tvp514x_try_fmt_cap() - V4L2 decoder interface handler for try_fmt + * tvp514x_fmt_cap() - V4L2 decoder interface handler for try/s/g_fmt * @sd: pointer to standard V4L2 sub-device structure * @f: pointer to standard V4L2 VIDIOC_TRY_FMT ioctl structure * - * Implement the VIDIOC_TRY_FMT ioctl for the CAPTURE buffer type. This - * ioctl is used to negotiate the image capture size and pixel format - * without actually making it take effect. + * Implement the VIDIOC_TRY/S/G_FMT ioctl for the CAPTURE buffer type. This + * ioctl is used to negotiate the image capture size and pixel format. */ static int -tvp514x_try_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f) +tvp514x_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f) { struct tvp514x_decoder *decoder = to_decoder(sd); - int ifmt; struct v4l2_pix_format *pix; enum tvp514x_std current_std; @@ -1012,106 +972,30 @@ tvp514x_try_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f) return -EINVAL; if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - /* only capture is supported */ - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + return -EINVAL; pix = &f->fmt.pix; /* Calculate height and width based on current standard */ - current_std = tvp514x_get_current_std(sd); - if (current_std == STD_INVALID) - return -EINVAL; + current_std = decoder->current_std; - decoder->current_std = current_std; + pix->pixelformat = V4L2_PIX_FMT_UYVY; pix->width = decoder->std_list[current_std].width; pix->height = decoder->std_list[current_std].height; - - for (ifmt = 0; ifmt < decoder->num_fmts; ifmt++) { - if (pix->pixelformat == - decoder->fmt_list[ifmt].pixelformat) - break; - } - if (ifmt == decoder->num_fmts) - /* None of the format matched, select default */ - ifmt = 0; - pix->pixelformat = decoder->fmt_list[ifmt].pixelformat; - pix->field = V4L2_FIELD_INTERLACED; pix->bytesperline = pix->width * 2; pix->sizeimage = pix->bytesperline * pix->height; pix->colorspace = V4L2_COLORSPACE_SMPTE170M; pix->priv = 0; - v4l2_dbg(1, debug, sd, "Try FMT: pixelformat - %s, bytesperline - %d" - "Width - %d, Height - %d", - decoder->fmt_list[ifmt].description, pix->bytesperline, + v4l2_dbg(1, debug, sd, "FMT: bytesperline - %d" + "Width - %d, Height - %d\n", + pix->bytesperline, pix->width, pix->height); return 0; } /** - * tvp514x_s_fmt_cap() - V4L2 decoder interface handler for s_fmt - * @sd: pointer to standard V4L2 sub-device structure - * @f: pointer to standard V4L2 VIDIOC_S_FMT ioctl structure - * - * If the requested format is supported, configures the HW to use that - * format, returns error code if format not supported or HW can't be - * correctly configured. - */ -static int -tvp514x_s_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f) -{ - struct tvp514x_decoder *decoder = to_decoder(sd); - struct v4l2_pix_format *pix; - int rval; - - if (f == NULL) - return -EINVAL; - - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - /* only capture is supported */ - return -EINVAL; - - pix = &f->fmt.pix; - rval = tvp514x_try_fmt_cap(sd, f); - if (rval) - return rval; - - decoder->pix = *pix; - - return rval; -} - -/** - * tvp514x_g_fmt_cap() - V4L2 decoder interface handler for tvp514x_g_fmt_cap - * @sd: pointer to standard V4L2 sub-device structure - * @f: pointer to standard V4L2 v4l2_format structure - * - * Returns the decoder's current pixel format in the v4l2_format - * parameter. - */ -static int -tvp514x_g_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f) -{ - struct tvp514x_decoder *decoder = to_decoder(sd); - - if (f == NULL) - return -EINVAL; - - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - /* only capture is supported */ - return -EINVAL; - - f->fmt.pix = decoder->pix; - - v4l2_dbg(1, debug, sd, "Current FMT: bytesperline - %d" - "Width - %d, Height - %d", - decoder->pix.bytesperline, - decoder->pix.width, decoder->pix.height); - return 0; -} - -/** * tvp514x_g_parm() - V4L2 decoder interface handler for g_parm * @sd: pointer to standard V4L2 sub-device structure * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure @@ -1132,15 +1016,8 @@ tvp514x_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a) /* only capture is supported */ return -EINVAL; - memset(a, 0, sizeof(*a)); - a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - /* get the current standard */ - current_std = tvp514x_get_current_std(sd); - if (current_std == STD_INVALID) - return -EINVAL; - - decoder->current_std = current_std; + current_std = decoder->current_std; cparm = &a->parm.capture; cparm->capability = V4L2_CAP_TIMEPERFRAME; @@ -1175,11 +1052,7 @@ tvp514x_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a) timeperframe = &a->parm.capture.timeperframe; /* get the current standard */ - current_std = tvp514x_get_current_std(sd); - if (current_std == STD_INVALID) - return -EINVAL; - - decoder->current_std = current_std; + current_std = decoder->current_std; *timeperframe = decoder->std_list[current_std].standard.frameperiod; @@ -1259,9 +1132,9 @@ static const struct v4l2_subdev_video_ops tvp514x_video_ops = { .s_routing = tvp514x_s_routing, .querystd = tvp514x_querystd, .enum_fmt = tvp514x_enum_fmt_cap, - .g_fmt = tvp514x_g_fmt_cap, - .try_fmt = tvp514x_try_fmt_cap, - .s_fmt = tvp514x_s_fmt_cap, + .g_fmt = tvp514x_fmt_cap, + .try_fmt = tvp514x_fmt_cap, + .s_fmt = tvp514x_fmt_cap, .g_parm = tvp514x_g_parm, .s_parm = tvp514x_s_parm, .s_stream = tvp514x_s_stream, @@ -1274,22 +1147,6 @@ static const struct v4l2_subdev_ops tvp514x_ops = { static struct tvp514x_decoder tvp514x_dev = { .streaming = 0, - - .fmt_list = tvp514x_fmt_list, - .num_fmts = ARRAY_SIZE(tvp514x_fmt_list), - - .pix = { - /* Default to NTSC 8-bit YUV 422 */ - .width = NTSC_NUM_ACTIVE_PIXELS, - .height = NTSC_NUM_ACTIVE_LINES, - .pixelformat = V4L2_PIX_FMT_UYVY, - .field = V4L2_FIELD_INTERLACED, - .bytesperline = NTSC_NUM_ACTIVE_PIXELS * 2, - .sizeimage = - NTSC_NUM_ACTIVE_PIXELS * 2 * NTSC_NUM_ACTIVE_LINES, - .colorspace = V4L2_COLORSPACE_SMPTE170M, - }, - .current_std = STD_NTSC_MJ, .std_list = tvp514x_std_list, .num_stds = ARRAY_SIZE(tvp514x_std_list), diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index 47f0582..1654f65 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -934,17 +934,6 @@ static int tvp5150_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f return 0; } -static int tvp5150_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) -{ - switch (fmt->type) { - case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: - return tvp5150_s_sliced_fmt(sd, &fmt->fmt.sliced); - - default: - return -EINVAL; - } -} - static int tvp5150_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi) { int i, mask = 0; @@ -960,13 +949,6 @@ static int tvp5150_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f return 0; } -static int tvp5150_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) -{ - if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) - return -EINVAL; - return tvp5150_g_sliced_fmt(sd, &fmt->fmt.sliced); -} - static int tvp5150_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) { @@ -1054,8 +1036,6 @@ static const struct v4l2_subdev_tuner_ops tvp5150_tuner_ops = { static const struct v4l2_subdev_video_ops tvp5150_video_ops = { .s_routing = tvp5150_s_routing, - .g_fmt = tvp5150_g_fmt, - .s_fmt = tvp5150_s_fmt, }; static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = { diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c index 6eb3395..445dc93 100644 --- a/drivers/media/video/tw9910.c +++ b/drivers/media/video/tw9910.c @@ -903,7 +903,7 @@ static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = { #endif }; -static int tw9910_enum_fmt(struct v4l2_subdev *sd, int index, +static int tw9910_enum_fmt(struct v4l2_subdev *sd, unsigned int index, enum v4l2_mbus_pixelcode *code) { if (index) diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index 6248a63..c2690df 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -1671,8 +1671,7 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf) PDEBUG(DBG_PROBE, ""); if (usbvision == NULL) { - dev_err(&usbvision->dev->dev, - "%s: usb_get_intfdata() failed\n", __func__); + pr_err("%s: usb_get_intfdata() failed\n", __func__); return; } |