1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * vivid-vid-cap.c - video capture support functions.
4 *
5 * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
6 */
7
8#include <linux/errno.h>
9#include <linux/kernel.h>
10#include <linux/sched.h>
11#include <linux/vmalloc.h>
12#include <linux/videodev2.h>
13#include <linux/v4l2-dv-timings.h>
14#include <media/v4l2-common.h>
15#include <media/v4l2-event.h>
16#include <media/v4l2-dv-timings.h>
17#include <media/v4l2-rect.h>
18
19#include "vivid-core.h"
20#include "vivid-vid-common.h"
21#include "vivid-kthread-cap.h"
22#include "vivid-vid-cap.h"
23
24/* Sizes must be in increasing order */
25static const struct v4l2_frmsize_discrete webcam_sizes[] = {
26 { 320, 180 },
27 { 640, 360 },
28 { 640, 480 },
29 { 1280, 720 },
30 { 1920, 1080 },
31 { 3840, 2160 },
32};
33
34/*
35 * Intervals must be in increasing order and there must be twice as many
36 * elements in this array as there are in webcam_sizes.
37 */
38static const struct v4l2_fract webcam_intervals[] = {
39 { 1, 1 },
40 { 1, 2 },
41 { 1, 4 },
42 { 1, 5 },
43 { 1, 10 },
44 { 2, 25 },
45 { 1, 15 }, /* 7 - maximum for 2160p */
46 { 1, 25 },
47 { 1, 30 }, /* 9 - maximum for 1080p */
48 { 1, 40 },
49 { 1, 50 },
50 { 1, 60 }, /* 12 - maximum for 720p */
51 { 1, 120 },
52};
53
54/* Limit maximum FPS rates for high resolutions */
55#define IVAL_COUNT_720P 12 /* 720p and up is limited to 60 fps */
56#define IVAL_COUNT_1080P 9 /* 1080p and up is limited to 30 fps */
57#define IVAL_COUNT_2160P 7 /* 2160p and up is limited to 15 fps */
58
59static inline unsigned int webcam_ival_count(const struct vivid_dev *dev,
60 unsigned int frmsize_idx)
61{
62 if (webcam_sizes[frmsize_idx].height >= 2160)
63 return IVAL_COUNT_2160P;
64
65 if (webcam_sizes[frmsize_idx].height >= 1080)
66 return IVAL_COUNT_1080P;
67
68 if (webcam_sizes[frmsize_idx].height >= 720)
69 return IVAL_COUNT_720P;
70
71 /* For low resolutions, allow all FPS rates */
72 return ARRAY_SIZE(webcam_intervals);
73}
74
75static int vid_cap_queue_setup(struct vb2_queue *vq,
76 unsigned *nbuffers, unsigned *nplanes,
77 unsigned sizes[], struct device *alloc_devs[])
78{
79 struct vivid_dev *dev = vb2_get_drv_priv(q: vq);
80 unsigned buffers = tpg_g_buffers(tpg: &dev->tpg);
81 unsigned h = dev->fmt_cap_rect.height;
82 unsigned p;
83
84 if (dev->field_cap == V4L2_FIELD_ALTERNATE) {
85 /*
86 * You cannot use read() with FIELD_ALTERNATE since the field
87 * information (TOP/BOTTOM) cannot be passed back to the user.
88 */
89 if (vb2_fileio_is_active(q: vq))
90 return -EINVAL;
91 }
92
93 if (dev->queue_setup_error) {
94 /*
95 * Error injection: test what happens if queue_setup() returns
96 * an error.
97 */
98 dev->queue_setup_error = false;
99 return -EINVAL;
100 }
101 if (*nplanes) {
102 /*
103 * Check if the number of requested planes match
104 * the number of buffers in the current format. You can't mix that.
105 */
106 if (*nplanes != buffers)
107 return -EINVAL;
108 for (p = 0; p < buffers; p++) {
109 if (sizes[p] < tpg_g_line_width(tpg: &dev->tpg, plane: p) * h +
110 dev->fmt_cap->data_offset[p])
111 return -EINVAL;
112 }
113 } else {
114 for (p = 0; p < buffers; p++)
115 sizes[p] = (tpg_g_line_width(tpg: &dev->tpg, plane: p) * h) /
116 dev->fmt_cap->vdownsampling[p] +
117 dev->fmt_cap->data_offset[p];
118 }
119
120 *nplanes = buffers;
121
122 dprintk(dev, 1, "%s: count=%d\n", __func__, *nbuffers);
123 for (p = 0; p < buffers; p++)
124 dprintk(dev, 1, "%s: size[%u]=%u\n", __func__, p, sizes[p]);
125
126 return 0;
127}
128
129static int vid_cap_buf_prepare(struct vb2_buffer *vb)
130{
131 struct vivid_dev *dev = vb2_get_drv_priv(q: vb->vb2_queue);
132 unsigned long size;
133 unsigned buffers = tpg_g_buffers(tpg: &dev->tpg);
134 unsigned p;
135
136 dprintk(dev, 1, "%s\n", __func__);
137
138 if (WARN_ON(NULL == dev->fmt_cap))
139 return -EINVAL;
140
141 if (dev->buf_prepare_error) {
142 /*
143 * Error injection: test what happens if buf_prepare() returns
144 * an error.
145 */
146 dev->buf_prepare_error = false;
147 return -EINVAL;
148 }
149 for (p = 0; p < buffers; p++) {
150 size = (tpg_g_line_width(tpg: &dev->tpg, plane: p) *
151 dev->fmt_cap_rect.height) /
152 dev->fmt_cap->vdownsampling[p] +
153 dev->fmt_cap->data_offset[p];
154
155 if (vb2_plane_size(vb, plane_no: p) < size) {
156 dprintk(dev, 1, "%s data will not fit into plane %u (%lu < %lu)\n",
157 __func__, p, vb2_plane_size(vb, p), size);
158 return -EINVAL;
159 }
160
161 vb2_set_plane_payload(vb, plane_no: p, size);
162 vb->planes[p].data_offset = dev->fmt_cap->data_offset[p];
163 }
164
165 return 0;
166}
167
168static void vid_cap_buf_finish(struct vb2_buffer *vb)
169{
170 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
171 struct vivid_dev *dev = vb2_get_drv_priv(q: vb->vb2_queue);
172 struct v4l2_timecode *tc = &vbuf->timecode;
173 unsigned fps = 25;
174 unsigned seq = vbuf->sequence;
175
176 if (!vivid_is_sdtv_cap(dev))
177 return;
178
179 /*
180 * Set the timecode. Rarely used, so it is interesting to
181 * test this.
182 */
183 vbuf->flags |= V4L2_BUF_FLAG_TIMECODE;
184 if (dev->std_cap[dev->input] & V4L2_STD_525_60)
185 fps = 30;
186 tc->type = (fps == 30) ? V4L2_TC_TYPE_30FPS : V4L2_TC_TYPE_25FPS;
187 tc->flags = 0;
188 tc->frames = seq % fps;
189 tc->seconds = (seq / fps) % 60;
190 tc->minutes = (seq / (60 * fps)) % 60;
191 tc->hours = (seq / (60 * 60 * fps)) % 24;
192}
193
194static void vid_cap_buf_queue(struct vb2_buffer *vb)
195{
196 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
197 struct vivid_dev *dev = vb2_get_drv_priv(q: vb->vb2_queue);
198 struct vivid_buffer *buf = container_of(vbuf, struct vivid_buffer, vb);
199
200 dprintk(dev, 1, "%s\n", __func__);
201
202 spin_lock(lock: &dev->slock);
203 list_add_tail(new: &buf->list, head: &dev->vid_cap_active);
204 spin_unlock(lock: &dev->slock);
205}
206
207static int vid_cap_start_streaming(struct vb2_queue *vq, unsigned count)
208{
209 struct vivid_dev *dev = vb2_get_drv_priv(q: vq);
210 unsigned i;
211 int err;
212
213 if (vb2_is_streaming(q: &dev->vb_vid_out_q))
214 dev->can_loop_video = vivid_vid_can_loop(dev);
215
216 dev->vid_cap_seq_count = 0;
217 dprintk(dev, 1, "%s\n", __func__);
218 for (i = 0; i < VIDEO_MAX_FRAME; i++)
219 dev->must_blank[i] = tpg_g_perc_fill(tpg: &dev->tpg) < 100;
220 if (dev->start_streaming_error) {
221 dev->start_streaming_error = false;
222 err = -EINVAL;
223 } else {
224 err = vivid_start_generating_vid_cap(dev, pstreaming: &dev->vid_cap_streaming);
225 }
226 if (err) {
227 struct vivid_buffer *buf, *tmp;
228
229 list_for_each_entry_safe(buf, tmp, &dev->vid_cap_active, list) {
230 list_del(entry: &buf->list);
231 vb2_buffer_done(vb: &buf->vb.vb2_buf,
232 state: VB2_BUF_STATE_QUEUED);
233 }
234 }
235 return err;
236}
237
238/* abort streaming and wait for last buffer */
239static void vid_cap_stop_streaming(struct vb2_queue *vq)
240{
241 struct vivid_dev *dev = vb2_get_drv_priv(q: vq);
242
243 dprintk(dev, 1, "%s\n", __func__);
244 vivid_stop_generating_vid_cap(dev, pstreaming: &dev->vid_cap_streaming);
245 dev->can_loop_video = false;
246}
247
248static void vid_cap_buf_request_complete(struct vb2_buffer *vb)
249{
250 struct vivid_dev *dev = vb2_get_drv_priv(q: vb->vb2_queue);
251
252 v4l2_ctrl_request_complete(req: vb->req_obj.req, parent: &dev->ctrl_hdl_vid_cap);
253}
254
255const struct vb2_ops vivid_vid_cap_qops = {
256 .queue_setup = vid_cap_queue_setup,
257 .buf_prepare = vid_cap_buf_prepare,
258 .buf_finish = vid_cap_buf_finish,
259 .buf_queue = vid_cap_buf_queue,
260 .start_streaming = vid_cap_start_streaming,
261 .stop_streaming = vid_cap_stop_streaming,
262 .buf_request_complete = vid_cap_buf_request_complete,
263 .wait_prepare = vb2_ops_wait_prepare,
264 .wait_finish = vb2_ops_wait_finish,
265};
266
267/*
268 * Determine the 'picture' quality based on the current TV frequency: either
269 * COLOR for a good 'signal', GRAY (grayscale picture) for a slightly off
270 * signal or NOISE for no signal.
271 */
272void vivid_update_quality(struct vivid_dev *dev)
273{
274 unsigned freq_modulus;
275
276 if (dev->loop_video && (vivid_is_svid_cap(dev) || vivid_is_hdmi_cap(dev))) {
277 /*
278 * The 'noise' will only be replaced by the actual video
279 * if the output video matches the input video settings.
280 */
281 tpg_s_quality(tpg: &dev->tpg, qual: TPG_QUAL_NOISE, qual_offset: 0);
282 return;
283 }
284 if (vivid_is_hdmi_cap(dev) &&
285 VIVID_INVALID_SIGNAL(dev->dv_timings_signal_mode[dev->input])) {
286 tpg_s_quality(tpg: &dev->tpg, qual: TPG_QUAL_NOISE, qual_offset: 0);
287 return;
288 }
289 if (vivid_is_sdtv_cap(dev) &&
290 VIVID_INVALID_SIGNAL(dev->std_signal_mode[dev->input])) {
291 tpg_s_quality(tpg: &dev->tpg, qual: TPG_QUAL_NOISE, qual_offset: 0);
292 return;
293 }
294 if (!vivid_is_tv_cap(dev)) {
295 tpg_s_quality(tpg: &dev->tpg, qual: TPG_QUAL_COLOR, qual_offset: 0);
296 return;
297 }
298
299 /*
300 * There is a fake channel every 6 MHz at 49.25, 55.25, etc.
301 * From +/- 0.25 MHz around the channel there is color, and from
302 * +/- 1 MHz there is grayscale (chroma is lost).
303 * Everywhere else it is just noise.
304 */
305 freq_modulus = (dev->tv_freq - 676 /* (43.25-1) * 16 */) % (6 * 16);
306 if (freq_modulus > 2 * 16) {
307 tpg_s_quality(tpg: &dev->tpg, qual: TPG_QUAL_NOISE,
308 qual_offset: next_pseudo_random32(seed: dev->tv_freq ^ 0x55) & 0x3f);
309 return;
310 }
311 if (freq_modulus < 12 /*0.75 * 16*/ || freq_modulus > 20 /*1.25 * 16*/)
312 tpg_s_quality(tpg: &dev->tpg, qual: TPG_QUAL_GRAY, qual_offset: 0);
313 else
314 tpg_s_quality(tpg: &dev->tpg, qual: TPG_QUAL_COLOR, qual_offset: 0);
315}
316
317/*
318 * Get the current picture quality and the associated afc value.
319 */
320static enum tpg_quality vivid_get_quality(struct vivid_dev *dev, s32 *afc)
321{
322 unsigned freq_modulus;
323
324 if (afc)
325 *afc = 0;
326 if (tpg_g_quality(tpg: &dev->tpg) == TPG_QUAL_COLOR ||
327 tpg_g_quality(tpg: &dev->tpg) == TPG_QUAL_NOISE)
328 return tpg_g_quality(tpg: &dev->tpg);
329
330 /*
331 * There is a fake channel every 6 MHz at 49.25, 55.25, etc.
332 * From +/- 0.25 MHz around the channel there is color, and from
333 * +/- 1 MHz there is grayscale (chroma is lost).
334 * Everywhere else it is just gray.
335 */
336 freq_modulus = (dev->tv_freq - 676 /* (43.25-1) * 16 */) % (6 * 16);
337 if (afc)
338 *afc = freq_modulus - 1 * 16;
339 return TPG_QUAL_GRAY;
340}
341
342enum tpg_video_aspect vivid_get_video_aspect(const struct vivid_dev *dev)
343{
344 if (vivid_is_sdtv_cap(dev))
345 return dev->std_aspect_ratio[dev->input];
346
347 if (vivid_is_hdmi_cap(dev))
348 return dev->dv_timings_aspect_ratio[dev->input];
349
350 return TPG_VIDEO_ASPECT_IMAGE;
351}
352
353static enum tpg_pixel_aspect vivid_get_pixel_aspect(const struct vivid_dev *dev)
354{
355 if (vivid_is_sdtv_cap(dev))
356 return (dev->std_cap[dev->input] & V4L2_STD_525_60) ?
357 TPG_PIXEL_ASPECT_NTSC : TPG_PIXEL_ASPECT_PAL;
358
359 if (vivid_is_hdmi_cap(dev) &&
360 dev->src_rect.width == 720 && dev->src_rect.height <= 576)
361 return dev->src_rect.height == 480 ?
362 TPG_PIXEL_ASPECT_NTSC : TPG_PIXEL_ASPECT_PAL;
363
364 return TPG_PIXEL_ASPECT_SQUARE;
365}
366
367/*
368 * Called whenever the format has to be reset which can occur when
369 * changing inputs, standard, timings, etc.
370 */
371void vivid_update_format_cap(struct vivid_dev *dev, bool keep_controls)
372{
373 struct v4l2_bt_timings *bt = &dev->dv_timings_cap[dev->input].bt;
374 u32 dims[V4L2_CTRL_MAX_DIMS] = {};
375 unsigned size;
376 u64 pixelclock;
377
378 switch (dev->input_type[dev->input]) {
379 case WEBCAM:
380 default:
381 dev->src_rect.width = webcam_sizes[dev->webcam_size_idx].width;
382 dev->src_rect.height = webcam_sizes[dev->webcam_size_idx].height;
383 dev->timeperframe_vid_cap = webcam_intervals[dev->webcam_ival_idx];
384 dev->field_cap = V4L2_FIELD_NONE;
385 tpg_s_rgb_range(tpg: &dev->tpg, rgb_range: V4L2_DV_RGB_RANGE_AUTO);
386 break;
387 case TV:
388 case SVID:
389 dev->field_cap = dev->tv_field_cap;
390 dev->src_rect.width = 720;
391 if (dev->std_cap[dev->input] & V4L2_STD_525_60) {
392 dev->src_rect.height = 480;
393 dev->timeperframe_vid_cap = (struct v4l2_fract) { 1001, 30000 };
394 dev->service_set_cap = V4L2_SLICED_CAPTION_525;
395 } else {
396 dev->src_rect.height = 576;
397 dev->timeperframe_vid_cap = (struct v4l2_fract) { 1000, 25000 };
398 dev->service_set_cap = V4L2_SLICED_WSS_625 | V4L2_SLICED_TELETEXT_B;
399 }
400 tpg_s_rgb_range(tpg: &dev->tpg, rgb_range: V4L2_DV_RGB_RANGE_AUTO);
401 break;
402 case HDMI:
403 dev->src_rect.width = bt->width;
404 dev->src_rect.height = bt->height;
405 size = V4L2_DV_BT_FRAME_WIDTH(bt) * V4L2_DV_BT_FRAME_HEIGHT(bt);
406 if (dev->reduced_fps && can_reduce_fps(bt)) {
407 pixelclock = div_u64(dividend: bt->pixelclock * 1000, divisor: 1001);
408 bt->flags |= V4L2_DV_FL_REDUCED_FPS;
409 } else {
410 pixelclock = bt->pixelclock;
411 bt->flags &= ~V4L2_DV_FL_REDUCED_FPS;
412 }
413 dev->timeperframe_vid_cap = (struct v4l2_fract) {
414 size / 100, (u32)pixelclock / 100
415 };
416 if (bt->interlaced)
417 dev->field_cap = V4L2_FIELD_ALTERNATE;
418 else
419 dev->field_cap = V4L2_FIELD_NONE;
420
421 /*
422 * We can be called from within s_ctrl, in that case we can't
423 * set/get controls. Luckily we don't need to in that case.
424 */
425 if (keep_controls || !dev->colorspace)
426 break;
427 if (bt->flags & V4L2_DV_FL_IS_CE_VIDEO) {
428 if (bt->width == 720 && bt->height <= 576)
429 v4l2_ctrl_s_ctrl(ctrl: dev->colorspace, val: VIVID_CS_170M);
430 else
431 v4l2_ctrl_s_ctrl(ctrl: dev->colorspace, val: VIVID_CS_709);
432 v4l2_ctrl_s_ctrl(ctrl: dev->real_rgb_range_cap, val: 1);
433 } else {
434 v4l2_ctrl_s_ctrl(ctrl: dev->colorspace, val: VIVID_CS_SRGB);
435 v4l2_ctrl_s_ctrl(ctrl: dev->real_rgb_range_cap, val: 0);
436 }
437 tpg_s_rgb_range(tpg: &dev->tpg, rgb_range: v4l2_ctrl_g_ctrl(ctrl: dev->rgb_range_cap));
438 break;
439 }
440 vivid_update_quality(dev);
441 tpg_reset_source(tpg: &dev->tpg, width: dev->src_rect.width, height: dev->src_rect.height, field: dev->field_cap);
442 dev->crop_cap = dev->src_rect;
443 dev->crop_bounds_cap = dev->src_rect;
444 dev->compose_cap = dev->crop_cap;
445 if (V4L2_FIELD_HAS_T_OR_B(dev->field_cap))
446 dev->compose_cap.height /= 2;
447 dev->fmt_cap_rect = dev->compose_cap;
448 tpg_s_video_aspect(tpg: &dev->tpg, vid_aspect: vivid_get_video_aspect(dev));
449 tpg_s_pixel_aspect(tpg: &dev->tpg, pix_aspect: vivid_get_pixel_aspect(dev));
450 tpg_update_mv_step(tpg: &dev->tpg);
451
452 /*
453 * We can be called from within s_ctrl, in that case we can't
454 * modify controls. Luckily we don't need to in that case.
455 */
456 if (keep_controls)
457 return;
458
459 dims[0] = roundup(dev->src_rect.width, PIXEL_ARRAY_DIV);
460 dims[1] = roundup(dev->src_rect.height, PIXEL_ARRAY_DIV);
461 v4l2_ctrl_modify_dimensions(ctrl: dev->pixel_array, dims);
462}
463
464/* Map the field to something that is valid for the current input */
465static enum v4l2_field vivid_field_cap(struct vivid_dev *dev, enum v4l2_field field)
466{
467 if (vivid_is_sdtv_cap(dev)) {
468 switch (field) {
469 case V4L2_FIELD_INTERLACED_TB:
470 case V4L2_FIELD_INTERLACED_BT:
471 case V4L2_FIELD_SEQ_TB:
472 case V4L2_FIELD_SEQ_BT:
473 case V4L2_FIELD_TOP:
474 case V4L2_FIELD_BOTTOM:
475 case V4L2_FIELD_ALTERNATE:
476 return field;
477 case V4L2_FIELD_INTERLACED:
478 default:
479 return V4L2_FIELD_INTERLACED;
480 }
481 }
482 if (vivid_is_hdmi_cap(dev))
483 return dev->dv_timings_cap[dev->input].bt.interlaced ?
484 V4L2_FIELD_ALTERNATE : V4L2_FIELD_NONE;
485 return V4L2_FIELD_NONE;
486}
487
488static unsigned vivid_colorspace_cap(struct vivid_dev *dev)
489{
490 if (!dev->loop_video || vivid_is_webcam(dev) || vivid_is_tv_cap(dev))
491 return tpg_g_colorspace(tpg: &dev->tpg);
492 return dev->colorspace_out;
493}
494
495static unsigned vivid_xfer_func_cap(struct vivid_dev *dev)
496{
497 if (!dev->loop_video || vivid_is_webcam(dev) || vivid_is_tv_cap(dev))
498 return tpg_g_xfer_func(tpg: &dev->tpg);
499 return dev->xfer_func_out;
500}
501
502static unsigned vivid_ycbcr_enc_cap(struct vivid_dev *dev)
503{
504 if (!dev->loop_video || vivid_is_webcam(dev) || vivid_is_tv_cap(dev))
505 return tpg_g_ycbcr_enc(tpg: &dev->tpg);
506 return dev->ycbcr_enc_out;
507}
508
509static unsigned int vivid_hsv_enc_cap(struct vivid_dev *dev)
510{
511 if (!dev->loop_video || vivid_is_webcam(dev) || vivid_is_tv_cap(dev))
512 return tpg_g_hsv_enc(tpg: &dev->tpg);
513 return dev->hsv_enc_out;
514}
515
516static unsigned vivid_quantization_cap(struct vivid_dev *dev)
517{
518 if (!dev->loop_video || vivid_is_webcam(dev) || vivid_is_tv_cap(dev))
519 return tpg_g_quantization(tpg: &dev->tpg);
520 return dev->quantization_out;
521}
522
523int vivid_g_fmt_vid_cap(struct file *file, void *priv,
524 struct v4l2_format *f)
525{
526 struct vivid_dev *dev = video_drvdata(file);
527 struct v4l2_pix_format_mplane *mp = &f->fmt.pix_mp;
528 unsigned p;
529
530 mp->width = dev->fmt_cap_rect.width;
531 mp->height = dev->fmt_cap_rect.height;
532 mp->field = dev->field_cap;
533 mp->pixelformat = dev->fmt_cap->fourcc;
534 mp->colorspace = vivid_colorspace_cap(dev);
535 mp->xfer_func = vivid_xfer_func_cap(dev);
536 if (dev->fmt_cap->color_enc == TGP_COLOR_ENC_HSV)
537 mp->hsv_enc = vivid_hsv_enc_cap(dev);
538 else
539 mp->ycbcr_enc = vivid_ycbcr_enc_cap(dev);
540 mp->quantization = vivid_quantization_cap(dev);
541 mp->num_planes = dev->fmt_cap->buffers;
542 for (p = 0; p < mp->num_planes; p++) {
543 mp->plane_fmt[p].bytesperline = tpg_g_bytesperline(tpg: &dev->tpg, plane: p);
544 mp->plane_fmt[p].sizeimage =
545 (tpg_g_line_width(tpg: &dev->tpg, plane: p) * mp->height) /
546 dev->fmt_cap->vdownsampling[p] +
547 dev->fmt_cap->data_offset[p];
548 }
549 return 0;
550}
551
552int vivid_try_fmt_vid_cap(struct file *file, void *priv,
553 struct v4l2_format *f)
554{
555 struct v4l2_pix_format_mplane *mp = &f->fmt.pix_mp;
556 struct v4l2_plane_pix_format *pfmt = mp->plane_fmt;
557 struct vivid_dev *dev = video_drvdata(file);
558 const struct vivid_fmt *fmt;
559 unsigned bytesperline, max_bpl;
560 unsigned factor = 1;
561 unsigned w, h;
562 unsigned p;
563 bool user_set_csc = !!(mp->flags & V4L2_PIX_FMT_FLAG_SET_CSC);
564
565 fmt = vivid_get_format(dev, pixelformat: mp->pixelformat);
566 if (!fmt) {
567 dprintk(dev, 1, "Fourcc format (0x%08x) unknown.\n",
568 mp->pixelformat);
569 mp->pixelformat = V4L2_PIX_FMT_YUYV;
570 fmt = vivid_get_format(dev, pixelformat: mp->pixelformat);
571 }
572
573 mp->field = vivid_field_cap(dev, field: mp->field);
574 if (vivid_is_webcam(dev)) {
575 const struct v4l2_frmsize_discrete *sz =
576 v4l2_find_nearest_size(webcam_sizes,
577 ARRAY_SIZE(webcam_sizes), width,
578 height, mp->width, mp->height);
579
580 w = sz->width;
581 h = sz->height;
582 } else if (vivid_is_sdtv_cap(dev)) {
583 w = 720;
584 h = (dev->std_cap[dev->input] & V4L2_STD_525_60) ? 480 : 576;
585 } else {
586 w = dev->src_rect.width;
587 h = dev->src_rect.height;
588 }
589 if (V4L2_FIELD_HAS_T_OR_B(mp->field))
590 factor = 2;
591 if (vivid_is_webcam(dev) ||
592 (!dev->has_scaler_cap && !dev->has_crop_cap && !dev->has_compose_cap)) {
593 mp->width = w;
594 mp->height = h / factor;
595 } else {
596 struct v4l2_rect r = { 0, 0, mp->width, mp->height * factor };
597
598 v4l2_rect_set_min_size(r: &r, min_size: &vivid_min_rect);
599 v4l2_rect_set_max_size(r: &r, max_size: &vivid_max_rect);
600 if (dev->has_scaler_cap && !dev->has_compose_cap) {
601 struct v4l2_rect max_r = { 0, 0, MAX_ZOOM * w, MAX_ZOOM * h };
602
603 v4l2_rect_set_max_size(r: &r, max_size: &max_r);
604 } else if (!dev->has_scaler_cap && dev->has_crop_cap && !dev->has_compose_cap) {
605 v4l2_rect_set_max_size(r: &r, max_size: &dev->src_rect);
606 } else if (!dev->has_scaler_cap && !dev->has_crop_cap) {
607 v4l2_rect_set_min_size(r: &r, min_size: &dev->src_rect);
608 }
609 mp->width = r.width;
610 mp->height = r.height / factor;
611 }
612
613 /* This driver supports custom bytesperline values */
614
615 mp->num_planes = fmt->buffers;
616 for (p = 0; p < fmt->buffers; p++) {
617 /* Calculate the minimum supported bytesperline value */
618 bytesperline = (mp->width * fmt->bit_depth[p]) >> 3;
619 /* Calculate the maximum supported bytesperline value */
620 max_bpl = (MAX_ZOOM * MAX_WIDTH * fmt->bit_depth[p]) >> 3;
621
622 if (pfmt[p].bytesperline > max_bpl)
623 pfmt[p].bytesperline = max_bpl;
624 if (pfmt[p].bytesperline < bytesperline)
625 pfmt[p].bytesperline = bytesperline;
626
627 pfmt[p].sizeimage = (pfmt[p].bytesperline * mp->height) /
628 fmt->vdownsampling[p] + fmt->data_offset[p];
629
630 memset(pfmt[p].reserved, 0, sizeof(pfmt[p].reserved));
631 }
632 for (p = fmt->buffers; p < fmt->planes; p++)
633 pfmt[0].sizeimage += (pfmt[0].bytesperline * mp->height *
634 (fmt->bit_depth[p] / fmt->vdownsampling[p])) /
635 (fmt->bit_depth[0] / fmt->vdownsampling[0]);
636
637 if (!user_set_csc || !v4l2_is_colorspace_valid(colorspace: mp->colorspace))
638 mp->colorspace = vivid_colorspace_cap(dev);
639
640 if (!user_set_csc || !v4l2_is_xfer_func_valid(xfer_func: mp->xfer_func))
641 mp->xfer_func = vivid_xfer_func_cap(dev);
642
643 if (fmt->color_enc == TGP_COLOR_ENC_HSV) {
644 if (!user_set_csc || !v4l2_is_hsv_enc_valid(hsv_enc: mp->hsv_enc))
645 mp->hsv_enc = vivid_hsv_enc_cap(dev);
646 } else if (fmt->color_enc == TGP_COLOR_ENC_YCBCR) {
647 if (!user_set_csc || !v4l2_is_ycbcr_enc_valid(ycbcr_enc: mp->ycbcr_enc))
648 mp->ycbcr_enc = vivid_ycbcr_enc_cap(dev);
649 } else {
650 mp->ycbcr_enc = vivid_ycbcr_enc_cap(dev);
651 }
652
653 if (fmt->color_enc == TGP_COLOR_ENC_YCBCR ||
654 fmt->color_enc == TGP_COLOR_ENC_RGB) {
655 if (!user_set_csc || !v4l2_is_quant_valid(quantization: mp->quantization))
656 mp->quantization = vivid_quantization_cap(dev);
657 } else {
658 mp->quantization = vivid_quantization_cap(dev);
659 }
660
661 memset(mp->reserved, 0, sizeof(mp->reserved));
662 return 0;
663}
664
665int vivid_s_fmt_vid_cap(struct file *file, void *priv,
666 struct v4l2_format *f)
667{
668 struct v4l2_pix_format_mplane *mp = &f->fmt.pix_mp;
669 struct vivid_dev *dev = video_drvdata(file);
670 struct v4l2_rect *crop = &dev->crop_cap;
671 struct v4l2_rect *compose = &dev->compose_cap;
672 struct vb2_queue *q = &dev->vb_vid_cap_q;
673 int ret = vivid_try_fmt_vid_cap(file, priv, f);
674 unsigned factor = 1;
675 unsigned p;
676 unsigned i;
677
678 if (ret < 0)
679 return ret;
680
681 if (vb2_is_busy(q)) {
682 dprintk(dev, 1, "%s device busy\n", __func__);
683 return -EBUSY;
684 }
685
686 dev->fmt_cap = vivid_get_format(dev, pixelformat: mp->pixelformat);
687 if (V4L2_FIELD_HAS_T_OR_B(mp->field))
688 factor = 2;
689
690 /* Note: the webcam input doesn't support scaling, cropping or composing */
691
692 if (!vivid_is_webcam(dev) &&
693 (dev->has_scaler_cap || dev->has_crop_cap || dev->has_compose_cap)) {
694 struct v4l2_rect r = { 0, 0, mp->width, mp->height };
695
696 if (dev->has_scaler_cap) {
697 if (dev->has_compose_cap)
698 v4l2_rect_map_inside(r: compose, boundary: &r);
699 else
700 *compose = r;
701 if (dev->has_crop_cap && !dev->has_compose_cap) {
702 struct v4l2_rect min_r = {
703 0, 0,
704 r.width / MAX_ZOOM,
705 factor * r.height / MAX_ZOOM
706 };
707 struct v4l2_rect max_r = {
708 0, 0,
709 r.width * MAX_ZOOM,
710 factor * r.height * MAX_ZOOM
711 };
712
713 v4l2_rect_set_min_size(r: crop, min_size: &min_r);
714 v4l2_rect_set_max_size(r: crop, max_size: &max_r);
715 v4l2_rect_map_inside(r: crop, boundary: &dev->crop_bounds_cap);
716 } else if (dev->has_crop_cap) {
717 struct v4l2_rect min_r = {
718 0, 0,
719 compose->width / MAX_ZOOM,
720 factor * compose->height / MAX_ZOOM
721 };
722 struct v4l2_rect max_r = {
723 0, 0,
724 compose->width * MAX_ZOOM,
725 factor * compose->height * MAX_ZOOM
726 };
727
728 v4l2_rect_set_min_size(r: crop, min_size: &min_r);
729 v4l2_rect_set_max_size(r: crop, max_size: &max_r);
730 v4l2_rect_map_inside(r: crop, boundary: &dev->crop_bounds_cap);
731 }
732 } else if (dev->has_crop_cap && !dev->has_compose_cap) {
733 r.height *= factor;
734 v4l2_rect_set_size_to(r: crop, size: &r);
735 v4l2_rect_map_inside(r: crop, boundary: &dev->crop_bounds_cap);
736 r = *crop;
737 r.height /= factor;
738 v4l2_rect_set_size_to(r: compose, size: &r);
739 } else if (!dev->has_crop_cap) {
740 v4l2_rect_map_inside(r: compose, boundary: &r);
741 } else {
742 r.height *= factor;
743 v4l2_rect_set_max_size(r: crop, max_size: &r);
744 v4l2_rect_map_inside(r: crop, boundary: &dev->crop_bounds_cap);
745 compose->top *= factor;
746 compose->height *= factor;
747 v4l2_rect_set_size_to(r: compose, size: crop);
748 v4l2_rect_map_inside(r: compose, boundary: &r);
749 compose->top /= factor;
750 compose->height /= factor;
751 }
752 } else if (vivid_is_webcam(dev)) {
753 unsigned int ival_sz = webcam_ival_count(dev, frmsize_idx: dev->webcam_size_idx);
754
755 /* Guaranteed to be a match */
756 for (i = 0; i < ARRAY_SIZE(webcam_sizes); i++)
757 if (webcam_sizes[i].width == mp->width &&
758 webcam_sizes[i].height == mp->height)
759 break;
760 dev->webcam_size_idx = i;
761 if (dev->webcam_ival_idx >= ival_sz)
762 dev->webcam_ival_idx = ival_sz - 1;
763 vivid_update_format_cap(dev, keep_controls: false);
764 } else {
765 struct v4l2_rect r = { 0, 0, mp->width, mp->height };
766
767 v4l2_rect_set_size_to(r: compose, size: &r);
768 r.height *= factor;
769 v4l2_rect_set_size_to(r: crop, size: &r);
770 }
771
772 dev->fmt_cap_rect.width = mp->width;
773 dev->fmt_cap_rect.height = mp->height;
774 tpg_s_buf_height(tpg: &dev->tpg, h: mp->height);
775 tpg_s_fourcc(tpg: &dev->tpg, fourcc: dev->fmt_cap->fourcc);
776 for (p = 0; p < tpg_g_buffers(tpg: &dev->tpg); p++)
777 tpg_s_bytesperline(tpg: &dev->tpg, plane: p, bpl: mp->plane_fmt[p].bytesperline);
778 dev->field_cap = mp->field;
779 if (dev->field_cap == V4L2_FIELD_ALTERNATE)
780 tpg_s_field(tpg: &dev->tpg, field: V4L2_FIELD_TOP, alternate: true);
781 else
782 tpg_s_field(tpg: &dev->tpg, field: dev->field_cap, alternate: false);
783 tpg_s_crop_compose(tpg: &dev->tpg, crop: &dev->crop_cap, compose: &dev->compose_cap);
784 if (vivid_is_sdtv_cap(dev))
785 dev->tv_field_cap = mp->field;
786 tpg_update_mv_step(tpg: &dev->tpg);
787 dev->tpg.colorspace = mp->colorspace;
788 dev->tpg.xfer_func = mp->xfer_func;
789 if (dev->fmt_cap->color_enc == TGP_COLOR_ENC_YCBCR)
790 dev->tpg.ycbcr_enc = mp->ycbcr_enc;
791 else
792 dev->tpg.hsv_enc = mp->hsv_enc;
793 dev->tpg.quantization = mp->quantization;
794
795 return 0;
796}
797
798int vidioc_g_fmt_vid_cap_mplane(struct file *file, void *priv,
799 struct v4l2_format *f)
800{
801 struct vivid_dev *dev = video_drvdata(file);
802
803 if (!dev->multiplanar)
804 return -ENOTTY;
805 return vivid_g_fmt_vid_cap(file, priv, f);
806}
807
808int vidioc_try_fmt_vid_cap_mplane(struct file *file, void *priv,
809 struct v4l2_format *f)
810{
811 struct vivid_dev *dev = video_drvdata(file);
812
813 if (!dev->multiplanar)
814 return -ENOTTY;
815 return vivid_try_fmt_vid_cap(file, priv, f);
816}
817
818int vidioc_s_fmt_vid_cap_mplane(struct file *file, void *priv,
819 struct v4l2_format *f)
820{
821 struct vivid_dev *dev = video_drvdata(file);
822
823 if (!dev->multiplanar)
824 return -ENOTTY;
825 return vivid_s_fmt_vid_cap(file, priv, f);
826}
827
828int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
829 struct v4l2_format *f)
830{
831 struct vivid_dev *dev = video_drvdata(file);
832
833 if (dev->multiplanar)
834 return -ENOTTY;
835 return fmt_sp2mp_func(file, priv, f, func: vivid_g_fmt_vid_cap);
836}
837
838int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
839 struct v4l2_format *f)
840{
841 struct vivid_dev *dev = video_drvdata(file);
842
843 if (dev->multiplanar)
844 return -ENOTTY;
845 return fmt_sp2mp_func(file, priv, f, func: vivid_try_fmt_vid_cap);
846}
847
848int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
849 struct v4l2_format *f)
850{
851 struct vivid_dev *dev = video_drvdata(file);
852
853 if (dev->multiplanar)
854 return -ENOTTY;
855 return fmt_sp2mp_func(file, priv, f, func: vivid_s_fmt_vid_cap);
856}
857
858int vivid_vid_cap_g_selection(struct file *file, void *priv,
859 struct v4l2_selection *sel)
860{
861 struct vivid_dev *dev = video_drvdata(file);
862
863 if (!dev->has_crop_cap && !dev->has_compose_cap)
864 return -ENOTTY;
865 if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
866 return -EINVAL;
867 if (vivid_is_webcam(dev))
868 return -ENODATA;
869
870 sel->r.left = sel->r.top = 0;
871 switch (sel->target) {
872 case V4L2_SEL_TGT_CROP:
873 if (!dev->has_crop_cap)
874 return -EINVAL;
875 sel->r = dev->crop_cap;
876 break;
877 case V4L2_SEL_TGT_CROP_DEFAULT:
878 case V4L2_SEL_TGT_CROP_BOUNDS:
879 if (!dev->has_crop_cap)
880 return -EINVAL;
881 sel->r = dev->src_rect;
882 break;
883 case V4L2_SEL_TGT_COMPOSE_BOUNDS:
884 if (!dev->has_compose_cap)
885 return -EINVAL;
886 sel->r = vivid_max_rect;
887 break;
888 case V4L2_SEL_TGT_COMPOSE:
889 if (!dev->has_compose_cap)
890 return -EINVAL;
891 sel->r = dev->compose_cap;
892 break;
893 case V4L2_SEL_TGT_COMPOSE_DEFAULT:
894 if (!dev->has_compose_cap)
895 return -EINVAL;
896 sel->r = dev->fmt_cap_rect;
897 break;
898 default:
899 return -EINVAL;
900 }
901 return 0;
902}
903
904int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection *s)
905{
906 struct vivid_dev *dev = video_drvdata(file);
907 struct v4l2_rect *crop = &dev->crop_cap;
908 struct v4l2_rect *compose = &dev->compose_cap;
909 unsigned factor = V4L2_FIELD_HAS_T_OR_B(dev->field_cap) ? 2 : 1;
910 int ret;
911
912 if (!dev->has_crop_cap && !dev->has_compose_cap)
913 return -ENOTTY;
914 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
915 return -EINVAL;
916 if (vivid_is_webcam(dev))
917 return -ENODATA;
918
919 switch (s->target) {
920 case V4L2_SEL_TGT_CROP:
921 if (!dev->has_crop_cap)
922 return -EINVAL;
923 ret = vivid_vid_adjust_sel(flags: s->flags, r: &s->r);
924 if (ret)
925 return ret;
926 v4l2_rect_set_min_size(r: &s->r, min_size: &vivid_min_rect);
927 v4l2_rect_set_max_size(r: &s->r, max_size: &dev->src_rect);
928 v4l2_rect_map_inside(r: &s->r, boundary: &dev->crop_bounds_cap);
929 s->r.top /= factor;
930 s->r.height /= factor;
931 if (dev->has_scaler_cap) {
932 struct v4l2_rect fmt = dev->fmt_cap_rect;
933 struct v4l2_rect max_rect = {
934 0, 0,
935 s->r.width * MAX_ZOOM,
936 s->r.height * MAX_ZOOM
937 };
938 struct v4l2_rect min_rect = {
939 0, 0,
940 s->r.width / MAX_ZOOM,
941 s->r.height / MAX_ZOOM
942 };
943
944 v4l2_rect_set_min_size(r: &fmt, min_size: &min_rect);
945 if (!dev->has_compose_cap)
946 v4l2_rect_set_max_size(r: &fmt, max_size: &max_rect);
947 if (!v4l2_rect_same_size(r1: &dev->fmt_cap_rect, r2: &fmt) &&
948 vb2_is_busy(q: &dev->vb_vid_cap_q))
949 return -EBUSY;
950 if (dev->has_compose_cap) {
951 v4l2_rect_set_min_size(r: compose, min_size: &min_rect);
952 v4l2_rect_set_max_size(r: compose, max_size: &max_rect);
953 v4l2_rect_map_inside(r: compose, boundary: &fmt);
954 }
955 dev->fmt_cap_rect = fmt;
956 tpg_s_buf_height(tpg: &dev->tpg, h: fmt.height);
957 } else if (dev->has_compose_cap) {
958 struct v4l2_rect fmt = dev->fmt_cap_rect;
959
960 v4l2_rect_set_min_size(r: &fmt, min_size: &s->r);
961 if (!v4l2_rect_same_size(r1: &dev->fmt_cap_rect, r2: &fmt) &&
962 vb2_is_busy(q: &dev->vb_vid_cap_q))
963 return -EBUSY;
964 dev->fmt_cap_rect = fmt;
965 tpg_s_buf_height(tpg: &dev->tpg, h: fmt.height);
966 v4l2_rect_set_size_to(r: compose, size: &s->r);
967 v4l2_rect_map_inside(r: compose, boundary: &dev->fmt_cap_rect);
968 } else {
969 if (!v4l2_rect_same_size(r1: &s->r, r2: &dev->fmt_cap_rect) &&
970 vb2_is_busy(q: &dev->vb_vid_cap_q))
971 return -EBUSY;
972 v4l2_rect_set_size_to(r: &dev->fmt_cap_rect, size: &s->r);
973 v4l2_rect_set_size_to(r: compose, size: &s->r);
974 v4l2_rect_map_inside(r: compose, boundary: &dev->fmt_cap_rect);
975 tpg_s_buf_height(tpg: &dev->tpg, h: dev->fmt_cap_rect.height);
976 }
977 s->r.top *= factor;
978 s->r.height *= factor;
979 *crop = s->r;
980 break;
981 case V4L2_SEL_TGT_COMPOSE:
982 if (!dev->has_compose_cap)
983 return -EINVAL;
984 ret = vivid_vid_adjust_sel(flags: s->flags, r: &s->r);
985 if (ret)
986 return ret;
987 v4l2_rect_set_min_size(r: &s->r, min_size: &vivid_min_rect);
988 v4l2_rect_set_max_size(r: &s->r, max_size: &dev->fmt_cap_rect);
989 if (dev->has_scaler_cap) {
990 struct v4l2_rect max_rect = {
991 0, 0,
992 dev->src_rect.width * MAX_ZOOM,
993 (dev->src_rect.height / factor) * MAX_ZOOM
994 };
995
996 v4l2_rect_set_max_size(r: &s->r, max_size: &max_rect);
997 if (dev->has_crop_cap) {
998 struct v4l2_rect min_rect = {
999 0, 0,
1000 s->r.width / MAX_ZOOM,
1001 (s->r.height * factor) / MAX_ZOOM
1002 };
1003 struct v4l2_rect max_rect = {
1004 0, 0,
1005 s->r.width * MAX_ZOOM,
1006 (s->r.height * factor) * MAX_ZOOM
1007 };
1008
1009 v4l2_rect_set_min_size(r: crop, min_size: &min_rect);
1010 v4l2_rect_set_max_size(r: crop, max_size: &max_rect);
1011 v4l2_rect_map_inside(r: crop, boundary: &dev->crop_bounds_cap);
1012 }
1013 } else if (dev->has_crop_cap) {
1014 s->r.top *= factor;
1015 s->r.height *= factor;
1016 v4l2_rect_set_max_size(r: &s->r, max_size: &dev->src_rect);
1017 v4l2_rect_set_size_to(r: crop, size: &s->r);
1018 v4l2_rect_map_inside(r: crop, boundary: &dev->crop_bounds_cap);
1019 s->r.top /= factor;
1020 s->r.height /= factor;
1021 } else {
1022 v4l2_rect_set_size_to(r: &s->r, size: &dev->src_rect);
1023 s->r.height /= factor;
1024 }
1025 v4l2_rect_map_inside(r: &s->r, boundary: &dev->fmt_cap_rect);
1026 *compose = s->r;
1027 break;
1028 default:
1029 return -EINVAL;
1030 }
1031
1032 tpg_s_crop_compose(tpg: &dev->tpg, crop, compose);
1033 return 0;
1034}
1035
1036int vivid_vid_cap_g_pixelaspect(struct file *file, void *priv,
1037 int type, struct v4l2_fract *f)
1038{
1039 struct vivid_dev *dev = video_drvdata(file);
1040
1041 if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1042 return -EINVAL;
1043
1044 switch (vivid_get_pixel_aspect(dev)) {
1045 case TPG_PIXEL_ASPECT_NTSC:
1046 f->numerator = 11;
1047 f->denominator = 10;
1048 break;
1049 case TPG_PIXEL_ASPECT_PAL:
1050 f->numerator = 54;
1051 f->denominator = 59;
1052 break;
1053 default:
1054 break;
1055 }
1056 return 0;
1057}
1058
1059static const struct v4l2_audio vivid_audio_inputs[] = {
1060 { 0, "TV", V4L2_AUDCAP_STEREO },
1061 { 1, "Line-In", V4L2_AUDCAP_STEREO },
1062};
1063
1064int vidioc_enum_input(struct file *file, void *priv,
1065 struct v4l2_input *inp)
1066{
1067 struct vivid_dev *dev = video_drvdata(file);
1068
1069 if (inp->index >= dev->num_inputs)
1070 return -EINVAL;
1071
1072 inp->type = V4L2_INPUT_TYPE_CAMERA;
1073 switch (dev->input_type[inp->index]) {
1074 case WEBCAM:
1075 snprintf(buf: inp->name, size: sizeof(inp->name), fmt: "Webcam %u",
1076 dev->input_name_counter[inp->index]);
1077 inp->capabilities = 0;
1078 break;
1079 case TV:
1080 snprintf(buf: inp->name, size: sizeof(inp->name), fmt: "TV %u",
1081 dev->input_name_counter[inp->index]);
1082 inp->type = V4L2_INPUT_TYPE_TUNER;
1083 inp->std = V4L2_STD_ALL;
1084 if (dev->has_audio_inputs)
1085 inp->audioset = (1 << ARRAY_SIZE(vivid_audio_inputs)) - 1;
1086 inp->capabilities = V4L2_IN_CAP_STD;
1087 break;
1088 case SVID:
1089 snprintf(buf: inp->name, size: sizeof(inp->name), fmt: "S-Video %u",
1090 dev->input_name_counter[inp->index]);
1091 inp->std = V4L2_STD_ALL;
1092 if (dev->has_audio_inputs)
1093 inp->audioset = (1 << ARRAY_SIZE(vivid_audio_inputs)) - 1;
1094 inp->capabilities = V4L2_IN_CAP_STD;
1095 break;
1096 case HDMI:
1097 snprintf(buf: inp->name, size: sizeof(inp->name), fmt: "HDMI %u",
1098 dev->input_name_counter[inp->index]);
1099 inp->capabilities = V4L2_IN_CAP_DV_TIMINGS;
1100 if (dev->edid_blocks == 0 ||
1101 dev->dv_timings_signal_mode[dev->input] == NO_SIGNAL)
1102 inp->status |= V4L2_IN_ST_NO_SIGNAL;
1103 else if (dev->dv_timings_signal_mode[dev->input] == NO_LOCK ||
1104 dev->dv_timings_signal_mode[dev->input] == OUT_OF_RANGE)
1105 inp->status |= V4L2_IN_ST_NO_H_LOCK;
1106 break;
1107 }
1108 if (dev->sensor_hflip)
1109 inp->status |= V4L2_IN_ST_HFLIP;
1110 if (dev->sensor_vflip)
1111 inp->status |= V4L2_IN_ST_VFLIP;
1112 if (dev->input == inp->index && vivid_is_sdtv_cap(dev)) {
1113 if (dev->std_signal_mode[dev->input] == NO_SIGNAL) {
1114 inp->status |= V4L2_IN_ST_NO_SIGNAL;
1115 } else if (dev->std_signal_mode[dev->input] == NO_LOCK) {
1116 inp->status |= V4L2_IN_ST_NO_H_LOCK;
1117 } else if (vivid_is_tv_cap(dev)) {
1118 switch (tpg_g_quality(tpg: &dev->tpg)) {
1119 case TPG_QUAL_GRAY:
1120 inp->status |= V4L2_IN_ST_COLOR_KILL;
1121 break;
1122 case TPG_QUAL_NOISE:
1123 inp->status |= V4L2_IN_ST_NO_H_LOCK;
1124 break;
1125 default:
1126 break;
1127 }
1128 }
1129 }
1130 return 0;
1131}
1132
1133int vidioc_g_input(struct file *file, void *priv, unsigned *i)
1134{
1135 struct vivid_dev *dev = video_drvdata(file);
1136
1137 *i = dev->input;
1138 return 0;
1139}
1140
1141int vidioc_s_input(struct file *file, void *priv, unsigned i)
1142{
1143 struct vivid_dev *dev = video_drvdata(file);
1144 struct v4l2_bt_timings *bt = &dev->dv_timings_cap[dev->input].bt;
1145 unsigned brightness;
1146
1147 if (i >= dev->num_inputs)
1148 return -EINVAL;
1149
1150 if (i == dev->input)
1151 return 0;
1152
1153 if (vb2_is_busy(q: &dev->vb_vid_cap_q) ||
1154 vb2_is_busy(q: &dev->vb_vbi_cap_q) ||
1155 vb2_is_busy(q: &dev->vb_meta_cap_q))
1156 return -EBUSY;
1157
1158 dev->input = i;
1159 dev->vid_cap_dev.tvnorms = 0;
1160 if (dev->input_type[i] == TV || dev->input_type[i] == SVID) {
1161 dev->tv_audio_input = (dev->input_type[i] == TV) ? 0 : 1;
1162 dev->vid_cap_dev.tvnorms = V4L2_STD_ALL;
1163 }
1164 dev->vbi_cap_dev.tvnorms = dev->vid_cap_dev.tvnorms;
1165 dev->meta_cap_dev.tvnorms = dev->vid_cap_dev.tvnorms;
1166 vivid_update_format_cap(dev, keep_controls: false);
1167
1168 if (dev->colorspace) {
1169 switch (dev->input_type[i]) {
1170 case WEBCAM:
1171 v4l2_ctrl_s_ctrl(ctrl: dev->colorspace, val: VIVID_CS_SRGB);
1172 break;
1173 case TV:
1174 case SVID:
1175 v4l2_ctrl_s_ctrl(ctrl: dev->colorspace, val: VIVID_CS_170M);
1176 break;
1177 case HDMI:
1178 if (bt->flags & V4L2_DV_FL_IS_CE_VIDEO) {
1179 if (dev->src_rect.width == 720 && dev->src_rect.height <= 576)
1180 v4l2_ctrl_s_ctrl(ctrl: dev->colorspace, val: VIVID_CS_170M);
1181 else
1182 v4l2_ctrl_s_ctrl(ctrl: dev->colorspace, val: VIVID_CS_709);
1183 } else {
1184 v4l2_ctrl_s_ctrl(ctrl: dev->colorspace, val: VIVID_CS_SRGB);
1185 }
1186 break;
1187 }
1188 }
1189
1190 /*
1191 * Modify the brightness range depending on the input.
1192 * This makes it easy to use vivid to test if applications can
1193 * handle control range modifications and is also how this is
1194 * typically used in practice as different inputs may be hooked
1195 * up to different receivers with different control ranges.
1196 */
1197 brightness = 128 * i + dev->input_brightness[i];
1198 v4l2_ctrl_modify_range(ctrl: dev->brightness,
1199 min: 128 * i, max: 255 + 128 * i, step: 1, def: 128 + 128 * i);
1200 v4l2_ctrl_s_ctrl(ctrl: dev->brightness, val: brightness);
1201
1202 /* Restore per-input states. */
1203 v4l2_ctrl_activate(ctrl: dev->ctrl_dv_timings_signal_mode,
1204 active: vivid_is_hdmi_cap(dev));
1205 v4l2_ctrl_activate(ctrl: dev->ctrl_dv_timings, active: vivid_is_hdmi_cap(dev) &&
1206 dev->dv_timings_signal_mode[dev->input] ==
1207 SELECTED_DV_TIMINGS);
1208 v4l2_ctrl_activate(ctrl: dev->ctrl_std_signal_mode, active: vivid_is_sdtv_cap(dev));
1209 v4l2_ctrl_activate(ctrl: dev->ctrl_standard, active: vivid_is_sdtv_cap(dev) &&
1210 dev->std_signal_mode[dev->input]);
1211
1212 if (vivid_is_hdmi_cap(dev)) {
1213 v4l2_ctrl_s_ctrl(ctrl: dev->ctrl_dv_timings_signal_mode,
1214 val: dev->dv_timings_signal_mode[dev->input]);
1215 v4l2_ctrl_s_ctrl(ctrl: dev->ctrl_dv_timings,
1216 val: dev->query_dv_timings[dev->input]);
1217 } else if (vivid_is_sdtv_cap(dev)) {
1218 v4l2_ctrl_s_ctrl(ctrl: dev->ctrl_std_signal_mode,
1219 val: dev->std_signal_mode[dev->input]);
1220 v4l2_ctrl_s_ctrl(ctrl: dev->ctrl_standard,
1221 val: dev->std_signal_mode[dev->input]);
1222 }
1223
1224 return 0;
1225}
1226
1227int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin)
1228{
1229 if (vin->index >= ARRAY_SIZE(vivid_audio_inputs))
1230 return -EINVAL;
1231 *vin = vivid_audio_inputs[vin->index];
1232 return 0;
1233}
1234
1235int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *vin)
1236{
1237 struct vivid_dev *dev = video_drvdata(file);
1238
1239 if (!vivid_is_sdtv_cap(dev))
1240 return -EINVAL;
1241 *vin = vivid_audio_inputs[dev->tv_audio_input];
1242 return 0;
1243}
1244
1245int vidioc_s_audio(struct file *file, void *fh, const struct v4l2_audio *vin)
1246{
1247 struct vivid_dev *dev = video_drvdata(file);
1248
1249 if (!vivid_is_sdtv_cap(dev))
1250 return -EINVAL;
1251 if (vin->index >= ARRAY_SIZE(vivid_audio_inputs))
1252 return -EINVAL;
1253 dev->tv_audio_input = vin->index;
1254 return 0;
1255}
1256
1257int vivid_video_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
1258{
1259 struct vivid_dev *dev = video_drvdata(file);
1260
1261 if (vf->tuner != 0)
1262 return -EINVAL;
1263 vf->frequency = dev->tv_freq;
1264 return 0;
1265}
1266
1267int vivid_video_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *vf)
1268{
1269 struct vivid_dev *dev = video_drvdata(file);
1270
1271 if (vf->tuner != 0)
1272 return -EINVAL;
1273 dev->tv_freq = clamp_t(unsigned, vf->frequency, MIN_TV_FREQ, MAX_TV_FREQ);
1274 if (vivid_is_tv_cap(dev))
1275 vivid_update_quality(dev);
1276 return 0;
1277}
1278
1279int vivid_video_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *vt)
1280{
1281 struct vivid_dev *dev = video_drvdata(file);
1282
1283 if (vt->index != 0)
1284 return -EINVAL;
1285 if (vt->audmode > V4L2_TUNER_MODE_LANG1_LANG2)
1286 return -EINVAL;
1287 dev->tv_audmode = vt->audmode;
1288 return 0;
1289}
1290
1291int vivid_video_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
1292{
1293 struct vivid_dev *dev = video_drvdata(file);
1294 enum tpg_quality qual;
1295
1296 if (vt->index != 0)
1297 return -EINVAL;
1298
1299 vt->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
1300 V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
1301 vt->audmode = dev->tv_audmode;
1302 vt->rangelow = MIN_TV_FREQ;
1303 vt->rangehigh = MAX_TV_FREQ;
1304 qual = vivid_get_quality(dev, afc: &vt->afc);
1305 if (qual == TPG_QUAL_COLOR)
1306 vt->signal = 0xffff;
1307 else if (qual == TPG_QUAL_GRAY)
1308 vt->signal = 0x8000;
1309 else
1310 vt->signal = 0;
1311 if (qual == TPG_QUAL_NOISE) {
1312 vt->rxsubchans = 0;
1313 } else if (qual == TPG_QUAL_GRAY) {
1314 vt->rxsubchans = V4L2_TUNER_SUB_MONO;
1315 } else {
1316 unsigned int channel_nr = dev->tv_freq / (6 * 16);
1317 unsigned int options =
1318 (dev->std_cap[dev->input] & V4L2_STD_NTSC_M) ? 4 : 3;
1319
1320 switch (channel_nr % options) {
1321 case 0:
1322 vt->rxsubchans = V4L2_TUNER_SUB_MONO;
1323 break;
1324 case 1:
1325 vt->rxsubchans = V4L2_TUNER_SUB_STEREO;
1326 break;
1327 case 2:
1328 if (dev->std_cap[dev->input] & V4L2_STD_NTSC_M)
1329 vt->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_SAP;
1330 else
1331 vt->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
1332 break;
1333 case 3:
1334 vt->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_SAP;
1335 break;
1336 }
1337 }
1338 strscpy(vt->name, "TV Tuner", sizeof(vt->name));
1339 return 0;
1340}
1341
1342/* Must remain in sync with the vivid_ctrl_standard_strings array */
1343const v4l2_std_id vivid_standard[] = {
1344 V4L2_STD_NTSC_M,
1345 V4L2_STD_NTSC_M_JP,
1346 V4L2_STD_NTSC_M_KR,
1347 V4L2_STD_NTSC_443,
1348 V4L2_STD_PAL_BG | V4L2_STD_PAL_H,
1349 V4L2_STD_PAL_I,
1350 V4L2_STD_PAL_DK,
1351 V4L2_STD_PAL_M,
1352 V4L2_STD_PAL_N,
1353 V4L2_STD_PAL_Nc,
1354 V4L2_STD_PAL_60,
1355 V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H,
1356 V4L2_STD_SECAM_DK,
1357 V4L2_STD_SECAM_L,
1358 V4L2_STD_SECAM_LC,
1359 V4L2_STD_UNKNOWN
1360};
1361
1362/* Must remain in sync with the vivid_standard array */
1363const char * const vivid_ctrl_standard_strings[] = {
1364 "NTSC-M",
1365 "NTSC-M-JP",
1366 "NTSC-M-KR",
1367 "NTSC-443",
1368 "PAL-BGH",
1369 "PAL-I",
1370 "PAL-DK",
1371 "PAL-M",
1372 "PAL-N",
1373 "PAL-Nc",
1374 "PAL-60",
1375 "SECAM-BGH",
1376 "SECAM-DK",
1377 "SECAM-L",
1378 "SECAM-Lc",
1379 NULL,
1380};
1381
1382int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *id)
1383{
1384 struct vivid_dev *dev = video_drvdata(file);
1385 unsigned int last = dev->query_std_last[dev->input];
1386
1387 if (!vivid_is_sdtv_cap(dev))
1388 return -ENODATA;
1389 if (dev->std_signal_mode[dev->input] == NO_SIGNAL ||
1390 dev->std_signal_mode[dev->input] == NO_LOCK) {
1391 *id = V4L2_STD_UNKNOWN;
1392 return 0;
1393 }
1394 if (vivid_is_tv_cap(dev) && tpg_g_quality(tpg: &dev->tpg) == TPG_QUAL_NOISE) {
1395 *id = V4L2_STD_UNKNOWN;
1396 } else if (dev->std_signal_mode[dev->input] == CURRENT_STD) {
1397 *id = dev->std_cap[dev->input];
1398 } else if (dev->std_signal_mode[dev->input] == SELECTED_STD) {
1399 *id = dev->query_std[dev->input];
1400 } else {
1401 *id = vivid_standard[last];
1402 dev->query_std_last[dev->input] =
1403 (last + 1) % ARRAY_SIZE(vivid_standard);
1404 }
1405
1406 return 0;
1407}
1408
1409int vivid_vid_cap_s_std(struct file *file, void *priv, v4l2_std_id id)
1410{
1411 struct vivid_dev *dev = video_drvdata(file);
1412
1413 if (!vivid_is_sdtv_cap(dev))
1414 return -ENODATA;
1415 if (dev->std_cap[dev->input] == id)
1416 return 0;
1417 if (vb2_is_busy(q: &dev->vb_vid_cap_q) || vb2_is_busy(q: &dev->vb_vbi_cap_q))
1418 return -EBUSY;
1419 dev->std_cap[dev->input] = id;
1420 vivid_update_format_cap(dev, keep_controls: false);
1421 return 0;
1422}
1423
1424static void find_aspect_ratio(u32 width, u32 height,
1425 u32 *num, u32 *denom)
1426{
1427 if (!(height % 3) && ((height * 4 / 3) == width)) {
1428 *num = 4;
1429 *denom = 3;
1430 } else if (!(height % 9) && ((height * 16 / 9) == width)) {
1431 *num = 16;
1432 *denom = 9;
1433 } else if (!(height % 10) && ((height * 16 / 10) == width)) {
1434 *num = 16;
1435 *denom = 10;
1436 } else if (!(height % 4) && ((height * 5 / 4) == width)) {
1437 *num = 5;
1438 *denom = 4;
1439 } else if (!(height % 9) && ((height * 15 / 9) == width)) {
1440 *num = 15;
1441 *denom = 9;
1442 } else { /* default to 16:9 */
1443 *num = 16;
1444 *denom = 9;
1445 }
1446}
1447
1448static bool valid_cvt_gtf_timings(struct v4l2_dv_timings *timings)
1449{
1450 struct v4l2_bt_timings *bt = &timings->bt;
1451 u32 total_h_pixel;
1452 u32 total_v_lines;
1453 u32 h_freq;
1454
1455 if (!v4l2_valid_dv_timings(t: timings, cap: &vivid_dv_timings_cap,
1456 NULL, NULL))
1457 return false;
1458
1459 total_h_pixel = V4L2_DV_BT_FRAME_WIDTH(bt);
1460 total_v_lines = V4L2_DV_BT_FRAME_HEIGHT(bt);
1461
1462 h_freq = (u32)bt->pixelclock / total_h_pixel;
1463
1464 if (bt->standards == 0 || (bt->standards & V4L2_DV_BT_STD_CVT)) {
1465 if (v4l2_detect_cvt(frame_height: total_v_lines, hfreq: h_freq, vsync: bt->vsync, active_width: bt->width,
1466 polarities: bt->polarities, interlaced: bt->interlaced, fmt: timings))
1467 return true;
1468 }
1469
1470 if (bt->standards == 0 || (bt->standards & V4L2_DV_BT_STD_GTF)) {
1471 struct v4l2_fract aspect_ratio;
1472
1473 find_aspect_ratio(width: bt->width, height: bt->height,
1474 num: &aspect_ratio.numerator,
1475 denom: &aspect_ratio.denominator);
1476 if (v4l2_detect_gtf(frame_height: total_v_lines, hfreq: h_freq, vsync: bt->vsync,
1477 polarities: bt->polarities, interlaced: bt->interlaced,
1478 aspect: aspect_ratio, fmt: timings))
1479 return true;
1480 }
1481 return false;
1482}
1483
1484int vivid_vid_cap_s_dv_timings(struct file *file, void *_fh,
1485 struct v4l2_dv_timings *timings)
1486{
1487 struct vivid_dev *dev = video_drvdata(file);
1488
1489 if (!vivid_is_hdmi_cap(dev))
1490 return -ENODATA;
1491 if (!v4l2_find_dv_timings_cap(t: timings, cap: &vivid_dv_timings_cap,
1492 pclock_delta: 0, NULL, NULL) &&
1493 !valid_cvt_gtf_timings(timings))
1494 return -EINVAL;
1495
1496 if (v4l2_match_dv_timings(measured: timings, standard: &dev->dv_timings_cap[dev->input],
1497 pclock_delta: 0, match_reduced_fps: false))
1498 return 0;
1499 if (vb2_is_busy(q: &dev->vb_vid_cap_q))
1500 return -EBUSY;
1501
1502 dev->dv_timings_cap[dev->input] = *timings;
1503 vivid_update_format_cap(dev, keep_controls: false);
1504 return 0;
1505}
1506
1507int vidioc_query_dv_timings(struct file *file, void *_fh,
1508 struct v4l2_dv_timings *timings)
1509{
1510 struct vivid_dev *dev = video_drvdata(file);
1511 unsigned int input = dev->input;
1512 unsigned int last = dev->query_dv_timings_last[input];
1513
1514 if (!vivid_is_hdmi_cap(dev))
1515 return -ENODATA;
1516 if (dev->dv_timings_signal_mode[input] == NO_SIGNAL ||
1517 dev->edid_blocks == 0)
1518 return -ENOLINK;
1519 if (dev->dv_timings_signal_mode[input] == NO_LOCK)
1520 return -ENOLCK;
1521 if (dev->dv_timings_signal_mode[input] == OUT_OF_RANGE) {
1522 timings->bt.pixelclock = vivid_dv_timings_cap.bt.max_pixelclock * 2;
1523 return -ERANGE;
1524 }
1525 if (dev->dv_timings_signal_mode[input] == CURRENT_DV_TIMINGS) {
1526 *timings = dev->dv_timings_cap[input];
1527 } else if (dev->dv_timings_signal_mode[input] ==
1528 SELECTED_DV_TIMINGS) {
1529 *timings =
1530 v4l2_dv_timings_presets[dev->query_dv_timings[input]];
1531 } else {
1532 *timings =
1533 v4l2_dv_timings_presets[last];
1534 dev->query_dv_timings_last[input] =
1535 (last + 1) % dev->query_dv_timings_size;
1536 }
1537 return 0;
1538}
1539
1540int vidioc_s_edid(struct file *file, void *_fh,
1541 struct v4l2_edid *edid)
1542{
1543 struct vivid_dev *dev = video_drvdata(file);
1544 u16 phys_addr;
1545 u32 display_present = 0;
1546 unsigned int i, j;
1547 int ret;
1548
1549 memset(edid->reserved, 0, sizeof(edid->reserved));
1550 if (edid->pad >= dev->num_inputs)
1551 return -EINVAL;
1552 if (dev->input_type[edid->pad] != HDMI || edid->start_block)
1553 return -EINVAL;
1554 if (edid->blocks == 0) {
1555 dev->edid_blocks = 0;
1556 v4l2_ctrl_s_ctrl(ctrl: dev->ctrl_tx_edid_present, val: 0);
1557 v4l2_ctrl_s_ctrl(ctrl: dev->ctrl_tx_hotplug, val: 0);
1558 phys_addr = CEC_PHYS_ADDR_INVALID;
1559 goto set_phys_addr;
1560 }
1561 if (edid->blocks > dev->edid_max_blocks) {
1562 edid->blocks = dev->edid_max_blocks;
1563 return -E2BIG;
1564 }
1565 phys_addr = cec_get_edid_phys_addr(edid: edid->edid, size: edid->blocks * 128, NULL);
1566 ret = v4l2_phys_addr_validate(phys_addr, parent: &phys_addr, NULL);
1567 if (ret)
1568 return ret;
1569
1570 if (vb2_is_busy(q: &dev->vb_vid_cap_q))
1571 return -EBUSY;
1572
1573 dev->edid_blocks = edid->blocks;
1574 memcpy(dev->edid, edid->edid, edid->blocks * 128);
1575
1576 for (i = 0, j = 0; i < dev->num_outputs; i++)
1577 if (dev->output_type[i] == HDMI)
1578 display_present |=
1579 dev->display_present[i] << j++;
1580
1581 v4l2_ctrl_s_ctrl(ctrl: dev->ctrl_tx_edid_present, val: display_present);
1582 v4l2_ctrl_s_ctrl(ctrl: dev->ctrl_tx_hotplug, val: display_present);
1583
1584set_phys_addr:
1585 /* TODO: a proper hotplug detect cycle should be emulated here */
1586 cec_s_phys_addr(adap: dev->cec_rx_adap, phys_addr, block: false);
1587
1588 for (i = 0; i < MAX_OUTPUTS && dev->cec_tx_adap[i]; i++)
1589 cec_s_phys_addr(adap: dev->cec_tx_adap[i],
1590 phys_addr: dev->display_present[i] ?
1591 v4l2_phys_addr_for_input(phys_addr, input: i + 1) :
1592 CEC_PHYS_ADDR_INVALID,
1593 block: false);
1594 return 0;
1595}
1596
1597int vidioc_enum_framesizes(struct file *file, void *fh,
1598 struct v4l2_frmsizeenum *fsize)
1599{
1600 struct vivid_dev *dev = video_drvdata(file);
1601
1602 if (!vivid_is_webcam(dev) && !dev->has_scaler_cap)
1603 return -EINVAL;
1604 if (vivid_get_format(dev, pixelformat: fsize->pixel_format) == NULL)
1605 return -EINVAL;
1606 if (vivid_is_webcam(dev)) {
1607 if (fsize->index >= ARRAY_SIZE(webcam_sizes))
1608 return -EINVAL;
1609 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
1610 fsize->discrete = webcam_sizes[fsize->index];
1611 return 0;
1612 }
1613 if (fsize->index)
1614 return -EINVAL;
1615 fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
1616 fsize->stepwise.min_width = MIN_WIDTH;
1617 fsize->stepwise.max_width = MAX_WIDTH * MAX_ZOOM;
1618 fsize->stepwise.step_width = 2;
1619 fsize->stepwise.min_height = MIN_HEIGHT;
1620 fsize->stepwise.max_height = MAX_HEIGHT * MAX_ZOOM;
1621 fsize->stepwise.step_height = 2;
1622 return 0;
1623}
1624
1625/* timeperframe is arbitrary and continuous */
1626int vidioc_enum_frameintervals(struct file *file, void *priv,
1627 struct v4l2_frmivalenum *fival)
1628{
1629 struct vivid_dev *dev = video_drvdata(file);
1630 const struct vivid_fmt *fmt;
1631 int i;
1632
1633 fmt = vivid_get_format(dev, pixelformat: fival->pixel_format);
1634 if (!fmt)
1635 return -EINVAL;
1636
1637 if (!vivid_is_webcam(dev)) {
1638 if (fival->index)
1639 return -EINVAL;
1640 if (fival->width < MIN_WIDTH || fival->width > MAX_WIDTH * MAX_ZOOM)
1641 return -EINVAL;
1642 if (fival->height < MIN_HEIGHT || fival->height > MAX_HEIGHT * MAX_ZOOM)
1643 return -EINVAL;
1644 fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
1645 fival->discrete = dev->timeperframe_vid_cap;
1646 return 0;
1647 }
1648
1649 for (i = 0; i < ARRAY_SIZE(webcam_sizes); i++)
1650 if (fival->width == webcam_sizes[i].width &&
1651 fival->height == webcam_sizes[i].height)
1652 break;
1653 if (i == ARRAY_SIZE(webcam_sizes))
1654 return -EINVAL;
1655 if (fival->index >= webcam_ival_count(dev, frmsize_idx: i))
1656 return -EINVAL;
1657 fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
1658 fival->discrete = webcam_intervals[fival->index];
1659 return 0;
1660}
1661
1662int vivid_vid_cap_g_parm(struct file *file, void *priv,
1663 struct v4l2_streamparm *parm)
1664{
1665 struct vivid_dev *dev = video_drvdata(file);
1666
1667 if (parm->type != (dev->multiplanar ?
1668 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
1669 V4L2_BUF_TYPE_VIDEO_CAPTURE))
1670 return -EINVAL;
1671
1672 parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
1673 parm->parm.capture.timeperframe = dev->timeperframe_vid_cap;
1674 parm->parm.capture.readbuffers = 1;
1675 return 0;
1676}
1677
1678int vivid_vid_cap_s_parm(struct file *file, void *priv,
1679 struct v4l2_streamparm *parm)
1680{
1681 struct vivid_dev *dev = video_drvdata(file);
1682 unsigned int ival_sz = webcam_ival_count(dev, frmsize_idx: dev->webcam_size_idx);
1683 struct v4l2_fract tpf;
1684 unsigned i;
1685
1686 if (parm->type != (dev->multiplanar ?
1687 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
1688 V4L2_BUF_TYPE_VIDEO_CAPTURE))
1689 return -EINVAL;
1690 if (!vivid_is_webcam(dev))
1691 return vivid_vid_cap_g_parm(file, priv, parm);
1692
1693 tpf = parm->parm.capture.timeperframe;
1694
1695 if (tpf.denominator == 0)
1696 tpf = webcam_intervals[ival_sz - 1];
1697 for (i = 0; i < ival_sz; i++)
1698 if (V4L2_FRACT_COMPARE(tpf, >=, webcam_intervals[i]))
1699 break;
1700 if (i == ival_sz)
1701 i = ival_sz - 1;
1702 dev->webcam_ival_idx = i;
1703 tpf = webcam_intervals[dev->webcam_ival_idx];
1704
1705 /* resync the thread's timings */
1706 dev->cap_seq_resync = true;
1707 dev->timeperframe_vid_cap = tpf;
1708 parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
1709 parm->parm.capture.timeperframe = tpf;
1710 parm->parm.capture.readbuffers = 1;
1711 return 0;
1712}
1713

source code of linux/drivers/media/test-drivers/vivid/vivid-vid-cap.c