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