Skip to content

Commit bddcf63

Browse files
author
Mauro Carvalho Chehab
committed
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 <[email protected]>
1 parent 381aaba commit bddcf63

File tree

3 files changed

+69
-21
lines changed

3 files changed

+69
-21
lines changed

drivers/media/video/em28xx/em28xx-core.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -621,10 +621,19 @@ int em28xx_capture_start(struct em28xx *dev, int start)
621621
return rc;
622622
}
623623

624-
int em28xx_outfmt_set_yuv422(struct em28xx *dev)
624+
int em28xx_set_outfmt(struct em28xx *dev)
625625
{
626-
em28xx_write_reg(dev, EM28XX_R27_OUTFMT, 0x34);
627-
em28xx_write_reg(dev, EM28XX_R10_VINMODE, 0x10);
626+
int ret;
627+
628+
ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT,
629+
dev->format->reg | 0x20, 0x3f);
630+
if (ret < 0)
631+
return ret;
632+
633+
ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, 0x10);
634+
if (ret < 0)
635+
return ret;
636+
628637
return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x11);
629638
}
630639

@@ -686,7 +695,7 @@ int em28xx_resolution_set(struct em28xx *dev)
686695
width = norm_maxw(dev);
687696
height = norm_maxh(dev) >> 1;
688697

689-
em28xx_outfmt_set_yuv422(dev);
698+
em28xx_set_outfmt(dev);
690699
em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2);
691700
em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2);
692701
return em28xx_scaler_set(dev, dev->hscale, dev->vscale);

drivers/media/video/em28xx/em28xx-video.c

Lines changed: 50 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,16 @@ MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
9696
/* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */
9797
static unsigned long em28xx_devused;
9898

99+
/* supported video standards */
100+
static struct em28xx_fmt format[] = {
101+
{
102+
.name = "16bpp YUY2, 4:2:2, packed",
103+
.fourcc = V4L2_PIX_FMT_YUYV,
104+
.depth = 16,
105+
.reg = 0x14,
106+
},
107+
};
108+
99109
/* supported controls */
100110
/* Common to all boards */
101111
static struct v4l2_queryctrl em28xx_qctrl[] = {
@@ -386,7 +396,8 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
386396
struct em28xx *dev = fh->dev;
387397
struct v4l2_frequency f;
388398

389-
*size = 16 * fh->dev->width * fh->dev->height >> 3;
399+
*size = (fh->dev->width * fh->dev->height * dev->format->depth + 7) >> 3;
400+
390401
if (0 == *count)
391402
*count = EM28XX_DEF_BUF;
392403

@@ -439,9 +450,7 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
439450
struct em28xx *dev = fh->dev;
440451
int rc = 0, urb_init = 0;
441452

442-
/* FIXME: It assumes depth = 16 */
443-
/* The only currently supported format is 16 bits/pixel */
444-
buf->vb.size = 16 * dev->width * dev->height >> 3;
453+
buf->vb.size = (fh->dev->width * fh->dev->height * dev->format->depth + 7) >> 3;
445454

446455
if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
447456
return -EINVAL;
@@ -536,7 +545,7 @@ static int em28xx_config(struct em28xx *dev)
536545
dev->mute = 1; /* maybe not the right place... */
537546
dev->volume = 0x1f;
538547

539-
em28xx_outfmt_set_yuv422(dev);
548+
em28xx_set_outfmt(dev);
540549
em28xx_colorlevels_set_default(dev);
541550
em28xx_compression_disable(dev);
542551

@@ -704,8 +713,8 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
704713

705714
f->fmt.pix.width = dev->width;
706715
f->fmt.pix.height = dev->height;
707-
f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
708-
f->fmt.pix.bytesperline = dev->width * 2;
716+
f->fmt.pix.pixelformat = dev->format->fourcc;
717+
f->fmt.pix.bytesperline = (dev->width * dev->format->depth + 7) >> 3;
709718
f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * dev->height;
710719
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
711720

@@ -717,6 +726,17 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
717726
return 0;
718727
}
719728

729+
static struct em28xx_fmt *format_by_fourcc(unsigned int fourcc)
730+
{
731+
unsigned int i;
732+
733+
for (i = 0; i < ARRAY_SIZE(format); i++)
734+
if (format[i].fourcc == fourcc)
735+
return &format[i];
736+
737+
return NULL;
738+
}
739+
720740
static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
721741
struct v4l2_format *f)
722742
{
@@ -727,6 +747,14 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
727747
unsigned int maxw = norm_maxw(dev);
728748
unsigned int maxh = norm_maxh(dev);
729749
unsigned int hscale, vscale;
750+
struct em28xx_fmt *fmt;
751+
752+
fmt = format_by_fourcc(f->fmt.pix.pixelformat);
753+
if (!fmt) {
754+
em28xx_videodbg("Fourcc format (%08x) invalid.\n",
755+
f->fmt.pix.pixelformat);
756+
return -EINVAL;
757+
}
730758

731759
/* width must even because of the YUYV format
732760
height must be even because of interlacing */
@@ -765,9 +793,9 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
765793

766794
f->fmt.pix.width = width;
767795
f->fmt.pix.height = height;
768-
f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
769-
f->fmt.pix.bytesperline = width * 2;
770-
f->fmt.pix.sizeimage = width * 2 * height;
796+
f->fmt.pix.pixelformat = fmt->fourcc;
797+
f->fmt.pix.bytesperline = (dev->width * fmt->depth + 7) >> 3;
798+
f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height;
771799
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
772800
f->fmt.pix.field = V4L2_FIELD_INTERLACED;
773801

@@ -780,6 +808,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
780808
struct em28xx_fh *fh = priv;
781809
struct em28xx *dev = fh->dev;
782810
int rc;
811+
struct em28xx_fmt *fmt;
783812

784813
rc = check_dev(dev);
785814
if (rc < 0)
@@ -789,6 +818,10 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
789818

790819
vidioc_try_fmt_vid_cap(file, priv, f);
791820

821+
fmt = format_by_fourcc(f->fmt.pix.pixelformat);
822+
if (!fmt)
823+
return -EINVAL;
824+
792825
if (videobuf_queue_is_busy(&fh->vb_vidq)) {
793826
em28xx_errdev("%s queue busy\n", __func__);
794827
rc = -EBUSY;
@@ -804,6 +837,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
804837
/* set new image size */
805838
dev->width = f->fmt.pix.width;
806839
dev->height = f->fmt.pix.height;
840+
dev->format = fmt;
807841
get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
808842

809843
em28xx_set_alternate(dev);
@@ -1332,15 +1366,13 @@ static int vidioc_querycap(struct file *file, void *priv,
13321366
}
13331367

13341368
static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
1335-
struct v4l2_fmtdesc *fmtd)
1369+
struct v4l2_fmtdesc *f)
13361370
{
1337-
if (fmtd->index != 0)
1371+
if (unlikely(f->index >= ARRAY_SIZE(format)))
13381372
return -EINVAL;
13391373

1340-
fmtd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1341-
strcpy(fmtd->description, "Packed YUY2");
1342-
fmtd->pixelformat = V4L2_PIX_FMT_YUYV;
1343-
memset(fmtd->reserved, 0, sizeof(fmtd->reserved));
1374+
strlcpy(f->description, format[f->index].name, sizeof(f->description));
1375+
f->pixelformat = format[f->index].fourcc;
13441376

13451377
return 0;
13461378
}
@@ -2075,6 +2107,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
20752107
dev->em28xx_write_regs_req = em28xx_write_regs_req;
20762108
dev->em28xx_read_reg_req = em28xx_read_reg_req;
20772109
dev->board.is_em2800 = em28xx_boards[dev->model].is_em2800;
2110+
dev->format = &format[0];
20782111

20792112
em28xx_pre_card_setup(dev);
20802113

@@ -2482,3 +2515,4 @@ static void __exit em28xx_module_exit(void)
24822515

24832516
module_init(em28xx_module_init);
24842517
module_exit(em28xx_module_exit);
2518+

drivers/media/video/em28xx/em28xx.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,9 +209,12 @@ struct em28xx_usb_isoc_ctl {
209209

210210
};
211211

212+
/* Struct to enumberate video formats */
212213
struct em28xx_fmt {
213214
char *name;
214215
u32 fourcc; /* v4l2 format id */
216+
int depth;
217+
int reg;
215218
};
216219

217220
/* buffer for one video frame */
@@ -430,6 +433,8 @@ struct em28xx {
430433
unsigned int has_audio_class:1;
431434
unsigned int has_alsa_audio:1;
432435

436+
struct em28xx_fmt *format;
437+
433438
struct em28xx_IR *ir;
434439

435440
/* Some older em28xx chips needs a waiting time after writing */
@@ -564,7 +569,7 @@ int em28xx_audio_setup(struct em28xx *dev);
564569

565570
int em28xx_colorlevels_set_default(struct em28xx *dev);
566571
int em28xx_capture_start(struct em28xx *dev, int start);
567-
int em28xx_outfmt_set_yuv422(struct em28xx *dev);
572+
int em28xx_set_outfmt(struct em28xx *dev);
568573
int em28xx_resolution_set(struct em28xx *dev);
569574
int em28xx_set_alternate(struct em28xx *dev);
570575
int em28xx_init_isoc(struct em28xx *dev, int max_packets,

0 commit comments

Comments
 (0)