^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Copyright (c) 2013,2016 Lubomir Rintel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Redistribution and use in source and binary forms, with or without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * modification, are permitted provided that the following conditions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * are met:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * 1. Redistributions of source code must retain the above copyright
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * notice, this list of conditions, and the following disclaimer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * without modification.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * 2. The name of the author may not be used to endorse or promote products
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * derived from this software without specific prior written permission.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Alternatively, this software may be distributed under the terms of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * GNU General Public License ("GPL").
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * Fushicai USBTV007 Audio-Video Grabber Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * Product web site:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * http://www.fushicai.com/products_detail/&productId=d05449ee-b690-42f9-a661-aa7353894bed.html
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * Following LWN articles were very useful in construction of this driver:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * Video4Linux2 API series: http://lwn.net/Articles/203924/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * videobuf2 API explanation: http://lwn.net/Articles/447435/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * Thanks go to Jonathan Corbet for providing this quality documentation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * He is awesome.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * No physical hardware was harmed running Windows during the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * reverse-engineering activity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <media/v4l2-ioctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include <media/videobuf2-v4l2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include "usbtv.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static struct usbtv_norm_params norm_params[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) .norm = V4L2_STD_525_60,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) .cap_width = 720,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) .cap_height = 480,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) .norm = V4L2_STD_625_50,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) .cap_width = 720,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) .cap_height = 576,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^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) static int usbtv_configure_for_norm(struct usbtv *usbtv, v4l2_std_id norm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) int i, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct usbtv_norm_params *params = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) for (i = 0; i < ARRAY_SIZE(norm_params); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (norm_params[i].norm & norm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) params = &norm_params[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (params) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) usbtv->width = params->cap_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) usbtv->height = params->cap_height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) usbtv->n_chunks = usbtv->width * usbtv->height
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) / 4 / USBTV_CHUNK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) usbtv->norm = norm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static int usbtv_select_input(struct usbtv *usbtv, int input)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static const u16 composite[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) { USBTV_BASE + 0x0105, 0x0060 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) { USBTV_BASE + 0x011f, 0x00f2 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) { USBTV_BASE + 0x0127, 0x0060 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) { USBTV_BASE + 0x00ae, 0x0010 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) { USBTV_BASE + 0x0239, 0x0060 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static const u16 svideo[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) { USBTV_BASE + 0x0105, 0x0010 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) { USBTV_BASE + 0x011f, 0x00ff },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) { USBTV_BASE + 0x0127, 0x0060 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) { USBTV_BASE + 0x00ae, 0x0030 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) { USBTV_BASE + 0x0239, 0x0060 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) switch (input) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) case USBTV_COMPOSITE_INPUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) ret = usbtv_set_regs(usbtv, composite, ARRAY_SIZE(composite));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) case USBTV_SVIDEO_INPUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) ret = usbtv_set_regs(usbtv, svideo, ARRAY_SIZE(svideo));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) usbtv->input = input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static uint16_t usbtv_norm_to_16f_reg(v4l2_std_id norm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /* NTSC M/M-JP/M-KR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (norm & V4L2_STD_NTSC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return 0x00b8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /* PAL BG/DK/H/I */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (norm & V4L2_STD_PAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) return 0x00ee;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /* SECAM B/D/G/H/K/K1/L/Lc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (norm & V4L2_STD_SECAM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return 0x00ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (norm & V4L2_STD_NTSC_443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return 0x00a8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (norm & (V4L2_STD_PAL_M | V4L2_STD_PAL_60))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return 0x00bc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) /* Fallback to automatic detection for other standards */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return 0x0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static int usbtv_select_norm(struct usbtv *usbtv, v4l2_std_id norm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /* These are the series of register values used to configure the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * decoder for a specific standard.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * The first 21 register writes are copied from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * Settings\DecoderDefaults registry keys present in the Windows driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * .INF file, and control various image tuning parameters (color
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * correction, sharpness, ...).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) static const u16 pal[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /* "AVPAL" tuning sequence from .INF file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) { USBTV_BASE + 0x0003, 0x0004 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) { USBTV_BASE + 0x001a, 0x0068 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) { USBTV_BASE + 0x0100, 0x00d3 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) { USBTV_BASE + 0x010e, 0x0072 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) { USBTV_BASE + 0x010f, 0x00a2 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) { USBTV_BASE + 0x0112, 0x00b0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) { USBTV_BASE + 0x0115, 0x0015 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) { USBTV_BASE + 0x0117, 0x0001 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) { USBTV_BASE + 0x0118, 0x002c },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) { USBTV_BASE + 0x012d, 0x0010 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) { USBTV_BASE + 0x012f, 0x0020 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) { USBTV_BASE + 0x0220, 0x002e },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) { USBTV_BASE + 0x0225, 0x0008 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) { USBTV_BASE + 0x024e, 0x0002 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) { USBTV_BASE + 0x024f, 0x0002 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) { USBTV_BASE + 0x0254, 0x0059 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) { USBTV_BASE + 0x025a, 0x0016 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) { USBTV_BASE + 0x025b, 0x0035 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) { USBTV_BASE + 0x0263, 0x0017 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) { USBTV_BASE + 0x0266, 0x0016 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) { USBTV_BASE + 0x0267, 0x0036 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) /* End image tuning */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) { USBTV_BASE + 0x024e, 0x0002 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) { USBTV_BASE + 0x024f, 0x0002 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static const u16 ntsc[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) /* "AVNTSC" tuning sequence from .INF file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) { USBTV_BASE + 0x0003, 0x0004 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) { USBTV_BASE + 0x001a, 0x0079 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) { USBTV_BASE + 0x0100, 0x00d3 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) { USBTV_BASE + 0x010e, 0x0068 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) { USBTV_BASE + 0x010f, 0x009c },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) { USBTV_BASE + 0x0112, 0x00f0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) { USBTV_BASE + 0x0115, 0x0015 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) { USBTV_BASE + 0x0117, 0x0000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) { USBTV_BASE + 0x0118, 0x00fc },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) { USBTV_BASE + 0x012d, 0x0004 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) { USBTV_BASE + 0x012f, 0x0008 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) { USBTV_BASE + 0x0220, 0x002e },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) { USBTV_BASE + 0x0225, 0x0008 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) { USBTV_BASE + 0x024e, 0x0002 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) { USBTV_BASE + 0x024f, 0x0001 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) { USBTV_BASE + 0x0254, 0x005f },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) { USBTV_BASE + 0x025a, 0x0012 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) { USBTV_BASE + 0x025b, 0x0001 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) { USBTV_BASE + 0x0263, 0x001c },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) { USBTV_BASE + 0x0266, 0x0011 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) { USBTV_BASE + 0x0267, 0x0005 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) /* End image tuning */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) { USBTV_BASE + 0x024e, 0x0002 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) { USBTV_BASE + 0x024f, 0x0002 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static const u16 secam[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) /* "AVSECAM" tuning sequence from .INF file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) { USBTV_BASE + 0x0003, 0x0004 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) { USBTV_BASE + 0x001a, 0x0073 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) { USBTV_BASE + 0x0100, 0x00dc },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) { USBTV_BASE + 0x010e, 0x0072 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) { USBTV_BASE + 0x010f, 0x00a2 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) { USBTV_BASE + 0x0112, 0x0090 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) { USBTV_BASE + 0x0115, 0x0035 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) { USBTV_BASE + 0x0117, 0x0001 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) { USBTV_BASE + 0x0118, 0x0030 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) { USBTV_BASE + 0x012d, 0x0004 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) { USBTV_BASE + 0x012f, 0x0008 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) { USBTV_BASE + 0x0220, 0x002d },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) { USBTV_BASE + 0x0225, 0x0028 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) { USBTV_BASE + 0x024e, 0x0008 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) { USBTV_BASE + 0x024f, 0x0002 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) { USBTV_BASE + 0x0254, 0x0069 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) { USBTV_BASE + 0x025a, 0x0016 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) { USBTV_BASE + 0x025b, 0x0035 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) { USBTV_BASE + 0x0263, 0x0021 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) { USBTV_BASE + 0x0266, 0x0016 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) { USBTV_BASE + 0x0267, 0x0036 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) /* End image tuning */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) { USBTV_BASE + 0x024e, 0x0002 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) { USBTV_BASE + 0x024f, 0x0002 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) ret = usbtv_configure_for_norm(usbtv, norm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) /* Masks for norms using a NTSC or PAL color encoding. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) static const v4l2_std_id ntsc_mask =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) V4L2_STD_NTSC | V4L2_STD_NTSC_443;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) static const v4l2_std_id pal_mask =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) V4L2_STD_PAL | V4L2_STD_PAL_60 | V4L2_STD_PAL_M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (norm & ntsc_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) ret = usbtv_set_regs(usbtv, ntsc, ARRAY_SIZE(ntsc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) else if (norm & pal_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) ret = usbtv_set_regs(usbtv, pal, ARRAY_SIZE(pal));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) else if (norm & V4L2_STD_SECAM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) ret = usbtv_set_regs(usbtv, secam, ARRAY_SIZE(secam));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) /* Configure the decoder for the color standard */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) const u16 cfg[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) { USBTV_BASE + 0x016f, usbtv_norm_to_16f_reg(norm) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) ret = usbtv_set_regs(usbtv, cfg, ARRAY_SIZE(cfg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) static int usbtv_setup_capture(struct usbtv *usbtv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) static const u16 setup[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) /* These seem to enable the device. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) { USBTV_BASE + 0x0008, 0x0001 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) { USBTV_BASE + 0x01d0, 0x00ff },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) { USBTV_BASE + 0x01d9, 0x0002 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) /* These seem to influence color parameters, such as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) * brightness, etc. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) { USBTV_BASE + 0x0239, 0x0040 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) { USBTV_BASE + 0x0240, 0x0000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) { USBTV_BASE + 0x0241, 0x0000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) { USBTV_BASE + 0x0242, 0x0002 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) { USBTV_BASE + 0x0243, 0x0080 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) { USBTV_BASE + 0x0244, 0x0012 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) { USBTV_BASE + 0x0245, 0x0090 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) { USBTV_BASE + 0x0246, 0x0000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) { USBTV_BASE + 0x0278, 0x002d },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) { USBTV_BASE + 0x0279, 0x000a },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) { USBTV_BASE + 0x027a, 0x0032 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) { 0xf890, 0x000c },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) { 0xf894, 0x0086 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) { USBTV_BASE + 0x00ac, 0x00c0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) { USBTV_BASE + 0x00ad, 0x0000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) { USBTV_BASE + 0x00a2, 0x0012 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) { USBTV_BASE + 0x00a3, 0x00e0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) { USBTV_BASE + 0x00a4, 0x0028 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) { USBTV_BASE + 0x00a5, 0x0082 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) { USBTV_BASE + 0x00a7, 0x0080 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) { USBTV_BASE + 0x0000, 0x0014 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) { USBTV_BASE + 0x0006, 0x0003 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) { USBTV_BASE + 0x0090, 0x0099 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) { USBTV_BASE + 0x0091, 0x0090 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) { USBTV_BASE + 0x0094, 0x0068 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) { USBTV_BASE + 0x0095, 0x0070 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) { USBTV_BASE + 0x009c, 0x0030 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) { USBTV_BASE + 0x009d, 0x00c0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) { USBTV_BASE + 0x009e, 0x00e0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) { USBTV_BASE + 0x0019, 0x0006 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) { USBTV_BASE + 0x008c, 0x00ba },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) { USBTV_BASE + 0x0101, 0x00ff },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) { USBTV_BASE + 0x010c, 0x00b3 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) { USBTV_BASE + 0x01b2, 0x0080 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) { USBTV_BASE + 0x01b4, 0x00a0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) { USBTV_BASE + 0x014c, 0x00ff },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) { USBTV_BASE + 0x014d, 0x00ca },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) { USBTV_BASE + 0x0113, 0x0053 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) { USBTV_BASE + 0x0119, 0x008a },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) { USBTV_BASE + 0x013c, 0x0003 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) { USBTV_BASE + 0x0150, 0x009c },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) { USBTV_BASE + 0x0151, 0x0071 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) { USBTV_BASE + 0x0152, 0x00c6 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) { USBTV_BASE + 0x0153, 0x0084 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) { USBTV_BASE + 0x0154, 0x00bc },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) { USBTV_BASE + 0x0155, 0x00a0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) { USBTV_BASE + 0x0156, 0x00a0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) { USBTV_BASE + 0x0157, 0x009c },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) { USBTV_BASE + 0x0158, 0x001f },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) { USBTV_BASE + 0x0159, 0x0006 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) { USBTV_BASE + 0x015d, 0x0000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) ret = usbtv_set_regs(usbtv, setup, ARRAY_SIZE(setup));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) ret = usbtv_select_norm(usbtv, usbtv->norm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) ret = usbtv_select_input(usbtv, usbtv->input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) ret = v4l2_ctrl_handler_setup(&usbtv->ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) return 0;
^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) /* Copy data from chunk into a frame buffer, deinterlacing the data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * into every second line. Unfortunately, they don't align nicely into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * 720 pixel lines, as the chunk is 240 words long, which is 480 pixels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * Therefore, we break down the chunk into two halves before copying,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * so that we can interleave a line if needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * Each "chunk" is 240 words; a word in this context equals 4 bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) * Image format is YUYV/YUV 4:2:2, consisting of Y Cr Y Cb, defining two
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) * pixels, the Cr and Cb shared between the two pixels, but each having
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) * separate Y values. Thus, the 240 words equal 480 pixels. It therefore,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) * takes 1.5 chunks to make a 720 pixel-wide line for the frame.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) * The image is interlaced, so there is a "scan" of odd lines, followed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) * by "scan" of even numbered lines.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) * Following code is writing the chunks in correct sequence, skipping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) * the rows based on "odd" value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) * line 1: chunk[0][ 0..479] chunk[0][480..959] chunk[1][ 0..479]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) * line 3: chunk[1][480..959] chunk[2][ 0..479] chunk[2][480..959]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) * ...etc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) static void usbtv_chunk_to_vbuf(u32 *frame, __be32 *src, int chunk_no, int odd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) int half;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) for (half = 0; half < 2; half++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) int part_no = chunk_no * 2 + half;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) int line = part_no / 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) int part_index = (line * 2 + !odd) * 3 + (part_no % 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) u32 *dst = &frame[part_index * USBTV_CHUNK/2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) memcpy(dst, src, USBTV_CHUNK/2 * sizeof(*src));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) src += USBTV_CHUNK/2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) /* Called for each 256-byte image chunk.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) * First word identifies the chunk, followed by 240 words of image
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) * data and padding. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) static void usbtv_image_chunk(struct usbtv *usbtv, __be32 *chunk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) int frame_id, odd, chunk_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) u32 *frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) struct usbtv_buf *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) /* Ignore corrupted lines. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if (!USBTV_MAGIC_OK(chunk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) frame_id = USBTV_FRAME_ID(chunk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) odd = USBTV_ODD(chunk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) chunk_no = USBTV_CHUNK_NO(chunk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) if (chunk_no >= usbtv->n_chunks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) /* Beginning of a frame. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (chunk_no == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) usbtv->frame_id = frame_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) usbtv->chunks_done = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (usbtv->frame_id != frame_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) spin_lock_irqsave(&usbtv->buflock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (list_empty(&usbtv->bufs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) /* No free buffers. Userspace likely too slow. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) spin_unlock_irqrestore(&usbtv->buflock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) /* First available buffer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) buf = list_first_entry(&usbtv->bufs, struct usbtv_buf, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) frame = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) /* Copy the chunk data. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) usbtv_chunk_to_vbuf(frame, &chunk[1], chunk_no, odd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) usbtv->chunks_done++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) /* Last chunk in a field */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) if (chunk_no == usbtv->n_chunks-1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) /* Last chunk in a frame, signalling an end */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) if (odd && !usbtv->last_odd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) int size = vb2_plane_size(&buf->vb.vb2_buf, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) enum vb2_buffer_state state = usbtv->chunks_done ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) usbtv->n_chunks ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) VB2_BUF_STATE_DONE :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) VB2_BUF_STATE_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) buf->vb.field = V4L2_FIELD_INTERLACED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) buf->vb.sequence = usbtv->sequence++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) buf->vb.vb2_buf.timestamp = ktime_get_ns();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) vb2_buffer_done(&buf->vb.vb2_buf, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) list_del(&buf->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) usbtv->last_odd = odd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) spin_unlock_irqrestore(&usbtv->buflock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) /* Got image data. Each packet contains a number of 256-word chunks we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) * compose the image from. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) static void usbtv_iso_cb(struct urb *ip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) struct usbtv *usbtv = (struct usbtv *)ip->context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) switch (ip->status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) /* All fine. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) /* Device disconnected or capture stopped? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) case -ENODEV:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) case -ENOENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) case -ECONNRESET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) case -ESHUTDOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) /* Unknown error. Retry. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) dev_warn(usbtv->dev, "Bad response for ISO request.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) goto resubmit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) for (i = 0; i < ip->number_of_packets; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) int size = ip->iso_frame_desc[i].actual_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) unsigned char *data = ip->transfer_buffer +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) ip->iso_frame_desc[i].offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) int offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) for (offset = 0; USBTV_CHUNK_SIZE * offset < size; offset++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) usbtv_image_chunk(usbtv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) (__be32 *)&data[USBTV_CHUNK_SIZE * offset]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) resubmit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) ret = usb_submit_urb(ip, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) dev_warn(usbtv->dev, "Could not resubmit ISO URB\n");
^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 struct urb *usbtv_setup_iso_transfer(struct usbtv *usbtv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) struct urb *ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) int size = usbtv->iso_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) ip = usb_alloc_urb(USBTV_ISOC_PACKETS, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) if (ip == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) ip->dev = usbtv->udev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) ip->context = usbtv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) ip->pipe = usb_rcvisocpipe(usbtv->udev, USBTV_VIDEO_ENDP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) ip->interval = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) ip->transfer_flags = URB_ISO_ASAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) ip->transfer_buffer = kcalloc(USBTV_ISOC_PACKETS, size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (!ip->transfer_buffer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) usb_free_urb(ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) ip->complete = usbtv_iso_cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) ip->number_of_packets = USBTV_ISOC_PACKETS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) ip->transfer_buffer_length = size * USBTV_ISOC_PACKETS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) for (i = 0; i < USBTV_ISOC_PACKETS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) ip->iso_frame_desc[i].offset = size * i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) ip->iso_frame_desc[i].length = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) return ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) static void usbtv_stop(struct usbtv *usbtv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) /* Cancel running transfers. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) for (i = 0; i < USBTV_ISOC_TRANSFERS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) struct urb *ip = usbtv->isoc_urbs[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) if (ip == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) usb_kill_urb(ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) kfree(ip->transfer_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) usb_free_urb(ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) usbtv->isoc_urbs[i] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) /* Return buffers to userspace. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) spin_lock_irqsave(&usbtv->buflock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) while (!list_empty(&usbtv->bufs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) struct usbtv_buf *buf = list_first_entry(&usbtv->bufs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) struct usbtv_buf, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) list_del(&buf->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) spin_unlock_irqrestore(&usbtv->buflock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) static int usbtv_start(struct usbtv *usbtv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) usbtv_audio_suspend(usbtv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) ret = usb_set_interface(usbtv->udev, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) ret = usbtv_setup_capture(usbtv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) ret = usb_set_interface(usbtv->udev, 0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) usbtv_audio_resume(usbtv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) for (i = 0; i < USBTV_ISOC_TRANSFERS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) struct urb *ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) ip = usbtv_setup_iso_transfer(usbtv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) if (ip == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) goto start_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) usbtv->isoc_urbs[i] = ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) ret = usb_submit_urb(ip, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) goto start_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) start_fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) usbtv_stop(usbtv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) static int usbtv_querycap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) struct v4l2_capability *cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) struct usbtv *dev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) strscpy(cap->driver, "usbtv", sizeof(cap->driver));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) strscpy(cap->card, "usbtv", sizeof(cap->card));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) static int usbtv_enum_input(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) struct v4l2_input *i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) struct usbtv *dev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) switch (i->index) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) case USBTV_COMPOSITE_INPUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) strscpy(i->name, "Composite", sizeof(i->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) case USBTV_SVIDEO_INPUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) strscpy(i->name, "S-Video", sizeof(i->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) i->type = V4L2_INPUT_TYPE_CAMERA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) i->std = dev->vdev.tvnorms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) static int usbtv_enum_fmt_vid_cap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) struct v4l2_fmtdesc *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) if (f->index > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) f->pixelformat = V4L2_PIX_FMT_YUYV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) static int usbtv_fmt_vid_cap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) struct usbtv *usbtv = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) f->fmt.pix.width = usbtv->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) f->fmt.pix.height = usbtv->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) f->fmt.pix.field = V4L2_FIELD_INTERLACED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) f->fmt.pix.bytesperline = usbtv->width * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) f->fmt.pix.sizeimage = (f->fmt.pix.bytesperline * f->fmt.pix.height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) static int usbtv_g_std(struct file *file, void *priv, v4l2_std_id *norm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) struct usbtv *usbtv = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) *norm = usbtv->norm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) static int usbtv_s_std(struct file *file, void *priv, v4l2_std_id norm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) int ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) struct usbtv *usbtv = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) if (norm & USBTV_TV_STD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) ret = usbtv_select_norm(usbtv, norm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) static int usbtv_g_input(struct file *file, void *priv, unsigned int *i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) struct usbtv *usbtv = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) *i = usbtv->input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) static int usbtv_s_input(struct file *file, void *priv, unsigned int i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) struct usbtv *usbtv = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) return usbtv_select_input(usbtv, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) static struct v4l2_ioctl_ops usbtv_ioctl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) .vidioc_querycap = usbtv_querycap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) .vidioc_enum_input = usbtv_enum_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) .vidioc_enum_fmt_vid_cap = usbtv_enum_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) .vidioc_g_fmt_vid_cap = usbtv_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) .vidioc_try_fmt_vid_cap = usbtv_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) .vidioc_s_fmt_vid_cap = usbtv_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) .vidioc_g_std = usbtv_g_std,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) .vidioc_s_std = usbtv_s_std,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) .vidioc_g_input = usbtv_g_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) .vidioc_s_input = usbtv_s_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) .vidioc_reqbufs = vb2_ioctl_reqbufs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) .vidioc_querybuf = vb2_ioctl_querybuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) .vidioc_create_bufs = vb2_ioctl_create_bufs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) .vidioc_qbuf = vb2_ioctl_qbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) .vidioc_dqbuf = vb2_ioctl_dqbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) .vidioc_streamon = vb2_ioctl_streamon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) .vidioc_streamoff = vb2_ioctl_streamoff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) static const struct v4l2_file_operations usbtv_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) .unlocked_ioctl = video_ioctl2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) .mmap = vb2_fop_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) .open = v4l2_fh_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) .release = vb2_fop_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) .read = vb2_fop_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) .poll = vb2_fop_poll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) static int usbtv_queue_setup(struct vb2_queue *vq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) unsigned int *nbuffers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) unsigned int *nplanes, unsigned int sizes[], struct device *alloc_devs[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) struct usbtv *usbtv = vb2_get_drv_priv(vq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) unsigned size = USBTV_CHUNK * usbtv->n_chunks * 2 * sizeof(u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) if (vq->num_buffers + *nbuffers < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) *nbuffers = 2 - vq->num_buffers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) if (*nplanes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) return sizes[0] < size ? -EINVAL : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) *nplanes = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) sizes[0] = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) static void usbtv_buf_queue(struct vb2_buffer *vb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) struct usbtv *usbtv = vb2_get_drv_priv(vb->vb2_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) struct usbtv_buf *buf = container_of(vbuf, struct usbtv_buf, vb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) if (usbtv->udev == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) spin_lock_irqsave(&usbtv->buflock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) list_add_tail(&buf->list, &usbtv->bufs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) spin_unlock_irqrestore(&usbtv->buflock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) static int usbtv_start_streaming(struct vb2_queue *vq, unsigned int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) struct usbtv *usbtv = vb2_get_drv_priv(vq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) if (usbtv->udev == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) usbtv->last_odd = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) usbtv->sequence = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) return usbtv_start(usbtv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) static void usbtv_stop_streaming(struct vb2_queue *vq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) struct usbtv *usbtv = vb2_get_drv_priv(vq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) if (usbtv->udev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) usbtv_stop(usbtv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) static const struct vb2_ops usbtv_vb2_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) .queue_setup = usbtv_queue_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) .buf_queue = usbtv_buf_queue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) .start_streaming = usbtv_start_streaming,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) .stop_streaming = usbtv_stop_streaming,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) .wait_prepare = vb2_ops_wait_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) .wait_finish = vb2_ops_wait_finish,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) static int usbtv_s_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) struct usbtv *usbtv = container_of(ctrl->handler, struct usbtv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) u8 *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) u16 index, size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) data = kmalloc(3, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) * Read in the current brightness/contrast registers. We need them
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) * both, because the values are for some reason interleaved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) if (ctrl->id == V4L2_CID_BRIGHTNESS || ctrl->id == V4L2_CID_CONTRAST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) ret = usb_control_msg(usbtv->udev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) usb_rcvctrlpipe(usbtv->udev, 0), USBTV_CONTROL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) 0, USBTV_BASE + 0x0244, (void *)data, 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) USB_CTRL_GET_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) switch (ctrl->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) case V4L2_CID_BRIGHTNESS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) index = USBTV_BASE + 0x0244;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) size = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) data[0] &= 0xf0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) data[0] |= (ctrl->val >> 8) & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) data[2] = ctrl->val & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) case V4L2_CID_CONTRAST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) index = USBTV_BASE + 0x0244;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) size = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) data[0] &= 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) data[0] |= (ctrl->val >> 4) & 0xf0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) data[1] = ctrl->val & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) case V4L2_CID_SATURATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) index = USBTV_BASE + 0x0242;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) data[0] = ctrl->val >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) data[1] = ctrl->val & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) size = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) case V4L2_CID_HUE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) index = USBTV_BASE + 0x0240;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) size = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) if (ctrl->val > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) data[0] = 0x92 + (ctrl->val >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) data[1] = ctrl->val & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) data[0] = 0x82 + (-ctrl->val >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) data[1] = -ctrl->val & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) case V4L2_CID_SHARPNESS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) index = USBTV_BASE + 0x0239;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) data[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) data[1] = ctrl->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) size = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) kfree(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) ret = usb_control_msg(usbtv->udev, usb_sndctrlpipe(usbtv->udev, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) USBTV_CONTROL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) 0, index, (void *)data, size, USB_CTRL_SET_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) dev_warn(usbtv->dev, "Failed to submit a control request.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) kfree(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) static const struct v4l2_ctrl_ops usbtv_ctrl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) .s_ctrl = usbtv_s_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) static void usbtv_release(struct v4l2_device *v4l2_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) struct usbtv *usbtv = container_of(v4l2_dev, struct usbtv, v4l2_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) v4l2_device_unregister(&usbtv->v4l2_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) v4l2_ctrl_handler_free(&usbtv->ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) kfree(usbtv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) int usbtv_video_init(struct usbtv *usbtv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) (void)usbtv_configure_for_norm(usbtv, V4L2_STD_525_60);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) spin_lock_init(&usbtv->buflock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) mutex_init(&usbtv->v4l2_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) mutex_init(&usbtv->vb2q_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) INIT_LIST_HEAD(&usbtv->bufs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) /* videobuf2 structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) usbtv->vb2q.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) usbtv->vb2q.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) usbtv->vb2q.drv_priv = usbtv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) usbtv->vb2q.buf_struct_size = sizeof(struct usbtv_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) usbtv->vb2q.ops = &usbtv_vb2_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) usbtv->vb2q.mem_ops = &vb2_vmalloc_memops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) usbtv->vb2q.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) usbtv->vb2q.lock = &usbtv->vb2q_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) ret = vb2_queue_init(&usbtv->vb2q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) dev_warn(usbtv->dev, "Could not initialize videobuf2 queue\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) /* controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) v4l2_ctrl_handler_init(&usbtv->ctrl, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) v4l2_ctrl_new_std(&usbtv->ctrl, &usbtv_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) V4L2_CID_CONTRAST, 0, 0x3ff, 1, 0x1d0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) v4l2_ctrl_new_std(&usbtv->ctrl, &usbtv_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) V4L2_CID_BRIGHTNESS, 0, 0x3ff, 1, 0x1c0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) v4l2_ctrl_new_std(&usbtv->ctrl, &usbtv_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) V4L2_CID_SATURATION, 0, 0x3ff, 1, 0x200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) v4l2_ctrl_new_std(&usbtv->ctrl, &usbtv_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) V4L2_CID_HUE, -0xdff, 0xdff, 1, 0x000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) v4l2_ctrl_new_std(&usbtv->ctrl, &usbtv_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) V4L2_CID_SHARPNESS, 0x0, 0xff, 1, 0x60);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) ret = usbtv->ctrl.error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) dev_warn(usbtv->dev, "Could not initialize controls\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) goto ctrl_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) /* v4l2 structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) usbtv->v4l2_dev.ctrl_handler = &usbtv->ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) usbtv->v4l2_dev.release = usbtv_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) ret = v4l2_device_register(usbtv->dev, &usbtv->v4l2_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) dev_warn(usbtv->dev, "Could not register v4l2 device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) goto v4l2_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) /* Video structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) strscpy(usbtv->vdev.name, "usbtv", sizeof(usbtv->vdev.name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) usbtv->vdev.v4l2_dev = &usbtv->v4l2_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) usbtv->vdev.release = video_device_release_empty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) usbtv->vdev.fops = &usbtv_fops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) usbtv->vdev.ioctl_ops = &usbtv_ioctl_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) usbtv->vdev.tvnorms = USBTV_TV_STD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) usbtv->vdev.queue = &usbtv->vb2q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) usbtv->vdev.lock = &usbtv->v4l2_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) usbtv->vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) V4L2_CAP_STREAMING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) video_set_drvdata(&usbtv->vdev, usbtv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) ret = video_register_device(&usbtv->vdev, VFL_TYPE_VIDEO, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) dev_warn(usbtv->dev, "Could not register video device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) goto vdev_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) vdev_fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) v4l2_device_unregister(&usbtv->v4l2_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) v4l2_fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) ctrl_fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) v4l2_ctrl_handler_free(&usbtv->ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) void usbtv_video_free(struct usbtv *usbtv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) mutex_lock(&usbtv->vb2q_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) mutex_lock(&usbtv->v4l2_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) usbtv_stop(usbtv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) vb2_video_unregister_device(&usbtv->vdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) v4l2_device_disconnect(&usbtv->v4l2_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) mutex_unlock(&usbtv->v4l2_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) mutex_unlock(&usbtv->vb2q_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) v4l2_device_put(&usbtv->v4l2_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) }