From 331ffeac0127bface1146240b2b494272452d6bc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 30 Jun 2009 08:36:17 -0300 Subject: em28xx: add other video formats From: Mauro Carvalho Chehab Add suppport for the teste RGB565 format (16 bits/pixel). Currently, webcam support works only at RGB565, at 640x480. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-video.c | 58 ++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) (limited to 'linux/drivers/media/video/em28xx/em28xx-video.c') diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 63d21698c..b4dde89e9 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -94,6 +94,49 @@ static struct em28xx_fmt format[] = { .fourcc = V4L2_PIX_FMT_YUYV, .depth = 16, .reg = EM28XX_OUTFMT_YUV422_Y0UY1V, + }, { + .name = "16 bpp RGB, le", + .fourcc = V4L2_PIX_FMT_RGB565, + .depth = 16, + .reg = EM28XX_OUTFMT_YUV211, +#if 0 + /* TODO: need tests and newer definitions */ + }, { + .name = "Y1-U-Y0-V, 16 bpp", + .fourcc = 0, + .depth = 16, + .reg = EM28XX_OUTFMT_YUV422_Y1UY0V + }, { + .name = "YUV211, 8 bpp", + .fourcc = 0, + .depth = 8, + .reg = EM28XX_OUTFMT_YUV211, + }, { + .name = "YUV411, 12 bpp", + .fourcc = 0, + .depth = 12, + .reg = EM28XX_OUTFMT_YUV411, + }, { + .name = "RGB, 8bit RGRG", + .fourcc = 0, + .depth = 8, + .reg = EM28XX_OUTFMT_YUV211, + }, { + .name = "RGB, 8bit GRGR", + .fourcc = 0, + .depth = 8, + .reg = EM28XX_OUTFMT_YUV211, + }, { + .name = "RGB, 8bit GBGB", + .fourcc = 0, + .depth = 8, + .reg = EM28XX_OUTFMT_YUV211, + }, { + .name = "RGB, 8bit BGBG", + .fourcc = 0, + .depth = 8, + .reg = EM28XX_OUTFMT_RGB_8_BGBG, +#endif }, }; @@ -698,6 +741,10 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, unsigned int hscale, vscale; struct em28xx_fmt *fmt; + /* FIXME: This is the only supported fmt */ + if (dev->board.is_27xx) + f->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565; + fmt = format_by_fourcc(f->fmt.pix.pixelformat); if (!fmt) { em28xx_videodbg("Fourcc format (%08x) invalid.\n", @@ -705,7 +752,12 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, return -EINVAL; } - if (dev->board.is_em2800) { + if (dev->board.is_27xx) { + /* FIXME: This is the only supported fmt */ + width = 640; + height = 480; + V4L2_PIX_FMT_RGB565; + } else if (dev->board.is_em2800) { /* the em2800 can only scale down to 50% */ height = height > (3 * maxh / 4) ? maxh : maxh / 2; width = width > (3 * maxw / 4) ? maxw : maxw / 2; @@ -751,6 +803,10 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, mutex_lock(&dev->lock); + /* FIXME: This is the only supported fmt */ + if (dev->board.is_27xx) + f->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565; + vidioc_try_fmt_vid_cap(file, priv, f); fmt = format_by_fourcc(f->fmt.pix.pixelformat); -- cgit v1.2.3 From edefe5abbee82017b6f74ca42a1606f273da719d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 30 Jun 2009 12:45:16 -0300 Subject: Remove a bogus code From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-video.c | 1 - 1 file changed, 1 deletion(-) (limited to 'linux/drivers/media/video/em28xx/em28xx-video.c') diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index b4dde89e9..3c47acee3 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -756,7 +756,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, /* FIXME: This is the only supported fmt */ width = 640; height = 480; - V4L2_PIX_FMT_RGB565; } else if (dev->board.is_em2800) { /* the em2800 can only scale down to 50% */ height = height > (3 * maxh / 4) ? maxh : maxh / 2; -- cgit v1.2.3 From 0e9def6497f0f045e2740fa24b0864b260678959 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 2 Jul 2009 17:34:04 -0300 Subject: em28xx-video: fix VIDIOC_G_FMT and VIDIOC_ENUMFMT with webcams From: Mauro Carvalho Chehab Webcams have different constraints than other v4l devices. This patch makes the format ioctls to behave better. It also fixes a bug at open() handler, that were always reseting resolution to the maximum available one. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-video.c | 79 +++++++++++++++---------- 1 file changed, 49 insertions(+), 30 deletions(-) (limited to 'linux/drivers/media/video/em28xx/em28xx-video.c') diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 3c47acee3..157996e5f 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -788,13 +788,41 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, return 0; } +static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc, + unsigned width, unsigned height) +{ + struct em28xx_fmt *fmt; + + /* FIXME: This is the only supported fmt */ + if (dev->board.is_27xx) { + fourcc = V4L2_PIX_FMT_RGB565; + width = 640; + height = 480; + } + + fmt = format_by_fourcc(fourcc); + if (!fmt) + return -EINVAL; + + dev->format = fmt; + dev->width = width; + dev->height = height; + + /* set new image size */ + get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); + + em28xx_set_alternate(dev); + em28xx_resolution_set(dev); + + return 0; +} + static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; int rc; - struct em28xx_fmt *fmt; rc = check_dev(dev); if (rc < 0) @@ -802,18 +830,8 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, mutex_lock(&dev->lock); - /* FIXME: This is the only supported fmt */ - if (dev->board.is_27xx) - f->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565; - vidioc_try_fmt_vid_cap(file, priv, f); - fmt = format_by_fourcc(f->fmt.pix.pixelformat); - if (!fmt) { - rc = -EINVAL; - goto out; - } - if (videobuf_queue_is_busy(&fh->vb_vidq)) { em28xx_errdev("%s queue busy\n", __func__); rc = -EBUSY; @@ -826,16 +844,8 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, goto out; } - /* set new image size */ - dev->width = f->fmt.pix.width; - dev->height = f->fmt.pix.height; - dev->format = fmt; - get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); - - em28xx_set_alternate(dev); - em28xx_resolution_set(dev); - - rc = 0; + rc = em28xx_set_video_format(dev, f->fmt.pix.pixelformat, + f->fmt.pix.width, f->fmt.pix.height); out: mutex_unlock(&dev->lock); @@ -1428,9 +1438,24 @@ static int vidioc_querycap(struct file *file, void *priv, static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { + struct em28xx_fh *fh = priv; + struct em28xx *dev = fh->dev; + if (unlikely(f->index >= ARRAY_SIZE(format))) return -EINVAL; + if (dev->board.is_27xx) { + struct em28xx_fmt *fmt; + if (f->index) + return -EINVAL; + + f->pixelformat = V4L2_PIX_FMT_RGB565; + fmt = format_by_fourcc(f->pixelformat); + strlcpy(f->description, fmt->name, sizeof(f->description)); + + return 0; + } + strlcpy(f->description, format[f->index].name, sizeof(f->description)); f->pixelformat = format[f->index].fourcc; @@ -1726,11 +1751,6 @@ static int em28xx_v4l2_open(struct file *filp) filp->private_data = fh; if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { - dev->width = norm_maxw(dev); - dev->height = norm_maxh(dev); - dev->hscale = 0; - dev->vscale = 0; - em28xx_set_mode(dev, EM28XX_ANALOG_MODE); em28xx_set_alternate(dev); em28xx_resolution_set(dev); @@ -2084,15 +2104,14 @@ int em28xx_register_analog_devices(struct em28xx *dev) /* set default norm */ dev->norm = em28xx_video_template.current_norm; - dev->width = norm_maxw(dev); - dev->height = norm_maxh(dev); dev->interlaced = EM28XX_INTERLACED_DEFAULT; - dev->hscale = 0; - dev->vscale = 0; dev->ctl_input = 0; /* Analog specific initialization */ dev->format = &format[0]; + em28xx_set_video_format(dev, format[0].fourcc, + norm_maxw(dev), norm_maxh(dev)); + video_mux(dev, dev->ctl_input); /* Audio defaults */ -- cgit v1.2.3 From 5fd0c79afbb036e1e2147505dd8902716e8ed08a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 3 Jul 2009 02:54:18 -0300 Subject: em28xx: Allow its usage with other different output formats From: Mauro Carvalho Chehab Discovered the bug that were limiting the output format to just RGB565. Now, it is possible to output image at Bayer format (the original one, as generated by Silvercrest sensor, and two others), and also on YUY. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-video.c | 67 +++++++++---------------- 1 file changed, 25 insertions(+), 42 deletions(-) (limited to 'linux/drivers/media/video/em28xx/em28xx-video.c') diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 157996e5f..fff90faca 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -90,52 +90,52 @@ MODULE_PARM_DESC(video_debug, "enable debug messages [video]"); /* supported video standards */ static struct em28xx_fmt format[] = { { - .name = "16bpp YUY2, 4:2:2, packed", + .name = "16 bpp YUY2, 4:2:2, packed", .fourcc = V4L2_PIX_FMT_YUYV, .depth = 16, .reg = EM28XX_OUTFMT_YUV422_Y0UY1V, }, { - .name = "16 bpp RGB, le", + .name = "16 bpp RGB 565, LE", .fourcc = V4L2_PIX_FMT_RGB565, .depth = 16, - .reg = EM28XX_OUTFMT_YUV211, -#if 0 - /* TODO: need tests and newer definitions */ + .reg = EM28XX_OUTFMT_RGB_16_656, }, { - .name = "Y1-U-Y0-V, 16 bpp", - .fourcc = 0, - .depth = 16, - .reg = EM28XX_OUTFMT_YUV422_Y1UY0V + .name = "8 bpp Bayer BGBG..GRGR", + .fourcc = V4L2_PIX_FMT_SBGGR8, + .depth = 8, + .reg = EM28XX_OUTFMT_RGB_8_BGBG, }, { - .name = "YUV211, 8 bpp", - .fourcc = 0, + .name = "8 bpp Bayer GRGR..BGBG", + .fourcc = V4L2_PIX_FMT_SGRBG8, .depth = 8, - .reg = EM28XX_OUTFMT_YUV211, + .reg = EM28XX_OUTFMT_RGB_8_GRGR, }, { - .name = "YUV411, 12 bpp", - .fourcc = 0, + .name = "8 bpp Bayer GBGB..RGRG", + .fourcc = V4L2_PIX_FMT_SGBRG8, + .depth = 8, + .reg = EM28XX_OUTFMT_RGB_8_GBGB, + }, { + .name = "12 bpp YUV411", + .fourcc = V4L2_PIX_FMT_YUV411P, .depth = 12, .reg = EM28XX_OUTFMT_YUV411, +#if 0 + /* TODO: Those formats need test and fourcc entries */ }, { - .name = "RGB, 8bit RGRG", + .name = "Bayer, 8bit RGRG..GBGB", .fourcc = 0, .depth = 8, - .reg = EM28XX_OUTFMT_YUV211, + .reg = EM28XX_OUTFMT_RGB_8_GBGB, }, { - .name = "RGB, 8bit GRGR", + .name = "Y1-U-Y0-V, 16 bpp", .fourcc = 0, - .depth = 8, - .reg = EM28XX_OUTFMT_YUV211, + .depth = 16, + .reg = EM28XX_OUTFMT_YUV422_Y1UY0V }, { - .name = "RGB, 8bit GBGB", + .name = "YUV211, 8 bpp", .fourcc = 0, .depth = 8, .reg = EM28XX_OUTFMT_YUV211, - }, { - .name = "RGB, 8bit BGBG", - .fourcc = 0, - .depth = 8, - .reg = EM28XX_OUTFMT_RGB_8_BGBG, #endif }, }; @@ -741,10 +741,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, unsigned int hscale, vscale; struct em28xx_fmt *fmt; - /* FIXME: This is the only supported fmt */ - if (dev->board.is_27xx) - f->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565; - fmt = format_by_fourcc(f->fmt.pix.pixelformat); if (!fmt) { em28xx_videodbg("Fourcc format (%08x) invalid.\n", @@ -795,7 +791,6 @@ static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc, /* FIXME: This is the only supported fmt */ if (dev->board.is_27xx) { - fourcc = V4L2_PIX_FMT_RGB565; width = 640; height = 480; } @@ -1444,18 +1439,6 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, if (unlikely(f->index >= ARRAY_SIZE(format))) return -EINVAL; - if (dev->board.is_27xx) { - struct em28xx_fmt *fmt; - if (f->index) - return -EINVAL; - - f->pixelformat = V4L2_PIX_FMT_RGB565; - fmt = format_by_fourcc(f->pixelformat); - strlcpy(f->description, fmt->name, sizeof(f->description)); - - return 0; - } - strlcpy(f->description, format[f->index].name, sizeof(f->description)); f->pixelformat = format[f->index].fourcc; -- cgit v1.2.3