1dacca5f0SHans Verkuil // SPDX-License-Identifier: GPL-2.0-only
2dacca5f0SHans Verkuil /*
3dacca5f0SHans Verkuil  * vivid-core.c - A Virtual Video Test Driver, core initialization
4dacca5f0SHans Verkuil  *
5dacca5f0SHans Verkuil  * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
6dacca5f0SHans Verkuil  */
7dacca5f0SHans Verkuil 
8dacca5f0SHans Verkuil #include <linux/module.h>
9dacca5f0SHans Verkuil #include <linux/errno.h>
10dacca5f0SHans Verkuil #include <linux/kernel.h>
11dacca5f0SHans Verkuil #include <linux/init.h>
12dacca5f0SHans Verkuil #include <linux/sched.h>
13dacca5f0SHans Verkuil #include <linux/slab.h>
14dacca5f0SHans Verkuil #include <linux/vmalloc.h>
15dacca5f0SHans Verkuil #include <linux/font.h>
16dacca5f0SHans Verkuil #include <linux/mutex.h>
17dacca5f0SHans Verkuil #include <linux/platform_device.h>
18dacca5f0SHans Verkuil #include <linux/videodev2.h>
19dacca5f0SHans Verkuil #include <linux/v4l2-dv-timings.h>
20dacca5f0SHans Verkuil #include <media/videobuf2-vmalloc.h>
21dacca5f0SHans Verkuil #include <media/videobuf2-dma-contig.h>
22dacca5f0SHans Verkuil #include <media/v4l2-dv-timings.h>
23dacca5f0SHans Verkuil #include <media/v4l2-ioctl.h>
24dacca5f0SHans Verkuil #include <media/v4l2-fh.h>
25dacca5f0SHans Verkuil #include <media/v4l2-event.h>
26dacca5f0SHans Verkuil 
27dacca5f0SHans Verkuil #include "vivid-core.h"
28dacca5f0SHans Verkuil #include "vivid-vid-common.h"
29dacca5f0SHans Verkuil #include "vivid-vid-cap.h"
30dacca5f0SHans Verkuil #include "vivid-vid-out.h"
31dacca5f0SHans Verkuil #include "vivid-radio-common.h"
32dacca5f0SHans Verkuil #include "vivid-radio-rx.h"
33dacca5f0SHans Verkuil #include "vivid-radio-tx.h"
34dacca5f0SHans Verkuil #include "vivid-sdr-cap.h"
35dacca5f0SHans Verkuil #include "vivid-vbi-cap.h"
36dacca5f0SHans Verkuil #include "vivid-vbi-out.h"
37dacca5f0SHans Verkuil #include "vivid-osd.h"
38dacca5f0SHans Verkuil #include "vivid-cec.h"
39dacca5f0SHans Verkuil #include "vivid-ctrls.h"
40dacca5f0SHans Verkuil #include "vivid-meta-cap.h"
41dacca5f0SHans Verkuil #include "vivid-meta-out.h"
42dacca5f0SHans Verkuil #include "vivid-touch-cap.h"
43dacca5f0SHans Verkuil 
44dacca5f0SHans Verkuil #define VIVID_MODULE_NAME "vivid"
45dacca5f0SHans Verkuil 
46dacca5f0SHans Verkuil /* The maximum number of vivid devices */
47dacca5f0SHans Verkuil #define VIVID_MAX_DEVS CONFIG_VIDEO_VIVID_MAX_DEVS
48dacca5f0SHans Verkuil 
49dacca5f0SHans Verkuil MODULE_DESCRIPTION("Virtual Video Test Driver");
50dacca5f0SHans Verkuil MODULE_AUTHOR("Hans Verkuil");
51dacca5f0SHans Verkuil MODULE_LICENSE("GPL");
52dacca5f0SHans Verkuil 
53dacca5f0SHans Verkuil static unsigned n_devs = 1;
54dacca5f0SHans Verkuil module_param(n_devs, uint, 0444);
55dacca5f0SHans Verkuil MODULE_PARM_DESC(n_devs, " number of driver instances to create");
56dacca5f0SHans Verkuil 
57dacca5f0SHans Verkuil static int vid_cap_nr[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = -1 };
58dacca5f0SHans Verkuil module_param_array(vid_cap_nr, int, NULL, 0444);
59dacca5f0SHans Verkuil MODULE_PARM_DESC(vid_cap_nr, " videoX start number, -1 is autodetect");
60dacca5f0SHans Verkuil 
61dacca5f0SHans Verkuil static int vid_out_nr[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = -1 };
62dacca5f0SHans Verkuil module_param_array(vid_out_nr, int, NULL, 0444);
63dacca5f0SHans Verkuil MODULE_PARM_DESC(vid_out_nr, " videoX start number, -1 is autodetect");
64dacca5f0SHans Verkuil 
65dacca5f0SHans Verkuil static int vbi_cap_nr[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = -1 };
66dacca5f0SHans Verkuil module_param_array(vbi_cap_nr, int, NULL, 0444);
67dacca5f0SHans Verkuil MODULE_PARM_DESC(vbi_cap_nr, " vbiX start number, -1 is autodetect");
68dacca5f0SHans Verkuil 
69dacca5f0SHans Verkuil static int vbi_out_nr[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = -1 };
70dacca5f0SHans Verkuil module_param_array(vbi_out_nr, int, NULL, 0444);
71dacca5f0SHans Verkuil MODULE_PARM_DESC(vbi_out_nr, " vbiX start number, -1 is autodetect");
72dacca5f0SHans Verkuil 
73dacca5f0SHans Verkuil static int sdr_cap_nr[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = -1 };
74dacca5f0SHans Verkuil module_param_array(sdr_cap_nr, int, NULL, 0444);
75dacca5f0SHans Verkuil MODULE_PARM_DESC(sdr_cap_nr, " swradioX start number, -1 is autodetect");
76dacca5f0SHans Verkuil 
77dacca5f0SHans Verkuil static int radio_rx_nr[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = -1 };
78dacca5f0SHans Verkuil module_param_array(radio_rx_nr, int, NULL, 0444);
79dacca5f0SHans Verkuil MODULE_PARM_DESC(radio_rx_nr, " radioX start number, -1 is autodetect");
80dacca5f0SHans Verkuil 
81dacca5f0SHans Verkuil static int radio_tx_nr[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = -1 };
82dacca5f0SHans Verkuil module_param_array(radio_tx_nr, int, NULL, 0444);
83dacca5f0SHans Verkuil MODULE_PARM_DESC(radio_tx_nr, " radioX start number, -1 is autodetect");
84dacca5f0SHans Verkuil 
85dacca5f0SHans Verkuil static int meta_cap_nr[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = -1 };
86dacca5f0SHans Verkuil module_param_array(meta_cap_nr, int, NULL, 0444);
87dacca5f0SHans Verkuil MODULE_PARM_DESC(meta_cap_nr, " videoX start number, -1 is autodetect");
88dacca5f0SHans Verkuil 
89dacca5f0SHans Verkuil static int meta_out_nr[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = -1 };
90dacca5f0SHans Verkuil module_param_array(meta_out_nr, int, NULL, 0444);
91dacca5f0SHans Verkuil MODULE_PARM_DESC(meta_out_nr, " videoX start number, -1 is autodetect");
92dacca5f0SHans Verkuil 
93dacca5f0SHans Verkuil static int touch_cap_nr[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = -1 };
94dacca5f0SHans Verkuil module_param_array(touch_cap_nr, int, NULL, 0444);
95dacca5f0SHans Verkuil MODULE_PARM_DESC(touch_cap_nr, " v4l-touchX start number, -1 is autodetect");
96dacca5f0SHans Verkuil 
97dacca5f0SHans Verkuil static int ccs_cap_mode[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = -1 };
98dacca5f0SHans Verkuil module_param_array(ccs_cap_mode, int, NULL, 0444);
99dacca5f0SHans Verkuil MODULE_PARM_DESC(ccs_cap_mode, " capture crop/compose/scale mode:\n"
100dacca5f0SHans Verkuil 			   "\t\t    bit 0=crop, 1=compose, 2=scale,\n"
101dacca5f0SHans Verkuil 			   "\t\t    -1=user-controlled (default)");
102dacca5f0SHans Verkuil 
103dacca5f0SHans Verkuil static int ccs_out_mode[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = -1 };
104dacca5f0SHans Verkuil module_param_array(ccs_out_mode, int, NULL, 0444);
105dacca5f0SHans Verkuil MODULE_PARM_DESC(ccs_out_mode, " output crop/compose/scale mode:\n"
106dacca5f0SHans Verkuil 			   "\t\t    bit 0=crop, 1=compose, 2=scale,\n"
107dacca5f0SHans Verkuil 			   "\t\t    -1=user-controlled (default)");
108dacca5f0SHans Verkuil 
109dacca5f0SHans Verkuil static unsigned multiplanar[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = 1 };
110dacca5f0SHans Verkuil module_param_array(multiplanar, uint, NULL, 0444);
111dacca5f0SHans Verkuil MODULE_PARM_DESC(multiplanar, " 1 (default) creates a single planar device, 2 creates a multiplanar device.");
112dacca5f0SHans Verkuil 
113dacca5f0SHans Verkuil /*
114dacca5f0SHans Verkuil  * Default: video + vbi-cap (raw and sliced) + radio rx + radio tx + sdr +
115dacca5f0SHans Verkuil  * vbi-out + vid-out + meta-cap
116dacca5f0SHans Verkuil  */
117dacca5f0SHans Verkuil static unsigned int node_types[VIVID_MAX_DEVS] = {
118dacca5f0SHans Verkuil 	[0 ... (VIVID_MAX_DEVS - 1)] = 0xe1d3d
119dacca5f0SHans Verkuil };
120dacca5f0SHans Verkuil module_param_array(node_types, uint, NULL, 0444);
121dacca5f0SHans Verkuil MODULE_PARM_DESC(node_types, " node types, default is 0xe1d3d. Bitmask with the following meaning:\n"
122dacca5f0SHans Verkuil 			     "\t\t    bit 0: Video Capture node\n"
123dacca5f0SHans Verkuil 			     "\t\t    bit 2-3: VBI Capture node: 0 = none, 1 = raw vbi, 2 = sliced vbi, 3 = both\n"
124dacca5f0SHans Verkuil 			     "\t\t    bit 4: Radio Receiver node\n"
125dacca5f0SHans Verkuil 			     "\t\t    bit 5: Software Defined Radio Receiver node\n"
126dacca5f0SHans Verkuil 			     "\t\t    bit 8: Video Output node\n"
127dacca5f0SHans Verkuil 			     "\t\t    bit 10-11: VBI Output node: 0 = none, 1 = raw vbi, 2 = sliced vbi, 3 = both\n"
128dacca5f0SHans Verkuil 			     "\t\t    bit 12: Radio Transmitter node\n"
129ccaa9d50SHans Verkuil 			     "\t\t    bit 16: Framebuffer for testing output overlays\n"
130dacca5f0SHans Verkuil 			     "\t\t    bit 17: Metadata Capture node\n"
131dacca5f0SHans Verkuil 			     "\t\t    bit 18: Metadata Output node\n"
132dacca5f0SHans Verkuil 			     "\t\t    bit 19: Touch Capture node\n");
133dacca5f0SHans Verkuil 
134dacca5f0SHans Verkuil /* Default: 4 inputs */
135dacca5f0SHans Verkuil static unsigned num_inputs[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = 4 };
136dacca5f0SHans Verkuil module_param_array(num_inputs, uint, NULL, 0444);
137dacca5f0SHans Verkuil MODULE_PARM_DESC(num_inputs, " number of inputs, default is 4");
138dacca5f0SHans Verkuil 
139dacca5f0SHans Verkuil /* Default: input 0 = WEBCAM, 1 = TV, 2 = SVID, 3 = HDMI */
140dacca5f0SHans Verkuil static unsigned input_types[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = 0xe4 };
141dacca5f0SHans Verkuil module_param_array(input_types, uint, NULL, 0444);
142dacca5f0SHans Verkuil MODULE_PARM_DESC(input_types, " input types, default is 0xe4. Two bits per input,\n"
143dacca5f0SHans Verkuil 			      "\t\t    bits 0-1 == input 0, bits 31-30 == input 15.\n"
144dacca5f0SHans Verkuil 			      "\t\t    Type 0 == webcam, 1 == TV, 2 == S-Video, 3 == HDMI");
145dacca5f0SHans Verkuil 
146dacca5f0SHans Verkuil /* Default: 2 outputs */
147dacca5f0SHans Verkuil static unsigned num_outputs[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = 2 };
148dacca5f0SHans Verkuil module_param_array(num_outputs, uint, NULL, 0444);
149dacca5f0SHans Verkuil MODULE_PARM_DESC(num_outputs, " number of outputs, default is 2");
150dacca5f0SHans Verkuil 
151dacca5f0SHans Verkuil /* Default: output 0 = SVID, 1 = HDMI */
152dacca5f0SHans Verkuil static unsigned output_types[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = 2 };
153dacca5f0SHans Verkuil module_param_array(output_types, uint, NULL, 0444);
154dacca5f0SHans Verkuil MODULE_PARM_DESC(output_types, " output types, default is 0x02. One bit per output,\n"
155dacca5f0SHans Verkuil 			      "\t\t    bit 0 == output 0, bit 15 == output 15.\n"
156dacca5f0SHans Verkuil 			      "\t\t    Type 0 == S-Video, 1 == HDMI");
157dacca5f0SHans Verkuil 
158dacca5f0SHans Verkuil unsigned vivid_debug;
159dacca5f0SHans Verkuil module_param(vivid_debug, uint, 0644);
160dacca5f0SHans Verkuil MODULE_PARM_DESC(vivid_debug, " activates debug info");
161dacca5f0SHans Verkuil 
162dacca5f0SHans Verkuil static bool no_error_inj;
163dacca5f0SHans Verkuil module_param(no_error_inj, bool, 0444);
164dacca5f0SHans Verkuil MODULE_PARM_DESC(no_error_inj, " if set disable the error injecting controls");
165dacca5f0SHans Verkuil 
166dacca5f0SHans Verkuil static unsigned int allocators[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = 0 };
167dacca5f0SHans Verkuil module_param_array(allocators, uint, NULL, 0444);
168dacca5f0SHans Verkuil MODULE_PARM_DESC(allocators, " memory allocator selection, default is 0.\n"
169dacca5f0SHans Verkuil 			     "\t\t    0 == vmalloc\n"
170dacca5f0SHans Verkuil 			     "\t\t    1 == dma-contig");
171dacca5f0SHans Verkuil 
17262a4cd01SSergey Senozhatsky static unsigned int cache_hints[VIVID_MAX_DEVS] = {
17362a4cd01SSergey Senozhatsky 	[0 ... (VIVID_MAX_DEVS - 1)] = 0
17462a4cd01SSergey Senozhatsky };
17562a4cd01SSergey Senozhatsky module_param_array(cache_hints, uint, NULL, 0444);
17662a4cd01SSergey Senozhatsky MODULE_PARM_DESC(cache_hints, " user-space cache hints, default is 0.\n"
17762a4cd01SSergey Senozhatsky 			     "\t\t    0 == forbid\n"
17862a4cd01SSergey Senozhatsky 			     "\t\t    1 == allow");
17962a4cd01SSergey Senozhatsky 
180b72dd0f3SHans Verkuil static unsigned int supports_requests[VIVID_MAX_DEVS] = {
181b72dd0f3SHans Verkuil 	[0 ... (VIVID_MAX_DEVS - 1)] = 1
182b72dd0f3SHans Verkuil };
183b72dd0f3SHans Verkuil module_param_array(supports_requests, uint, NULL, 0444);
184b72dd0f3SHans Verkuil MODULE_PARM_DESC(supports_requests, " support for requests, default is 1.\n"
185b72dd0f3SHans Verkuil 			     "\t\t    0 == no support\n"
186b72dd0f3SHans Verkuil 			     "\t\t    1 == supports requests\n"
187b72dd0f3SHans Verkuil 			     "\t\t    2 == requires requests");
188b72dd0f3SHans Verkuil 
189dacca5f0SHans Verkuil static struct vivid_dev *vivid_devs[VIVID_MAX_DEVS];
190dacca5f0SHans Verkuil 
191dacca5f0SHans Verkuil const struct v4l2_rect vivid_min_rect = {
192dacca5f0SHans Verkuil 	0, 0, MIN_WIDTH, MIN_HEIGHT
193dacca5f0SHans Verkuil };
194dacca5f0SHans Verkuil 
195dacca5f0SHans Verkuil const struct v4l2_rect vivid_max_rect = {
196dacca5f0SHans Verkuil 	0, 0, MAX_WIDTH * MAX_ZOOM, MAX_HEIGHT * MAX_ZOOM
197dacca5f0SHans Verkuil };
198dacca5f0SHans Verkuil 
199dacca5f0SHans Verkuil static const u8 vivid_hdmi_edid[256] = {
200dacca5f0SHans Verkuil 	0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
201dacca5f0SHans Verkuil 	0x31, 0xd8, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00,
202dacca5f0SHans Verkuil 	0x22, 0x1a, 0x01, 0x03, 0x80, 0x60, 0x36, 0x78,
203dacca5f0SHans Verkuil 	0x0f, 0xee, 0x91, 0xa3, 0x54, 0x4c, 0x99, 0x26,
204dacca5f0SHans Verkuil 	0x0f, 0x50, 0x54, 0x2f, 0xcf, 0x00, 0x31, 0x59,
205dacca5f0SHans Verkuil 	0x45, 0x59, 0x81, 0x80, 0x81, 0x40, 0x90, 0x40,
206dacca5f0SHans Verkuil 	0x95, 0x00, 0xa9, 0x40, 0xb3, 0x00, 0x08, 0xe8,
207dacca5f0SHans Verkuil 	0x00, 0x30, 0xf2, 0x70, 0x5a, 0x80, 0xb0, 0x58,
208dacca5f0SHans Verkuil 	0x8a, 0x00, 0xc0, 0x1c, 0x32, 0x00, 0x00, 0x1e,
209dacca5f0SHans Verkuil 	0x00, 0x00, 0x00, 0xfd, 0x00, 0x18, 0x55, 0x18,
210dacca5f0SHans Verkuil 	0x87, 0x3c, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20,
211dacca5f0SHans Verkuil 	0x20, 0x20, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x76,
212dacca5f0SHans Verkuil 	0x69, 0x76, 0x69, 0x64, 0x0a, 0x20, 0x20, 0x20,
213dacca5f0SHans Verkuil 	0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x10,
214dacca5f0SHans Verkuil 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
215dacca5f0SHans Verkuil 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7b,
216dacca5f0SHans Verkuil 
217443ec4bbSHans Verkuil 	0x02, 0x03, 0x3f, 0xf1, 0x51, 0x61, 0x60, 0x5f,
218dacca5f0SHans Verkuil 	0x5e, 0x5d, 0x10, 0x1f, 0x04, 0x13, 0x22, 0x21,
219dacca5f0SHans Verkuil 	0x20, 0x05, 0x14, 0x02, 0x11, 0x01, 0x23, 0x09,
220dacca5f0SHans Verkuil 	0x07, 0x07, 0x83, 0x01, 0x00, 0x00, 0x6d, 0x03,
221dacca5f0SHans Verkuil 	0x0c, 0x00, 0x10, 0x00, 0x00, 0x3c, 0x21, 0x00,
222dacca5f0SHans Verkuil 	0x60, 0x01, 0x02, 0x03, 0x67, 0xd8, 0x5d, 0xc4,
223443ec4bbSHans Verkuil 	0x01, 0x78, 0x00, 0x00, 0xe2, 0x00, 0xca, 0xe3,
224dacca5f0SHans Verkuil 	0x05, 0x00, 0x00, 0xe3, 0x06, 0x01, 0x00, 0x4d,
225dacca5f0SHans Verkuil 	0xd0, 0x00, 0xa0, 0xf0, 0x70, 0x3e, 0x80, 0x30,
226dacca5f0SHans Verkuil 	0x20, 0x35, 0x00, 0xc0, 0x1c, 0x32, 0x00, 0x00,
227dacca5f0SHans Verkuil 	0x1e, 0x1a, 0x36, 0x80, 0xa0, 0x70, 0x38, 0x1f,
228dacca5f0SHans Verkuil 	0x40, 0x30, 0x20, 0x35, 0x00, 0xc0, 0x1c, 0x32,
229dacca5f0SHans Verkuil 	0x00, 0x00, 0x1a, 0x1a, 0x1d, 0x00, 0x80, 0x51,
230dacca5f0SHans Verkuil 	0xd0, 0x1c, 0x20, 0x40, 0x80, 0x35, 0x00, 0xc0,
231dacca5f0SHans Verkuil 	0x1c, 0x32, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
232443ec4bbSHans Verkuil 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82,
233dacca5f0SHans Verkuil };
234dacca5f0SHans Verkuil 
vidioc_querycap(struct file * file,void * priv,struct v4l2_capability * cap)235dacca5f0SHans Verkuil static int vidioc_querycap(struct file *file, void  *priv,
236dacca5f0SHans Verkuil 					struct v4l2_capability *cap)
237dacca5f0SHans Verkuil {
238dacca5f0SHans Verkuil 	struct vivid_dev *dev = video_drvdata(file);
239dacca5f0SHans Verkuil 
240dacca5f0SHans Verkuil 	strscpy(cap->driver, "vivid", sizeof(cap->driver));
241dacca5f0SHans Verkuil 	strscpy(cap->card, "vivid", sizeof(cap->card));
242dacca5f0SHans Verkuil 	snprintf(cap->bus_info, sizeof(cap->bus_info),
243dacca5f0SHans Verkuil 			"platform:%s", dev->v4l2_dev.name);
244dacca5f0SHans Verkuil 
245dacca5f0SHans Verkuil 	cap->capabilities = dev->vid_cap_caps | dev->vid_out_caps |
246dacca5f0SHans Verkuil 		dev->vbi_cap_caps | dev->vbi_out_caps |
247dacca5f0SHans Verkuil 		dev->radio_rx_caps | dev->radio_tx_caps |
248dacca5f0SHans Verkuil 		dev->sdr_cap_caps | dev->meta_cap_caps |
249dacca5f0SHans Verkuil 		dev->meta_out_caps | dev->touch_cap_caps |
250dacca5f0SHans Verkuil 		V4L2_CAP_DEVICE_CAPS;
251dacca5f0SHans Verkuil 	return 0;
252dacca5f0SHans Verkuil }
253dacca5f0SHans Verkuil 
vidioc_s_hw_freq_seek(struct file * file,void * fh,const struct v4l2_hw_freq_seek * a)254dacca5f0SHans Verkuil static int vidioc_s_hw_freq_seek(struct file *file, void *fh, const struct v4l2_hw_freq_seek *a)
255dacca5f0SHans Verkuil {
256dacca5f0SHans Verkuil 	struct video_device *vdev = video_devdata(file);
257dacca5f0SHans Verkuil 
258dacca5f0SHans Verkuil 	if (vdev->vfl_type == VFL_TYPE_RADIO)
259dacca5f0SHans Verkuil 		return vivid_radio_rx_s_hw_freq_seek(file, fh, a);
260dacca5f0SHans Verkuil 	return -ENOTTY;
261dacca5f0SHans Verkuil }
262dacca5f0SHans Verkuil 
vidioc_enum_freq_bands(struct file * file,void * fh,struct v4l2_frequency_band * band)263dacca5f0SHans Verkuil static int vidioc_enum_freq_bands(struct file *file, void *fh, struct v4l2_frequency_band *band)
264dacca5f0SHans Verkuil {
265dacca5f0SHans Verkuil 	struct video_device *vdev = video_devdata(file);
266dacca5f0SHans Verkuil 
267dacca5f0SHans Verkuil 	if (vdev->vfl_type == VFL_TYPE_RADIO)
268dacca5f0SHans Verkuil 		return vivid_radio_rx_enum_freq_bands(file, fh, band);
269dacca5f0SHans Verkuil 	if (vdev->vfl_type == VFL_TYPE_SDR)
270dacca5f0SHans Verkuil 		return vivid_sdr_enum_freq_bands(file, fh, band);
271dacca5f0SHans Verkuil 	return -ENOTTY;
272dacca5f0SHans Verkuil }
273dacca5f0SHans Verkuil 
vidioc_g_tuner(struct file * file,void * fh,struct v4l2_tuner * vt)274dacca5f0SHans Verkuil static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
275dacca5f0SHans Verkuil {
276dacca5f0SHans Verkuil 	struct video_device *vdev = video_devdata(file);
277dacca5f0SHans Verkuil 
278dacca5f0SHans Verkuil 	if (vdev->vfl_type == VFL_TYPE_RADIO)
279dacca5f0SHans Verkuil 		return vivid_radio_rx_g_tuner(file, fh, vt);
280dacca5f0SHans Verkuil 	if (vdev->vfl_type == VFL_TYPE_SDR)
281dacca5f0SHans Verkuil 		return vivid_sdr_g_tuner(file, fh, vt);
282dacca5f0SHans Verkuil 	return vivid_video_g_tuner(file, fh, vt);
283dacca5f0SHans Verkuil }
284dacca5f0SHans Verkuil 
vidioc_s_tuner(struct file * file,void * fh,const struct v4l2_tuner * vt)285dacca5f0SHans Verkuil static int vidioc_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *vt)
286dacca5f0SHans Verkuil {
287dacca5f0SHans Verkuil 	struct video_device *vdev = video_devdata(file);
288dacca5f0SHans Verkuil 
289dacca5f0SHans Verkuil 	if (vdev->vfl_type == VFL_TYPE_RADIO)
290dacca5f0SHans Verkuil 		return vivid_radio_rx_s_tuner(file, fh, vt);
291dacca5f0SHans Verkuil 	if (vdev->vfl_type == VFL_TYPE_SDR)
292dacca5f0SHans Verkuil 		return vivid_sdr_s_tuner(file, fh, vt);
293dacca5f0SHans Verkuil 	return vivid_video_s_tuner(file, fh, vt);
294dacca5f0SHans Verkuil }
295dacca5f0SHans Verkuil 
vidioc_g_frequency(struct file * file,void * fh,struct v4l2_frequency * vf)296dacca5f0SHans Verkuil static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
297dacca5f0SHans Verkuil {
298dacca5f0SHans Verkuil 	struct vivid_dev *dev = video_drvdata(file);
299dacca5f0SHans Verkuil 	struct video_device *vdev = video_devdata(file);
300dacca5f0SHans Verkuil 
301dacca5f0SHans Verkuil 	if (vdev->vfl_type == VFL_TYPE_RADIO)
302dacca5f0SHans Verkuil 		return vivid_radio_g_frequency(file,
303dacca5f0SHans Verkuil 			vdev->vfl_dir == VFL_DIR_RX ?
304dacca5f0SHans Verkuil 			&dev->radio_rx_freq : &dev->radio_tx_freq, vf);
305dacca5f0SHans Verkuil 	if (vdev->vfl_type == VFL_TYPE_SDR)
306dacca5f0SHans Verkuil 		return vivid_sdr_g_frequency(file, fh, vf);
307dacca5f0SHans Verkuil 	return vivid_video_g_frequency(file, fh, vf);
308dacca5f0SHans Verkuil }
309dacca5f0SHans Verkuil 
vidioc_s_frequency(struct file * file,void * fh,const struct v4l2_frequency * vf)310dacca5f0SHans Verkuil static int vidioc_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *vf)
311dacca5f0SHans Verkuil {
312dacca5f0SHans Verkuil 	struct vivid_dev *dev = video_drvdata(file);
313dacca5f0SHans Verkuil 	struct video_device *vdev = video_devdata(file);
314dacca5f0SHans Verkuil 
315dacca5f0SHans Verkuil 	if (vdev->vfl_type == VFL_TYPE_RADIO)
316dacca5f0SHans Verkuil 		return vivid_radio_s_frequency(file,
317dacca5f0SHans Verkuil 			vdev->vfl_dir == VFL_DIR_RX ?
318dacca5f0SHans Verkuil 			&dev->radio_rx_freq : &dev->radio_tx_freq, vf);
319dacca5f0SHans Verkuil 	if (vdev->vfl_type == VFL_TYPE_SDR)
320dacca5f0SHans Verkuil 		return vivid_sdr_s_frequency(file, fh, vf);
321dacca5f0SHans Verkuil 	return vivid_video_s_frequency(file, fh, vf);
322dacca5f0SHans Verkuil }
323dacca5f0SHans Verkuil 
vidioc_overlay(struct file * file,void * fh,unsigned i)324dacca5f0SHans Verkuil static int vidioc_overlay(struct file *file, void *fh, unsigned i)
325dacca5f0SHans Verkuil {
326dacca5f0SHans Verkuil 	struct video_device *vdev = video_devdata(file);
327dacca5f0SHans Verkuil 
328dacca5f0SHans Verkuil 	if (vdev->vfl_dir == VFL_DIR_RX)
329ccaa9d50SHans Verkuil 		return -ENOTTY;
330dacca5f0SHans Verkuil 	return vivid_vid_out_overlay(file, fh, i);
331dacca5f0SHans Verkuil }
332dacca5f0SHans Verkuil 
vidioc_g_fbuf(struct file * file,void * fh,struct v4l2_framebuffer * a)333dacca5f0SHans Verkuil static int vidioc_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *a)
334dacca5f0SHans Verkuil {
335dacca5f0SHans Verkuil 	struct video_device *vdev = video_devdata(file);
336dacca5f0SHans Verkuil 
337dacca5f0SHans Verkuil 	if (vdev->vfl_dir == VFL_DIR_RX)
338ccaa9d50SHans Verkuil 		return -ENOTTY;
339dacca5f0SHans Verkuil 	return vivid_vid_out_g_fbuf(file, fh, a);
340dacca5f0SHans Verkuil }
341dacca5f0SHans Verkuil 
vidioc_s_fbuf(struct file * file,void * fh,const struct v4l2_framebuffer * a)342dacca5f0SHans Verkuil static int vidioc_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffer *a)
343dacca5f0SHans Verkuil {
344dacca5f0SHans Verkuil 	struct video_device *vdev = video_devdata(file);
345dacca5f0SHans Verkuil 
346dacca5f0SHans Verkuil 	if (vdev->vfl_dir == VFL_DIR_RX)
347ccaa9d50SHans Verkuil 		return -ENOTTY;
348dacca5f0SHans Verkuil 	return vivid_vid_out_s_fbuf(file, fh, a);
349dacca5f0SHans Verkuil }
350dacca5f0SHans Verkuil 
vidioc_s_std(struct file * file,void * fh,v4l2_std_id id)351dacca5f0SHans Verkuil static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id id)
352dacca5f0SHans Verkuil {
353dacca5f0SHans Verkuil 	struct video_device *vdev = video_devdata(file);
354dacca5f0SHans Verkuil 
355dacca5f0SHans Verkuil 	if (vdev->vfl_dir == VFL_DIR_RX)
356dacca5f0SHans Verkuil 		return vivid_vid_cap_s_std(file, fh, id);
357dacca5f0SHans Verkuil 	return vivid_vid_out_s_std(file, fh, id);
358dacca5f0SHans Verkuil }
359dacca5f0SHans Verkuil 
vidioc_s_dv_timings(struct file * file,void * fh,struct v4l2_dv_timings * timings)360dacca5f0SHans Verkuil static int vidioc_s_dv_timings(struct file *file, void *fh, struct v4l2_dv_timings *timings)
361dacca5f0SHans Verkuil {
362dacca5f0SHans Verkuil 	struct video_device *vdev = video_devdata(file);
363dacca5f0SHans Verkuil 
364dacca5f0SHans Verkuil 	if (vdev->vfl_dir == VFL_DIR_RX)
365dacca5f0SHans Verkuil 		return vivid_vid_cap_s_dv_timings(file, fh, timings);
366dacca5f0SHans Verkuil 	return vivid_vid_out_s_dv_timings(file, fh, timings);
367dacca5f0SHans Verkuil }
368dacca5f0SHans Verkuil 
vidioc_g_pixelaspect(struct file * file,void * fh,int type,struct v4l2_fract * f)369dacca5f0SHans Verkuil static int vidioc_g_pixelaspect(struct file *file, void *fh,
370dacca5f0SHans Verkuil 				int type, struct v4l2_fract *f)
371dacca5f0SHans Verkuil {
372dacca5f0SHans Verkuil 	struct video_device *vdev = video_devdata(file);
373dacca5f0SHans Verkuil 
374dacca5f0SHans Verkuil 	if (vdev->vfl_dir == VFL_DIR_RX)
375dacca5f0SHans Verkuil 		return vivid_vid_cap_g_pixelaspect(file, fh, type, f);
376dacca5f0SHans Verkuil 	return vivid_vid_out_g_pixelaspect(file, fh, type, f);
377dacca5f0SHans Verkuil }
378dacca5f0SHans Verkuil 
vidioc_g_selection(struct file * file,void * fh,struct v4l2_selection * sel)379dacca5f0SHans Verkuil static int vidioc_g_selection(struct file *file, void *fh,
380dacca5f0SHans Verkuil 			      struct v4l2_selection *sel)
381dacca5f0SHans Verkuil {
382dacca5f0SHans Verkuil 	struct video_device *vdev = video_devdata(file);
383dacca5f0SHans Verkuil 
384dacca5f0SHans Verkuil 	if (vdev->vfl_dir == VFL_DIR_RX)
385dacca5f0SHans Verkuil 		return vivid_vid_cap_g_selection(file, fh, sel);
386dacca5f0SHans Verkuil 	return vivid_vid_out_g_selection(file, fh, sel);
387dacca5f0SHans Verkuil }
388dacca5f0SHans Verkuil 
vidioc_s_selection(struct file * file,void * fh,struct v4l2_selection * sel)389dacca5f0SHans Verkuil static int vidioc_s_selection(struct file *file, void *fh,
390dacca5f0SHans Verkuil 			      struct v4l2_selection *sel)
391dacca5f0SHans Verkuil {
392dacca5f0SHans Verkuil 	struct video_device *vdev = video_devdata(file);
393dacca5f0SHans Verkuil 
394dacca5f0SHans Verkuil 	if (vdev->vfl_dir == VFL_DIR_RX)
395dacca5f0SHans Verkuil 		return vivid_vid_cap_s_selection(file, fh, sel);
396dacca5f0SHans Verkuil 	return vivid_vid_out_s_selection(file, fh, sel);
397dacca5f0SHans Verkuil }
398dacca5f0SHans Verkuil 
vidioc_g_parm(struct file * file,void * fh,struct v4l2_streamparm * parm)399dacca5f0SHans Verkuil static int vidioc_g_parm(struct file *file, void *fh,
400dacca5f0SHans Verkuil 			  struct v4l2_streamparm *parm)
401dacca5f0SHans Verkuil {
402dacca5f0SHans Verkuil 	struct video_device *vdev = video_devdata(file);
403dacca5f0SHans Verkuil 
404dacca5f0SHans Verkuil 	if (vdev->vfl_type == VFL_TYPE_TOUCH)
405dacca5f0SHans Verkuil 		return vivid_g_parm_tch(file, fh, parm);
406dacca5f0SHans Verkuil 	if (vdev->vfl_dir == VFL_DIR_RX)
407dacca5f0SHans Verkuil 		return vivid_vid_cap_g_parm(file, fh, parm);
408dacca5f0SHans Verkuil 	return vivid_vid_out_g_parm(file, fh, parm);
409dacca5f0SHans Verkuil }
410dacca5f0SHans Verkuil 
vidioc_s_parm(struct file * file,void * fh,struct v4l2_streamparm * parm)411dacca5f0SHans Verkuil static int vidioc_s_parm(struct file *file, void *fh,
412dacca5f0SHans Verkuil 			  struct v4l2_streamparm *parm)
413dacca5f0SHans Verkuil {
414dacca5f0SHans Verkuil 	struct video_device *vdev = video_devdata(file);
415dacca5f0SHans Verkuil 
416dacca5f0SHans Verkuil 	if (vdev->vfl_dir == VFL_DIR_RX)
417dacca5f0SHans Verkuil 		return vivid_vid_cap_s_parm(file, fh, parm);
418dacca5f0SHans Verkuil 	return -ENOTTY;
419dacca5f0SHans Verkuil }
420dacca5f0SHans Verkuil 
vidioc_log_status(struct file * file,void * fh)421dacca5f0SHans Verkuil static int vidioc_log_status(struct file *file, void *fh)
422dacca5f0SHans Verkuil {
423dacca5f0SHans Verkuil 	struct vivid_dev *dev = video_drvdata(file);
424dacca5f0SHans Verkuil 	struct video_device *vdev = video_devdata(file);
425dacca5f0SHans Verkuil 
426dacca5f0SHans Verkuil 	v4l2_ctrl_log_status(file, fh);
427dacca5f0SHans Verkuil 	if (vdev->vfl_dir == VFL_DIR_RX && vdev->vfl_type == VFL_TYPE_VIDEO)
428dacca5f0SHans Verkuil 		tpg_log_status(&dev->tpg);
429dacca5f0SHans Verkuil 	return 0;
430dacca5f0SHans Verkuil }
431dacca5f0SHans Verkuil 
vivid_radio_read(struct file * file,char __user * buf,size_t size,loff_t * offset)432dacca5f0SHans Verkuil static ssize_t vivid_radio_read(struct file *file, char __user *buf,
433dacca5f0SHans Verkuil 			 size_t size, loff_t *offset)
434dacca5f0SHans Verkuil {
435dacca5f0SHans Verkuil 	struct video_device *vdev = video_devdata(file);
436dacca5f0SHans Verkuil 
437dacca5f0SHans Verkuil 	if (vdev->vfl_dir == VFL_DIR_TX)
438dacca5f0SHans Verkuil 		return -EINVAL;
439dacca5f0SHans Verkuil 	return vivid_radio_rx_read(file, buf, size, offset);
440dacca5f0SHans Verkuil }
441dacca5f0SHans Verkuil 
vivid_radio_write(struct file * file,const char __user * buf,size_t size,loff_t * offset)442dacca5f0SHans Verkuil static ssize_t vivid_radio_write(struct file *file, const char __user *buf,
443dacca5f0SHans Verkuil 			  size_t size, loff_t *offset)
444dacca5f0SHans Verkuil {
445dacca5f0SHans Verkuil 	struct video_device *vdev = video_devdata(file);
446dacca5f0SHans Verkuil 
447dacca5f0SHans Verkuil 	if (vdev->vfl_dir == VFL_DIR_RX)
448dacca5f0SHans Verkuil 		return -EINVAL;
449dacca5f0SHans Verkuil 	return vivid_radio_tx_write(file, buf, size, offset);
450dacca5f0SHans Verkuil }
451dacca5f0SHans Verkuil 
vivid_radio_poll(struct file * file,struct poll_table_struct * wait)452dacca5f0SHans Verkuil static __poll_t vivid_radio_poll(struct file *file, struct poll_table_struct *wait)
453dacca5f0SHans Verkuil {
454dacca5f0SHans Verkuil 	struct video_device *vdev = video_devdata(file);
455dacca5f0SHans Verkuil 
456dacca5f0SHans Verkuil 	if (vdev->vfl_dir == VFL_DIR_RX)
457dacca5f0SHans Verkuil 		return vivid_radio_rx_poll(file, wait);
458dacca5f0SHans Verkuil 	return vivid_radio_tx_poll(file, wait);
459dacca5f0SHans Verkuil }
460dacca5f0SHans Verkuil 
vivid_enum_input(struct file * file,void * priv,struct v4l2_input * inp)461dacca5f0SHans Verkuil static int vivid_enum_input(struct file *file, void *priv,
462dacca5f0SHans Verkuil 			    struct v4l2_input *inp)
463dacca5f0SHans Verkuil {
464dacca5f0SHans Verkuil 	struct video_device *vdev = video_devdata(file);
465dacca5f0SHans Verkuil 
466dacca5f0SHans Verkuil 	if (vdev->vfl_type == VFL_TYPE_TOUCH)
467dacca5f0SHans Verkuil 		return vivid_enum_input_tch(file, priv, inp);
468dacca5f0SHans Verkuil 	return vidioc_enum_input(file, priv, inp);
469dacca5f0SHans Verkuil }
470dacca5f0SHans Verkuil 
vivid_g_input(struct file * file,void * priv,unsigned int * i)471dacca5f0SHans Verkuil static int vivid_g_input(struct file *file, void *priv, unsigned int *i)
472dacca5f0SHans Verkuil {
473dacca5f0SHans Verkuil 	struct video_device *vdev = video_devdata(file);
474dacca5f0SHans Verkuil 
475dacca5f0SHans Verkuil 	if (vdev->vfl_type == VFL_TYPE_TOUCH)
476dacca5f0SHans Verkuil 		return vivid_g_input_tch(file, priv, i);
477dacca5f0SHans Verkuil 	return vidioc_g_input(file, priv, i);
478dacca5f0SHans Verkuil }
479dacca5f0SHans Verkuil 
vivid_s_input(struct file * file,void * priv,unsigned int i)480dacca5f0SHans Verkuil static int vivid_s_input(struct file *file, void *priv, unsigned int i)
481dacca5f0SHans Verkuil {
482dacca5f0SHans Verkuil 	struct video_device *vdev = video_devdata(file);
483dacca5f0SHans Verkuil 
484dacca5f0SHans Verkuil 	if (vdev->vfl_type == VFL_TYPE_TOUCH)
485dacca5f0SHans Verkuil 		return vivid_s_input_tch(file, priv, i);
486dacca5f0SHans Verkuil 	return vidioc_s_input(file, priv, i);
487dacca5f0SHans Verkuil }
488dacca5f0SHans Verkuil 
vivid_enum_fmt_cap(struct file * file,void * priv,struct v4l2_fmtdesc * f)489dacca5f0SHans Verkuil static int vivid_enum_fmt_cap(struct file *file, void  *priv,
490dacca5f0SHans Verkuil 			      struct v4l2_fmtdesc *f)
491dacca5f0SHans Verkuil {
492dacca5f0SHans Verkuil 	struct video_device *vdev = video_devdata(file);
493dacca5f0SHans Verkuil 
494dacca5f0SHans Verkuil 	if (vdev->vfl_type == VFL_TYPE_TOUCH)
495dacca5f0SHans Verkuil 		return vivid_enum_fmt_tch(file, priv, f);
496dacca5f0SHans Verkuil 	return vivid_enum_fmt_vid(file, priv, f);
497dacca5f0SHans Verkuil }
498dacca5f0SHans Verkuil 
vivid_g_fmt_cap(struct file * file,void * priv,struct v4l2_format * f)499dacca5f0SHans Verkuil static int vivid_g_fmt_cap(struct file *file, void *priv,
500dacca5f0SHans Verkuil 			   struct v4l2_format *f)
501dacca5f0SHans Verkuil {
502dacca5f0SHans Verkuil 	struct video_device *vdev = video_devdata(file);
503dacca5f0SHans Verkuil 
504dacca5f0SHans Verkuil 	if (vdev->vfl_type == VFL_TYPE_TOUCH)
505dacca5f0SHans Verkuil 		return vivid_g_fmt_tch(file, priv, f);
506dacca5f0SHans Verkuil 	return vidioc_g_fmt_vid_cap(file, priv, f);
507dacca5f0SHans Verkuil }
508dacca5f0SHans Verkuil 
vivid_try_fmt_cap(struct file * file,void * priv,struct v4l2_format * f)509dacca5f0SHans Verkuil static int vivid_try_fmt_cap(struct file *file, void *priv,
510dacca5f0SHans Verkuil 			     struct v4l2_format *f)
511dacca5f0SHans Verkuil {
512dacca5f0SHans Verkuil 	struct video_device *vdev = video_devdata(file);
513dacca5f0SHans Verkuil 
514dacca5f0SHans Verkuil 	if (vdev->vfl_type == VFL_TYPE_TOUCH)
515dacca5f0SHans Verkuil 		return vivid_g_fmt_tch(file, priv, f);
516dacca5f0SHans Verkuil 	return vidioc_try_fmt_vid_cap(file, priv, f);
517dacca5f0SHans Verkuil }
518dacca5f0SHans Verkuil 
vivid_s_fmt_cap(struct file * file,void * priv,struct v4l2_format * f)519dacca5f0SHans Verkuil static int vivid_s_fmt_cap(struct file *file, void *priv,
520dacca5f0SHans Verkuil 			   struct v4l2_format *f)
521dacca5f0SHans Verkuil {
522dacca5f0SHans Verkuil 	struct video_device *vdev = video_devdata(file);
523dacca5f0SHans Verkuil 
524dacca5f0SHans Verkuil 	if (vdev->vfl_type == VFL_TYPE_TOUCH)
525dacca5f0SHans Verkuil 		return vivid_g_fmt_tch(file, priv, f);
526dacca5f0SHans Verkuil 	return vidioc_s_fmt_vid_cap(file, priv, f);
527dacca5f0SHans Verkuil }
528dacca5f0SHans Verkuil 
vivid_g_fmt_cap_mplane(struct file * file,void * priv,struct v4l2_format * f)529dacca5f0SHans Verkuil static int vivid_g_fmt_cap_mplane(struct file *file, void *priv,
530dacca5f0SHans Verkuil 				  struct v4l2_format *f)
531dacca5f0SHans Verkuil {
532dacca5f0SHans Verkuil 	struct video_device *vdev = video_devdata(file);
533dacca5f0SHans Verkuil 
534dacca5f0SHans Verkuil 	if (vdev->vfl_type == VFL_TYPE_TOUCH)
535dacca5f0SHans Verkuil 		return vivid_g_fmt_tch_mplane(file, priv, f);
536dacca5f0SHans Verkuil 	return vidioc_g_fmt_vid_cap_mplane(file, priv, f);
537dacca5f0SHans Verkuil }
538dacca5f0SHans Verkuil 
vivid_try_fmt_cap_mplane(struct file * file,void * priv,struct v4l2_format * f)539dacca5f0SHans Verkuil static int vivid_try_fmt_cap_mplane(struct file *file, void *priv,
540dacca5f0SHans Verkuil 				    struct v4l2_format *f)
541dacca5f0SHans Verkuil {
542dacca5f0SHans Verkuil 	struct video_device *vdev = video_devdata(file);
543dacca5f0SHans Verkuil 
544dacca5f0SHans Verkuil 	if (vdev->vfl_type == VFL_TYPE_TOUCH)
545dacca5f0SHans Verkuil 		return vivid_g_fmt_tch_mplane(file, priv, f);
546dacca5f0SHans Verkuil 	return vidioc_try_fmt_vid_cap_mplane(file, priv, f);
547dacca5f0SHans Verkuil }
548dacca5f0SHans Verkuil 
vivid_s_fmt_cap_mplane(struct file * file,void * priv,struct v4l2_format * f)549dacca5f0SHans Verkuil static int vivid_s_fmt_cap_mplane(struct file *file, void *priv,
550dacca5f0SHans Verkuil 				  struct v4l2_format *f)
551dacca5f0SHans Verkuil {
552dacca5f0SHans Verkuil 	struct video_device *vdev = video_devdata(file);
553dacca5f0SHans Verkuil 
554dacca5f0SHans Verkuil 	if (vdev->vfl_type == VFL_TYPE_TOUCH)
555dacca5f0SHans Verkuil 		return vivid_g_fmt_tch_mplane(file, priv, f);
556dacca5f0SHans Verkuil 	return vidioc_s_fmt_vid_cap_mplane(file, priv, f);
557dacca5f0SHans Verkuil }
558dacca5f0SHans Verkuil 
vivid_is_in_use(bool valid,struct video_device * vdev)5599e5f21d6SHans Verkuil static bool vivid_is_in_use(bool valid, struct video_device *vdev)
560dacca5f0SHans Verkuil {
561dacca5f0SHans Verkuil 	unsigned long flags;
562dacca5f0SHans Verkuil 	bool res;
563dacca5f0SHans Verkuil 
5649e5f21d6SHans Verkuil 	if (!valid)
5659e5f21d6SHans Verkuil 		return false;
566dacca5f0SHans Verkuil 	spin_lock_irqsave(&vdev->fh_lock, flags);
567dacca5f0SHans Verkuil 	res = !list_empty(&vdev->fh_list);
568dacca5f0SHans Verkuil 	spin_unlock_irqrestore(&vdev->fh_lock, flags);
569dacca5f0SHans Verkuil 	return res;
570dacca5f0SHans Verkuil }
571dacca5f0SHans Verkuil 
vivid_is_last_user(struct vivid_dev * dev)572dacca5f0SHans Verkuil static bool vivid_is_last_user(struct vivid_dev *dev)
573dacca5f0SHans Verkuil {
5749e5f21d6SHans Verkuil 	unsigned int uses =
5759e5f21d6SHans Verkuil 		vivid_is_in_use(dev->has_vid_cap, &dev->vid_cap_dev) +
5769e5f21d6SHans Verkuil 		vivid_is_in_use(dev->has_vid_out, &dev->vid_out_dev) +
5779e5f21d6SHans Verkuil 		vivid_is_in_use(dev->has_vbi_cap, &dev->vbi_cap_dev) +
5789e5f21d6SHans Verkuil 		vivid_is_in_use(dev->has_vbi_out, &dev->vbi_out_dev) +
5799e5f21d6SHans Verkuil 		vivid_is_in_use(dev->has_radio_rx, &dev->radio_rx_dev) +
5809e5f21d6SHans Verkuil 		vivid_is_in_use(dev->has_radio_tx, &dev->radio_tx_dev) +
5819e5f21d6SHans Verkuil 		vivid_is_in_use(dev->has_sdr_cap, &dev->sdr_cap_dev) +
5829e5f21d6SHans Verkuil 		vivid_is_in_use(dev->has_meta_cap, &dev->meta_cap_dev) +
5839e5f21d6SHans Verkuil 		vivid_is_in_use(dev->has_meta_out, &dev->meta_out_dev) +
5849e5f21d6SHans Verkuil 		vivid_is_in_use(dev->has_touch_cap, &dev->touch_cap_dev);
585dacca5f0SHans Verkuil 
586dacca5f0SHans Verkuil 	return uses == 1;
587dacca5f0SHans Verkuil }
588dacca5f0SHans Verkuil 
vivid_reconnect(struct vivid_dev * dev)5899e5f21d6SHans Verkuil static void vivid_reconnect(struct vivid_dev *dev)
5909e5f21d6SHans Verkuil {
5919e5f21d6SHans Verkuil 	if (dev->has_vid_cap)
5929e5f21d6SHans Verkuil 		set_bit(V4L2_FL_REGISTERED, &dev->vid_cap_dev.flags);
5939e5f21d6SHans Verkuil 	if (dev->has_vid_out)
5949e5f21d6SHans Verkuil 		set_bit(V4L2_FL_REGISTERED, &dev->vid_out_dev.flags);
5959e5f21d6SHans Verkuil 	if (dev->has_vbi_cap)
5969e5f21d6SHans Verkuil 		set_bit(V4L2_FL_REGISTERED, &dev->vbi_cap_dev.flags);
5979e5f21d6SHans Verkuil 	if (dev->has_vbi_out)
5989e5f21d6SHans Verkuil 		set_bit(V4L2_FL_REGISTERED, &dev->vbi_out_dev.flags);
5999e5f21d6SHans Verkuil 	if (dev->has_radio_rx)
6009e5f21d6SHans Verkuil 		set_bit(V4L2_FL_REGISTERED, &dev->radio_rx_dev.flags);
6019e5f21d6SHans Verkuil 	if (dev->has_radio_tx)
6029e5f21d6SHans Verkuil 		set_bit(V4L2_FL_REGISTERED, &dev->radio_tx_dev.flags);
6039e5f21d6SHans Verkuil 	if (dev->has_sdr_cap)
6049e5f21d6SHans Verkuil 		set_bit(V4L2_FL_REGISTERED, &dev->sdr_cap_dev.flags);
6059e5f21d6SHans Verkuil 	if (dev->has_meta_cap)
6069e5f21d6SHans Verkuil 		set_bit(V4L2_FL_REGISTERED, &dev->meta_cap_dev.flags);
6079e5f21d6SHans Verkuil 	if (dev->has_meta_out)
6089e5f21d6SHans Verkuil 		set_bit(V4L2_FL_REGISTERED, &dev->meta_out_dev.flags);
6099e5f21d6SHans Verkuil 	if (dev->has_touch_cap)
6109e5f21d6SHans Verkuil 		set_bit(V4L2_FL_REGISTERED, &dev->touch_cap_dev.flags);
6119e5f21d6SHans Verkuil 	dev->disconnect_error = false;
6129e5f21d6SHans Verkuil }
6139e5f21d6SHans Verkuil 
vivid_fop_release(struct file * file)614dacca5f0SHans Verkuil static int vivid_fop_release(struct file *file)
615dacca5f0SHans Verkuil {
616dacca5f0SHans Verkuil 	struct vivid_dev *dev = video_drvdata(file);
617dacca5f0SHans Verkuil 	struct video_device *vdev = video_devdata(file);
618dacca5f0SHans Verkuil 
619dacca5f0SHans Verkuil 	mutex_lock(&dev->mutex);
620dacca5f0SHans Verkuil 	if (!no_error_inj && v4l2_fh_is_singular_file(file) &&
6219e5f21d6SHans Verkuil 	    dev->disconnect_error && !video_is_registered(vdev) &&
6229e5f21d6SHans Verkuil 	    vivid_is_last_user(dev)) {
623dacca5f0SHans Verkuil 		/*
624dacca5f0SHans Verkuil 		 * I am the last user of this driver, and a disconnect
625dacca5f0SHans Verkuil 		 * was forced (since this video_device is unregistered),
626dacca5f0SHans Verkuil 		 * so re-register all video_device's again.
627dacca5f0SHans Verkuil 		 */
628dacca5f0SHans Verkuil 		v4l2_info(&dev->v4l2_dev, "reconnect\n");
6299e5f21d6SHans Verkuil 		vivid_reconnect(dev);
630dacca5f0SHans Verkuil 	}
631dacca5f0SHans Verkuil 	if (file->private_data == dev->radio_rx_rds_owner) {
632dacca5f0SHans Verkuil 		dev->radio_rx_rds_last_block = 0;
633dacca5f0SHans Verkuil 		dev->radio_rx_rds_owner = NULL;
634dacca5f0SHans Verkuil 	}
635dacca5f0SHans Verkuil 	if (file->private_data == dev->radio_tx_rds_owner) {
636dacca5f0SHans Verkuil 		dev->radio_tx_rds_last_block = 0;
637dacca5f0SHans Verkuil 		dev->radio_tx_rds_owner = NULL;
638dacca5f0SHans Verkuil 	}
639*54921a8fSSishuai Gong 	mutex_unlock(&dev->mutex);
640dacca5f0SHans Verkuil 	if (vdev->queue)
641dacca5f0SHans Verkuil 		return vb2_fop_release(file);
642dacca5f0SHans Verkuil 	return v4l2_fh_release(file);
643dacca5f0SHans Verkuil }
644dacca5f0SHans Verkuil 
645dacca5f0SHans Verkuil static const struct v4l2_file_operations vivid_fops = {
646dacca5f0SHans Verkuil 	.owner		= THIS_MODULE,
647dacca5f0SHans Verkuil 	.open           = v4l2_fh_open,
648dacca5f0SHans Verkuil 	.release        = vivid_fop_release,
649dacca5f0SHans Verkuil 	.read           = vb2_fop_read,
650dacca5f0SHans Verkuil 	.write          = vb2_fop_write,
651dacca5f0SHans Verkuil 	.poll		= vb2_fop_poll,
652dacca5f0SHans Verkuil 	.unlocked_ioctl = video_ioctl2,
653dacca5f0SHans Verkuil 	.mmap           = vb2_fop_mmap,
654dacca5f0SHans Verkuil };
655dacca5f0SHans Verkuil 
656dacca5f0SHans Verkuil static const struct v4l2_file_operations vivid_radio_fops = {
657dacca5f0SHans Verkuil 	.owner		= THIS_MODULE,
658dacca5f0SHans Verkuil 	.open           = v4l2_fh_open,
659dacca5f0SHans Verkuil 	.release        = vivid_fop_release,
660dacca5f0SHans Verkuil 	.read           = vivid_radio_read,
661dacca5f0SHans Verkuil 	.write          = vivid_radio_write,
662dacca5f0SHans Verkuil 	.poll		= vivid_radio_poll,
663dacca5f0SHans Verkuil 	.unlocked_ioctl = video_ioctl2,
664dacca5f0SHans Verkuil };
665dacca5f0SHans Verkuil 
vidioc_reqbufs(struct file * file,void * priv,struct v4l2_requestbuffers * p)666c9cbf021STomi Valkeinen static int vidioc_reqbufs(struct file *file, void *priv,
667c9cbf021STomi Valkeinen 			  struct v4l2_requestbuffers *p)
668c9cbf021STomi Valkeinen {
669c9cbf021STomi Valkeinen 	struct video_device *vdev = video_devdata(file);
670c9cbf021STomi Valkeinen 	int r;
671c9cbf021STomi Valkeinen 
672c9cbf021STomi Valkeinen 	/*
673c9cbf021STomi Valkeinen 	 * Sliced and raw VBI capture share the same queue so we must
674c9cbf021STomi Valkeinen 	 * change the type.
675c9cbf021STomi Valkeinen 	 */
676c9cbf021STomi Valkeinen 	if (p->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE ||
677c9cbf021STomi Valkeinen 	    p->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
678c9cbf021STomi Valkeinen 		r = vb2_queue_change_type(vdev->queue, p->type);
679c9cbf021STomi Valkeinen 		if (r)
680c9cbf021STomi Valkeinen 			return r;
681c9cbf021STomi Valkeinen 	}
682c9cbf021STomi Valkeinen 
683c9cbf021STomi Valkeinen 	return vb2_ioctl_reqbufs(file, priv, p);
684c9cbf021STomi Valkeinen }
685c9cbf021STomi Valkeinen 
vidioc_create_bufs(struct file * file,void * priv,struct v4l2_create_buffers * p)686c9cbf021STomi Valkeinen static int vidioc_create_bufs(struct file *file, void *priv,
687c9cbf021STomi Valkeinen 			      struct v4l2_create_buffers *p)
688c9cbf021STomi Valkeinen {
689c9cbf021STomi Valkeinen 	struct video_device *vdev = video_devdata(file);
690c9cbf021STomi Valkeinen 	int r;
691c9cbf021STomi Valkeinen 
692c9cbf021STomi Valkeinen 	/*
693c9cbf021STomi Valkeinen 	 * Sliced and raw VBI capture share the same queue so we must
694c9cbf021STomi Valkeinen 	 * change the type.
695c9cbf021STomi Valkeinen 	 */
696c9cbf021STomi Valkeinen 	if (p->format.type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE ||
697c9cbf021STomi Valkeinen 	    p->format.type == V4L2_BUF_TYPE_VBI_CAPTURE) {
698c9cbf021STomi Valkeinen 		r = vb2_queue_change_type(vdev->queue, p->format.type);
699c9cbf021STomi Valkeinen 		if (r)
700c9cbf021STomi Valkeinen 			return r;
701c9cbf021STomi Valkeinen 	}
702c9cbf021STomi Valkeinen 
703c9cbf021STomi Valkeinen 	return vb2_ioctl_create_bufs(file, priv, p);
704c9cbf021STomi Valkeinen }
705c9cbf021STomi Valkeinen 
706dacca5f0SHans Verkuil static const struct v4l2_ioctl_ops vivid_ioctl_ops = {
707dacca5f0SHans Verkuil 	.vidioc_querycap		= vidioc_querycap,
708dacca5f0SHans Verkuil 
709dacca5f0SHans Verkuil 	.vidioc_enum_fmt_vid_cap	= vivid_enum_fmt_cap,
710dacca5f0SHans Verkuil 	.vidioc_g_fmt_vid_cap		= vivid_g_fmt_cap,
711dacca5f0SHans Verkuil 	.vidioc_try_fmt_vid_cap		= vivid_try_fmt_cap,
712dacca5f0SHans Verkuil 	.vidioc_s_fmt_vid_cap		= vivid_s_fmt_cap,
713dacca5f0SHans Verkuil 	.vidioc_g_fmt_vid_cap_mplane	= vivid_g_fmt_cap_mplane,
714dacca5f0SHans Verkuil 	.vidioc_try_fmt_vid_cap_mplane	= vivid_try_fmt_cap_mplane,
715dacca5f0SHans Verkuil 	.vidioc_s_fmt_vid_cap_mplane	= vivid_s_fmt_cap_mplane,
716dacca5f0SHans Verkuil 
717dacca5f0SHans Verkuil 	.vidioc_enum_fmt_vid_out	= vivid_enum_fmt_vid,
718dacca5f0SHans Verkuil 	.vidioc_g_fmt_vid_out		= vidioc_g_fmt_vid_out,
719dacca5f0SHans Verkuil 	.vidioc_try_fmt_vid_out		= vidioc_try_fmt_vid_out,
720dacca5f0SHans Verkuil 	.vidioc_s_fmt_vid_out		= vidioc_s_fmt_vid_out,
721dacca5f0SHans Verkuil 	.vidioc_g_fmt_vid_out_mplane	= vidioc_g_fmt_vid_out_mplane,
722dacca5f0SHans Verkuil 	.vidioc_try_fmt_vid_out_mplane	= vidioc_try_fmt_vid_out_mplane,
723dacca5f0SHans Verkuil 	.vidioc_s_fmt_vid_out_mplane	= vidioc_s_fmt_vid_out_mplane,
724dacca5f0SHans Verkuil 
725dacca5f0SHans Verkuil 	.vidioc_g_selection		= vidioc_g_selection,
726dacca5f0SHans Verkuil 	.vidioc_s_selection		= vidioc_s_selection,
727dacca5f0SHans Verkuil 	.vidioc_g_pixelaspect		= vidioc_g_pixelaspect,
728dacca5f0SHans Verkuil 
729dacca5f0SHans Verkuil 	.vidioc_g_fmt_vbi_cap		= vidioc_g_fmt_vbi_cap,
730dacca5f0SHans Verkuil 	.vidioc_try_fmt_vbi_cap		= vidioc_g_fmt_vbi_cap,
731dacca5f0SHans Verkuil 	.vidioc_s_fmt_vbi_cap		= vidioc_s_fmt_vbi_cap,
732dacca5f0SHans Verkuil 
733dacca5f0SHans Verkuil 	.vidioc_g_fmt_sliced_vbi_cap    = vidioc_g_fmt_sliced_vbi_cap,
734dacca5f0SHans Verkuil 	.vidioc_try_fmt_sliced_vbi_cap  = vidioc_try_fmt_sliced_vbi_cap,
735dacca5f0SHans Verkuil 	.vidioc_s_fmt_sliced_vbi_cap    = vidioc_s_fmt_sliced_vbi_cap,
736dacca5f0SHans Verkuil 	.vidioc_g_sliced_vbi_cap	= vidioc_g_sliced_vbi_cap,
737dacca5f0SHans Verkuil 
738dacca5f0SHans Verkuil 	.vidioc_g_fmt_vbi_out		= vidioc_g_fmt_vbi_out,
739dacca5f0SHans Verkuil 	.vidioc_try_fmt_vbi_out		= vidioc_g_fmt_vbi_out,
740dacca5f0SHans Verkuil 	.vidioc_s_fmt_vbi_out		= vidioc_s_fmt_vbi_out,
741dacca5f0SHans Verkuil 
742dacca5f0SHans Verkuil 	.vidioc_g_fmt_sliced_vbi_out    = vidioc_g_fmt_sliced_vbi_out,
743dacca5f0SHans Verkuil 	.vidioc_try_fmt_sliced_vbi_out  = vidioc_try_fmt_sliced_vbi_out,
744dacca5f0SHans Verkuil 	.vidioc_s_fmt_sliced_vbi_out    = vidioc_s_fmt_sliced_vbi_out,
745dacca5f0SHans Verkuil 
746dacca5f0SHans Verkuil 	.vidioc_enum_fmt_sdr_cap	= vidioc_enum_fmt_sdr_cap,
747dacca5f0SHans Verkuil 	.vidioc_g_fmt_sdr_cap		= vidioc_g_fmt_sdr_cap,
748dacca5f0SHans Verkuil 	.vidioc_try_fmt_sdr_cap		= vidioc_try_fmt_sdr_cap,
749dacca5f0SHans Verkuil 	.vidioc_s_fmt_sdr_cap		= vidioc_s_fmt_sdr_cap,
750dacca5f0SHans Verkuil 
751dacca5f0SHans Verkuil 	.vidioc_overlay			= vidioc_overlay,
752dacca5f0SHans Verkuil 	.vidioc_enum_framesizes		= vidioc_enum_framesizes,
753dacca5f0SHans Verkuil 	.vidioc_enum_frameintervals	= vidioc_enum_frameintervals,
754dacca5f0SHans Verkuil 	.vidioc_g_parm			= vidioc_g_parm,
755dacca5f0SHans Verkuil 	.vidioc_s_parm			= vidioc_s_parm,
756dacca5f0SHans Verkuil 
757dacca5f0SHans Verkuil 	.vidioc_g_fmt_vid_out_overlay	= vidioc_g_fmt_vid_out_overlay,
758dacca5f0SHans Verkuil 	.vidioc_try_fmt_vid_out_overlay	= vidioc_try_fmt_vid_out_overlay,
759dacca5f0SHans Verkuil 	.vidioc_s_fmt_vid_out_overlay	= vidioc_s_fmt_vid_out_overlay,
760dacca5f0SHans Verkuil 	.vidioc_g_fbuf			= vidioc_g_fbuf,
761dacca5f0SHans Verkuil 	.vidioc_s_fbuf			= vidioc_s_fbuf,
762dacca5f0SHans Verkuil 
763c9cbf021STomi Valkeinen 	.vidioc_reqbufs			= vidioc_reqbufs,
764c9cbf021STomi Valkeinen 	.vidioc_create_bufs		= vidioc_create_bufs,
765dacca5f0SHans Verkuil 	.vidioc_prepare_buf		= vb2_ioctl_prepare_buf,
766dacca5f0SHans Verkuil 	.vidioc_querybuf		= vb2_ioctl_querybuf,
767dacca5f0SHans Verkuil 	.vidioc_qbuf			= vb2_ioctl_qbuf,
768dacca5f0SHans Verkuil 	.vidioc_dqbuf			= vb2_ioctl_dqbuf,
769dacca5f0SHans Verkuil 	.vidioc_expbuf			= vb2_ioctl_expbuf,
770dacca5f0SHans Verkuil 	.vidioc_streamon		= vb2_ioctl_streamon,
771dacca5f0SHans Verkuil 	.vidioc_streamoff		= vb2_ioctl_streamoff,
772dacca5f0SHans Verkuil 
773dacca5f0SHans Verkuil 	.vidioc_enum_input		= vivid_enum_input,
774dacca5f0SHans Verkuil 	.vidioc_g_input			= vivid_g_input,
775dacca5f0SHans Verkuil 	.vidioc_s_input			= vivid_s_input,
776dacca5f0SHans Verkuil 	.vidioc_s_audio			= vidioc_s_audio,
777dacca5f0SHans Verkuil 	.vidioc_g_audio			= vidioc_g_audio,
778dacca5f0SHans Verkuil 	.vidioc_enumaudio		= vidioc_enumaudio,
779dacca5f0SHans Verkuil 	.vidioc_s_frequency		= vidioc_s_frequency,
780dacca5f0SHans Verkuil 	.vidioc_g_frequency		= vidioc_g_frequency,
781dacca5f0SHans Verkuil 	.vidioc_s_tuner			= vidioc_s_tuner,
782dacca5f0SHans Verkuil 	.vidioc_g_tuner			= vidioc_g_tuner,
783dacca5f0SHans Verkuil 	.vidioc_s_modulator		= vidioc_s_modulator,
784dacca5f0SHans Verkuil 	.vidioc_g_modulator		= vidioc_g_modulator,
785dacca5f0SHans Verkuil 	.vidioc_s_hw_freq_seek		= vidioc_s_hw_freq_seek,
786dacca5f0SHans Verkuil 	.vidioc_enum_freq_bands		= vidioc_enum_freq_bands,
787dacca5f0SHans Verkuil 
788dacca5f0SHans Verkuil 	.vidioc_enum_output		= vidioc_enum_output,
789dacca5f0SHans Verkuil 	.vidioc_g_output		= vidioc_g_output,
790dacca5f0SHans Verkuil 	.vidioc_s_output		= vidioc_s_output,
791dacca5f0SHans Verkuil 	.vidioc_s_audout		= vidioc_s_audout,
792dacca5f0SHans Verkuil 	.vidioc_g_audout		= vidioc_g_audout,
793dacca5f0SHans Verkuil 	.vidioc_enumaudout		= vidioc_enumaudout,
794dacca5f0SHans Verkuil 
795dacca5f0SHans Verkuil 	.vidioc_querystd		= vidioc_querystd,
796dacca5f0SHans Verkuil 	.vidioc_g_std			= vidioc_g_std,
797dacca5f0SHans Verkuil 	.vidioc_s_std			= vidioc_s_std,
798dacca5f0SHans Verkuil 	.vidioc_s_dv_timings		= vidioc_s_dv_timings,
799dacca5f0SHans Verkuil 	.vidioc_g_dv_timings		= vidioc_g_dv_timings,
800dacca5f0SHans Verkuil 	.vidioc_query_dv_timings	= vidioc_query_dv_timings,
801dacca5f0SHans Verkuil 	.vidioc_enum_dv_timings		= vidioc_enum_dv_timings,
802dacca5f0SHans Verkuil 	.vidioc_dv_timings_cap		= vidioc_dv_timings_cap,
803dacca5f0SHans Verkuil 	.vidioc_g_edid			= vidioc_g_edid,
804dacca5f0SHans Verkuil 	.vidioc_s_edid			= vidioc_s_edid,
805dacca5f0SHans Verkuil 
806dacca5f0SHans Verkuil 	.vidioc_log_status		= vidioc_log_status,
807dacca5f0SHans Verkuil 	.vidioc_subscribe_event		= vidioc_subscribe_event,
808dacca5f0SHans Verkuil 	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
809dacca5f0SHans Verkuil 
810dacca5f0SHans Verkuil 	.vidioc_enum_fmt_meta_cap	= vidioc_enum_fmt_meta_cap,
811dacca5f0SHans Verkuil 	.vidioc_g_fmt_meta_cap		= vidioc_g_fmt_meta_cap,
812dacca5f0SHans Verkuil 	.vidioc_s_fmt_meta_cap		= vidioc_g_fmt_meta_cap,
813dacca5f0SHans Verkuil 	.vidioc_try_fmt_meta_cap	= vidioc_g_fmt_meta_cap,
814dacca5f0SHans Verkuil 
815dacca5f0SHans Verkuil 	.vidioc_enum_fmt_meta_out       = vidioc_enum_fmt_meta_out,
816dacca5f0SHans Verkuil 	.vidioc_g_fmt_meta_out          = vidioc_g_fmt_meta_out,
817dacca5f0SHans Verkuil 	.vidioc_s_fmt_meta_out          = vidioc_g_fmt_meta_out,
818dacca5f0SHans Verkuil 	.vidioc_try_fmt_meta_out        = vidioc_g_fmt_meta_out,
819dacca5f0SHans Verkuil };
820dacca5f0SHans Verkuil 
821dacca5f0SHans Verkuil /* -----------------------------------------------------------------
822dacca5f0SHans Verkuil 	Initialization and module stuff
823dacca5f0SHans Verkuil    ------------------------------------------------------------------*/
824dacca5f0SHans Verkuil 
vivid_dev_release(struct v4l2_device * v4l2_dev)825dacca5f0SHans Verkuil static void vivid_dev_release(struct v4l2_device *v4l2_dev)
826dacca5f0SHans Verkuil {
827dacca5f0SHans Verkuil 	struct vivid_dev *dev = container_of(v4l2_dev, struct vivid_dev, v4l2_dev);
828dacca5f0SHans Verkuil 
829dacca5f0SHans Verkuil 	vivid_free_controls(dev);
830dacca5f0SHans Verkuil 	v4l2_device_unregister(&dev->v4l2_dev);
831dacca5f0SHans Verkuil #ifdef CONFIG_MEDIA_CONTROLLER
832dacca5f0SHans Verkuil 	media_device_cleanup(&dev->mdev);
833dacca5f0SHans Verkuil #endif
834dacca5f0SHans Verkuil 	vfree(dev->scaled_line);
835dacca5f0SHans Verkuil 	vfree(dev->blended_line);
836dacca5f0SHans Verkuil 	vfree(dev->edid);
837dacca5f0SHans Verkuil 	tpg_free(&dev->tpg);
838dacca5f0SHans Verkuil 	kfree(dev->query_dv_timings_qmenu);
839dacca5f0SHans Verkuil 	kfree(dev->query_dv_timings_qmenu_strings);
840dacca5f0SHans Verkuil 	kfree(dev);
841dacca5f0SHans Verkuil }
842dacca5f0SHans Verkuil 
843dacca5f0SHans Verkuil #ifdef CONFIG_MEDIA_CONTROLLER
vivid_req_validate(struct media_request * req)844dacca5f0SHans Verkuil static int vivid_req_validate(struct media_request *req)
845dacca5f0SHans Verkuil {
846dacca5f0SHans Verkuil 	struct vivid_dev *dev = container_of(req->mdev, struct vivid_dev, mdev);
847dacca5f0SHans Verkuil 
848dacca5f0SHans Verkuil 	if (dev->req_validate_error) {
849dacca5f0SHans Verkuil 		dev->req_validate_error = false;
850dacca5f0SHans Verkuil 		return -EINVAL;
851dacca5f0SHans Verkuil 	}
852dacca5f0SHans Verkuil 	return vb2_request_validate(req);
853dacca5f0SHans Verkuil }
854dacca5f0SHans Verkuil 
855dacca5f0SHans Verkuil static const struct media_device_ops vivid_media_ops = {
856dacca5f0SHans Verkuil 	.req_validate = vivid_req_validate,
857dacca5f0SHans Verkuil 	.req_queue = vb2_request_queue,
858dacca5f0SHans Verkuil };
859dacca5f0SHans Verkuil #endif
860dacca5f0SHans Verkuil 
vivid_create_queue(struct vivid_dev * dev,struct vb2_queue * q,u32 buf_type,unsigned int min_buffers_needed,const struct vb2_ops * ops)861dacca5f0SHans Verkuil static int vivid_create_queue(struct vivid_dev *dev,
862dacca5f0SHans Verkuil 			      struct vb2_queue *q,
863dacca5f0SHans Verkuil 			      u32 buf_type,
864dacca5f0SHans Verkuil 			      unsigned int min_buffers_needed,
865dacca5f0SHans Verkuil 			      const struct vb2_ops *ops)
866dacca5f0SHans Verkuil {
867dacca5f0SHans Verkuil 	if (buf_type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->multiplanar)
868dacca5f0SHans Verkuil 		buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
869dacca5f0SHans Verkuil 	else if (buf_type == V4L2_BUF_TYPE_VIDEO_OUTPUT && dev->multiplanar)
870dacca5f0SHans Verkuil 		buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
871dacca5f0SHans Verkuil 	else if (buf_type == V4L2_BUF_TYPE_VBI_CAPTURE && !dev->has_raw_vbi_cap)
872dacca5f0SHans Verkuil 		buf_type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
873dacca5f0SHans Verkuil 	else if (buf_type == V4L2_BUF_TYPE_VBI_OUTPUT && !dev->has_raw_vbi_out)
874dacca5f0SHans Verkuil 		buf_type = V4L2_BUF_TYPE_SLICED_VBI_OUTPUT;
875dacca5f0SHans Verkuil 
876dacca5f0SHans Verkuil 	q->type = buf_type;
877dacca5f0SHans Verkuil 	q->io_modes = VB2_MMAP | VB2_DMABUF;
878dacca5f0SHans Verkuil 	q->io_modes |= V4L2_TYPE_IS_OUTPUT(buf_type) ?  VB2_WRITE : VB2_READ;
879dacca5f0SHans Verkuil 	if (allocators[dev->inst] != 1)
880dacca5f0SHans Verkuil 		q->io_modes |= VB2_USERPTR;
881dacca5f0SHans Verkuil 	q->drv_priv = dev;
882dacca5f0SHans Verkuil 	q->buf_struct_size = sizeof(struct vivid_buffer);
883dacca5f0SHans Verkuil 	q->ops = ops;
884dacca5f0SHans Verkuil 	q->mem_ops = allocators[dev->inst] == 1 ? &vb2_dma_contig_memops :
885dacca5f0SHans Verkuil 						  &vb2_vmalloc_memops;
886dacca5f0SHans Verkuil 	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
887b72dd0f3SHans Verkuil 	q->min_buffers_needed = supports_requests[dev->inst] ? 0 : min_buffers_needed;
888dacca5f0SHans Verkuil 	q->lock = &dev->mutex;
889dacca5f0SHans Verkuil 	q->dev = dev->v4l2_dev.dev;
890b72dd0f3SHans Verkuil 	q->supports_requests = supports_requests[dev->inst];
891b72dd0f3SHans Verkuil 	q->requires_requests = supports_requests[dev->inst] >= 2;
89262a4cd01SSergey Senozhatsky 	q->allow_cache_hints = (cache_hints[dev->inst] == 1);
893dacca5f0SHans Verkuil 
894dacca5f0SHans Verkuil 	return vb2_queue_init(q);
895dacca5f0SHans Verkuil }
896dacca5f0SHans Verkuil 
vivid_detect_feature_set(struct vivid_dev * dev,int inst,unsigned node_type,bool * has_tuner,bool * has_modulator,int * ccs_cap,int * ccs_out,unsigned in_type_counter[4],unsigned out_type_counter[4])89731b97d35SMauro Carvalho Chehab static int vivid_detect_feature_set(struct vivid_dev *dev, int inst,
89831b97d35SMauro Carvalho Chehab 				    unsigned node_type,
89931b97d35SMauro Carvalho Chehab 				    bool *has_tuner,
90031b97d35SMauro Carvalho Chehab 				    bool *has_modulator,
90131b97d35SMauro Carvalho Chehab 				    int *ccs_cap,
90231b97d35SMauro Carvalho Chehab 				    int *ccs_out,
90331b97d35SMauro Carvalho Chehab 				    unsigned in_type_counter[4],
90431b97d35SMauro Carvalho Chehab 				    unsigned out_type_counter[4])
905dacca5f0SHans Verkuil {
906dacca5f0SHans Verkuil 	int i;
907dacca5f0SHans Verkuil 
908dacca5f0SHans Verkuil 	/* do we use single- or multi-planar? */
909dacca5f0SHans Verkuil 	dev->multiplanar = multiplanar[inst] > 1;
910dacca5f0SHans Verkuil 	v4l2_info(&dev->v4l2_dev, "using %splanar format API\n",
911dacca5f0SHans Verkuil 			dev->multiplanar ? "multi" : "single ");
912dacca5f0SHans Verkuil 
913dacca5f0SHans Verkuil 	/* how many inputs do we have and of what type? */
914dacca5f0SHans Verkuil 	dev->num_inputs = num_inputs[inst];
91569d78a80SHans Verkuil 	if (node_type & 0x20007) {
916dacca5f0SHans Verkuil 		if (dev->num_inputs < 1)
917dacca5f0SHans Verkuil 			dev->num_inputs = 1;
91869d78a80SHans Verkuil 	} else {
91969d78a80SHans Verkuil 		dev->num_inputs = 0;
92069d78a80SHans Verkuil 	}
921dacca5f0SHans Verkuil 	if (dev->num_inputs >= MAX_INPUTS)
922dacca5f0SHans Verkuil 		dev->num_inputs = MAX_INPUTS;
923dacca5f0SHans Verkuil 	for (i = 0; i < dev->num_inputs; i++) {
924dacca5f0SHans Verkuil 		dev->input_type[i] = (input_types[inst] >> (i * 2)) & 0x3;
925dacca5f0SHans Verkuil 		dev->input_name_counter[i] = in_type_counter[dev->input_type[i]]++;
926dacca5f0SHans Verkuil 	}
927dacca5f0SHans Verkuil 	dev->has_audio_inputs = in_type_counter[TV] && in_type_counter[SVID];
928dacca5f0SHans Verkuil 	if (in_type_counter[HDMI] == 16) {
929dacca5f0SHans Verkuil 		/* The CEC physical address only allows for max 15 inputs */
930dacca5f0SHans Verkuil 		in_type_counter[HDMI]--;
931dacca5f0SHans Verkuil 		dev->num_inputs--;
932dacca5f0SHans Verkuil 	}
933dacca5f0SHans Verkuil 	dev->num_hdmi_inputs = in_type_counter[HDMI];
934dacca5f0SHans Verkuil 
935dacca5f0SHans Verkuil 	/* how many outputs do we have and of what type? */
936dacca5f0SHans Verkuil 	dev->num_outputs = num_outputs[inst];
93769d78a80SHans Verkuil 	if (node_type & 0x40300) {
938dacca5f0SHans Verkuil 		if (dev->num_outputs < 1)
939dacca5f0SHans Verkuil 			dev->num_outputs = 1;
94069d78a80SHans Verkuil 	} else {
94169d78a80SHans Verkuil 		dev->num_outputs = 0;
94269d78a80SHans Verkuil 	}
943dacca5f0SHans Verkuil 	if (dev->num_outputs >= MAX_OUTPUTS)
944dacca5f0SHans Verkuil 		dev->num_outputs = MAX_OUTPUTS;
945dacca5f0SHans Verkuil 	for (i = 0; i < dev->num_outputs; i++) {
946dacca5f0SHans Verkuil 		dev->output_type[i] = ((output_types[inst] >> i) & 1) ? HDMI : SVID;
947dacca5f0SHans Verkuil 		dev->output_name_counter[i] = out_type_counter[dev->output_type[i]]++;
948dacca5f0SHans Verkuil 		dev->display_present[i] = true;
949dacca5f0SHans Verkuil 	}
950dacca5f0SHans Verkuil 	dev->has_audio_outputs = out_type_counter[SVID];
951dacca5f0SHans Verkuil 	if (out_type_counter[HDMI] == 16) {
952dacca5f0SHans Verkuil 		/*
953dacca5f0SHans Verkuil 		 * The CEC physical address only allows for max 15 inputs,
954dacca5f0SHans Verkuil 		 * so outputs are also limited to 15 to allow for easy
955dacca5f0SHans Verkuil 		 * CEC output to input mapping.
956dacca5f0SHans Verkuil 		 */
957dacca5f0SHans Verkuil 		out_type_counter[HDMI]--;
958dacca5f0SHans Verkuil 		dev->num_outputs--;
959dacca5f0SHans Verkuil 	}
960dacca5f0SHans Verkuil 	dev->num_hdmi_outputs = out_type_counter[HDMI];
961dacca5f0SHans Verkuil 
962dacca5f0SHans Verkuil 	/* do we create a video capture device? */
963dacca5f0SHans Verkuil 	dev->has_vid_cap = node_type & 0x0001;
964dacca5f0SHans Verkuil 
965dacca5f0SHans Verkuil 	/* do we create a vbi capture device? */
966dacca5f0SHans Verkuil 	if (in_type_counter[TV] || in_type_counter[SVID]) {
967dacca5f0SHans Verkuil 		dev->has_raw_vbi_cap = node_type & 0x0004;
968dacca5f0SHans Verkuil 		dev->has_sliced_vbi_cap = node_type & 0x0008;
969dacca5f0SHans Verkuil 		dev->has_vbi_cap = dev->has_raw_vbi_cap | dev->has_sliced_vbi_cap;
970dacca5f0SHans Verkuil 	}
971dacca5f0SHans Verkuil 
972dacca5f0SHans Verkuil 	/* do we create a meta capture device */
973dacca5f0SHans Verkuil 	dev->has_meta_cap = node_type & 0x20000;
974dacca5f0SHans Verkuil 
975dacca5f0SHans Verkuil 	/* sanity checks */
976dacca5f0SHans Verkuil 	if ((in_type_counter[WEBCAM] || in_type_counter[HDMI]) &&
977dacca5f0SHans Verkuil 	    !dev->has_vid_cap && !dev->has_meta_cap) {
978dacca5f0SHans Verkuil 		v4l2_warn(&dev->v4l2_dev,
979dacca5f0SHans Verkuil 			  "Webcam or HDMI input without video or metadata nodes\n");
980dacca5f0SHans Verkuil 		return -EINVAL;
981dacca5f0SHans Verkuil 	}
982dacca5f0SHans Verkuil 	if ((in_type_counter[TV] || in_type_counter[SVID]) &&
983dacca5f0SHans Verkuil 	    !dev->has_vid_cap && !dev->has_vbi_cap && !dev->has_meta_cap) {
984dacca5f0SHans Verkuil 		v4l2_warn(&dev->v4l2_dev,
985dacca5f0SHans Verkuil 			  "TV or S-Video input without video, VBI or metadata nodes\n");
986dacca5f0SHans Verkuil 		return -EINVAL;
987dacca5f0SHans Verkuil 	}
988dacca5f0SHans Verkuil 
989dacca5f0SHans Verkuil 	/* do we create a video output device? */
990dacca5f0SHans Verkuil 	dev->has_vid_out = node_type & 0x0100;
991dacca5f0SHans Verkuil 
992dacca5f0SHans Verkuil 	/* do we create a vbi output device? */
993dacca5f0SHans Verkuil 	if (out_type_counter[SVID]) {
994dacca5f0SHans Verkuil 		dev->has_raw_vbi_out = node_type & 0x0400;
995dacca5f0SHans Verkuil 		dev->has_sliced_vbi_out = node_type & 0x0800;
996dacca5f0SHans Verkuil 		dev->has_vbi_out = dev->has_raw_vbi_out | dev->has_sliced_vbi_out;
997dacca5f0SHans Verkuil 	}
998dacca5f0SHans Verkuil 
999dacca5f0SHans Verkuil 	/* do we create a metadata output device */
1000dacca5f0SHans Verkuil 	dev->has_meta_out = node_type & 0x40000;
1001dacca5f0SHans Verkuil 
1002dacca5f0SHans Verkuil 	/* sanity checks */
1003dacca5f0SHans Verkuil 	if (out_type_counter[SVID] &&
1004dacca5f0SHans Verkuil 	    !dev->has_vid_out && !dev->has_vbi_out && !dev->has_meta_out) {
1005dacca5f0SHans Verkuil 		v4l2_warn(&dev->v4l2_dev,
1006dacca5f0SHans Verkuil 			  "S-Video output without video, VBI or metadata nodes\n");
1007dacca5f0SHans Verkuil 		return -EINVAL;
1008dacca5f0SHans Verkuil 	}
1009dacca5f0SHans Verkuil 	if (out_type_counter[HDMI] && !dev->has_vid_out && !dev->has_meta_out) {
1010dacca5f0SHans Verkuil 		v4l2_warn(&dev->v4l2_dev,
1011dacca5f0SHans Verkuil 			  "HDMI output without video or metadata nodes\n");
1012dacca5f0SHans Verkuil 		return -EINVAL;
1013dacca5f0SHans Verkuil 	}
1014dacca5f0SHans Verkuil 
1015dacca5f0SHans Verkuil 	/* do we create a radio receiver device? */
1016dacca5f0SHans Verkuil 	dev->has_radio_rx = node_type & 0x0010;
1017dacca5f0SHans Verkuil 
1018dacca5f0SHans Verkuil 	/* do we create a radio transmitter device? */
1019dacca5f0SHans Verkuil 	dev->has_radio_tx = node_type & 0x1000;
1020dacca5f0SHans Verkuil 
1021dacca5f0SHans Verkuil 	/* do we create a software defined radio capture device? */
1022dacca5f0SHans Verkuil 	dev->has_sdr_cap = node_type & 0x0020;
1023dacca5f0SHans Verkuil 
1024dacca5f0SHans Verkuil 	/* do we have a TV tuner? */
1025dacca5f0SHans Verkuil 	dev->has_tv_tuner = in_type_counter[TV];
1026dacca5f0SHans Verkuil 
1027dacca5f0SHans Verkuil 	/* do we have a tuner? */
102831b97d35SMauro Carvalho Chehab 	*has_tuner = ((dev->has_vid_cap || dev->has_vbi_cap) && in_type_counter[TV]) ||
1029dacca5f0SHans Verkuil 		      dev->has_radio_rx || dev->has_sdr_cap;
1030dacca5f0SHans Verkuil 
1031dacca5f0SHans Verkuil 	/* do we have a modulator? */
103231b97d35SMauro Carvalho Chehab 	*has_modulator = dev->has_radio_tx;
1033dacca5f0SHans Verkuil 
1034dacca5f0SHans Verkuil 	if (dev->has_vid_cap)
1035dacca5f0SHans Verkuil 		/* do we have a framebuffer for overlay testing? */
1036dacca5f0SHans Verkuil 		dev->has_fb = node_type & 0x10000;
1037dacca5f0SHans Verkuil 
1038dacca5f0SHans Verkuil 	/* can we do crop/compose/scaling while capturing? */
103931b97d35SMauro Carvalho Chehab 	if (no_error_inj && *ccs_cap == -1)
104031b97d35SMauro Carvalho Chehab 		*ccs_cap = 7;
1041dacca5f0SHans Verkuil 
1042dacca5f0SHans Verkuil 	/* if ccs_cap == -1, then the user can select it using controls */
104331b97d35SMauro Carvalho Chehab 	if (*ccs_cap != -1) {
104431b97d35SMauro Carvalho Chehab 		dev->has_crop_cap = *ccs_cap & 1;
104531b97d35SMauro Carvalho Chehab 		dev->has_compose_cap = *ccs_cap & 2;
104631b97d35SMauro Carvalho Chehab 		dev->has_scaler_cap = *ccs_cap & 4;
1047dacca5f0SHans Verkuil 		v4l2_info(&dev->v4l2_dev, "Capture Crop: %c Compose: %c Scaler: %c\n",
1048dacca5f0SHans Verkuil 			dev->has_crop_cap ? 'Y' : 'N',
1049dacca5f0SHans Verkuil 			dev->has_compose_cap ? 'Y' : 'N',
1050dacca5f0SHans Verkuil 			dev->has_scaler_cap ? 'Y' : 'N');
1051dacca5f0SHans Verkuil 	}
1052dacca5f0SHans Verkuil 
1053dacca5f0SHans Verkuil 	/* can we do crop/compose/scaling with video output? */
105431b97d35SMauro Carvalho Chehab 	if (no_error_inj && *ccs_out == -1)
105531b97d35SMauro Carvalho Chehab 		*ccs_out = 7;
1056dacca5f0SHans Verkuil 
1057dacca5f0SHans Verkuil 	/* if ccs_out == -1, then the user can select it using controls */
105831b97d35SMauro Carvalho Chehab 	if (*ccs_out != -1) {
105931b97d35SMauro Carvalho Chehab 		dev->has_crop_out = *ccs_out & 1;
106031b97d35SMauro Carvalho Chehab 		dev->has_compose_out = *ccs_out & 2;
106131b97d35SMauro Carvalho Chehab 		dev->has_scaler_out = *ccs_out & 4;
1062dacca5f0SHans Verkuil 		v4l2_info(&dev->v4l2_dev, "Output Crop: %c Compose: %c Scaler: %c\n",
1063dacca5f0SHans Verkuil 			dev->has_crop_out ? 'Y' : 'N',
1064dacca5f0SHans Verkuil 			dev->has_compose_out ? 'Y' : 'N',
1065dacca5f0SHans Verkuil 			dev->has_scaler_out ? 'Y' : 'N');
1066dacca5f0SHans Verkuil 	}
1067dacca5f0SHans Verkuil 
1068dacca5f0SHans Verkuil 	/* do we create a touch capture device */
1069dacca5f0SHans Verkuil 	dev->has_touch_cap = node_type & 0x80000;
1070dacca5f0SHans Verkuil 
107131b97d35SMauro Carvalho Chehab 	return 0;
107231b97d35SMauro Carvalho Chehab }
107331b97d35SMauro Carvalho Chehab 
vivid_set_capabilities(struct vivid_dev * dev)10744306c537SMauro Carvalho Chehab static void vivid_set_capabilities(struct vivid_dev *dev)
10754306c537SMauro Carvalho Chehab {
10764306c537SMauro Carvalho Chehab 	if (dev->has_vid_cap) {
10774306c537SMauro Carvalho Chehab 		/* set up the capabilities of the video capture device */
10784306c537SMauro Carvalho Chehab 		dev->vid_cap_caps = dev->multiplanar ?
10794306c537SMauro Carvalho Chehab 			V4L2_CAP_VIDEO_CAPTURE_MPLANE :
1080ccaa9d50SHans Verkuil 			V4L2_CAP_VIDEO_CAPTURE;
10814306c537SMauro Carvalho Chehab 		dev->vid_cap_caps |= V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
10824306c537SMauro Carvalho Chehab 		if (dev->has_audio_inputs)
10834306c537SMauro Carvalho Chehab 			dev->vid_cap_caps |= V4L2_CAP_AUDIO;
10844306c537SMauro Carvalho Chehab 		if (dev->has_tv_tuner)
10854306c537SMauro Carvalho Chehab 			dev->vid_cap_caps |= V4L2_CAP_TUNER;
10864306c537SMauro Carvalho Chehab 	}
10874306c537SMauro Carvalho Chehab 	if (dev->has_vid_out) {
10884306c537SMauro Carvalho Chehab 		/* set up the capabilities of the video output device */
10894306c537SMauro Carvalho Chehab 		dev->vid_out_caps = dev->multiplanar ?
10904306c537SMauro Carvalho Chehab 			V4L2_CAP_VIDEO_OUTPUT_MPLANE :
10914306c537SMauro Carvalho Chehab 			V4L2_CAP_VIDEO_OUTPUT;
10924306c537SMauro Carvalho Chehab 		if (dev->has_fb)
10934306c537SMauro Carvalho Chehab 			dev->vid_out_caps |= V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
10944306c537SMauro Carvalho Chehab 		dev->vid_out_caps |= V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
10954306c537SMauro Carvalho Chehab 		if (dev->has_audio_outputs)
10964306c537SMauro Carvalho Chehab 			dev->vid_out_caps |= V4L2_CAP_AUDIO;
10974306c537SMauro Carvalho Chehab 	}
10984306c537SMauro Carvalho Chehab 	if (dev->has_vbi_cap) {
10994306c537SMauro Carvalho Chehab 		/* set up the capabilities of the vbi capture device */
11004306c537SMauro Carvalho Chehab 		dev->vbi_cap_caps = (dev->has_raw_vbi_cap ? V4L2_CAP_VBI_CAPTURE : 0) |
11014306c537SMauro Carvalho Chehab 				    (dev->has_sliced_vbi_cap ? V4L2_CAP_SLICED_VBI_CAPTURE : 0);
11024306c537SMauro Carvalho Chehab 		dev->vbi_cap_caps |= V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
11034306c537SMauro Carvalho Chehab 		if (dev->has_audio_inputs)
11044306c537SMauro Carvalho Chehab 			dev->vbi_cap_caps |= V4L2_CAP_AUDIO;
11054306c537SMauro Carvalho Chehab 		if (dev->has_tv_tuner)
11064306c537SMauro Carvalho Chehab 			dev->vbi_cap_caps |= V4L2_CAP_TUNER;
11074306c537SMauro Carvalho Chehab 	}
11084306c537SMauro Carvalho Chehab 	if (dev->has_vbi_out) {
11094306c537SMauro Carvalho Chehab 		/* set up the capabilities of the vbi output device */
11104306c537SMauro Carvalho Chehab 		dev->vbi_out_caps = (dev->has_raw_vbi_out ? V4L2_CAP_VBI_OUTPUT : 0) |
11114306c537SMauro Carvalho Chehab 				    (dev->has_sliced_vbi_out ? V4L2_CAP_SLICED_VBI_OUTPUT : 0);
11124306c537SMauro Carvalho Chehab 		dev->vbi_out_caps |= V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
11134306c537SMauro Carvalho Chehab 		if (dev->has_audio_outputs)
11144306c537SMauro Carvalho Chehab 			dev->vbi_out_caps |= V4L2_CAP_AUDIO;
11154306c537SMauro Carvalho Chehab 	}
11164306c537SMauro Carvalho Chehab 	if (dev->has_sdr_cap) {
11174306c537SMauro Carvalho Chehab 		/* set up the capabilities of the sdr capture device */
11184306c537SMauro Carvalho Chehab 		dev->sdr_cap_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_TUNER;
11194306c537SMauro Carvalho Chehab 		dev->sdr_cap_caps |= V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
11204306c537SMauro Carvalho Chehab 	}
11214306c537SMauro Carvalho Chehab 	/* set up the capabilities of the radio receiver device */
11224306c537SMauro Carvalho Chehab 	if (dev->has_radio_rx)
11234306c537SMauro Carvalho Chehab 		dev->radio_rx_caps = V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE |
11244306c537SMauro Carvalho Chehab 				     V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_TUNER |
11254306c537SMauro Carvalho Chehab 				     V4L2_CAP_READWRITE;
11264306c537SMauro Carvalho Chehab 	/* set up the capabilities of the radio transmitter device */
11274306c537SMauro Carvalho Chehab 	if (dev->has_radio_tx)
11284306c537SMauro Carvalho Chehab 		dev->radio_tx_caps = V4L2_CAP_RDS_OUTPUT | V4L2_CAP_MODULATOR |
11294306c537SMauro Carvalho Chehab 				     V4L2_CAP_READWRITE;
11304306c537SMauro Carvalho Chehab 
11314306c537SMauro Carvalho Chehab 	/* set up the capabilities of meta capture device */
11324306c537SMauro Carvalho Chehab 	if (dev->has_meta_cap) {
11334306c537SMauro Carvalho Chehab 		dev->meta_cap_caps = V4L2_CAP_META_CAPTURE |
11344306c537SMauro Carvalho Chehab 				     V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
11354306c537SMauro Carvalho Chehab 		if (dev->has_audio_inputs)
11364306c537SMauro Carvalho Chehab 			dev->meta_cap_caps |= V4L2_CAP_AUDIO;
11374306c537SMauro Carvalho Chehab 		if (dev->has_tv_tuner)
11384306c537SMauro Carvalho Chehab 			dev->meta_cap_caps |= V4L2_CAP_TUNER;
11394306c537SMauro Carvalho Chehab 	}
11404306c537SMauro Carvalho Chehab 	/* set up the capabilities of meta output device */
11414306c537SMauro Carvalho Chehab 	if (dev->has_meta_out) {
11424306c537SMauro Carvalho Chehab 		dev->meta_out_caps = V4L2_CAP_META_OUTPUT |
11434306c537SMauro Carvalho Chehab 				     V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
11444306c537SMauro Carvalho Chehab 		if (dev->has_audio_outputs)
11454306c537SMauro Carvalho Chehab 			dev->meta_out_caps |= V4L2_CAP_AUDIO;
11464306c537SMauro Carvalho Chehab 	}
11474306c537SMauro Carvalho Chehab 	/* set up the capabilities of the touch capture device */
11484306c537SMauro Carvalho Chehab 	if (dev->has_touch_cap) {
11494306c537SMauro Carvalho Chehab 		dev->touch_cap_caps = V4L2_CAP_TOUCH | V4L2_CAP_STREAMING |
11504306c537SMauro Carvalho Chehab 				      V4L2_CAP_READWRITE;
11514306c537SMauro Carvalho Chehab 		dev->touch_cap_caps |= dev->multiplanar ?
11524306c537SMauro Carvalho Chehab 			V4L2_CAP_VIDEO_CAPTURE_MPLANE : V4L2_CAP_VIDEO_CAPTURE;
11534306c537SMauro Carvalho Chehab 	}
11544306c537SMauro Carvalho Chehab }
11554306c537SMauro Carvalho Chehab 
vivid_disable_unused_ioctls(struct vivid_dev * dev,bool has_tuner,bool has_modulator,unsigned in_type_counter[4],unsigned out_type_counter[4])1156fcaeb019SMauro Carvalho Chehab static void vivid_disable_unused_ioctls(struct vivid_dev *dev,
1157fcaeb019SMauro Carvalho Chehab 					bool has_tuner,
1158fcaeb019SMauro Carvalho Chehab 					bool has_modulator,
1159fcaeb019SMauro Carvalho Chehab 					unsigned in_type_counter[4],
1160fcaeb019SMauro Carvalho Chehab 					unsigned out_type_counter[4])
1161fcaeb019SMauro Carvalho Chehab {
1162fcaeb019SMauro Carvalho Chehab 	/* disable invalid ioctls based on the feature set */
1163fcaeb019SMauro Carvalho Chehab 	if (!dev->has_audio_inputs) {
1164fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_S_AUDIO);
1165fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_G_AUDIO);
1166fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_ENUMAUDIO);
1167fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vbi_cap_dev, VIDIOC_S_AUDIO);
1168fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vbi_cap_dev, VIDIOC_G_AUDIO);
1169fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vbi_cap_dev, VIDIOC_ENUMAUDIO);
1170fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->meta_cap_dev, VIDIOC_S_AUDIO);
1171fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->meta_cap_dev, VIDIOC_G_AUDIO);
1172fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->meta_cap_dev, VIDIOC_ENUMAUDIO);
1173fcaeb019SMauro Carvalho Chehab 	}
1174fcaeb019SMauro Carvalho Chehab 	if (!dev->has_audio_outputs) {
1175fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_S_AUDOUT);
1176fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_G_AUDOUT);
1177fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_ENUMAUDOUT);
1178fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vbi_out_dev, VIDIOC_S_AUDOUT);
1179fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vbi_out_dev, VIDIOC_G_AUDOUT);
1180fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vbi_out_dev, VIDIOC_ENUMAUDOUT);
1181fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->meta_out_dev, VIDIOC_S_AUDOUT);
1182fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->meta_out_dev, VIDIOC_G_AUDOUT);
1183fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->meta_out_dev, VIDIOC_ENUMAUDOUT);
1184fcaeb019SMauro Carvalho Chehab 	}
1185fcaeb019SMauro Carvalho Chehab 	if (!in_type_counter[TV] && !in_type_counter[SVID]) {
1186fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_S_STD);
1187fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_G_STD);
1188fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_ENUMSTD);
1189fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_QUERYSTD);
1190fcaeb019SMauro Carvalho Chehab 	}
1191fcaeb019SMauro Carvalho Chehab 	if (!out_type_counter[SVID]) {
1192fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_S_STD);
1193fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_G_STD);
1194fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_ENUMSTD);
1195fcaeb019SMauro Carvalho Chehab 	}
1196fcaeb019SMauro Carvalho Chehab 	if (!has_tuner && !has_modulator) {
1197fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_S_FREQUENCY);
1198fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_G_FREQUENCY);
1199fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vbi_cap_dev, VIDIOC_S_FREQUENCY);
1200fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vbi_cap_dev, VIDIOC_G_FREQUENCY);
1201fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->meta_cap_dev, VIDIOC_S_FREQUENCY);
1202fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->meta_cap_dev, VIDIOC_G_FREQUENCY);
1203fcaeb019SMauro Carvalho Chehab 	}
1204fcaeb019SMauro Carvalho Chehab 	if (!has_tuner) {
1205fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_S_TUNER);
1206fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_G_TUNER);
1207fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vbi_cap_dev, VIDIOC_S_TUNER);
1208fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vbi_cap_dev, VIDIOC_G_TUNER);
1209fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->meta_cap_dev, VIDIOC_S_TUNER);
1210fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->meta_cap_dev, VIDIOC_G_TUNER);
1211fcaeb019SMauro Carvalho Chehab 	}
1212fcaeb019SMauro Carvalho Chehab 	if (in_type_counter[HDMI] == 0) {
1213fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_S_EDID);
1214fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_G_EDID);
1215fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_DV_TIMINGS_CAP);
1216fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_G_DV_TIMINGS);
1217fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_S_DV_TIMINGS);
1218fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_ENUM_DV_TIMINGS);
1219fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_QUERY_DV_TIMINGS);
1220fcaeb019SMauro Carvalho Chehab 	}
1221fcaeb019SMauro Carvalho Chehab 	if (out_type_counter[HDMI] == 0) {
1222fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_G_EDID);
1223fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_DV_TIMINGS_CAP);
1224fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_G_DV_TIMINGS);
1225fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_S_DV_TIMINGS);
1226fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_ENUM_DV_TIMINGS);
1227fcaeb019SMauro Carvalho Chehab 	}
1228fcaeb019SMauro Carvalho Chehab 	if (!dev->has_fb) {
1229fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_G_FBUF);
1230fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_S_FBUF);
1231fcaeb019SMauro Carvalho Chehab 		v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_OVERLAY);
1232fcaeb019SMauro Carvalho Chehab 	}
1233fcaeb019SMauro Carvalho Chehab 	v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_S_HW_FREQ_SEEK);
1234fcaeb019SMauro Carvalho Chehab 	v4l2_disable_ioctl(&dev->vbi_cap_dev, VIDIOC_S_HW_FREQ_SEEK);
1235fcaeb019SMauro Carvalho Chehab 	v4l2_disable_ioctl(&dev->sdr_cap_dev, VIDIOC_S_HW_FREQ_SEEK);
1236fcaeb019SMauro Carvalho Chehab 	v4l2_disable_ioctl(&dev->meta_cap_dev, VIDIOC_S_HW_FREQ_SEEK);
1237fcaeb019SMauro Carvalho Chehab 	v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_S_FREQUENCY);
1238fcaeb019SMauro Carvalho Chehab 	v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_G_FREQUENCY);
1239fcaeb019SMauro Carvalho Chehab 	v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_ENUM_FRAMESIZES);
1240fcaeb019SMauro Carvalho Chehab 	v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_ENUM_FRAMEINTERVALS);
1241fcaeb019SMauro Carvalho Chehab 	v4l2_disable_ioctl(&dev->vbi_out_dev, VIDIOC_S_FREQUENCY);
1242fcaeb019SMauro Carvalho Chehab 	v4l2_disable_ioctl(&dev->vbi_out_dev, VIDIOC_G_FREQUENCY);
1243fcaeb019SMauro Carvalho Chehab 	v4l2_disable_ioctl(&dev->meta_out_dev, VIDIOC_S_FREQUENCY);
1244fcaeb019SMauro Carvalho Chehab 	v4l2_disable_ioctl(&dev->meta_out_dev, VIDIOC_G_FREQUENCY);
1245fcaeb019SMauro Carvalho Chehab 	v4l2_disable_ioctl(&dev->touch_cap_dev, VIDIOC_S_PARM);
1246fcaeb019SMauro Carvalho Chehab 	v4l2_disable_ioctl(&dev->touch_cap_dev, VIDIOC_ENUM_FRAMESIZES);
1247fcaeb019SMauro Carvalho Chehab 	v4l2_disable_ioctl(&dev->touch_cap_dev, VIDIOC_ENUM_FRAMEINTERVALS);
1248fcaeb019SMauro Carvalho Chehab }
1249fcaeb019SMauro Carvalho Chehab 
vivid_init_dv_timings(struct vivid_dev * dev)1250d92c8e31SMauro Carvalho Chehab static int vivid_init_dv_timings(struct vivid_dev *dev)
1251d92c8e31SMauro Carvalho Chehab {
1252d92c8e31SMauro Carvalho Chehab 	int i;
1253d92c8e31SMauro Carvalho Chehab 
1254d92c8e31SMauro Carvalho Chehab 	while (v4l2_dv_timings_presets[dev->query_dv_timings_size].bt.width)
1255d92c8e31SMauro Carvalho Chehab 		dev->query_dv_timings_size++;
1256d92c8e31SMauro Carvalho Chehab 
1257d92c8e31SMauro Carvalho Chehab 	/*
1258d92c8e31SMauro Carvalho Chehab 	 * Create a char pointer array that points to the names of all the
1259d92c8e31SMauro Carvalho Chehab 	 * preset timings
1260d92c8e31SMauro Carvalho Chehab 	 */
1261d92c8e31SMauro Carvalho Chehab 	dev->query_dv_timings_qmenu = kmalloc_array(dev->query_dv_timings_size,
1262d92c8e31SMauro Carvalho Chehab 						    sizeof(char *), GFP_KERNEL);
1263d92c8e31SMauro Carvalho Chehab 	/*
1264d92c8e31SMauro Carvalho Chehab 	 * Create a string array containing the names of all the preset
1265d92c8e31SMauro Carvalho Chehab 	 * timings. Each name is max 31 chars long (+ terminating 0).
1266d92c8e31SMauro Carvalho Chehab 	 */
1267d92c8e31SMauro Carvalho Chehab 	dev->query_dv_timings_qmenu_strings =
1268d92c8e31SMauro Carvalho Chehab 		kmalloc_array(dev->query_dv_timings_size, 32, GFP_KERNEL);
1269d92c8e31SMauro Carvalho Chehab 
1270d92c8e31SMauro Carvalho Chehab 	if (!dev->query_dv_timings_qmenu ||
1271d92c8e31SMauro Carvalho Chehab 	    !dev->query_dv_timings_qmenu_strings)
1272d92c8e31SMauro Carvalho Chehab 		return -ENOMEM;
1273d92c8e31SMauro Carvalho Chehab 
1274d92c8e31SMauro Carvalho Chehab 	for (i = 0; i < dev->query_dv_timings_size; i++) {
1275d92c8e31SMauro Carvalho Chehab 		const struct v4l2_bt_timings *bt = &v4l2_dv_timings_presets[i].bt;
1276d92c8e31SMauro Carvalho Chehab 		char *p = dev->query_dv_timings_qmenu_strings + i * 32;
1277d92c8e31SMauro Carvalho Chehab 		u32 htot, vtot;
1278d92c8e31SMauro Carvalho Chehab 
1279d92c8e31SMauro Carvalho Chehab 		dev->query_dv_timings_qmenu[i] = p;
1280d92c8e31SMauro Carvalho Chehab 
1281d92c8e31SMauro Carvalho Chehab 		htot = V4L2_DV_BT_FRAME_WIDTH(bt);
1282d92c8e31SMauro Carvalho Chehab 		vtot = V4L2_DV_BT_FRAME_HEIGHT(bt);
1283d92c8e31SMauro Carvalho Chehab 		snprintf(p, 32, "%ux%u%s%u",
1284d92c8e31SMauro Carvalho Chehab 			bt->width, bt->height, bt->interlaced ? "i" : "p",
1285d92c8e31SMauro Carvalho Chehab 			(u32)bt->pixelclock / (htot * vtot));
1286d92c8e31SMauro Carvalho Chehab 	}
1287d92c8e31SMauro Carvalho Chehab 
1288d92c8e31SMauro Carvalho Chehab 	return 0;
1289d92c8e31SMauro Carvalho Chehab }
1290d92c8e31SMauro Carvalho Chehab 
vivid_create_queues(struct vivid_dev * dev)1291faf21f28SMauro Carvalho Chehab static int vivid_create_queues(struct vivid_dev *dev)
1292faf21f28SMauro Carvalho Chehab {
1293faf21f28SMauro Carvalho Chehab 	int ret;
1294faf21f28SMauro Carvalho Chehab 
1295faf21f28SMauro Carvalho Chehab 	/* start creating the vb2 queues */
1296faf21f28SMauro Carvalho Chehab 	if (dev->has_vid_cap) {
1297faf21f28SMauro Carvalho Chehab 		/* initialize vid_cap queue */
1298faf21f28SMauro Carvalho Chehab 		ret = vivid_create_queue(dev, &dev->vb_vid_cap_q,
1299faf21f28SMauro Carvalho Chehab 					 V4L2_BUF_TYPE_VIDEO_CAPTURE, 2,
1300faf21f28SMauro Carvalho Chehab 					 &vivid_vid_cap_qops);
1301faf21f28SMauro Carvalho Chehab 		if (ret)
1302faf21f28SMauro Carvalho Chehab 			return ret;
1303faf21f28SMauro Carvalho Chehab 	}
1304faf21f28SMauro Carvalho Chehab 
1305faf21f28SMauro Carvalho Chehab 	if (dev->has_vid_out) {
1306faf21f28SMauro Carvalho Chehab 		/* initialize vid_out queue */
1307faf21f28SMauro Carvalho Chehab 		ret = vivid_create_queue(dev, &dev->vb_vid_out_q,
1308faf21f28SMauro Carvalho Chehab 					 V4L2_BUF_TYPE_VIDEO_OUTPUT, 2,
1309faf21f28SMauro Carvalho Chehab 					 &vivid_vid_out_qops);
1310faf21f28SMauro Carvalho Chehab 		if (ret)
1311faf21f28SMauro Carvalho Chehab 			return ret;
1312faf21f28SMauro Carvalho Chehab 	}
1313faf21f28SMauro Carvalho Chehab 
1314faf21f28SMauro Carvalho Chehab 	if (dev->has_vbi_cap) {
1315faf21f28SMauro Carvalho Chehab 		/* initialize vbi_cap queue */
1316faf21f28SMauro Carvalho Chehab 		ret = vivid_create_queue(dev, &dev->vb_vbi_cap_q,
1317faf21f28SMauro Carvalho Chehab 					 V4L2_BUF_TYPE_VBI_CAPTURE, 2,
1318faf21f28SMauro Carvalho Chehab 					 &vivid_vbi_cap_qops);
1319faf21f28SMauro Carvalho Chehab 		if (ret)
1320faf21f28SMauro Carvalho Chehab 			return ret;
1321faf21f28SMauro Carvalho Chehab 	}
1322faf21f28SMauro Carvalho Chehab 
1323faf21f28SMauro Carvalho Chehab 	if (dev->has_vbi_out) {
1324faf21f28SMauro Carvalho Chehab 		/* initialize vbi_out queue */
1325faf21f28SMauro Carvalho Chehab 		ret = vivid_create_queue(dev, &dev->vb_vbi_out_q,
1326faf21f28SMauro Carvalho Chehab 					 V4L2_BUF_TYPE_VBI_OUTPUT, 2,
1327faf21f28SMauro Carvalho Chehab 					 &vivid_vbi_out_qops);
1328faf21f28SMauro Carvalho Chehab 		if (ret)
1329faf21f28SMauro Carvalho Chehab 			return ret;
1330faf21f28SMauro Carvalho Chehab 	}
1331faf21f28SMauro Carvalho Chehab 
1332faf21f28SMauro Carvalho Chehab 	if (dev->has_sdr_cap) {
1333faf21f28SMauro Carvalho Chehab 		/* initialize sdr_cap queue */
1334faf21f28SMauro Carvalho Chehab 		ret = vivid_create_queue(dev, &dev->vb_sdr_cap_q,
1335faf21f28SMauro Carvalho Chehab 					 V4L2_BUF_TYPE_SDR_CAPTURE, 8,
1336faf21f28SMauro Carvalho Chehab 					 &vivid_sdr_cap_qops);
1337faf21f28SMauro Carvalho Chehab 		if (ret)
1338faf21f28SMauro Carvalho Chehab 			return ret;
1339faf21f28SMauro Carvalho Chehab 	}
1340faf21f28SMauro Carvalho Chehab 
1341faf21f28SMauro Carvalho Chehab 	if (dev->has_meta_cap) {
1342faf21f28SMauro Carvalho Chehab 		/* initialize meta_cap queue */
1343faf21f28SMauro Carvalho Chehab 		ret = vivid_create_queue(dev, &dev->vb_meta_cap_q,
1344faf21f28SMauro Carvalho Chehab 					 V4L2_BUF_TYPE_META_CAPTURE, 2,
1345faf21f28SMauro Carvalho Chehab 					 &vivid_meta_cap_qops);
1346faf21f28SMauro Carvalho Chehab 		if (ret)
1347faf21f28SMauro Carvalho Chehab 			return ret;
1348faf21f28SMauro Carvalho Chehab 	}
1349faf21f28SMauro Carvalho Chehab 
1350faf21f28SMauro Carvalho Chehab 	if (dev->has_meta_out) {
1351faf21f28SMauro Carvalho Chehab 		/* initialize meta_out queue */
1352faf21f28SMauro Carvalho Chehab 		ret = vivid_create_queue(dev, &dev->vb_meta_out_q,
1353faf21f28SMauro Carvalho Chehab 					 V4L2_BUF_TYPE_META_OUTPUT, 1,
1354faf21f28SMauro Carvalho Chehab 					 &vivid_meta_out_qops);
1355faf21f28SMauro Carvalho Chehab 		if (ret)
1356faf21f28SMauro Carvalho Chehab 			return ret;
1357faf21f28SMauro Carvalho Chehab 	}
1358faf21f28SMauro Carvalho Chehab 
1359faf21f28SMauro Carvalho Chehab 	if (dev->has_touch_cap) {
1360faf21f28SMauro Carvalho Chehab 		/* initialize touch_cap queue */
1361faf21f28SMauro Carvalho Chehab 		ret = vivid_create_queue(dev, &dev->vb_touch_cap_q,
1362faf21f28SMauro Carvalho Chehab 					 V4L2_BUF_TYPE_VIDEO_CAPTURE, 1,
1363faf21f28SMauro Carvalho Chehab 					 &vivid_touch_cap_qops);
1364faf21f28SMauro Carvalho Chehab 		if (ret)
1365faf21f28SMauro Carvalho Chehab 			return ret;
1366faf21f28SMauro Carvalho Chehab 	}
1367faf21f28SMauro Carvalho Chehab 
1368faf21f28SMauro Carvalho Chehab 	if (dev->has_fb) {
1369ccaa9d50SHans Verkuil 		/* Create framebuffer for testing output overlay */
1370faf21f28SMauro Carvalho Chehab 		ret = vivid_fb_init(dev);
1371faf21f28SMauro Carvalho Chehab 		if (ret)
1372faf21f28SMauro Carvalho Chehab 			return ret;
1373faf21f28SMauro Carvalho Chehab 		v4l2_info(&dev->v4l2_dev, "Framebuffer device registered as fb%d\n",
1374faf21f28SMauro Carvalho Chehab 			  dev->fb_info.node);
1375faf21f28SMauro Carvalho Chehab 	}
1376faf21f28SMauro Carvalho Chehab 	return 0;
1377faf21f28SMauro Carvalho Chehab }
1378d92c8e31SMauro Carvalho Chehab 
vivid_create_devnodes(struct platform_device * pdev,struct vivid_dev * dev,int inst,unsigned int cec_tx_bus_cnt,v4l2_std_id tvnorms_cap,v4l2_std_id tvnorms_out,unsigned in_type_counter[4],unsigned out_type_counter[4])137962c6b4c9SMauro Carvalho Chehab static int vivid_create_devnodes(struct platform_device *pdev,
138062c6b4c9SMauro Carvalho Chehab 				 struct vivid_dev *dev, int inst,
138162c6b4c9SMauro Carvalho Chehab 				 unsigned int cec_tx_bus_cnt,
138262c6b4c9SMauro Carvalho Chehab 				 v4l2_std_id tvnorms_cap,
138362c6b4c9SMauro Carvalho Chehab 				 v4l2_std_id tvnorms_out,
138462c6b4c9SMauro Carvalho Chehab 				 unsigned in_type_counter[4],
138562c6b4c9SMauro Carvalho Chehab 				 unsigned out_type_counter[4])
138662c6b4c9SMauro Carvalho Chehab {
138762c6b4c9SMauro Carvalho Chehab 	struct video_device *vfd;
1388d034731bSHans Verkuil 	int ret;
138962c6b4c9SMauro Carvalho Chehab 
139062c6b4c9SMauro Carvalho Chehab 	if (dev->has_vid_cap) {
139162c6b4c9SMauro Carvalho Chehab 		vfd = &dev->vid_cap_dev;
139262c6b4c9SMauro Carvalho Chehab 		snprintf(vfd->name, sizeof(vfd->name),
139362c6b4c9SMauro Carvalho Chehab 			 "vivid-%03d-vid-cap", inst);
139462c6b4c9SMauro Carvalho Chehab 		vfd->fops = &vivid_fops;
139562c6b4c9SMauro Carvalho Chehab 		vfd->ioctl_ops = &vivid_ioctl_ops;
139662c6b4c9SMauro Carvalho Chehab 		vfd->device_caps = dev->vid_cap_caps;
139762c6b4c9SMauro Carvalho Chehab 		vfd->release = video_device_release_empty;
139862c6b4c9SMauro Carvalho Chehab 		vfd->v4l2_dev = &dev->v4l2_dev;
139962c6b4c9SMauro Carvalho Chehab 		vfd->queue = &dev->vb_vid_cap_q;
140062c6b4c9SMauro Carvalho Chehab 		vfd->tvnorms = tvnorms_cap;
140162c6b4c9SMauro Carvalho Chehab 
140262c6b4c9SMauro Carvalho Chehab 		/*
140362c6b4c9SMauro Carvalho Chehab 		 * Provide a mutex to v4l2 core. It will be used to protect
140462c6b4c9SMauro Carvalho Chehab 		 * all fops and v4l2 ioctls.
140562c6b4c9SMauro Carvalho Chehab 		 */
140662c6b4c9SMauro Carvalho Chehab 		vfd->lock = &dev->mutex;
140762c6b4c9SMauro Carvalho Chehab 		video_set_drvdata(vfd, dev);
140862c6b4c9SMauro Carvalho Chehab 
140962c6b4c9SMauro Carvalho Chehab #ifdef CONFIG_MEDIA_CONTROLLER
141062c6b4c9SMauro Carvalho Chehab 		dev->vid_cap_pad.flags = MEDIA_PAD_FL_SINK;
141162c6b4c9SMauro Carvalho Chehab 		ret = media_entity_pads_init(&vfd->entity, 1, &dev->vid_cap_pad);
141262c6b4c9SMauro Carvalho Chehab 		if (ret)
141362c6b4c9SMauro Carvalho Chehab 			return ret;
141462c6b4c9SMauro Carvalho Chehab #endif
141562c6b4c9SMauro Carvalho Chehab 
141662c6b4c9SMauro Carvalho Chehab #ifdef CONFIG_VIDEO_VIVID_CEC
141762c6b4c9SMauro Carvalho Chehab 		if (in_type_counter[HDMI]) {
141862c6b4c9SMauro Carvalho Chehab 			ret = cec_register_adapter(dev->cec_rx_adap, &pdev->dev);
141962c6b4c9SMauro Carvalho Chehab 			if (ret < 0) {
142062c6b4c9SMauro Carvalho Chehab 				cec_delete_adapter(dev->cec_rx_adap);
142162c6b4c9SMauro Carvalho Chehab 				dev->cec_rx_adap = NULL;
142262c6b4c9SMauro Carvalho Chehab 				return ret;
142362c6b4c9SMauro Carvalho Chehab 			}
142462c6b4c9SMauro Carvalho Chehab 			cec_s_phys_addr(dev->cec_rx_adap, 0, false);
142562c6b4c9SMauro Carvalho Chehab 			v4l2_info(&dev->v4l2_dev, "CEC adapter %s registered for HDMI input 0\n",
142662c6b4c9SMauro Carvalho Chehab 				  dev_name(&dev->cec_rx_adap->devnode.dev));
142762c6b4c9SMauro Carvalho Chehab 		}
142862c6b4c9SMauro Carvalho Chehab #endif
142962c6b4c9SMauro Carvalho Chehab 
143062c6b4c9SMauro Carvalho Chehab 		ret = video_register_device(vfd, VFL_TYPE_VIDEO, vid_cap_nr[inst]);
143162c6b4c9SMauro Carvalho Chehab 		if (ret < 0)
143262c6b4c9SMauro Carvalho Chehab 			return ret;
143362c6b4c9SMauro Carvalho Chehab 		v4l2_info(&dev->v4l2_dev, "V4L2 capture device registered as %s\n",
143462c6b4c9SMauro Carvalho Chehab 					  video_device_node_name(vfd));
143562c6b4c9SMauro Carvalho Chehab 	}
143662c6b4c9SMauro Carvalho Chehab 
143762c6b4c9SMauro Carvalho Chehab 	if (dev->has_vid_out) {
1438d034731bSHans Verkuil #ifdef CONFIG_VIDEO_VIVID_CEC
1439d034731bSHans Verkuil 		int i;
1440d034731bSHans Verkuil #endif
144162c6b4c9SMauro Carvalho Chehab 		vfd = &dev->vid_out_dev;
144262c6b4c9SMauro Carvalho Chehab 		snprintf(vfd->name, sizeof(vfd->name),
144362c6b4c9SMauro Carvalho Chehab 			 "vivid-%03d-vid-out", inst);
144462c6b4c9SMauro Carvalho Chehab 		vfd->vfl_dir = VFL_DIR_TX;
144562c6b4c9SMauro Carvalho Chehab 		vfd->fops = &vivid_fops;
144662c6b4c9SMauro Carvalho Chehab 		vfd->ioctl_ops = &vivid_ioctl_ops;
144762c6b4c9SMauro Carvalho Chehab 		vfd->device_caps = dev->vid_out_caps;
144862c6b4c9SMauro Carvalho Chehab 		vfd->release = video_device_release_empty;
144962c6b4c9SMauro Carvalho Chehab 		vfd->v4l2_dev = &dev->v4l2_dev;
145062c6b4c9SMauro Carvalho Chehab 		vfd->queue = &dev->vb_vid_out_q;
145162c6b4c9SMauro Carvalho Chehab 		vfd->tvnorms = tvnorms_out;
145262c6b4c9SMauro Carvalho Chehab 
145362c6b4c9SMauro Carvalho Chehab 		/*
145462c6b4c9SMauro Carvalho Chehab 		 * Provide a mutex to v4l2 core. It will be used to protect
145562c6b4c9SMauro Carvalho Chehab 		 * all fops and v4l2 ioctls.
145662c6b4c9SMauro Carvalho Chehab 		 */
145762c6b4c9SMauro Carvalho Chehab 		vfd->lock = &dev->mutex;
145862c6b4c9SMauro Carvalho Chehab 		video_set_drvdata(vfd, dev);
145962c6b4c9SMauro Carvalho Chehab 
146062c6b4c9SMauro Carvalho Chehab #ifdef CONFIG_MEDIA_CONTROLLER
146162c6b4c9SMauro Carvalho Chehab 		dev->vid_out_pad.flags = MEDIA_PAD_FL_SOURCE;
146262c6b4c9SMauro Carvalho Chehab 		ret = media_entity_pads_init(&vfd->entity, 1, &dev->vid_out_pad);
146362c6b4c9SMauro Carvalho Chehab 		if (ret)
146462c6b4c9SMauro Carvalho Chehab 			return ret;
146562c6b4c9SMauro Carvalho Chehab #endif
146662c6b4c9SMauro Carvalho Chehab 
146762c6b4c9SMauro Carvalho Chehab #ifdef CONFIG_VIDEO_VIVID_CEC
146862c6b4c9SMauro Carvalho Chehab 		for (i = 0; i < cec_tx_bus_cnt; i++) {
146962c6b4c9SMauro Carvalho Chehab 			ret = cec_register_adapter(dev->cec_tx_adap[i], &pdev->dev);
147062c6b4c9SMauro Carvalho Chehab 			if (ret < 0) {
147162c6b4c9SMauro Carvalho Chehab 				for (; i < cec_tx_bus_cnt; i++) {
147262c6b4c9SMauro Carvalho Chehab 					cec_delete_adapter(dev->cec_tx_adap[i]);
147362c6b4c9SMauro Carvalho Chehab 					dev->cec_tx_adap[i] = NULL;
147462c6b4c9SMauro Carvalho Chehab 				}
147562c6b4c9SMauro Carvalho Chehab 				return ret;
147662c6b4c9SMauro Carvalho Chehab 			}
147762c6b4c9SMauro Carvalho Chehab 			v4l2_info(&dev->v4l2_dev, "CEC adapter %s registered for HDMI output %d\n",
147862c6b4c9SMauro Carvalho Chehab 				  dev_name(&dev->cec_tx_adap[i]->devnode.dev), i);
147962c6b4c9SMauro Carvalho Chehab 			if (i < out_type_counter[HDMI])
148062c6b4c9SMauro Carvalho Chehab 				cec_s_phys_addr(dev->cec_tx_adap[i], (i + 1) << 12, false);
148162c6b4c9SMauro Carvalho Chehab 			else
148262c6b4c9SMauro Carvalho Chehab 				cec_s_phys_addr(dev->cec_tx_adap[i], 0x1000, false);
148362c6b4c9SMauro Carvalho Chehab 		}
148462c6b4c9SMauro Carvalho Chehab #endif
148562c6b4c9SMauro Carvalho Chehab 
148662c6b4c9SMauro Carvalho Chehab 		ret = video_register_device(vfd, VFL_TYPE_VIDEO, vid_out_nr[inst]);
148762c6b4c9SMauro Carvalho Chehab 		if (ret < 0)
148862c6b4c9SMauro Carvalho Chehab 			return ret;
148962c6b4c9SMauro Carvalho Chehab 		v4l2_info(&dev->v4l2_dev, "V4L2 output device registered as %s\n",
149062c6b4c9SMauro Carvalho Chehab 					  video_device_node_name(vfd));
149162c6b4c9SMauro Carvalho Chehab 	}
149262c6b4c9SMauro Carvalho Chehab 
149362c6b4c9SMauro Carvalho Chehab 	if (dev->has_vbi_cap) {
149462c6b4c9SMauro Carvalho Chehab 		vfd = &dev->vbi_cap_dev;
149562c6b4c9SMauro Carvalho Chehab 		snprintf(vfd->name, sizeof(vfd->name),
149662c6b4c9SMauro Carvalho Chehab 			 "vivid-%03d-vbi-cap", inst);
149762c6b4c9SMauro Carvalho Chehab 		vfd->fops = &vivid_fops;
149862c6b4c9SMauro Carvalho Chehab 		vfd->ioctl_ops = &vivid_ioctl_ops;
149962c6b4c9SMauro Carvalho Chehab 		vfd->device_caps = dev->vbi_cap_caps;
150062c6b4c9SMauro Carvalho Chehab 		vfd->release = video_device_release_empty;
150162c6b4c9SMauro Carvalho Chehab 		vfd->v4l2_dev = &dev->v4l2_dev;
150262c6b4c9SMauro Carvalho Chehab 		vfd->queue = &dev->vb_vbi_cap_q;
150362c6b4c9SMauro Carvalho Chehab 		vfd->lock = &dev->mutex;
150462c6b4c9SMauro Carvalho Chehab 		vfd->tvnorms = tvnorms_cap;
150562c6b4c9SMauro Carvalho Chehab 		video_set_drvdata(vfd, dev);
150662c6b4c9SMauro Carvalho Chehab 
150762c6b4c9SMauro Carvalho Chehab #ifdef CONFIG_MEDIA_CONTROLLER
150862c6b4c9SMauro Carvalho Chehab 		dev->vbi_cap_pad.flags = MEDIA_PAD_FL_SINK;
150962c6b4c9SMauro Carvalho Chehab 		ret = media_entity_pads_init(&vfd->entity, 1, &dev->vbi_cap_pad);
151062c6b4c9SMauro Carvalho Chehab 		if (ret)
151162c6b4c9SMauro Carvalho Chehab 			return ret;
151262c6b4c9SMauro Carvalho Chehab #endif
151362c6b4c9SMauro Carvalho Chehab 
151462c6b4c9SMauro Carvalho Chehab 		ret = video_register_device(vfd, VFL_TYPE_VBI, vbi_cap_nr[inst]);
151562c6b4c9SMauro Carvalho Chehab 		if (ret < 0)
151662c6b4c9SMauro Carvalho Chehab 			return ret;
151762c6b4c9SMauro Carvalho Chehab 		v4l2_info(&dev->v4l2_dev, "V4L2 capture device registered as %s, supports %s VBI\n",
151862c6b4c9SMauro Carvalho Chehab 					  video_device_node_name(vfd),
151962c6b4c9SMauro Carvalho Chehab 					  (dev->has_raw_vbi_cap && dev->has_sliced_vbi_cap) ?
152062c6b4c9SMauro Carvalho Chehab 					  "raw and sliced" :
152162c6b4c9SMauro Carvalho Chehab 					  (dev->has_raw_vbi_cap ? "raw" : "sliced"));
152262c6b4c9SMauro Carvalho Chehab 	}
152362c6b4c9SMauro Carvalho Chehab 
152462c6b4c9SMauro Carvalho Chehab 	if (dev->has_vbi_out) {
152562c6b4c9SMauro Carvalho Chehab 		vfd = &dev->vbi_out_dev;
152662c6b4c9SMauro Carvalho Chehab 		snprintf(vfd->name, sizeof(vfd->name),
152762c6b4c9SMauro Carvalho Chehab 			 "vivid-%03d-vbi-out", inst);
152862c6b4c9SMauro Carvalho Chehab 		vfd->vfl_dir = VFL_DIR_TX;
152962c6b4c9SMauro Carvalho Chehab 		vfd->fops = &vivid_fops;
153062c6b4c9SMauro Carvalho Chehab 		vfd->ioctl_ops = &vivid_ioctl_ops;
153162c6b4c9SMauro Carvalho Chehab 		vfd->device_caps = dev->vbi_out_caps;
153262c6b4c9SMauro Carvalho Chehab 		vfd->release = video_device_release_empty;
153362c6b4c9SMauro Carvalho Chehab 		vfd->v4l2_dev = &dev->v4l2_dev;
153462c6b4c9SMauro Carvalho Chehab 		vfd->queue = &dev->vb_vbi_out_q;
153562c6b4c9SMauro Carvalho Chehab 		vfd->lock = &dev->mutex;
153662c6b4c9SMauro Carvalho Chehab 		vfd->tvnorms = tvnorms_out;
153762c6b4c9SMauro Carvalho Chehab 		video_set_drvdata(vfd, dev);
153862c6b4c9SMauro Carvalho Chehab 
153962c6b4c9SMauro Carvalho Chehab #ifdef CONFIG_MEDIA_CONTROLLER
154062c6b4c9SMauro Carvalho Chehab 		dev->vbi_out_pad.flags = MEDIA_PAD_FL_SOURCE;
154162c6b4c9SMauro Carvalho Chehab 		ret = media_entity_pads_init(&vfd->entity, 1, &dev->vbi_out_pad);
154262c6b4c9SMauro Carvalho Chehab 		if (ret)
154362c6b4c9SMauro Carvalho Chehab 			return ret;
154462c6b4c9SMauro Carvalho Chehab #endif
154562c6b4c9SMauro Carvalho Chehab 
154662c6b4c9SMauro Carvalho Chehab 		ret = video_register_device(vfd, VFL_TYPE_VBI, vbi_out_nr[inst]);
154762c6b4c9SMauro Carvalho Chehab 		if (ret < 0)
154862c6b4c9SMauro Carvalho Chehab 			return ret;
154962c6b4c9SMauro Carvalho Chehab 		v4l2_info(&dev->v4l2_dev, "V4L2 output device registered as %s, supports %s VBI\n",
155062c6b4c9SMauro Carvalho Chehab 					  video_device_node_name(vfd),
155162c6b4c9SMauro Carvalho Chehab 					  (dev->has_raw_vbi_out && dev->has_sliced_vbi_out) ?
155262c6b4c9SMauro Carvalho Chehab 					  "raw and sliced" :
155362c6b4c9SMauro Carvalho Chehab 					  (dev->has_raw_vbi_out ? "raw" : "sliced"));
155462c6b4c9SMauro Carvalho Chehab 	}
155562c6b4c9SMauro Carvalho Chehab 
155662c6b4c9SMauro Carvalho Chehab 	if (dev->has_sdr_cap) {
155762c6b4c9SMauro Carvalho Chehab 		vfd = &dev->sdr_cap_dev;
155862c6b4c9SMauro Carvalho Chehab 		snprintf(vfd->name, sizeof(vfd->name),
155962c6b4c9SMauro Carvalho Chehab 			 "vivid-%03d-sdr-cap", inst);
156062c6b4c9SMauro Carvalho Chehab 		vfd->fops = &vivid_fops;
156162c6b4c9SMauro Carvalho Chehab 		vfd->ioctl_ops = &vivid_ioctl_ops;
156262c6b4c9SMauro Carvalho Chehab 		vfd->device_caps = dev->sdr_cap_caps;
156362c6b4c9SMauro Carvalho Chehab 		vfd->release = video_device_release_empty;
156462c6b4c9SMauro Carvalho Chehab 		vfd->v4l2_dev = &dev->v4l2_dev;
156562c6b4c9SMauro Carvalho Chehab 		vfd->queue = &dev->vb_sdr_cap_q;
156662c6b4c9SMauro Carvalho Chehab 		vfd->lock = &dev->mutex;
156762c6b4c9SMauro Carvalho Chehab 		video_set_drvdata(vfd, dev);
156862c6b4c9SMauro Carvalho Chehab 
156962c6b4c9SMauro Carvalho Chehab #ifdef CONFIG_MEDIA_CONTROLLER
157062c6b4c9SMauro Carvalho Chehab 		dev->sdr_cap_pad.flags = MEDIA_PAD_FL_SINK;
157162c6b4c9SMauro Carvalho Chehab 		ret = media_entity_pads_init(&vfd->entity, 1, &dev->sdr_cap_pad);
157262c6b4c9SMauro Carvalho Chehab 		if (ret)
157362c6b4c9SMauro Carvalho Chehab 			return ret;
157462c6b4c9SMauro Carvalho Chehab #endif
157562c6b4c9SMauro Carvalho Chehab 
157662c6b4c9SMauro Carvalho Chehab 		ret = video_register_device(vfd, VFL_TYPE_SDR, sdr_cap_nr[inst]);
157762c6b4c9SMauro Carvalho Chehab 		if (ret < 0)
157862c6b4c9SMauro Carvalho Chehab 			return ret;
157962c6b4c9SMauro Carvalho Chehab 		v4l2_info(&dev->v4l2_dev, "V4L2 capture device registered as %s\n",
158062c6b4c9SMauro Carvalho Chehab 					  video_device_node_name(vfd));
158162c6b4c9SMauro Carvalho Chehab 	}
158262c6b4c9SMauro Carvalho Chehab 
158362c6b4c9SMauro Carvalho Chehab 	if (dev->has_radio_rx) {
158462c6b4c9SMauro Carvalho Chehab 		vfd = &dev->radio_rx_dev;
158562c6b4c9SMauro Carvalho Chehab 		snprintf(vfd->name, sizeof(vfd->name),
158662c6b4c9SMauro Carvalho Chehab 			 "vivid-%03d-rad-rx", inst);
158762c6b4c9SMauro Carvalho Chehab 		vfd->fops = &vivid_radio_fops;
158862c6b4c9SMauro Carvalho Chehab 		vfd->ioctl_ops = &vivid_ioctl_ops;
158962c6b4c9SMauro Carvalho Chehab 		vfd->device_caps = dev->radio_rx_caps;
159062c6b4c9SMauro Carvalho Chehab 		vfd->release = video_device_release_empty;
159162c6b4c9SMauro Carvalho Chehab 		vfd->v4l2_dev = &dev->v4l2_dev;
159262c6b4c9SMauro Carvalho Chehab 		vfd->lock = &dev->mutex;
159362c6b4c9SMauro Carvalho Chehab 		video_set_drvdata(vfd, dev);
159462c6b4c9SMauro Carvalho Chehab 
159562c6b4c9SMauro Carvalho Chehab 		ret = video_register_device(vfd, VFL_TYPE_RADIO, radio_rx_nr[inst]);
159662c6b4c9SMauro Carvalho Chehab 		if (ret < 0)
159762c6b4c9SMauro Carvalho Chehab 			return ret;
159862c6b4c9SMauro Carvalho Chehab 		v4l2_info(&dev->v4l2_dev, "V4L2 receiver device registered as %s\n",
159962c6b4c9SMauro Carvalho Chehab 					  video_device_node_name(vfd));
160062c6b4c9SMauro Carvalho Chehab 	}
160162c6b4c9SMauro Carvalho Chehab 
160262c6b4c9SMauro Carvalho Chehab 	if (dev->has_radio_tx) {
160362c6b4c9SMauro Carvalho Chehab 		vfd = &dev->radio_tx_dev;
160462c6b4c9SMauro Carvalho Chehab 		snprintf(vfd->name, sizeof(vfd->name),
160562c6b4c9SMauro Carvalho Chehab 			 "vivid-%03d-rad-tx", inst);
160662c6b4c9SMauro Carvalho Chehab 		vfd->vfl_dir = VFL_DIR_TX;
160762c6b4c9SMauro Carvalho Chehab 		vfd->fops = &vivid_radio_fops;
160862c6b4c9SMauro Carvalho Chehab 		vfd->ioctl_ops = &vivid_ioctl_ops;
160962c6b4c9SMauro Carvalho Chehab 		vfd->device_caps = dev->radio_tx_caps;
161062c6b4c9SMauro Carvalho Chehab 		vfd->release = video_device_release_empty;
161162c6b4c9SMauro Carvalho Chehab 		vfd->v4l2_dev = &dev->v4l2_dev;
161262c6b4c9SMauro Carvalho Chehab 		vfd->lock = &dev->mutex;
161362c6b4c9SMauro Carvalho Chehab 		video_set_drvdata(vfd, dev);
161462c6b4c9SMauro Carvalho Chehab 
161562c6b4c9SMauro Carvalho Chehab 		ret = video_register_device(vfd, VFL_TYPE_RADIO, radio_tx_nr[inst]);
161662c6b4c9SMauro Carvalho Chehab 		if (ret < 0)
161762c6b4c9SMauro Carvalho Chehab 			return ret;
161862c6b4c9SMauro Carvalho Chehab 		v4l2_info(&dev->v4l2_dev, "V4L2 transmitter device registered as %s\n",
161962c6b4c9SMauro Carvalho Chehab 					  video_device_node_name(vfd));
162062c6b4c9SMauro Carvalho Chehab 	}
162162c6b4c9SMauro Carvalho Chehab 
162262c6b4c9SMauro Carvalho Chehab 	if (dev->has_meta_cap) {
162362c6b4c9SMauro Carvalho Chehab 		vfd = &dev->meta_cap_dev;
162462c6b4c9SMauro Carvalho Chehab 		snprintf(vfd->name, sizeof(vfd->name),
162562c6b4c9SMauro Carvalho Chehab 			 "vivid-%03d-meta-cap", inst);
162662c6b4c9SMauro Carvalho Chehab 		vfd->fops = &vivid_fops;
162762c6b4c9SMauro Carvalho Chehab 		vfd->ioctl_ops = &vivid_ioctl_ops;
162862c6b4c9SMauro Carvalho Chehab 		vfd->device_caps = dev->meta_cap_caps;
162962c6b4c9SMauro Carvalho Chehab 		vfd->release = video_device_release_empty;
163062c6b4c9SMauro Carvalho Chehab 		vfd->v4l2_dev = &dev->v4l2_dev;
163162c6b4c9SMauro Carvalho Chehab 		vfd->queue = &dev->vb_meta_cap_q;
163262c6b4c9SMauro Carvalho Chehab 		vfd->lock = &dev->mutex;
163362c6b4c9SMauro Carvalho Chehab 		vfd->tvnorms = tvnorms_cap;
163462c6b4c9SMauro Carvalho Chehab 		video_set_drvdata(vfd, dev);
163562c6b4c9SMauro Carvalho Chehab #ifdef CONFIG_MEDIA_CONTROLLER
163662c6b4c9SMauro Carvalho Chehab 		dev->meta_cap_pad.flags = MEDIA_PAD_FL_SINK;
163762c6b4c9SMauro Carvalho Chehab 		ret = media_entity_pads_init(&vfd->entity, 1,
163862c6b4c9SMauro Carvalho Chehab 					     &dev->meta_cap_pad);
163962c6b4c9SMauro Carvalho Chehab 		if (ret)
164062c6b4c9SMauro Carvalho Chehab 			return ret;
164162c6b4c9SMauro Carvalho Chehab #endif
164262c6b4c9SMauro Carvalho Chehab 		ret = video_register_device(vfd, VFL_TYPE_VIDEO,
164362c6b4c9SMauro Carvalho Chehab 					    meta_cap_nr[inst]);
164462c6b4c9SMauro Carvalho Chehab 		if (ret < 0)
164562c6b4c9SMauro Carvalho Chehab 			return ret;
164662c6b4c9SMauro Carvalho Chehab 		v4l2_info(&dev->v4l2_dev,
164762c6b4c9SMauro Carvalho Chehab 			  "V4L2 metadata capture device registered as %s\n",
164862c6b4c9SMauro Carvalho Chehab 			  video_device_node_name(vfd));
164962c6b4c9SMauro Carvalho Chehab 	}
165062c6b4c9SMauro Carvalho Chehab 
165162c6b4c9SMauro Carvalho Chehab 	if (dev->has_meta_out) {
165262c6b4c9SMauro Carvalho Chehab 		vfd = &dev->meta_out_dev;
165362c6b4c9SMauro Carvalho Chehab 		snprintf(vfd->name, sizeof(vfd->name),
165462c6b4c9SMauro Carvalho Chehab 			 "vivid-%03d-meta-out", inst);
165562c6b4c9SMauro Carvalho Chehab 		vfd->vfl_dir = VFL_DIR_TX;
165662c6b4c9SMauro Carvalho Chehab 		vfd->fops = &vivid_fops;
165762c6b4c9SMauro Carvalho Chehab 		vfd->ioctl_ops = &vivid_ioctl_ops;
165862c6b4c9SMauro Carvalho Chehab 		vfd->device_caps = dev->meta_out_caps;
165962c6b4c9SMauro Carvalho Chehab 		vfd->release = video_device_release_empty;
166062c6b4c9SMauro Carvalho Chehab 		vfd->v4l2_dev = &dev->v4l2_dev;
166162c6b4c9SMauro Carvalho Chehab 		vfd->queue = &dev->vb_meta_out_q;
166262c6b4c9SMauro Carvalho Chehab 		vfd->lock = &dev->mutex;
166362c6b4c9SMauro Carvalho Chehab 		vfd->tvnorms = tvnorms_out;
166462c6b4c9SMauro Carvalho Chehab 		video_set_drvdata(vfd, dev);
166562c6b4c9SMauro Carvalho Chehab #ifdef CONFIG_MEDIA_CONTROLLER
166662c6b4c9SMauro Carvalho Chehab 		dev->meta_out_pad.flags = MEDIA_PAD_FL_SOURCE;
166762c6b4c9SMauro Carvalho Chehab 		ret = media_entity_pads_init(&vfd->entity, 1,
166862c6b4c9SMauro Carvalho Chehab 					     &dev->meta_out_pad);
166962c6b4c9SMauro Carvalho Chehab 		if (ret)
167062c6b4c9SMauro Carvalho Chehab 			return ret;
167162c6b4c9SMauro Carvalho Chehab #endif
167262c6b4c9SMauro Carvalho Chehab 		ret = video_register_device(vfd, VFL_TYPE_VIDEO,
167362c6b4c9SMauro Carvalho Chehab 					    meta_out_nr[inst]);
167462c6b4c9SMauro Carvalho Chehab 		if (ret < 0)
167562c6b4c9SMauro Carvalho Chehab 			return ret;
167662c6b4c9SMauro Carvalho Chehab 		v4l2_info(&dev->v4l2_dev,
167762c6b4c9SMauro Carvalho Chehab 			  "V4L2 metadata output device registered as %s\n",
167862c6b4c9SMauro Carvalho Chehab 			  video_device_node_name(vfd));
167962c6b4c9SMauro Carvalho Chehab 	}
168062c6b4c9SMauro Carvalho Chehab 
168162c6b4c9SMauro Carvalho Chehab 	if (dev->has_touch_cap) {
168262c6b4c9SMauro Carvalho Chehab 		vfd = &dev->touch_cap_dev;
168362c6b4c9SMauro Carvalho Chehab 		snprintf(vfd->name, sizeof(vfd->name),
168462c6b4c9SMauro Carvalho Chehab 			 "vivid-%03d-touch-cap", inst);
168562c6b4c9SMauro Carvalho Chehab 		vfd->fops = &vivid_fops;
168662c6b4c9SMauro Carvalho Chehab 		vfd->ioctl_ops = &vivid_ioctl_ops;
168762c6b4c9SMauro Carvalho Chehab 		vfd->device_caps = dev->touch_cap_caps;
168862c6b4c9SMauro Carvalho Chehab 		vfd->release = video_device_release_empty;
168962c6b4c9SMauro Carvalho Chehab 		vfd->v4l2_dev = &dev->v4l2_dev;
169062c6b4c9SMauro Carvalho Chehab 		vfd->queue = &dev->vb_touch_cap_q;
169162c6b4c9SMauro Carvalho Chehab 		vfd->tvnorms = tvnorms_cap;
169262c6b4c9SMauro Carvalho Chehab 		vfd->lock = &dev->mutex;
169362c6b4c9SMauro Carvalho Chehab 		video_set_drvdata(vfd, dev);
169462c6b4c9SMauro Carvalho Chehab #ifdef CONFIG_MEDIA_CONTROLLER
169562c6b4c9SMauro Carvalho Chehab 		dev->touch_cap_pad.flags = MEDIA_PAD_FL_SINK;
169662c6b4c9SMauro Carvalho Chehab 		ret = media_entity_pads_init(&vfd->entity, 1,
169762c6b4c9SMauro Carvalho Chehab 					     &dev->touch_cap_pad);
169862c6b4c9SMauro Carvalho Chehab 		if (ret)
169962c6b4c9SMauro Carvalho Chehab 			return ret;
170062c6b4c9SMauro Carvalho Chehab #endif
170162c6b4c9SMauro Carvalho Chehab 		ret = video_register_device(vfd, VFL_TYPE_TOUCH,
170262c6b4c9SMauro Carvalho Chehab 					    touch_cap_nr[inst]);
170362c6b4c9SMauro Carvalho Chehab 		if (ret < 0)
170462c6b4c9SMauro Carvalho Chehab 			return ret;
170562c6b4c9SMauro Carvalho Chehab 		v4l2_info(&dev->v4l2_dev,
170662c6b4c9SMauro Carvalho Chehab 			  "V4L2 touch capture device registered as %s\n",
170762c6b4c9SMauro Carvalho Chehab 			  video_device_node_name(vfd));
170862c6b4c9SMauro Carvalho Chehab 	}
170962c6b4c9SMauro Carvalho Chehab 
171062c6b4c9SMauro Carvalho Chehab #ifdef CONFIG_MEDIA_CONTROLLER
171162c6b4c9SMauro Carvalho Chehab 	/* Register the media device */
171262c6b4c9SMauro Carvalho Chehab 	ret = media_device_register(&dev->mdev);
171362c6b4c9SMauro Carvalho Chehab 	if (ret) {
171462c6b4c9SMauro Carvalho Chehab 		dev_err(dev->mdev.dev,
171562c6b4c9SMauro Carvalho Chehab 			"media device register failed (err=%d)\n", ret);
171662c6b4c9SMauro Carvalho Chehab 		return ret;
171762c6b4c9SMauro Carvalho Chehab 	}
171862c6b4c9SMauro Carvalho Chehab #endif
171962c6b4c9SMauro Carvalho Chehab 	return 0;
172062c6b4c9SMauro Carvalho Chehab }
172162c6b4c9SMauro Carvalho Chehab 
vivid_create_instance(struct platform_device * pdev,int inst)172231b97d35SMauro Carvalho Chehab static int vivid_create_instance(struct platform_device *pdev, int inst)
172331b97d35SMauro Carvalho Chehab {
172431b97d35SMauro Carvalho Chehab 	static const struct v4l2_dv_timings def_dv_timings =
172531b97d35SMauro Carvalho Chehab 					V4L2_DV_BT_CEA_1280X720P60;
172631b97d35SMauro Carvalho Chehab 	unsigned in_type_counter[4] = { 0, 0, 0, 0 };
172731b97d35SMauro Carvalho Chehab 	unsigned out_type_counter[4] = { 0, 0, 0, 0 };
172831b97d35SMauro Carvalho Chehab 	int ccs_cap = ccs_cap_mode[inst];
172931b97d35SMauro Carvalho Chehab 	int ccs_out = ccs_out_mode[inst];
173031b97d35SMauro Carvalho Chehab 	bool has_tuner;
173131b97d35SMauro Carvalho Chehab 	bool has_modulator;
173231b97d35SMauro Carvalho Chehab 	struct vivid_dev *dev;
173331b97d35SMauro Carvalho Chehab 	unsigned node_type = node_types[inst];
173431b97d35SMauro Carvalho Chehab 	v4l2_std_id tvnorms_cap = 0, tvnorms_out = 0;
1735d034731bSHans Verkuil 	unsigned int cec_tx_bus_cnt = 0;
173631b97d35SMauro Carvalho Chehab 	int ret;
173731b97d35SMauro Carvalho Chehab 	int i;
173831b97d35SMauro Carvalho Chehab 
173931b97d35SMauro Carvalho Chehab 	/* allocate main vivid state structure */
174031b97d35SMauro Carvalho Chehab 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
174131b97d35SMauro Carvalho Chehab 	if (!dev)
174231b97d35SMauro Carvalho Chehab 		return -ENOMEM;
174331b97d35SMauro Carvalho Chehab 
174431b97d35SMauro Carvalho Chehab 	dev->inst = inst;
174531b97d35SMauro Carvalho Chehab 
174631b97d35SMauro Carvalho Chehab #ifdef CONFIG_MEDIA_CONTROLLER
174731b97d35SMauro Carvalho Chehab 	dev->v4l2_dev.mdev = &dev->mdev;
174831b97d35SMauro Carvalho Chehab 
174931b97d35SMauro Carvalho Chehab 	/* Initialize media device */
175031b97d35SMauro Carvalho Chehab 	strscpy(dev->mdev.model, VIVID_MODULE_NAME, sizeof(dev->mdev.model));
175131b97d35SMauro Carvalho Chehab 	snprintf(dev->mdev.bus_info, sizeof(dev->mdev.bus_info),
175231b97d35SMauro Carvalho Chehab 		 "platform:%s-%03d", VIVID_MODULE_NAME, inst);
175331b97d35SMauro Carvalho Chehab 	dev->mdev.dev = &pdev->dev;
175431b97d35SMauro Carvalho Chehab 	media_device_init(&dev->mdev);
175531b97d35SMauro Carvalho Chehab 	dev->mdev.ops = &vivid_media_ops;
175631b97d35SMauro Carvalho Chehab #endif
175731b97d35SMauro Carvalho Chehab 
175831b97d35SMauro Carvalho Chehab 	/* register v4l2_device */
175931b97d35SMauro Carvalho Chehab 	snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
176031b97d35SMauro Carvalho Chehab 			"%s-%03d", VIVID_MODULE_NAME, inst);
176131b97d35SMauro Carvalho Chehab 	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
176231b97d35SMauro Carvalho Chehab 	if (ret) {
176331b97d35SMauro Carvalho Chehab 		kfree(dev);
176431b97d35SMauro Carvalho Chehab 		return ret;
176531b97d35SMauro Carvalho Chehab 	}
176631b97d35SMauro Carvalho Chehab 	dev->v4l2_dev.release = vivid_dev_release;
176731b97d35SMauro Carvalho Chehab 
176831b97d35SMauro Carvalho Chehab 	ret = vivid_detect_feature_set(dev, inst, node_type,
176931b97d35SMauro Carvalho Chehab 				       &has_tuner, &has_modulator,
177031b97d35SMauro Carvalho Chehab 				       &ccs_cap, &ccs_out,
177131b97d35SMauro Carvalho Chehab 				       in_type_counter, out_type_counter);
177249a3d74bSMauro Carvalho Chehab 	if (ret)
177349a3d74bSMauro Carvalho Chehab 		goto free_dev;
1774dacca5f0SHans Verkuil 
17754306c537SMauro Carvalho Chehab 	vivid_set_capabilities(dev);
1776dacca5f0SHans Verkuil 
1777dacca5f0SHans Verkuil 	ret = -ENOMEM;
1778dacca5f0SHans Verkuil 	/* initialize the test pattern generator */
1779dacca5f0SHans Verkuil 	tpg_init(&dev->tpg, 640, 360);
1780a32e8adfSGustavo A. R. Silva 	if (tpg_alloc(&dev->tpg, array_size(MAX_WIDTH, MAX_ZOOM)))
1781dacca5f0SHans Verkuil 		goto free_dev;
1782dacca5f0SHans Verkuil 	dev->scaled_line = vzalloc(array_size(MAX_WIDTH, MAX_ZOOM));
1783dacca5f0SHans Verkuil 	if (!dev->scaled_line)
1784dacca5f0SHans Verkuil 		goto free_dev;
1785dacca5f0SHans Verkuil 	dev->blended_line = vzalloc(array_size(MAX_WIDTH, MAX_ZOOM));
1786dacca5f0SHans Verkuil 	if (!dev->blended_line)
1787dacca5f0SHans Verkuil 		goto free_dev;
1788dacca5f0SHans Verkuil 
1789dacca5f0SHans Verkuil 	/* load the edid */
1790a32e8adfSGustavo A. R. Silva 	dev->edid = vmalloc(array_size(256, 128));
1791dacca5f0SHans Verkuil 	if (!dev->edid)
1792dacca5f0SHans Verkuil 		goto free_dev;
1793dacca5f0SHans Verkuil 
1794d92c8e31SMauro Carvalho Chehab 	ret = vivid_init_dv_timings(dev);
1795d92c8e31SMauro Carvalho Chehab 	if (ret < 0)
1796dacca5f0SHans Verkuil 		goto free_dev;
1797dacca5f0SHans Verkuil 
1798fcaeb019SMauro Carvalho Chehab 	vivid_disable_unused_ioctls(dev, has_tuner, has_modulator,
1799fcaeb019SMauro Carvalho Chehab 				    in_type_counter, out_type_counter);
1800dacca5f0SHans Verkuil 
1801dacca5f0SHans Verkuil 	/* configure internal data */
1802dacca5f0SHans Verkuil 	dev->fmt_cap = &vivid_formats[0];
1803dacca5f0SHans Verkuil 	dev->fmt_out = &vivid_formats[0];
1804dacca5f0SHans Verkuil 	if (!dev->multiplanar)
1805dacca5f0SHans Verkuil 		vivid_formats[0].data_offset[0] = 0;
1806dacca5f0SHans Verkuil 	dev->webcam_size_idx = 1;
1807dacca5f0SHans Verkuil 	dev->webcam_ival_idx = 3;
1808dacca5f0SHans Verkuil 	tpg_s_fourcc(&dev->tpg, dev->fmt_cap->fourcc);
1809dacca5f0SHans Verkuil 	dev->std_out = V4L2_STD_PAL;
1810dacca5f0SHans Verkuil 	if (dev->input_type[0] == TV || dev->input_type[0] == SVID)
1811dacca5f0SHans Verkuil 		tvnorms_cap = V4L2_STD_ALL;
1812dacca5f0SHans Verkuil 	if (dev->output_type[0] == SVID)
1813dacca5f0SHans Verkuil 		tvnorms_out = V4L2_STD_ALL;
1814dacca5f0SHans Verkuil 	for (i = 0; i < MAX_INPUTS; i++) {
1815dacca5f0SHans Verkuil 		dev->dv_timings_cap[i] = def_dv_timings;
1816dacca5f0SHans Verkuil 		dev->std_cap[i] = V4L2_STD_PAL;
1817dacca5f0SHans Verkuil 	}
1818dacca5f0SHans Verkuil 	dev->dv_timings_out = def_dv_timings;
1819dacca5f0SHans Verkuil 	dev->tv_freq = 2804 /* 175.25 * 16 */;
1820dacca5f0SHans Verkuil 	dev->tv_audmode = V4L2_TUNER_MODE_STEREO;
1821dacca5f0SHans Verkuil 	dev->tv_field_cap = V4L2_FIELD_INTERLACED;
1822dacca5f0SHans Verkuil 	dev->tv_field_out = V4L2_FIELD_INTERLACED;
1823dacca5f0SHans Verkuil 	dev->radio_rx_freq = 95000 * 16;
1824dacca5f0SHans Verkuil 	dev->radio_rx_audmode = V4L2_TUNER_MODE_STEREO;
1825dacca5f0SHans Verkuil 	if (dev->has_radio_tx) {
1826dacca5f0SHans Verkuil 		dev->radio_tx_freq = 95500 * 16;
1827dacca5f0SHans Verkuil 		dev->radio_rds_loop = false;
1828dacca5f0SHans Verkuil 	}
1829dacca5f0SHans Verkuil 	dev->radio_tx_subchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_RDS;
1830dacca5f0SHans Verkuil 	dev->sdr_adc_freq = 300000;
1831dacca5f0SHans Verkuil 	dev->sdr_fm_freq = 50000000;
1832dacca5f0SHans Verkuil 	dev->sdr_pixelformat = V4L2_SDR_FMT_CU8;
1833dacca5f0SHans Verkuil 	dev->sdr_buffersize = SDR_CAP_SAMPLES_PER_BUF * 2;
1834dacca5f0SHans Verkuil 
1835dacca5f0SHans Verkuil 	dev->edid_max_blocks = dev->edid_blocks = 2;
1836dacca5f0SHans Verkuil 	memcpy(dev->edid, vivid_hdmi_edid, sizeof(vivid_hdmi_edid));
1837dacca5f0SHans Verkuil 	dev->radio_rds_init_time = ktime_get();
1838dacca5f0SHans Verkuil 
1839dacca5f0SHans Verkuil 	/* create all controls */
1840dacca5f0SHans Verkuil 	ret = vivid_create_controls(dev, ccs_cap == -1, ccs_out == -1, no_error_inj,
1841dacca5f0SHans Verkuil 			in_type_counter[TV] || in_type_counter[SVID] ||
1842dacca5f0SHans Verkuil 			out_type_counter[SVID],
1843dacca5f0SHans Verkuil 			in_type_counter[HDMI] || out_type_counter[HDMI]);
1844dacca5f0SHans Verkuil 	if (ret)
1845dacca5f0SHans Verkuil 		goto unreg_dev;
1846dacca5f0SHans Verkuil 
1847dacca5f0SHans Verkuil 	/* enable/disable interface specific controls */
1848dacca5f0SHans Verkuil 	if (dev->num_outputs && dev->output_type[0] != HDMI)
1849dacca5f0SHans Verkuil 		v4l2_ctrl_activate(dev->ctrl_display_present, false);
1850dacca5f0SHans Verkuil 	if (dev->num_inputs && dev->input_type[0] != HDMI) {
1851dacca5f0SHans Verkuil 		v4l2_ctrl_activate(dev->ctrl_dv_timings_signal_mode, false);
1852dacca5f0SHans Verkuil 		v4l2_ctrl_activate(dev->ctrl_dv_timings, false);
1853dacca5f0SHans Verkuil 	} else if (dev->num_inputs && dev->input_type[0] == HDMI) {
1854dacca5f0SHans Verkuil 		v4l2_ctrl_activate(dev->ctrl_std_signal_mode, false);
1855dacca5f0SHans Verkuil 		v4l2_ctrl_activate(dev->ctrl_standard, false);
1856dacca5f0SHans Verkuil 	}
1857dacca5f0SHans Verkuil 
1858dacca5f0SHans Verkuil 	/*
1859dacca5f0SHans Verkuil 	 * update the capture and output formats to do a proper initial
1860dacca5f0SHans Verkuil 	 * configuration.
1861dacca5f0SHans Verkuil 	 */
1862dacca5f0SHans Verkuil 	vivid_update_format_cap(dev, false);
1863dacca5f0SHans Verkuil 	vivid_update_format_out(dev);
1864dacca5f0SHans Verkuil 
1865dacca5f0SHans Verkuil 	/* update touch configuration */
1866dacca5f0SHans Verkuil 	dev->timeperframe_tch_cap.numerator = 1;
1867dacca5f0SHans Verkuil 	dev->timeperframe_tch_cap.denominator = 10;
1868dacca5f0SHans Verkuil 	vivid_set_touch(dev, 0);
1869dacca5f0SHans Verkuil 
1870dacca5f0SHans Verkuil 	/* initialize locks */
1871dacca5f0SHans Verkuil 	spin_lock_init(&dev->slock);
1872dacca5f0SHans Verkuil 	mutex_init(&dev->mutex);
1873dacca5f0SHans Verkuil 
1874dacca5f0SHans Verkuil 	/* init dma queues */
1875dacca5f0SHans Verkuil 	INIT_LIST_HEAD(&dev->vid_cap_active);
1876dacca5f0SHans Verkuil 	INIT_LIST_HEAD(&dev->vid_out_active);
1877dacca5f0SHans Verkuil 	INIT_LIST_HEAD(&dev->vbi_cap_active);
1878dacca5f0SHans Verkuil 	INIT_LIST_HEAD(&dev->vbi_out_active);
1879dacca5f0SHans Verkuil 	INIT_LIST_HEAD(&dev->sdr_cap_active);
1880dacca5f0SHans Verkuil 	INIT_LIST_HEAD(&dev->meta_cap_active);
1881dacca5f0SHans Verkuil 	INIT_LIST_HEAD(&dev->meta_out_active);
1882dacca5f0SHans Verkuil 	INIT_LIST_HEAD(&dev->touch_cap_active);
1883dacca5f0SHans Verkuil 
1884c6c709eeSDeborah Brouwer 	spin_lock_init(&dev->cec_xfers_slock);
1885dacca5f0SHans Verkuil 
1886dacca5f0SHans Verkuil 	if (allocators[inst] == 1)
1887dacca5f0SHans Verkuil 		dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
1888dacca5f0SHans Verkuil 
1889faf21f28SMauro Carvalho Chehab 	ret = vivid_create_queues(dev);
1890dacca5f0SHans Verkuil 	if (ret)
1891dacca5f0SHans Verkuil 		goto unreg_dev;
1892dacca5f0SHans Verkuil 
1893dacca5f0SHans Verkuil #ifdef CONFIG_VIDEO_VIVID_CEC
1894dacca5f0SHans Verkuil 	if (dev->has_vid_cap && in_type_counter[HDMI]) {
1895dacca5f0SHans Verkuil 		struct cec_adapter *adap;
1896dacca5f0SHans Verkuil 
1897dacca5f0SHans Verkuil 		adap = vivid_cec_alloc_adap(dev, 0, false);
1898dacca5f0SHans Verkuil 		ret = PTR_ERR_OR_ZERO(adap);
1899dacca5f0SHans Verkuil 		if (ret < 0)
1900dacca5f0SHans Verkuil 			goto unreg_dev;
1901dacca5f0SHans Verkuil 		dev->cec_rx_adap = adap;
1902dacca5f0SHans Verkuil 	}
1903dacca5f0SHans Verkuil 
1904dacca5f0SHans Verkuil 	if (dev->has_vid_out) {
1905dacca5f0SHans Verkuil 		for (i = 0; i < dev->num_outputs; i++) {
1906dacca5f0SHans Verkuil 			struct cec_adapter *adap;
1907dacca5f0SHans Verkuil 
1908dacca5f0SHans Verkuil 			if (dev->output_type[i] != HDMI)
1909dacca5f0SHans Verkuil 				continue;
1910dacca5f0SHans Verkuil 
1911dacca5f0SHans Verkuil 			dev->cec_output2bus_map[i] = cec_tx_bus_cnt;
1912dacca5f0SHans Verkuil 			adap = vivid_cec_alloc_adap(dev, cec_tx_bus_cnt, true);
1913dacca5f0SHans Verkuil 			ret = PTR_ERR_OR_ZERO(adap);
1914dacca5f0SHans Verkuil 			if (ret < 0) {
1915dacca5f0SHans Verkuil 				for (i = 0; i < dev->num_outputs; i++)
1916dacca5f0SHans Verkuil 					cec_delete_adapter(dev->cec_tx_adap[i]);
1917dacca5f0SHans Verkuil 				goto unreg_dev;
1918dacca5f0SHans Verkuil 			}
1919dacca5f0SHans Verkuil 
1920dacca5f0SHans Verkuil 			dev->cec_tx_adap[cec_tx_bus_cnt] = adap;
1921dacca5f0SHans Verkuil 			cec_tx_bus_cnt++;
1922dacca5f0SHans Verkuil 		}
1923dacca5f0SHans Verkuil 	}
1924c6c709eeSDeborah Brouwer 
1925c6c709eeSDeborah Brouwer 	if (dev->cec_rx_adap || cec_tx_bus_cnt) {
1926c6c709eeSDeborah Brouwer 		init_waitqueue_head(&dev->kthread_waitq_cec);
1927c6c709eeSDeborah Brouwer 		dev->kthread_cec = kthread_run(vivid_cec_bus_thread, dev,
1928c6c709eeSDeborah Brouwer 					       "vivid_cec-%s", dev->v4l2_dev.name);
1929c6c709eeSDeborah Brouwer 		if (IS_ERR(dev->kthread_cec)) {
193021001fdbSDan Carpenter 			ret = PTR_ERR(dev->kthread_cec);
1931c6c709eeSDeborah Brouwer 			dev->kthread_cec = NULL;
1932c6c709eeSDeborah Brouwer 			v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
1933c6c709eeSDeborah Brouwer 			goto unreg_dev;
1934c6c709eeSDeborah Brouwer 		}
1935c6c709eeSDeborah Brouwer 	}
1936c6c709eeSDeborah Brouwer 
1937dacca5f0SHans Verkuil #endif
1938dacca5f0SHans Verkuil 
1939dacca5f0SHans Verkuil 	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vid_cap);
1940dacca5f0SHans Verkuil 	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vid_out);
1941dacca5f0SHans Verkuil 	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vbi_cap);
1942dacca5f0SHans Verkuil 	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vbi_out);
1943dacca5f0SHans Verkuil 	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_radio_rx);
1944dacca5f0SHans Verkuil 	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_radio_tx);
1945dacca5f0SHans Verkuil 	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_sdr_cap);
1946dacca5f0SHans Verkuil 	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_meta_cap);
1947dacca5f0SHans Verkuil 	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_meta_out);
1948dacca5f0SHans Verkuil 	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_touch_cap);
1949dacca5f0SHans Verkuil 
1950dacca5f0SHans Verkuil 	/* finally start creating the device nodes */
195162c6b4c9SMauro Carvalho Chehab 	ret = vivid_create_devnodes(pdev, dev, inst, cec_tx_bus_cnt,
195262c6b4c9SMauro Carvalho Chehab 				    tvnorms_cap, tvnorms_out,
195362c6b4c9SMauro Carvalho Chehab 				    in_type_counter, out_type_counter);
1954dacca5f0SHans Verkuil 	if (ret)
1955dacca5f0SHans Verkuil 		goto unreg_dev;
1956dacca5f0SHans Verkuil 
1957dacca5f0SHans Verkuil 	/* Now that everything is fine, let's add it to device list */
1958dacca5f0SHans Verkuil 	vivid_devs[inst] = dev;
1959dacca5f0SHans Verkuil 
1960dacca5f0SHans Verkuil 	return 0;
1961dacca5f0SHans Verkuil 
1962dacca5f0SHans Verkuil unreg_dev:
1963bda24f43SHans Verkuil 	vb2_video_unregister_device(&dev->touch_cap_dev);
1964bda24f43SHans Verkuil 	vb2_video_unregister_device(&dev->meta_out_dev);
1965bda24f43SHans Verkuil 	vb2_video_unregister_device(&dev->meta_cap_dev);
1966dacca5f0SHans Verkuil 	video_unregister_device(&dev->radio_tx_dev);
1967dacca5f0SHans Verkuil 	video_unregister_device(&dev->radio_rx_dev);
1968bda24f43SHans Verkuil 	vb2_video_unregister_device(&dev->sdr_cap_dev);
1969bda24f43SHans Verkuil 	vb2_video_unregister_device(&dev->vbi_out_dev);
1970bda24f43SHans Verkuil 	vb2_video_unregister_device(&dev->vbi_cap_dev);
1971bda24f43SHans Verkuil 	vb2_video_unregister_device(&dev->vid_out_dev);
1972bda24f43SHans Verkuil 	vb2_video_unregister_device(&dev->vid_cap_dev);
1973dacca5f0SHans Verkuil 	cec_unregister_adapter(dev->cec_rx_adap);
1974dacca5f0SHans Verkuil 	for (i = 0; i < MAX_OUTPUTS; i++)
1975dacca5f0SHans Verkuil 		cec_unregister_adapter(dev->cec_tx_adap[i]);
1976c6c709eeSDeborah Brouwer 	if (dev->kthread_cec)
1977c6c709eeSDeborah Brouwer 		kthread_stop(dev->kthread_cec);
1978dacca5f0SHans Verkuil free_dev:
1979dacca5f0SHans Verkuil 	v4l2_device_put(&dev->v4l2_dev);
1980dacca5f0SHans Verkuil 	return ret;
1981dacca5f0SHans Verkuil }
1982dacca5f0SHans Verkuil 
1983dacca5f0SHans Verkuil /* This routine allocates from 1 to n_devs virtual drivers.
1984dacca5f0SHans Verkuil 
1985dacca5f0SHans Verkuil    The real maximum number of virtual drivers will depend on how many drivers
1986dacca5f0SHans Verkuil    will succeed. This is limited to the maximum number of devices that
1987dacca5f0SHans Verkuil    videodev supports, which is equal to VIDEO_NUM_DEVICES.
1988dacca5f0SHans Verkuil  */
vivid_probe(struct platform_device * pdev)1989dacca5f0SHans Verkuil static int vivid_probe(struct platform_device *pdev)
1990dacca5f0SHans Verkuil {
1991dacca5f0SHans Verkuil 	const struct font_desc *font = find_font("VGA8x16");
1992dacca5f0SHans Verkuil 	int ret = 0, i;
1993dacca5f0SHans Verkuil 
1994dacca5f0SHans Verkuil 	if (font == NULL) {
1995dacca5f0SHans Verkuil 		pr_err("vivid: could not find font\n");
1996dacca5f0SHans Verkuil 		return -ENODEV;
1997dacca5f0SHans Verkuil 	}
1998dacca5f0SHans Verkuil 
1999dacca5f0SHans Verkuil 	tpg_set_font(font->data);
2000dacca5f0SHans Verkuil 
2001dacca5f0SHans Verkuil 	n_devs = clamp_t(unsigned, n_devs, 1, VIVID_MAX_DEVS);
2002dacca5f0SHans Verkuil 
2003dacca5f0SHans Verkuil 	for (i = 0; i < n_devs; i++) {
2004dacca5f0SHans Verkuil 		ret = vivid_create_instance(pdev, i);
2005dacca5f0SHans Verkuil 		if (ret) {
2006dacca5f0SHans Verkuil 			/* If some instantiations succeeded, keep driver */
2007dacca5f0SHans Verkuil 			if (i)
2008dacca5f0SHans Verkuil 				ret = 0;
2009dacca5f0SHans Verkuil 			break;
2010dacca5f0SHans Verkuil 		}
2011dacca5f0SHans Verkuil 	}
2012dacca5f0SHans Verkuil 
2013dacca5f0SHans Verkuil 	if (ret < 0) {
2014dacca5f0SHans Verkuil 		pr_err("vivid: error %d while loading driver\n", ret);
2015dacca5f0SHans Verkuil 		return ret;
2016dacca5f0SHans Verkuil 	}
2017dacca5f0SHans Verkuil 
2018dacca5f0SHans Verkuil 	/* n_devs will reflect the actual number of allocated devices */
2019dacca5f0SHans Verkuil 	n_devs = i;
2020dacca5f0SHans Verkuil 
2021dacca5f0SHans Verkuil 	return ret;
2022dacca5f0SHans Verkuil }
2023dacca5f0SHans Verkuil 
vivid_remove(struct platform_device * pdev)2024fc63c5b1SUwe Kleine-König static void vivid_remove(struct platform_device *pdev)
2025dacca5f0SHans Verkuil {
2026dacca5f0SHans Verkuil 	struct vivid_dev *dev;
2027dacca5f0SHans Verkuil 	unsigned int i, j;
2028dacca5f0SHans Verkuil 
2029dacca5f0SHans Verkuil 	for (i = 0; i < n_devs; i++) {
2030dacca5f0SHans Verkuil 		dev = vivid_devs[i];
2031dacca5f0SHans Verkuil 		if (!dev)
2032dacca5f0SHans Verkuil 			continue;
2033dacca5f0SHans Verkuil 
20349e5f21d6SHans Verkuil 		if (dev->disconnect_error)
20359e5f21d6SHans Verkuil 			vivid_reconnect(dev);
2036dacca5f0SHans Verkuil #ifdef CONFIG_MEDIA_CONTROLLER
2037dacca5f0SHans Verkuil 		media_device_unregister(&dev->mdev);
2038dacca5f0SHans Verkuil #endif
2039dacca5f0SHans Verkuil 
2040dacca5f0SHans Verkuil 		if (dev->has_vid_cap) {
2041dacca5f0SHans Verkuil 			v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
2042dacca5f0SHans Verkuil 				video_device_node_name(&dev->vid_cap_dev));
2043bda24f43SHans Verkuil 			vb2_video_unregister_device(&dev->vid_cap_dev);
2044dacca5f0SHans Verkuil 		}
2045dacca5f0SHans Verkuil 		if (dev->has_vid_out) {
2046dacca5f0SHans Verkuil 			v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
2047dacca5f0SHans Verkuil 				video_device_node_name(&dev->vid_out_dev));
2048bda24f43SHans Verkuil 			vb2_video_unregister_device(&dev->vid_out_dev);
2049dacca5f0SHans Verkuil 		}
2050dacca5f0SHans Verkuil 		if (dev->has_vbi_cap) {
2051dacca5f0SHans Verkuil 			v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
2052dacca5f0SHans Verkuil 				video_device_node_name(&dev->vbi_cap_dev));
2053bda24f43SHans Verkuil 			vb2_video_unregister_device(&dev->vbi_cap_dev);
2054dacca5f0SHans Verkuil 		}
2055dacca5f0SHans Verkuil 		if (dev->has_vbi_out) {
2056dacca5f0SHans Verkuil 			v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
2057dacca5f0SHans Verkuil 				video_device_node_name(&dev->vbi_out_dev));
2058bda24f43SHans Verkuil 			vb2_video_unregister_device(&dev->vbi_out_dev);
2059dacca5f0SHans Verkuil 		}
2060dacca5f0SHans Verkuil 		if (dev->has_sdr_cap) {
2061dacca5f0SHans Verkuil 			v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
2062dacca5f0SHans Verkuil 				video_device_node_name(&dev->sdr_cap_dev));
2063bda24f43SHans Verkuil 			vb2_video_unregister_device(&dev->sdr_cap_dev);
2064dacca5f0SHans Verkuil 		}
2065dacca5f0SHans Verkuil 		if (dev->has_radio_rx) {
2066dacca5f0SHans Verkuil 			v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
2067dacca5f0SHans Verkuil 				video_device_node_name(&dev->radio_rx_dev));
2068dacca5f0SHans Verkuil 			video_unregister_device(&dev->radio_rx_dev);
2069dacca5f0SHans Verkuil 		}
2070dacca5f0SHans Verkuil 		if (dev->has_radio_tx) {
2071dacca5f0SHans Verkuil 			v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
2072dacca5f0SHans Verkuil 				video_device_node_name(&dev->radio_tx_dev));
2073dacca5f0SHans Verkuil 			video_unregister_device(&dev->radio_tx_dev);
2074dacca5f0SHans Verkuil 		}
2075dacca5f0SHans Verkuil 		if (dev->has_fb) {
2076dacca5f0SHans Verkuil 			v4l2_info(&dev->v4l2_dev, "unregistering fb%d\n",
2077dacca5f0SHans Verkuil 				dev->fb_info.node);
2078dacca5f0SHans Verkuil 			unregister_framebuffer(&dev->fb_info);
2079dacca5f0SHans Verkuil 			vivid_fb_release_buffers(dev);
2080dacca5f0SHans Verkuil 		}
2081dacca5f0SHans Verkuil 		if (dev->has_meta_cap) {
2082dacca5f0SHans Verkuil 			v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
2083dacca5f0SHans Verkuil 				  video_device_node_name(&dev->meta_cap_dev));
2084bda24f43SHans Verkuil 			vb2_video_unregister_device(&dev->meta_cap_dev);
2085dacca5f0SHans Verkuil 		}
2086dacca5f0SHans Verkuil 		if (dev->has_meta_out) {
2087dacca5f0SHans Verkuil 			v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
2088dacca5f0SHans Verkuil 				  video_device_node_name(&dev->meta_out_dev));
2089bda24f43SHans Verkuil 			vb2_video_unregister_device(&dev->meta_out_dev);
2090dacca5f0SHans Verkuil 		}
2091dacca5f0SHans Verkuil 		if (dev->has_touch_cap) {
2092dacca5f0SHans Verkuil 			v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
2093dacca5f0SHans Verkuil 				  video_device_node_name(&dev->touch_cap_dev));
2094bda24f43SHans Verkuil 			vb2_video_unregister_device(&dev->touch_cap_dev);
2095dacca5f0SHans Verkuil 		}
2096dacca5f0SHans Verkuil 		cec_unregister_adapter(dev->cec_rx_adap);
2097dacca5f0SHans Verkuil 		for (j = 0; j < MAX_OUTPUTS; j++)
2098dacca5f0SHans Verkuil 			cec_unregister_adapter(dev->cec_tx_adap[j]);
2099c6c709eeSDeborah Brouwer 		if (dev->kthread_cec)
2100c6c709eeSDeborah Brouwer 			kthread_stop(dev->kthread_cec);
2101dacca5f0SHans Verkuil 		v4l2_device_put(&dev->v4l2_dev);
2102dacca5f0SHans Verkuil 		vivid_devs[i] = NULL;
2103dacca5f0SHans Verkuil 	}
2104dacca5f0SHans Verkuil }
2105dacca5f0SHans Verkuil 
vivid_pdev_release(struct device * dev)2106dacca5f0SHans Verkuil static void vivid_pdev_release(struct device *dev)
2107dacca5f0SHans Verkuil {
2108dacca5f0SHans Verkuil }
2109dacca5f0SHans Verkuil 
2110dacca5f0SHans Verkuil static struct platform_device vivid_pdev = {
2111dacca5f0SHans Verkuil 	.name		= "vivid",
2112dacca5f0SHans Verkuil 	.dev.release	= vivid_pdev_release,
2113dacca5f0SHans Verkuil };
2114dacca5f0SHans Verkuil 
2115dacca5f0SHans Verkuil static struct platform_driver vivid_pdrv = {
2116dacca5f0SHans Verkuil 	.probe		= vivid_probe,
2117fc63c5b1SUwe Kleine-König 	.remove_new	= vivid_remove,
2118dacca5f0SHans Verkuil 	.driver		= {
2119dacca5f0SHans Verkuil 		.name	= "vivid",
2120dacca5f0SHans Verkuil 	},
2121dacca5f0SHans Verkuil };
2122dacca5f0SHans Verkuil 
vivid_init(void)2123dacca5f0SHans Verkuil static int __init vivid_init(void)
2124dacca5f0SHans Verkuil {
2125dacca5f0SHans Verkuil 	int ret;
2126dacca5f0SHans Verkuil 
2127dacca5f0SHans Verkuil 	ret = platform_device_register(&vivid_pdev);
2128dacca5f0SHans Verkuil 	if (ret)
2129dacca5f0SHans Verkuil 		return ret;
2130dacca5f0SHans Verkuil 
2131dacca5f0SHans Verkuil 	ret = platform_driver_register(&vivid_pdrv);
2132dacca5f0SHans Verkuil 	if (ret)
2133dacca5f0SHans Verkuil 		platform_device_unregister(&vivid_pdev);
2134dacca5f0SHans Verkuil 
2135dacca5f0SHans Verkuil 	return ret;
2136dacca5f0SHans Verkuil }
2137dacca5f0SHans Verkuil 
vivid_exit(void)2138dacca5f0SHans Verkuil static void __exit vivid_exit(void)
2139dacca5f0SHans Verkuil {
2140dacca5f0SHans Verkuil 	platform_driver_unregister(&vivid_pdrv);
2141dacca5f0SHans Verkuil 	platform_device_unregister(&vivid_pdev);
2142dacca5f0SHans Verkuil }
2143dacca5f0SHans Verkuil 
2144dacca5f0SHans Verkuil module_init(vivid_init);
2145dacca5f0SHans Verkuil module_exit(vivid_exit);
2146