From bddcf63313c6a4a85f94db092f45e31f530da691 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 20 Dec 2008 09:06:37 -0300 Subject: [PATCH] V4L/DVB (9927): em28xx: use a more standard way to specify video formats This patch uses the same code for enumberating video formats that are present on cx88, bttv and saa7134 drivers. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-core.c | 17 ++++-- drivers/media/video/em28xx/em28xx-video.c | 66 +++++++++++++++++------ drivers/media/video/em28xx/em28xx.h | 7 ++- 3 files changed, 69 insertions(+), 21 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index f515f8791251..c647dcb20a57 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -621,10 +621,19 @@ int em28xx_capture_start(struct em28xx *dev, int start) return rc; } -int em28xx_outfmt_set_yuv422(struct em28xx *dev) +int em28xx_set_outfmt(struct em28xx *dev) { - em28xx_write_reg(dev, EM28XX_R27_OUTFMT, 0x34); - em28xx_write_reg(dev, EM28XX_R10_VINMODE, 0x10); + int ret; + + ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT, + dev->format->reg | 0x20, 0x3f); + if (ret < 0) + return ret; + + ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, 0x10); + if (ret < 0) + return ret; + return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x11); } @@ -686,7 +695,7 @@ int em28xx_resolution_set(struct em28xx *dev) width = norm_maxw(dev); height = norm_maxh(dev) >> 1; - em28xx_outfmt_set_yuv422(dev); + em28xx_set_outfmt(dev); em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2); em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2); return em28xx_scaler_set(dev, dev->hscale, dev->vscale); diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 1b56e78b7744..dbae8bcb18d7 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -96,6 +96,16 @@ MODULE_PARM_DESC(video_debug, "enable debug messages [video]"); /* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */ static unsigned long em28xx_devused; +/* supported video standards */ +static struct em28xx_fmt format[] = { + { + .name = "16bpp YUY2, 4:2:2, packed", + .fourcc = V4L2_PIX_FMT_YUYV, + .depth = 16, + .reg = 0x14, + }, +}; + /* supported controls */ /* Common to all boards */ static struct v4l2_queryctrl em28xx_qctrl[] = { @@ -386,7 +396,8 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) struct em28xx *dev = fh->dev; struct v4l2_frequency f; - *size = 16 * fh->dev->width * fh->dev->height >> 3; + *size = (fh->dev->width * fh->dev->height * dev->format->depth + 7) >> 3; + if (0 == *count) *count = EM28XX_DEF_BUF; @@ -439,9 +450,7 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, struct em28xx *dev = fh->dev; int rc = 0, urb_init = 0; - /* FIXME: It assumes depth = 16 */ - /* The only currently supported format is 16 bits/pixel */ - buf->vb.size = 16 * dev->width * dev->height >> 3; + buf->vb.size = (fh->dev->width * fh->dev->height * dev->format->depth + 7) >> 3; if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) return -EINVAL; @@ -536,7 +545,7 @@ static int em28xx_config(struct em28xx *dev) dev->mute = 1; /* maybe not the right place... */ dev->volume = 0x1f; - em28xx_outfmt_set_yuv422(dev); + em28xx_set_outfmt(dev); em28xx_colorlevels_set_default(dev); em28xx_compression_disable(dev); @@ -704,8 +713,8 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.width = dev->width; f->fmt.pix.height = dev->height; - f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; - f->fmt.pix.bytesperline = dev->width * 2; + f->fmt.pix.pixelformat = dev->format->fourcc; + f->fmt.pix.bytesperline = (dev->width * dev->format->depth + 7) >> 3; f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * dev->height; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; @@ -717,6 +726,17 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, return 0; } +static struct em28xx_fmt *format_by_fourcc(unsigned int fourcc) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(format); i++) + if (format[i].fourcc == fourcc) + return &format[i]; + + return NULL; +} + static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { @@ -727,6 +747,14 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, unsigned int maxw = norm_maxw(dev); unsigned int maxh = norm_maxh(dev); unsigned int hscale, vscale; + struct em28xx_fmt *fmt; + + fmt = format_by_fourcc(f->fmt.pix.pixelformat); + if (!fmt) { + em28xx_videodbg("Fourcc format (%08x) invalid.\n", + f->fmt.pix.pixelformat); + return -EINVAL; + } /* width must even because of the YUYV format height must be even because of interlacing */ @@ -765,9 +793,9 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.width = width; f->fmt.pix.height = height; - f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; - f->fmt.pix.bytesperline = width * 2; - f->fmt.pix.sizeimage = width * 2 * height; + f->fmt.pix.pixelformat = fmt->fourcc; + f->fmt.pix.bytesperline = (dev->width * fmt->depth + 7) >> 3; + f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; f->fmt.pix.field = V4L2_FIELD_INTERLACED; @@ -780,6 +808,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; int rc; + struct em28xx_fmt *fmt; rc = check_dev(dev); if (rc < 0) @@ -789,6 +818,10 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, vidioc_try_fmt_vid_cap(file, priv, f); + fmt = format_by_fourcc(f->fmt.pix.pixelformat); + if (!fmt) + return -EINVAL; + if (videobuf_queue_is_busy(&fh->vb_vidq)) { em28xx_errdev("%s queue busy\n", __func__); rc = -EBUSY; @@ -804,6 +837,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, /* 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); @@ -1332,15 +1366,13 @@ static int vidioc_querycap(struct file *file, void *priv, } static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *fmtd) + struct v4l2_fmtdesc *f) { - if (fmtd->index != 0) + if (unlikely(f->index >= ARRAY_SIZE(format))) return -EINVAL; - fmtd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - strcpy(fmtd->description, "Packed YUY2"); - fmtd->pixelformat = V4L2_PIX_FMT_YUYV; - memset(fmtd->reserved, 0, sizeof(fmtd->reserved)); + strlcpy(f->description, format[f->index].name, sizeof(f->description)); + f->pixelformat = format[f->index].fourcc; return 0; } @@ -2075,6 +2107,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, dev->em28xx_write_regs_req = em28xx_write_regs_req; dev->em28xx_read_reg_req = em28xx_read_reg_req; dev->board.is_em2800 = em28xx_boards[dev->model].is_em2800; + dev->format = &format[0]; em28xx_pre_card_setup(dev); @@ -2482,3 +2515,4 @@ static void __exit em28xx_module_exit(void) module_init(em28xx_module_init); module_exit(em28xx_module_exit); + diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 54802d2d1bc5..80d1d55d80f9 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -209,9 +209,12 @@ struct em28xx_usb_isoc_ctl { }; +/* Struct to enumberate video formats */ struct em28xx_fmt { char *name; u32 fourcc; /* v4l2 format id */ + int depth; + int reg; }; /* buffer for one video frame */ @@ -430,6 +433,8 @@ struct em28xx { unsigned int has_audio_class:1; unsigned int has_alsa_audio:1; + struct em28xx_fmt *format; + struct em28xx_IR *ir; /* Some older em28xx chips needs a waiting time after writing */ @@ -564,7 +569,7 @@ int em28xx_audio_setup(struct em28xx *dev); int em28xx_colorlevels_set_default(struct em28xx *dev); int em28xx_capture_start(struct em28xx *dev, int start); -int em28xx_outfmt_set_yuv422(struct em28xx *dev); +int em28xx_set_outfmt(struct em28xx *dev); int em28xx_resolution_set(struct em28xx *dev); int em28xx_set_alternate(struct em28xx *dev); int em28xx_init_isoc(struct em28xx *dev, int max_packets, -- 2.39.5