1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Zoran zr36057/zr36067 PCI controller driver, for the
4 * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
5 * Media Labs LML33/LML33R10.
6 *
7 * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
8 *
9 * Changes for BUZ by Wolfgang Scherr <scherr@net4you.net>
10 *
11 * Changes for DC10/DC30 by Laurent Pinchart <laurent.pinchart@skynet.be>
12 *
13 * Changes for LML33R10 by Maxim Yevtyushkin <max@linuxmedialabs.com>
14 *
15 * Changes for videodev2/v4l2 by Ronald Bultje <rbultje@ronald.bitfreak.net>
16 *
17 * Based on
18 *
19 * Miro DC10 driver
20 * Copyright (C) 1999 Wolfgang Scherr <scherr@net4you.net>
21 *
22 * Iomega Buz driver version 1.0
23 * Copyright (C) 1999 Rainer Johanni <Rainer@Johanni.de>
24 *
25 * buz.0.0.3
26 * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
27 *
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)
31 */
32
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>
39
40#include <linux/interrupt.h>
41#include <linux/i2c.h>
42#include <linux/i2c-algo-bit.h>
43
44#include <linux/spinlock.h>
45
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"
51
52#include <linux/io.h>
53#include <linux/uaccess.h>
54
55#include <linux/mutex.h>
56#include "zoran.h"
57#include "zoran_device.h"
58#include "zoran_card.h"
59
60const struct zoran_format zoran_formats[] = {
61 {
62 .name = "15-bit RGB LE",
63 .fourcc = V4L2_PIX_FMT_RGB555,
64 .colorspace = V4L2_COLORSPACE_SRGB,
65 .depth = 15,
66 .flags = ZORAN_FORMAT_CAPTURE,
67 .vfespfr = ZR36057_VFESPFR_RGB555 | ZR36057_VFESPFR_ERR_DIF |
68 ZR36057_VFESPFR_LITTLE_ENDIAN,
69 }, {
70 .name = "15-bit RGB BE",
71 .fourcc = V4L2_PIX_FMT_RGB555X,
72 .colorspace = V4L2_COLORSPACE_SRGB,
73 .depth = 15,
74 .flags = ZORAN_FORMAT_CAPTURE,
75 .vfespfr = ZR36057_VFESPFR_RGB555 | ZR36057_VFESPFR_ERR_DIF,
76 }, {
77 .name = "16-bit RGB LE",
78 .fourcc = V4L2_PIX_FMT_RGB565,
79 .colorspace = V4L2_COLORSPACE_SRGB,
80 .depth = 16,
81 .flags = ZORAN_FORMAT_CAPTURE,
82 .vfespfr = ZR36057_VFESPFR_RGB565 | ZR36057_VFESPFR_ERR_DIF |
83 ZR36057_VFESPFR_LITTLE_ENDIAN,
84 }, {
85 .name = "16-bit RGB BE",
86 .fourcc = V4L2_PIX_FMT_RGB565X,
87 .colorspace = V4L2_COLORSPACE_SRGB,
88 .depth = 16,
89 .flags = ZORAN_FORMAT_CAPTURE,
90 .vfespfr = ZR36057_VFESPFR_RGB565 | ZR36057_VFESPFR_ERR_DIF,
91 }, {
92 .name = "24-bit RGB",
93 .fourcc = V4L2_PIX_FMT_BGR24,
94 .colorspace = V4L2_COLORSPACE_SRGB,
95 .depth = 24,
96 .flags = ZORAN_FORMAT_CAPTURE,
97 .vfespfr = ZR36057_VFESPFR_RGB888 | ZR36057_VFESPFR_PACK24,
98 }, {
99 .name = "32-bit RGB LE",
100 .fourcc = V4L2_PIX_FMT_BGR32,
101 .colorspace = V4L2_COLORSPACE_SRGB,
102 .depth = 32,
103 .flags = ZORAN_FORMAT_CAPTURE,
104 .vfespfr = ZR36057_VFESPFR_RGB888 | ZR36057_VFESPFR_LITTLE_ENDIAN,
105 }, {
106 .name = "32-bit RGB BE",
107 .fourcc = V4L2_PIX_FMT_RGB32,
108 .colorspace = V4L2_COLORSPACE_SRGB,
109 .depth = 32,
110 .flags = ZORAN_FORMAT_CAPTURE,
111 .vfespfr = ZR36057_VFESPFR_RGB888,
112 }, {
113 .name = "4:2:2, packed, YUYV",
114 .fourcc = V4L2_PIX_FMT_YUYV,
115 .colorspace = V4L2_COLORSPACE_SMPTE170M,
116 .depth = 16,
117 .flags = ZORAN_FORMAT_CAPTURE,
118 .vfespfr = ZR36057_VFESPFR_YUV422,
119 }, {
120 .name = "4:2:2, packed, UYVY",
121 .fourcc = V4L2_PIX_FMT_UYVY,
122 .colorspace = V4L2_COLORSPACE_SMPTE170M,
123 .depth = 16,
124 .flags = ZORAN_FORMAT_CAPTURE,
125 .vfespfr = ZR36057_VFESPFR_YUV422 | ZR36057_VFESPFR_LITTLE_ENDIAN,
126 }, {
127 .name = "Hardware-encoded Motion-JPEG",
128 .fourcc = V4L2_PIX_FMT_MJPEG,
129 .colorspace = V4L2_COLORSPACE_SMPTE170M,
130 .depth = 0,
131 .flags = ZORAN_FORMAT_CAPTURE |
132 ZORAN_FORMAT_PLAYBACK |
133 ZORAN_FORMAT_COMPRESSED,
134 }
135};
136
137#define NUM_FORMATS ARRAY_SIZE(zoran_formats)
138
139 /*
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
143 */
144static __u32 zoran_v4l2_calc_bufsize(struct zoran_jpg_settings *settings)
145{
146 __u8 div = settings->ver_dcm * settings->hor_dcm * settings->tmp_dcm;
147 __u32 num = (1024 * 512) / (div);
148 __u32 result = 2;
149
150 num--;
151 while (num) {
152 num >>= 1;
153 result <<= 1;
154 }
155
156 if (result < 8192)
157 return 8192;
158
159 return result;
160}
161
162/*
163 * V4L Buffer grabbing
164 */
165static int zoran_v4l_set_format(struct zoran *zr, int width, int height,
166 const struct zoran_format *format)
167{
168 int bpp;
169
170 /* Check size and format of the grab wanted */
171
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);
175 return -EINVAL;
176 }
177
178 bpp = (format->depth + 7) / 8;
179
180 zr->buffer_size = height * width * bpp;
181
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);
186 return -EINVAL;
187 }
188
189 /* The video front end needs 4-byte alinged line sizes */
190
191 if ((bpp == 2 && (width & 1)) || (bpp == 3 && (width & 3))) {
192 pci_dbg(zr->pci_dev, "%s - wrong frame alignment\n", __func__);
193 return -EINVAL;
194 }
195
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;
200
201 return 0;
202}
203
204static int zoran_set_norm(struct zoran *zr, v4l2_std_id norm)
205{
206 if (!(norm & zr->card.norms)) {
207 pci_dbg(zr->pci_dev, "%s - unsupported norm %llx\n", __func__, norm);
208 return -EINVAL;
209 }
210
211 if (norm & V4L2_STD_SECAM)
212 zr->timing = zr->card.tvn[ZR_NORM_SECAM];
213 else if (norm & V4L2_STD_NTSC)
214 zr->timing = zr->card.tvn[ZR_NORM_NTSC];
215 else
216 zr->timing = zr->card.tvn[ZR_NORM_PAL];
217
218 decoder_call(zr, video, s_std, norm);
219 encoder_call(zr, video, s_std_output, norm);
220
221 /* Make sure the changes come into effect */
222 zr->norm = norm;
223
224 return 0;
225}
226
227static int zoran_set_input(struct zoran *zr, int input)
228{
229 if (input == zr->input)
230 return 0;
231
232 if (input < 0 || input >= zr->card.inputs) {
233 pci_dbg(zr->pci_dev, "%s - unsupported input %d\n", __func__, input);
234 return -EINVAL;
235 }
236
237 zr->input = input;
238
239 decoder_call(zr, video, s_routing, zr->card.input[input].muxsel, 0, 0);
240
241 return 0;
242}
243
244/*
245 * ioctl routine
246 */
247
248static int zoran_querycap(struct file *file, void *__fh, struct v4l2_capability *cap)
249{
250 struct zoran *zr = video_drvdata(file);
251
252 strscpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card));
253 strscpy(cap->driver, "zoran", sizeof(cap->driver));
254 snprintf(buf: cap->bus_info, size: sizeof(cap->bus_info), fmt: "PCI:%s", pci_name(pdev: zr->pci_dev));
255 return 0;
256}
257
258static int zoran_enum_fmt(struct zoran *zr, struct v4l2_fmtdesc *fmt, int flag)
259{
260 unsigned int num, i;
261
262 if (fmt->index >= ARRAY_SIZE(zoran_formats))
263 return -EINVAL;
264 if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
265 return -EINVAL;
266
267 for (num = i = 0; i < NUM_FORMATS; i++) {
268 if (zoran_formats[i].flags & flag && num++ == fmt->index) {
269 strscpy(fmt->description, zoran_formats[i].name,
270 sizeof(fmt->description));
271 /* fmt struct pre-zeroed, so adding '\0' not needed */
272 fmt->pixelformat = zoran_formats[i].fourcc;
273 if (zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED)
274 fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
275 return 0;
276 }
277 }
278 return -EINVAL;
279}
280
281static int zoran_enum_fmt_vid_cap(struct file *file, void *__fh,
282 struct v4l2_fmtdesc *f)
283{
284 struct zoran *zr = video_drvdata(file);
285
286 return zoran_enum_fmt(zr, fmt: f, ZORAN_FORMAT_CAPTURE);
287}
288
289static int zoran_g_fmt_vid_out(struct file *file, void *__fh,
290 struct v4l2_format *fmt)
291{
292 struct zoran *zr = video_drvdata(file);
293
294 fmt->fmt.pix.width = zr->jpg_settings.img_width / zr->jpg_settings.hor_dcm;
295 fmt->fmt.pix.height = zr->jpg_settings.img_height * 2 /
296 (zr->jpg_settings.ver_dcm * zr->jpg_settings.tmp_dcm);
297 fmt->fmt.pix.sizeimage = zr->buffer_size;
298 fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
299 if (zr->jpg_settings.tmp_dcm == 1)
300 fmt->fmt.pix.field = (zr->jpg_settings.odd_even ?
301 V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT);
302 else
303 fmt->fmt.pix.field = (zr->jpg_settings.odd_even ?
304 V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM);
305 fmt->fmt.pix.bytesperline = 0;
306 fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
307
308 return 0;
309}
310
311static int zoran_g_fmt_vid_cap(struct file *file, void *__fh,
312 struct v4l2_format *fmt)
313{
314 struct zoran *zr = video_drvdata(file);
315
316 if (zr->map_mode != ZORAN_MAP_MODE_RAW)
317 return zoran_g_fmt_vid_out(file, __fh, fmt);
318 fmt->fmt.pix.width = zr->v4l_settings.width;
319 fmt->fmt.pix.height = zr->v4l_settings.height;
320 fmt->fmt.pix.sizeimage = zr->buffer_size;
321 fmt->fmt.pix.pixelformat = zr->v4l_settings.format->fourcc;
322 fmt->fmt.pix.colorspace = zr->v4l_settings.format->colorspace;
323 fmt->fmt.pix.bytesperline = zr->v4l_settings.bytesperline;
324 if (BUZ_MAX_HEIGHT < (zr->v4l_settings.height * 2))
325 fmt->fmt.pix.field = V4L2_FIELD_INTERLACED;
326 else
327 fmt->fmt.pix.field = V4L2_FIELD_TOP;
328 return 0;
329}
330
331static int zoran_try_fmt_vid_out(struct file *file, void *__fh,
332 struct v4l2_format *fmt)
333{
334 struct zoran *zr = video_drvdata(file);
335 struct zoran_jpg_settings settings;
336 int res = 0;
337
338 if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
339 return -EINVAL;
340
341 settings = zr->jpg_settings;
342
343 /* we actually need to set 'real' parameters now */
344 if ((fmt->fmt.pix.height * 2) > BUZ_MAX_HEIGHT)
345 settings.tmp_dcm = 1;
346 else
347 settings.tmp_dcm = 2;
348 settings.decimation = 0;
349 if (fmt->fmt.pix.height <= zr->jpg_settings.img_height / 2)
350 settings.ver_dcm = 2;
351 else
352 settings.ver_dcm = 1;
353 if (fmt->fmt.pix.width <= zr->jpg_settings.img_width / 4)
354 settings.hor_dcm = 4;
355 else if (fmt->fmt.pix.width <= zr->jpg_settings.img_width / 2)
356 settings.hor_dcm = 2;
357 else
358 settings.hor_dcm = 1;
359 if (settings.tmp_dcm == 1)
360 settings.field_per_buff = 2;
361 else
362 settings.field_per_buff = 1;
363
364 if (settings.hor_dcm > 1) {
365 settings.img_x = (BUZ_MAX_WIDTH == 720) ? 8 : 0;
366 settings.img_width = (BUZ_MAX_WIDTH == 720) ? 704 : BUZ_MAX_WIDTH;
367 } else {
368 settings.img_x = 0;
369 settings.img_width = BUZ_MAX_WIDTH;
370 }
371
372 /* check */
373 res = zoran_check_jpg_settings(zr, settings: &settings, try: 1);
374 if (res)
375 return res;
376
377 /* tell the user what we actually did */
378 fmt->fmt.pix.width = settings.img_width / settings.hor_dcm;
379 fmt->fmt.pix.height = settings.img_height * 2 /
380 (settings.tmp_dcm * settings.ver_dcm);
381 if (settings.tmp_dcm == 1)
382 fmt->fmt.pix.field = (zr->jpg_settings.odd_even ?
383 V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT);
384 else
385 fmt->fmt.pix.field = (zr->jpg_settings.odd_even ?
386 V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM);
387
388 fmt->fmt.pix.sizeimage = zoran_v4l2_calc_bufsize(settings: &settings);
389 fmt->fmt.pix.bytesperline = 0;
390 fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
391 return res;
392}
393
394static int zoran_try_fmt_vid_cap(struct file *file, void *__fh,
395 struct v4l2_format *fmt)
396{
397 struct zoran *zr = video_drvdata(file);
398 int bpp;
399 int i;
400
401 if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG)
402 return zoran_try_fmt_vid_out(file, __fh, fmt);
403
404 for (i = 0; i < NUM_FORMATS; i++)
405 if (zoran_formats[i].fourcc == fmt->fmt.pix.pixelformat)
406 break;
407
408 if (i == NUM_FORMATS) {
409 /* TODO do not return here to fix the TRY_FMT cannot handle an invalid pixelformat*/
410 return -EINVAL;
411 }
412
413 fmt->fmt.pix.pixelformat = zoran_formats[i].fourcc;
414 fmt->fmt.pix.colorspace = zoran_formats[i].colorspace;
415 if (BUZ_MAX_HEIGHT < (fmt->fmt.pix.height * 2))
416 fmt->fmt.pix.field = V4L2_FIELD_INTERLACED;
417 else
418 fmt->fmt.pix.field = V4L2_FIELD_TOP;
419
420 bpp = DIV_ROUND_UP(zoran_formats[i].depth, 8);
421 v4l_bound_align_image(width: &fmt->fmt.pix.width, BUZ_MIN_WIDTH, BUZ_MAX_WIDTH,
422 walign: bpp == 2 ? 1 : 2,
423 height: &fmt->fmt.pix.height, BUZ_MIN_HEIGHT, BUZ_MAX_HEIGHT,
424 halign: 0, salign: 0);
425 fmt->fmt.pix.bytesperline = fmt->fmt.pix.width * bpp;
426 fmt->fmt.pix.sizeimage = fmt->fmt.pix.bytesperline * fmt->fmt.pix.height;
427 return 0;
428}
429
430static int zoran_s_fmt_vid_out(struct file *file, void *__fh,
431 struct v4l2_format *fmt)
432{
433 struct zoran *zr = video_drvdata(file);
434 __le32 printformat = __cpu_to_le32(fmt->fmt.pix.pixelformat);
435 struct zoran_jpg_settings settings;
436 int res = 0;
437
438 pci_dbg(zr->pci_dev, "size=%dx%d, fmt=0x%x (%4.4s)\n",
439 fmt->fmt.pix.width, fmt->fmt.pix.height,
440 fmt->fmt.pix.pixelformat,
441 (char *)&printformat);
442 if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
443 return -EINVAL;
444
445 if (!fmt->fmt.pix.height || !fmt->fmt.pix.width)
446 return -EINVAL;
447
448 settings = zr->jpg_settings;
449
450 /* we actually need to set 'real' parameters now */
451 if (fmt->fmt.pix.height * 2 > BUZ_MAX_HEIGHT)
452 settings.tmp_dcm = 1;
453 else
454 settings.tmp_dcm = 2;
455 settings.decimation = 0;
456 if (fmt->fmt.pix.height <= zr->jpg_settings.img_height / 2)
457 settings.ver_dcm = 2;
458 else
459 settings.ver_dcm = 1;
460 if (fmt->fmt.pix.width <= zr->jpg_settings.img_width / 4)
461 settings.hor_dcm = 4;
462 else if (fmt->fmt.pix.width <= zr->jpg_settings.img_width / 2)
463 settings.hor_dcm = 2;
464 else
465 settings.hor_dcm = 1;
466 if (settings.tmp_dcm == 1)
467 settings.field_per_buff = 2;
468 else
469 settings.field_per_buff = 1;
470
471 if (settings.hor_dcm > 1) {
472 settings.img_x = (BUZ_MAX_WIDTH == 720) ? 8 : 0;
473 settings.img_width = (BUZ_MAX_WIDTH == 720) ? 704 : BUZ_MAX_WIDTH;
474 } else {
475 settings.img_x = 0;
476 settings.img_width = BUZ_MAX_WIDTH;
477 }
478
479 /* check */
480 res = zoran_check_jpg_settings(zr, settings: &settings, try: 0);
481 if (res)
482 return res;
483
484 /* it's ok, so set them */
485 zr->jpg_settings = settings;
486
487 if (fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
488 zr->map_mode = ZORAN_MAP_MODE_JPG_REC;
489 else
490 zr->map_mode = ZORAN_MAP_MODE_JPG_PLAY;
491
492 zr->buffer_size = zoran_v4l2_calc_bufsize(settings: &zr->jpg_settings);
493
494 /* tell the user what we actually did */
495 fmt->fmt.pix.width = settings.img_width / settings.hor_dcm;
496 fmt->fmt.pix.height = settings.img_height * 2 /
497 (settings.tmp_dcm * settings.ver_dcm);
498 if (settings.tmp_dcm == 1)
499 fmt->fmt.pix.field = (zr->jpg_settings.odd_even ?
500 V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT);
501 else
502 fmt->fmt.pix.field = (zr->jpg_settings.odd_even ?
503 V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM);
504 fmt->fmt.pix.bytesperline = 0;
505 fmt->fmt.pix.sizeimage = zr->buffer_size;
506 fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
507 return res;
508}
509
510static int zoran_s_fmt_vid_cap(struct file *file, void *__fh,
511 struct v4l2_format *fmt)
512{
513 struct zoran *zr = video_drvdata(file);
514 struct zoran_fh *fh = __fh;
515 int i;
516 int res = 0;
517
518 if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG)
519 return zoran_s_fmt_vid_out(file, fh: fh, fmt);
520
521 for (i = 0; i < NUM_FORMATS; i++)
522 if (fmt->fmt.pix.pixelformat == zoran_formats[i].fourcc)
523 break;
524 if (i == NUM_FORMATS) {
525 pci_dbg(zr->pci_dev, "VIDIOC_S_FMT - unknown/unsupported format 0x%x\n",
526 fmt->fmt.pix.pixelformat);
527 /* TODO do not return here to fix the TRY_FMT cannot handle an invalid pixelformat*/
528 return -EINVAL;
529 }
530
531 fmt->fmt.pix.pixelformat = zoran_formats[i].fourcc;
532 if (fmt->fmt.pix.height > BUZ_MAX_HEIGHT)
533 fmt->fmt.pix.height = BUZ_MAX_HEIGHT;
534 if (fmt->fmt.pix.width > BUZ_MAX_WIDTH)
535 fmt->fmt.pix.width = BUZ_MAX_WIDTH;
536 if (fmt->fmt.pix.height < BUZ_MIN_HEIGHT)
537 fmt->fmt.pix.height = BUZ_MIN_HEIGHT;
538 if (fmt->fmt.pix.width < BUZ_MIN_WIDTH)
539 fmt->fmt.pix.width = BUZ_MIN_WIDTH;
540
541 zr->map_mode = ZORAN_MAP_MODE_RAW;
542
543 res = zoran_v4l_set_format(zr, width: fmt->fmt.pix.width, height: fmt->fmt.pix.height,
544 format: &zoran_formats[i]);
545 if (res)
546 return res;
547
548 /* tell the user the results/missing stuff */
549 fmt->fmt.pix.bytesperline = zr->v4l_settings.bytesperline;
550 fmt->fmt.pix.sizeimage = zr->buffer_size;
551 fmt->fmt.pix.colorspace = zr->v4l_settings.format->colorspace;
552 if (BUZ_MAX_HEIGHT < (zr->v4l_settings.height * 2))
553 fmt->fmt.pix.field = V4L2_FIELD_INTERLACED;
554 else
555 fmt->fmt.pix.field = V4L2_FIELD_TOP;
556 return res;
557}
558
559static int zoran_g_std(struct file *file, void *__fh, v4l2_std_id *std)
560{
561 struct zoran *zr = video_drvdata(file);
562
563 *std = zr->norm;
564 return 0;
565}
566
567static int zoran_s_std(struct file *file, void *__fh, v4l2_std_id std)
568{
569 struct zoran *zr = video_drvdata(file);
570 int res = 0;
571
572 if (zr->norm == std)
573 return 0;
574
575 if (zr->running != ZORAN_MAP_MODE_NONE)
576 return -EBUSY;
577
578 res = zoran_set_norm(zr, norm: std);
579 return res;
580}
581
582static int zoran_enum_input(struct file *file, void *__fh,
583 struct v4l2_input *inp)
584{
585 struct zoran *zr = video_drvdata(file);
586
587 if (inp->index >= zr->card.inputs)
588 return -EINVAL;
589
590 strscpy(inp->name, zr->card.input[inp->index].name, sizeof(inp->name));
591 inp->type = V4L2_INPUT_TYPE_CAMERA;
592 inp->std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM;
593
594 /* Get status of video decoder */
595 decoder_call(zr, video, g_input_status, &inp->status);
596 return 0;
597}
598
599static int zoran_g_input(struct file *file, void *__fh, unsigned int *input)
600{
601 struct zoran *zr = video_drvdata(file);
602
603 *input = zr->input;
604
605 return 0;
606}
607
608static int zoran_s_input(struct file *file, void *__fh, unsigned int input)
609{
610 struct zoran *zr = video_drvdata(file);
611 int res;
612
613 if (zr->running != ZORAN_MAP_MODE_NONE)
614 return -EBUSY;
615
616 res = zoran_set_input(zr, input);
617 return res;
618}
619
620/* cropping (sub-frame capture) */
621static int zoran_g_selection(struct file *file, void *__fh, struct v4l2_selection *sel)
622{
623 struct zoran *zr = video_drvdata(file);
624
625 if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
626 sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
627 pci_dbg(zr->pci_dev, "%s invalid selection type combination\n", __func__);
628 return -EINVAL;
629 }
630
631 switch (sel->target) {
632 case V4L2_SEL_TGT_CROP:
633 sel->r.top = zr->jpg_settings.img_y;
634 sel->r.left = zr->jpg_settings.img_x;
635 sel->r.width = zr->jpg_settings.img_width;
636 sel->r.height = zr->jpg_settings.img_height;
637 break;
638 case V4L2_SEL_TGT_CROP_DEFAULT:
639 sel->r.top = 0;
640 sel->r.left = 0;
641 sel->r.width = BUZ_MIN_WIDTH;
642 sel->r.height = BUZ_MIN_HEIGHT;
643 break;
644 case V4L2_SEL_TGT_CROP_BOUNDS:
645 sel->r.top = 0;
646 sel->r.left = 0;
647 sel->r.width = BUZ_MAX_WIDTH;
648 sel->r.height = BUZ_MAX_HEIGHT;
649 break;
650 default:
651 return -EINVAL;
652 }
653 return 0;
654}
655
656static int zoran_s_selection(struct file *file, void *__fh, struct v4l2_selection *sel)
657{
658 struct zoran *zr = video_drvdata(file);
659 struct zoran_jpg_settings settings;
660 int res;
661
662 if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
663 sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
664 return -EINVAL;
665
666 if (!sel->r.width || !sel->r.height)
667 return -EINVAL;
668
669 if (sel->target != V4L2_SEL_TGT_CROP)
670 return -EINVAL;
671
672 if (zr->map_mode == ZORAN_MAP_MODE_RAW) {
673 pci_dbg(zr->pci_dev, "VIDIOC_S_SELECTION - subcapture only supported for compressed capture\n");
674 return -EINVAL;
675 }
676
677 settings = zr->jpg_settings;
678
679 /* move into a form that we understand */
680 settings.img_x = sel->r.left;
681 settings.img_y = sel->r.top;
682 settings.img_width = sel->r.width;
683 settings.img_height = sel->r.height;
684
685 /* check validity */
686 res = zoran_check_jpg_settings(zr, settings: &settings, try: 0);
687 if (res)
688 return res;
689
690 /* accept */
691 zr->jpg_settings = settings;
692 return res;
693}
694
695/*
696 * Output is disabled temporarily
697 * Zoran is picky about jpeg data it accepts. At least it seems to unsupport COM and APPn.
698 * So until a way to filter data will be done, disable output.
699 */
700static const struct v4l2_ioctl_ops zoran_ioctl_ops = {
701 .vidioc_querycap = zoran_querycap,
702 .vidioc_s_selection = zoran_s_selection,
703 .vidioc_g_selection = zoran_g_selection,
704 .vidioc_enum_input = zoran_enum_input,
705 .vidioc_g_input = zoran_g_input,
706 .vidioc_s_input = zoran_s_input,
707 .vidioc_g_std = zoran_g_std,
708 .vidioc_s_std = zoran_s_std,
709 .vidioc_create_bufs = vb2_ioctl_create_bufs,
710 .vidioc_reqbufs = vb2_ioctl_reqbufs,
711 .vidioc_querybuf = vb2_ioctl_querybuf,
712 .vidioc_qbuf = vb2_ioctl_qbuf,
713 .vidioc_dqbuf = vb2_ioctl_dqbuf,
714 .vidioc_expbuf = vb2_ioctl_expbuf,
715 .vidioc_streamon = vb2_ioctl_streamon,
716 .vidioc_streamoff = vb2_ioctl_streamoff,
717 .vidioc_enum_fmt_vid_cap = zoran_enum_fmt_vid_cap,
718 .vidioc_g_fmt_vid_cap = zoran_g_fmt_vid_cap,
719 .vidioc_s_fmt_vid_cap = zoran_s_fmt_vid_cap,
720 .vidioc_try_fmt_vid_cap = zoran_try_fmt_vid_cap,
721 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
722 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
723};
724
725static const struct v4l2_file_operations zoran_fops = {
726 .owner = THIS_MODULE,
727 .unlocked_ioctl = video_ioctl2,
728 .open = v4l2_fh_open,
729 .release = vb2_fop_release,
730 .mmap = vb2_fop_mmap,
731 .poll = vb2_fop_poll,
732};
733
734const struct video_device zoran_template = {
735 .name = ZORAN_NAME,
736 .fops = &zoran_fops,
737 .ioctl_ops = &zoran_ioctl_ops,
738 .release = &zoran_vdev_release,
739 .tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
740};
741
742static int zr_vb2_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes,
743 unsigned int sizes[], struct device *alloc_devs[])
744{
745 struct zoran *zr = vb2_get_drv_priv(q: vq);
746 unsigned int size = zr->buffer_size;
747
748 pci_dbg(zr->pci_dev, "%s nbuf=%u nplanes=%u", __func__, *nbuffers, *nplanes);
749
750 zr->buf_in_reserve = 0;
751
752 if (*nbuffers < vq->min_queued_buffers)
753 *nbuffers = vq->min_queued_buffers;
754
755 if (*nplanes) {
756 if (sizes[0] < size)
757 return -EINVAL;
758 else
759 return 0;
760 }
761
762 *nplanes = 1;
763 sizes[0] = size;
764
765 return 0;
766}
767
768static void zr_vb2_queue(struct vb2_buffer *vb)
769{
770 struct zoran *zr = vb2_get_drv_priv(q: vb->vb2_queue);
771 struct zr_buffer *buf = vb2_to_zr_buffer(vb);
772 unsigned long flags;
773
774 spin_lock_irqsave(&zr->queued_bufs_lock, flags);
775 list_add_tail(new: &buf->queue, head: &zr->queued_bufs);
776 zr->buf_in_reserve++;
777 spin_unlock_irqrestore(lock: &zr->queued_bufs_lock, flags);
778 if (zr->running == ZORAN_MAP_MODE_JPG_REC)
779 zoran_feed_stat_com(zr);
780 zr->queued++;
781}
782
783static int zr_vb2_prepare(struct vb2_buffer *vb)
784{
785 struct zoran *zr = vb2_get_drv_priv(q: vb->vb2_queue);
786
787 if (vb2_plane_size(vb, plane_no: 0) < zr->buffer_size)
788 return -EINVAL;
789 zr->prepared++;
790
791 return 0;
792}
793
794int zr_set_buf(struct zoran *zr)
795{
796 struct zr_buffer *buf;
797 struct vb2_v4l2_buffer *vbuf;
798 dma_addr_t phys_addr;
799 unsigned long flags;
800 u32 reg;
801
802 if (zr->running == ZORAN_MAP_MODE_NONE)
803 return 0;
804
805 if (zr->inuse[0]) {
806 buf = zr->inuse[0];
807 buf->vbuf.vb2_buf.timestamp = ktime_get_ns();
808 buf->vbuf.sequence = zr->vbseq++;
809 vbuf = &buf->vbuf;
810
811 buf->vbuf.field = V4L2_FIELD_INTERLACED;
812 if (BUZ_MAX_HEIGHT < (zr->v4l_settings.height * 2))
813 buf->vbuf.field = V4L2_FIELD_INTERLACED;
814 else
815 buf->vbuf.field = V4L2_FIELD_TOP;
816 vb2_set_plane_payload(vb: &buf->vbuf.vb2_buf, plane_no: 0, size: zr->buffer_size);
817 vb2_buffer_done(vb: &buf->vbuf.vb2_buf, state: VB2_BUF_STATE_DONE);
818 zr->inuse[0] = NULL;
819 }
820
821 spin_lock_irqsave(&zr->queued_bufs_lock, flags);
822 if (list_empty(head: &zr->queued_bufs)) {
823 btand(~ZR36057_ICR_INT_PIN_EN, ZR36057_ICR);
824 vb2_queue_error(q: zr->video_dev->queue);
825 spin_unlock_irqrestore(lock: &zr->queued_bufs_lock, flags);
826 return -EINVAL;
827 }
828 buf = list_first_entry_or_null(&zr->queued_bufs, struct zr_buffer, queue);
829 if (!buf) {
830 btand(~ZR36057_ICR_INT_PIN_EN, ZR36057_ICR);
831 vb2_queue_error(q: zr->video_dev->queue);
832 spin_unlock_irqrestore(lock: &zr->queued_bufs_lock, flags);
833 return -EINVAL;
834 }
835 list_del(entry: &buf->queue);
836 zr->buf_in_reserve--;
837 spin_unlock_irqrestore(lock: &zr->queued_bufs_lock, flags);
838
839 vbuf = &buf->vbuf;
840 vbuf->vb2_buf.state = VB2_BUF_STATE_ACTIVE;
841 phys_addr = vb2_dma_contig_plane_dma_addr(vb: &vbuf->vb2_buf, plane_no: 0);
842
843 if (!phys_addr)
844 return -EINVAL;
845
846 zr->inuse[0] = buf;
847
848 reg = phys_addr;
849 btwrite(reg, ZR36057_VDTR);
850 if (zr->v4l_settings.height > BUZ_MAX_HEIGHT / 2)
851 reg += zr->v4l_settings.bytesperline;
852 btwrite(reg, ZR36057_VDBR);
853
854 reg = 0;
855 if (zr->v4l_settings.height > BUZ_MAX_HEIGHT / 2)
856 reg += zr->v4l_settings.bytesperline;
857 reg = (reg << ZR36057_VSSFGR_DISP_STRIDE);
858 reg |= ZR36057_VSSFGR_VID_OVF;
859 reg |= ZR36057_VSSFGR_SNAP_SHOT;
860 reg |= ZR36057_VSSFGR_FRAME_GRAB;
861 btwrite(reg, ZR36057_VSSFGR);
862
863 btor(ZR36057_VDCR_VID_EN, ZR36057_VDCR);
864 return 0;
865}
866
867static int zr_vb2_start_streaming(struct vb2_queue *vq, unsigned int count)
868{
869 struct zoran *zr = vq->drv_priv;
870 int j;
871
872 for (j = 0; j < BUZ_NUM_STAT_COM; j++) {
873 zr->stat_com[j] = cpu_to_le32(1);
874 zr->inuse[j] = NULL;
875 }
876 zr->vbseq = 0;
877
878 if (zr->map_mode != ZORAN_MAP_MODE_RAW) {
879 pci_dbg(zr->pci_dev, "START JPG\n");
880 zr36057_restart(zr);
881 zoran_init_hardware(zr);
882 if (zr->map_mode == ZORAN_MAP_MODE_JPG_REC)
883 zr36057_enable_jpg(zr, mode: BUZ_MODE_MOTION_DECOMPRESS);
884 else
885 zr36057_enable_jpg(zr, mode: BUZ_MODE_MOTION_COMPRESS);
886 zoran_feed_stat_com(zr);
887 jpeg_start(zr);
888 zr->running = zr->map_mode;
889 btor(ZR36057_ICR_INT_PIN_EN, ZR36057_ICR);
890 return 0;
891 }
892
893 pci_dbg(zr->pci_dev, "START RAW\n");
894 zr36057_restart(zr);
895 zoran_init_hardware(zr);
896
897 zr36057_enable_jpg(zr, mode: BUZ_MODE_IDLE);
898 zr36057_set_memgrab(zr, mode: 1);
899 zr->running = zr->map_mode;
900 btor(ZR36057_ICR_INT_PIN_EN, ZR36057_ICR);
901 return 0;
902}
903
904static void zr_vb2_stop_streaming(struct vb2_queue *vq)
905{
906 struct zoran *zr = vq->drv_priv;
907 struct zr_buffer *buf;
908 unsigned long flags;
909 int j;
910
911 btand(~ZR36057_ICR_INT_PIN_EN, ZR36057_ICR);
912 if (zr->map_mode != ZORAN_MAP_MODE_RAW)
913 zr36057_enable_jpg(zr, mode: BUZ_MODE_IDLE);
914 zr36057_set_memgrab(zr, mode: 0);
915 zr->running = ZORAN_MAP_MODE_NONE;
916
917 zoran_set_pci_master(zr, set_master: 0);
918
919 if (!pass_through) { /* Switch to color bar */
920 decoder_call(zr, video, s_stream, 0);
921 encoder_call(zr, video, s_routing, 2, 0, 0);
922 }
923
924 for (j = 0; j < BUZ_NUM_STAT_COM; j++) {
925 zr->stat_com[j] = cpu_to_le32(1);
926 if (!zr->inuse[j])
927 continue;
928 buf = zr->inuse[j];
929 pci_dbg(zr->pci_dev, "%s clean buf %d\n", __func__, j);
930 vb2_buffer_done(vb: &buf->vbuf.vb2_buf, state: VB2_BUF_STATE_ERROR);
931 zr->inuse[j] = NULL;
932 }
933
934 spin_lock_irqsave(&zr->queued_bufs_lock, flags);
935 while (!list_empty(head: &zr->queued_bufs)) {
936 buf = list_entry(zr->queued_bufs.next, struct zr_buffer, queue);
937 list_del(entry: &buf->queue);
938 vb2_buffer_done(vb: &buf->vbuf.vb2_buf, state: VB2_BUF_STATE_ERROR);
939 zr->buf_in_reserve--;
940 }
941 spin_unlock_irqrestore(lock: &zr->queued_bufs_lock, flags);
942 if (zr->buf_in_reserve)
943 pci_dbg(zr->pci_dev, "Buffer remaining %d\n", zr->buf_in_reserve);
944 zr->map_mode = ZORAN_MAP_MODE_RAW;
945}
946
947static const struct vb2_ops zr_video_qops = {
948 .queue_setup = zr_vb2_queue_setup,
949 .buf_queue = zr_vb2_queue,
950 .buf_prepare = zr_vb2_prepare,
951 .start_streaming = zr_vb2_start_streaming,
952 .stop_streaming = zr_vb2_stop_streaming,
953 .wait_prepare = vb2_ops_wait_prepare,
954 .wait_finish = vb2_ops_wait_finish,
955};
956
957int zoran_queue_init(struct zoran *zr, struct vb2_queue *vq, int dir)
958{
959 int err;
960
961 spin_lock_init(&zr->queued_bufs_lock);
962 INIT_LIST_HEAD(list: &zr->queued_bufs);
963
964 vq->dev = &zr->pci_dev->dev;
965 vq->type = dir;
966
967 vq->io_modes = VB2_DMABUF | VB2_MMAP;
968 vq->drv_priv = zr;
969 vq->buf_struct_size = sizeof(struct zr_buffer);
970 vq->ops = &zr_video_qops;
971 vq->mem_ops = &vb2_dma_contig_memops;
972 vq->gfp_flags = GFP_DMA32;
973 vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
974 vq->min_queued_buffers = 9;
975 vq->lock = &zr->lock;
976 err = vb2_queue_init(q: vq);
977 if (err)
978 return err;
979 zr->video_dev->queue = vq;
980 return 0;
981}
982
983void zoran_queue_exit(struct zoran *zr)
984{
985 vb2_queue_release(q: zr->video_dev->queue);
986}
987

source code of linux/drivers/media/pci/zoran/zoran_driver.c