1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Zoran zr36057/zr36067 PCI controller driver, for the
4 * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
5 * Media Labs LML33/LML33R10.
7 * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
9 * Changes for BUZ by Wolfgang Scherr <scherr@net4you.net>
11 * Changes for DC10/DC30 by Laurent Pinchart <laurent.pinchart@skynet.be>
13 * Changes for LML33R10 by Maxim Yevtyushkin <max@linuxmedialabs.com>
15 * Changes for videodev2/v4l2 by Ronald Bultje <rbultje@ronald.bitfreak.net>
20 * Copyright (C) 1999 Wolfgang Scherr <scherr@net4you.net>
22 * Iomega Buz driver version 1.0
23 * Copyright (C) 1999 Rainer Johanni <Rainer@Johanni.de>
26 * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
28 * bttv - Bt848 frame grabber driver
29 * Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de)
30 * & Marcus Metzler (mocm@thp.uni-koeln.de)
33 #include <linux/init.h>
34 #include <linux/module.h>
35 #include <linux/delay.h>
36 #include <linux/slab.h>
37 #include <linux/pci.h>
38 #include <linux/wait.h>
40 #include <linux/interrupt.h>
41 #include <linux/i2c.h>
42 #include <linux/i2c-algo-bit.h>
44 #include <linux/spinlock.h>
46 #include <linux/videodev2.h>
47 #include <media/v4l2-common.h>
48 #include <media/v4l2-ioctl.h>
49 #include <media/v4l2-event.h>
50 #include "videocodec.h"
53 #include <linux/uaccess.h>
55 #include <linux/mutex.h>
57 #include "zoran_device.h"
58 #include "zoran_card.h"
60 const struct zoran_format zoran_formats[] = {
62 .name = "15-bit RGB LE",
63 .fourcc = V4L2_PIX_FMT_RGB555,
64 .colorspace = V4L2_COLORSPACE_SRGB,
66 .flags = ZORAN_FORMAT_CAPTURE,
67 .vfespfr = ZR36057_VFESPFR_RGB555 | ZR36057_VFESPFR_ERR_DIF |
68 ZR36057_VFESPFR_LITTLE_ENDIAN,
70 .name = "15-bit RGB BE",
71 .fourcc = V4L2_PIX_FMT_RGB555X,
72 .colorspace = V4L2_COLORSPACE_SRGB,
74 .flags = ZORAN_FORMAT_CAPTURE,
75 .vfespfr = ZR36057_VFESPFR_RGB555 | ZR36057_VFESPFR_ERR_DIF,
77 .name = "16-bit RGB LE",
78 .fourcc = V4L2_PIX_FMT_RGB565,
79 .colorspace = V4L2_COLORSPACE_SRGB,
81 .flags = ZORAN_FORMAT_CAPTURE,
82 .vfespfr = ZR36057_VFESPFR_RGB565 | ZR36057_VFESPFR_ERR_DIF |
83 ZR36057_VFESPFR_LITTLE_ENDIAN,
85 .name = "16-bit RGB BE",
86 .fourcc = V4L2_PIX_FMT_RGB565X,
87 .colorspace = V4L2_COLORSPACE_SRGB,
89 .flags = ZORAN_FORMAT_CAPTURE,
90 .vfespfr = ZR36057_VFESPFR_RGB565 | ZR36057_VFESPFR_ERR_DIF,
93 .fourcc = V4L2_PIX_FMT_BGR24,
94 .colorspace = V4L2_COLORSPACE_SRGB,
96 .flags = ZORAN_FORMAT_CAPTURE,
97 .vfespfr = ZR36057_VFESPFR_RGB888 | ZR36057_VFESPFR_PACK24,
99 .name = "32-bit RGB LE",
100 .fourcc = V4L2_PIX_FMT_BGR32,
101 .colorspace = V4L2_COLORSPACE_SRGB,
103 .flags = ZORAN_FORMAT_CAPTURE,
104 .vfespfr = ZR36057_VFESPFR_RGB888 | ZR36057_VFESPFR_LITTLE_ENDIAN,
106 .name = "32-bit RGB BE",
107 .fourcc = V4L2_PIX_FMT_RGB32,
108 .colorspace = V4L2_COLORSPACE_SRGB,
110 .flags = ZORAN_FORMAT_CAPTURE,
111 .vfespfr = ZR36057_VFESPFR_RGB888,
113 .name = "4:2:2, packed, YUYV",
114 .fourcc = V4L2_PIX_FMT_YUYV,
115 .colorspace = V4L2_COLORSPACE_SMPTE170M,
117 .flags = ZORAN_FORMAT_CAPTURE,
118 .vfespfr = ZR36057_VFESPFR_YUV422,
120 .name = "4:2:2, packed, UYVY",
121 .fourcc = V4L2_PIX_FMT_UYVY,
122 .colorspace = V4L2_COLORSPACE_SMPTE170M,
124 .flags = ZORAN_FORMAT_CAPTURE,
125 .vfespfr = ZR36057_VFESPFR_YUV422 | ZR36057_VFESPFR_LITTLE_ENDIAN,
127 .name = "Hardware-encoded Motion-JPEG",
128 .fourcc = V4L2_PIX_FMT_MJPEG,
129 .colorspace = V4L2_COLORSPACE_SMPTE170M,
131 .flags = ZORAN_FORMAT_CAPTURE |
132 ZORAN_FORMAT_PLAYBACK |
133 ZORAN_FORMAT_COMPRESSED,
137 #define NUM_FORMATS ARRAY_SIZE(zoran_formats)
140 * small helper function for calculating buffersizes for v4l2
141 * we calculate the nearest higher power-of-two, which
142 * will be the recommended buffersize
144 static __u32 zoran_v4l2_calc_bufsize(struct zoran_jpg_settings *settings)
146 __u8 div = settings->ver_dcm * settings->hor_dcm * settings->tmp_dcm;
147 __u32 num = (1024 * 512) / (div);
163 * V4L Buffer grabbing
165 static int zoran_v4l_set_format(struct zoran *zr, int width, int height,
166 const struct zoran_format *format)
170 /* Check size and format of the grab wanted */
172 if (height < BUZ_MIN_HEIGHT || width < BUZ_MIN_WIDTH ||
173 height > BUZ_MAX_HEIGHT || width > BUZ_MAX_WIDTH) {
174 pci_dbg(zr->pci_dev, "%s - wrong frame size (%dx%d)\n", __func__, width, height);
178 bpp = (format->depth + 7) / 8;
180 zr->buffer_size = height * width * bpp;
182 /* Check against available buffer size */
183 if (height * width * bpp > zr->buffer_size) {
184 pci_dbg(zr->pci_dev, "%s - video buffer size (%d kB) is too small\n",
185 __func__, zr->buffer_size >> 10);
189 /* The video front end needs 4-byte alinged line sizes */
191 if ((bpp == 2 && (width & 1)) || (bpp == 3 && (width & 3))) {
192 pci_dbg(zr->pci_dev, "%s - wrong frame alignment\n", __func__);
196 zr->v4l_settings.width = width;
197 zr->v4l_settings.height = height;
198 zr->v4l_settings.format = format;
199 zr->v4l_settings.bytesperline = bpp * zr->v4l_settings.width;
204 static int zoran_set_norm(struct zoran *zr, v4l2_std_id norm)
207 if (!(norm & zr->card.norms)) {
208 pci_dbg(zr->pci_dev, "%s - unsupported norm %llx\n", __func__, norm);
212 if (norm & V4L2_STD_SECAM)
213 zr->timing = zr->card.tvn[ZR_NORM_SECAM];
214 else if (norm & V4L2_STD_NTSC)
215 zr->timing = zr->card.tvn[ZR_NORM_NTSC];
217 zr->timing = zr->card.tvn[ZR_NORM_PAL];
219 decoder_call(zr, video, s_std, norm);
220 encoder_call(zr, video, s_std_output, norm);
222 /* Make sure the changes come into effect */
228 static int zoran_set_input(struct zoran *zr, int input)
230 if (input == zr->input)
233 if (input < 0 || input >= zr->card.inputs) {
234 pci_dbg(zr->pci_dev, "%s - unsupported input %d\n", __func__, input);
240 decoder_call(zr, video, s_routing, zr->card.input[input].muxsel, 0, 0);
249 static int zoran_querycap(struct file *file, void *__fh, struct v4l2_capability *cap)
251 struct zoran *zr = video_drvdata(file);
253 strscpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card));
254 strscpy(cap->driver, "zoran", sizeof(cap->driver));
255 snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", pci_name(zr->pci_dev));
259 static int zoran_enum_fmt(struct zoran *zr, struct v4l2_fmtdesc *fmt, int flag)
263 if (fmt->index >= ARRAY_SIZE(zoran_formats))
265 if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
268 for (num = i = 0; i < NUM_FORMATS; i++) {
269 if (zoran_formats[i].flags & flag && num++ == fmt->index) {
270 strscpy(fmt->description, zoran_formats[i].name,
271 sizeof(fmt->description));
272 /* fmt struct pre-zeroed, so adding '\0' not needed */
273 fmt->pixelformat = zoran_formats[i].fourcc;
274 if (zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED)
275 fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
282 static int zoran_enum_fmt_vid_cap(struct file *file, void *__fh,
283 struct v4l2_fmtdesc *f)
285 struct zoran *zr = video_drvdata(file);
287 return zoran_enum_fmt(zr, f, ZORAN_FORMAT_CAPTURE);
291 /* TODO: output does not work yet */
292 static int zoran_enum_fmt_vid_out(struct file *file, void *__fh,
293 struct v4l2_fmtdesc *f)
295 struct zoran *zr = video_drvdata(file);
297 return zoran_enum_fmt(zr, f, ZORAN_FORMAT_PLAYBACK);
301 static int zoran_g_fmt_vid_out(struct file *file, void *__fh,
302 struct v4l2_format *fmt)
304 struct zoran *zr = video_drvdata(file);
306 fmt->fmt.pix.width = zr->jpg_settings.img_width / zr->jpg_settings.hor_dcm;
307 fmt->fmt.pix.height = zr->jpg_settings.img_height * 2 /
308 (zr->jpg_settings.ver_dcm * zr->jpg_settings.tmp_dcm);
309 fmt->fmt.pix.sizeimage = zr->buffer_size;
310 fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
311 if (zr->jpg_settings.tmp_dcm == 1)
312 fmt->fmt.pix.field = (zr->jpg_settings.odd_even ?
313 V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT);
315 fmt->fmt.pix.field = (zr->jpg_settings.odd_even ?
316 V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM);
317 fmt->fmt.pix.bytesperline = 0;
318 fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
323 static int zoran_g_fmt_vid_cap(struct file *file, void *__fh,
324 struct v4l2_format *fmt)
326 struct zoran *zr = video_drvdata(file);
328 if (zr->map_mode != ZORAN_MAP_MODE_RAW)
329 return zoran_g_fmt_vid_out(file, __fh, fmt);
330 fmt->fmt.pix.width = zr->v4l_settings.width;
331 fmt->fmt.pix.height = zr->v4l_settings.height;
332 fmt->fmt.pix.sizeimage = zr->buffer_size;
333 fmt->fmt.pix.pixelformat = zr->v4l_settings.format->fourcc;
334 fmt->fmt.pix.colorspace = zr->v4l_settings.format->colorspace;
335 fmt->fmt.pix.bytesperline = zr->v4l_settings.bytesperline;
336 if (BUZ_MAX_HEIGHT < (zr->v4l_settings.height * 2))
337 fmt->fmt.pix.field = V4L2_FIELD_INTERLACED;
339 fmt->fmt.pix.field = V4L2_FIELD_TOP;
343 static int zoran_try_fmt_vid_out(struct file *file, void *__fh,
344 struct v4l2_format *fmt)
346 struct zoran *zr = video_drvdata(file);
347 struct zoran_jpg_settings settings;
350 if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
353 settings = zr->jpg_settings;
355 /* we actually need to set 'real' parameters now */
356 if ((fmt->fmt.pix.height * 2) > BUZ_MAX_HEIGHT)
357 settings.tmp_dcm = 1;
359 settings.tmp_dcm = 2;
360 settings.decimation = 0;
361 if (fmt->fmt.pix.height <= zr->jpg_settings.img_height / 2)
362 settings.ver_dcm = 2;
364 settings.ver_dcm = 1;
365 if (fmt->fmt.pix.width <= zr->jpg_settings.img_width / 4)
366 settings.hor_dcm = 4;
367 else if (fmt->fmt.pix.width <= zr->jpg_settings.img_width / 2)
368 settings.hor_dcm = 2;
370 settings.hor_dcm = 1;
371 if (settings.tmp_dcm == 1)
372 settings.field_per_buff = 2;
374 settings.field_per_buff = 1;
376 if (settings.hor_dcm > 1) {
377 settings.img_x = (BUZ_MAX_WIDTH == 720) ? 8 : 0;
378 settings.img_width = (BUZ_MAX_WIDTH == 720) ? 704 : BUZ_MAX_WIDTH;
381 settings.img_width = BUZ_MAX_WIDTH;
385 res = zoran_check_jpg_settings(zr, &settings, 1);
389 /* tell the user what we actually did */
390 fmt->fmt.pix.width = settings.img_width / settings.hor_dcm;
391 fmt->fmt.pix.height = settings.img_height * 2 /
392 (settings.tmp_dcm * settings.ver_dcm);
393 if (settings.tmp_dcm == 1)
394 fmt->fmt.pix.field = (zr->jpg_settings.odd_even ?
395 V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT);
397 fmt->fmt.pix.field = (zr->jpg_settings.odd_even ?
398 V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM);
400 fmt->fmt.pix.sizeimage = zoran_v4l2_calc_bufsize(&settings);
401 fmt->fmt.pix.bytesperline = 0;
402 fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
406 static int zoran_try_fmt_vid_cap(struct file *file, void *__fh,
407 struct v4l2_format *fmt)
409 struct zoran *zr = video_drvdata(file);
413 if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG)
414 return zoran_try_fmt_vid_out(file, __fh, fmt);
416 for (i = 0; i < NUM_FORMATS; i++)
417 if (zoran_formats[i].fourcc == fmt->fmt.pix.pixelformat)
420 if (i == NUM_FORMATS) {
421 /* TODO do not return here to fix the TRY_FMT cannot handle an invalid pixelformat*/
425 fmt->fmt.pix.pixelformat = zoran_formats[i].fourcc;
426 fmt->fmt.pix.colorspace = zoran_formats[i].colorspace;
427 if (BUZ_MAX_HEIGHT < (fmt->fmt.pix.height * 2))
428 fmt->fmt.pix.field = V4L2_FIELD_INTERLACED;
430 fmt->fmt.pix.field = V4L2_FIELD_TOP;
432 bpp = DIV_ROUND_UP(zoran_formats[i].depth, 8);
433 v4l_bound_align_image(&fmt->fmt.pix.width, BUZ_MIN_WIDTH, BUZ_MAX_WIDTH, bpp == 2 ? 1 : 2,
434 &fmt->fmt.pix.height, BUZ_MIN_HEIGHT, BUZ_MAX_HEIGHT, 0, 0);
435 fmt->fmt.pix.bytesperline = fmt->fmt.pix.width * bpp;
436 fmt->fmt.pix.sizeimage = fmt->fmt.pix.bytesperline * fmt->fmt.pix.height;
440 static int zoran_s_fmt_vid_out(struct file *file, void *__fh,
441 struct v4l2_format *fmt)
443 struct zoran *zr = video_drvdata(file);
444 __le32 printformat = __cpu_to_le32(fmt->fmt.pix.pixelformat);
445 struct zoran_jpg_settings settings;
448 pci_dbg(zr->pci_dev, "size=%dx%d, fmt=0x%x (%4.4s)\n",
449 fmt->fmt.pix.width, fmt->fmt.pix.height,
450 fmt->fmt.pix.pixelformat,
451 (char *)&printformat);
452 if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
455 if (!fmt->fmt.pix.height || !fmt->fmt.pix.width)
458 settings = zr->jpg_settings;
460 /* we actually need to set 'real' parameters now */
461 if (fmt->fmt.pix.height * 2 > BUZ_MAX_HEIGHT)
462 settings.tmp_dcm = 1;
464 settings.tmp_dcm = 2;
465 settings.decimation = 0;
466 if (fmt->fmt.pix.height <= zr->jpg_settings.img_height / 2)
467 settings.ver_dcm = 2;
469 settings.ver_dcm = 1;
470 if (fmt->fmt.pix.width <= zr->jpg_settings.img_width / 4)
471 settings.hor_dcm = 4;
472 else if (fmt->fmt.pix.width <= zr->jpg_settings.img_width / 2)
473 settings.hor_dcm = 2;
475 settings.hor_dcm = 1;
476 if (settings.tmp_dcm == 1)
477 settings.field_per_buff = 2;
479 settings.field_per_buff = 1;
481 if (settings.hor_dcm > 1) {
482 settings.img_x = (BUZ_MAX_WIDTH == 720) ? 8 : 0;
483 settings.img_width = (BUZ_MAX_WIDTH == 720) ? 704 : BUZ_MAX_WIDTH;
486 settings.img_width = BUZ_MAX_WIDTH;
490 res = zoran_check_jpg_settings(zr, &settings, 0);
494 /* it's ok, so set them */
495 zr->jpg_settings = settings;
497 if (fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
498 zr->map_mode = ZORAN_MAP_MODE_JPG_REC;
500 zr->map_mode = ZORAN_MAP_MODE_JPG_PLAY;
502 zr->buffer_size = zoran_v4l2_calc_bufsize(&zr->jpg_settings);
504 /* tell the user what we actually did */
505 fmt->fmt.pix.width = settings.img_width / settings.hor_dcm;
506 fmt->fmt.pix.height = settings.img_height * 2 /
507 (settings.tmp_dcm * settings.ver_dcm);
508 if (settings.tmp_dcm == 1)
509 fmt->fmt.pix.field = (zr->jpg_settings.odd_even ?
510 V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT);
512 fmt->fmt.pix.field = (zr->jpg_settings.odd_even ?
513 V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM);
514 fmt->fmt.pix.bytesperline = 0;
515 fmt->fmt.pix.sizeimage = zr->buffer_size;
516 fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
520 static int zoran_s_fmt_vid_cap(struct file *file, void *__fh,
521 struct v4l2_format *fmt)
523 struct zoran *zr = video_drvdata(file);
524 struct zoran_fh *fh = __fh;
528 if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG)
529 return zoran_s_fmt_vid_out(file, fh, fmt);
531 for (i = 0; i < NUM_FORMATS; i++)
532 if (fmt->fmt.pix.pixelformat == zoran_formats[i].fourcc)
534 if (i == NUM_FORMATS) {
535 pci_dbg(zr->pci_dev, "VIDIOC_S_FMT - unknown/unsupported format 0x%x\n",
536 fmt->fmt.pix.pixelformat);
537 /* TODO do not return here to fix the TRY_FMT cannot handle an invalid pixelformat*/
541 fmt->fmt.pix.pixelformat = zoran_formats[i].fourcc;
542 if (fmt->fmt.pix.height > BUZ_MAX_HEIGHT)
543 fmt->fmt.pix.height = BUZ_MAX_HEIGHT;
544 if (fmt->fmt.pix.width > BUZ_MAX_WIDTH)
545 fmt->fmt.pix.width = BUZ_MAX_WIDTH;
546 if (fmt->fmt.pix.height < BUZ_MIN_HEIGHT)
547 fmt->fmt.pix.height = BUZ_MIN_HEIGHT;
548 if (fmt->fmt.pix.width < BUZ_MIN_WIDTH)
549 fmt->fmt.pix.width = BUZ_MIN_WIDTH;
551 zr->map_mode = ZORAN_MAP_MODE_RAW;
553 res = zoran_v4l_set_format(zr, fmt->fmt.pix.width, fmt->fmt.pix.height,
558 /* tell the user the results/missing stuff */
559 fmt->fmt.pix.bytesperline = zr->v4l_settings.bytesperline;
560 fmt->fmt.pix.sizeimage = zr->buffer_size;
561 fmt->fmt.pix.colorspace = zr->v4l_settings.format->colorspace;
562 if (BUZ_MAX_HEIGHT < (zr->v4l_settings.height * 2))
563 fmt->fmt.pix.field = V4L2_FIELD_INTERLACED;
565 fmt->fmt.pix.field = V4L2_FIELD_TOP;
569 static int zoran_g_std(struct file *file, void *__fh, v4l2_std_id *std)
571 struct zoran *zr = video_drvdata(file);
577 static int zoran_s_std(struct file *file, void *__fh, v4l2_std_id std)
579 struct zoran *zr = video_drvdata(file);
585 if (zr->running != ZORAN_MAP_MODE_NONE)
588 res = zoran_set_norm(zr, std);
592 static int zoran_enum_input(struct file *file, void *__fh,
593 struct v4l2_input *inp)
595 struct zoran *zr = video_drvdata(file);
597 if (inp->index >= zr->card.inputs)
600 strscpy(inp->name, zr->card.input[inp->index].name, sizeof(inp->name));
601 inp->type = V4L2_INPUT_TYPE_CAMERA;
602 inp->std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM;
604 /* Get status of video decoder */
605 decoder_call(zr, video, g_input_status, &inp->status);
609 static int zoran_g_input(struct file *file, void *__fh, unsigned int *input)
611 struct zoran *zr = video_drvdata(file);
618 static int zoran_s_input(struct file *file, void *__fh, unsigned int input)
620 struct zoran *zr = video_drvdata(file);
623 if (zr->running != ZORAN_MAP_MODE_NONE)
626 res = zoran_set_input(zr, input);
631 /* TODO: output does not work yet */
632 static int zoran_enum_output(struct file *file, void *__fh,
633 struct v4l2_output *outp)
635 if (outp->index != 0)
639 outp->type = V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY;
640 outp->std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM;
641 outp->capabilities = V4L2_OUT_CAP_STD;
642 strscpy(outp->name, "Autodetect", sizeof(outp->name));
646 static int zoran_g_output(struct file *file, void *__fh, unsigned int *output)
653 static int zoran_s_output(struct file *file, void *__fh, unsigned int output)
662 /* cropping (sub-frame capture) */
663 static int zoran_g_selection(struct file *file, void *__fh, struct v4l2_selection *sel)
665 struct zoran *zr = video_drvdata(file);
667 if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
668 sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
669 pci_dbg(zr->pci_dev, "%s invalid selection type combination\n", __func__);
673 switch (sel->target) {
674 case V4L2_SEL_TGT_CROP:
675 sel->r.top = zr->jpg_settings.img_y;
676 sel->r.left = zr->jpg_settings.img_x;
677 sel->r.width = zr->jpg_settings.img_width;
678 sel->r.height = zr->jpg_settings.img_height;
680 case V4L2_SEL_TGT_CROP_DEFAULT:
683 sel->r.width = BUZ_MIN_WIDTH;
684 sel->r.height = BUZ_MIN_HEIGHT;
686 case V4L2_SEL_TGT_CROP_BOUNDS:
689 sel->r.width = BUZ_MAX_WIDTH;
690 sel->r.height = BUZ_MAX_HEIGHT;
698 static int zoran_s_selection(struct file *file, void *__fh, struct v4l2_selection *sel)
700 struct zoran *zr = video_drvdata(file);
701 struct zoran_jpg_settings settings;
704 if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
705 sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
708 if (!sel->r.width || !sel->r.height)
711 if (sel->target != V4L2_SEL_TGT_CROP)
714 if (zr->map_mode == ZORAN_MAP_MODE_RAW) {
715 pci_dbg(zr->pci_dev, "VIDIOC_S_SELECTION - subcapture only supported for compressed capture\n");
719 settings = zr->jpg_settings;
721 /* move into a form that we understand */
722 settings.img_x = sel->r.left;
723 settings.img_y = sel->r.top;
724 settings.img_width = sel->r.width;
725 settings.img_height = sel->r.height;
728 res = zoran_check_jpg_settings(zr, &settings, 0);
733 zr->jpg_settings = settings;
738 * Output is disabled temporarily
739 * Zoran is picky about jpeg data it accepts. At least it seems to unsupport COM and APPn.
740 * So until a way to filter data will be done, disable output.
742 static const struct v4l2_ioctl_ops zoran_ioctl_ops = {
743 .vidioc_querycap = zoran_querycap,
744 .vidioc_s_selection = zoran_s_selection,
745 .vidioc_g_selection = zoran_g_selection,
746 .vidioc_enum_input = zoran_enum_input,
747 .vidioc_g_input = zoran_g_input,
748 .vidioc_s_input = zoran_s_input,
749 /* .vidioc_enum_output = zoran_enum_output,
750 .vidioc_g_output = zoran_g_output,
751 .vidioc_s_output = zoran_s_output,*/
752 .vidioc_g_std = zoran_g_std,
753 .vidioc_s_std = zoran_s_std,
754 .vidioc_create_bufs = vb2_ioctl_create_bufs,
755 .vidioc_reqbufs = vb2_ioctl_reqbufs,
756 .vidioc_querybuf = vb2_ioctl_querybuf,
757 .vidioc_qbuf = vb2_ioctl_qbuf,
758 .vidioc_dqbuf = vb2_ioctl_dqbuf,
759 .vidioc_expbuf = vb2_ioctl_expbuf,
760 .vidioc_streamon = vb2_ioctl_streamon,
761 .vidioc_streamoff = vb2_ioctl_streamoff,
762 .vidioc_enum_fmt_vid_cap = zoran_enum_fmt_vid_cap,
763 /* .vidioc_enum_fmt_vid_out = zoran_enum_fmt_vid_out,*/
764 .vidioc_g_fmt_vid_cap = zoran_g_fmt_vid_cap,
765 /* .vidioc_g_fmt_vid_out = zoran_g_fmt_vid_out,*/
766 .vidioc_s_fmt_vid_cap = zoran_s_fmt_vid_cap,
767 /* .vidioc_s_fmt_vid_out = zoran_s_fmt_vid_out,*/
768 .vidioc_try_fmt_vid_cap = zoran_try_fmt_vid_cap,
769 /* .vidioc_try_fmt_vid_out = zoran_try_fmt_vid_out,*/
770 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
771 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
774 static const struct v4l2_file_operations zoran_fops = {
775 .owner = THIS_MODULE,
776 .unlocked_ioctl = video_ioctl2,
777 .open = v4l2_fh_open,
778 .release = vb2_fop_release,
779 .mmap = vb2_fop_mmap,
780 .poll = vb2_fop_poll,
783 const struct video_device zoran_template = {
786 .ioctl_ops = &zoran_ioctl_ops,
787 .release = &zoran_vdev_release,
788 .tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
791 static int zr_vb2_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes,
792 unsigned int sizes[], struct device *alloc_devs[])
794 struct zoran *zr = vb2_get_drv_priv(vq);
795 unsigned int size = zr->buffer_size;
797 pci_dbg(zr->pci_dev, "%s nbuf=%u nplanes=%u", __func__, *nbuffers, *nplanes);
799 zr->buf_in_reserve = 0;
801 if (*nbuffers < vq->min_buffers_needed)
802 *nbuffers = vq->min_buffers_needed;
817 static void zr_vb2_queue(struct vb2_buffer *vb)
819 struct zoran *zr = vb2_get_drv_priv(vb->vb2_queue);
820 struct zr_buffer *buf = vb2_to_zr_buffer(vb);
823 spin_lock_irqsave(&zr->queued_bufs_lock, flags);
824 list_add_tail(&buf->queue, &zr->queued_bufs);
825 zr->buf_in_reserve++;
826 spin_unlock_irqrestore(&zr->queued_bufs_lock, flags);
827 if (zr->running == ZORAN_MAP_MODE_JPG_REC)
828 zoran_feed_stat_com(zr);
832 static int zr_vb2_prepare(struct vb2_buffer *vb)
834 struct zoran *zr = vb2_get_drv_priv(vb->vb2_queue);
836 if (vb2_plane_size(vb, 0) < zr->buffer_size)
843 int zr_set_buf(struct zoran *zr)
845 struct zr_buffer *buf;
846 struct vb2_v4l2_buffer *vbuf;
847 dma_addr_t phys_addr;
851 if (zr->running == ZORAN_MAP_MODE_NONE)
856 buf->vbuf.vb2_buf.timestamp = ktime_get_ns();
857 buf->vbuf.sequence = zr->vbseq++;
860 buf->vbuf.field = V4L2_FIELD_INTERLACED;
861 if (BUZ_MAX_HEIGHT < (zr->v4l_settings.height * 2))
862 buf->vbuf.field = V4L2_FIELD_INTERLACED;
864 buf->vbuf.field = V4L2_FIELD_TOP;
865 vb2_set_plane_payload(&buf->vbuf.vb2_buf, 0, zr->buffer_size);
866 vb2_buffer_done(&buf->vbuf.vb2_buf, VB2_BUF_STATE_DONE);
870 spin_lock_irqsave(&zr->queued_bufs_lock, flags);
871 if (list_empty(&zr->queued_bufs)) {
872 btand(~ZR36057_ICR_INT_PIN_EN, ZR36057_ICR);
873 vb2_queue_error(zr->video_dev->queue);
874 spin_unlock_irqrestore(&zr->queued_bufs_lock, flags);
877 buf = list_first_entry_or_null(&zr->queued_bufs, struct zr_buffer, queue);
879 btand(~ZR36057_ICR_INT_PIN_EN, ZR36057_ICR);
880 vb2_queue_error(zr->video_dev->queue);
881 spin_unlock_irqrestore(&zr->queued_bufs_lock, flags);
884 list_del(&buf->queue);
885 zr->buf_in_reserve--;
886 spin_unlock_irqrestore(&zr->queued_bufs_lock, flags);
889 vbuf->vb2_buf.state = VB2_BUF_STATE_ACTIVE;
890 phys_addr = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0);
898 btwrite(reg, ZR36057_VDTR);
899 if (zr->v4l_settings.height > BUZ_MAX_HEIGHT / 2)
900 reg += zr->v4l_settings.bytesperline;
901 btwrite(reg, ZR36057_VDBR);
904 if (zr->v4l_settings.height > BUZ_MAX_HEIGHT / 2)
905 reg += zr->v4l_settings.bytesperline;
906 reg = (reg << ZR36057_VSSFGR_DISP_STRIDE);
907 reg |= ZR36057_VSSFGR_VID_OVF;
908 reg |= ZR36057_VSSFGR_SNAP_SHOT;
909 reg |= ZR36057_VSSFGR_FRAME_GRAB;
910 btwrite(reg, ZR36057_VSSFGR);
912 btor(ZR36057_VDCR_VID_EN, ZR36057_VDCR);
916 static int zr_vb2_start_streaming(struct vb2_queue *vq, unsigned int count)
918 struct zoran *zr = vq->drv_priv;
921 for (j = 0; j < BUZ_NUM_STAT_COM; j++) {
922 zr->stat_com[j] = cpu_to_le32(1);
927 if (zr->map_mode != ZORAN_MAP_MODE_RAW) {
928 pci_dbg(zr->pci_dev, "START JPG\n");
930 zoran_init_hardware(zr);
931 if (zr->map_mode == ZORAN_MAP_MODE_JPG_REC)
932 zr36057_enable_jpg(zr, BUZ_MODE_MOTION_DECOMPRESS);
934 zr36057_enable_jpg(zr, BUZ_MODE_MOTION_COMPRESS);
935 zoran_feed_stat_com(zr);
937 zr->running = zr->map_mode;
938 btor(ZR36057_ICR_INT_PIN_EN, ZR36057_ICR);
942 pci_dbg(zr->pci_dev, "START RAW\n");
944 zoran_init_hardware(zr);
946 zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
947 zr36057_set_memgrab(zr, 1);
948 zr->running = zr->map_mode;
949 btor(ZR36057_ICR_INT_PIN_EN, ZR36057_ICR);
953 static void zr_vb2_stop_streaming(struct vb2_queue *vq)
955 struct zoran *zr = vq->drv_priv;
956 struct zr_buffer *buf;
960 btand(~ZR36057_ICR_INT_PIN_EN, ZR36057_ICR);
961 if (zr->map_mode != ZORAN_MAP_MODE_RAW)
962 zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
963 zr36057_set_memgrab(zr, 0);
964 zr->running = ZORAN_MAP_MODE_NONE;
966 zoran_set_pci_master(zr, 0);
968 if (!pass_through) { /* Switch to color bar */
969 decoder_call(zr, video, s_stream, 0);
970 encoder_call(zr, video, s_routing, 2, 0, 0);
973 for (j = 0; j < BUZ_NUM_STAT_COM; j++) {
974 zr->stat_com[j] = cpu_to_le32(1);
978 pci_dbg(zr->pci_dev, "%s clean buf %d\n", __func__, j);
979 vb2_buffer_done(&buf->vbuf.vb2_buf, VB2_BUF_STATE_ERROR);
983 spin_lock_irqsave(&zr->queued_bufs_lock, flags);
984 while (!list_empty(&zr->queued_bufs)) {
985 buf = list_entry(zr->queued_bufs.next, struct zr_buffer, queue);
986 list_del(&buf->queue);
987 vb2_buffer_done(&buf->vbuf.vb2_buf, VB2_BUF_STATE_ERROR);
988 zr->buf_in_reserve--;
990 spin_unlock_irqrestore(&zr->queued_bufs_lock, flags);
991 if (zr->buf_in_reserve)
992 pci_dbg(zr->pci_dev, "Buffer remaining %d\n", zr->buf_in_reserve);
993 zr->map_mode = ZORAN_MAP_MODE_RAW;
996 static const struct vb2_ops zr_video_qops = {
997 .queue_setup = zr_vb2_queue_setup,
998 .buf_queue = zr_vb2_queue,
999 .buf_prepare = zr_vb2_prepare,
1000 .start_streaming = zr_vb2_start_streaming,
1001 .stop_streaming = zr_vb2_stop_streaming,
1002 .wait_prepare = vb2_ops_wait_prepare,
1003 .wait_finish = vb2_ops_wait_finish,
1006 int zoran_queue_init(struct zoran *zr, struct vb2_queue *vq, int dir)
1010 spin_lock_init(&zr->queued_bufs_lock);
1011 INIT_LIST_HEAD(&zr->queued_bufs);
1013 vq->dev = &zr->pci_dev->dev;
1016 vq->io_modes = VB2_DMABUF | VB2_MMAP | VB2_READ | VB2_WRITE;
1018 vq->buf_struct_size = sizeof(struct zr_buffer);
1019 vq->ops = &zr_video_qops;
1020 vq->mem_ops = &vb2_dma_contig_memops;
1021 vq->gfp_flags = GFP_DMA32;
1022 vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1023 vq->min_buffers_needed = 9;
1024 vq->lock = &zr->lock;
1025 err = vb2_queue_init(vq);
1028 zr->video_dev->queue = vq;
1032 void zoran_queue_exit(struct zoran *zr)
1034 vb2_queue_release(zr->video_dev->queue);