blob: 8bff7d8a0310f368be24975201650b2cd523921c [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
Hans Verkuil7c617132019-09-05 08:31:11 -030061static unsigned int card[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = -1U };
62static unsigned int video_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = -1U };
63static unsigned int vbi_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = -1U };
64static unsigned int radio_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = -1U };
Sri Deevie0d3baf2009-03-03 14:37:50 -030065
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 */
Hans Verkuil7c617132019-09-05 08:31:11 -0300169 cx231xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.vb2_buf.index);
170 buf->vb.sequence = dma_q->sequence++;
171 buf->vb.field = V4L2_FIELD_INTERLACED;
172 buf->vb.vb2_buf.timestamp = ktime_get_ns();
173 vb2_set_plane_payload(&buf->vb.vb2_buf, 0, dev->size);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300174
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300175 if (dev->USE_ISO)
176 dev->video_mode.isoc_ctl.buf = NULL;
177 else
178 dev->video_mode.bulk_ctl.buf = NULL;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300179
Hans Verkuil7c617132019-09-05 08:31:11 -0300180 list_del(&buf->list);
181 vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300182}
183
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300184static inline void print_err_status(struct cx231xx *dev, int packet, int status)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300185{
186 char *errmsg = "Unknown";
187
188 switch (status) {
189 case -ENOENT:
Colin Ian Kingb436e262017-11-02 06:11:53 -0400190 errmsg = "unlinked synchronously";
Sri Deevie0d3baf2009-03-03 14:37:50 -0300191 break;
192 case -ECONNRESET:
Colin Ian Kingb436e262017-11-02 06:11:53 -0400193 errmsg = "unlinked asynchronously";
Sri Deevie0d3baf2009-03-03 14:37:50 -0300194 break;
195 case -ENOSR:
196 errmsg = "Buffer error (overrun)";
197 break;
198 case -EPIPE:
199 errmsg = "Stalled (device not responding)";
200 break;
201 case -EOVERFLOW:
202 errmsg = "Babble (bad cable?)";
203 break;
204 case -EPROTO:
205 errmsg = "Bit-stuff error (bad cable?)";
206 break;
207 case -EILSEQ:
208 errmsg = "CRC/Timeout (could be anything)";
209 break;
210 case -ETIME:
211 errmsg = "Device does not respond";
212 break;
213 }
214 if (packet < 0) {
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300215 cx231xx_isocdbg("URB status %d [%s].\n", status, errmsg);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300216 } else {
217 cx231xx_isocdbg("URB packet %d, status %d [%s].\n",
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300218 packet, status, errmsg);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300219 }
220}
221
222/*
223 * video-buf generic routine to get the next available buffer
224 */
225static inline void get_next_buf(struct cx231xx_dmaqueue *dma_q,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300226 struct cx231xx_buffer **buf)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300227{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300228 struct cx231xx_video_mode *vmode =
229 container_of(dma_q, struct cx231xx_video_mode, vidq);
230 struct cx231xx *dev = container_of(vmode, struct cx231xx, video_mode);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300231
232 char *outp;
233
Sri Deevie0d3baf2009-03-03 14:37:50 -0300234 if (list_empty(&dma_q->active)) {
235 cx231xx_isocdbg("No active queue to serve\n");
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300236 if (dev->USE_ISO)
237 dev->video_mode.isoc_ctl.buf = NULL;
238 else
239 dev->video_mode.bulk_ctl.buf = NULL;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300240 *buf = NULL;
241 return;
242 }
243
244 /* Get the next buffer */
Hans Verkuil7c617132019-09-05 08:31:11 -0300245 *buf = list_entry(dma_q->active.next, struct cx231xx_buffer, list);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300246
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300247 /* Cleans up buffer - Useful for testing for frame/URB loss */
Hans Verkuil7c617132019-09-05 08:31:11 -0300248 outp = vb2_plane_vaddr(&(*buf)->vb.vb2_buf, 0);
249 memset(outp, 0, dev->size);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300250
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300251 if (dev->USE_ISO)
252 dev->video_mode.isoc_ctl.buf = *buf;
253 else
254 dev->video_mode.bulk_ctl.buf = *buf;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300255
256 return;
257}
258
259/*
260 * Controls the isoc copy of each urb packet
261 */
262static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb)
263{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300264 struct cx231xx_dmaqueue *dma_q = urb->context;
Peter Senna Tschudin4df16f72014-05-31 13:30:52 -0300265 int i;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300266 unsigned char *p_buffer;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300267 u32 bytes_parsed = 0, buffer_size = 0;
268 u8 sav_eav = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300269
270 if (!dev)
271 return 0;
272
Mauro Carvalho Chehab990862a2012-01-10 09:48:50 -0200273 if (dev->state & DEV_DISCONNECTED)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300274 return 0;
275
276 if (urb->status < 0) {
277 print_err_status(dev, -1, urb->status);
278 if (urb->status == -ENOENT)
279 return 0;
280 }
281
Sri Deevie0d3baf2009-03-03 14:37:50 -0300282 for (i = 0; i < urb->number_of_packets; i++) {
283 int status = urb->iso_frame_desc[i].status;
284
285 if (status < 0) {
286 print_err_status(dev, i, status);
287 if (urb->iso_frame_desc[i].status != -EPROTO)
288 continue;
289 }
290
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300291 if (urb->iso_frame_desc[i].actual_length <= 0) {
Sri Deevie0d3baf2009-03-03 14:37:50 -0300292 /* cx231xx_isocdbg("packet %d is empty",i); - spammy */
293 continue;
294 }
295 if (urb->iso_frame_desc[i].actual_length >
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300296 dev->video_mode.max_pkt_size) {
Sri Deevie0d3baf2009-03-03 14:37:50 -0300297 cx231xx_isocdbg("packet bigger than packet size");
298 continue;
299 }
300
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300301 /* get buffer pointer and length */
Sri Deevie0d3baf2009-03-03 14:37:50 -0300302 p_buffer = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300303 buffer_size = urb->iso_frame_desc[i].actual_length;
304 bytes_parsed = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300305
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300306 if (dma_q->is_partial_line) {
Sri Deevib9255172009-03-04 17:49:01 -0300307 /* Handle the case of a partial line */
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300308 sav_eav = dma_q->last_sav;
309 } else {
Sri Deevib9255172009-03-04 17:49:01 -0300310 /* Check for a SAV/EAV overlapping
311 the buffer boundary */
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300312 sav_eav =
313 cx231xx_find_boundary_SAV_EAV(p_buffer,
314 dma_q->partial_buf,
315 &bytes_parsed);
316 }
Sri Deevie0d3baf2009-03-03 14:37:50 -0300317
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300318 sav_eav &= 0xF0;
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300319 /* Get the first line if we have some portion of an SAV/EAV from
320 the last buffer or a partial line */
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300321 if (sav_eav) {
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300322 bytes_parsed += cx231xx_get_video_line(dev, dma_q,
Sri Deevib9255172009-03-04 17:49:01 -0300323 sav_eav, /* SAV/EAV */
324 p_buffer + bytes_parsed, /* p_buffer */
325 buffer_size - bytes_parsed);/* buf size */
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300326 }
Sri Deevie0d3baf2009-03-03 14:37:50 -0300327
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300328 /* Now parse data that is completely in this buffer */
329 /* dma_q->is_partial_line = 0; */
Sri Deevie0d3baf2009-03-03 14:37:50 -0300330
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300331 while (bytes_parsed < buffer_size) {
332 u32 bytes_used = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300333
Sri Deevib9255172009-03-04 17:49:01 -0300334 sav_eav = cx231xx_find_next_SAV_EAV(
335 p_buffer + bytes_parsed, /* p_buffer */
336 buffer_size - bytes_parsed, /* buf size */
337 &bytes_used);/* bytes used to get SAV/EAV */
Sri Deevie0d3baf2009-03-03 14:37:50 -0300338
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300339 bytes_parsed += bytes_used;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300340
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300341 sav_eav &= 0xF0;
342 if (sav_eav && (bytes_parsed < buffer_size)) {
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300343 bytes_parsed += cx231xx_get_video_line(dev,
Sri Deevib9255172009-03-04 17:49:01 -0300344 dma_q, sav_eav, /* SAV/EAV */
345 p_buffer + bytes_parsed,/* p_buffer */
346 buffer_size - bytes_parsed);/*buf size*/
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300347 }
348 }
Sri Deevie0d3baf2009-03-03 14:37:50 -0300349
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300350 /* Save the last four bytes of the buffer so we can check the
351 buffer boundary condition next time */
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300352 memcpy(dma_q->partial_buf, p_buffer + buffer_size - 4, 4);
353 bytes_parsed = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300354
355 }
Peter Senna Tschudin4df16f72014-05-31 13:30:52 -0300356 return 1;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300357}
358
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300359static inline int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb)
360{
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300361 struct cx231xx_dmaqueue *dma_q = urb->context;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300362 unsigned char *p_buffer;
363 u32 bytes_parsed = 0, buffer_size = 0;
364 u8 sav_eav = 0;
365
366 if (!dev)
367 return 0;
368
Mauro Carvalho Chehab990862a2012-01-10 09:48:50 -0200369 if (dev->state & DEV_DISCONNECTED)
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300370 return 0;
371
372 if (urb->status < 0) {
373 print_err_status(dev, -1, urb->status);
374 if (urb->status == -ENOENT)
375 return 0;
376 }
377
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300378 if (1) {
379
380 /* get buffer pointer and length */
381 p_buffer = urb->transfer_buffer;
382 buffer_size = urb->actual_length;
383 bytes_parsed = 0;
384
385 if (dma_q->is_partial_line) {
386 /* Handle the case of a partial line */
387 sav_eav = dma_q->last_sav;
388 } else {
389 /* Check for a SAV/EAV overlapping
390 the buffer boundary */
391 sav_eav =
392 cx231xx_find_boundary_SAV_EAV(p_buffer,
393 dma_q->partial_buf,
394 &bytes_parsed);
395 }
396
397 sav_eav &= 0xF0;
398 /* Get the first line if we have some portion of an SAV/EAV from
399 the last buffer or a partial line */
400 if (sav_eav) {
401 bytes_parsed += cx231xx_get_video_line(dev, dma_q,
402 sav_eav, /* SAV/EAV */
403 p_buffer + bytes_parsed, /* p_buffer */
404 buffer_size - bytes_parsed);/* buf size */
405 }
406
407 /* Now parse data that is completely in this buffer */
408 /* dma_q->is_partial_line = 0; */
409
410 while (bytes_parsed < buffer_size) {
411 u32 bytes_used = 0;
412
413 sav_eav = cx231xx_find_next_SAV_EAV(
414 p_buffer + bytes_parsed, /* p_buffer */
415 buffer_size - bytes_parsed, /* buf size */
416 &bytes_used);/* bytes used to get SAV/EAV */
417
418 bytes_parsed += bytes_used;
419
420 sav_eav &= 0xF0;
421 if (sav_eav && (bytes_parsed < buffer_size)) {
422 bytes_parsed += cx231xx_get_video_line(dev,
423 dma_q, sav_eav, /* SAV/EAV */
424 p_buffer + bytes_parsed,/* p_buffer */
425 buffer_size - bytes_parsed);/*buf size*/
426 }
427 }
428
429 /* Save the last four bytes of the buffer so we can check the
430 buffer boundary condition next time */
431 memcpy(dma_q->partial_buf, p_buffer + buffer_size - 4, 4);
432 bytes_parsed = 0;
433
434 }
Peter Senna Tschudin4df16f72014-05-31 13:30:52 -0300435 return 1;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300436}
437
438
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300439u8 cx231xx_find_boundary_SAV_EAV(u8 *p_buffer, u8 *partial_buf,
440 u32 *p_bytes_used)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300441{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300442 u32 bytes_used;
443 u8 boundary_bytes[8];
444 u8 sav_eav = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300445
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300446 *p_bytes_used = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300447
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300448 /* Create an array of the last 4 bytes of the last buffer and the first
449 4 bytes of the current buffer. */
Sri Deevie0d3baf2009-03-03 14:37:50 -0300450
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300451 memcpy(boundary_bytes, partial_buf, 4);
452 memcpy(boundary_bytes + 4, p_buffer, 4);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300453
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300454 /* Check for the SAV/EAV in the boundary buffer */
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300455 sav_eav = cx231xx_find_next_SAV_EAV((u8 *)&boundary_bytes, 8,
456 &bytes_used);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300457
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300458 if (sav_eav) {
459 /* found a boundary SAV/EAV. Updates the bytes used to reflect
460 only those used in the new buffer */
461 *p_bytes_used = bytes_used - 4;
462 }
Sri Deevie0d3baf2009-03-03 14:37:50 -0300463
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300464 return sav_eav;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300465}
466
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300467u8 cx231xx_find_next_SAV_EAV(u8 *p_buffer, u32 buffer_size, u32 *p_bytes_used)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300468{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300469 u32 i;
470 u8 sav_eav = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300471
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300472 /*
473 * Don't search if the buffer size is less than 4. It causes a page
474 * fault since buffer_size - 4 evaluates to a large number in that
475 * case.
476 */
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300477 if (buffer_size < 4) {
478 *p_bytes_used = buffer_size;
479 return 0;
480 }
Sri Deevie0d3baf2009-03-03 14:37:50 -0300481
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300482 for (i = 0; i < (buffer_size - 3); i++) {
Sri Deevie0d3baf2009-03-03 14:37:50 -0300483
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300484 if ((p_buffer[i] == 0xFF) &&
485 (p_buffer[i + 1] == 0x00) && (p_buffer[i + 2] == 0x00)) {
Sri Deevie0d3baf2009-03-03 14:37:50 -0300486
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300487 *p_bytes_used = i + 4;
488 sav_eav = p_buffer[i + 3];
489 return sav_eav;
490 }
491 }
Sri Deevie0d3baf2009-03-03 14:37:50 -0300492
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300493 *p_bytes_used = buffer_size;
494 return 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300495}
496
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300497u32 cx231xx_get_video_line(struct cx231xx *dev,
498 struct cx231xx_dmaqueue *dma_q, u8 sav_eav,
499 u8 *p_buffer, u32 buffer_size)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300500{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300501 u32 bytes_copied = 0;
502 int current_field = -1;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300503
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300504 switch (sav_eav) {
505 case SAV_ACTIVE_VIDEO_FIELD1:
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300506 /* looking for skipped line which occurred in PAL 720x480 mode.
507 In this case, there will be no active data contained
508 between the SAV and EAV */
509 if ((buffer_size > 3) && (p_buffer[0] == 0xFF) &&
510 (p_buffer[1] == 0x00) && (p_buffer[2] == 0x00) &&
511 ((p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD1) ||
512 (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD2) ||
513 (p_buffer[3] == EAV_VBLANK_FIELD1) ||
514 (p_buffer[3] == EAV_VBLANK_FIELD2)))
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300515 return bytes_copied;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300516 current_field = 1;
517 break;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300518
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300519 case SAV_ACTIVE_VIDEO_FIELD2:
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300520 /* looking for skipped line which occurred in PAL 720x480 mode.
521 In this case, there will be no active data contained between
522 the SAV and EAV */
523 if ((buffer_size > 3) && (p_buffer[0] == 0xFF) &&
524 (p_buffer[1] == 0x00) && (p_buffer[2] == 0x00) &&
525 ((p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD1) ||
526 (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD2) ||
527 (p_buffer[3] == EAV_VBLANK_FIELD1) ||
528 (p_buffer[3] == EAV_VBLANK_FIELD2)))
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300529 return bytes_copied;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300530 current_field = 2;
531 break;
532 }
Sri Deevie0d3baf2009-03-03 14:37:50 -0300533
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300534 dma_q->last_sav = sav_eav;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300535
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300536 bytes_copied = cx231xx_copy_video_line(dev, dma_q, p_buffer,
537 buffer_size, current_field);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300538
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300539 return bytes_copied;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300540}
541
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300542u32 cx231xx_copy_video_line(struct cx231xx *dev,
543 struct cx231xx_dmaqueue *dma_q, u8 *p_line,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300544 u32 length, int field_number)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300545{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300546 u32 bytes_to_copy;
547 struct cx231xx_buffer *buf;
548 u32 _line_size = dev->width * 2;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300549
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300550 if (dma_q->current_field != field_number)
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300551 cx231xx_reset_video_buffer(dev, dma_q);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300552
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300553 /* get the buffer pointer */
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300554 if (dev->USE_ISO)
555 buf = dev->video_mode.isoc_ctl.buf;
556 else
557 buf = dev->video_mode.bulk_ctl.buf;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300558
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300559 /* Remember the field number for next time */
560 dma_q->current_field = field_number;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300561
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300562 bytes_to_copy = dma_q->bytes_left_in_line;
563 if (bytes_to_copy > length)
564 bytes_to_copy = length;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300565
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300566 if (dma_q->lines_completed >= dma_q->lines_per_field) {
567 dma_q->bytes_left_in_line -= bytes_to_copy;
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300568 dma_q->is_partial_line = (dma_q->bytes_left_in_line == 0) ?
569 0 : 1;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300570 return 0;
571 }
Sri Deevie0d3baf2009-03-03 14:37:50 -0300572
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300573 dma_q->is_partial_line = 1;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300574
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300575 /* If we don't have a buffer, just return the number of bytes we would
576 have copied if we had a buffer. */
577 if (!buf) {
578 dma_q->bytes_left_in_line -= bytes_to_copy;
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300579 dma_q->is_partial_line = (dma_q->bytes_left_in_line == 0)
580 ? 0 : 1;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300581 return bytes_to_copy;
582 }
Sri Deevie0d3baf2009-03-03 14:37:50 -0300583
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300584 /* copy the data to video buffer */
585 cx231xx_do_copy(dev, dma_q, p_line, bytes_to_copy);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300586
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300587 dma_q->pos += bytes_to_copy;
588 dma_q->bytes_left_in_line -= bytes_to_copy;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300589
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300590 if (dma_q->bytes_left_in_line == 0) {
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300591 dma_q->bytes_left_in_line = _line_size;
592 dma_q->lines_completed++;
593 dma_q->is_partial_line = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300594
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300595 if (cx231xx_is_buffer_done(dev, dma_q) && buf) {
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300596 buffer_filled(dev, dma_q, buf);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300597
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300598 dma_q->pos = 0;
599 buf = NULL;
600 dma_q->lines_completed = 0;
601 }
602 }
Sri Deevie0d3baf2009-03-03 14:37:50 -0300603
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300604 return bytes_to_copy;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300605}
606
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300607void cx231xx_reset_video_buffer(struct cx231xx *dev,
608 struct cx231xx_dmaqueue *dma_q)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300609{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300610 struct cx231xx_buffer *buf;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300611
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300612 /* handle the switch from field 1 to field 2 */
613 if (dma_q->current_field == 1) {
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300614 if (dma_q->lines_completed >= dma_q->lines_per_field)
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300615 dma_q->field1_done = 1;
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300616 else
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300617 dma_q->field1_done = 0;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300618 }
Sri Deevie0d3baf2009-03-03 14:37:50 -0300619
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300620 if (dev->USE_ISO)
621 buf = dev->video_mode.isoc_ctl.buf;
622 else
623 buf = dev->video_mode.bulk_ctl.buf;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300624
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300625 if (buf == NULL) {
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300626 /* first try to get the buffer */
627 get_next_buf(dma_q, &buf);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300628
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300629 dma_q->pos = 0;
630 dma_q->field1_done = 0;
631 dma_q->current_field = -1;
632 }
Sri Deevie0d3baf2009-03-03 14:37:50 -0300633
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300634 /* reset the counters */
635 dma_q->bytes_left_in_line = dev->width << 1;
636 dma_q->lines_completed = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300637}
638
639int cx231xx_do_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300640 u8 *p_buffer, u32 bytes_to_copy)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300641{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300642 u8 *p_out_buffer = NULL;
643 u32 current_line_bytes_copied = 0;
644 struct cx231xx_buffer *buf;
645 u32 _line_size = dev->width << 1;
646 void *startwrite;
647 int offset, lencopy;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300648
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300649 if (dev->USE_ISO)
650 buf = dev->video_mode.isoc_ctl.buf;
651 else
652 buf = dev->video_mode.bulk_ctl.buf;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300653
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300654 if (buf == NULL)
655 return -1;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300656
Hans Verkuil7c617132019-09-05 08:31:11 -0300657 p_out_buffer = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300658
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300659 current_line_bytes_copied = _line_size - dma_q->bytes_left_in_line;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300660
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300661 /* Offset field 2 one line from the top of the buffer */
662 offset = (dma_q->current_field == 1) ? 0 : _line_size;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300663
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300664 /* Offset for field 2 */
665 startwrite = p_out_buffer + offset;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300666
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300667 /* lines already completed in the current field */
668 startwrite += (dma_q->lines_completed * _line_size * 2);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300669
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300670 /* bytes already completed in the current line */
671 startwrite += current_line_bytes_copied;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300672
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300673 lencopy = dma_q->bytes_left_in_line > bytes_to_copy ?
674 bytes_to_copy : dma_q->bytes_left_in_line;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300675
Hans Verkuil7c617132019-09-05 08:31:11 -0300676 if ((u8 *)(startwrite + lencopy) > (u8 *)(p_out_buffer + dev->size))
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300677 return 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300678
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300679 /* The below copies the UYVY data straight into video buffer */
680 cx231xx_swab((u16 *) p_buffer, (u16 *) startwrite, (u16) lencopy);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300681
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300682 return 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300683}
684
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300685void cx231xx_swab(u16 *from, u16 *to, u16 len)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300686{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300687 u16 i;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300688
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300689 if (len <= 0)
690 return;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300691
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300692 for (i = 0; i < len / 2; i++)
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300693 to[i] = (from[i] << 8) | (from[i] >> 8);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300694}
695
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300696u8 cx231xx_is_buffer_done(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300697{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300698 u8 buffer_complete = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300699
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300700 /* Dual field stream */
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300701 buffer_complete = ((dma_q->current_field == 2) &&
702 (dma_q->lines_completed >= dma_q->lines_per_field) &&
703 dma_q->field1_done);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300704
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300705 return buffer_complete;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300706}
707
Sri Deevie0d3baf2009-03-03 14:37:50 -0300708/* ------------------------------------------------------------------
709 Videobuf operations
710 ------------------------------------------------------------------*/
711
Hans Verkuil7c617132019-09-05 08:31:11 -0300712static int queue_setup(struct vb2_queue *vq,
713 unsigned int *nbuffers, unsigned int *nplanes,
714 unsigned int sizes[], struct device *alloc_devs[])
Sri Deevie0d3baf2009-03-03 14:37:50 -0300715{
Hans Verkuil7c617132019-09-05 08:31:11 -0300716 struct cx231xx *dev = vb2_get_drv_priv(vq);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300717
Hans Verkuil7c617132019-09-05 08:31:11 -0300718 dev->size = (dev->width * dev->height * dev->format->depth + 7) >> 3;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300719
Hans Verkuil7c617132019-09-05 08:31:11 -0300720 if (vq->num_buffers + *nbuffers < CX231XX_MIN_BUF)
721 *nbuffers = CX231XX_MIN_BUF - vq->num_buffers;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300722
Hans Verkuil7c617132019-09-05 08:31:11 -0300723 if (*nplanes)
724 return sizes[0] < dev->size ? -EINVAL : 0;
725 *nplanes = 1;
726 sizes[0] = dev->size;
Mauro Carvalho Chehab3d263112015-02-18 12:22:27 -0300727
Sri Deevie0d3baf2009-03-03 14:37:50 -0300728 return 0;
729}
730
Hans Verkuil7c617132019-09-05 08:31:11 -0300731static void buffer_queue(struct vb2_buffer *vb)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300732{
Hans Verkuil7c617132019-09-05 08:31:11 -0300733 struct cx231xx_buffer *buf =
734 container_of(vb, struct cx231xx_buffer, vb.vb2_buf);
735 struct cx231xx *dev = vb2_get_drv_priv(vb->vb2_queue);
736 struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq;
737 unsigned long flags;
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300738
Sri Deevie0d3baf2009-03-03 14:37:50 -0300739 spin_lock_irqsave(&dev->video_mode.slock, flags);
Hans Verkuil7c617132019-09-05 08:31:11 -0300740 list_add_tail(&buf->list, &vidq->active);
741 spin_unlock_irqrestore(&dev->video_mode.slock, flags);
742}
743
744static void return_all_buffers(struct cx231xx *dev,
745 enum vb2_buffer_state state)
746{
747 struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq;
748 struct cx231xx_buffer *buf, *node;
749 unsigned long flags;
750
751 spin_lock_irqsave(&dev->video_mode.slock, flags);
752 if (dev->USE_ISO)
753 dev->video_mode.isoc_ctl.buf = NULL;
754 else
755 dev->video_mode.bulk_ctl.buf = NULL;
756 list_for_each_entry_safe(buf, node, &vidq->active, list) {
757 list_del(&buf->list);
758 vb2_buffer_done(&buf->vb.vb2_buf, state);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300759 }
Sri Deevie0d3baf2009-03-03 14:37:50 -0300760 spin_unlock_irqrestore(&dev->video_mode.slock, flags);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300761}
762
Hans Verkuil7c617132019-09-05 08:31:11 -0300763static int start_streaming(struct vb2_queue *vq, unsigned int count)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300764{
Hans Verkuil7c617132019-09-05 08:31:11 -0300765 struct cx231xx *dev = vb2_get_drv_priv(vq);
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300766 struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq;
Hans Verkuil7c617132019-09-05 08:31:11 -0300767 int ret = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300768
Hans Verkuil7c617132019-09-05 08:31:11 -0300769 vidq->sequence = 0;
770 dev->mode_tv = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300771
Hans Verkuil7c617132019-09-05 08:31:11 -0300772 cx231xx_enable_analog_tuner(dev);
773 if (dev->USE_ISO)
774 ret = cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS,
775 CX231XX_NUM_BUFS,
776 dev->video_mode.max_pkt_size,
777 cx231xx_isoc_copy);
778 else
779 ret = cx231xx_init_bulk(dev, CX231XX_NUM_PACKETS,
780 CX231XX_NUM_BUFS,
781 dev->video_mode.max_pkt_size,
782 cx231xx_bulk_copy);
783 if (ret)
784 return_all_buffers(dev, VB2_BUF_STATE_QUEUED);
785 call_all(dev, video, s_stream, 1);
786 return ret;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300787}
788
Hans Verkuil7c617132019-09-05 08:31:11 -0300789static void stop_streaming(struct vb2_queue *vq)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300790{
Hans Verkuil7c617132019-09-05 08:31:11 -0300791 struct cx231xx *dev = vb2_get_drv_priv(vq);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300792
Hans Verkuil7c617132019-09-05 08:31:11 -0300793 call_all(dev, video, s_stream, 0);
794 return_all_buffers(dev, VB2_BUF_STATE_ERROR);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300795}
796
Hans Verkuil7c617132019-09-05 08:31:11 -0300797static struct vb2_ops cx231xx_video_qops = {
798 .queue_setup = queue_setup,
799 .buf_queue = buffer_queue,
800 .start_streaming = start_streaming,
801 .stop_streaming = stop_streaming,
802 .wait_prepare = vb2_ops_wait_prepare,
803 .wait_finish = vb2_ops_wait_finish,
Sri Deevie0d3baf2009-03-03 14:37:50 -0300804};
805
806/********************* v4l2 interface **************************************/
807
Sri Deevie0d3baf2009-03-03 14:37:50 -0300808void video_mux(struct cx231xx *dev, int index)
809{
Sri Deevie0d3baf2009-03-03 14:37:50 -0300810 dev->video_input = index;
811 dev->ctl_ainput = INPUT(index)->amux;
812
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300813 cx231xx_set_video_input_mux(dev, index);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300814
Hans Verkuil5325b422009-04-02 11:26:22 -0300815 cx25840_call(dev, video, s_routing, INPUT(index)->vmux, 0, 0);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300816
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300817 cx231xx_set_audio_input(dev, dev->ctl_ainput);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300818
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -0300819 dev_dbg(dev->dev, "video_mux : %d\n", index);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300820
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300821 /* do mode control overrides if required */
822 cx231xx_do_mode_ctrl_overrides(dev);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300823}
824
Sri Deevie0d3baf2009-03-03 14:37:50 -0300825/* ------------------------------------------------------------------
826 IOCTL vidioc handling
827 ------------------------------------------------------------------*/
828
829static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300830 struct v4l2_format *f)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300831{
Hans Verkuil7c617132019-09-05 08:31:11 -0300832 struct cx231xx *dev = video_drvdata(file);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300833
Sri Deevie0d3baf2009-03-03 14:37:50 -0300834 f->fmt.pix.width = dev->width;
835 f->fmt.pix.height = dev->height;
Joe Perches1ebcad72009-07-02 15:57:09 -0300836 f->fmt.pix.pixelformat = dev->format->fourcc;
837 f->fmt.pix.bytesperline = (dev->width * dev->format->depth + 7) >> 3;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300838 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * dev->height;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300839 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
840
841 f->fmt.pix.field = V4L2_FIELD_INTERLACED;
842
Sri Deevie0d3baf2009-03-03 14:37:50 -0300843 return 0;
844}
845
846static struct cx231xx_fmt *format_by_fourcc(unsigned int fourcc)
847{
848 unsigned int i;
849
850 for (i = 0; i < ARRAY_SIZE(format); i++)
851 if (format[i].fourcc == fourcc)
852 return &format[i];
853
854 return NULL;
855}
856
857static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300858 struct v4l2_format *f)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300859{
Hans Verkuil7c617132019-09-05 08:31:11 -0300860 struct cx231xx *dev = video_drvdata(file);
Trent Piepho9bd0e8d2009-05-30 21:45:46 -0300861 unsigned int width = f->fmt.pix.width;
862 unsigned int height = f->fmt.pix.height;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300863 unsigned int maxw = norm_maxw(dev);
864 unsigned int maxh = norm_maxh(dev);
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300865 struct cx231xx_fmt *fmt;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300866
867 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
868 if (!fmt) {
869 cx231xx_videodbg("Fourcc format (%08x) invalid.\n",
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300870 f->fmt.pix.pixelformat);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300871 return -EINVAL;
872 }
873
874 /* width must even because of the YUYV format
875 height must be even because of interlacing */
Trent Piepho9bd0e8d2009-05-30 21:45:46 -0300876 v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh, 1, 0);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300877
Sri Deevie0d3baf2009-03-03 14:37:50 -0300878 f->fmt.pix.width = width;
879 f->fmt.pix.height = height;
880 f->fmt.pix.pixelformat = fmt->fourcc;
Hans Verkuil8b735c12013-02-09 06:35:02 -0300881 f->fmt.pix.bytesperline = (width * fmt->depth + 7) >> 3;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300882 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height;
883 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
884 f->fmt.pix.field = V4L2_FIELD_INTERLACED;
885
886 return 0;
887}
888
889static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300890 struct v4l2_format *f)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300891{
Hans Verkuil7c617132019-09-05 08:31:11 -0300892 struct cx231xx *dev = video_drvdata(file);
Hans Verkuilebf984b2015-04-09 04:05:59 -0300893 struct v4l2_subdev_format format = {
894 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
895 };
Hans Verkuil7c617132019-09-05 08:31:11 -0300896 int rc;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300897
Hans Verkuil7c617132019-09-05 08:31:11 -0300898 rc = vidioc_try_fmt_vid_cap(file, priv, f);
899 if (rc)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300900 return rc;
901
Hans Verkuil7c617132019-09-05 08:31:11 -0300902 if (vb2_is_busy(&dev->vidq)) {
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -0300903 dev_err(dev->dev, "%s: queue busy\n", __func__);
Mauro Carvalho Chehab643800d2010-10-09 13:13:35 -0300904 return -EBUSY;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300905 }
906
Sri Deevie0d3baf2009-03-03 14:37:50 -0300907 /* set new image size */
908 dev->width = f->fmt.pix.width;
909 dev->height = f->fmt.pix.height;
Hans Verkuil7c617132019-09-05 08:31:11 -0300910 dev->format = format_by_fourcc(f->fmt.pix.pixelformat);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300911
Hans Verkuilebf984b2015-04-09 04:05:59 -0300912 v4l2_fill_mbus_format(&format.format, &f->fmt.pix, MEDIA_BUS_FMT_FIXED);
913 call_all(dev, pad, set_fmt, NULL, &format);
914 v4l2_fill_pix_format(&f->fmt.pix, &format.format);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300915
Sri Deevie0d3baf2009-03-03 14:37:50 -0300916 return rc;
917}
918
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300919static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300920{
Hans Verkuil7c617132019-09-05 08:31:11 -0300921 struct cx231xx *dev = video_drvdata(file);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300922
923 *id = dev->norm;
924 return 0;
925}
926
Hans Verkuil314527a2013-03-15 06:10:40 -0300927static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm)
Sri Deevie0d3baf2009-03-03 14:37:50 -0300928{
Hans Verkuil7c617132019-09-05 08:31:11 -0300929 struct cx231xx *dev = video_drvdata(file);
Hans Verkuilebf984b2015-04-09 04:05:59 -0300930 struct v4l2_subdev_format format = {
931 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
932 };
Sri Deevie0d3baf2009-03-03 14:37:50 -0300933
Hans Verkuil314527a2013-03-15 06:10:40 -0300934 if (dev->norm == norm)
Hans Verkuild61072a2013-01-29 10:50:54 -0300935 return 0;
936
Hans Verkuil7c617132019-09-05 08:31:11 -0300937 if (vb2_is_busy(&dev->vidq))
Hans Verkuild61072a2013-01-29 10:50:54 -0300938 return -EBUSY;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300939
Hans Verkuil314527a2013-03-15 06:10:40 -0300940 dev->norm = norm;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300941
Sri Deevie0d3baf2009-03-03 14:37:50 -0300942 /* Adjusts width/height, if needed */
Hans Verkuild61072a2013-01-29 10:50:54 -0300943 dev->width = 720;
944 dev->height = (dev->norm & V4L2_STD_625_50) ? 576 : 480;
Sri Deevie0d3baf2009-03-03 14:37:50 -0300945
Laurent Pinchart8774bed2014-04-28 16:53:01 -0300946 call_all(dev, video, s_std, dev->norm);
Devin Heitmueller435b4f72010-07-09 13:29:31 -0300947
948 /* We need to reset basic properties in the decoder related to
949 resolution (since a standard change effects things like the number
950 of lines in VACT, etc) */
Hans Verkuilebf984b2015-04-09 04:05:59 -0300951 format.format.code = MEDIA_BUS_FMT_FIXED;
952 format.format.width = dev->width;
953 format.format.height = dev->height;
954 call_all(dev, pad, set_fmt, NULL, &format);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300955
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -0300956 /* do mode control overrides */
957 cx231xx_do_mode_ctrl_overrides(dev);
Sri Deevie0d3baf2009-03-03 14:37:50 -0300958
959 return 0;
960}
961
962static const char *iname[] = {
963 [CX231XX_VMUX_COMPOSITE1] = "Composite1",
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300964 [CX231XX_VMUX_SVIDEO] = "S-Video",
Sri Deevie0d3baf2009-03-03 14:37:50 -0300965 [CX231XX_VMUX_TELEVISION] = "Television",
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -0300966 [CX231XX_VMUX_CABLE] = "Cable TV",
967 [CX231XX_VMUX_DVB] = "DVB",
Sri Deevie0d3baf2009-03-03 14:37:50 -0300968};
969
Mauro Carvalho Chehab61683092016-02-11 22:39:52 -0200970void cx231xx_v4l2_create_entities(struct cx231xx *dev)
971{
972#if defined(CONFIG_MEDIA_CONTROLLER)
973 int ret, i;
974
975 /* Create entities for each input connector */
976 for (i = 0; i < MAX_CX231XX_INPUT; i++) {
977 struct media_entity *ent = &dev->input_ent[i];
978
979 if (!INPUT(i)->type)
980 break;
981
982 ent->name = iname[INPUT(i)->type];
983 ent->flags = MEDIA_ENT_FL_CONNECTOR;
984 dev->input_pad[i].flags = MEDIA_PAD_FL_SOURCE;
985
986 switch (INPUT(i)->type) {
987 case CX231XX_VMUX_COMPOSITE1:
988 ent->function = MEDIA_ENT_F_CONN_COMPOSITE;
989 break;
990 case CX231XX_VMUX_SVIDEO:
991 ent->function = MEDIA_ENT_F_CONN_SVIDEO;
992 break;
993 case CX231XX_VMUX_TELEVISION:
994 case CX231XX_VMUX_CABLE:
995 case CX231XX_VMUX_DVB:
996 /* The DVB core will handle it */
997 if (dev->tuner_type == TUNER_ABSENT)
998 continue;
Mauro Carvalho Chehab06eeefe2017-05-18 08:13:28 -0300999 /* fall through */
Mauro Carvalho Chehab22d50e92016-02-12 09:17:14 -02001000 default: /* just to shut up a gcc warning */
Mauro Carvalho Chehab61683092016-02-11 22:39:52 -02001001 ent->function = MEDIA_ENT_F_CONN_RF;
1002 break;
1003 }
1004
1005 ret = media_entity_pads_init(ent, 1, &dev->input_pad[i]);
1006 if (ret < 0)
1007 pr_err("failed to initialize input pad[%d]!\n", i);
1008
1009 ret = media_device_register_entity(dev->media_dev, ent);
1010 if (ret < 0)
1011 pr_err("failed to register input entity %d!\n", i);
1012 }
1013#endif
1014}
1015
Hans Verkuilb86d1542013-01-29 13:16:06 -03001016int cx231xx_enum_input(struct file *file, void *priv,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001017 struct v4l2_input *i)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001018{
Hans Verkuil7c617132019-09-05 08:31:11 -03001019 struct cx231xx *dev = video_drvdata(file);
Devin Heitmuellerde99d532011-07-24 17:07:07 -03001020 u32 gen_stat;
Andrzej Hajdae54560d2015-09-24 11:00:18 -03001021 unsigned int n;
1022 int ret;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001023
1024 n = i->index;
1025 if (n >= MAX_CX231XX_INPUT)
1026 return -EINVAL;
1027 if (0 == INPUT(n)->type)
1028 return -EINVAL;
1029
1030 i->index = n;
1031 i->type = V4L2_INPUT_TYPE_CAMERA;
1032
Mauro Carvalho Chehabcc1e6312018-09-10 16:20:42 -04001033 strscpy(i->name, iname[INPUT(n)->type], sizeof(i->name));
Sri Deevie0d3baf2009-03-03 14:37:50 -03001034
1035 if ((CX231XX_VMUX_TELEVISION == INPUT(n)->type) ||
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001036 (CX231XX_VMUX_CABLE == INPUT(n)->type))
Sri Deevie0d3baf2009-03-03 14:37:50 -03001037 i->type = V4L2_INPUT_TYPE_TUNER;
1038
Hans Verkuil60acf182015-03-09 13:34:13 -03001039 i->std = dev->vdev.tvnorms;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001040
Devin Heitmuellerde99d532011-07-24 17:07:07 -03001041 /* If they are asking about the active input, read signal status */
1042 if (n == dev->video_input) {
1043 ret = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS,
1044 GEN_STAT, 2, &gen_stat, 4);
1045 if (ret > 0) {
1046 if ((gen_stat & FLD_VPRES) == 0x00)
1047 i->status |= V4L2_IN_ST_NO_SIGNAL;
1048 if ((gen_stat & FLD_HLOCK) == 0x00)
1049 i->status |= V4L2_IN_ST_NO_H_LOCK;
1050 }
1051 }
1052
Sri Deevie0d3baf2009-03-03 14:37:50 -03001053 return 0;
1054}
1055
Hans Verkuilb86d1542013-01-29 13:16:06 -03001056int cx231xx_g_input(struct file *file, void *priv, unsigned int *i)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001057{
Hans Verkuil7c617132019-09-05 08:31:11 -03001058 struct cx231xx *dev = video_drvdata(file);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001059
1060 *i = dev->video_input;
1061
1062 return 0;
1063}
1064
Hans Verkuilb86d1542013-01-29 13:16:06 -03001065int cx231xx_s_input(struct file *file, void *priv, unsigned int i)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001066{
Hans Verkuil7c617132019-09-05 08:31:11 -03001067 struct cx231xx *dev = video_drvdata(file);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001068
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001069 dev->mode_tv = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001070
1071 if (i >= MAX_CX231XX_INPUT)
1072 return -EINVAL;
1073 if (0 == INPUT(i)->type)
1074 return -EINVAL;
1075
Sri Deevie0d3baf2009-03-03 14:37:50 -03001076 video_mux(dev, i);
1077
Devin Heitmuellerc09d6692010-07-12 16:50:30 -03001078 if (INPUT(i)->type == CX231XX_VMUX_TELEVISION ||
1079 INPUT(i)->type == CX231XX_VMUX_CABLE) {
1080 /* There's a tuner, so reset the standard and put it on the
1081 last known frequency (since it was probably powered down
1082 until now */
Laurent Pinchart8774bed2014-04-28 16:53:01 -03001083 call_all(dev, video, s_std, dev->norm);
Devin Heitmuellerc09d6692010-07-12 16:50:30 -03001084 }
1085
Sri Deevie0d3baf2009-03-03 14:37:50 -03001086 return 0;
1087}
1088
Hans Verkuilb86d1542013-01-29 13:16:06 -03001089int cx231xx_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001090{
Hans Verkuil7c617132019-09-05 08:31:11 -03001091 struct cx231xx *dev = video_drvdata(file);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001092
1093 if (0 != t->index)
1094 return -EINVAL;
1095
Mauro Carvalho Chehabcc1e6312018-09-10 16:20:42 -04001096 strscpy(t->name, "Tuner", sizeof(t->name));
Sri Deevie0d3baf2009-03-03 14:37:50 -03001097
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001098 t->type = V4L2_TUNER_ANALOG_TV;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001099 t->capability = V4L2_TUNER_CAP_NORM;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001100 t->rangehigh = 0xffffffffUL;
1101 t->signal = 0xffff; /* LOCKED */
Hans Verkuilb251f952012-09-13 12:54:36 -03001102 call_all(dev, tuner, g_tuner, t);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001103
1104 return 0;
1105}
1106
Hans Verkuil2f73c7c2013-03-15 06:10:06 -03001107int cx231xx_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *t)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001108{
Sri Deevie0d3baf2009-03-03 14:37:50 -03001109 if (0 != t->index)
1110 return -EINVAL;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001111 return 0;
1112}
1113
Hans Verkuilb86d1542013-01-29 13:16:06 -03001114int cx231xx_g_frequency(struct file *file, void *priv,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001115 struct v4l2_frequency *f)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001116{
Hans Verkuil7c617132019-09-05 08:31:11 -03001117 struct cx231xx *dev = video_drvdata(file);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001118
Hans Verkuilb251f952012-09-13 12:54:36 -03001119 if (f->tuner)
1120 return -EINVAL;
1121
Sri Deevie0d3baf2009-03-03 14:37:50 -03001122 f->frequency = dev->ctl_freq;
1123
Sri Deevie0d3baf2009-03-03 14:37:50 -03001124 return 0;
1125}
1126
Hans Verkuilb86d1542013-01-29 13:16:06 -03001127int cx231xx_s_frequency(struct file *file, void *priv,
Hans Verkuilb530a442013-03-19 04:09:26 -03001128 const struct v4l2_frequency *f)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001129{
Hans Verkuil7c617132019-09-05 08:31:11 -03001130 struct cx231xx *dev = video_drvdata(file);
Hans Verkuilb530a442013-03-19 04:09:26 -03001131 struct v4l2_frequency new_freq = *f;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001132 int rc;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001133 u32 if_frequency = 5400000;
1134
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -03001135 dev_dbg(dev->dev,
Mauro Carvalho Chehabb7085c02014-11-02 07:21:44 -03001136 "Enter vidioc_s_frequency()f->frequency=%d;f->type=%d\n",
1137 f->frequency, f->type);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001138
Sri Deevie0d3baf2009-03-03 14:37:50 -03001139 if (0 != f->tuner)
1140 return -EINVAL;
1141
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001142 /* set pre channel change settings in DIF first */
1143 rc = cx231xx_tuner_pre_channel_change(dev);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001144
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001145 call_all(dev, tuner, s_frequency, f);
Hans Verkuilb530a442013-03-19 04:09:26 -03001146 call_all(dev, tuner, g_frequency, &new_freq);
1147 dev->ctl_freq = new_freq.frequency;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001148
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001149 /* set post channel change settings in DIF first */
1150 rc = cx231xx_tuner_post_channel_change(dev);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001151
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001152 if (dev->tuner_type == TUNER_NXP_TDA18271) {
1153 if (dev->norm & (V4L2_STD_MN | V4L2_STD_NTSC_443))
1154 if_frequency = 5400000; /*5.4MHz */
1155 else if (dev->norm & V4L2_STD_B)
1156 if_frequency = 6000000; /*6.0MHz */
1157 else if (dev->norm & (V4L2_STD_PAL_DK | V4L2_STD_SECAM_DK))
1158 if_frequency = 6900000; /*6.9MHz */
1159 else if (dev->norm & V4L2_STD_GH)
1160 if_frequency = 7100000; /*7.1MHz */
1161 else if (dev->norm & V4L2_STD_PAL_I)
1162 if_frequency = 7250000; /*7.25MHz */
1163 else if (dev->norm & V4L2_STD_SECAM_L)
1164 if_frequency = 6900000; /*6.9MHz */
1165 else if (dev->norm & V4L2_STD_SECAM_LC)
1166 if_frequency = 1250000; /*1.25MHz */
1167
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -03001168 dev_dbg(dev->dev,
Mauro Carvalho Chehabb7085c02014-11-02 07:21:44 -03001169 "if_frequency is set to %d\n", if_frequency);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001170 cx231xx_set_Colibri_For_LowIF(dev, if_frequency, 1, 1);
1171
1172 update_HH_register_after_set_DIF(dev);
1173 }
1174
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -03001175 dev_dbg(dev->dev, "Set New FREQUENCY to %d\n", f->frequency);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001176
1177 return rc;
1178}
1179
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001180#ifdef CONFIG_VIDEO_ADV_DEBUG
1181
1182int cx231xx_g_chip_info(struct file *file, void *fh,
1183 struct v4l2_dbg_chip_info *chip)
Hans Verkuilfddd14c2012-09-13 05:37:11 -03001184{
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001185 switch (chip->match.addr) {
1186 case 0: /* Cx231xx - internal registers */
1187 return 0;
1188 case 1: /* AFE - read byte */
Mauro Carvalho Chehabc0decac2018-09-10 08:19:14 -04001189 strscpy(chip->name, "AFE (byte)", sizeof(chip->name));
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001190 return 0;
1191 case 2: /* Video Block - read byte */
Mauro Carvalho Chehabc0decac2018-09-10 08:19:14 -04001192 strscpy(chip->name, "Video (byte)", sizeof(chip->name));
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001193 return 0;
1194 case 3: /* I2S block - read byte */
Mauro Carvalho Chehabc0decac2018-09-10 08:19:14 -04001195 strscpy(chip->name, "I2S (byte)", sizeof(chip->name));
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001196 return 0;
1197 case 4: /* AFE - read dword */
Mauro Carvalho Chehabc0decac2018-09-10 08:19:14 -04001198 strscpy(chip->name, "AFE (dword)", sizeof(chip->name));
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001199 return 0;
1200 case 5: /* Video Block - read dword */
Mauro Carvalho Chehabc0decac2018-09-10 08:19:14 -04001201 strscpy(chip->name, "Video (dword)", sizeof(chip->name));
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001202 return 0;
1203 case 6: /* I2S Block - read dword */
Mauro Carvalho Chehabc0decac2018-09-10 08:19:14 -04001204 strscpy(chip->name, "I2S (dword)", sizeof(chip->name));
Hans Verkuilfddd14c2012-09-13 05:37:11 -03001205 return 0;
1206 }
1207 return -EINVAL;
1208}
1209
Hans Verkuilb86d1542013-01-29 13:16:06 -03001210int cx231xx_g_register(struct file *file, void *priv,
Sri Deevie0d3baf2009-03-03 14:37:50 -03001211 struct v4l2_dbg_register *reg)
1212{
Hans Verkuil7c617132019-09-05 08:31:11 -03001213 struct cx231xx *dev = video_drvdata(file);
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001214 int ret;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001215 u8 value[4] = { 0, 0, 0, 0 };
1216 u32 data = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001217
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001218 switch (reg->match.addr) {
1219 case 0: /* Cx231xx - internal registers */
1220 ret = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER,
1221 (u16)reg->reg, value, 4);
1222 reg->val = value[0] | value[1] << 8 |
Colin Ian King32ae5922018-10-06 14:01:42 -04001223 value[2] << 16 | (u32)value[3] << 24;
Hans Verkuil04ae4cf2013-05-29 07:00:04 -03001224 reg->size = 4;
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001225 break;
1226 case 1: /* AFE - read byte */
1227 ret = cx231xx_read_i2c_data(dev, AFE_DEVICE_ADDRESS,
1228 (u16)reg->reg, 2, &data, 1);
1229 reg->val = data;
Hans Verkuil04ae4cf2013-05-29 07:00:04 -03001230 reg->size = 1;
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001231 break;
1232 case 2: /* Video Block - read byte */
1233 ret = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS,
1234 (u16)reg->reg, 2, &data, 1);
1235 reg->val = data;
Hans Verkuil04ae4cf2013-05-29 07:00:04 -03001236 reg->size = 1;
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001237 break;
1238 case 3: /* I2S block - read byte */
1239 ret = cx231xx_read_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
1240 (u16)reg->reg, 1, &data, 1);
1241 reg->val = data;
Hans Verkuil04ae4cf2013-05-29 07:00:04 -03001242 reg->size = 1;
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001243 break;
1244 case 4: /* AFE - read dword */
1245 ret = cx231xx_read_i2c_data(dev, AFE_DEVICE_ADDRESS,
1246 (u16)reg->reg, 2, &data, 4);
1247 reg->val = data;
Hans Verkuil04ae4cf2013-05-29 07:00:04 -03001248 reg->size = 4;
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001249 break;
1250 case 5: /* Video Block - read dword */
1251 ret = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS,
1252 (u16)reg->reg, 2, &data, 4);
1253 reg->val = data;
Hans Verkuil04ae4cf2013-05-29 07:00:04 -03001254 reg->size = 4;
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001255 break;
1256 case 6: /* I2S Block - read dword */
1257 ret = cx231xx_read_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
1258 (u16)reg->reg, 1, &data, 4);
1259 reg->val = data;
Hans Verkuil04ae4cf2013-05-29 07:00:04 -03001260 reg->size = 4;
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001261 break;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001262 default:
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001263 return -EINVAL;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001264 }
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001265 return ret < 0 ? ret : 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001266}
1267
Hans Verkuilb86d1542013-01-29 13:16:06 -03001268int cx231xx_s_register(struct file *file, void *priv,
Hans Verkuil977ba3b12013-03-24 08:28:46 -03001269 const struct v4l2_dbg_register *reg)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001270{
Hans Verkuil7c617132019-09-05 08:31:11 -03001271 struct cx231xx *dev = video_drvdata(file);
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001272 int ret;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001273 u8 data[4] = { 0, 0, 0, 0 };
Sri Deevie0d3baf2009-03-03 14:37:50 -03001274
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001275 switch (reg->match.addr) {
1276 case 0: /* cx231xx internal registers */
1277 data[0] = (u8) reg->val;
1278 data[1] = (u8) (reg->val >> 8);
1279 data[2] = (u8) (reg->val >> 16);
1280 data[3] = (u8) (reg->val >> 24);
1281 ret = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
1282 (u16)reg->reg, data, 4);
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001283 break;
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001284 case 1: /* AFE - write byte */
1285 ret = cx231xx_write_i2c_data(dev, AFE_DEVICE_ADDRESS,
1286 (u16)reg->reg, 2, reg->val, 1);
1287 break;
1288 case 2: /* Video Block - write byte */
1289 ret = cx231xx_write_i2c_data(dev, VID_BLK_I2C_ADDRESS,
1290 (u16)reg->reg, 2, reg->val, 1);
1291 break;
1292 case 3: /* I2S block - write byte */
1293 ret = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
1294 (u16)reg->reg, 1, reg->val, 1);
1295 break;
1296 case 4: /* AFE - write dword */
1297 ret = cx231xx_write_i2c_data(dev, AFE_DEVICE_ADDRESS,
1298 (u16)reg->reg, 2, reg->val, 4);
1299 break;
1300 case 5: /* Video Block - write dword */
1301 ret = cx231xx_write_i2c_data(dev, VID_BLK_I2C_ADDRESS,
1302 (u16)reg->reg, 2, reg->val, 4);
1303 break;
1304 case 6: /* I2S block - write dword */
1305 ret = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
1306 (u16)reg->reg, 1, reg->val, 4);
1307 break;
1308 default:
1309 return -EINVAL;
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001310 }
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001311 return ret < 0 ? ret : 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001312}
1313#endif
1314
Hans Verkuil5200ab62018-10-04 17:38:15 -04001315static int vidioc_g_pixelaspect(struct file *file, void *priv,
1316 int type, struct v4l2_fract *f)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001317{
Hans Verkuil7c617132019-09-05 08:31:11 -03001318 struct cx231xx *dev = video_drvdata(file);
Hans Verkuile25cb202015-11-30 10:03:30 -02001319 bool is_50hz = dev->norm & V4L2_STD_625_50;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001320
Hans Verkuil5200ab62018-10-04 17:38:15 -04001321 if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001322 return -EINVAL;
1323
Hans Verkuil5200ab62018-10-04 17:38:15 -04001324 f->numerator = is_50hz ? 54 : 11;
1325 f->denominator = is_50hz ? 59 : 10;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001326
1327 return 0;
1328}
1329
Hans Verkuilee10dc32018-10-04 17:06:32 -04001330static int vidioc_g_selection(struct file *file, void *priv,
1331 struct v4l2_selection *s)
1332{
Hans Verkuil7c617132019-09-05 08:31:11 -03001333 struct cx231xx *dev = video_drvdata(file);
Hans Verkuilee10dc32018-10-04 17:06:32 -04001334
1335 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1336 return -EINVAL;
1337
1338 switch (s->target) {
1339 case V4L2_SEL_TGT_CROP_BOUNDS:
1340 case V4L2_SEL_TGT_CROP_DEFAULT:
1341 s->r.left = 0;
1342 s->r.top = 0;
1343 s->r.width = dev->width;
1344 s->r.height = dev->height;
1345 break;
1346 default:
1347 return -EINVAL;
1348 }
1349 return 0;
1350}
1351
Hans Verkuilbc087342013-01-29 12:52:33 -03001352int cx231xx_querycap(struct file *file, void *priv,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001353 struct v4l2_capability *cap)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001354{
Hans Verkuil7c617132019-09-05 08:31:11 -03001355 struct cx231xx *dev = video_drvdata(file);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001356
Mauro Carvalho Chehabc0decac2018-09-10 08:19:14 -04001357 strscpy(cap->driver, "cx231xx", sizeof(cap->driver));
1358 strscpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card));
Mauro Carvalho Chehab2c6beca2009-03-22 08:53:36 -03001359 usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
Hans Verkuil8c3854d2019-06-04 07:19:53 -04001360 cap->capabilities = V4L2_CAP_READWRITE |
Hans Verkuil4bc837d2012-09-13 05:29:12 -03001361 V4L2_CAP_VBI_CAPTURE | V4L2_CAP_VIDEO_CAPTURE |
Hans Verkuil530e01e2013-01-29 12:32:20 -03001362 V4L2_CAP_STREAMING | V4L2_CAP_DEVICE_CAPS;
Hans Verkuil60acf182015-03-09 13:34:13 -03001363 if (video_is_registered(&dev->radio_dev))
Hans Verkuil530e01e2013-01-29 12:32:20 -03001364 cap->capabilities |= V4L2_CAP_RADIO;
Hans Verkuil8c3854d2019-06-04 07:19:53 -04001365 if (dev->tuner_type != TUNER_ABSENT)
1366 cap->capabilities |= V4L2_CAP_TUNER;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001367
1368 return 0;
1369}
1370
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001371static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
1372 struct v4l2_fmtdesc *f)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001373{
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001374 if (unlikely(f->index >= ARRAY_SIZE(format)))
Sri Deevie0d3baf2009-03-03 14:37:50 -03001375 return -EINVAL;
1376
Sri Deevie0d3baf2009-03-03 14:37:50 -03001377 f->pixelformat = format[f->index].fourcc;
1378
1379 return 0;
1380}
1381
Sri Deevie0d3baf2009-03-03 14:37:50 -03001382/* RAW VBI ioctls */
1383
1384static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001385 struct v4l2_format *f)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001386{
Hans Verkuil7c617132019-09-05 08:31:11 -03001387 struct cx231xx *dev = video_drvdata(file);
Hans Verkuil62647222013-02-09 06:41:11 -03001388
Devin Heitmuelleradc03562010-07-08 13:12:47 -03001389 f->fmt.vbi.sampling_rate = 6750000 * 4;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001390 f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
1391 f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
Devin Heitmuelleradc03562010-07-08 13:12:47 -03001392 f->fmt.vbi.offset = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001393 f->fmt.vbi.start[0] = (dev->norm & V4L2_STD_625_50) ?
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001394 PAL_VBI_START_LINE : NTSC_VBI_START_LINE;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001395 f->fmt.vbi.count[0] = (dev->norm & V4L2_STD_625_50) ?
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001396 PAL_VBI_LINES : NTSC_VBI_LINES;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001397 f->fmt.vbi.start[1] = (dev->norm & V4L2_STD_625_50) ?
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001398 PAL_VBI_START_LINE + 312 : NTSC_VBI_START_LINE + 263;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001399 f->fmt.vbi.count[1] = f->fmt.vbi.count[0];
Hans Verkuil62647222013-02-09 06:41:11 -03001400 memset(f->fmt.vbi.reserved, 0, sizeof(f->fmt.vbi.reserved));
Sri Deevie0d3baf2009-03-03 14:37:50 -03001401
1402 return 0;
1403
1404}
1405
1406static int vidioc_try_fmt_vbi_cap(struct file *file, void *priv,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001407 struct v4l2_format *f)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001408{
Hans Verkuil7c617132019-09-05 08:31:11 -03001409 struct cx231xx *dev = video_drvdata(file);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001410
Devin Heitmuelleradc03562010-07-08 13:12:47 -03001411 f->fmt.vbi.sampling_rate = 6750000 * 4;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001412 f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
1413 f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
Devin Heitmuelleradc03562010-07-08 13:12:47 -03001414 f->fmt.vbi.offset = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001415 f->fmt.vbi.flags = 0;
1416 f->fmt.vbi.start[0] = (dev->norm & V4L2_STD_625_50) ?
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001417 PAL_VBI_START_LINE : NTSC_VBI_START_LINE;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001418 f->fmt.vbi.count[0] = (dev->norm & V4L2_STD_625_50) ?
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001419 PAL_VBI_LINES : NTSC_VBI_LINES;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001420 f->fmt.vbi.start[1] = (dev->norm & V4L2_STD_625_50) ?
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001421 PAL_VBI_START_LINE + 312 : NTSC_VBI_START_LINE + 263;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001422 f->fmt.vbi.count[1] = f->fmt.vbi.count[0];
Hans Verkuil62647222013-02-09 06:41:11 -03001423 memset(f->fmt.vbi.reserved, 0, sizeof(f->fmt.vbi.reserved));
Sri Deevie0d3baf2009-03-03 14:37:50 -03001424
1425 return 0;
1426
1427}
1428
Hans Verkuil62647222013-02-09 06:41:11 -03001429static int vidioc_s_fmt_vbi_cap(struct file *file, void *priv,
1430 struct v4l2_format *f)
1431{
Hans Verkuil62647222013-02-09 06:41:11 -03001432 return vidioc_try_fmt_vbi_cap(file, priv, f);
1433}
1434
Sri Deevie0d3baf2009-03-03 14:37:50 -03001435/* ----------------------------------------------------------- */
1436/* RADIO ESPECIFIC IOCTLS */
1437/* ----------------------------------------------------------- */
1438
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001439static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001440{
Hans Verkuil7c617132019-09-05 08:31:11 -03001441 struct cx231xx *dev = video_drvdata(file);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001442
Hans Verkuil530e01e2013-01-29 12:32:20 -03001443 if (t->index)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001444 return -EINVAL;
1445
Mauro Carvalho Chehabcc1e6312018-09-10 16:20:42 -04001446 strscpy(t->name, "Radio", sizeof(t->name));
Sri Deevie0d3baf2009-03-03 14:37:50 -03001447
Hans Verkuil530e01e2013-01-29 12:32:20 -03001448 call_all(dev, tuner, g_tuner, t);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001449
1450 return 0;
1451}
Hans Verkuil2f73c7c2013-03-15 06:10:06 -03001452static int radio_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *t)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001453{
Hans Verkuil7c617132019-09-05 08:31:11 -03001454 struct cx231xx *dev = video_drvdata(file);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001455
Hans Verkuilb86d1542013-01-29 13:16:06 -03001456 if (t->index)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001457 return -EINVAL;
1458
Sri Deevib1196122009-03-20 23:33:48 -03001459 call_all(dev, tuner, s_tuner, t);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001460
1461 return 0;
1462}
1463
Sri Deevie0d3baf2009-03-03 14:37:50 -03001464/*
1465 * cx231xx_v4l2_open()
1466 * inits the device and starts isoc transfer
1467 */
1468static int cx231xx_v4l2_open(struct file *filp)
1469{
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001470 struct video_device *vdev = video_devdata(filp);
1471 struct cx231xx *dev = video_drvdata(filp);
Hans Verkuil7c617132019-09-05 08:31:11 -03001472 int ret;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001473
Hans Verkuil7c617132019-09-05 08:31:11 -03001474 if (mutex_lock_interruptible(&dev->lock))
Hans Verkuil1f7e0732012-06-24 06:43:02 -03001475 return -ERESTARTSYS;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001476
Hans Verkuil7c617132019-09-05 08:31:11 -03001477 ret = v4l2_fh_open(filp);
1478 if (ret) {
1479 mutex_unlock(&dev->lock);
1480 return ret;
1481 }
1482
1483 if (dev->users++ == 0) {
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001484 /* Power up in Analog TV mode */
Mauro Carvalho Chehab2f861382011-01-31 22:12:15 -03001485 if (dev->board.external_av)
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001486 cx231xx_set_power_mode(dev,
1487 POLARIS_AVMODE_ENXTERNAL_AV);
1488 else
1489 cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001490
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001491 /* set video alternate setting */
1492 cx231xx_set_video_alternate(dev);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001493
1494 /* Needed, since GPIO might have disabled power of
1495 some i2c device */
1496 cx231xx_config_i2c(dev);
1497
1498 /* device needs to be initialized before isoc transfer */
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001499 dev->video_input = dev->video_input > 2 ? 2 : dev->video_input;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001500 }
Hans Verkuil7c617132019-09-05 08:31:11 -03001501
1502 if (vdev->vfl_type == VFL_TYPE_RADIO) {
Sri Deevie0d3baf2009-03-03 14:37:50 -03001503 cx231xx_videodbg("video_open: setting radio device\n");
1504
1505 /* cx231xx_start_radio(dev); */
1506
Sri Deevib1196122009-03-20 23:33:48 -03001507 call_all(dev, tuner, s_radio);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001508 }
Hans Verkuil7c617132019-09-05 08:31:11 -03001509 if (vdev->vfl_type == VFL_TYPE_VBI) {
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03001510 /* Set the required alternate setting VBI interface works in
1511 Bulk mode only */
Mauro Carvalho Chehab2f861382011-01-31 22:12:15 -03001512 cx231xx_set_alt_setting(dev, INDEX_VANC, 0);
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001513 }
Hans Verkuil1f7e0732012-06-24 06:43:02 -03001514 mutex_unlock(&dev->lock);
Peter Senna Tschudin4df16f72014-05-31 13:30:52 -03001515 return 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001516}
1517
1518/*
1519 * cx231xx_realease_resources()
1520 * unregisters the v4l2,i2c and usb devices
Geert Uytterhoeven6b338c72019-08-14 06:12:31 -03001521 * called when the device gets disconnected or at module unload
Sri Deevie0d3baf2009-03-03 14:37:50 -03001522*/
1523void cx231xx_release_analog_resources(struct cx231xx *dev)
1524{
1525
1526 /*FIXME: I2C IR should be disconnected */
1527
Hans Verkuil60acf182015-03-09 13:34:13 -03001528 if (video_is_registered(&dev->radio_dev))
1529 video_unregister_device(&dev->radio_dev);
1530 if (video_is_registered(&dev->vbi_dev)) {
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -03001531 dev_info(dev->dev, "V4L2 device %s deregistered\n",
Hans Verkuil60acf182015-03-09 13:34:13 -03001532 video_device_node_name(&dev->vbi_dev));
1533 video_unregister_device(&dev->vbi_dev);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001534 }
Hans Verkuil60acf182015-03-09 13:34:13 -03001535 if (video_is_registered(&dev->vdev)) {
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -03001536 dev_info(dev->dev, "V4L2 device %s deregistered\n",
Hans Verkuil60acf182015-03-09 13:34:13 -03001537 video_device_node_name(&dev->vdev));
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001538
Mauro Carvalho Chehab2f861382011-01-31 22:12:15 -03001539 if (dev->board.has_417)
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001540 cx231xx_417_unregister(dev);
1541
Hans Verkuil60acf182015-03-09 13:34:13 -03001542 video_unregister_device(&dev->vdev);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001543 }
Hans Verkuild2370f82012-09-17 07:22:09 -03001544 v4l2_ctrl_handler_free(&dev->ctrl_handler);
1545 v4l2_ctrl_handler_free(&dev->radio_ctrl_handler);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001546}
1547
1548/*
Hans Verkuil1f7e0732012-06-24 06:43:02 -03001549 * cx231xx_close()
Sri Deevie0d3baf2009-03-03 14:37:50 -03001550 * stops streaming and deallocates all resources allocated by the v4l2
1551 * calls and ioctls
1552 */
Hans Verkuil1f7e0732012-06-24 06:43:02 -03001553static int cx231xx_close(struct file *filp)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001554{
Hans Verkuil7c617132019-09-05 08:31:11 -03001555 struct cx231xx *dev = video_drvdata(filp);
1556 struct video_device *vdev = video_devdata(filp);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001557
Hans Verkuil7c617132019-09-05 08:31:11 -03001558 _vb2_fop_release(filp, NULL);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001559
Hans Verkuil7c617132019-09-05 08:31:11 -03001560 if (--dev->users == 0) {
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001561 /* Save some power by putting tuner to sleep */
Hans Verkuil3aab15a2018-02-21 02:49:25 -05001562 call_all(dev, tuner, standby);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001563
1564 /* do this before setting alternate! */
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001565 if (dev->USE_ISO)
1566 cx231xx_uninit_isoc(dev);
1567 else
1568 cx231xx_uninit_bulk(dev);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001569 cx231xx_set_mode(dev, CX231XX_SUSPEND);
Hans Verkuil7c617132019-09-05 08:31:11 -03001570 }
Sri Deevie0d3baf2009-03-03 14:37:50 -03001571
Hans Verkuil7c617132019-09-05 08:31:11 -03001572 /*
1573 * To workaround error number=-71 on EP0 for VideoGrabber,
1574 * need exclude following.
1575 * FIXME: It is probably safe to remove most of these, as we're
1576 * now avoiding the alternate setting for INDEX_VANC
1577 */
1578 if (!dev->board.no_alt_vanc && vdev->vfl_type == VFL_TYPE_VBI) {
1579 /* do this before setting alternate! */
1580 cx231xx_uninit_vbi_isoc(dev);
1581
1582 /* set alternate 0 */
1583 if (!dev->vbi_or_sliced_cc_mode)
1584 cx231xx_set_alt_setting(dev, INDEX_VANC, 0);
1585 else
1586 cx231xx_set_alt_setting(dev, INDEX_HANC, 0);
1587
1588 wake_up_interruptible_nr(&dev->open, 1);
1589 return 0;
1590 }
1591
1592 if (dev->users == 0) {
Sri Deevie0d3baf2009-03-03 14:37:50 -03001593 /* set alternate 0 */
1594 cx231xx_set_alt_setting(dev, INDEX_VIDEO, 0);
1595 }
Hans Verkuil7c617132019-09-05 08:31:11 -03001596
Steven Rostedt543409a2015-08-20 18:03:43 -03001597 wake_up_interruptible(&dev->open);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001598 return 0;
1599}
1600
Hans Verkuil1f7e0732012-06-24 06:43:02 -03001601static int cx231xx_v4l2_close(struct file *filp)
1602{
Hans Verkuil7c617132019-09-05 08:31:11 -03001603 struct cx231xx *dev = video_drvdata(filp);
Hans Verkuil1f7e0732012-06-24 06:43:02 -03001604 int rc;
1605
1606 mutex_lock(&dev->lock);
1607 rc = cx231xx_close(filp);
1608 mutex_unlock(&dev->lock);
1609 return rc;
1610}
1611
Sri Deevie0d3baf2009-03-03 14:37:50 -03001612static const struct v4l2_file_operations cx231xx_v4l_fops = {
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03001613 .owner = THIS_MODULE,
1614 .open = cx231xx_v4l2_open,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001615 .release = cx231xx_v4l2_close,
Hans Verkuil7c617132019-09-05 08:31:11 -03001616 .read = vb2_fop_read,
1617 .poll = vb2_fop_poll,
1618 .mmap = vb2_fop_mmap,
Mauro Carvalho Chehab643800d2010-10-09 13:13:35 -03001619 .unlocked_ioctl = video_ioctl2,
Sri Deevie0d3baf2009-03-03 14:37:50 -03001620};
1621
1622static const struct v4l2_ioctl_ops video_ioctl_ops = {
Hans Verkuilbc087342013-01-29 12:52:33 -03001623 .vidioc_querycap = cx231xx_querycap,
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03001624 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1625 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1626 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1627 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
1628 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
1629 .vidioc_try_fmt_vbi_cap = vidioc_try_fmt_vbi_cap,
Hans Verkuil62647222013-02-09 06:41:11 -03001630 .vidioc_s_fmt_vbi_cap = vidioc_s_fmt_vbi_cap,
Hans Verkuil5200ab62018-10-04 17:38:15 -04001631 .vidioc_g_pixelaspect = vidioc_g_pixelaspect,
Hans Verkuilee10dc32018-10-04 17:06:32 -04001632 .vidioc_g_selection = vidioc_g_selection,
Hans Verkuil7c617132019-09-05 08:31:11 -03001633 .vidioc_reqbufs = vb2_ioctl_reqbufs,
1634 .vidioc_querybuf = vb2_ioctl_querybuf,
1635 .vidioc_qbuf = vb2_ioctl_qbuf,
1636 .vidioc_dqbuf = vb2_ioctl_dqbuf,
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03001637 .vidioc_s_std = vidioc_s_std,
1638 .vidioc_g_std = vidioc_g_std,
Hans Verkuilb86d1542013-01-29 13:16:06 -03001639 .vidioc_enum_input = cx231xx_enum_input,
1640 .vidioc_g_input = cx231xx_g_input,
1641 .vidioc_s_input = cx231xx_s_input,
Hans Verkuil7c617132019-09-05 08:31:11 -03001642 .vidioc_streamon = vb2_ioctl_streamon,
1643 .vidioc_streamoff = vb2_ioctl_streamoff,
Hans Verkuilb86d1542013-01-29 13:16:06 -03001644 .vidioc_g_tuner = cx231xx_g_tuner,
1645 .vidioc_s_tuner = cx231xx_s_tuner,
1646 .vidioc_g_frequency = cx231xx_g_frequency,
1647 .vidioc_s_frequency = cx231xx_s_frequency,
Sri Deevie0d3baf2009-03-03 14:37:50 -03001648#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001649 .vidioc_g_chip_info = cx231xx_g_chip_info,
Hans Verkuilb86d1542013-01-29 13:16:06 -03001650 .vidioc_g_register = cx231xx_g_register,
1651 .vidioc_s_register = cx231xx_s_register,
Sri Deevie0d3baf2009-03-03 14:37:50 -03001652#endif
Hans Verkuil1d08a4f2012-09-17 07:31:04 -03001653 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
1654 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Sri Deevie0d3baf2009-03-03 14:37:50 -03001655};
1656
1657static struct video_device cx231xx_vbi_template;
1658
1659static const struct video_device cx231xx_video_template = {
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03001660 .fops = &cx231xx_v4l_fops,
Hans Verkuil60acf182015-03-09 13:34:13 -03001661 .release = video_device_release_empty,
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03001662 .ioctl_ops = &video_ioctl_ops,
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03001663 .tvnorms = V4L2_STD_ALL,
Sri Deevie0d3baf2009-03-03 14:37:50 -03001664};
1665
1666static const struct v4l2_file_operations radio_fops = {
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03001667 .owner = THIS_MODULE,
1668 .open = cx231xx_v4l2_open,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001669 .release = cx231xx_v4l2_close,
Hans Verkuil1d08a4f2012-09-17 07:31:04 -03001670 .poll = v4l2_ctrl_poll,
Hans Verkuil1265f082012-09-17 09:26:46 -03001671 .unlocked_ioctl = video_ioctl2,
Sri Deevie0d3baf2009-03-03 14:37:50 -03001672};
1673
1674static const struct v4l2_ioctl_ops radio_ioctl_ops = {
Hans Verkuilbc087342013-01-29 12:52:33 -03001675 .vidioc_querycap = cx231xx_querycap,
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03001676 .vidioc_g_tuner = radio_g_tuner,
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03001677 .vidioc_s_tuner = radio_s_tuner,
Hans Verkuilb86d1542013-01-29 13:16:06 -03001678 .vidioc_g_frequency = cx231xx_g_frequency,
1679 .vidioc_s_frequency = cx231xx_s_frequency,
Sri Deevie0d3baf2009-03-03 14:37:50 -03001680#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuil08fe9f72013-05-29 06:59:43 -03001681 .vidioc_g_chip_info = cx231xx_g_chip_info,
Hans Verkuilb86d1542013-01-29 13:16:06 -03001682 .vidioc_g_register = cx231xx_g_register,
1683 .vidioc_s_register = cx231xx_s_register,
Sri Deevie0d3baf2009-03-03 14:37:50 -03001684#endif
Hans Verkuil1d08a4f2012-09-17 07:31:04 -03001685 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
1686 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Sri Deevie0d3baf2009-03-03 14:37:50 -03001687};
1688
1689static struct video_device cx231xx_radio_template = {
Mauro Carvalho Chehabcde43622009-03-03 13:31:36 -03001690 .name = "cx231xx-radio",
1691 .fops = &radio_fops,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001692 .ioctl_ops = &radio_ioctl_ops,
Sri Deevie0d3baf2009-03-03 14:37:50 -03001693};
1694
1695/******************************** usb interface ******************************/
1696
Hans Verkuil60acf182015-03-09 13:34:13 -03001697static void cx231xx_vdev_init(struct cx231xx *dev,
1698 struct video_device *vfd,
1699 const struct video_device *template,
1700 const char *type_name)
Sri Deevie0d3baf2009-03-03 14:37:50 -03001701{
Sri Deevie0d3baf2009-03-03 14:37:50 -03001702 *vfd = *template;
Sri Deevib1196122009-03-20 23:33:48 -03001703 vfd->v4l2_dev = &dev->v4l2_dev;
Hans Verkuil60acf182015-03-09 13:34:13 -03001704 vfd->release = video_device_release_empty;
Mauro Carvalho Chehab643800d2010-10-09 13:13:35 -03001705 vfd->lock = &dev->lock;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001706
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001707 snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001708
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001709 video_set_drvdata(vfd, dev);
Hans Verkuil06c46002012-09-13 06:17:47 -03001710 if (dev->tuner_type == TUNER_ABSENT) {
1711 v4l2_disable_ioctl(vfd, VIDIOC_G_FREQUENCY);
1712 v4l2_disable_ioctl(vfd, VIDIOC_S_FREQUENCY);
1713 v4l2_disable_ioctl(vfd, VIDIOC_G_TUNER);
1714 v4l2_disable_ioctl(vfd, VIDIOC_S_TUNER);
1715 }
Sri Deevie0d3baf2009-03-03 14:37:50 -03001716}
1717
1718int cx231xx_register_analog_devices(struct cx231xx *dev)
1719{
Hans Verkuil7c617132019-09-05 08:31:11 -03001720 struct vb2_queue *q;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001721 int ret;
1722
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -03001723 dev_info(dev->dev, "v4l2 driver version %s\n", CX231XX_VERSION);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001724
1725 /* set default norm */
Hans Verkuila25a70122012-09-17 08:30:07 -03001726 dev->norm = V4L2_STD_PAL;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001727 dev->width = norm_maxw(dev);
1728 dev->height = norm_maxh(dev);
1729 dev->interlaced = 0;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001730
1731 /* Analog specific initialization */
1732 dev->format = &format[0];
Devin Heitmueller6e6a2ba2010-07-12 15:34:57 -03001733
1734 /* Set the initial input */
1735 video_mux(dev, dev->video_input);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001736
Laurent Pinchart8774bed2014-04-28 16:53:01 -03001737 call_all(dev, video, s_std, dev->norm);
Hans Verkuild61072a2013-01-29 10:50:54 -03001738
Hans Verkuild2370f82012-09-17 07:22:09 -03001739 v4l2_ctrl_handler_init(&dev->ctrl_handler, 10);
1740 v4l2_ctrl_handler_init(&dev->radio_ctrl_handler, 5);
1741
1742 if (dev->sd_cx25840) {
1743 v4l2_ctrl_add_handler(&dev->ctrl_handler,
Hans Verkuilda1b1ae2018-05-21 04:54:36 -04001744 dev->sd_cx25840->ctrl_handler, NULL, true);
Hans Verkuild2370f82012-09-17 07:22:09 -03001745 v4l2_ctrl_add_handler(&dev->radio_ctrl_handler,
1746 dev->sd_cx25840->ctrl_handler,
Hans Verkuilda1b1ae2018-05-21 04:54:36 -04001747 v4l2_ctrl_radio_filter, true);
Hans Verkuild2370f82012-09-17 07:22:09 -03001748 }
1749
1750 if (dev->ctrl_handler.error)
1751 return dev->ctrl_handler.error;
1752 if (dev->radio_ctrl_handler.error)
1753 return dev->radio_ctrl_handler.error;
Sri Deevie0d3baf2009-03-03 14:37:50 -03001754
1755 /* enable vbi capturing */
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001756 /* write code here... */
Sri Deevie0d3baf2009-03-03 14:37:50 -03001757
1758 /* allocate and fill video video_device struct */
Hans Verkuil60acf182015-03-09 13:34:13 -03001759 cx231xx_vdev_init(dev, &dev->vdev, &cx231xx_video_template, "video");
Mauro Carvalho Chehabb6a40e72015-01-03 16:08:07 -03001760#if defined(CONFIG_MEDIA_CONTROLLER)
1761 dev->video_pad.flags = MEDIA_PAD_FL_SINK;
Mauro Carvalho Chehabab22e772015-12-11 07:44:40 -02001762 ret = media_entity_pads_init(&dev->vdev.entity, 1, &dev->video_pad);
Mauro Carvalho Chehabb6a40e72015-01-03 16:08:07 -03001763 if (ret < 0)
1764 dev_err(dev->dev, "failed to initialize video media entity!\n");
1765#endif
Hans Verkuil60acf182015-03-09 13:34:13 -03001766 dev->vdev.ctrl_handler = &dev->ctrl_handler;
Hans Verkuil7c617132019-09-05 08:31:11 -03001767
1768 q = &dev->vidq;
1769 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1770 q->io_modes = VB2_USERPTR | VB2_MMAP | VB2_DMABUF | VB2_READ;
1771 q->drv_priv = dev;
1772 q->buf_struct_size = sizeof(struct cx231xx_buffer);
1773 q->ops = &cx231xx_video_qops;
1774 q->mem_ops = &vb2_vmalloc_memops;
1775 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1776 q->min_buffers_needed = 1;
1777 q->lock = &dev->lock;
1778 ret = vb2_queue_init(q);
1779 if (ret)
1780 return ret;
1781 dev->vdev.queue = q;
Hans Verkuil8c3854d2019-06-04 07:19:53 -04001782 dev->vdev.device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
1783 V4L2_CAP_VIDEO_CAPTURE;
1784 if (dev->tuner_type != TUNER_ABSENT)
1785 dev->vdev.device_caps |= V4L2_CAP_TUNER;
1786
Sri Deevie0d3baf2009-03-03 14:37:50 -03001787 /* register v4l2 video video_device */
Hans Verkuil7fbbbc72020-02-03 12:41:14 +01001788 ret = video_register_device(&dev->vdev, VFL_TYPE_VIDEO,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001789 video_nr[dev->devno]);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001790 if (ret) {
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -03001791 dev_err(dev->dev,
Mauro Carvalho Chehabb7085c02014-11-02 07:21:44 -03001792 "unable to register video device (error=%i).\n",
Mauro Carvalho Chehabed0e3722014-11-01 08:59:03 -03001793 ret);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001794 return ret;
1795 }
1796
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -03001797 dev_info(dev->dev, "Registered video device %s [v4l2]\n",
Hans Verkuil60acf182015-03-09 13:34:13 -03001798 video_device_node_name(&dev->vdev));
Sri Deevie0d3baf2009-03-03 14:37:50 -03001799
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001800 /* Initialize VBI template */
Ezequiel Garcia3724dde2012-10-23 15:57:05 -03001801 cx231xx_vbi_template = cx231xx_video_template;
Mauro Carvalho Chehabcc1e6312018-09-10 16:20:42 -04001802 strscpy(cx231xx_vbi_template.name, "cx231xx-vbi",
1803 sizeof(cx231xx_vbi_template.name));
Sri Deevie0d3baf2009-03-03 14:37:50 -03001804
1805 /* Allocate and fill vbi video_device struct */
Hans Verkuil60acf182015-03-09 13:34:13 -03001806 cx231xx_vdev_init(dev, &dev->vbi_dev, &cx231xx_vbi_template, "vbi");
Sri Deevie0d3baf2009-03-03 14:37:50 -03001807
Mauro Carvalho Chehabb6a40e72015-01-03 16:08:07 -03001808#if defined(CONFIG_MEDIA_CONTROLLER)
1809 dev->vbi_pad.flags = MEDIA_PAD_FL_SINK;
Mauro Carvalho Chehabab22e772015-12-11 07:44:40 -02001810 ret = media_entity_pads_init(&dev->vbi_dev.entity, 1, &dev->vbi_pad);
Mauro Carvalho Chehabb6a40e72015-01-03 16:08:07 -03001811 if (ret < 0)
1812 dev_err(dev->dev, "failed to initialize vbi media entity!\n");
1813#endif
Hans Verkuil60acf182015-03-09 13:34:13 -03001814 dev->vbi_dev.ctrl_handler = &dev->ctrl_handler;
Hans Verkuil7c617132019-09-05 08:31:11 -03001815
1816 q = &dev->vbiq;
1817 q->type = V4L2_BUF_TYPE_VBI_CAPTURE;
1818 q->io_modes = VB2_USERPTR | VB2_MMAP | VB2_DMABUF | VB2_READ;
1819 q->drv_priv = dev;
1820 q->buf_struct_size = sizeof(struct cx231xx_buffer);
1821 q->ops = &cx231xx_vbi_qops;
1822 q->mem_ops = &vb2_vmalloc_memops;
1823 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1824 q->min_buffers_needed = 1;
1825 q->lock = &dev->lock;
1826 ret = vb2_queue_init(q);
1827 if (ret)
1828 return ret;
1829 dev->vbi_dev.queue = q;
Hans Verkuil8c3854d2019-06-04 07:19:53 -04001830 dev->vbi_dev.device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
1831 V4L2_CAP_VBI_CAPTURE;
1832 if (dev->tuner_type != TUNER_ABSENT)
1833 dev->vbi_dev.device_caps |= V4L2_CAP_TUNER;
1834
Sri Deevie0d3baf2009-03-03 14:37:50 -03001835 /* register v4l2 vbi video_device */
Hans Verkuil60acf182015-03-09 13:34:13 -03001836 ret = video_register_device(&dev->vbi_dev, VFL_TYPE_VBI,
Mauro Carvalho Chehab84b5dbf2009-03-03 06:14:34 -03001837 vbi_nr[dev->devno]);
Sri Deevie0d3baf2009-03-03 14:37:50 -03001838 if (ret < 0) {
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -03001839 dev_err(dev->dev, "unable to register vbi device\n");
Sri Deevie0d3baf2009-03-03 14:37:50 -03001840 return ret;
1841 }
1842
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -03001843 dev_info(dev->dev, "Registered VBI device %s\n",
Hans Verkuil60acf182015-03-09 13:34:13 -03001844 video_device_node_name(&dev->vbi_dev));
Sri Deevie0d3baf2009-03-03 14:37:50 -03001845
1846 if (cx231xx_boards[dev->model].radio.type == CX231XX_RADIO) {
Hans Verkuil60acf182015-03-09 13:34:13 -03001847 cx231xx_vdev_init(dev, &dev->radio_dev,
1848 &cx231xx_radio_template, "radio");
1849 dev->radio_dev.ctrl_handler = &dev->radio_ctrl_handler;
Hans Verkuil8c3854d2019-06-04 07:19:53 -04001850 dev->radio_dev.device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER;
Hans Verkuil60acf182015-03-09 13:34:13 -03001851 ret = video_register_device(&dev->radio_dev, VFL_TYPE_RADIO,
Sri Deevie0d3baf2009-03-03 14:37:50 -03001852 radio_nr[dev->devno]);
1853 if (ret < 0) {
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -03001854 dev_err(dev->dev,
Mauro Carvalho Chehabb7085c02014-11-02 07:21:44 -03001855 "can't register radio device\n");
Sri Deevie0d3baf2009-03-03 14:37:50 -03001856 return ret;
1857 }
Mauro Carvalho Chehab336fea92014-11-03 06:07:38 -03001858 dev_info(dev->dev, "Registered radio device as %s\n",
Hans Verkuil60acf182015-03-09 13:34:13 -03001859 video_device_node_name(&dev->radio_dev));
Sri Deevie0d3baf2009-03-03 14:37:50 -03001860 }
1861
Sri Deevie0d3baf2009-03-03 14:37:50 -03001862 return 0;
1863}