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