blob: 9b51f07a729e4e949b309082912600e3ec6ecf40 [file] [log] [blame]
Thomas Gleixner74ba9202019-05-20 09:19:02 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Sri Deevie0d3baf2009-03-03 14:37:50 -03002/*
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03003 cx231xx-video.c - driver for Conexant Cx23100/101/102
4 USB video capture devices
Sri Deevie0d3baf2009-03-03 14:37:50 -03005
6 Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03007 Based on em28xx driver
8 Based on cx23885 driver
9 Based on cx88 driver
Sri Deevie0d3baf2009-03-03 14:37:50 -030010
Sri Deevie0d3baf2009-03-03 14:37:50 -030011 */
12
Mauro Carvalho Chehab589dadf2014-11-01 08:09:44 -030013#include "cx231xx.h"
Sri Deevie0d3baf2009-03-03 14:37:50 -030014#include <linux/init.h>
15#include <linux/list.h>
16#include <linux/module.h>
17#include <linux/kernel.h>
18#include <linux/bitmap.h>
Sri Deevie0d3baf2009-03-03 14:37:50 -030019#include <linux/i2c.h>
Sri Deevie0d3baf2009-03-03 14:37:50 -030020#include <linux/mm.h>
21#include <linux/mutex.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090022#include <linux/slab.h>
Sri Deevie0d3baf2009-03-03 14:37:50 -030023
24#include <media/v4l2-common.h>
25#include <media/v4l2-ioctl.h>
Hans Verkuil1d08a4f2012-09-17 07:31:04 -030026#include <media/v4l2-event.h>
Mauro Carvalho Chehabd647f0b2015-11-13 19:40:07 -020027#include <media/drv-intf/msp3400.h>
Sri Deevie0d3baf2009-03-03 14:37:50 -030028#include <media/tuner.h>
29
Mauro Carvalho Chehabfada1932017-12-28 13:03:51 -050030#include <media/dvb_frontend.h>
Sri Deevie0d3baf2009-03-03 14:37:50 -030031
Sri Deevie0d3baf2009-03-03 14:37:50 -030032#include "cx231xx-vbi.h"
33
Mauro Carvalho Chehab3d28cf32014-11-02 08:35:46 -030034#define CX231XX_VERSION "0.0.3"
Mauro Carvalho Chehab818fdf32009-03-13 07:41:58 -030035
Sri Deevie0d3baf2009-03-03 14:37:50 -030036#define DRIVER_AUTHOR "Srinivasa Deevi <srinivasa.deevi@conexant.com>"
37#define DRIVER_DESC "Conexant cx231xx based USB video device driver"
38
Sri Deevie0d3baf2009-03-03 14:37:50 -030039#define cx231xx_videodbg(fmt, arg...) do {\
40 if (video_debug) \
41 printk(KERN_INFO "%s %s :"fmt, \
42 dev->name, __func__ , ##arg); } while (0)
43
44static unsigned int isoc_debug;
45module_param(isoc_debug, int, 0644);
46MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");
47
48#define cx231xx_isocdbg(fmt, arg...) \
49do {\
50 if (isoc_debug) { \
51 printk(KERN_INFO "%s %s :"fmt, \
52 dev->name, __func__ , ##arg); \
53 } \
54 } while (0)
55
56MODULE_AUTHOR(DRIVER_AUTHOR);
57MODULE_DESCRIPTION(DRIVER_DESC);
58MODULE_LICENSE("GPL");
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -030059MODULE_VERSION(CX231XX_VERSION);
Sri Deevie0d3baf2009-03-03 14:37:50 -030060
Sri Deevie0d3baf2009-03-03 14:37:50 -030061static unsigned int card[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET };
62static unsigned int video_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET };
63static unsigned int vbi_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET };
64static unsigned int radio_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET };
65
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -030066module_param_array(card, int, NULL, 0444);
Sri Deevie0d3baf2009-03-03 14:37:50 -030067module_param_array(video_nr, int, NULL, 0444);
68module_param_array(vbi_nr, int, NULL, 0444);
69module_param_array(radio_nr, int, NULL, 0444);
70
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -030071MODULE_PARM_DESC(card, "card type");
Sri Deevie0d3baf2009-03-03 14:37:50 -030072MODULE_PARM_DESC(video_nr, "video device numbers");
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -030073MODULE_PARM_DESC(vbi_nr, "vbi device numbers");
Sri Deevie0d3baf2009-03-03 14:37:50 -030074MODULE_PARM_DESC(radio_nr, "radio device numbers");
75
76static unsigned int video_debug;
77module_param(video_debug, int, 0644);
78MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
79
Sri Deevie0d3baf2009-03-03 14:37:50 -030080/* supported video standards */
81static struct cx231xx_fmt format[] = {
82 {
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -030083 .fourcc = V4L2_PIX_FMT_YUYV,
84 .depth = 16,
85 .reg = 0,
86 },
Sri Deevie0d3baf2009-03-03 14:37:50 -030087};
88
Sri Deevie0d3baf2009-03-03 14:37:50 -030089
Mauro Carvalho Chehab3d263112015-02-18 12:22:27 -030090static int cx231xx_enable_analog_tuner(struct cx231xx *dev)
91{
92#ifdef CONFIG_MEDIA_CONTROLLER
93 struct media_device *mdev = dev->media_dev;
94 struct media_entity *entity, *decoder = NULL, *source;
95 struct media_link *link, *found_link = NULL;
Mauro Carvalho Chehab57208e52015-08-07 06:55:40 -030096 int ret, active_links = 0;
Mauro Carvalho Chehab3d263112015-02-18 12:22:27 -030097
98 if (!mdev)
99 return 0;
100
101 /*
102 * This will find the tuner that is connected into the decoder.
103 * Technically, this is not 100% correct, as the device may be
104 * using an analog input instead of the tuner. However, as we can't
105 * do DVB streaming while the DMA engine is being used for V4L2,
106 * this should be enough for the actual needs.
107 */
108 media_device_for_each_entity(entity, mdev) {
Mauro Carvalho Chehab4ca72ef2015-12-10 17:25:41 -0200109 if (entity->function == MEDIA_ENT_F_ATV_DECODER) {
Mauro Carvalho Chehab3d263112015-02-18 12:22:27 -0300110 decoder = entity;
111 break;
112 }
113 }
114 if (!decoder)
115 return 0;
116
Mauro Carvalho Chehab57208e52015-08-07 06:55:40 -0300117 list_for_each_entry(link, &decoder->links, list) {
Mauro Carvalho Chehab3d263112015-02-18 12:22:27 -0300118 if (link->sink->entity == decoder) {
119 found_link = link;
120 if (link->flags & MEDIA_LNK_FL_ENABLED)
121 active_links++;
122 break;
123 }
124 }
125
126 if (active_links == 1 || !found_link)
127 return 0;
128
129 source = found_link->source->entity;
Mauro Carvalho Chehab57208e52015-08-07 06:55:40 -0300130 list_for_each_entry(link, &source->links, list) {
Mauro Carvalho Chehab3d263112015-02-18 12:22:27 -0300131 struct media_entity *sink;
132 int flags = 0;
133
Mauro Carvalho Chehab3d263112015-02-18 12:22:27 -0300134 sink = link->sink->entity;
135
136 if (sink == entity)
137 flags = MEDIA_LNK_FL_ENABLED;
138
139 ret = media_entity_setup_link(link, flags);
140 if (ret) {
141 dev_err(dev->dev,
142 "Couldn't change link %s->%s to %s. Error %d\n",
143 source->name, sink->name,
144 flags ? "enabled" : "disabled",
145 ret);
146 return ret;
147 } else
148 dev_dbg(dev->dev,
149 "link %s->%s was %s\n",
150 source->name, sink->name,
151 flags ? "ENABLED" : "disabled");
152 }
153#endif
154 return 0;
155}
156
Sri Deevie0d3baf2009-03-03 14:37:50 -0300157/* ------------------------------------------------------------------
158 Video buffer and parser functions
159 ------------------------------------------------------------------*/
160
161/*
162 * Announces that a buffer were filled and request the next
163 */
164static inline void buffer_filled(struct cx231xx *dev,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300165 struct cx231xx_dmaqueue *dma_q,
166 struct cx231xx_buffer *buf)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300167{
168 /* Advice that buffer was filled */
169 cx231xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
170 buf->vb.state = VIDEOBUF_DONE;
171 buf->vb.field_count++;
Hans Verkuil15a40b22019-01-21 08:32:23 -0500172 buf->vb.ts = ktime_get_ns();
Sri Deevie0d3baf2009-03-03 14:37:50 -0300173
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300174 if (dev->USE_ISO)
175 dev->video_mode.isoc_ctl.buf = NULL;
176 else
177 dev->video_mode.bulk_ctl.buf = NULL;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300178
179 list_del(&buf->vb.queue);
180 wake_up(&buf->vb.done);
181}
182
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300183static inline void print_err_status(struct cx231xx *dev, int packet, int status)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300184{
185 char *errmsg = "Unknown";
186
187 switch (status) {
188 case -ENOENT:
Colin Ian Kingb436e262017-11-02 06:11:53 -0400189 errmsg = "unlinked synchronously";
Sri Deevie0d3baf2009-03-03 14:37:50 -0300190 break;
191 case -ECONNRESET:
Colin Ian Kingb436e262017-11-02 06:11:53 -0400192 errmsg = "unlinked asynchronously";
Sri Deevie0d3baf2009-03-03 14:37:50 -0300193 break;
194 case -ENOSR:
195 errmsg = "Buffer error (overrun)";
196 break;
197 case -EPIPE:
198 errmsg = "Stalled (device not responding)";
199 break;
200 case -EOVERFLOW:
201 errmsg = "Babble (bad cable?)";
202 break;
203 case -EPROTO:
204 errmsg = "Bit-stuff error (bad cable?)";
205 break;
206 case -EILSEQ:
207 errmsg = "CRC/Timeout (could be anything)";
208 break;
209 case -ETIME:
210 errmsg = "Device does not respond";
211 break;
212 }
213 if (packet < 0) {
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300214 cx231xx_isocdbg("URB status %d [%s].\n", status, errmsg);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300215 } else {
216 cx231xx_isocdbg("URB packet %d, status %d [%s].\n",
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300217 packet, status, errmsg);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300218 }
219}
220
221/*
222 * video-buf generic routine to get the next available buffer
223 */
224static inline void get_next_buf(struct cx231xx_dmaqueue *dma_q,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300225 struct cx231xx_buffer **buf)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300226{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300227 struct cx231xx_video_mode *vmode =
228 container_of(dma_q, struct cx231xx_video_mode, vidq);
229 struct cx231xx *dev = container_of(vmode, struct cx231xx, video_mode);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300230
231 char *outp;
232
Sri Deevie0d3baf2009-03-03 14:37:50 -0300233 if (list_empty(&dma_q->active)) {
234 cx231xx_isocdbg("No active queue to serve\n");
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300235 if (dev->USE_ISO)
236 dev->video_mode.isoc_ctl.buf = NULL;
237 else
238 dev->video_mode.bulk_ctl.buf = NULL;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300239 *buf = NULL;
240 return;
241 }
242
243 /* Get the next buffer */
244 *buf = list_entry(dma_q->active.next, struct cx231xx_buffer, vb.queue);
245
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300246 /* Cleans up buffer - Useful for testing for frame/URB loss */
Sri Deevie0d3baf2009-03-03 14:37:50 -0300247 outp = videobuf_to_vmalloc(&(*buf)->vb);
248 memset(outp, 0, (*buf)->vb.size);
249
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300250 if (dev->USE_ISO)
251 dev->video_mode.isoc_ctl.buf = *buf;
252 else
253 dev->video_mode.bulk_ctl.buf = *buf;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300254
255 return;
256}
257
258/*
259 * Controls the isoc copy of each urb packet
260 */
261static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb)
262{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300263 struct cx231xx_dmaqueue *dma_q = urb->context;
Peter Senna Tschudin4df16f72014-05-31 13:30:52 -0300264 int i;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300265 unsigned char *p_buffer;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300266 u32 bytes_parsed = 0, buffer_size = 0;
267 u8 sav_eav = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300268
269 if (!dev)
270 return 0;
271
Mauro Carvalho Chehab990862a2012-01-10 09:48:50 -0200272 if (dev->state & DEV_DISCONNECTED)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300273 return 0;
274
275 if (urb->status < 0) {
276 print_err_status(dev, -1, urb->status);
277 if (urb->status == -ENOENT)
278 return 0;
279 }
280
Sri Deevie0d3baf2009-03-03 14:37:50 -0300281 for (i = 0; i < urb->number_of_packets; i++) {
282 int status = urb->iso_frame_desc[i].status;
283
284 if (status < 0) {
285 print_err_status(dev, i, status);
286 if (urb->iso_frame_desc[i].status != -EPROTO)
287 continue;
288 }
289
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300290 if (urb->iso_frame_desc[i].actual_length <= 0) {
Sri Deevie0d3baf2009-03-03 14:37:50 -0300291 /* cx231xx_isocdbg("packet %d is empty",i); - spammy */
292 continue;
293 }
294 if (urb->iso_frame_desc[i].actual_length >
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300295 dev->video_mode.max_pkt_size) {
Sri Deevie0d3baf2009-03-03 14:37:50 -0300296 cx231xx_isocdbg("packet bigger than packet size");
297 continue;
298 }
299
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300300 /* get buffer pointer and length */
Sri Deevie0d3baf2009-03-03 14:37:50 -0300301 p_buffer = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300302 buffer_size = urb->iso_frame_desc[i].actual_length;
303 bytes_parsed = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300304
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300305 if (dma_q->is_partial_line) {
Sri Deevib9255172009-03-04 17:49:01 -0300306 /* Handle the case of a partial line */
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300307 sav_eav = dma_q->last_sav;
308 } else {
Sri Deevib9255172009-03-04 17:49:01 -0300309 /* Check for a SAV/EAV overlapping
310 the buffer boundary */
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300311 sav_eav =
312 cx231xx_find_boundary_SAV_EAV(p_buffer,
313 dma_q->partial_buf,
314 &bytes_parsed);
315 }
Sri Deevie0d3baf2009-03-03 14:37:50 -0300316
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300317 sav_eav &= 0xF0;
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300318 /* Get the first line if we have some portion of an SAV/EAV from
319 the last buffer or a partial line */
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300320 if (sav_eav) {
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300321 bytes_parsed += cx231xx_get_video_line(dev, dma_q,
Sri Deevib9255172009-03-04 17:49:01 -0300322 sav_eav, /* SAV/EAV */
323 p_buffer + bytes_parsed, /* p_buffer */
324 buffer_size - bytes_parsed);/* buf size */
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300325 }
Sri Deevie0d3baf2009-03-03 14:37:50 -0300326
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300327 /* Now parse data that is completely in this buffer */
328 /* dma_q->is_partial_line = 0; */
Sri Deevie0d3baf2009-03-03 14:37:50 -0300329
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300330 while (bytes_parsed < buffer_size) {
331 u32 bytes_used = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300332
Sri Deevib9255172009-03-04 17:49:01 -0300333 sav_eav = cx231xx_find_next_SAV_EAV(
334 p_buffer + bytes_parsed, /* p_buffer */
335 buffer_size - bytes_parsed, /* buf size */
336 &bytes_used);/* bytes used to get SAV/EAV */
Sri Deevie0d3baf2009-03-03 14:37:50 -0300337
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300338 bytes_parsed += bytes_used;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300339
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300340 sav_eav &= 0xF0;
341 if (sav_eav && (bytes_parsed < buffer_size)) {
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300342 bytes_parsed += cx231xx_get_video_line(dev,
Sri Deevib9255172009-03-04 17:49:01 -0300343 dma_q, sav_eav, /* SAV/EAV */
344 p_buffer + bytes_parsed,/* p_buffer */
345 buffer_size - bytes_parsed);/*buf size*/
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300346 }
347 }
Sri Deevie0d3baf2009-03-03 14:37:50 -0300348
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300349 /* Save the last four bytes of the buffer so we can check the
350 buffer boundary condition next time */
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300351 memcpy(dma_q->partial_buf, p_buffer + buffer_size - 4, 4);
352 bytes_parsed = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300353
354 }
Peter Senna Tschudin4df16f72014-05-31 13:30:52 -0300355 return 1;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300356}
357
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300358static inline int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb)
359{
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300360 struct cx231xx_dmaqueue *dma_q = urb->context;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300361 unsigned char *p_buffer;
362 u32 bytes_parsed = 0, buffer_size = 0;
363 u8 sav_eav = 0;
364
365 if (!dev)
366 return 0;
367
Mauro Carvalho Chehab990862a2012-01-10 09:48:50 -0200368 if (dev->state & DEV_DISCONNECTED)
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300369 return 0;
370
371 if (urb->status < 0) {
372 print_err_status(dev, -1, urb->status);
373 if (urb->status == -ENOENT)
374 return 0;
375 }
376
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300377 if (1) {
378
379 /* get buffer pointer and length */
380 p_buffer = urb->transfer_buffer;
381 buffer_size = urb->actual_length;
382 bytes_parsed = 0;
383
384 if (dma_q->is_partial_line) {
385 /* Handle the case of a partial line */
386 sav_eav = dma_q->last_sav;
387 } else {
388 /* Check for a SAV/EAV overlapping
389 the buffer boundary */
390 sav_eav =
391 cx231xx_find_boundary_SAV_EAV(p_buffer,
392 dma_q->partial_buf,
393 &bytes_parsed);
394 }
395
396 sav_eav &= 0xF0;
397 /* Get the first line if we have some portion of an SAV/EAV from
398 the last buffer or a partial line */
399 if (sav_eav) {
400 bytes_parsed += cx231xx_get_video_line(dev, dma_q,
401 sav_eav, /* SAV/EAV */
402 p_buffer + bytes_parsed, /* p_buffer */
403 buffer_size - bytes_parsed);/* buf size */
404 }
405
406 /* Now parse data that is completely in this buffer */
407 /* dma_q->is_partial_line = 0; */
408
409 while (bytes_parsed < buffer_size) {
410 u32 bytes_used = 0;
411
412 sav_eav = cx231xx_find_next_SAV_EAV(
413 p_buffer + bytes_parsed, /* p_buffer */
414 buffer_size - bytes_parsed, /* buf size */
415 &bytes_used);/* bytes used to get SAV/EAV */
416
417 bytes_parsed += bytes_used;
418
419 sav_eav &= 0xF0;
420 if (sav_eav && (bytes_parsed < buffer_size)) {
421 bytes_parsed += cx231xx_get_video_line(dev,
422 dma_q, sav_eav, /* SAV/EAV */
423 p_buffer + bytes_parsed,/* p_buffer */
424 buffer_size - bytes_parsed);/*buf size*/
425 }
426 }
427
428 /* Save the last four bytes of the buffer so we can check the
429 buffer boundary condition next time */
430 memcpy(dma_q->partial_buf, p_buffer + buffer_size - 4, 4);
431 bytes_parsed = 0;
432
433 }
Peter Senna Tschudin4df16f72014-05-31 13:30:52 -0300434 return 1;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300435}
436
437
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300438u8 cx231xx_find_boundary_SAV_EAV(u8 *p_buffer, u8 *partial_buf,
439 u32 *p_bytes_used)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300440{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300441 u32 bytes_used;
442 u8 boundary_bytes[8];
443 u8 sav_eav = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300444
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300445 *p_bytes_used = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300446
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300447 /* Create an array of the last 4 bytes of the last buffer and the first
448 4 bytes of the current buffer. */
Sri Deevie0d3baf2009-03-03 14:37:50 -0300449
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300450 memcpy(boundary_bytes, partial_buf, 4);
451 memcpy(boundary_bytes + 4, p_buffer, 4);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300452
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300453 /* Check for the SAV/EAV in the boundary buffer */
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300454 sav_eav = cx231xx_find_next_SAV_EAV((u8 *)&boundary_bytes, 8,
455 &bytes_used);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300456
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300457 if (sav_eav) {
458 /* found a boundary SAV/EAV. Updates the bytes used to reflect
459 only those used in the new buffer */
460 *p_bytes_used = bytes_used - 4;
461 }
Sri Deevie0d3baf2009-03-03 14:37:50 -0300462
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300463 return sav_eav;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300464}
465
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300466u8 cx231xx_find_next_SAV_EAV(u8 *p_buffer, u32 buffer_size, u32 *p_bytes_used)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300467{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300468 u32 i;
469 u8 sav_eav = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300470
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300471 /*
472 * Don't search if the buffer size is less than 4. It causes a page
473 * fault since buffer_size - 4 evaluates to a large number in that
474 * case.
475 */
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300476 if (buffer_size < 4) {
477 *p_bytes_used = buffer_size;
478 return 0;
479 }
Sri Deevie0d3baf2009-03-03 14:37:50 -0300480
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300481 for (i = 0; i < (buffer_size - 3); i++) {
Sri Deevie0d3baf2009-03-03 14:37:50 -0300482
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300483 if ((p_buffer[i] == 0xFF) &&
484 (p_buffer[i + 1] == 0x00) && (p_buffer[i + 2] == 0x00)) {
Sri Deevie0d3baf2009-03-03 14:37:50 -0300485
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300486 *p_bytes_used = i + 4;
487 sav_eav = p_buffer[i + 3];
488 return sav_eav;
489 }
490 }
Sri Deevie0d3baf2009-03-03 14:37:50 -0300491
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300492 *p_bytes_used = buffer_size;
493 return 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300494}
495
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300496u32 cx231xx_get_video_line(struct cx231xx *dev,
497 struct cx231xx_dmaqueue *dma_q, u8 sav_eav,
498 u8 *p_buffer, u32 buffer_size)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300499{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300500 u32 bytes_copied = 0;
501 int current_field = -1;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300502
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300503 switch (sav_eav) {
504 case SAV_ACTIVE_VIDEO_FIELD1:
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300505 /* looking for skipped line which occurred in PAL 720x480 mode.
506 In this case, there will be no active data contained
507 between the SAV and EAV */
508 if ((buffer_size > 3) && (p_buffer[0] == 0xFF) &&
509 (p_buffer[1] == 0x00) && (p_buffer[2] == 0x00) &&
510 ((p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD1) ||
511 (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD2) ||
512 (p_buffer[3] == EAV_VBLANK_FIELD1) ||
513 (p_buffer[3] == EAV_VBLANK_FIELD2)))
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300514 return bytes_copied;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300515 current_field = 1;
516 break;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300517
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300518 case SAV_ACTIVE_VIDEO_FIELD2:
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300519 /* looking for skipped line which occurred in PAL 720x480 mode.
520 In this case, there will be no active data contained between
521 the SAV and EAV */
522 if ((buffer_size > 3) && (p_buffer[0] == 0xFF) &&
523 (p_buffer[1] == 0x00) && (p_buffer[2] == 0x00) &&
524 ((p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD1) ||
525 (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD2) ||
526 (p_buffer[3] == EAV_VBLANK_FIELD1) ||
527 (p_buffer[3] == EAV_VBLANK_FIELD2)))
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300528 return bytes_copied;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300529 current_field = 2;
530 break;
531 }
Sri Deevie0d3baf2009-03-03 14:37:50 -0300532
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300533 dma_q->last_sav = sav_eav;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300534
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300535 bytes_copied = cx231xx_copy_video_line(dev, dma_q, p_buffer,
536 buffer_size, current_field);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300537
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300538 return bytes_copied;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300539}
540
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300541u32 cx231xx_copy_video_line(struct cx231xx *dev,
542 struct cx231xx_dmaqueue *dma_q, u8 *p_line,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300543 u32 length, int field_number)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300544{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300545 u32 bytes_to_copy;
546 struct cx231xx_buffer *buf;
547 u32 _line_size = dev->width * 2;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300548
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300549 if (dma_q->current_field != field_number)
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300550 cx231xx_reset_video_buffer(dev, dma_q);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300551
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300552 /* get the buffer pointer */
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300553 if (dev->USE_ISO)
554 buf = dev->video_mode.isoc_ctl.buf;
555 else
556 buf = dev->video_mode.bulk_ctl.buf;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300557
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300558 /* Remember the field number for next time */
559 dma_q->current_field = field_number;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300560
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300561 bytes_to_copy = dma_q->bytes_left_in_line;
562 if (bytes_to_copy > length)
563 bytes_to_copy = length;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300564
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300565 if (dma_q->lines_completed >= dma_q->lines_per_field) {
566 dma_q->bytes_left_in_line -= bytes_to_copy;
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300567 dma_q->is_partial_line = (dma_q->bytes_left_in_line == 0) ?
568 0 : 1;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300569 return 0;
570 }
Sri Deevie0d3baf2009-03-03 14:37:50 -0300571
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300572 dma_q->is_partial_line = 1;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300573
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300574 /* If we don't have a buffer, just return the number of bytes we would
575 have copied if we had a buffer. */
576 if (!buf) {
577 dma_q->bytes_left_in_line -= bytes_to_copy;
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300578 dma_q->is_partial_line = (dma_q->bytes_left_in_line == 0)
579 ? 0 : 1;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300580 return bytes_to_copy;
581 }
Sri Deevie0d3baf2009-03-03 14:37:50 -0300582
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300583 /* copy the data to video buffer */
584 cx231xx_do_copy(dev, dma_q, p_line, bytes_to_copy);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300585
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300586 dma_q->pos += bytes_to_copy;
587 dma_q->bytes_left_in_line -= bytes_to_copy;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300588
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300589 if (dma_q->bytes_left_in_line == 0) {
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300590 dma_q->bytes_left_in_line = _line_size;
591 dma_q->lines_completed++;
592 dma_q->is_partial_line = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300593
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300594 if (cx231xx_is_buffer_done(dev, dma_q) && buf) {
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300595 buffer_filled(dev, dma_q, buf);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300596
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300597 dma_q->pos = 0;
598 buf = NULL;
599 dma_q->lines_completed = 0;
600 }
601 }
Sri Deevie0d3baf2009-03-03 14:37:50 -0300602
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300603 return bytes_to_copy;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300604}
605
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300606void cx231xx_reset_video_buffer(struct cx231xx *dev,
607 struct cx231xx_dmaqueue *dma_q)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300608{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300609 struct cx231xx_buffer *buf;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300610
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300611 /* handle the switch from field 1 to field 2 */
612 if (dma_q->current_field == 1) {
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300613 if (dma_q->lines_completed >= dma_q->lines_per_field)
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300614 dma_q->field1_done = 1;
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300615 else
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300616 dma_q->field1_done = 0;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300617 }
Sri Deevie0d3baf2009-03-03 14:37:50 -0300618
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300619 if (dev->USE_ISO)
620 buf = dev->video_mode.isoc_ctl.buf;
621 else
622 buf = dev->video_mode.bulk_ctl.buf;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300623
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300624 if (buf == NULL) {
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300625 /* first try to get the buffer */
626 get_next_buf(dma_q, &buf);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300627
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300628 dma_q->pos = 0;
629 dma_q->field1_done = 0;
630 dma_q->current_field = -1;
631 }
Sri Deevie0d3baf2009-03-03 14:37:50 -0300632
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300633 /* reset the counters */
634 dma_q->bytes_left_in_line = dev->width << 1;
635 dma_q->lines_completed = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300636}
637
638int cx231xx_do_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300639 u8 *p_buffer, u32 bytes_to_copy)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300640{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300641 u8 *p_out_buffer = NULL;
642 u32 current_line_bytes_copied = 0;
643 struct cx231xx_buffer *buf;
644 u32 _line_size = dev->width << 1;
645 void *startwrite;
646 int offset, lencopy;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300647
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300648 if (dev->USE_ISO)
649 buf = dev->video_mode.isoc_ctl.buf;
650 else
651 buf = dev->video_mode.bulk_ctl.buf;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300652
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300653 if (buf == NULL)
654 return -1;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300655
656 p_out_buffer = videobuf_to_vmalloc(&buf->vb);
657
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300658 current_line_bytes_copied = _line_size - dma_q->bytes_left_in_line;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300659
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300660 /* Offset field 2 one line from the top of the buffer */
661 offset = (dma_q->current_field == 1) ? 0 : _line_size;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300662
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300663 /* Offset for field 2 */
664 startwrite = p_out_buffer + offset;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300665
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300666 /* lines already completed in the current field */
667 startwrite += (dma_q->lines_completed * _line_size * 2);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300668
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300669 /* bytes already completed in the current line */
670 startwrite += current_line_bytes_copied;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300671
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300672 lencopy = dma_q->bytes_left_in_line > bytes_to_copy ?
673 bytes_to_copy : dma_q->bytes_left_in_line;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300674
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300675 if ((u8 *)(startwrite + lencopy) > (u8 *)(p_out_buffer + buf->vb.size))
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300676 return 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300677
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300678 /* The below copies the UYVY data straight into video buffer */
679 cx231xx_swab((u16 *) p_buffer, (u16 *) startwrite, (u16) lencopy);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300680
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300681 return 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300682}
683
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300684void cx231xx_swab(u16 *from, u16 *to, u16 len)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300685{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300686 u16 i;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300687
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300688 if (len <= 0)
689 return;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300690
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300691 for (i = 0; i < len / 2; i++)
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300692 to[i] = (from[i] << 8) | (from[i] >> 8);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300693}
694
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300695u8 cx231xx_is_buffer_done(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300696{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300697 u8 buffer_complete = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300698
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300699 /* Dual field stream */
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300700 buffer_complete = ((dma_q->current_field == 2) &&
701 (dma_q->lines_completed >= dma_q->lines_per_field) &&
702 dma_q->field1_done);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300703
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300704 return buffer_complete;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300705}
706
Sri Deevie0d3baf2009-03-03 14:37:50 -0300707/* ------------------------------------------------------------------
708 Videobuf operations
709 ------------------------------------------------------------------*/
710
711static int
712buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
713{
714 struct cx231xx_fh *fh = vq->priv_data;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300715 struct cx231xx *dev = fh->dev;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300716
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300717 *size = (fh->dev->width * fh->dev->height * dev->format->depth + 7)>>3;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300718 if (0 == *count)
719 *count = CX231XX_DEF_BUF;
720
721 if (*count < CX231XX_MIN_BUF)
722 *count = CX231XX_MIN_BUF;
723
Mauro Carvalho Chehab3d263112015-02-18 12:22:27 -0300724
725 cx231xx_enable_analog_tuner(dev);
726
Sri Deevie0d3baf2009-03-03 14:37:50 -0300727 return 0;
728}
729
730/* This is called *without* dev->slock held; please keep it that way */
731static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf)
732{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300733 struct cx231xx_fh *fh = vq->priv_data;
734 struct cx231xx *dev = fh->dev;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300735 unsigned long flags = 0;
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300736
Mauro Carvalho Chehab09f20822015-05-19 08:00:56 -0300737 BUG_ON(in_interrupt());
Sri Deevie0d3baf2009-03-03 14:37:50 -0300738
739 /* We used to wait for the buffer to finish here, but this didn't work
740 because, as we were keeping the state as VIDEOBUF_QUEUED,
741 videobuf_queue_cancel marked it as finished for us.
742 (Also, it could wedge forever if the hardware was misconfigured.)
743
744 This should be safe; by the time we get here, the buffer isn't
745 queued anymore. If we ever start marking the buffers as
746 VIDEOBUF_ACTIVE, it won't be, though.
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300747 */
Sri Deevie0d3baf2009-03-03 14:37:50 -0300748 spin_lock_irqsave(&dev->video_mode.slock, flags);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300749 if (dev->USE_ISO) {
750 if (dev->video_mode.isoc_ctl.buf == buf)
751 dev->video_mode.isoc_ctl.buf = NULL;
752 } else {
753 if (dev->video_mode.bulk_ctl.buf == buf)
754 dev->video_mode.bulk_ctl.buf = NULL;
755 }
Sri Deevie0d3baf2009-03-03 14:37:50 -0300756 spin_unlock_irqrestore(&dev->video_mode.slock, flags);
757
758 videobuf_vmalloc_free(&buf->vb);
759 buf->vb.state = VIDEOBUF_NEEDS_INIT;
760}
761
762static int
763buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300764 enum v4l2_field field)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300765{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300766 struct cx231xx_fh *fh = vq->priv_data;
767 struct cx231xx_buffer *buf =
768 container_of(vb, struct cx231xx_buffer, vb);
769 struct cx231xx *dev = fh->dev;
770 int rc = 0, urb_init = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300771
772 /* The only currently supported format is 16 bits/pixel */
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300773 buf->vb.size = (fh->dev->width * fh->dev->height * dev->format->depth
774 + 7) >> 3;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300775 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300776 return -EINVAL;
777
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300778 buf->vb.width = dev->width;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300779 buf->vb.height = dev->height;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300780 buf->vb.field = field;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300781
782 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
783 rc = videobuf_iolock(vq, &buf->vb, NULL);
784 if (rc < 0)
785 goto fail;
786 }
787
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300788 if (dev->USE_ISO) {
789 if (!dev->video_mode.isoc_ctl.num_bufs)
790 urb_init = 1;
791 } else {
792 if (!dev->video_mode.bulk_ctl.num_bufs)
793 urb_init = 1;
794 }
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -0300795 dev_dbg(dev->dev,
Mauro Carvalho Chehabb7085c02014-11-02 07:21:44 -0300796 "urb_init=%d dev->video_mode.max_pkt_size=%d\n",
797 urb_init, dev->video_mode.max_pkt_size);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300798 if (urb_init) {
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300799 dev->mode_tv = 0;
800 if (dev->USE_ISO)
801 rc = cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300802 CX231XX_NUM_BUFS,
803 dev->video_mode.max_pkt_size,
804 cx231xx_isoc_copy);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300805 else
806 rc = cx231xx_init_bulk(dev, CX231XX_NUM_PACKETS,
807 CX231XX_NUM_BUFS,
808 dev->video_mode.max_pkt_size,
809 cx231xx_bulk_copy);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300810 if (rc < 0)
811 goto fail;
812 }
813
814 buf->vb.state = VIDEOBUF_PREPARED;
Mauro Carvalho Chehab0f0fa902015-01-06 15:26:06 -0300815
Sri Deevie0d3baf2009-03-03 14:37:50 -0300816 return 0;
817
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300818fail:
Sri Deevie0d3baf2009-03-03 14:37:50 -0300819 free_buffer(vq, buf);
820 return rc;
821}
822
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300823static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300824{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300825 struct cx231xx_buffer *buf =
826 container_of(vb, struct cx231xx_buffer, vb);
827 struct cx231xx_fh *fh = vq->priv_data;
828 struct cx231xx *dev = fh->dev;
829 struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300830
831 buf->vb.state = VIDEOBUF_QUEUED;
832 list_add_tail(&buf->vb.queue, &vidq->active);
833
834}
835
836static void buffer_release(struct videobuf_queue *vq,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300837 struct videobuf_buffer *vb)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300838{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300839 struct cx231xx_buffer *buf =
840 container_of(vb, struct cx231xx_buffer, vb);
841 struct cx231xx_fh *fh = vq->priv_data;
842 struct cx231xx *dev = (struct cx231xx *)fh->dev;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300843
844 cx231xx_isocdbg("cx231xx: called buffer_release\n");
845
846 free_buffer(vq, buf);
847}
848
Julia Lawall177267a2017-08-04 08:09:46 -0400849static const struct videobuf_queue_ops cx231xx_video_qops = {
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300850 .buf_setup = buffer_setup,
851 .buf_prepare = buffer_prepare,
852 .buf_queue = buffer_queue,
853 .buf_release = buffer_release,
Sri Deevie0d3baf2009-03-03 14:37:50 -0300854};
855
856/********************* v4l2 interface **************************************/
857
Sri Deevie0d3baf2009-03-03 14:37:50 -0300858void video_mux(struct cx231xx *dev, int index)
859{
Sri Deevie0d3baf2009-03-03 14:37:50 -0300860 dev->video_input = index;
861 dev->ctl_ainput = INPUT(index)->amux;
862
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300863 cx231xx_set_video_input_mux(dev, index);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300864
Hans Verkuil5325b422009-04-02 11:26:22 -0300865 cx25840_call(dev, video, s_routing, INPUT(index)->vmux, 0, 0);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300866
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300867 cx231xx_set_audio_input(dev, dev->ctl_ainput);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300868
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -0300869 dev_dbg(dev->dev, "video_mux : %d\n", index);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300870
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300871 /* do mode control overrides if required */
872 cx231xx_do_mode_ctrl_overrides(dev);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300873}
874
875/* Usage lock check functions */
876static int res_get(struct cx231xx_fh *fh)
877{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300878 struct cx231xx *dev = fh->dev;
879 int rc = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300880
881 /* This instance already has stream_on */
882 if (fh->stream_on)
883 return rc;
884
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300885 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
886 if (dev->stream_on)
887 return -EBUSY;
888 dev->stream_on = 1;
889 } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
890 if (dev->vbi_stream_on)
891 return -EBUSY;
892 dev->vbi_stream_on = 1;
893 } else
894 return -EINVAL;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300895
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300896 fh->stream_on = 1;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300897
898 return rc;
899}
900
901static int res_check(struct cx231xx_fh *fh)
902{
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300903 return fh->stream_on;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300904}
905
906static void res_free(struct cx231xx_fh *fh)
907{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300908 struct cx231xx *dev = fh->dev;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300909
910 fh->stream_on = 0;
911
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300912 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
913 dev->stream_on = 0;
914 if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
915 dev->vbi_stream_on = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300916}
917
918static int check_dev(struct cx231xx *dev)
919{
920 if (dev->state & DEV_DISCONNECTED) {
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -0300921 dev_err(dev->dev, "v4l2 ioctl: device not present\n");
Sri Deevie0d3baf2009-03-03 14:37:50 -0300922 return -ENODEV;
923 }
Sri Deevie0d3baf2009-03-03 14:37:50 -0300924 return 0;
925}
926
Sri Deevie0d3baf2009-03-03 14:37:50 -0300927/* ------------------------------------------------------------------
928 IOCTL vidioc handling
929 ------------------------------------------------------------------*/
930
931static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300932 struct v4l2_format *f)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300933{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300934 struct cx231xx_fh *fh = priv;
935 struct cx231xx *dev = fh->dev;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300936
Sri Deevie0d3baf2009-03-03 14:37:50 -0300937 f->fmt.pix.width = dev->width;
938 f->fmt.pix.height = dev->height;
Joe Perches1ebcad72009-07-02 15:57:09 -0300939 f->fmt.pix.pixelformat = dev->format->fourcc;
940 f->fmt.pix.bytesperline = (dev->width * dev->format->depth + 7) >> 3;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300941 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * dev->height;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300942 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
943
944 f->fmt.pix.field = V4L2_FIELD_INTERLACED;
945
Sri Deevie0d3baf2009-03-03 14:37:50 -0300946 return 0;
947}
948
949static struct cx231xx_fmt *format_by_fourcc(unsigned int fourcc)
950{
951 unsigned int i;
952
953 for (i = 0; i < ARRAY_SIZE(format); i++)
954 if (format[i].fourcc == fourcc)
955 return &format[i];
956
957 return NULL;
958}
959
960static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300961 struct v4l2_format *f)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300962{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300963 struct cx231xx_fh *fh = priv;
964 struct cx231xx *dev = fh->dev;
Trent Piepho9bd0e8d2009-05-30 21:45:46 -0300965 unsigned int width = f->fmt.pix.width;
966 unsigned int height = f->fmt.pix.height;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300967 unsigned int maxw = norm_maxw(dev);
968 unsigned int maxh = norm_maxh(dev);
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300969 struct cx231xx_fmt *fmt;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300970
971 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
972 if (!fmt) {
973 cx231xx_videodbg("Fourcc format (%08x) invalid.\n",
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300974 f->fmt.pix.pixelformat);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300975 return -EINVAL;
976 }
977
978 /* width must even because of the YUYV format
979 height must be even because of interlacing */
Trent Piepho9bd0e8d2009-05-30 21:45:46 -0300980 v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh, 1, 0);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300981
Sri Deevie0d3baf2009-03-03 14:37:50 -0300982 f->fmt.pix.width = width;
983 f->fmt.pix.height = height;
984 f->fmt.pix.pixelformat = fmt->fourcc;
Hans Verkuil8b735c12013-02-09 06:35:02 -0300985 f->fmt.pix.bytesperline = (width * fmt->depth + 7) >> 3;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300986 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height;
987 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
988 f->fmt.pix.field = V4L2_FIELD_INTERLACED;
989
990 return 0;
991}
992
993static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300994 struct v4l2_format *f)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300995{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300996 struct cx231xx_fh *fh = priv;
997 struct cx231xx *dev = fh->dev;
998 int rc;
999 struct cx231xx_fmt *fmt;
Hans Verkuilebf984b2015-04-09 04:05:59 -03001000 struct v4l2_subdev_format format = {
1001 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
1002 };
Sri Deevie0d3baf2009-03-03 14:37:50 -03001003
1004 rc = check_dev(dev);
1005 if (rc < 0)
1006 return rc;
1007
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001008 vidioc_try_fmt_vid_cap(file, priv, f);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001009
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001010 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
Mauro Carvalho Chehab643800d2010-10-09 13:13:35 -03001011 if (!fmt)
1012 return -EINVAL;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001013
1014 if (videobuf_queue_is_busy(&fh->vb_vidq)) {
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -03001015 dev_err(dev->dev, "%s: queue busy\n", __func__);
Mauro Carvalho Chehab643800d2010-10-09 13:13:35 -03001016 return -EBUSY;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001017 }
1018
1019 if (dev->stream_on && !fh->stream_on) {
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -03001020 dev_err(dev->dev,
Mauro Carvalho Chehabb7085c02014-11-02 07:21:44 -03001021 "%s: device in use by another fh\n", __func__);
Mauro Carvalho Chehab643800d2010-10-09 13:13:35 -03001022 return -EBUSY;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001023 }
1024
1025 /* set new image size */
1026 dev->width = f->fmt.pix.width;
1027 dev->height = f->fmt.pix.height;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001028 dev->format = fmt;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001029
Hans Verkuilebf984b2015-04-09 04:05:59 -03001030 v4l2_fill_mbus_format(&format.format, &f->fmt.pix, MEDIA_BUS_FMT_FIXED);
1031 call_all(dev, pad, set_fmt, NULL, &format);
1032 v4l2_fill_pix_format(&f->fmt.pix, &format.format);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001033
Sri Deevie0d3baf2009-03-03 14:37:50 -03001034 return rc;
1035}
1036
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001037static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001038{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001039 struct cx231xx_fh *fh = priv;
1040 struct cx231xx *dev = fh->dev;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001041
1042 *id = dev->norm;
1043 return 0;
1044}
1045
Hans Verkuil314527acb2013-03-15 06:10:40 -03001046static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001047{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001048 struct cx231xx_fh *fh = priv;
1049 struct cx231xx *dev = fh->dev;
Hans Verkuilebf984b2015-04-09 04:05:59 -03001050 struct v4l2_subdev_format format = {
1051 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
1052 };
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001053 int rc;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001054
1055 rc = check_dev(dev);
1056 if (rc < 0)
1057 return rc;
1058
Hans Verkuil314527acb2013-03-15 06:10:40 -03001059 if (dev->norm == norm)
Hans Verkuild61072a2013-01-29 10:50:54 -03001060 return 0;
1061
1062 if (videobuf_queue_is_busy(&fh->vb_vidq))
1063 return -EBUSY;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001064
Hans Verkuil314527acb2013-03-15 06:10:40 -03001065 dev->norm = norm;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001066
Sri Deevie0d3baf2009-03-03 14:37:50 -03001067 /* Adjusts width/height, if needed */
Hans Verkuild61072a2013-01-29 10:50:54 -03001068 dev->width = 720;
1069 dev->height = (dev->norm & V4L2_STD_625_50) ? 576 : 480;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001070
Laurent Pinchart8774bed2014-04-28 16:53:01 -03001071 call_all(dev, video, s_std, dev->norm);
Devin Heitmueller435b4f72010-07-09 13:29:31 -03001072
1073 /* We need to reset basic properties in the decoder related to
1074 resolution (since a standard change effects things like the number
1075 of lines in VACT, etc) */
Hans Verkuilebf984b2015-04-09 04:05:59 -03001076 format.format.code = MEDIA_BUS_FMT_FIXED;
1077 format.format.width = dev->width;
1078 format.format.height = dev->height;
1079 call_all(dev, pad, set_fmt, NULL, &format);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001080
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001081 /* do mode control overrides */
1082 cx231xx_do_mode_ctrl_overrides(dev);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001083
1084 return 0;
1085}
1086
1087static const char *iname[] = {
1088 [CX231XX_VMUX_COMPOSITE1] = "Composite1",
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03001089 [CX231XX_VMUX_SVIDEO] = "S-Video",
Sri Deevie0d3baf2009-03-03 14:37:50 -03001090 [CX231XX_VMUX_TELEVISION] = "Television",
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03001091 [CX231XX_VMUX_CABLE] = "Cable TV",
1092 [CX231XX_VMUX_DVB] = "DVB",
Sri Deevie0d3baf2009-03-03 14:37:50 -03001093};
1094
Mauro Carvalho Chehab61683092016-02-11 22:39:52 -02001095void cx231xx_v4l2_create_entities(struct cx231xx *dev)
1096{
1097#if defined(CONFIG_MEDIA_CONTROLLER)
1098 int ret, i;
1099
1100 /* Create entities for each input connector */
1101 for (i = 0; i < MAX_CX231XX_INPUT; i++) {
1102 struct media_entity *ent = &dev->input_ent[i];
1103
1104 if (!INPUT(i)->type)
1105 break;
1106
1107 ent->name = iname[INPUT(i)->type];
1108 ent->flags = MEDIA_ENT_FL_CONNECTOR;
1109 dev->input_pad[i].flags = MEDIA_PAD_FL_SOURCE;
1110
1111 switch (INPUT(i)->type) {
1112 case CX231XX_VMUX_COMPOSITE1:
1113 ent->function = MEDIA_ENT_F_CONN_COMPOSITE;
1114 break;
1115 case CX231XX_VMUX_SVIDEO:
1116 ent->function = MEDIA_ENT_F_CONN_SVIDEO;
1117 break;
1118 case CX231XX_VMUX_TELEVISION:
1119 case CX231XX_VMUX_CABLE:
1120 case CX231XX_VMUX_DVB:
1121 /* The DVB core will handle it */
1122 if (dev->tuner_type == TUNER_ABSENT)
1123 continue;
Mauro Carvalho Chehab06eeefe2017-05-18 08:13:28 -03001124 /* fall through */
Mauro Carvalho Chehab22d50e92016-02-12 09:17:14 -02001125 default: /* just to shut up a gcc warning */
Mauro Carvalho Chehab61683092016-02-11 22:39:52 -02001126 ent->function = MEDIA_ENT_F_CONN_RF;
1127 break;
1128 }
1129
1130 ret = media_entity_pads_init(ent, 1, &dev->input_pad[i]);
1131 if (ret < 0)
1132 pr_err("failed to initialize input pad[%d]!\n", i);
1133
1134 ret = media_device_register_entity(dev->media_dev, ent);
1135 if (ret < 0)
1136 pr_err("failed to register input entity %d!\n", i);
1137 }
1138#endif
1139}
1140
Hans Verkuilb86d1542013-01-29 13:16:06 -03001141int cx231xx_enum_input(struct file *file, void *priv,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001142 struct v4l2_input *i)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001143{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001144 struct cx231xx_fh *fh = priv;
1145 struct cx231xx *dev = fh->dev;
Devin Heitmuellerde99d532011-07-24 17:07:07 -03001146 u32 gen_stat;
Andrzej Hajdae54560d2015-09-24 11:00:18 -03001147 unsigned int n;
1148 int ret;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001149
1150 n = i->index;
1151 if (n >= MAX_CX231XX_INPUT)
1152 return -EINVAL;
1153 if (0 == INPUT(n)->type)
1154 return -EINVAL;
1155
1156 i->index = n;
1157 i->type = V4L2_INPUT_TYPE_CAMERA;
1158
Mauro Carvalho Chehabcc1e6312018-09-10 16:20:42 -04001159 strscpy(i->name, iname[INPUT(n)->type], sizeof(i->name));
Sri Deevie0d3baf2009-03-03 14:37:50 -03001160
1161 if ((CX231XX_VMUX_TELEVISION == INPUT(n)->type) ||
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001162 (CX231XX_VMUX_CABLE == INPUT(n)->type))
Sri Deevie0d3baf2009-03-03 14:37:50 -03001163 i->type = V4L2_INPUT_TYPE_TUNER;
1164
Hans Verkuil60acf182015-03-09 13:34:13 -03001165 i->std = dev->vdev.tvnorms;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001166
Devin Heitmuellerde99d532011-07-24 17:07:07 -03001167 /* If they are asking about the active input, read signal status */
1168 if (n == dev->video_input) {
1169 ret = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS,
1170 GEN_STAT, 2, &gen_stat, 4);
1171 if (ret > 0) {
1172 if ((gen_stat & FLD_VPRES) == 0x00)
1173 i->status |= V4L2_IN_ST_NO_SIGNAL;
1174 if ((gen_stat & FLD_HLOCK) == 0x00)
1175 i->status |= V4L2_IN_ST_NO_H_LOCK;
1176 }
1177 }
1178
Sri Deevie0d3baf2009-03-03 14:37:50 -03001179 return 0;
1180}
1181
Hans Verkuilb86d1542013-01-29 13:16:06 -03001182int cx231xx_g_input(struct file *file, void *priv, unsigned int *i)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001183{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001184 struct cx231xx_fh *fh = priv;
1185 struct cx231xx *dev = fh->dev;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001186
1187 *i = dev->video_input;
1188
1189 return 0;
1190}
1191
Hans Verkuilb86d1542013-01-29 13:16:06 -03001192int cx231xx_s_input(struct file *file, void *priv, unsigned int i)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001193{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001194 struct cx231xx_fh *fh = priv;
1195 struct cx231xx *dev = fh->dev;
1196 int rc;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001197
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001198 dev->mode_tv = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001199 rc = check_dev(dev);
1200 if (rc < 0)
1201 return rc;
1202
1203 if (i >= MAX_CX231XX_INPUT)
1204 return -EINVAL;
1205 if (0 == INPUT(i)->type)
1206 return -EINVAL;
1207
Sri Deevie0d3baf2009-03-03 14:37:50 -03001208 video_mux(dev, i);
1209
Devin Heitmuellerc09d6692010-07-12 16:50:30 -03001210 if (INPUT(i)->type == CX231XX_VMUX_TELEVISION ||
1211 INPUT(i)->type == CX231XX_VMUX_CABLE) {
1212 /* There's a tuner, so reset the standard and put it on the
1213 last known frequency (since it was probably powered down
1214 until now */
Laurent Pinchart8774bed2014-04-28 16:53:01 -03001215 call_all(dev, video, s_std, dev->norm);
Devin Heitmuellerc09d6692010-07-12 16:50:30 -03001216 }
1217
Sri Deevie0d3baf2009-03-03 14:37:50 -03001218 return 0;
1219}
1220
Hans Verkuilb86d1542013-01-29 13:16:06 -03001221int cx231xx_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001222{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001223 struct cx231xx_fh *fh = priv;
1224 struct cx231xx *dev = fh->dev;
1225 int rc;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001226
1227 rc = check_dev(dev);
1228 if (rc < 0)
1229 return rc;
1230
1231 if (0 != t->index)
1232 return -EINVAL;
1233
Mauro Carvalho Chehabcc1e6312018-09-10 16:20:42 -04001234 strscpy(t->name, "Tuner", sizeof(t->name));
Sri Deevie0d3baf2009-03-03 14:37:50 -03001235
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001236 t->type = V4L2_TUNER_ANALOG_TV;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001237 t->capability = V4L2_TUNER_CAP_NORM;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001238 t->rangehigh = 0xffffffffUL;
1239 t->signal = 0xffff; /* LOCKED */
Hans Verkuilb251f952012-09-13 12:54:36 -03001240 call_all(dev, tuner, g_tuner, t);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001241
1242 return 0;
1243}
1244
Hans Verkuil2f73c7c2013-03-15 06:10:06 -03001245int cx231xx_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *t)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001246{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001247 struct cx231xx_fh *fh = priv;
1248 struct cx231xx *dev = fh->dev;
1249 int rc;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001250
1251 rc = check_dev(dev);
1252 if (rc < 0)
1253 return rc;
1254
1255 if (0 != t->index)
1256 return -EINVAL;
1257#if 0
Sri Deevib1196122009-03-20 23:33:48 -03001258 call_all(dev, tuner, s_tuner, t);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001259#endif
1260 return 0;
1261}
1262
Hans Verkuilb86d1542013-01-29 13:16:06 -03001263int cx231xx_g_frequency(struct file *file, void *priv,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001264 struct v4l2_frequency *f)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001265{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001266 struct cx231xx_fh *fh = priv;
1267 struct cx231xx *dev = fh->dev;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001268
Hans Verkuilb251f952012-09-13 12:54:36 -03001269 if (f->tuner)
1270 return -EINVAL;
1271
Sri Deevie0d3baf2009-03-03 14:37:50 -03001272 f->frequency = dev->ctl_freq;
1273
Sri Deevie0d3baf2009-03-03 14:37:50 -03001274 return 0;
1275}
1276
Hans Verkuilb86d1542013-01-29 13:16:06 -03001277int cx231xx_s_frequency(struct file *file, void *priv,
Hans Verkuilb530a442013-03-19 04:09:26 -03001278 const struct v4l2_frequency *f)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001279{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001280 struct cx231xx_fh *fh = priv;
1281 struct cx231xx *dev = fh->dev;
Hans Verkuilb530a442013-03-19 04:09:26 -03001282 struct v4l2_frequency new_freq = *f;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001283 int rc;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001284 u32 if_frequency = 5400000;
1285
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -03001286 dev_dbg(dev->dev,
Mauro Carvalho Chehabb7085c02014-11-02 07:21:44 -03001287 "Enter vidioc_s_frequency()f->frequency=%d;f->type=%d\n",
1288 f->frequency, f->type);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001289
1290 rc = check_dev(dev);
1291 if (rc < 0)
1292 return rc;
1293
1294 if (0 != f->tuner)
1295 return -EINVAL;
1296
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001297 /* set pre channel change settings in DIF first */
1298 rc = cx231xx_tuner_pre_channel_change(dev);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001299
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001300 call_all(dev, tuner, s_frequency, f);
Hans Verkuilb530a442013-03-19 04:09:26 -03001301 call_all(dev, tuner, g_frequency, &new_freq);
1302 dev->ctl_freq = new_freq.frequency;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001303
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001304 /* set post channel change settings in DIF first */
1305 rc = cx231xx_tuner_post_channel_change(dev);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001306
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001307 if (dev->tuner_type == TUNER_NXP_TDA18271) {
1308 if (dev->norm & (V4L2_STD_MN | V4L2_STD_NTSC_443))
1309 if_frequency = 5400000; /*5.4MHz */
1310 else if (dev->norm & V4L2_STD_B)
1311 if_frequency = 6000000; /*6.0MHz */
1312 else if (dev->norm & (V4L2_STD_PAL_DK | V4L2_STD_SECAM_DK))
1313 if_frequency = 6900000; /*6.9MHz */
1314 else if (dev->norm & V4L2_STD_GH)
1315 if_frequency = 7100000; /*7.1MHz */
1316 else if (dev->norm & V4L2_STD_PAL_I)
1317 if_frequency = 7250000; /*7.25MHz */
1318 else if (dev->norm & V4L2_STD_SECAM_L)
1319 if_frequency = 6900000; /*6.9MHz */
1320 else if (dev->norm & V4L2_STD_SECAM_LC)
1321 if_frequency = 1250000; /*1.25MHz */
1322
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -03001323 dev_dbg(dev->dev,
Mauro Carvalho Chehabb7085c02014-11-02 07:21:44 -03001324 "if_frequency is set to %d\n", if_frequency);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001325 cx231xx_set_Colibri_For_LowIF(dev, if_frequency, 1, 1);
1326
1327 update_HH_register_after_set_DIF(dev);
1328 }
1329
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -03001330 dev_dbg(dev->dev, "Set New FREQUENCY to %d\n", f->frequency);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001331
1332 return rc;
1333}
1334
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001335#ifdef CONFIG_VIDEO_ADV_DEBUG
1336
1337int cx231xx_g_chip_info(struct file *file, void *fh,
1338 struct v4l2_dbg_chip_info *chip)
Hans Verkuilfddd14c2012-09-13 05:37:11 -03001339{
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001340 switch (chip->match.addr) {
1341 case 0: /* Cx231xx - internal registers */
1342 return 0;
1343 case 1: /* AFE - read byte */
Mauro Carvalho Chehabc0decac2018-09-10 08:19:14 -04001344 strscpy(chip->name, "AFE (byte)", sizeof(chip->name));
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001345 return 0;
1346 case 2: /* Video Block - read byte */
Mauro Carvalho Chehabc0decac2018-09-10 08:19:14 -04001347 strscpy(chip->name, "Video (byte)", sizeof(chip->name));
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001348 return 0;
1349 case 3: /* I2S block - read byte */
Mauro Carvalho Chehabc0decac2018-09-10 08:19:14 -04001350 strscpy(chip->name, "I2S (byte)", sizeof(chip->name));
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001351 return 0;
1352 case 4: /* AFE - read dword */
Mauro Carvalho Chehabc0decac2018-09-10 08:19:14 -04001353 strscpy(chip->name, "AFE (dword)", sizeof(chip->name));
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001354 return 0;
1355 case 5: /* Video Block - read dword */
Mauro Carvalho Chehabc0decac2018-09-10 08:19:14 -04001356 strscpy(chip->name, "Video (dword)", sizeof(chip->name));
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001357 return 0;
1358 case 6: /* I2S Block - read dword */
Mauro Carvalho Chehabc0decac2018-09-10 08:19:14 -04001359 strscpy(chip->name, "I2S (dword)", sizeof(chip->name));
Hans Verkuilfddd14c2012-09-13 05:37:11 -03001360 return 0;
1361 }
1362 return -EINVAL;
1363}
1364
Hans Verkuilb86d1542013-01-29 13:16:06 -03001365int cx231xx_g_register(struct file *file, void *priv,
Sri Deevie0d3baf2009-03-03 14:37:50 -03001366 struct v4l2_dbg_register *reg)
1367{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001368 struct cx231xx_fh *fh = priv;
1369 struct cx231xx *dev = fh->dev;
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001370 int ret;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001371 u8 value[4] = { 0, 0, 0, 0 };
1372 u32 data = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001373
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001374 switch (reg->match.addr) {
1375 case 0: /* Cx231xx - internal registers */
1376 ret = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER,
1377 (u16)reg->reg, value, 4);
1378 reg->val = value[0] | value[1] << 8 |
Colin Ian King32ae5922018-10-06 14:01:42 -04001379 value[2] << 16 | (u32)value[3] << 24;
Hans Verkuil04ae4cf2013-05-29 07:00:04 -03001380 reg->size = 4;
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001381 break;
1382 case 1: /* AFE - read byte */
1383 ret = cx231xx_read_i2c_data(dev, AFE_DEVICE_ADDRESS,
1384 (u16)reg->reg, 2, &data, 1);
1385 reg->val = data;
Hans Verkuil04ae4cf2013-05-29 07:00:04 -03001386 reg->size = 1;
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001387 break;
1388 case 2: /* Video Block - read byte */
1389 ret = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS,
1390 (u16)reg->reg, 2, &data, 1);
1391 reg->val = data;
Hans Verkuil04ae4cf2013-05-29 07:00:04 -03001392 reg->size = 1;
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001393 break;
1394 case 3: /* I2S block - read byte */
1395 ret = cx231xx_read_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
1396 (u16)reg->reg, 1, &data, 1);
1397 reg->val = data;
Hans Verkuil04ae4cf2013-05-29 07:00:04 -03001398 reg->size = 1;
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001399 break;
1400 case 4: /* AFE - read dword */
1401 ret = cx231xx_read_i2c_data(dev, AFE_DEVICE_ADDRESS,
1402 (u16)reg->reg, 2, &data, 4);
1403 reg->val = data;
Hans Verkuil04ae4cf2013-05-29 07:00:04 -03001404 reg->size = 4;
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001405 break;
1406 case 5: /* Video Block - read dword */
1407 ret = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS,
1408 (u16)reg->reg, 2, &data, 4);
1409 reg->val = data;
Hans Verkuil04ae4cf2013-05-29 07:00:04 -03001410 reg->size = 4;
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001411 break;
1412 case 6: /* I2S Block - read dword */
1413 ret = cx231xx_read_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
1414 (u16)reg->reg, 1, &data, 4);
1415 reg->val = data;
Hans Verkuil04ae4cf2013-05-29 07:00:04 -03001416 reg->size = 4;
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001417 break;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001418 default:
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001419 return -EINVAL;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001420 }
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001421 return ret < 0 ? ret : 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001422}
1423
Hans Verkuilb86d1542013-01-29 13:16:06 -03001424int cx231xx_s_register(struct file *file, void *priv,
Hans Verkuil977ba3b12013-03-24 08:28:46 -03001425 const struct v4l2_dbg_register *reg)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001426{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001427 struct cx231xx_fh *fh = priv;
1428 struct cx231xx *dev = fh->dev;
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001429 int ret;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001430 u8 data[4] = { 0, 0, 0, 0 };
Sri Deevie0d3baf2009-03-03 14:37:50 -03001431
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001432 switch (reg->match.addr) {
1433 case 0: /* cx231xx internal registers */
1434 data[0] = (u8) reg->val;
1435 data[1] = (u8) (reg->val >> 8);
1436 data[2] = (u8) (reg->val >> 16);
1437 data[3] = (u8) (reg->val >> 24);
1438 ret = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
1439 (u16)reg->reg, data, 4);
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001440 break;
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001441 case 1: /* AFE - write byte */
1442 ret = cx231xx_write_i2c_data(dev, AFE_DEVICE_ADDRESS,
1443 (u16)reg->reg, 2, reg->val, 1);
1444 break;
1445 case 2: /* Video Block - write byte */
1446 ret = cx231xx_write_i2c_data(dev, VID_BLK_I2C_ADDRESS,
1447 (u16)reg->reg, 2, reg->val, 1);
1448 break;
1449 case 3: /* I2S block - write byte */
1450 ret = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
1451 (u16)reg->reg, 1, reg->val, 1);
1452 break;
1453 case 4: /* AFE - write dword */
1454 ret = cx231xx_write_i2c_data(dev, AFE_DEVICE_ADDRESS,
1455 (u16)reg->reg, 2, reg->val, 4);
1456 break;
1457 case 5: /* Video Block - write dword */
1458 ret = cx231xx_write_i2c_data(dev, VID_BLK_I2C_ADDRESS,
1459 (u16)reg->reg, 2, reg->val, 4);
1460 break;
1461 case 6: /* I2S block - write dword */
1462 ret = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
1463 (u16)reg->reg, 1, reg->val, 4);
1464 break;
1465 default:
1466 return -EINVAL;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001467 }
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001468 return ret < 0 ? ret : 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001469}
1470#endif
1471
Hans Verkuil5200ab62018-10-04 17:38:15 -04001472static int vidioc_g_pixelaspect(struct file *file, void *priv,
1473 int type, struct v4l2_fract *f)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001474{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001475 struct cx231xx_fh *fh = priv;
1476 struct cx231xx *dev = fh->dev;
Hans Verkuile25cb202015-11-30 10:03:30 -02001477 bool is_50hz = dev->norm & V4L2_STD_625_50;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001478
Hans Verkuil5200ab62018-10-04 17:38:15 -04001479 if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001480 return -EINVAL;
1481
Hans Verkuil5200ab62018-10-04 17:38:15 -04001482 f->numerator = is_50hz ? 54 : 11;
1483 f->denominator = is_50hz ? 59 : 10;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001484
1485 return 0;
1486}
1487
Hans Verkuilee10dc32018-10-04 17:06:32 -04001488static int vidioc_g_selection(struct file *file, void *priv,
1489 struct v4l2_selection *s)
1490{
1491 struct cx231xx_fh *fh = priv;
1492 struct cx231xx *dev = fh->dev;
1493
1494 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1495 return -EINVAL;
1496
1497 switch (s->target) {
1498 case V4L2_SEL_TGT_CROP_BOUNDS:
1499 case V4L2_SEL_TGT_CROP_DEFAULT:
1500 s->r.left = 0;
1501 s->r.top = 0;
1502 s->r.width = dev->width;
1503 s->r.height = dev->height;
1504 break;
1505 default:
1506 return -EINVAL;
1507 }
1508 return 0;
1509}
1510
Sri Deevie0d3baf2009-03-03 14:37:50 -03001511static int vidioc_streamon(struct file *file, void *priv,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001512 enum v4l2_buf_type type)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001513{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001514 struct cx231xx_fh *fh = priv;
1515 struct cx231xx *dev = fh->dev;
1516 int rc;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001517
1518 rc = check_dev(dev);
1519 if (rc < 0)
1520 return rc;
1521
Sri Deevie0d3baf2009-03-03 14:37:50 -03001522 rc = res_get(fh);
1523
1524 if (likely(rc >= 0))
1525 rc = videobuf_streamon(&fh->vb_vidq);
1526
Sri Deevib1196122009-03-20 23:33:48 -03001527 call_all(dev, video, s_stream, 1);
1528
Sri Deevie0d3baf2009-03-03 14:37:50 -03001529 return rc;
1530}
1531
1532static int vidioc_streamoff(struct file *file, void *priv,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001533 enum v4l2_buf_type type)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001534{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001535 struct cx231xx_fh *fh = priv;
1536 struct cx231xx *dev = fh->dev;
1537 int rc;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001538
1539 rc = check_dev(dev);
1540 if (rc < 0)
1541 return rc;
1542
Sri Deevie0d3baf2009-03-03 14:37:50 -03001543 if (type != fh->type)
1544 return -EINVAL;
1545
Sri Deevib1196122009-03-20 23:33:48 -03001546 cx25840_call(dev, video, s_stream, 0);
1547
Sri Deevie0d3baf2009-03-03 14:37:50 -03001548 videobuf_streamoff(&fh->vb_vidq);
1549 res_free(fh);
1550
Sri Deevie0d3baf2009-03-03 14:37:50 -03001551 return 0;
1552}
1553
Hans Verkuilbc087342013-01-29 12:52:33 -03001554int cx231xx_querycap(struct file *file, void *priv,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001555 struct v4l2_capability *cap)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001556{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001557 struct cx231xx_fh *fh = priv;
1558 struct cx231xx *dev = fh->dev;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001559
Mauro Carvalho Chehabc0decac2018-09-10 08:19:14 -04001560 strscpy(cap->driver, "cx231xx", sizeof(cap->driver));
1561 strscpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card));
Mauro Carvalho Chehab2c6beca2009-03-22 08:53:36 -03001562 usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
Hans Verkuil8c3854d2019-06-04 07:19:53 -04001563 cap->capabilities = V4L2_CAP_READWRITE |
Hans Verkuil4bc837d2012-09-13 05:29:12 -03001564 V4L2_CAP_VBI_CAPTURE | V4L2_CAP_VIDEO_CAPTURE |
Hans Verkuil530e01e2013-01-29 12:32:20 -03001565 V4L2_CAP_STREAMING | V4L2_CAP_DEVICE_CAPS;
Hans Verkuil60acf182015-03-09 13:34:13 -03001566 if (video_is_registered(&dev->radio_dev))
Hans Verkuil530e01e2013-01-29 12:32:20 -03001567 cap->capabilities |= V4L2_CAP_RADIO;
Hans Verkuil8c3854d2019-06-04 07:19:53 -04001568 if (dev->tuner_type != TUNER_ABSENT)
1569 cap->capabilities |= V4L2_CAP_TUNER;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001570
1571 return 0;
1572}
1573
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001574static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
1575 struct v4l2_fmtdesc *f)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001576{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001577 if (unlikely(f->index >= ARRAY_SIZE(format)))
Sri Deevie0d3baf2009-03-03 14:37:50 -03001578 return -EINVAL;
1579
Sri Deevie0d3baf2009-03-03 14:37:50 -03001580 f->pixelformat = format[f->index].fourcc;
1581
1582 return 0;
1583}
1584
Sri Deevie0d3baf2009-03-03 14:37:50 -03001585/* RAW VBI ioctls */
1586
1587static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001588 struct v4l2_format *f)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001589{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001590 struct cx231xx_fh *fh = priv;
1591 struct cx231xx *dev = fh->dev;
Hans Verkuil62647222013-02-09 06:41:11 -03001592
Devin Heitmuelleradc03562010-07-08 13:12:47 -03001593 f->fmt.vbi.sampling_rate = 6750000 * 4;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001594 f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
1595 f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
Devin Heitmuelleradc03562010-07-08 13:12:47 -03001596 f->fmt.vbi.offset = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001597 f->fmt.vbi.start[0] = (dev->norm & V4L2_STD_625_50) ?
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001598 PAL_VBI_START_LINE : NTSC_VBI_START_LINE;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001599 f->fmt.vbi.count[0] = (dev->norm & V4L2_STD_625_50) ?
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001600 PAL_VBI_LINES : NTSC_VBI_LINES;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001601 f->fmt.vbi.start[1] = (dev->norm & V4L2_STD_625_50) ?
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001602 PAL_VBI_START_LINE + 312 : NTSC_VBI_START_LINE + 263;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001603 f->fmt.vbi.count[1] = f->fmt.vbi.count[0];
Hans Verkuil62647222013-02-09 06:41:11 -03001604 memset(f->fmt.vbi.reserved, 0, sizeof(f->fmt.vbi.reserved));
Sri Deevie0d3baf2009-03-03 14:37:50 -03001605
1606 return 0;
1607
1608}
1609
1610static int vidioc_try_fmt_vbi_cap(struct file *file, void *priv,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001611 struct v4l2_format *f)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001612{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001613 struct cx231xx_fh *fh = priv;
1614 struct cx231xx *dev = fh->dev;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001615
Devin Heitmuelleradc03562010-07-08 13:12:47 -03001616 f->fmt.vbi.sampling_rate = 6750000 * 4;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001617 f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
1618 f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
Devin Heitmuelleradc03562010-07-08 13:12:47 -03001619 f->fmt.vbi.offset = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001620 f->fmt.vbi.flags = 0;
1621 f->fmt.vbi.start[0] = (dev->norm & V4L2_STD_625_50) ?
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001622 PAL_VBI_START_LINE : NTSC_VBI_START_LINE;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001623 f->fmt.vbi.count[0] = (dev->norm & V4L2_STD_625_50) ?
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001624 PAL_VBI_LINES : NTSC_VBI_LINES;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001625 f->fmt.vbi.start[1] = (dev->norm & V4L2_STD_625_50) ?
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001626 PAL_VBI_START_LINE + 312 : NTSC_VBI_START_LINE + 263;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001627 f->fmt.vbi.count[1] = f->fmt.vbi.count[0];
Hans Verkuil62647222013-02-09 06:41:11 -03001628 memset(f->fmt.vbi.reserved, 0, sizeof(f->fmt.vbi.reserved));
Sri Deevie0d3baf2009-03-03 14:37:50 -03001629
1630 return 0;
1631
1632}
1633
Hans Verkuil62647222013-02-09 06:41:11 -03001634static int vidioc_s_fmt_vbi_cap(struct file *file, void *priv,
1635 struct v4l2_format *f)
1636{
1637 struct cx231xx_fh *fh = priv;
1638 struct cx231xx *dev = fh->dev;
1639
1640 if (dev->vbi_stream_on && !fh->stream_on) {
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -03001641 dev_err(dev->dev,
Mauro Carvalho Chehabb7085c02014-11-02 07:21:44 -03001642 "%s device in use by another fh\n", __func__);
Hans Verkuil62647222013-02-09 06:41:11 -03001643 return -EBUSY;
1644 }
1645 return vidioc_try_fmt_vbi_cap(file, priv, f);
1646}
1647
Sri Deevie0d3baf2009-03-03 14:37:50 -03001648static int vidioc_reqbufs(struct file *file, void *priv,
1649 struct v4l2_requestbuffers *rb)
1650{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001651 struct cx231xx_fh *fh = priv;
1652 struct cx231xx *dev = fh->dev;
1653 int rc;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001654
1655 rc = check_dev(dev);
1656 if (rc < 0)
1657 return rc;
1658
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03001659 return videobuf_reqbufs(&fh->vb_vidq, rb);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001660}
1661
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001662static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *b)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001663{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001664 struct cx231xx_fh *fh = priv;
1665 struct cx231xx *dev = fh->dev;
1666 int rc;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001667
1668 rc = check_dev(dev);
1669 if (rc < 0)
1670 return rc;
1671
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03001672 return videobuf_querybuf(&fh->vb_vidq, b);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001673}
1674
1675static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
1676{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001677 struct cx231xx_fh *fh = priv;
1678 struct cx231xx *dev = fh->dev;
1679 int rc;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001680
1681 rc = check_dev(dev);
1682 if (rc < 0)
1683 return rc;
1684
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03001685 return videobuf_qbuf(&fh->vb_vidq, b);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001686}
1687
1688static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
1689{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001690 struct cx231xx_fh *fh = priv;
1691 struct cx231xx *dev = fh->dev;
1692 int rc;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001693
1694 rc = check_dev(dev);
1695 if (rc < 0)
1696 return rc;
1697
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03001698 return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001699}
1700
Sri Deevie0d3baf2009-03-03 14:37:50 -03001701/* ----------------------------------------------------------- */
1702/* RADIO ESPECIFIC IOCTLS */
1703/* ----------------------------------------------------------- */
1704
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001705static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001706{
1707 struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev;
1708
Hans Verkuil530e01e2013-01-29 12:32:20 -03001709 if (t->index)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001710 return -EINVAL;
1711
Mauro Carvalho Chehabcc1e6312018-09-10 16:20:42 -04001712 strscpy(t->name, "Radio", sizeof(t->name));
Sri Deevie0d3baf2009-03-03 14:37:50 -03001713
Hans Verkuil530e01e2013-01-29 12:32:20 -03001714 call_all(dev, tuner, g_tuner, t);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001715
1716 return 0;
1717}
Hans Verkuil2f73c7c2013-03-15 06:10:06 -03001718static int radio_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *t)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001719{
1720 struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev;
1721
Hans Verkuilb86d1542013-01-29 13:16:06 -03001722 if (t->index)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001723 return -EINVAL;
1724
Sri Deevib1196122009-03-20 23:33:48 -03001725 call_all(dev, tuner, s_tuner, t);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001726
1727 return 0;
1728}
1729
Sri Deevie0d3baf2009-03-03 14:37:50 -03001730/*
1731 * cx231xx_v4l2_open()
1732 * inits the device and starts isoc transfer
1733 */
1734static int cx231xx_v4l2_open(struct file *filp)
1735{
Peter Senna Tschudin4df16f72014-05-31 13:30:52 -03001736 int radio = 0;
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001737 struct video_device *vdev = video_devdata(filp);
1738 struct cx231xx *dev = video_drvdata(filp);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001739 struct cx231xx_fh *fh;
1740 enum v4l2_buf_type fh_type = 0;
1741
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001742 switch (vdev->vfl_type) {
1743 case VFL_TYPE_GRABBER:
1744 fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1745 break;
1746 case VFL_TYPE_VBI:
1747 fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
1748 break;
1749 case VFL_TYPE_RADIO:
1750 radio = 1;
1751 break;
Mauro Carvalho Chehab4839c582017-09-28 18:39:32 -04001752 default:
1753 return -EINVAL;
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001754 }
Sri Deevie0d3baf2009-03-03 14:37:50 -03001755
Laurent Pinchart50462eb2009-12-10 11:47:13 -02001756 cx231xx_videodbg("open dev=%s type=%s users=%d\n",
1757 video_device_node_name(vdev), v4l2_type_names[fh_type],
1758 dev->users);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001759
1760#if 0
1761 errCode = cx231xx_set_mode(dev, CX231XX_ANALOG_MODE);
1762 if (errCode < 0) {
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -03001763 dev_err(dev->dev,
Mauro Carvalho Chehabb7085c02014-11-02 07:21:44 -03001764 "Device locked on digital mode. Can't open analog\n");
Sri Deevie0d3baf2009-03-03 14:37:50 -03001765 return -EBUSY;
1766 }
1767#endif
1768
1769 fh = kzalloc(sizeof(struct cx231xx_fh), GFP_KERNEL);
Mauro Carvalho Chehabb7085c02014-11-02 07:21:44 -03001770 if (!fh)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001771 return -ENOMEM;
Hans Verkuil1f7e0732012-06-24 06:43:02 -03001772 if (mutex_lock_interruptible(&dev->lock)) {
1773 kfree(fh);
1774 return -ERESTARTSYS;
1775 }
Sri Deevie0d3baf2009-03-03 14:37:50 -03001776 fh->dev = dev;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001777 fh->type = fh_type;
1778 filp->private_data = fh;
Hans Verkuil1d08a4f2012-09-17 07:31:04 -03001779 v4l2_fh_init(&fh->fh, vdev);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001780
1781 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001782 /* Power up in Analog TV mode */
Mauro Carvalho Chehab2f861382011-01-31 22:12:15 -03001783 if (dev->board.external_av)
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001784 cx231xx_set_power_mode(dev,
1785 POLARIS_AVMODE_ENXTERNAL_AV);
1786 else
1787 cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001788
1789#if 0
1790 cx231xx_set_mode(dev, CX231XX_ANALOG_MODE);
1791#endif
Sri Deevie0d3baf2009-03-03 14:37:50 -03001792
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001793 /* set video alternate setting */
1794 cx231xx_set_video_alternate(dev);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001795
1796 /* Needed, since GPIO might have disabled power of
1797 some i2c device */
1798 cx231xx_config_i2c(dev);
1799
1800 /* device needs to be initialized before isoc transfer */
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001801 dev->video_input = dev->video_input > 2 ? 2 : dev->video_input;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001802
1803 }
Hans Verkuil71590762013-01-28 12:57:47 -03001804 if (radio) {
Sri Deevie0d3baf2009-03-03 14:37:50 -03001805 cx231xx_videodbg("video_open: setting radio device\n");
1806
1807 /* cx231xx_start_radio(dev); */
1808
Sri Deevib1196122009-03-20 23:33:48 -03001809 call_all(dev, tuner, s_radio);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001810 }
1811
1812 dev->users++;
1813
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03001814 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1815 videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_video_qops,
1816 NULL, &dev->video_mode.slock,
1817 fh->type, V4L2_FIELD_INTERLACED,
Hans Verkuil08bff032010-09-20 17:39:46 -03001818 sizeof(struct cx231xx_buffer),
Mauro Carvalho Chehab643800d2010-10-09 13:13:35 -03001819 fh, &dev->lock);
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001820 if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03001821 /* Set the required alternate setting VBI interface works in
1822 Bulk mode only */
Mauro Carvalho Chehab2f861382011-01-31 22:12:15 -03001823 cx231xx_set_alt_setting(dev, INDEX_VANC, 0);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001824
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03001825 videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_vbi_qops,
1826 NULL, &dev->vbi_mode.slock,
1827 fh->type, V4L2_FIELD_SEQ_TB,
Hans Verkuil08bff032010-09-20 17:39:46 -03001828 sizeof(struct cx231xx_buffer),
Mauro Carvalho Chehab643800d2010-10-09 13:13:35 -03001829 fh, &dev->lock);
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001830 }
Hans Verkuil1f7e0732012-06-24 06:43:02 -03001831 mutex_unlock(&dev->lock);
Hans Verkuil1d08a4f2012-09-17 07:31:04 -03001832 v4l2_fh_add(&fh->fh);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001833
Peter Senna Tschudin4df16f72014-05-31 13:30:52 -03001834 return 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001835}
1836
1837/*
1838 * cx231xx_realease_resources()
1839 * unregisters the v4l2,i2c and usb devices
Geert Uytterhoeven6b338c72019-08-14 06:12:31 -03001840 * called when the device gets disconnected or at module unload
Sri Deevie0d3baf2009-03-03 14:37:50 -03001841*/
1842void cx231xx_release_analog_resources(struct cx231xx *dev)
1843{
1844
1845 /*FIXME: I2C IR should be disconnected */
1846
Hans Verkuil60acf182015-03-09 13:34:13 -03001847 if (video_is_registered(&dev->radio_dev))
1848 video_unregister_device(&dev->radio_dev);
1849 if (video_is_registered(&dev->vbi_dev)) {
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -03001850 dev_info(dev->dev, "V4L2 device %s deregistered\n",
Hans Verkuil60acf182015-03-09 13:34:13 -03001851 video_device_node_name(&dev->vbi_dev));
1852 video_unregister_device(&dev->vbi_dev);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001853 }
Hans Verkuil60acf182015-03-09 13:34:13 -03001854 if (video_is_registered(&dev->vdev)) {
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -03001855 dev_info(dev->dev, "V4L2 device %s deregistered\n",
Hans Verkuil60acf182015-03-09 13:34:13 -03001856 video_device_node_name(&dev->vdev));
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001857
Mauro Carvalho Chehab2f861382011-01-31 22:12:15 -03001858 if (dev->board.has_417)
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001859 cx231xx_417_unregister(dev);
1860
Hans Verkuil60acf182015-03-09 13:34:13 -03001861 video_unregister_device(&dev->vdev);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001862 }
Hans Verkuild2370f82012-09-17 07:22:09 -03001863 v4l2_ctrl_handler_free(&dev->ctrl_handler);
1864 v4l2_ctrl_handler_free(&dev->radio_ctrl_handler);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001865}
1866
1867/*
Hans Verkuil1f7e0732012-06-24 06:43:02 -03001868 * cx231xx_close()
Sri Deevie0d3baf2009-03-03 14:37:50 -03001869 * stops streaming and deallocates all resources allocated by the v4l2
1870 * calls and ioctls
1871 */
Hans Verkuil1f7e0732012-06-24 06:43:02 -03001872static int cx231xx_close(struct file *filp)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001873{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001874 struct cx231xx_fh *fh = filp->private_data;
1875 struct cx231xx *dev = fh->dev;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001876
1877 cx231xx_videodbg("users=%d\n", dev->users);
1878
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001879 cx231xx_videodbg("users=%d\n", dev->users);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001880 if (res_check(fh))
1881 res_free(fh);
1882
Mauro Carvalho Chehab2f861382011-01-31 22:12:15 -03001883 /*
1884 * To workaround error number=-71 on EP0 for VideoGrabber,
1885 * need exclude following.
1886 * FIXME: It is probably safe to remove most of these, as we're
1887 * now avoiding the alternate setting for INDEX_VANC
1888 */
1889 if (!dev->board.no_alt_vanc)
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001890 if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
1891 videobuf_stop(&fh->vb_vidq);
1892 videobuf_mmap_free(&fh->vb_vidq);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001893
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001894 /* the device is already disconnect,
1895 free the remaining resources */
1896 if (dev->state & DEV_DISCONNECTED) {
1897 if (atomic_read(&dev->devlist_count) > 0) {
1898 cx231xx_release_resources(dev);
Jesper Juhl266e8ae2012-03-04 16:25:04 -03001899 fh->dev = NULL;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001900 return 0;
1901 }
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001902 return 0;
1903 }
1904
1905 /* do this before setting alternate! */
1906 cx231xx_uninit_vbi_isoc(dev);
1907
1908 /* set alternate 0 */
1909 if (!dev->vbi_or_sliced_cc_mode)
1910 cx231xx_set_alt_setting(dev, INDEX_VANC, 0);
1911 else
1912 cx231xx_set_alt_setting(dev, INDEX_HANC, 0);
1913
Hans Verkuil1d08a4f2012-09-17 07:31:04 -03001914 v4l2_fh_del(&fh->fh);
1915 v4l2_fh_exit(&fh->fh);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001916 kfree(fh);
1917 dev->users--;
Steven Rostedt543409a2015-08-20 18:03:43 -03001918 wake_up_interruptible(&dev->open);
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001919 return 0;
1920 }
Sri Deevie0d3baf2009-03-03 14:37:50 -03001921
Hans Verkuil1d08a4f2012-09-17 07:31:04 -03001922 v4l2_fh_del(&fh->fh);
Mauro Carvalho Chehab990862a2012-01-10 09:48:50 -02001923 dev->users--;
1924 if (!dev->users) {
Sri Deevie0d3baf2009-03-03 14:37:50 -03001925 videobuf_stop(&fh->vb_vidq);
1926 videobuf_mmap_free(&fh->vb_vidq);
1927
1928 /* the device is already disconnect,
1929 free the remaining resources */
1930 if (dev->state & DEV_DISCONNECTED) {
1931 cx231xx_release_resources(dev);
Jesper Juhl266e8ae2012-03-04 16:25:04 -03001932 fh->dev = NULL;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001933 return 0;
1934 }
1935
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001936 /* Save some power by putting tuner to sleep */
Hans Verkuil3aab15a2018-02-21 02:49:25 -05001937 call_all(dev, tuner, standby);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001938
1939 /* do this before setting alternate! */
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001940 if (dev->USE_ISO)
1941 cx231xx_uninit_isoc(dev);
1942 else
1943 cx231xx_uninit_bulk(dev);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001944 cx231xx_set_mode(dev, CX231XX_SUSPEND);
1945
1946 /* set alternate 0 */
1947 cx231xx_set_alt_setting(dev, INDEX_VIDEO, 0);
1948 }
Hans Verkuil1d08a4f2012-09-17 07:31:04 -03001949 v4l2_fh_exit(&fh->fh);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001950 kfree(fh);
Steven Rostedt543409a2015-08-20 18:03:43 -03001951 wake_up_interruptible(&dev->open);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001952 return 0;
1953}
1954
Hans Verkuil1f7e0732012-06-24 06:43:02 -03001955static int cx231xx_v4l2_close(struct file *filp)
1956{
1957 struct cx231xx_fh *fh = filp->private_data;
1958 struct cx231xx *dev = fh->dev;
1959 int rc;
1960
1961 mutex_lock(&dev->lock);
1962 rc = cx231xx_close(filp);
1963 mutex_unlock(&dev->lock);
1964 return rc;
1965}
1966
Sri Deevie0d3baf2009-03-03 14:37:50 -03001967/*
1968 * cx231xx_v4l2_read()
1969 * will allocate buffers when called for the first time
1970 */
1971static ssize_t
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03001972cx231xx_v4l2_read(struct file *filp, char __user *buf, size_t count,
1973 loff_t *pos)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001974{
1975 struct cx231xx_fh *fh = filp->private_data;
1976 struct cx231xx *dev = fh->dev;
1977 int rc;
1978
1979 rc = check_dev(dev);
1980 if (rc < 0)
1981 return rc;
1982
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001983 if ((fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
1984 (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)) {
Sri Deevie0d3baf2009-03-03 14:37:50 -03001985 rc = res_get(fh);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001986
1987 if (unlikely(rc < 0))
1988 return rc;
1989
Hans Verkuil1f7e0732012-06-24 06:43:02 -03001990 if (mutex_lock_interruptible(&dev->lock))
1991 return -ERESTARTSYS;
1992 rc = videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001993 filp->f_flags & O_NONBLOCK);
Hans Verkuil1f7e0732012-06-24 06:43:02 -03001994 mutex_unlock(&dev->lock);
1995 return rc;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001996 }
1997 return 0;
1998}
1999
2000/*
2001 * cx231xx_v4l2_poll()
2002 * will allocate buffers when called for the first time
2003 */
Al Viroc23e0cb2017-07-03 03:02:56 -04002004static __poll_t cx231xx_v4l2_poll(struct file *filp, poll_table *wait)
Sri Deevie0d3baf2009-03-03 14:37:50 -03002005{
Al Viro01699432017-07-03 03:14:15 -04002006 __poll_t req_events = poll_requested_events(wait);
Sri Deevie0d3baf2009-03-03 14:37:50 -03002007 struct cx231xx_fh *fh = filp->private_data;
2008 struct cx231xx *dev = fh->dev;
Al Viroc23e0cb2017-07-03 03:02:56 -04002009 __poll_t res = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -03002010 int rc;
2011
2012 rc = check_dev(dev);
2013 if (rc < 0)
Linus Torvaldsa9a08842018-02-11 14:34:03 -08002014 return EPOLLERR;
Sri Deevie0d3baf2009-03-03 14:37:50 -03002015
Sri Deevie0d3baf2009-03-03 14:37:50 -03002016 rc = res_get(fh);
Sri Deevie0d3baf2009-03-03 14:37:50 -03002017
2018 if (unlikely(rc < 0))
Linus Torvaldsa9a08842018-02-11 14:34:03 -08002019 return EPOLLERR;
Sri Deevie0d3baf2009-03-03 14:37:50 -03002020
Hans Verkuil1d08a4f2012-09-17 07:31:04 -03002021 if (v4l2_event_pending(&fh->fh))
Linus Torvaldsa9a08842018-02-11 14:34:03 -08002022 res |= EPOLLPRI;
Hans Verkuil1d08a4f2012-09-17 07:31:04 -03002023 else
2024 poll_wait(filp, &fh->fh.wait, wait);
2025
Linus Torvaldsa9a08842018-02-11 14:34:03 -08002026 if (!(req_events & (EPOLLIN | EPOLLRDNORM)))
Hans Verkuil1d08a4f2012-09-17 07:31:04 -03002027 return res;
2028
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03002029 if ((V4L2_BUF_TYPE_VIDEO_CAPTURE == fh->type) ||
Hans Verkuil1f7e0732012-06-24 06:43:02 -03002030 (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type)) {
Hans Verkuil1f7e0732012-06-24 06:43:02 -03002031 mutex_lock(&dev->lock);
Hans Verkuil1d08a4f2012-09-17 07:31:04 -03002032 res |= videobuf_poll_stream(filp, &fh->vb_vidq, wait);
Hans Verkuil1f7e0732012-06-24 06:43:02 -03002033 mutex_unlock(&dev->lock);
2034 return res;
2035 }
Linus Torvaldsa9a08842018-02-11 14:34:03 -08002036 return res | EPOLLERR;
Sri Deevie0d3baf2009-03-03 14:37:50 -03002037}
2038
2039/*
2040 * cx231xx_v4l2_mmap()
2041 */
2042static int cx231xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
2043{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03002044 struct cx231xx_fh *fh = filp->private_data;
2045 struct cx231xx *dev = fh->dev;
2046 int rc;
Sri Deevie0d3baf2009-03-03 14:37:50 -03002047
2048 rc = check_dev(dev);
2049 if (rc < 0)
2050 return rc;
2051
Sri Deevie0d3baf2009-03-03 14:37:50 -03002052 rc = res_get(fh);
Sri Deevie0d3baf2009-03-03 14:37:50 -03002053
2054 if (unlikely(rc < 0))
2055 return rc;
2056
Hans Verkuil1f7e0732012-06-24 06:43:02 -03002057 if (mutex_lock_interruptible(&dev->lock))
2058 return -ERESTARTSYS;
Sri Deevie0d3baf2009-03-03 14:37:50 -03002059 rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
Hans Verkuil1f7e0732012-06-24 06:43:02 -03002060 mutex_unlock(&dev->lock);
Sri Deevie0d3baf2009-03-03 14:37:50 -03002061
2062 cx231xx_videodbg("vma start=0x%08lx, size=%ld, ret=%d\n",
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03002063 (unsigned long)vma->vm_start,
2064 (unsigned long)vma->vm_end -
2065 (unsigned long)vma->vm_start, rc);
Sri Deevie0d3baf2009-03-03 14:37:50 -03002066
2067 return rc;
2068}
2069
2070static const struct v4l2_file_operations cx231xx_v4l_fops = {
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03002071 .owner = THIS_MODULE,
2072 .open = cx231xx_v4l2_open,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03002073 .release = cx231xx_v4l2_close,
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03002074 .read = cx231xx_v4l2_read,
2075 .poll = cx231xx_v4l2_poll,
2076 .mmap = cx231xx_v4l2_mmap,
Mauro Carvalho Chehab643800d2010-10-09 13:13:35 -03002077 .unlocked_ioctl = video_ioctl2,
Sri Deevie0d3baf2009-03-03 14:37:50 -03002078};
2079
2080static const struct v4l2_ioctl_ops video_ioctl_ops = {
Hans Verkuilbc087342013-01-29 12:52:33 -03002081 .vidioc_querycap = cx231xx_querycap,
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03002082 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
2083 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
2084 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
2085 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
2086 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
2087 .vidioc_try_fmt_vbi_cap = vidioc_try_fmt_vbi_cap,
Hans Verkuil62647222013-02-09 06:41:11 -03002088 .vidioc_s_fmt_vbi_cap = vidioc_s_fmt_vbi_cap,
Hans Verkuil5200ab62018-10-04 17:38:15 -04002089 .vidioc_g_pixelaspect = vidioc_g_pixelaspect,
Hans Verkuilee10dc32018-10-04 17:06:32 -04002090 .vidioc_g_selection = vidioc_g_selection,
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03002091 .vidioc_reqbufs = vidioc_reqbufs,
2092 .vidioc_querybuf = vidioc_querybuf,
2093 .vidioc_qbuf = vidioc_qbuf,
2094 .vidioc_dqbuf = vidioc_dqbuf,
2095 .vidioc_s_std = vidioc_s_std,
2096 .vidioc_g_std = vidioc_g_std,
Hans Verkuilb86d1542013-01-29 13:16:06 -03002097 .vidioc_enum_input = cx231xx_enum_input,
2098 .vidioc_g_input = cx231xx_g_input,
2099 .vidioc_s_input = cx231xx_s_input,
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03002100 .vidioc_streamon = vidioc_streamon,
2101 .vidioc_streamoff = vidioc_streamoff,
Hans Verkuilb86d1542013-01-29 13:16:06 -03002102 .vidioc_g_tuner = cx231xx_g_tuner,
2103 .vidioc_s_tuner = cx231xx_s_tuner,
2104 .vidioc_g_frequency = cx231xx_g_frequency,
2105 .vidioc_s_frequency = cx231xx_s_frequency,
Sri Deevie0d3baf2009-03-03 14:37:50 -03002106#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuil08fe9f72013-05-29 06:59:43 -03002107 .vidioc_g_chip_info = cx231xx_g_chip_info,
Hans Verkuilb86d1542013-01-29 13:16:06 -03002108 .vidioc_g_register = cx231xx_g_register,
2109 .vidioc_s_register = cx231xx_s_register,
Sri Deevie0d3baf2009-03-03 14:37:50 -03002110#endif
Hans Verkuil1d08a4f2012-09-17 07:31:04 -03002111 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
2112 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Sri Deevie0d3baf2009-03-03 14:37:50 -03002113};
2114
2115static struct video_device cx231xx_vbi_template;
2116
2117static const struct video_device cx231xx_video_template = {
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03002118 .fops = &cx231xx_v4l_fops,
Hans Verkuil60acf182015-03-09 13:34:13 -03002119 .release = video_device_release_empty,
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03002120 .ioctl_ops = &video_ioctl_ops,
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03002121 .tvnorms = V4L2_STD_ALL,
Sri Deevie0d3baf2009-03-03 14:37:50 -03002122};
2123
2124static const struct v4l2_file_operations radio_fops = {
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03002125 .owner = THIS_MODULE,
2126 .open = cx231xx_v4l2_open,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03002127 .release = cx231xx_v4l2_close,
Hans Verkuil1d08a4f2012-09-17 07:31:04 -03002128 .poll = v4l2_ctrl_poll,
Hans Verkuil1265f082012-09-17 09:26:46 -03002129 .unlocked_ioctl = video_ioctl2,
Sri Deevie0d3baf2009-03-03 14:37:50 -03002130};
2131
2132static const struct v4l2_ioctl_ops radio_ioctl_ops = {
Hans Verkuilbc087342013-01-29 12:52:33 -03002133 .vidioc_querycap = cx231xx_querycap,
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03002134 .vidioc_g_tuner = radio_g_tuner,
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03002135 .vidioc_s_tuner = radio_s_tuner,
Hans Verkuilb86d1542013-01-29 13:16:06 -03002136 .vidioc_g_frequency = cx231xx_g_frequency,
2137 .vidioc_s_frequency = cx231xx_s_frequency,
Sri Deevie0d3baf2009-03-03 14:37:50 -03002138#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuil08fe9f72013-05-29 06:59:43 -03002139 .vidioc_g_chip_info = cx231xx_g_chip_info,
Hans Verkuilb86d1542013-01-29 13:16:06 -03002140 .vidioc_g_register = cx231xx_g_register,
2141 .vidioc_s_register = cx231xx_s_register,
Sri Deevie0d3baf2009-03-03 14:37:50 -03002142#endif
Hans Verkuil1d08a4f2012-09-17 07:31:04 -03002143 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
2144 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Sri Deevie0d3baf2009-03-03 14:37:50 -03002145};
2146
2147static struct video_device cx231xx_radio_template = {
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03002148 .name = "cx231xx-radio",
2149 .fops = &radio_fops,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03002150 .ioctl_ops = &radio_ioctl_ops,
Sri Deevie0d3baf2009-03-03 14:37:50 -03002151};
2152
2153/******************************** usb interface ******************************/
2154
Hans Verkuil60acf182015-03-09 13:34:13 -03002155static void cx231xx_vdev_init(struct cx231xx *dev,
2156 struct video_device *vfd,
2157 const struct video_device *template,
2158 const char *type_name)
Sri Deevie0d3baf2009-03-03 14:37:50 -03002159{
Sri Deevie0d3baf2009-03-03 14:37:50 -03002160 *vfd = *template;
Sri Deevib1196122009-03-20 23:33:48 -03002161 vfd->v4l2_dev = &dev->v4l2_dev;
Hans Verkuil60acf182015-03-09 13:34:13 -03002162 vfd->release = video_device_release_empty;
Mauro Carvalho Chehab643800d2010-10-09 13:13:35 -03002163 vfd->lock = &dev->lock;
Sri Deevie0d3baf2009-03-03 14:37:50 -03002164
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03002165 snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name);
Sri Deevie0d3baf2009-03-03 14:37:50 -03002166
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02002167 video_set_drvdata(vfd, dev);
Hans Verkuil06c46002012-09-13 06:17:47 -03002168 if (dev->tuner_type == TUNER_ABSENT) {
2169 v4l2_disable_ioctl(vfd, VIDIOC_G_FREQUENCY);
2170 v4l2_disable_ioctl(vfd, VIDIOC_S_FREQUENCY);
2171 v4l2_disable_ioctl(vfd, VIDIOC_G_TUNER);
2172 v4l2_disable_ioctl(vfd, VIDIOC_S_TUNER);
2173 }
Sri Deevie0d3baf2009-03-03 14:37:50 -03002174}
2175
2176int cx231xx_register_analog_devices(struct cx231xx *dev)
2177{
2178 int ret;
2179
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -03002180 dev_info(dev->dev, "v4l2 driver version %s\n", CX231XX_VERSION);
Sri Deevie0d3baf2009-03-03 14:37:50 -03002181
2182 /* set default norm */
Hans Verkuila25a70122012-09-17 08:30:07 -03002183 dev->norm = V4L2_STD_PAL;
Sri Deevie0d3baf2009-03-03 14:37:50 -03002184 dev->width = norm_maxw(dev);
2185 dev->height = norm_maxh(dev);
2186 dev->interlaced = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -03002187
2188 /* Analog specific initialization */
2189 dev->format = &format[0];
Devin Heitmueller6e6a2ba2010-07-12 15:34:57 -03002190
2191 /* Set the initial input */
2192 video_mux(dev, dev->video_input);
Sri Deevie0d3baf2009-03-03 14:37:50 -03002193
Laurent Pinchart8774bed2014-04-28 16:53:01 -03002194 call_all(dev, video, s_std, dev->norm);
Hans Verkuild61072a2013-01-29 10:50:54 -03002195
Hans Verkuild2370f82012-09-17 07:22:09 -03002196 v4l2_ctrl_handler_init(&dev->ctrl_handler, 10);
2197 v4l2_ctrl_handler_init(&dev->radio_ctrl_handler, 5);
2198
2199 if (dev->sd_cx25840) {
2200 v4l2_ctrl_add_handler(&dev->ctrl_handler,
Hans Verkuilda1b1ae2018-05-21 04:54:36 -04002201 dev->sd_cx25840->ctrl_handler, NULL, true);
Hans Verkuild2370f82012-09-17 07:22:09 -03002202 v4l2_ctrl_add_handler(&dev->radio_ctrl_handler,
2203 dev->sd_cx25840->ctrl_handler,
Hans Verkuilda1b1ae2018-05-21 04:54:36 -04002204 v4l2_ctrl_radio_filter, true);
Hans Verkuild2370f82012-09-17 07:22:09 -03002205 }
2206
2207 if (dev->ctrl_handler.error)
2208 return dev->ctrl_handler.error;
2209 if (dev->radio_ctrl_handler.error)
2210 return dev->radio_ctrl_handler.error;
Sri Deevie0d3baf2009-03-03 14:37:50 -03002211
2212 /* enable vbi capturing */
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03002213 /* write code here... */
Sri Deevie0d3baf2009-03-03 14:37:50 -03002214
2215 /* allocate and fill video video_device struct */
Hans Verkuil60acf182015-03-09 13:34:13 -03002216 cx231xx_vdev_init(dev, &dev->vdev, &cx231xx_video_template, "video");
Mauro Carvalho Chehabb6a40e72015-01-03 16:08:07 -03002217#if defined(CONFIG_MEDIA_CONTROLLER)
2218 dev->video_pad.flags = MEDIA_PAD_FL_SINK;
Mauro Carvalho Chehabab22e772015-12-11 07:44:40 -02002219 ret = media_entity_pads_init(&dev->vdev.entity, 1, &dev->video_pad);
Mauro Carvalho Chehabb6a40e72015-01-03 16:08:07 -03002220 if (ret < 0)
2221 dev_err(dev->dev, "failed to initialize video media entity!\n");
2222#endif
Hans Verkuil60acf182015-03-09 13:34:13 -03002223 dev->vdev.ctrl_handler = &dev->ctrl_handler;
Hans Verkuil8c3854d2019-06-04 07:19:53 -04002224 dev->vdev.device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
2225 V4L2_CAP_VIDEO_CAPTURE;
2226 if (dev->tuner_type != TUNER_ABSENT)
2227 dev->vdev.device_caps |= V4L2_CAP_TUNER;
2228
Sri Deevie0d3baf2009-03-03 14:37:50 -03002229 /* register v4l2 video video_device */
Hans Verkuil60acf182015-03-09 13:34:13 -03002230 ret = video_register_device(&dev->vdev, VFL_TYPE_GRABBER,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03002231 video_nr[dev->devno]);
Sri Deevie0d3baf2009-03-03 14:37:50 -03002232 if (ret) {
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -03002233 dev_err(dev->dev,
Mauro Carvalho Chehabb7085c02014-11-02 07:21:44 -03002234 "unable to register video device (error=%i).\n",
Mauro Carvalho Chehabed0e3722014-11-01 08:59:03 -03002235 ret);
Sri Deevie0d3baf2009-03-03 14:37:50 -03002236 return ret;
2237 }
2238
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -03002239 dev_info(dev->dev, "Registered video device %s [v4l2]\n",
Hans Verkuil60acf182015-03-09 13:34:13 -03002240 video_device_node_name(&dev->vdev));
Sri Deevie0d3baf2009-03-03 14:37:50 -03002241
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03002242 /* Initialize VBI template */
Ezequiel Garcia3724dde2012-10-23 15:57:05 -03002243 cx231xx_vbi_template = cx231xx_video_template;
Mauro Carvalho Chehabcc1e6312018-09-10 16:20:42 -04002244 strscpy(cx231xx_vbi_template.name, "cx231xx-vbi",
2245 sizeof(cx231xx_vbi_template.name));
Sri Deevie0d3baf2009-03-03 14:37:50 -03002246
2247 /* Allocate and fill vbi video_device struct */
Hans Verkuil60acf182015-03-09 13:34:13 -03002248 cx231xx_vdev_init(dev, &dev->vbi_dev, &cx231xx_vbi_template, "vbi");
Sri Deevie0d3baf2009-03-03 14:37:50 -03002249
Mauro Carvalho Chehabb6a40e72015-01-03 16:08:07 -03002250#if defined(CONFIG_MEDIA_CONTROLLER)
2251 dev->vbi_pad.flags = MEDIA_PAD_FL_SINK;
Mauro Carvalho Chehabab22e772015-12-11 07:44:40 -02002252 ret = media_entity_pads_init(&dev->vbi_dev.entity, 1, &dev->vbi_pad);
Mauro Carvalho Chehabb6a40e72015-01-03 16:08:07 -03002253 if (ret < 0)
2254 dev_err(dev->dev, "failed to initialize vbi media entity!\n");
2255#endif
Hans Verkuil60acf182015-03-09 13:34:13 -03002256 dev->vbi_dev.ctrl_handler = &dev->ctrl_handler;
Hans Verkuil8c3854d2019-06-04 07:19:53 -04002257 dev->vbi_dev.device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
2258 V4L2_CAP_VBI_CAPTURE;
2259 if (dev->tuner_type != TUNER_ABSENT)
2260 dev->vbi_dev.device_caps |= V4L2_CAP_TUNER;
2261
Sri Deevie0d3baf2009-03-03 14:37:50 -03002262 /* register v4l2 vbi video_device */
Hans Verkuil60acf182015-03-09 13:34:13 -03002263 ret = video_register_device(&dev->vbi_dev, VFL_TYPE_VBI,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03002264 vbi_nr[dev->devno]);
Sri Deevie0d3baf2009-03-03 14:37:50 -03002265 if (ret < 0) {
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -03002266 dev_err(dev->dev, "unable to register vbi device\n");
Sri Deevie0d3baf2009-03-03 14:37:50 -03002267 return ret;
2268 }
2269
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -03002270 dev_info(dev->dev, "Registered VBI device %s\n",
Hans Verkuil60acf182015-03-09 13:34:13 -03002271 video_device_node_name(&dev->vbi_dev));
Sri Deevie0d3baf2009-03-03 14:37:50 -03002272
2273 if (cx231xx_boards[dev->model].radio.type == CX231XX_RADIO) {
Hans Verkuil60acf182015-03-09 13:34:13 -03002274 cx231xx_vdev_init(dev, &dev->radio_dev,
2275 &cx231xx_radio_template, "radio");
2276 dev->radio_dev.ctrl_handler = &dev->radio_ctrl_handler;
Hans Verkuil8c3854d2019-06-04 07:19:53 -04002277 dev->radio_dev.device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER;
Hans Verkuil60acf182015-03-09 13:34:13 -03002278 ret = video_register_device(&dev->radio_dev, VFL_TYPE_RADIO,
Sri Deevie0d3baf2009-03-03 14:37:50 -03002279 radio_nr[dev->devno]);
2280 if (ret < 0) {
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -03002281 dev_err(dev->dev,
Mauro Carvalho Chehabb7085c02014-11-02 07:21:44 -03002282 "can't register radio device\n");
Sri Deevie0d3baf2009-03-03 14:37:50 -03002283 return ret;
2284 }
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -03002285 dev_info(dev->dev, "Registered radio device as %s\n",
Hans Verkuil60acf182015-03-09 13:34:13 -03002286 video_device_node_name(&dev->radio_dev));
Sri Deevie0d3baf2009-03-03 14:37:50 -03002287 }
2288
Sri Deevie0d3baf2009-03-03 14:37:50 -03002289 return 0;
2290}