diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-07-24 16:19:39 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-07-24 16:19:39 -0300 |
commit | 2fd774d86f3c8fe4d2653967fbb2e292fe1ef581 (patch) | |
tree | 8ba8e2b482f16d305ca75211df2531f0cdcaa2ac /linux/drivers/media/video | |
parent | 54a9310128f01c9c97607d99f52ced91e050e834 (diff) | |
parent | d35fd05efa549e444999c3cc2260906c51b0d4b9 (diff) | |
download | mediapointer-dvb-s2-2fd774d86f3c8fe4d2653967fbb2e292fe1ef581.tar.gz mediapointer-dvb-s2-2fd774d86f3c8fe4d2653967fbb2e292fe1ef581.tar.bz2 |
merge: http://linuxtv.org/hg/~awalls/v4l-dvb
From: Mauro Carvalho Chehab <mchehab@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'linux/drivers/media/video')
-rw-r--r-- | linux/drivers/media/video/pxa_camera.c | 2 | ||||
-rw-r--r-- | linux/drivers/media/video/uvc/uvc_driver.c | 25 | ||||
-rw-r--r-- | linux/drivers/media/video/uvc/uvc_video.c | 3 | ||||
-rw-r--r-- | linux/drivers/media/video/uvc/uvcvideo.h | 1 | ||||
-rw-r--r-- | linux/drivers/media/video/zr364xx.c | 126 |
5 files changed, 114 insertions, 43 deletions
diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 8964d60cd..3f1b63e4e 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -1591,6 +1591,7 @@ static int __devinit pxa_camera_probe(struct platform_device *pdev) pcdev->mclk = 20000000; } + pcdev->soc_host.dev = &pdev->dev; pcdev->mclk_divisor = mclk_get_divisor(pcdev); INIT_LIST_HEAD(&pcdev->capture); @@ -1656,7 +1657,6 @@ static int __devinit pxa_camera_probe(struct platform_device *pdev) pcdev->soc_host.drv_name = PXA_CAM_DRV_NAME; pcdev->soc_host.ops = &pxa_soc_camera_host_ops; pcdev->soc_host.priv = pcdev; - pcdev->soc_host.dev = &pdev->dev; pcdev->soc_host.nr = pdev->id; err = soc_camera_host_register(&pcdev->soc_host); diff --git a/linux/drivers/media/video/uvc/uvc_driver.c b/linux/drivers/media/video/uvc/uvc_driver.c index f7b76884d..1d09751a3 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -1851,11 +1851,29 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_STREAM_NO_FID }, - /* ViMicro */ + /* ViMicro Vega */ { .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, .idVendor = 0x0ac8, - .idProduct = 0x0000, + .idProduct = 0x332d, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_FIX_BANDWIDTH }, + /* ViMicro - Minoru3D */ + { .match_flags = USB_DEVICE_ID_MATCH_VENDOR + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x0ac8, + .idProduct = 0x3410, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_FIX_BANDWIDTH }, + /* ViMicro Venus - Minoru3D */ + { .match_flags = USB_DEVICE_ID_MATCH_VENDOR + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x0ac8, + .idProduct = 0x3420, .bInterfaceClass = USB_CLASS_VIDEO, .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, @@ -1868,7 +1886,8 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceClass = USB_CLASS_VIDEO, .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_PROBE_MINMAX }, + .driver_info = UVC_QUIRK_PROBE_MINMAX + | UVC_QUIRK_PROBE_DEF }, /* Syntek (HP Spartan) */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, diff --git a/linux/drivers/media/video/uvc/uvc_video.c b/linux/drivers/media/video/uvc/uvc_video.c index c833e984e..f4f4e1bb3 100644 --- a/linux/drivers/media/video/uvc/uvc_video.c +++ b/linux/drivers/media/video/uvc/uvc_video.c @@ -128,6 +128,9 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video, if (data == NULL) return -ENOMEM; + if ((video->dev->quirks & UVC_QUIRK_PROBE_DEF) && query == UVC_GET_DEF) + return -EIO; + ret = __uvc_query_ctrl(video->dev, query, 0, video->streaming->intfnum, probe ? UVC_VS_PROBE_CONTROL : UVC_VS_COMMIT_CONTROL, data, size, UVC_CTRL_STREAMING_TIMEOUT); diff --git a/linux/drivers/media/video/uvc/uvcvideo.h b/linux/drivers/media/video/uvc/uvcvideo.h index 4887650c9..e700bdc20 100644 --- a/linux/drivers/media/video/uvc/uvcvideo.h +++ b/linux/drivers/media/video/uvc/uvcvideo.h @@ -157,6 +157,7 @@ struct uvc_xu_control { #define UVC_QUIRK_STREAM_NO_FID 0x00000010 #define UVC_QUIRK_IGNORE_SELECTOR_UNIT 0x00000020 #define UVC_QUIRK_FIX_BANDWIDTH 0x00000080 +#define UVC_QUIRK_PROBE_DEF 0x00000100 /* Format flags */ #define UVC_FMT_FLAG_COMPRESSED 0x00000001 diff --git a/linux/drivers/media/video/zr364xx.c b/linux/drivers/media/video/zr364xx.c index 084f97f6a..c298ce625 100644 --- a/linux/drivers/media/video/zr364xx.c +++ b/linux/drivers/media/video/zr364xx.c @@ -44,14 +44,14 @@ /* Version Information */ #define DRIVER_VERSION "v0.73" -#define ZR364_VERSION_CODE KERNEL_VERSION(0, 7, 3) +#define ZR364XX_VERSION_CODE KERNEL_VERSION(0, 7, 3) #define DRIVER_AUTHOR "Antoine Jacquet, http://royale.zerezo.com/" #define DRIVER_DESC "Zoran 364xx" /* Camera */ #define FRAMES 1 -#define MAX_FRAME_SIZE 100000 +#define MAX_FRAME_SIZE 200000 #define BUFFER_SIZE 0x1000 #define CTRL_TIMEOUT 500 @@ -67,6 +67,13 @@ } \ } while (0) +/*#define FULL_DEBUG 1*/ +#ifdef FULL_DEBUG +#define _DBG DBG +#else +#define _DBG(fmt, args...) +#endif + /* Init methods, need to find nicer names for these * the exact names of the chipsets would be the best if someone finds it */ #define METHOD0 0 @@ -376,7 +383,7 @@ static int buffer_setup(struct videobuf_queue *vq, unsigned int *count, static void free_buffer(struct videobuf_queue *vq, struct zr364xx_buffer *buf) { - DBG("%s\n", __func__); + _DBG("%s\n", __func__); if (in_interrupt()) BUG(); @@ -429,7 +436,7 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) vb); struct zr364xx_camera *cam = vq->priv_data; - DBG("%s\n", __func__); + _DBG("%s\n", __func__); buf->vb.state = VIDEOBUF_QUEUED; list_add_tail(&buf->vb.queue, &cam->vidq.active); @@ -441,7 +448,7 @@ static void buffer_release(struct videobuf_queue *vq, struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer, vb); - DBG("%s\n", __func__); + _DBG("%s\n", __func__); free_buffer(vq, buf); } @@ -463,7 +470,7 @@ static ssize_t zr364xx_read(struct file *file, char __user *buf, size_t count, { struct zr364xx_camera *cam = video_drvdata(file); - DBG("%s\n", __func__); + _DBG("%s\n", __func__); if (!buf) return -EINVAL; @@ -583,7 +590,7 @@ static int zr364xx_read_video_callback(struct zr364xx_camera *cam, int i = 0; unsigned char *ptr = NULL; - /*DBG("buffer to user\n");*/ + _DBG("buffer to user\n"); idx = cam->cur_frame; frm = &cam->buffer.frame[idx]; @@ -601,12 +608,6 @@ static int zr364xx_read_video_callback(struct zr364xx_camera *cam, return -EINVAL; } - if (frm->lpvbits == NULL) { - DBG("%s: frame buffer == NULL.%p %p %d\n", __func__, - frm, cam, idx); - return -ENOMEM; - } - psrc = (u8 *)pipe_info->transfer_buffer; ptr = pdest = frm->lpvbits; @@ -614,7 +615,7 @@ static int zr364xx_read_video_callback(struct zr364xx_camera *cam, frm->ulState = ZR364XX_READ_FRAME; frm->cur_size = 0; - DBG("jpeg header, "); + _DBG("jpeg header, "); memcpy(ptr, header1, sizeof(header1)); ptr += sizeof(header1); header3 = 0; @@ -632,21 +633,28 @@ static int zr364xx_read_video_callback(struct zr364xx_camera *cam, memcpy(ptr, psrc + 128, purb->actual_length - 128); ptr += purb->actual_length - 128; - DBG("header : %d %d %d %d %d %d %d %d %d\n", + _DBG("header : %d %d %d %d %d %d %d %d %d\n", psrc[0], psrc[1], psrc[2], psrc[3], psrc[4], psrc[5], psrc[6], psrc[7], psrc[8]); frm->cur_size = ptr - pdest; } else { - pdest += frm->cur_size; - memcpy(pdest, psrc, purb->actual_length); - frm->cur_size += purb->actual_length; + if (frm->cur_size + purb->actual_length > MAX_FRAME_SIZE) { + dev_info(&cam->udev->dev, + "%s: buffer (%d bytes) too small to hold " + "frame data. Discarding frame data.\n", + __func__, MAX_FRAME_SIZE); + } else { + pdest += frm->cur_size; + memcpy(pdest, psrc, purb->actual_length); + frm->cur_size += purb->actual_length; + } } - /*DBG("cur_size %lu urb size %d\n", frm->cur_size, + /*_DBG("cur_size %lu urb size %d\n", frm->cur_size, purb->actual_length);*/ if (purb->actual_length < pipe_info->transfer_size) { - DBG("****************Buffer[%d]full*************\n", idx); + _DBG("****************Buffer[%d]full*************\n", idx); cam->last_frame = cam->cur_frame; cam->cur_frame++; /* end of system frame ring buffer, start at zero */ @@ -681,7 +689,7 @@ static int zr364xx_read_video_callback(struct zr364xx_camera *cam, if (cam->skip) cam->skip--; else { - DBG("jpeg(%lu): %d %d %d %d %d %d %d %d\n", + _DBG("jpeg(%lu): %d %d %d %d %d %d %d %d\n", frm->cur_size, pdest[0], pdest[1], pdest[2], pdest[3], pdest[4], pdest[5], pdest[6], pdest[7]); @@ -708,7 +716,7 @@ static int res_get(struct zr364xx_camera *cam) } /* it's free, grab it */ cam->resources = 1; - DBG("res: get\n"); + _DBG("res: get\n"); mutex_unlock(&cam->lock); return 1; } @@ -723,7 +731,7 @@ static void res_free(struct zr364xx_camera *cam) mutex_lock(&cam->lock); cam->resources = 0; mutex_unlock(&cam->lock); - DBG("res: put\n"); + _DBG("res: put\n"); } static int zr364xx_vidioc_querycap(struct file *file, void *priv, @@ -735,7 +743,7 @@ static int zr364xx_vidioc_querycap(struct file *file, void *priv, strlcpy(cap->card, cam->udev->product, sizeof(cap->card)); strlcpy(cap->bus_info, dev_name(&cam->udev->dev), sizeof(cap->bus_info)); - cap->version = ZR364_VERSION_CODE; + cap->version = ZR364XX_VERSION_CODE; cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; @@ -875,9 +883,13 @@ static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv, return -EINVAL; } + if (!(f->fmt.pix.width == 160 && f->fmt.pix.height == 120) && + !(f->fmt.pix.width == 640 && f->fmt.pix.height == 480)) { + f->fmt.pix.width = 320; + f->fmt.pix.height = 240; + } + f->fmt.pix.field = V4L2_FIELD_NONE; - f->fmt.pix.width = cam->width; - f->fmt.pix.height = cam->height; f->fmt.pix.bytesperline = f->fmt.pix.width * 2; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; f->fmt.pix.colorspace = 0; @@ -908,7 +920,6 @@ static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv, return 0; } -/* Lamarque TODO: implement changing resolution on the fly */ static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { @@ -916,6 +927,7 @@ static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct videobuf_queue *q = &cam->vb_vidq; char pixelformat_name[5]; int ret = zr364xx_vidioc_try_fmt_vid_cap(file, cam, f); + int i; if (ret < 0) return ret; @@ -928,15 +940,55 @@ static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv, goto out; } - f->fmt.pix.field = V4L2_FIELD_NONE; - f->fmt.pix.width = cam->width; - f->fmt.pix.height = cam->height; + if (res_check(cam)) { + DBG("%s can't change format after started\n", __func__); + ret = -EBUSY; + goto out; + } + + cam->width = f->fmt.pix.width; + cam->height = f->fmt.pix.height; + dev_info(&cam->udev->dev, "%s: %dx%d mode selected\n", __func__, + cam->width, cam->height); f->fmt.pix.bytesperline = f->fmt.pix.width * 2; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; f->fmt.pix.colorspace = 0; f->fmt.pix.priv = 0; cam->vb_vidq.field = f->fmt.pix.field; cam->mode.color = V4L2_PIX_FMT_JPEG; + + if (f->fmt.pix.width == 160 && f->fmt.pix.height == 120) + mode = 1; + else if (f->fmt.pix.width == 640 && f->fmt.pix.height == 480) + mode = 2; + else + mode = 0; + + m0d1[0] = mode; + m1[2].value = 0xf000 + mode; + m2[1].value = 0xf000 + mode; + header2[437] = cam->height / 256; + header2[438] = cam->height % 256; + header2[439] = cam->width / 256; + header2[440] = cam->width % 256; + + for (i = 0; init[cam->method][i].size != -1; i++) { + ret = + send_control_msg(cam->udev, 1, init[cam->method][i].value, + 0, init[cam->method][i].bytes, + init[cam->method][i].size); + if (ret < 0) { + dev_err(&cam->udev->dev, + "error during resolution change sequence: %d\n", i); + goto out; + } + } + + /* Added some delay here, since opening/closing the camera quickly, + * like Ekiga does during its startup, can crash the webcam + */ + mdelay(100); + cam->skip = 2; ret = 0; out: @@ -973,7 +1025,7 @@ static int zr364xx_vidioc_qbuf(struct file *file, { int rc; struct zr364xx_camera *cam = video_drvdata(file); - DBG("%s\n", __func__); + _DBG("%s\n", __func__); rc = videobuf_qbuf(&cam->vb_vidq, p); return rc; } @@ -984,7 +1036,7 @@ static int zr364xx_vidioc_dqbuf(struct file *file, { int rc; struct zr364xx_camera *cam = video_drvdata(file); - DBG("%s\n", __func__); + _DBG("%s\n", __func__); rc = videobuf_dqbuf(&cam->vb_vidq, p, file->f_flags & O_NONBLOCK); return rc; } @@ -996,7 +1048,7 @@ static void read_pipe_completion(struct urb *purb) int pipe; pipe_info = purb->context; - /*DBG("%s %p, status %d\n", __func__, purb, purb->status);*/ + _DBG("%s %p, status %d\n", __func__, purb, purb->status); if (pipe_info == NULL) { printk(KERN_ERR KBUILD_MODNAME ": no context!\n"); return; @@ -1107,7 +1159,6 @@ static void zr364xx_stop_readpipe(struct zr364xx_camera *cam) pipe_info->stream_urb = NULL; } } - DBG("stop read pipe\n"); return; } @@ -1124,6 +1175,7 @@ static int zr364xx_start_acquire(struct zr364xx_camera *cam) cam->buffer.frame[j].ulState = ZR364XX_READ_IDLE; cam->buffer.frame[j].cur_size = 0; } + cam->b_acquire = 1; return 0; } @@ -1166,11 +1218,9 @@ static int zr364xx_vidioc_streamon(struct file *file, void *priv, res = videobuf_streamon(&cam->vb_vidq); if (res == 0) { zr364xx_start_acquire(cam); - cam->b_acquire = 1; } else { res_free(cam); } - DBG("%s: %d\n", __func__, res); return res; } @@ -1282,8 +1332,6 @@ static void zr364xx_destroy(struct zr364xx_camera *cam) /* release transfer buffer */ kfree(cam->pipe->transfer_buffer); cam->pipe->transfer_buffer = NULL; - - DBG("%s\n", __func__); mutex_unlock(&cam->open_lock); kfree(cam); cam = NULL; @@ -1364,7 +1412,7 @@ static unsigned int zr364xx_poll(struct file *file, { struct zr364xx_camera *cam = video_drvdata(file); struct videobuf_queue *q = &cam->vb_vidq; - DBG("%s\n", __func__); + _DBG("%s\n", __func__); if (cam->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return POLLERR; |