blob: efbc877c6181611cddd7cb58008e6cd0cff66164 [file] [log] [blame]
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001/*
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03002 em28xx-video.c - driver for Empia EM2800/EM2820/2840 USB
3 video capture devices
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08004
Mauro Carvalho Chehabf7abcd32005-11-08 21:38:25 -08005 Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
6 Markus Rechberger <mrechberger@gmail.com>
Mauro Carvalho Chehab2e7c6dc2006-04-03 07:53:40 -03007 Mauro Carvalho Chehab <mchehab@infradead.org>
Mauro Carvalho Chehabf7abcd32005-11-08 21:38:25 -08008 Sascha Sommer <saschasommer@freenet.de>
Frank Schaefer0fa4a402012-11-08 14:11:45 -03009 Copyright (C) 2012 Frank Schäfer <fschaefer.oss@googlemail.com>
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080010
Mauro Carvalho Chehab439090d2006-01-23 17:10:54 -020011 Some parts based on SN9C10x PC Camera Controllers GPL driver made
12 by Luca Risolia <luca.risolia@studio.unibo.it>
13
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080014 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 */
28
29#include <linux/init.h>
30#include <linux/list.h>
31#include <linux/module.h>
32#include <linux/kernel.h>
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -020033#include <linux/bitmap.h>
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080034#include <linux/usb.h>
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080035#include <linux/i2c.h>
Trent Piepho6d35c8f2007-11-01 01:16:09 -030036#include <linux/mm.h>
Ingo Molnar1e4baed2006-01-15 07:52:23 -020037#include <linux/mutex.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090038#include <linux/slab.h>
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080039
Mauro Carvalho Chehabf7abcd32005-11-08 21:38:25 -080040#include "em28xx.h"
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -030041#include "em28xx-v4l.h"
Mauro Carvalho Chehabc0477ad2006-01-09 15:25:14 -020042#include <media/v4l2-common.h>
Hans Verkuil35ea11f2008-07-20 08:12:02 -030043#include <media/v4l2-ioctl.h>
Hans Verkuil50fdf402012-09-07 06:10:12 -030044#include <media/v4l2-event.h>
Hans Verkuil2474ed42006-03-19 12:35:57 -030045#include <media/msp3400.h>
Mauro Carvalho Chehabed086312008-01-24 06:59:20 -030046#include <media/tuner.h>
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080047
Mauro Carvalho Chehabf7abcd32005-11-08 21:38:25 -080048#define DRIVER_AUTHOR "Ludovico Cavedon <cavedon@sssup.it>, " \
49 "Markus Rechberger <mrechberger@gmail.com>, " \
Mauro Carvalho Chehab2e7c6dc2006-04-03 07:53:40 -030050 "Mauro Carvalho Chehab <mchehab@infradead.org>, " \
Mauro Carvalho Chehabf7abcd32005-11-08 21:38:25 -080051 "Sascha Sommer <saschasommer@freenet.de>"
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080052
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -030053static unsigned int isoc_debug;
54module_param(isoc_debug, int, 0644);
55MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");
56
57static unsigned int disable_vbi;
58module_param(disable_vbi, int, 0644);
59MODULE_PARM_DESC(disable_vbi, "disable vbi support");
60
61static int alt;
62module_param(alt, int, 0644);
63MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint");
64
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -080065#define em28xx_videodbg(fmt, arg...) do {\
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -080066 if (video_debug) \
67 printk(KERN_INFO "%s %s :"fmt, \
Harvey Harrisond80e1342008-04-08 23:20:00 -030068 dev->name, __func__ , ##arg); } while (0)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080069
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -030070#define em28xx_isocdbg(fmt, arg...) \
71do {\
72 if (isoc_debug) { \
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -030073 printk(KERN_INFO "%s %s :"fmt, \
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -030074 dev->name, __func__ , ##arg); \
75 } \
76 } while (0)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -030077
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080078MODULE_AUTHOR(DRIVER_AUTHOR);
Mauro Carvalho Chehabd8992b02013-12-27 11:14:59 -030079MODULE_DESCRIPTION(DRIVER_DESC " - v4l2 interface");
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080080MODULE_LICENSE("GPL");
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -030081MODULE_VERSION(EM28XX_VERSION);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080082
Frank Schaefere507e0e2013-03-26 13:38:38 -030083
84#define EM25XX_FRMDATAHDR_BYTE1 0x02
85#define EM25XX_FRMDATAHDR_BYTE2_STILL_IMAGE 0x20
86#define EM25XX_FRMDATAHDR_BYTE2_FRAME_END 0x02
87#define EM25XX_FRMDATAHDR_BYTE2_FRAME_ID 0x01
88#define EM25XX_FRMDATAHDR_BYTE2_MASK (EM25XX_FRMDATAHDR_BYTE2_STILL_IMAGE | \
89 EM25XX_FRMDATAHDR_BYTE2_FRAME_END | \
90 EM25XX_FRMDATAHDR_BYTE2_FRAME_ID)
91
92
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -030093static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
94static unsigned int vbi_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
95static unsigned int radio_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -030096
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -020097module_param_array(video_nr, int, NULL, 0444);
98module_param_array(vbi_nr, int, NULL, 0444);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -030099module_param_array(radio_nr, int, NULL, 0444);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -0300100MODULE_PARM_DESC(video_nr, "video device numbers");
101MODULE_PARM_DESC(vbi_nr, "vbi device numbers");
102MODULE_PARM_DESC(radio_nr, "radio device numbers");
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800103
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -0300104static unsigned int video_debug;
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -0300105module_param(video_debug, int, 0644);
106MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800107
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -0300108/* supported video standards */
109static struct em28xx_fmt format[] = {
110 {
Mauro Carvalho Chehab58fc1ce2009-07-03 02:54:18 -0300111 .name = "16 bpp YUY2, 4:2:2, packed",
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -0300112 .fourcc = V4L2_PIX_FMT_YUYV,
113 .depth = 16,
Devin Heitmueller3fbf9302008-12-29 23:34:37 -0300114 .reg = EM28XX_OUTFMT_YUV422_Y0UY1V,
Mauro Carvalho Chehab43cb9fe2009-06-30 08:36:17 -0300115 }, {
Mauro Carvalho Chehab58fc1ce2009-07-03 02:54:18 -0300116 .name = "16 bpp RGB 565, LE",
Mauro Carvalho Chehab43cb9fe2009-06-30 08:36:17 -0300117 .fourcc = V4L2_PIX_FMT_RGB565,
118 .depth = 16,
Mauro Carvalho Chehab58fc1ce2009-07-03 02:54:18 -0300119 .reg = EM28XX_OUTFMT_RGB_16_656,
120 }, {
121 .name = "8 bpp Bayer BGBG..GRGR",
122 .fourcc = V4L2_PIX_FMT_SBGGR8,
123 .depth = 8,
124 .reg = EM28XX_OUTFMT_RGB_8_BGBG,
125 }, {
126 .name = "8 bpp Bayer GRGR..BGBG",
127 .fourcc = V4L2_PIX_FMT_SGRBG8,
128 .depth = 8,
129 .reg = EM28XX_OUTFMT_RGB_8_GRGR,
130 }, {
131 .name = "8 bpp Bayer GBGB..RGRG",
132 .fourcc = V4L2_PIX_FMT_SGBRG8,
133 .depth = 8,
134 .reg = EM28XX_OUTFMT_RGB_8_GBGB,
135 }, {
136 .name = "12 bpp YUV411",
137 .fourcc = V4L2_PIX_FMT_YUV411P,
138 .depth = 12,
139 .reg = EM28XX_OUTFMT_YUV411,
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -0300140 },
141};
142
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300143static int em28xx_vbi_supported(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300144{
145 /* Modprobe option to manually disable */
146 if (disable_vbi == 1)
147 return 0;
148
149 if (dev->board.is_webcam)
150 return 0;
151
152 /* FIXME: check subdevices for VBI support */
153
154 if (dev->chip_id == CHIP_ID_EM2860 ||
155 dev->chip_id == CHIP_ID_EM2883)
156 return 1;
157
158 /* Version of em28xx that does not support VBI */
159 return 0;
160}
161
162/*
163 * em28xx_wake_i2c()
164 * configure i2c attached devices
165 */
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300166static void em28xx_wake_i2c(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300167{
168 v4l2_device_call_all(&dev->v4l2_dev, 0, core, reset, 0);
169 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
170 INPUT(dev->ctl_input)->vmux, 0, 0);
171 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
172}
173
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300174static int em28xx_colorlevels_set_default(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300175{
176 em28xx_write_reg(dev, EM28XX_R20_YGAIN, CONTRAST_DEFAULT);
177 em28xx_write_reg(dev, EM28XX_R21_YOFFSET, BRIGHTNESS_DEFAULT);
178 em28xx_write_reg(dev, EM28XX_R22_UVGAIN, SATURATION_DEFAULT);
179 em28xx_write_reg(dev, EM28XX_R23_UOFFSET, BLUE_BALANCE_DEFAULT);
180 em28xx_write_reg(dev, EM28XX_R24_VOFFSET, RED_BALANCE_DEFAULT);
181 em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, SHARPNESS_DEFAULT);
182
183 em28xx_write_reg(dev, EM28XX_R14_GAMMA, 0x20);
184 em28xx_write_reg(dev, EM28XX_R15_RGAIN, 0x20);
185 em28xx_write_reg(dev, EM28XX_R16_GGAIN, 0x20);
186 em28xx_write_reg(dev, EM28XX_R17_BGAIN, 0x20);
187 em28xx_write_reg(dev, EM28XX_R18_ROFFSET, 0x00);
188 em28xx_write_reg(dev, EM28XX_R19_GOFFSET, 0x00);
189 return em28xx_write_reg(dev, EM28XX_R1A_BOFFSET, 0x00);
190}
191
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300192static int em28xx_set_outfmt(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300193{
194 int ret;
195 u8 fmt, vinctrl;
196
197 fmt = dev->format->reg;
198 if (!dev->is_em25xx)
199 fmt |= 0x20;
200 /*
201 * NOTE: it's not clear if this is really needed !
202 * The datasheets say bit 5 is a reserved bit and devices seem to work
203 * fine without it. But the Windows driver sets it for em2710/50+em28xx
204 * devices and we've always been setting it, too.
205 *
206 * em2765 (em25xx, em276x/7x/8x) devices do NOT work with this bit set,
207 * it's likely used for an additional (compressed ?) format there.
208 */
209 ret = em28xx_write_reg(dev, EM28XX_R27_OUTFMT, fmt);
210 if (ret < 0)
211 return ret;
212
213 ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, dev->vinmode);
214 if (ret < 0)
215 return ret;
216
217 vinctrl = dev->vinctl;
218 if (em28xx_vbi_supported(dev) == 1) {
219 vinctrl |= EM28XX_VINCTRL_VBI_RAW;
220 em28xx_write_reg(dev, EM28XX_R34_VBI_START_H, 0x00);
221 em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH, dev->vbi_width/4);
222 em28xx_write_reg(dev, EM28XX_R37_VBI_HEIGHT, dev->vbi_height);
223 if (dev->norm & V4L2_STD_525_60) {
224 /* NTSC */
225 em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x09);
226 } else if (dev->norm & V4L2_STD_625_50) {
227 /* PAL */
228 em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x07);
229 }
230 }
231
232 return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctrl);
233}
234
235static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax,
236 u8 ymin, u8 ymax)
237{
238 em28xx_videodbg("em28xx Scale: (%d,%d)-(%d,%d)\n",
239 xmin, ymin, xmax, ymax);
240
241 em28xx_write_regs(dev, EM28XX_R28_XMIN, &xmin, 1);
242 em28xx_write_regs(dev, EM28XX_R29_XMAX, &xmax, 1);
243 em28xx_write_regs(dev, EM28XX_R2A_YMIN, &ymin, 1);
244 return em28xx_write_regs(dev, EM28XX_R2B_YMAX, &ymax, 1);
245}
246
247static void em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
248 u16 width, u16 height)
249{
250 u8 cwidth = width >> 2;
251 u8 cheight = height >> 2;
252 u8 overflow = (height >> 9 & 0x02) | (width >> 10 & 0x01);
253 /* NOTE: size limit: 2047x1023 = 2MPix */
254
255 em28xx_videodbg("capture area set to (%d,%d): %dx%d\n",
256 hstart, vstart,
257 ((overflow & 2) << 9 | cwidth << 2),
258 ((overflow & 1) << 10 | cheight << 2));
259
260 em28xx_write_regs(dev, EM28XX_R1C_HSTART, &hstart, 1);
261 em28xx_write_regs(dev, EM28XX_R1D_VSTART, &vstart, 1);
262 em28xx_write_regs(dev, EM28XX_R1E_CWIDTH, &cwidth, 1);
263 em28xx_write_regs(dev, EM28XX_R1F_CHEIGHT, &cheight, 1);
264 em28xx_write_regs(dev, EM28XX_R1B_OFLOW, &overflow, 1);
265
266 /* FIXME: function/meaning of these registers ? */
267 /* FIXME: align width+height to multiples of 4 ?! */
268 if (dev->is_em25xx) {
269 em28xx_write_reg(dev, 0x34, width >> 4);
270 em28xx_write_reg(dev, 0x35, height >> 4);
271 }
272}
273
274static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v)
275{
276 u8 mode;
277 /* the em2800 scaler only supports scaling down to 50% */
278
279 if (dev->board.is_em2800) {
280 mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00);
281 } else {
282 u8 buf[2];
283
284 buf[0] = h;
285 buf[1] = h >> 8;
286 em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2);
287
288 buf[0] = v;
289 buf[1] = v >> 8;
290 em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2);
291 /* it seems that both H and V scalers must be active
292 to work correctly */
293 mode = (h || v) ? 0x30 : 0x00;
294 }
295 return em28xx_write_reg_bits(dev, EM28XX_R26_COMPR, mode, 0x30);
296}
297
298/* FIXME: this only function read values from dev */
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300299static int em28xx_resolution_set(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300300{
301 int width, height;
302 width = norm_maxw(dev);
303 height = norm_maxh(dev);
304
305 /* Properly setup VBI */
306 dev->vbi_width = 720;
307 if (dev->norm & V4L2_STD_525_60)
308 dev->vbi_height = 12;
309 else
310 dev->vbi_height = 18;
311
312 em28xx_set_outfmt(dev);
313
314 em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2);
315
316 /* If we don't set the start position to 2 in VBI mode, we end up
317 with line 20/21 being YUYV encoded instead of being in 8-bit
318 greyscale. The core of the issue is that line 21 (and line 23 for
319 PAL WSS) are inside of active video region, and as a result they
320 get the pixelformatting associated with that area. So by cropping
321 it out, we end up with the same format as the rest of the VBI
322 region */
323 if (em28xx_vbi_supported(dev) == 1)
324 em28xx_capture_area_set(dev, 0, 2, width, height);
325 else
326 em28xx_capture_area_set(dev, 0, 0, width, height);
327
328 return em28xx_scaler_set(dev, dev->hscale, dev->vscale);
329}
330
331/* Set USB alternate setting for analog video */
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300332static int em28xx_set_alternate(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300333{
334 int errCode;
335 int i;
336 unsigned int min_pkt_size = dev->width * 2 + 4;
337
338 /* NOTE: for isoc transfers, only alt settings > 0 are allowed
339 bulk transfers seem to work only with alt=0 ! */
340 dev->alt = 0;
341 if ((alt > 0) && (alt < dev->num_alt)) {
342 em28xx_videodbg("alternate forced to %d\n", dev->alt);
343 dev->alt = alt;
344 goto set_alt;
345 }
346 if (dev->analog_xfer_bulk)
347 goto set_alt;
348
349 /* When image size is bigger than a certain value,
350 the frame size should be increased, otherwise, only
351 green screen will be received.
352 */
353 if (dev->width * 2 * dev->height > 720 * 240 * 2)
354 min_pkt_size *= 2;
355
356 for (i = 0; i < dev->num_alt; i++) {
357 /* stop when the selected alt setting offers enough bandwidth */
358 if (dev->alt_max_pkt_size_isoc[i] >= min_pkt_size) {
359 dev->alt = i;
360 break;
361 /* otherwise make sure that we end up with the maximum bandwidth
362 because the min_pkt_size equation might be wrong...
363 */
364 } else if (dev->alt_max_pkt_size_isoc[i] >
365 dev->alt_max_pkt_size_isoc[dev->alt])
366 dev->alt = i;
367 }
368
369set_alt:
370 /* NOTE: for bulk transfers, we need to call usb_set_interface()
371 * even if the previous settings were the same. Otherwise streaming
372 * fails with all urbs having status = -EOVERFLOW ! */
373 if (dev->analog_xfer_bulk) {
374 dev->max_pkt_size = 512; /* USB 2.0 spec */
375 dev->packet_multiplier = EM28XX_BULK_PACKET_MULTIPLIER;
376 } else { /* isoc */
377 em28xx_videodbg("minimum isoc packet size: %u (alt=%d)\n",
378 min_pkt_size, dev->alt);
379 dev->max_pkt_size =
380 dev->alt_max_pkt_size_isoc[dev->alt];
381 dev->packet_multiplier = EM28XX_NUM_ISOC_PACKETS;
382 }
383 em28xx_videodbg("setting alternate %d with wMaxPacketSize=%u\n",
384 dev->alt, dev->max_pkt_size);
385 errCode = usb_set_interface(dev->udev, 0, dev->alt);
386 if (errCode < 0) {
387 em28xx_errdev("cannot change alternate number to %d (error=%i)\n",
388 dev->alt, errCode);
389 return errCode;
390 }
391 return 0;
392}
393
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300394/* ------------------------------------------------------------------
395 DMA and thread functions
396 ------------------------------------------------------------------*/
397
398/*
Frank Schaefer948a49a2012-12-08 11:31:25 -0300399 * Finish the current buffer
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300400 */
Frank Schaefer948a49a2012-12-08 11:31:25 -0300401static inline void finish_buffer(struct em28xx *dev,
402 struct em28xx_buffer *buf)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300403{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300404 em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->top_field);
405
406 buf->vb.v4l2_buf.sequence = dev->field_count++;
407 buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
408 v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
409
410 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300411}
412
413/*
Frank Schaefer36016a32012-12-08 11:31:32 -0300414 * Copy picture data from USB buffer to videobuf buffer
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300415 */
416static void em28xx_copy_video(struct em28xx *dev,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300417 struct em28xx_buffer *buf,
Frank Schaefer36016a32012-12-08 11:31:32 -0300418 unsigned char *usb_buf,
Frank Schaefer4078d622012-12-08 11:31:29 -0300419 unsigned long len)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300420{
421 void *fieldstart, *startwrite, *startread;
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300422 int linesdone, currlinedone, offset, lencopy, remain;
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300423 int bytesperline = dev->width << 1;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300424
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300425 if (buf->pos + len > buf->length)
426 len = buf->length - buf->pos;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300427
Frank Schaefer36016a32012-12-08 11:31:32 -0300428 startread = usb_buf;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300429 remain = len;
430
Frank Schaeferc02ec712012-11-08 14:11:33 -0300431 if (dev->progressive || buf->top_field)
Frank Schaefer36016a32012-12-08 11:31:32 -0300432 fieldstart = buf->vb_buf;
Frank Schaeferc02ec712012-11-08 14:11:33 -0300433 else /* interlaced mode, even nr. of lines */
Frank Schaefer36016a32012-12-08 11:31:32 -0300434 fieldstart = buf->vb_buf + bytesperline;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300435
Frank Schaefer87325332012-12-08 11:31:27 -0300436 linesdone = buf->pos / bytesperline;
437 currlinedone = buf->pos % bytesperline;
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -0300438
439 if (dev->progressive)
440 offset = linesdone * bytesperline + currlinedone;
441 else
442 offset = linesdone * bytesperline * 2 + currlinedone;
443
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300444 startwrite = fieldstart + offset;
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300445 lencopy = bytesperline - currlinedone;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300446 lencopy = lencopy > remain ? remain : lencopy;
447
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300448 if ((char *)startwrite + lencopy > (char *)buf->vb_buf + buf->length) {
Mauro Carvalho Chehabea8df7e2008-04-13 14:39:29 -0300449 em28xx_isocdbg("Overflow of %zi bytes past buffer end (1)\n",
Frank Schaefer36016a32012-12-08 11:31:32 -0300450 ((char *)startwrite + lencopy) -
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300451 ((char *)buf->vb_buf + buf->length));
452 remain = (char *)buf->vb_buf + buf->length -
Frank Schaefer36016a32012-12-08 11:31:32 -0300453 (char *)startwrite;
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -0300454 lencopy = remain;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300455 }
Aidan Thorntone0fadfd342008-04-13 14:56:02 -0300456 if (lencopy <= 0)
457 return;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300458 memcpy(startwrite, startread, lencopy);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300459
460 remain -= lencopy;
461
462 while (remain > 0) {
Frank Schaeferc02ec712012-11-08 14:11:33 -0300463 if (dev->progressive)
464 startwrite += lencopy;
465 else
466 startwrite += lencopy + bytesperline;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300467 startread += lencopy;
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300468 if (bytesperline > remain)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300469 lencopy = remain;
470 else
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300471 lencopy = bytesperline;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300472
Frank Schaefer36016a32012-12-08 11:31:32 -0300473 if ((char *)startwrite + lencopy > (char *)buf->vb_buf +
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300474 buf->length) {
Devin Heitmuellere3ba4d32009-09-15 00:18:06 -0300475 em28xx_isocdbg("Overflow of %zi bytes past buffer end"
476 "(2)\n",
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300477 ((char *)startwrite + lencopy) -
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300478 ((char *)buf->vb_buf + buf->length));
479 lencopy = remain = (char *)buf->vb_buf + buf->length -
480 (char *)startwrite;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300481 }
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300482 if (lencopy <= 0)
483 break;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300484
485 memcpy(startwrite, startread, lencopy);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300486
487 remain -= lencopy;
488 }
489
Frank Schaefer87325332012-12-08 11:31:27 -0300490 buf->pos += len;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300491}
492
Frank Schaefer36016a32012-12-08 11:31:32 -0300493/*
494 * Copy VBI data from USB buffer to videobuf buffer
495 */
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300496static void em28xx_copy_vbi(struct em28xx *dev,
Frank Schaefer87325332012-12-08 11:31:27 -0300497 struct em28xx_buffer *buf,
Frank Schaefer36016a32012-12-08 11:31:32 -0300498 unsigned char *usb_buf,
Frank Schaefer4078d622012-12-08 11:31:29 -0300499 unsigned long len)
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300500{
Frank Schaefer36016a32012-12-08 11:31:32 -0300501 unsigned int offset;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300502
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300503 if (buf->pos + len > buf->length)
504 len = buf->length - buf->pos;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300505
Frank Schaefer87325332012-12-08 11:31:27 -0300506 offset = buf->pos;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300507 /* Make sure the bottom field populates the second half of the frame */
Frank Schaefer36016a32012-12-08 11:31:32 -0300508 if (buf->top_field == 0)
509 offset += dev->vbi_width * dev->vbi_height;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300510
Frank Schaefer36016a32012-12-08 11:31:32 -0300511 memcpy(buf->vb_buf + offset, usb_buf, len);
Frank Schaefer87325332012-12-08 11:31:27 -0300512 buf->pos += len;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300513}
514
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300515static inline void print_err_status(struct em28xx *dev,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300516 int packet, int status)
517{
518 char *errmsg = "Unknown";
519
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300520 switch (status) {
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300521 case -ENOENT:
522 errmsg = "unlinked synchronuously";
523 break;
524 case -ECONNRESET:
525 errmsg = "unlinked asynchronuously";
526 break;
527 case -ENOSR:
528 errmsg = "Buffer error (overrun)";
529 break;
530 case -EPIPE:
531 errmsg = "Stalled (device not responding)";
532 break;
533 case -EOVERFLOW:
534 errmsg = "Babble (bad cable?)";
535 break;
536 case -EPROTO:
537 errmsg = "Bit-stuff error (bad cable?)";
538 break;
539 case -EILSEQ:
540 errmsg = "CRC/Timeout (could be anything)";
541 break;
542 case -ETIME:
543 errmsg = "Device does not respond";
544 break;
545 }
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300546 if (packet < 0) {
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300547 em28xx_isocdbg("URB status %d [%s].\n", status, errmsg);
548 } else {
549 em28xx_isocdbg("URB packet %d, status %d [%s].\n",
550 packet, status, errmsg);
551 }
552}
553
554/*
Frank Schaefer24a6d842012-12-08 11:31:24 -0300555 * get the next available buffer from dma queue
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300556 */
Frank Schaefer24a6d842012-12-08 11:31:24 -0300557static inline struct em28xx_buffer *get_next_buf(struct em28xx *dev,
558 struct em28xx_dmaqueue *dma_q)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300559{
Frank Schaefer24a6d842012-12-08 11:31:24 -0300560 struct em28xx_buffer *buf;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300561
Mauro Carvalho Chehabdbecb442008-04-13 15:08:55 -0300562 if (list_empty(&dma_q->active)) {
563 em28xx_isocdbg("No active queue to serve\n");
Frank Schaefer24a6d842012-12-08 11:31:24 -0300564 return NULL;
Mauro Carvalho Chehabdbecb442008-04-13 15:08:55 -0300565 }
566
Mauro Carvalho Chehabdbecb442008-04-13 15:08:55 -0300567 /* Get the next buffer */
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300568 buf = list_entry(dma_q->active.next, struct em28xx_buffer, list);
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300569 /* Cleans up buffer - Useful for testing for frame/URB loss */
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300570 list_del(&buf->list);
Frank Schaefer87325332012-12-08 11:31:27 -0300571 buf->pos = 0;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300572 buf->vb_buf = buf->mem;
Mauro Carvalho Chehabcb784722008-04-13 15:06:52 -0300573
Frank Schaefer24a6d842012-12-08 11:31:24 -0300574 return buf;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300575}
576
Frank Schaefere04c00d2012-12-08 11:31:30 -0300577/*
578 * Finish the current buffer if completed and prepare for the next field
579 */
580static struct em28xx_buffer *
581finish_field_prepare_next(struct em28xx *dev,
582 struct em28xx_buffer *buf,
583 struct em28xx_dmaqueue *dma_q)
584{
585 if (dev->progressive || dev->top_field) { /* Brand new frame */
586 if (buf != NULL)
587 finish_buffer(dev, buf);
588 buf = get_next_buf(dev, dma_q);
589 }
590 if (buf != NULL) {
591 buf->top_field = dev->top_field;
592 buf->pos = 0;
593 }
594
595 return buf;
596}
597
Frank Schaefer227b7c92012-12-08 11:31:31 -0300598/*
599 * Process data packet according to the em2710/em2750/em28xx frame data format
600 */
601static inline void process_frame_data_em28xx(struct em28xx *dev,
602 unsigned char *data_pkt,
603 unsigned int data_len)
604{
605 struct em28xx_buffer *buf = dev->usb_ctl.vid_buf;
606 struct em28xx_buffer *vbi_buf = dev->usb_ctl.vbi_buf;
607 struct em28xx_dmaqueue *dma_q = &dev->vidq;
608 struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq;
609
610 /* capture type 0 = vbi start
611 capture type 1 = vbi in progress
612 capture type 2 = video start
613 capture type 3 = video in progress */
614 if (data_len >= 4) {
615 /* NOTE: Headers are always 4 bytes and
616 * never split across packets */
617 if (data_pkt[0] == 0x88 && data_pkt[1] == 0x88 &&
618 data_pkt[2] == 0x88 && data_pkt[3] == 0x88) {
619 /* Continuation */
620 data_pkt += 4;
621 data_len -= 4;
622 } else if (data_pkt[0] == 0x33 && data_pkt[1] == 0x95) {
623 /* Field start (VBI mode) */
624 dev->capture_type = 0;
625 dev->vbi_read = 0;
626 em28xx_isocdbg("VBI START HEADER !!!\n");
627 dev->top_field = !(data_pkt[2] & 1);
628 data_pkt += 4;
629 data_len -= 4;
630 } else if (data_pkt[0] == 0x22 && data_pkt[1] == 0x5a) {
631 /* Field start (VBI disabled) */
632 dev->capture_type = 2;
633 em28xx_isocdbg("VIDEO START HEADER !!!\n");
634 dev->top_field = !(data_pkt[2] & 1);
635 data_pkt += 4;
636 data_len -= 4;
637 }
638 }
639 /* NOTE: With bulk transfers, intermediate data packets
640 * have no continuation header */
641
642 if (dev->capture_type == 0) {
643 vbi_buf = finish_field_prepare_next(dev, vbi_buf, vbi_dma_q);
644 dev->usb_ctl.vbi_buf = vbi_buf;
645 dev->capture_type = 1;
646 }
647
648 if (dev->capture_type == 1) {
649 int vbi_size = dev->vbi_width * dev->vbi_height;
650 int vbi_data_len = ((dev->vbi_read + data_len) > vbi_size) ?
651 (vbi_size - dev->vbi_read) : data_len;
652
653 /* Copy VBI data */
654 if (vbi_buf != NULL)
655 em28xx_copy_vbi(dev, vbi_buf, data_pkt, vbi_data_len);
656 dev->vbi_read += vbi_data_len;
657
658 if (vbi_data_len < data_len) {
659 /* Continue with copying video data */
660 dev->capture_type = 2;
661 data_pkt += vbi_data_len;
662 data_len -= vbi_data_len;
663 }
664 }
665
666 if (dev->capture_type == 2) {
667 buf = finish_field_prepare_next(dev, buf, dma_q);
668 dev->usb_ctl.vid_buf = buf;
669 dev->capture_type = 3;
670 }
671
672 if (dev->capture_type == 3 && buf != NULL && data_len > 0)
673 em28xx_copy_video(dev, buf, data_pkt, data_len);
674}
675
Frank Schaefere507e0e2013-03-26 13:38:38 -0300676/*
677 * Process data packet according to the em25xx/em276x/7x/8x frame data format
678 */
679static inline void process_frame_data_em25xx(struct em28xx *dev,
680 unsigned char *data_pkt,
681 unsigned int data_len)
682{
683 struct em28xx_buffer *buf = dev->usb_ctl.vid_buf;
684 struct em28xx_dmaqueue *dmaq = &dev->vidq;
685 bool frame_end = 0;
686
687 /* Check for header */
688 /* NOTE: at least with bulk transfers, only the first packet
689 * has a header and has always set the FRAME_END bit */
690 if (data_len >= 2) { /* em25xx header is only 2 bytes long */
691 if ((data_pkt[0] == EM25XX_FRMDATAHDR_BYTE1) &&
692 ((data_pkt[1] & ~EM25XX_FRMDATAHDR_BYTE2_MASK) == 0x00)) {
693 dev->top_field = !(data_pkt[1] &
694 EM25XX_FRMDATAHDR_BYTE2_FRAME_ID);
695 frame_end = data_pkt[1] &
696 EM25XX_FRMDATAHDR_BYTE2_FRAME_END;
697 data_pkt += 2;
698 data_len -= 2;
699 }
700
701 /* Finish field and prepare next (BULK only) */
702 if (dev->analog_xfer_bulk && frame_end) {
703 buf = finish_field_prepare_next(dev, buf, dmaq);
704 dev->usb_ctl.vid_buf = buf;
705 }
706 /* NOTE: in ISOC mode when a new frame starts and buf==NULL,
707 * we COULD already prepare a buffer here to avoid skipping the
708 * first frame.
709 */
710 }
711
712 /* Copy data */
713 if (buf != NULL && data_len > 0)
714 em28xx_copy_video(dev, buf, data_pkt, data_len);
715
716 /* Finish frame (ISOC only) => avoids lag of 1 frame */
717 if (!dev->analog_xfer_bulk && frame_end) {
718 buf = finish_field_prepare_next(dev, buf, dmaq);
719 dev->usb_ctl.vid_buf = buf;
720 }
721
722 /* NOTE: Tested with USB bulk transfers only !
723 * The wording in the datasheet suggests that isoc might work different.
724 * The current code assumes that with isoc transfers each packet has a
725 * header like with the other em28xx devices.
726 */
727 /* NOTE: Support for interlaced mode is pure theory. It has not been
728 * tested and it is unknown if these devices actually support it. */
729 /* NOTE: No VBI support yet (these chips likely do not support VBI). */
730}
731
Frank Schaefer960da932012-11-25 06:37:37 -0300732/* Processes and copies the URB data content (video and VBI data) */
Frank Schaefer0fa4a402012-11-08 14:11:45 -0300733static inline int em28xx_urb_data_copy(struct em28xx *dev, struct urb *urb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300734{
Frank Schaefer227b7c92012-12-08 11:31:31 -0300735 int xfer_bulk, num_packets, i;
736 unsigned char *usb_data_pkt;
737 unsigned int usb_data_len;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300738
739 if (!dev)
740 return 0;
741
Frank Schaefer2665c292012-12-27 19:02:43 -0300742 if (dev->disconnected)
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300743 return 0;
744
Frank Schaefer1653cb0c2012-11-08 14:11:44 -0300745 if (urb->status < 0)
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300746 print_err_status(dev, -1, urb->status);
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300747
Frank Schaefer4601cc32012-11-08 14:11:46 -0300748 xfer_bulk = usb_pipebulk(urb->pipe);
749
Frank Schaefer4601cc32012-11-08 14:11:46 -0300750 if (xfer_bulk) /* bulk */
751 num_packets = 1;
752 else /* isoc */
753 num_packets = urb->number_of_packets;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300754
Frank Schaefer4601cc32012-11-08 14:11:46 -0300755 for (i = 0; i < num_packets; i++) {
756 if (xfer_bulk) { /* bulk */
Frank Schaefer227b7c92012-12-08 11:31:31 -0300757 usb_data_len = urb->actual_length;
Frank Schaefer4601cc32012-11-08 14:11:46 -0300758
Frank Schaefer227b7c92012-12-08 11:31:31 -0300759 usb_data_pkt = urb->transfer_buffer;
Frank Schaefer4601cc32012-11-08 14:11:46 -0300760 } else { /* isoc */
761 if (urb->iso_frame_desc[i].status < 0) {
762 print_err_status(dev, i,
763 urb->iso_frame_desc[i].status);
764 if (urb->iso_frame_desc[i].status != -EPROTO)
765 continue;
766 }
767
Frank Schaefer227b7c92012-12-08 11:31:31 -0300768 usb_data_len = urb->iso_frame_desc[i].actual_length;
769 if (usb_data_len > dev->max_pkt_size) {
Frank Schaefer4601cc32012-11-08 14:11:46 -0300770 em28xx_isocdbg("packet bigger than packet size");
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300771 continue;
Frank Schaefer4601cc32012-11-08 14:11:46 -0300772 }
773
Frank Schaefer227b7c92012-12-08 11:31:31 -0300774 usb_data_pkt = urb->transfer_buffer +
775 urb->iso_frame_desc[i].offset;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300776 }
777
Frank Schaefer227b7c92012-12-08 11:31:31 -0300778 if (usb_data_len == 0) {
Frank Schaefer4601cc32012-11-08 14:11:46 -0300779 /* NOTE: happens very often with isoc transfers */
780 /* em28xx_usbdbg("packet %d is empty",i); - spammy */
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300781 continue;
782 }
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300783
Frank Schaefere507e0e2013-03-26 13:38:38 -0300784 if (dev->is_em25xx)
785 process_frame_data_em25xx(dev,
786 usb_data_pkt, usb_data_len);
787 else
788 process_frame_data_em28xx(dev,
789 usb_data_pkt, usb_data_len);
790
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300791 }
Frank Schaefer227b7c92012-12-08 11:31:31 -0300792 return 1;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300793}
794
795
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300796static int get_ressource(enum v4l2_buf_type f_type)
797{
798 switch (f_type) {
799 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
800 return EM28XX_RESOURCE_VIDEO;
801 case V4L2_BUF_TYPE_VBI_CAPTURE:
802 return EM28XX_RESOURCE_VBI;
803 default:
804 BUG();
805 return 0;
806 }
807}
808
809/* Usage lock check functions */
810static int res_get(struct em28xx *dev, enum v4l2_buf_type f_type)
811{
812 int res_type = get_ressource(f_type);
813
814 /* is it free? */
815 if (dev->resources & res_type) {
816 /* no, someone else uses it */
817 return -EBUSY;
818 }
819
820 /* it's free, grab it */
821 dev->resources |= res_type;
822 em28xx_videodbg("res: get %d\n", res_type);
823 return 0;
824}
825
826static void res_free(struct em28xx *dev, enum v4l2_buf_type f_type)
827{
828 int res_type = get_ressource(f_type);
829
830 dev->resources &= ~res_type;
831 em28xx_videodbg("res: put %d\n", res_type);
832}
833
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300834/* ------------------------------------------------------------------
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300835 Videobuf2 operations
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300836 ------------------------------------------------------------------*/
837
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300838static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
839 unsigned int *nbuffers, unsigned int *nplanes,
840 unsigned int sizes[], void *alloc_ctxs[])
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300841{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300842 struct em28xx *dev = vb2_get_drv_priv(vq);
843 unsigned long size;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300844
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300845 if (fmt)
846 size = fmt->fmt.pix.sizeimage;
847 else
848 size = (dev->width * dev->height * dev->format->depth + 7) >> 3;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -0300849
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300850 if (size == 0)
851 return -EINVAL;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300852
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300853 if (0 == *nbuffers)
854 *nbuffers = 32;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300855
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300856 *nplanes = 1;
857 sizes[0] = size;
Mauro Carvalho Chehabd2d9fbf2008-04-17 21:38:53 -0300858
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300859 return 0;
860}
861
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300862static int
863buffer_prepare(struct vb2_buffer *vb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300864{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300865 struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue);
866 struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
867 unsigned long size;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300868
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300869 em28xx_videodbg("%s, field=%d\n", __func__, vb->v4l2_buf.field);
Aidan Thornton3b5fa922008-04-13 15:09:36 -0300870
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300871 size = (dev->width * dev->height * dev->format->depth + 7) >> 3;
Aidan Thornton3b5fa922008-04-13 15:09:36 -0300872
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300873 if (vb2_plane_size(vb, 0) < size) {
874 em28xx_videodbg("%s data will not fit into plane (%lu < %lu)\n",
875 __func__, vb2_plane_size(vb, 0), size);
876 return -EINVAL;
877 }
878 vb2_set_plane_payload(&buf->vb, 0, size);
879
880 return 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300881}
882
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300883int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300884{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300885 struct em28xx *dev = vb2_get_drv_priv(vq);
886 struct v4l2_frequency f;
887 int rc = 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300888
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300889 em28xx_videodbg("%s\n", __func__);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300890
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300891 /* Make sure streaming is not already in progress for this type
892 of filehandle (e.g. video, vbi) */
893 rc = res_get(dev, vq->type);
894 if (rc)
895 return rc;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300896
Frank Schaefer032f1dd2013-10-10 15:31:53 -0300897 if (dev->streaming_users == 0) {
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300898 /* First active streaming user, so allocate all the URBs */
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300899
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300900 /* Allocate the USB bandwidth */
901 em28xx_set_alternate(dev);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300902
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300903 /* Needed, since GPIO might have disabled power of
904 some i2c device
905 */
906 em28xx_wake_i2c(dev);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300907
Frank Schaefer0455eeb2012-11-25 06:37:34 -0300908 dev->capture_type = -1;
Frank Schaefer960da932012-11-25 06:37:37 -0300909 rc = em28xx_init_usb_xfer(dev, EM28XX_ANALOG_MODE,
910 dev->analog_xfer_bulk,
911 EM28XX_NUM_BUFS,
912 dev->max_pkt_size,
913 dev->packet_multiplier,
914 em28xx_urb_data_copy);
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300915 if (rc < 0)
Frank Schaefer032f1dd2013-10-10 15:31:53 -0300916 return rc;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300917
918 /*
919 * djh: it's not clear whether this code is still needed. I'm
920 * leaving it in here for now entirely out of concern for
921 * backward compatibility (the old code did it)
922 */
923
924 /* Ask tuner to go to analog or radio mode */
925 memset(&f, 0, sizeof(f));
926 f.frequency = dev->ctl_freq;
927 if (vq->owner && vq->owner->vdev->vfl_type == VFL_TYPE_RADIO)
928 f.type = V4L2_TUNER_RADIO;
929 else
930 f.type = V4L2_TUNER_ANALOG_TV;
931 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300932 }
933
Frank Schaefer032f1dd2013-10-10 15:31:53 -0300934 dev->streaming_users++;
935
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300936 return rc;
937}
938
Mauro Carvalho Chehab3a799c22013-01-05 01:27:21 -0200939static int em28xx_stop_streaming(struct vb2_queue *vq)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300940{
941 struct em28xx *dev = vb2_get_drv_priv(vq);
942 struct em28xx_dmaqueue *vidq = &dev->vidq;
943 unsigned long flags = 0;
944
945 em28xx_videodbg("%s\n", __func__);
946
947 res_free(dev, vq->type);
948
949 if (dev->streaming_users-- == 1) {
950 /* Last active user, so shutdown all the URBS */
951 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
952 }
953
954 spin_lock_irqsave(&dev->slock, flags);
955 while (!list_empty(&vidq->active)) {
956 struct em28xx_buffer *buf;
957 buf = list_entry(vidq->active.next, struct em28xx_buffer, list);
958 list_del(&buf->list);
959 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
960 }
961 dev->usb_ctl.vid_buf = NULL;
962 spin_unlock_irqrestore(&dev->slock, flags);
963
964 return 0;
965}
966
967int em28xx_stop_vbi_streaming(struct vb2_queue *vq)
968{
969 struct em28xx *dev = vb2_get_drv_priv(vq);
970 struct em28xx_dmaqueue *vbiq = &dev->vbiq;
971 unsigned long flags = 0;
972
973 em28xx_videodbg("%s\n", __func__);
974
975 res_free(dev, vq->type);
976
977 if (dev->streaming_users-- == 1) {
978 /* Last active user, so shutdown all the URBS */
979 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
980 }
981
982 spin_lock_irqsave(&dev->slock, flags);
983 while (!list_empty(&vbiq->active)) {
984 struct em28xx_buffer *buf;
985 buf = list_entry(vbiq->active.next, struct em28xx_buffer, list);
986 list_del(&buf->list);
987 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
988 }
989 dev->usb_ctl.vbi_buf = NULL;
990 spin_unlock_irqrestore(&dev->slock, flags);
991
992 return 0;
993}
994
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300995static void
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300996buffer_queue(struct vb2_buffer *vb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300997{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300998 struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue);
999 struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
1000 struct em28xx_dmaqueue *vidq = &dev->vidq;
1001 unsigned long flags = 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001002
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001003 em28xx_videodbg("%s\n", __func__);
1004 buf->mem = vb2_plane_vaddr(vb, 0);
1005 buf->length = vb2_plane_size(vb, 0);
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001006
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001007 spin_lock_irqsave(&dev->slock, flags);
1008 list_add_tail(&buf->list, &vidq->active);
1009 spin_unlock_irqrestore(&dev->slock, flags);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001010}
1011
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001012static struct vb2_ops em28xx_video_qops = {
1013 .queue_setup = queue_setup,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001014 .buf_prepare = buffer_prepare,
1015 .buf_queue = buffer_queue,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001016 .start_streaming = em28xx_start_analog_streaming,
1017 .stop_streaming = em28xx_stop_streaming,
1018 .wait_prepare = vb2_ops_wait_prepare,
1019 .wait_finish = vb2_ops_wait_finish,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001020};
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001021
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001022static int em28xx_vb2_setup(struct em28xx *dev)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001023{
1024 int rc;
1025 struct vb2_queue *q;
1026
1027 /* Setup Videobuf2 for Video capture */
1028 q = &dev->vb_vidq;
1029 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Mauro Carvalho Chehabef85cd92013-01-06 00:34:22 -02001030 q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
Frank Schaefer195281d2013-03-09 06:53:01 -03001031 q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001032 q->drv_priv = dev;
1033 q->buf_struct_size = sizeof(struct em28xx_buffer);
1034 q->ops = &em28xx_video_qops;
1035 q->mem_ops = &vb2_vmalloc_memops;
1036
1037 rc = vb2_queue_init(q);
1038 if (rc < 0)
1039 return rc;
1040
1041 /* Setup Videobuf2 for VBI capture */
1042 q = &dev->vb_vbiq;
1043 q->type = V4L2_BUF_TYPE_VBI_CAPTURE;
1044 q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR;
Frank Schaefer195281d2013-03-09 06:53:01 -03001045 q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001046 q->drv_priv = dev;
1047 q->buf_struct_size = sizeof(struct em28xx_buffer);
1048 q->ops = &em28xx_vbi_qops;
1049 q->mem_ops = &vb2_vmalloc_memops;
1050
1051 rc = vb2_queue_init(q);
1052 if (rc < 0)
1053 return rc;
1054
1055 return 0;
1056}
1057
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001058/********************* v4l2 interface **************************************/
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001059
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001060static void video_mux(struct em28xx *dev, int index)
1061{
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001062 dev->ctl_input = index;
1063 dev->ctl_ainput = INPUT(index)->amux;
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001064 dev->ctl_aoutput = INPUT(index)->aout;
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001065
Mauro Carvalho Chehabe879b8e2008-11-20 13:39:39 -03001066 if (!dev->ctl_aoutput)
1067 dev->ctl_aoutput = EM28XX_AOUT_MASTER;
1068
Hans Verkuil5325b422009-04-02 11:26:22 -03001069 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
1070 INPUT(index)->vmux, 0, 0);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001071
Mauro Carvalho Chehab505b6d02008-11-25 09:39:50 -03001072 if (dev->board.has_msp34xx) {
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001073 if (dev->i2s_speed) {
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03001074 v4l2_device_call_all(&dev->v4l2_dev, 0, audio,
1075 s_i2s_clock_freq, dev->i2s_speed);
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001076 }
Hans Verkuil2474ed42006-03-19 12:35:57 -03001077 /* Note: this is msp3400 specific */
Hans Verkuil5325b422009-04-02 11:26:22 -03001078 v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing,
1079 dev->ctl_ainput, MSP_OUTPUT(MSP_SC_IN_DSP_SCART1), 0);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001080 }
Mauro Carvalho Chehab539c96d2008-01-05 09:53:54 -03001081
Vitaly Wool2bd1d9e2009-03-04 08:27:52 -03001082 if (dev->board.adecoder != EM28XX_NOADECODER) {
Hans Verkuil5325b422009-04-02 11:26:22 -03001083 v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing,
1084 dev->ctl_ainput, dev->ctl_aoutput, 0);
Vitaly Wool2bd1d9e2009-03-04 08:27:52 -03001085 }
1086
Mauro Carvalho Chehab00b87302008-02-06 18:34:13 -03001087 em28xx_audio_analog_set(dev);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001088}
1089
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001090static void em28xx_ctrl_notify(struct v4l2_ctrl *ctrl, void *priv)
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001091{
Hans Verkuil081b9452012-09-07 05:43:59 -03001092 struct em28xx *dev = priv;
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001093
Hans Verkuil081b9452012-09-07 05:43:59 -03001094 /*
1095 * In the case of non-AC97 volume controls, we still need
1096 * to do some setups at em28xx, in order to mute/unmute
1097 * and to adjust audio volume. However, the value ranges
1098 * should be checked by the corresponding V4L subdriver.
1099 */
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001100 switch (ctrl->id) {
1101 case V4L2_CID_AUDIO_MUTE:
Hans Verkuil081b9452012-09-07 05:43:59 -03001102 dev->mute = ctrl->val;
1103 em28xx_audio_analog_set(dev);
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001104 break;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001105 case V4L2_CID_AUDIO_VOLUME:
Hans Verkuil081b9452012-09-07 05:43:59 -03001106 dev->volume = ctrl->val;
1107 em28xx_audio_analog_set(dev);
1108 break;
1109 }
1110}
1111
1112static int em28xx_s_ctrl(struct v4l2_ctrl *ctrl)
1113{
1114 struct em28xx *dev = container_of(ctrl->handler, struct em28xx, ctrl_handler);
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001115 int ret = -EINVAL;
Hans Verkuil081b9452012-09-07 05:43:59 -03001116
1117 switch (ctrl->id) {
1118 case V4L2_CID_AUDIO_MUTE:
1119 dev->mute = ctrl->val;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001120 ret = em28xx_audio_analog_set(dev);
Hans Verkuil081b9452012-09-07 05:43:59 -03001121 break;
1122 case V4L2_CID_AUDIO_VOLUME:
1123 dev->volume = ctrl->val;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001124 ret = em28xx_audio_analog_set(dev);
1125 break;
1126 case V4L2_CID_CONTRAST:
1127 ret = em28xx_write_reg(dev, EM28XX_R20_YGAIN, ctrl->val);
1128 break;
1129 case V4L2_CID_BRIGHTNESS:
1130 ret = em28xx_write_reg(dev, EM28XX_R21_YOFFSET, ctrl->val);
1131 break;
1132 case V4L2_CID_SATURATION:
1133 ret = em28xx_write_reg(dev, EM28XX_R22_UVGAIN, ctrl->val);
1134 break;
1135 case V4L2_CID_BLUE_BALANCE:
1136 ret = em28xx_write_reg(dev, EM28XX_R23_UOFFSET, ctrl->val);
1137 break;
1138 case V4L2_CID_RED_BALANCE:
1139 ret = em28xx_write_reg(dev, EM28XX_R24_VOFFSET, ctrl->val);
1140 break;
1141 case V4L2_CID_SHARPNESS:
1142 ret = em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, ctrl->val);
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001143 break;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001144 }
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001145
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001146 return (ret < 0) ? ret : 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001147}
1148
Hans Verkuil081b9452012-09-07 05:43:59 -03001149const struct v4l2_ctrl_ops em28xx_ctrl_ops = {
1150 .s_ctrl = em28xx_s_ctrl,
1151};
1152
Frank Schaefer6b09a212013-02-10 16:05:12 -03001153static void size_to_scale(struct em28xx *dev,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001154 unsigned int width, unsigned int height,
1155 unsigned int *hscale, unsigned int *vscale)
1156{
Mauro Carvalho Chehab55699962009-07-13 20:15:02 -03001157 unsigned int maxw = norm_maxw(dev);
1158 unsigned int maxh = norm_maxh(dev);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001159
1160 *hscale = (((unsigned long)maxw) << 12) / width - 4096L;
Frank Schaefer81685322013-02-10 16:05:11 -03001161 if (*hscale > EM28XX_HVSCALE_MAX)
1162 *hscale = EM28XX_HVSCALE_MAX;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001163
1164 *vscale = (((unsigned long)maxh) << 12) / height - 4096L;
Frank Schaefer81685322013-02-10 16:05:11 -03001165 if (*vscale > EM28XX_HVSCALE_MAX)
1166 *vscale = EM28XX_HVSCALE_MAX;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001167}
1168
Frank Schaeferb8374132013-02-10 16:05:13 -03001169static void scale_to_size(struct em28xx *dev,
1170 unsigned int hscale, unsigned int vscale,
1171 unsigned int *width, unsigned int *height)
1172{
1173 unsigned int maxw = norm_maxw(dev);
1174 unsigned int maxh = norm_maxh(dev);
1175
1176 *width = (((unsigned long)maxw) << 12) / (hscale + 4096L);
1177 *height = (((unsigned long)maxh) << 12) / (vscale + 4096L);
1178}
1179
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001180/* ------------------------------------------------------------------
1181 IOCTL vidioc handling
1182 ------------------------------------------------------------------*/
1183
Hans Verkuil78b526a2008-05-28 12:16:41 -03001184static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001185 struct v4l2_format *f)
1186{
1187 struct em28xx_fh *fh = priv;
1188 struct em28xx *dev = fh->dev;
1189
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001190 f->fmt.pix.width = dev->width;
1191 f->fmt.pix.height = dev->height;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001192 f->fmt.pix.pixelformat = dev->format->fourcc;
1193 f->fmt.pix.bytesperline = (dev->width * dev->format->depth + 7) >> 3;
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -03001194 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * dev->height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001195 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
1196
1197 /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -03001198 if (dev->progressive)
1199 f->fmt.pix.field = V4L2_FIELD_NONE;
1200 else
1201 f->fmt.pix.field = dev->interlaced ?
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001202 V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001203 return 0;
1204}
1205
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001206static struct em28xx_fmt *format_by_fourcc(unsigned int fourcc)
1207{
1208 unsigned int i;
1209
1210 for (i = 0; i < ARRAY_SIZE(format); i++)
1211 if (format[i].fourcc == fourcc)
1212 return &format[i];
1213
1214 return NULL;
1215}
1216
Hans Verkuil78b526a2008-05-28 12:16:41 -03001217static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001218 struct v4l2_format *f)
1219{
1220 struct em28xx_fh *fh = priv;
1221 struct em28xx *dev = fh->dev;
Trent Piephoccb83402009-05-30 21:45:46 -03001222 unsigned int width = f->fmt.pix.width;
1223 unsigned int height = f->fmt.pix.height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001224 unsigned int maxw = norm_maxw(dev);
1225 unsigned int maxh = norm_maxh(dev);
1226 unsigned int hscale, vscale;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001227 struct em28xx_fmt *fmt;
1228
1229 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
1230 if (!fmt) {
1231 em28xx_videodbg("Fourcc format (%08x) invalid.\n",
1232 f->fmt.pix.pixelformat);
1233 return -EINVAL;
1234 }
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001235
Mauro Carvalho Chehab55699962009-07-13 20:15:02 -03001236 if (dev->board.is_em2800) {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001237 /* the em2800 can only scale down to 50% */
Trent Piephoccb83402009-05-30 21:45:46 -03001238 height = height > (3 * maxh / 4) ? maxh : maxh / 2;
1239 width = width > (3 * maxw / 4) ? maxw : maxw / 2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001240 /*
1241 * MaxPacketSize for em2800 is too small to capture at full
1242 * resolution use half of maxw as the scaler can only scale
1243 * to 50%
1244 */
Sascha Sommer1020d132012-01-08 16:54:28 -03001245 if (width == maxw && height == maxh)
1246 width /= 2;
Trent Piephoccb83402009-05-30 21:45:46 -03001247 } else {
1248 /* width must even because of the YUYV format
1249 height must be even because of interlacing */
Devin Heitmuellere3ba4d32009-09-15 00:18:06 -03001250 v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh,
1251 1, 0);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001252 }
1253
Frank Schaefer6b09a212013-02-10 16:05:12 -03001254 size_to_scale(dev, width, height, &hscale, &vscale);
Hans Verkuil46f85972013-03-30 05:31:42 -03001255 scale_to_size(dev, hscale, vscale, &width, &height);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001256
1257 f->fmt.pix.width = width;
1258 f->fmt.pix.height = height;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001259 f->fmt.pix.pixelformat = fmt->fourcc;
Hans Verkuile6066db2013-02-06 08:14:47 -03001260 f->fmt.pix.bytesperline = (width * fmt->depth + 7) >> 3;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001261 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001262 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -03001263 if (dev->progressive)
1264 f->fmt.pix.field = V4L2_FIELD_NONE;
1265 else
1266 f->fmt.pix.field = dev->interlaced ?
1267 V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
Alban Browaeys51dd4d72013-07-16 19:06:46 -03001268 f->fmt.pix.priv = 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001269
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001270 return 0;
1271}
1272
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001273static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc,
1274 unsigned width, unsigned height)
1275{
1276 struct em28xx_fmt *fmt;
1277
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001278 fmt = format_by_fourcc(fourcc);
1279 if (!fmt)
1280 return -EINVAL;
1281
1282 dev->format = fmt;
1283 dev->width = width;
1284 dev->height = height;
1285
1286 /* set new image size */
Frank Schaefer6b09a212013-02-10 16:05:12 -03001287 size_to_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001288
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001289 em28xx_resolution_set(dev);
1290
1291 return 0;
1292}
1293
Hans Verkuil78b526a2008-05-28 12:16:41 -03001294static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001295 struct v4l2_format *f)
1296{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001297 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001298
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001299 if (dev->streaming_users > 0)
1300 return -EBUSY;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001301
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001302 vidioc_try_fmt_vid_cap(file, priv, f);
1303
Hans Verkuil0499a5a2010-09-26 07:34:45 -03001304 return em28xx_set_video_format(dev, f->fmt.pix.pixelformat,
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001305 f->fmt.pix.width, f->fmt.pix.height);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001306}
1307
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001308static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
1309{
1310 struct em28xx_fh *fh = priv;
1311 struct em28xx *dev = fh->dev;
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001312
1313 *norm = dev->norm;
1314
1315 return 0;
1316}
1317
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001318static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm)
1319{
1320 struct em28xx_fh *fh = priv;
1321 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001322
1323 v4l2_device_call_all(&dev->v4l2_dev, 0, video, querystd, norm);
1324
1325 return 0;
1326}
1327
Hans Verkuil314527a2013-03-15 06:10:40 -03001328static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001329{
1330 struct em28xx_fh *fh = priv;
1331 struct em28xx *dev = fh->dev;
1332 struct v4l2_format f;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001333
Hans Verkuil314527a2013-03-15 06:10:40 -03001334 if (norm == dev->norm)
Hans Verkuild8c95c02012-09-07 07:31:54 -03001335 return 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001336
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001337 if (dev->streaming_users > 0)
Hans Verkuild8c95c02012-09-07 07:31:54 -03001338 return -EBUSY;
Hans Verkuild8c95c02012-09-07 07:31:54 -03001339
Hans Verkuil314527a2013-03-15 06:10:40 -03001340 dev->norm = norm;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001341
1342 /* Adjusts width/height, if needed */
Hans Verkuild8c95c02012-09-07 07:31:54 -03001343 f.fmt.pix.width = 720;
Hans Verkuil314527a2013-03-15 06:10:40 -03001344 f.fmt.pix.height = (norm & V4L2_STD_525_60) ? 480 : 576;
Hans Verkuil78b526a2008-05-28 12:16:41 -03001345 vidioc_try_fmt_vid_cap(file, priv, &f);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001346
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001347 /* set new image size */
1348 dev->width = f.fmt.pix.width;
1349 dev->height = f.fmt.pix.height;
Frank Schaefer6b09a212013-02-10 16:05:12 -03001350 size_to_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001351
1352 em28xx_resolution_set(dev);
Hans Verkuilf41737e2009-04-01 03:52:39 -03001353 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001354
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001355 return 0;
1356}
1357
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001358static int vidioc_g_parm(struct file *file, void *priv,
1359 struct v4l2_streamparm *p)
1360{
1361 struct em28xx_fh *fh = priv;
1362 struct em28xx *dev = fh->dev;
1363 int rc = 0;
1364
Hans Verkuil86ff7f12012-09-07 06:16:03 -03001365 p->parm.capture.readbuffers = EM28XX_MIN_BUF;
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001366 if (dev->board.is_webcam)
1367 rc = v4l2_device_call_until_err(&dev->v4l2_dev, 0,
1368 video, g_parm, p);
1369 else
1370 v4l2_video_std_frame_period(dev->norm,
1371 &p->parm.capture.timeperframe);
1372
1373 return rc;
1374}
1375
1376static int vidioc_s_parm(struct file *file, void *priv,
1377 struct v4l2_streamparm *p)
1378{
1379 struct em28xx_fh *fh = priv;
1380 struct em28xx *dev = fh->dev;
1381
Hans Verkuil86ff7f12012-09-07 06:16:03 -03001382 p->parm.capture.readbuffers = EM28XX_MIN_BUF;
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001383 return v4l2_device_call_until_err(&dev->v4l2_dev, 0, video, s_parm, p);
1384}
1385
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001386static const char *iname[] = {
1387 [EM28XX_VMUX_COMPOSITE1] = "Composite1",
1388 [EM28XX_VMUX_COMPOSITE2] = "Composite2",
1389 [EM28XX_VMUX_COMPOSITE3] = "Composite3",
1390 [EM28XX_VMUX_COMPOSITE4] = "Composite4",
1391 [EM28XX_VMUX_SVIDEO] = "S-Video",
1392 [EM28XX_VMUX_TELEVISION] = "Television",
1393 [EM28XX_VMUX_CABLE] = "Cable TV",
1394 [EM28XX_VMUX_DVB] = "DVB",
1395 [EM28XX_VMUX_DEBUG] = "for debug only",
1396};
1397
1398static int vidioc_enum_input(struct file *file, void *priv,
1399 struct v4l2_input *i)
1400{
1401 struct em28xx_fh *fh = priv;
1402 struct em28xx *dev = fh->dev;
1403 unsigned int n;
1404
1405 n = i->index;
1406 if (n >= MAX_EM28XX_INPUT)
1407 return -EINVAL;
1408 if (0 == INPUT(n)->type)
1409 return -EINVAL;
1410
1411 i->index = n;
1412 i->type = V4L2_INPUT_TYPE_CAMERA;
1413
1414 strcpy(i->name, iname[INPUT(n)->type]);
1415
1416 if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type) ||
1417 (EM28XX_VMUX_CABLE == INPUT(n)->type))
1418 i->type = V4L2_INPUT_TYPE_TUNER;
1419
Mauro Carvalho Chehab7d497f82007-11-11 14:15:34 -03001420 i->std = dev->vdev->tvnorms;
Hans Verkuild8c95c02012-09-07 07:31:54 -03001421 /* webcams do not have the STD API */
1422 if (dev->board.is_webcam)
1423 i->capabilities = 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001424
1425 return 0;
1426}
1427
1428static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1429{
1430 struct em28xx_fh *fh = priv;
1431 struct em28xx *dev = fh->dev;
1432
1433 *i = dev->ctl_input;
1434
1435 return 0;
1436}
1437
1438static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
1439{
1440 struct em28xx_fh *fh = priv;
1441 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001442
1443 if (i >= MAX_EM28XX_INPUT)
1444 return -EINVAL;
1445 if (0 == INPUT(i)->type)
1446 return -EINVAL;
1447
Ezequiel García96371fc2012-03-23 18:09:34 -03001448 video_mux(dev, i);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001449 return 0;
1450}
1451
1452static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
1453{
1454 struct em28xx_fh *fh = priv;
1455 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001456
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001457 switch (a->index) {
1458 case EM28XX_AMUX_VIDEO:
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001459 strcpy(a->name, "Television");
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001460 break;
1461 case EM28XX_AMUX_LINE_IN:
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001462 strcpy(a->name, "Line In");
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001463 break;
1464 case EM28XX_AMUX_VIDEO2:
1465 strcpy(a->name, "Television alt");
1466 break;
1467 case EM28XX_AMUX_PHONE:
1468 strcpy(a->name, "Phone");
1469 break;
1470 case EM28XX_AMUX_MIC:
1471 strcpy(a->name, "Mic");
1472 break;
1473 case EM28XX_AMUX_CD:
1474 strcpy(a->name, "CD");
1475 break;
1476 case EM28XX_AMUX_AUX:
1477 strcpy(a->name, "Aux");
1478 break;
1479 case EM28XX_AMUX_PCM_OUT:
1480 strcpy(a->name, "PCM");
1481 break;
1482 default:
1483 return -EINVAL;
1484 }
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001485
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001486 a->index = dev->ctl_ainput;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001487 a->capability = V4L2_AUDCAP_STEREO;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001488
1489 return 0;
1490}
1491
Hans Verkuil0e8025b92012-09-04 11:59:31 -03001492static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001493{
1494 struct em28xx_fh *fh = priv;
1495 struct em28xx *dev = fh->dev;
1496
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03001497 if (a->index >= MAX_EM28XX_INPUT)
1498 return -EINVAL;
1499 if (0 == INPUT(a->index)->type)
1500 return -EINVAL;
1501
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001502 dev->ctl_ainput = INPUT(a->index)->amux;
1503 dev->ctl_aoutput = INPUT(a->index)->aout;
Mauro Carvalho Chehabe879b8e2008-11-20 13:39:39 -03001504
1505 if (!dev->ctl_aoutput)
1506 dev->ctl_aoutput = EM28XX_AOUT_MASTER;
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001507
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001508 return 0;
1509}
1510
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001511static int vidioc_g_tuner(struct file *file, void *priv,
1512 struct v4l2_tuner *t)
1513{
1514 struct em28xx_fh *fh = priv;
1515 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001516
1517 if (0 != t->index)
1518 return -EINVAL;
1519
1520 strcpy(t->name, "Tuner");
1521
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03001522 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001523 return 0;
1524}
1525
1526static int vidioc_s_tuner(struct file *file, void *priv,
Hans Verkuil2f73c7c2013-03-15 06:10:06 -03001527 const struct v4l2_tuner *t)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001528{
1529 struct em28xx_fh *fh = priv;
1530 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001531
1532 if (0 != t->index)
1533 return -EINVAL;
1534
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03001535 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001536 return 0;
1537}
1538
1539static int vidioc_g_frequency(struct file *file, void *priv,
1540 struct v4l2_frequency *f)
1541{
1542 struct em28xx_fh *fh = priv;
1543 struct em28xx *dev = fh->dev;
1544
Hans Verkuil20deebf2012-09-06 10:07:25 -03001545 if (0 != f->tuner)
1546 return -EINVAL;
1547
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001548 f->frequency = dev->ctl_freq;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001549 return 0;
1550}
1551
1552static int vidioc_s_frequency(struct file *file, void *priv,
Hans Verkuilb530a442013-03-19 04:09:26 -03001553 const struct v4l2_frequency *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001554{
Hans Verkuilb530a442013-03-19 04:09:26 -03001555 struct v4l2_frequency new_freq = *f;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001556 struct em28xx_fh *fh = priv;
1557 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001558
1559 if (0 != f->tuner)
1560 return -EINVAL;
1561
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03001562 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, f);
Hans Verkuilb530a442013-03-19 04:09:26 -03001563 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_frequency, &new_freq);
1564 dev->ctl_freq = new_freq.frequency;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001565
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001566 return 0;
1567}
1568
Hans Verkuilcd634f12013-03-27 08:04:23 -03001569#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuil96b03d22013-04-06 06:16:58 -03001570static int vidioc_g_chip_info(struct file *file, void *priv,
1571 struct v4l2_dbg_chip_info *chip)
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001572{
1573 struct em28xx_fh *fh = priv;
1574 struct em28xx *dev = fh->dev;
1575
1576 if (chip->match.addr > 1)
1577 return -EINVAL;
1578 if (chip->match.addr == 1)
1579 strlcpy(chip->name, "ac97", sizeof(chip->name));
1580 else
1581 strlcpy(chip->name, dev->v4l2_dev.name, sizeof(chip->name));
1582 return 0;
1583}
1584
Frank Schaefer35deba32013-02-07 13:39:19 -03001585static int em28xx_reg_len(int reg)
1586{
1587 switch (reg) {
1588 case EM28XX_R40_AC97LSB:
1589 case EM28XX_R30_HSCALELOW:
1590 case EM28XX_R32_VSCALELOW:
1591 return 2;
1592 default:
1593 return 1;
1594 }
1595}
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001596
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001597static int vidioc_g_register(struct file *file, void *priv,
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001598 struct v4l2_dbg_register *reg)
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001599{
1600 struct em28xx_fh *fh = priv;
1601 struct em28xx *dev = fh->dev;
1602 int ret;
1603
Hans Verkuilabca2052013-05-29 06:59:35 -03001604 if (reg->match.addr > 1)
1605 return -EINVAL;
1606 if (reg->match.addr) {
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001607 ret = em28xx_read_ac97(dev, reg->reg);
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001608 if (ret < 0)
1609 return ret;
1610
1611 reg->val = ret;
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001612 reg->size = 1;
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001613 return 0;
1614 }
1615
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001616 /* Match host */
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001617 reg->size = em28xx_reg_len(reg->reg);
1618 if (reg->size == 1) {
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001619 ret = em28xx_read_reg(dev, reg->reg);
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001620
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001621 if (ret < 0)
1622 return ret;
1623
1624 reg->val = ret;
1625 } else {
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001626 __le16 val = 0;
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001627 ret = dev->em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001628 reg->reg, (char *)&val, 2);
1629 if (ret < 0)
1630 return ret;
1631
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001632 reg->val = le16_to_cpu(val);
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001633 }
1634
1635 return 0;
1636}
1637
1638static int vidioc_s_register(struct file *file, void *priv,
Hans Verkuil977ba3b2013-03-24 08:28:46 -03001639 const struct v4l2_dbg_register *reg)
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001640{
1641 struct em28xx_fh *fh = priv;
1642 struct em28xx *dev = fh->dev;
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001643 __le16 buf;
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001644
Hans Verkuilabca2052013-05-29 06:59:35 -03001645 if (reg->match.addr > 1)
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001646 return -EINVAL;
Hans Verkuilabca2052013-05-29 06:59:35 -03001647 if (reg->match.addr)
1648 return em28xx_write_ac97(dev, reg->reg, reg->val);
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001649
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001650 /* Match host */
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001651 buf = cpu_to_le16(reg->val);
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001652
Hans Verkuil0499a5a2010-09-26 07:34:45 -03001653 return em28xx_write_regs(dev, reg->reg, (char *)&buf,
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001654 em28xx_reg_len(reg->reg));
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001655}
1656#endif
1657
1658
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001659static int vidioc_querycap(struct file *file, void *priv,
1660 struct v4l2_capability *cap)
1661{
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001662 struct video_device *vdev = video_devdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001663 struct em28xx_fh *fh = priv;
1664 struct em28xx *dev = fh->dev;
1665
1666 strlcpy(cap->driver, "em28xx", sizeof(cap->driver));
1667 strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card));
Thierry MERLEcb977162009-01-20 18:01:33 -03001668 usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001669
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001670 if (vdev->vfl_type == VFL_TYPE_GRABBER)
1671 cap->device_caps = V4L2_CAP_READWRITE |
1672 V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1673 else if (vdev->vfl_type == VFL_TYPE_RADIO)
1674 cap->device_caps = V4L2_CAP_RADIO;
1675 else
Hans Verkuil1d179ee2012-09-07 08:45:10 -03001676 cap->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE;
Devin Heitmueller04146142009-09-11 00:08:44 -03001677
Mauro Carvalho Chehab6c428b52009-08-04 19:52:37 -03001678 if (dev->audio_mode.has_audio)
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001679 cap->device_caps |= V4L2_CAP_AUDIO;
Mauro Carvalho Chehab6c428b52009-08-04 19:52:37 -03001680
Mauro Carvalho Chehabed086312008-01-24 06:59:20 -03001681 if (dev->tuner_type != TUNER_ABSENT)
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001682 cap->device_caps |= V4L2_CAP_TUNER;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001683
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001684 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS |
1685 V4L2_CAP_READWRITE | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1686 if (dev->vbi_dev)
Hans Verkuil1d179ee2012-09-07 08:45:10 -03001687 cap->capabilities |= V4L2_CAP_VBI_CAPTURE;
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001688 if (dev->radio_dev)
1689 cap->capabilities |= V4L2_CAP_RADIO;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001690 return 0;
1691}
1692
Hans Verkuil78b526a2008-05-28 12:16:41 -03001693static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001694 struct v4l2_fmtdesc *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001695{
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001696 if (unlikely(f->index >= ARRAY_SIZE(format)))
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001697 return -EINVAL;
1698
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001699 strlcpy(f->description, format[f->index].name, sizeof(f->description));
1700 f->pixelformat = format[f->index].fourcc;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001701
1702 return 0;
1703}
1704
Mauro Carvalho Chehab1c5c50682011-10-16 13:52:43 -02001705static int vidioc_enum_framesizes(struct file *file, void *priv,
1706 struct v4l2_frmsizeenum *fsize)
1707{
1708 struct em28xx_fh *fh = priv;
1709 struct em28xx *dev = fh->dev;
1710 struct em28xx_fmt *fmt;
1711 unsigned int maxw = norm_maxw(dev);
1712 unsigned int maxh = norm_maxh(dev);
1713
1714 fmt = format_by_fourcc(fsize->pixel_format);
1715 if (!fmt) {
1716 em28xx_videodbg("Fourcc format (%08x) invalid.\n",
1717 fsize->pixel_format);
1718 return -EINVAL;
1719 }
1720
1721 if (dev->board.is_em2800) {
1722 if (fsize->index > 1)
1723 return -EINVAL;
1724 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
1725 fsize->discrete.width = maxw / (1 + fsize->index);
1726 fsize->discrete.height = maxh / (1 + fsize->index);
1727 return 0;
1728 }
1729
1730 if (fsize->index != 0)
1731 return -EINVAL;
1732
1733 /* Report a continuous range */
1734 fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
Frank Schaefer6c3598e2013-02-10 16:05:14 -03001735 scale_to_size(dev, EM28XX_HVSCALE_MAX, EM28XX_HVSCALE_MAX,
1736 &fsize->stepwise.min_width, &fsize->stepwise.min_height);
1737 if (fsize->stepwise.min_width < 48)
1738 fsize->stepwise.min_width = 48;
1739 if (fsize->stepwise.min_height < 38)
1740 fsize->stepwise.min_height = 38;
Mauro Carvalho Chehab1c5c50682011-10-16 13:52:43 -02001741 fsize->stepwise.max_width = maxw;
1742 fsize->stepwise.max_height = maxh;
1743 fsize->stepwise.step_width = 1;
1744 fsize->stepwise.step_height = 1;
1745 return 0;
1746}
1747
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001748/* RAW VBI ioctls */
1749
1750static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
1751 struct v4l2_format *format)
1752{
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001753 struct em28xx_fh *fh = priv;
1754 struct em28xx *dev = fh->dev;
1755
1756 format->fmt.vbi.samples_per_line = dev->vbi_width;
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001757 format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
1758 format->fmt.vbi.offset = 0;
1759 format->fmt.vbi.flags = 0;
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001760 format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
1761 format->fmt.vbi.count[0] = dev->vbi_height;
1762 format->fmt.vbi.count[1] = dev->vbi_height;
Hans Verkuil2a221d32012-09-07 08:51:32 -03001763 memset(format->fmt.vbi.reserved, 0, sizeof(format->fmt.vbi.reserved));
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001764
1765 /* Varies by video standard (NTSC, PAL, etc.) */
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001766 if (dev->norm & V4L2_STD_525_60) {
1767 /* NTSC */
1768 format->fmt.vbi.start[0] = 10;
1769 format->fmt.vbi.start[1] = 273;
1770 } else if (dev->norm & V4L2_STD_625_50) {
1771 /* PAL */
1772 format->fmt.vbi.start[0] = 6;
1773 format->fmt.vbi.start[1] = 318;
1774 }
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001775
1776 return 0;
1777}
1778
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001779/* ----------------------------------------------------------- */
1780/* RADIO ESPECIFIC IOCTLS */
1781/* ----------------------------------------------------------- */
1782
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001783static int radio_g_tuner(struct file *file, void *priv,
1784 struct v4l2_tuner *t)
1785{
1786 struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;
1787
1788 if (unlikely(t->index > 0))
1789 return -EINVAL;
1790
1791 strcpy(t->name, "Radio");
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001792
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03001793 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001794
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001795 return 0;
1796}
1797
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001798static int radio_s_tuner(struct file *file, void *priv,
Hans Verkuil2f73c7c2013-03-15 06:10:06 -03001799 const struct v4l2_tuner *t)
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001800{
1801 struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;
1802
1803 if (0 != t->index)
1804 return -EINVAL;
1805
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03001806 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001807
1808 return 0;
1809}
1810
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001811/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08001812 * em28xx_v4l2_open()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001813 * inits the device and starts isoc transfer
1814 */
Hans Verkuilbec43662008-12-30 06:58:20 -03001815static int em28xx_v4l2_open(struct file *filp)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001816{
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001817 struct video_device *vdev = video_devdata(filp);
1818 struct em28xx *dev = video_drvdata(filp);
1819 enum v4l2_buf_type fh_type = 0;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001820 struct em28xx_fh *fh;
Markus Rechberger9c755412005-11-08 21:37:52 -08001821
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001822 switch (vdev->vfl_type) {
1823 case VFL_TYPE_GRABBER:
1824 fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1825 break;
1826 case VFL_TYPE_VBI:
1827 fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
1828 break;
Frank Schaefer4e170242014-01-12 13:24:18 -03001829 case VFL_TYPE_RADIO:
1830 break;
1831 default:
1832 return -EINVAL;
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001833 }
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03001834
Laurent Pinchart50462eb2009-12-10 11:47:13 -02001835 em28xx_videodbg("open dev=%s type=%s users=%d\n",
1836 video_device_node_name(vdev), v4l2_type_names[fh_type],
1837 dev->users);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001838
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001839
Hans Verkuil876cb142012-06-23 08:12:47 -03001840 if (mutex_lock_interruptible(&dev->lock))
1841 return -ERESTARTSYS;
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001842 fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001843 if (!fh) {
1844 em28xx_errdev("em28xx-video.c: Out of memory?!\n");
Hans Verkuil876cb142012-06-23 08:12:47 -03001845 mutex_unlock(&dev->lock);
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001846 return -ENOMEM;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001847 }
Hans Verkuil69a61642012-09-07 05:52:40 -03001848 v4l2_fh_init(&fh->fh, vdev);
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001849 fh->dev = dev;
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001850 fh->type = fh_type;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001851 filp->private_data = fh;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001852
Frank Schaefer4e170242014-01-12 13:24:18 -03001853 if (dev->users == 0) {
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001854 em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001855
Frank Schaefer4e170242014-01-12 13:24:18 -03001856 if (vdev->vfl_type != VFL_TYPE_RADIO)
1857 em28xx_resolution_set(dev);
1858
1859 /*
1860 * Needed, since GPIO might have disabled power
1861 * of some i2c devices
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001862 */
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03001863 em28xx_wake_i2c(dev);
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02001864 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001865
1866 if (vdev->vfl_type == VFL_TYPE_RADIO) {
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001867 em28xx_videodbg("video_open: setting radio device\n");
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03001868 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_radio);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001869 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001870
1871 dev->users++;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001872
Hans Verkuil876cb142012-06-23 08:12:47 -03001873 mutex_unlock(&dev->lock);
Hans Verkuil69a61642012-09-07 05:52:40 -03001874 v4l2_fh_add(&fh->fh);
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001875
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001876 return 0;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001877}
1878
1879/*
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001880 * em28xx_v4l2_fini()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001881 * unregisters the v4l2,i2c and usb devices
1882 * called when the device gets disconected or at module unload
1883*/
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001884static int em28xx_v4l2_fini(struct em28xx *dev)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001885{
Mauro Carvalho Chehab822b8de2014-01-06 05:27:47 -03001886 if (dev->is_audio_only) {
1887 /* Shouldn't initialize IR for this interface */
1888 return 0;
1889 }
1890
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001891 if (!dev->has_video) {
1892 /* This device does not support the v4l2 extension */
1893 return 0;
1894 }
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02001895
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001896 if (dev->radio_dev) {
Laurent Pinchartf0813b42009-11-27 13:57:30 -03001897 if (video_is_registered(dev->radio_dev))
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001898 video_unregister_device(dev->radio_dev);
1899 else
1900 video_device_release(dev->radio_dev);
1901 dev->radio_dev = NULL;
1902 }
1903 if (dev->vbi_dev) {
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001904 em28xx_info("V4L2 device %s deregistered\n",
1905 video_device_node_name(dev->vbi_dev));
Laurent Pinchartf0813b42009-11-27 13:57:30 -03001906 if (video_is_registered(dev->vbi_dev))
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001907 video_unregister_device(dev->vbi_dev);
1908 else
1909 video_device_release(dev->vbi_dev);
1910 dev->vbi_dev = NULL;
1911 }
1912 if (dev->vdev) {
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001913 em28xx_info("V4L2 device %s deregistered\n",
1914 video_device_node_name(dev->vdev));
Laurent Pinchartf0813b42009-11-27 13:57:30 -03001915 if (video_is_registered(dev->vdev))
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001916 video_unregister_device(dev->vdev);
1917 else
1918 video_device_release(dev->vdev);
1919 dev->vdev = NULL;
1920 }
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001921
1922 return 0;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001923}
1924
1925/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08001926 * em28xx_v4l2_close()
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001927 * stops streaming and deallocates all resources allocated by the v4l2
1928 * calls and ioctls
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001929 */
Hans Verkuilbec43662008-12-30 06:58:20 -03001930static int em28xx_v4l2_close(struct file *filp)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001931{
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001932 struct em28xx_fh *fh = filp->private_data;
1933 struct em28xx *dev = fh->dev;
1934 int errCode;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001935
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001936 em28xx_videodbg("users=%d\n", dev->users);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001937
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001938 vb2_fop_release(filp);
Ricardo Ribalda98c24dcd2013-11-06 05:39:35 -03001939 mutex_lock(&dev->lock);
Devin Heitmueller8c873d32009-09-03 00:23:27 -03001940
Devin Heitmuellere3ba4d32009-09-15 00:18:06 -03001941 if (dev->users == 1) {
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001942 /* the device is already disconnect,
1943 free the remaining resources */
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001944
Frank Schaefer2665c292012-12-27 19:02:43 -03001945 if (dev->disconnected) {
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001946 em28xx_release_resources(dev);
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001947 v4l2_ctrl_handler_free(&dev->ctrl_handler);
1948 v4l2_device_unregister(&dev->v4l2_dev);
Frank Schaefer0cf544a2012-11-08 14:11:49 -03001949 kfree(dev->alt_max_pkt_size_isoc);
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001950 goto exit;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001951 }
1952
Mauro Carvalho Chehabeb6c9632008-12-05 10:39:12 -03001953 /* Save some power by putting tuner to sleep */
Laurent Pinchart622b8282009-10-05 10:48:17 -03001954 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
Mauro Carvalho Chehabeb6c9632008-12-05 10:39:12 -03001955
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001956 /* do this before setting alternate! */
Mauro Carvalho Chehab2fe3e2e2008-11-27 09:10:40 -03001957 em28xx_set_mode(dev, EM28XX_SUSPEND);
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001958
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001959 /* set alternate 0 */
1960 dev->alt = 0;
1961 em28xx_videodbg("setting alternate 0\n");
1962 errCode = usb_set_interface(dev->udev, 0, 0);
1963 if (errCode < 0) {
1964 em28xx_errdev("cannot change alternate number to "
1965 "0 (error=%i)\n", errCode);
1966 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001967 }
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001968
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001969exit:
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001970 dev->users--;
Hans Verkuil876cb142012-06-23 08:12:47 -03001971 mutex_unlock(&dev->lock);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001972 return 0;
1973}
1974
Hans Verkuilbec43662008-12-30 06:58:20 -03001975static const struct v4l2_file_operations em28xx_v4l_fops = {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001976 .owner = THIS_MODULE,
1977 .open = em28xx_v4l2_open,
1978 .release = em28xx_v4l2_close,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001979 .read = vb2_fop_read,
1980 .poll = vb2_fop_poll,
1981 .mmap = vb2_fop_mmap,
Hans Verkuil0499a5a2010-09-26 07:34:45 -03001982 .unlocked_ioctl = video_ioctl2,
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001983};
1984
Hans Verkuila3998102008-07-21 02:57:38 -03001985static const struct v4l2_ioctl_ops video_ioctl_ops = {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001986 .vidioc_querycap = vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03001987 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1988 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1989 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1990 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001991 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Hans Verkuil2a221d32012-09-07 08:51:32 -03001992 .vidioc_try_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Frank Schaeferaab34612013-02-07 13:39:16 -03001993 .vidioc_s_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Mauro Carvalho Chehab1c5c50682011-10-16 13:52:43 -02001994 .vidioc_enum_framesizes = vidioc_enum_framesizes,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001995 .vidioc_g_audio = vidioc_g_audio,
1996 .vidioc_s_audio = vidioc_s_audio,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001997
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001998 .vidioc_reqbufs = vb2_ioctl_reqbufs,
1999 .vidioc_create_bufs = vb2_ioctl_create_bufs,
2000 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
2001 .vidioc_querybuf = vb2_ioctl_querybuf,
2002 .vidioc_qbuf = vb2_ioctl_qbuf,
2003 .vidioc_dqbuf = vb2_ioctl_dqbuf,
2004
Devin Heitmueller19bf0032009-09-11 00:40:18 -03002005 .vidioc_g_std = vidioc_g_std,
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03002006 .vidioc_querystd = vidioc_querystd,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002007 .vidioc_s_std = vidioc_s_std,
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03002008 .vidioc_g_parm = vidioc_g_parm,
2009 .vidioc_s_parm = vidioc_s_parm,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002010 .vidioc_enum_input = vidioc_enum_input,
2011 .vidioc_g_input = vidioc_g_input,
2012 .vidioc_s_input = vidioc_s_input,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002013 .vidioc_streamon = vb2_ioctl_streamon,
2014 .vidioc_streamoff = vb2_ioctl_streamoff,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002015 .vidioc_g_tuner = vidioc_g_tuner,
2016 .vidioc_s_tuner = vidioc_s_tuner,
2017 .vidioc_g_frequency = vidioc_g_frequency,
2018 .vidioc_s_frequency = vidioc_s_frequency,
Hans Verkuil50fdf402012-09-07 06:10:12 -03002019 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
2020 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002021#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuil96b03d22013-04-06 06:16:58 -03002022 .vidioc_g_chip_info = vidioc_g_chip_info,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002023 .vidioc_g_register = vidioc_g_register,
2024 .vidioc_s_register = vidioc_s_register,
2025#endif
Hans Verkuila3998102008-07-21 02:57:38 -03002026};
2027
2028static const struct video_device em28xx_video_template = {
2029 .fops = &em28xx_v4l_fops,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002030 .release = video_device_release_empty,
Hans Verkuila3998102008-07-21 02:57:38 -03002031 .ioctl_ops = &video_ioctl_ops,
2032
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002033 .tvnorms = V4L2_STD_ALL,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002034};
2035
Hans Verkuilbec43662008-12-30 06:58:20 -03002036static const struct v4l2_file_operations radio_fops = {
Hans Verkuila3998102008-07-21 02:57:38 -03002037 .owner = THIS_MODULE,
2038 .open = em28xx_v4l2_open,
2039 .release = em28xx_v4l2_close,
Hans Verkuil8fd0bda2010-12-18 09:59:51 -03002040 .unlocked_ioctl = video_ioctl2,
Hans Verkuila3998102008-07-21 02:57:38 -03002041};
2042
2043static const struct v4l2_ioctl_ops radio_ioctl_ops = {
Hans Verkuila9d79fe2012-09-06 07:31:04 -03002044 .vidioc_querycap = vidioc_querycap,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002045 .vidioc_g_tuner = radio_g_tuner,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002046 .vidioc_s_tuner = radio_s_tuner,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002047 .vidioc_g_frequency = vidioc_g_frequency,
2048 .vidioc_s_frequency = vidioc_s_frequency,
Hans Verkuil50fdf402012-09-07 06:10:12 -03002049 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
2050 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002051#ifdef CONFIG_VIDEO_ADV_DEBUG
Michal Marek430c73f2013-04-16 08:06:30 -03002052 .vidioc_g_chip_info = vidioc_g_chip_info,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002053 .vidioc_g_register = vidioc_g_register,
2054 .vidioc_s_register = vidioc_s_register,
2055#endif
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002056};
2057
Hans Verkuila3998102008-07-21 02:57:38 -03002058static struct video_device em28xx_radio_template = {
2059 .name = "em28xx-radio",
Hans Verkuila3998102008-07-21 02:57:38 -03002060 .fops = &radio_fops,
2061 .ioctl_ops = &radio_ioctl_ops,
Hans Verkuila3998102008-07-21 02:57:38 -03002062};
2063
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002064/* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */
2065static unsigned short saa711x_addrs[] = {
2066 0x4a >> 1, 0x48 >> 1, /* SAA7111, SAA7111A and SAA7113 */
2067 0x42 >> 1, 0x40 >> 1, /* SAA7114, SAA7115 and SAA7118 */
2068 I2C_CLIENT_END };
2069
2070static unsigned short tvp5150_addrs[] = {
2071 0xb8 >> 1,
2072 0xba >> 1,
2073 I2C_CLIENT_END
2074};
2075
2076static unsigned short msp3400_addrs[] = {
2077 0x80 >> 1,
2078 0x88 >> 1,
2079 I2C_CLIENT_END
2080};
2081
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03002082/******************************** usb interface ******************************/
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002083
Adrian Bunk532fe652008-01-28 22:10:48 -03002084static struct video_device *em28xx_vdev_init(struct em28xx *dev,
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -03002085 const struct video_device *template,
2086 const char *type_name)
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002087{
2088 struct video_device *vfd;
2089
2090 vfd = video_device_alloc();
2091 if (NULL == vfd)
2092 return NULL;
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03002093
2094 *vfd = *template;
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03002095 vfd->v4l2_dev = &dev->v4l2_dev;
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03002096 vfd->debug = video_debug;
Hans Verkuil0499a5a2010-09-26 07:34:45 -03002097 vfd->lock = &dev->lock;
Hans Verkuil69a61642012-09-07 05:52:40 -03002098 set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
Hans Verkuild8c95c02012-09-07 07:31:54 -03002099 if (dev->board.is_webcam)
2100 vfd->tvnorms = 0;
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002101
2102 snprintf(vfd->name, sizeof(vfd->name), "%s %s",
2103 dev->name, type_name);
2104
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02002105 video_set_drvdata(vfd, dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002106 return vfd;
2107}
2108
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002109static void em28xx_tuner_setup(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002110{
2111 struct tuner_setup tun_setup;
2112 struct v4l2_frequency f;
2113
2114 if (dev->tuner_type == TUNER_ABSENT)
2115 return;
2116
2117 memset(&tun_setup, 0, sizeof(tun_setup));
2118
2119 tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
2120 tun_setup.tuner_callback = em28xx_tuner_callback;
2121
2122 if (dev->board.radio.type) {
2123 tun_setup.type = dev->board.radio.type;
2124 tun_setup.addr = dev->board.radio_addr;
2125
2126 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup);
2127 }
2128
2129 if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type)) {
2130 tun_setup.type = dev->tuner_type;
2131 tun_setup.addr = dev->tuner_addr;
2132
2133 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup);
2134 }
2135
2136 if (dev->tda9887_conf) {
2137 struct v4l2_priv_tun_config tda9887_cfg;
2138
2139 tda9887_cfg.tuner = TUNER_TDA9887;
2140 tda9887_cfg.priv = &dev->tda9887_conf;
2141
2142 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, &tda9887_cfg);
2143 }
2144
2145 if (dev->tuner_type == TUNER_XC2028) {
2146 struct v4l2_priv_tun_config xc2028_cfg;
2147 struct xc2028_ctrl ctl;
2148
2149 memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
2150 memset(&ctl, 0, sizeof(ctl));
2151
2152 em28xx_setup_xc3028(dev, &ctl);
2153
2154 xc2028_cfg.tuner = TUNER_XC2028;
2155 xc2028_cfg.priv = &ctl;
2156
2157 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, &xc2028_cfg);
2158 }
2159
2160 /* configure tuner */
2161 f.tuner = 0;
2162 f.type = V4L2_TUNER_ANALOG_TV;
2163 f.frequency = 9076; /* just a magic number */
2164 dev->ctl_freq = f.frequency;
2165 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
2166}
2167
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002168static int em28xx_v4l2_init(struct em28xx *dev)
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002169{
Hans Verkuil081b9452012-09-07 05:43:59 -03002170 u8 val;
Mauro Carvalho Chehab2e5ef2d2008-12-28 22:26:36 -03002171 int ret;
Sascha Sommer1020d132012-01-08 16:54:28 -03002172 unsigned int maxw;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002173 struct v4l2_ctrl_handler *hdl = &dev->ctrl_handler;
2174
Mauro Carvalho Chehab822b8de2014-01-06 05:27:47 -03002175 if (dev->is_audio_only) {
2176 /* Shouldn't initialize IR for this interface */
2177 return 0;
2178 }
2179
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002180 if (!dev->has_video) {
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002181 /* This device does not support the v4l2 extension */
2182 return 0;
2183 }
Mauro Carvalho Chehab2e5ef2d2008-12-28 22:26:36 -03002184
Mauro Carvalho Chehab96346142013-12-26 12:41:03 -03002185 em28xx_info("Registering V4L2 extension\n");
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002186
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002187 mutex_lock(&dev->lock);
2188
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002189 ret = v4l2_device_register(&dev->udev->dev, &dev->v4l2_dev);
2190 if (ret < 0) {
2191 em28xx_errdev("Call to v4l2_device_register() failed!\n");
2192 goto err;
2193 }
2194
2195 v4l2_ctrl_handler_init(hdl, 8);
2196 dev->v4l2_dev.ctrl_handler = hdl;
2197
2198 /*
2199 * Default format, used for tvp5150 or saa711x output formats
2200 */
2201 dev->vinmode = 0x10;
2202 dev->vinctl = EM28XX_VINCTRL_INTERLACED |
2203 EM28XX_VINCTRL_CCIR656_ENABLE;
2204
2205 /* request some modules */
2206
2207 if (dev->board.has_msp34xx)
2208 v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap[dev->def_i2c_bus],
2209 "msp3400", 0, msp3400_addrs);
2210
2211 if (dev->board.decoder == EM28XX_SAA711X)
2212 v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap[dev->def_i2c_bus],
2213 "saa7115_auto", 0, saa711x_addrs);
2214
2215 if (dev->board.decoder == EM28XX_TVP5150)
2216 v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap[dev->def_i2c_bus],
2217 "tvp5150", 0, tvp5150_addrs);
2218
2219 if (dev->board.adecoder == EM28XX_TVAUDIO)
2220 v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap[dev->def_i2c_bus],
2221 "tvaudio", dev->board.tvaudio_addr, NULL);
2222
2223 /* Initialize tuner and camera */
2224
2225 if (dev->board.tuner_type != TUNER_ABSENT) {
2226 int has_demod = (dev->tda9887_conf & TDA9887_PRESENT);
2227
2228 if (dev->board.radio.type)
2229 v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap[dev->def_i2c_bus],
2230 "tuner", dev->board.radio_addr, NULL);
2231
2232 if (has_demod)
2233 v4l2_i2c_new_subdev(&dev->v4l2_dev,
2234 &dev->i2c_adap[dev->def_i2c_bus], "tuner",
2235 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
2236 if (dev->tuner_addr == 0) {
2237 enum v4l2_i2c_tuner_type type =
2238 has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV;
2239 struct v4l2_subdev *sd;
2240
2241 sd = v4l2_i2c_new_subdev(&dev->v4l2_dev,
2242 &dev->i2c_adap[dev->def_i2c_bus], "tuner",
2243 0, v4l2_i2c_tuner_addrs(type));
2244
2245 if (sd)
2246 dev->tuner_addr = v4l2_i2c_subdev_addr(sd);
2247 } else {
2248 v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap[dev->def_i2c_bus],
2249 "tuner", dev->tuner_addr, NULL);
2250 }
2251 }
2252
2253 em28xx_tuner_setup(dev);
2254 em28xx_init_camera(dev);
2255
2256 /* Configure audio */
2257 ret = em28xx_audio_setup(dev);
2258 if (ret < 0) {
2259 em28xx_errdev("%s: Error while setting audio - error [%d]!\n",
2260 __func__, ret);
2261 goto unregister_dev;
2262 }
2263 if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
2264 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
2265 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
2266 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
2267 V4L2_CID_AUDIO_VOLUME, 0, 0x1f, 1, 0x1f);
2268 } else {
2269 /* install the em28xx notify callback */
2270 v4l2_ctrl_notify(v4l2_ctrl_find(hdl, V4L2_CID_AUDIO_MUTE),
2271 em28xx_ctrl_notify, dev);
2272 v4l2_ctrl_notify(v4l2_ctrl_find(hdl, V4L2_CID_AUDIO_VOLUME),
2273 em28xx_ctrl_notify, dev);
2274 }
2275
2276 /* wake i2c devices */
2277 em28xx_wake_i2c(dev);
2278
2279 /* init video dma queues */
2280 INIT_LIST_HEAD(&dev->vidq.active);
2281 INIT_LIST_HEAD(&dev->vbiq.active);
2282
2283 if (dev->board.has_msp34xx) {
2284 /* Send a reset to other chips via gpio */
2285 ret = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xf7);
2286 if (ret < 0) {
2287 em28xx_errdev("%s: em28xx_write_reg - msp34xx(1) failed! error [%d]\n",
2288 __func__, ret);
2289 goto unregister_dev;
2290 }
2291 msleep(3);
2292
2293 ret = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xff);
2294 if (ret < 0) {
2295 em28xx_errdev("%s: em28xx_write_reg - msp34xx(2) failed! error [%d]\n",
2296 __func__, ret);
2297 goto unregister_dev;
2298 }
2299 msleep(3);
2300 }
2301
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002302 /* set default norm */
Hans Verkuild8c95c02012-09-07 07:31:54 -03002303 dev->norm = V4L2_STD_PAL;
Hans Verkuild5906dd2010-09-26 07:45:15 -03002304 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm);
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002305 dev->interlaced = EM28XX_INTERLACED_DEFAULT;
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002306
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002307 /* Analog specific initialization */
2308 dev->format = &format[0];
Sascha Sommer1020d132012-01-08 16:54:28 -03002309
2310 maxw = norm_maxw(dev);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002311 /* MaxPacketSize for em2800 is too small to capture at full resolution
2312 * use half of maxw as the scaler can only scale to 50% */
2313 if (dev->board.is_em2800)
2314 maxw /= 2;
Sascha Sommer1020d132012-01-08 16:54:28 -03002315
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03002316 em28xx_set_video_format(dev, format[0].fourcc,
Sascha Sommer1020d132012-01-08 16:54:28 -03002317 maxw, norm_maxh(dev));
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03002318
Ezequiel García96371fc2012-03-23 18:09:34 -03002319 video_mux(dev, 0);
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002320
2321 /* Audio defaults */
2322 dev->mute = 1;
2323 dev->volume = 0x1f;
2324
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002325/* em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -03002326 val = (u8)em28xx_read_reg(dev, EM28XX_R0F_XCLK);
2327 em28xx_write_reg(dev, EM28XX_R0F_XCLK,
2328 (EM28XX_XCLK_AUDIO_UNMUTE | val));
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002329
2330 em28xx_set_outfmt(dev);
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002331 em28xx_compression_disable(dev);
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002332
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002333 /* Add image controls */
2334 /* NOTE: at this point, the subdevices are already registered, so bridge
2335 * controls are only added/enabled when no subdevice provides them */
2336 if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_CONTRAST))
2337 v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops,
2338 V4L2_CID_CONTRAST,
2339 0, 0x1f, 1, CONTRAST_DEFAULT);
2340 if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_BRIGHTNESS))
2341 v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops,
2342 V4L2_CID_BRIGHTNESS,
2343 -0x80, 0x7f, 1, BRIGHTNESS_DEFAULT);
2344 if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_SATURATION))
2345 v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops,
2346 V4L2_CID_SATURATION,
2347 0, 0x1f, 1, SATURATION_DEFAULT);
2348 if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_BLUE_BALANCE))
2349 v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops,
2350 V4L2_CID_BLUE_BALANCE,
2351 -0x30, 0x30, 1, BLUE_BALANCE_DEFAULT);
2352 if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_RED_BALANCE))
2353 v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops,
2354 V4L2_CID_RED_BALANCE,
2355 -0x30, 0x30, 1, RED_BALANCE_DEFAULT);
2356 if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_SHARPNESS))
2357 v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops,
2358 V4L2_CID_SHARPNESS,
2359 0, 0x0f, 1, SHARPNESS_DEFAULT);
2360
2361 /* Reset image controls */
2362 em28xx_colorlevels_set_default(dev);
2363 v4l2_ctrl_handler_setup(&dev->ctrl_handler);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002364 ret = dev->ctrl_handler.error;
2365 if (ret)
2366 goto unregister_dev;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002367
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002368 /* allocate and fill video video_device struct */
2369 dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video");
2370 if (!dev->vdev) {
2371 em28xx_errdev("cannot allocate video_device.\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002372 ret = -ENODEV;
2373 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002374 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002375 dev->vdev->queue = &dev->vb_vidq;
2376 dev->vdev->queue->lock = &dev->vb_queue_lock;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002377
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002378 /* disable inapplicable ioctls */
2379 if (dev->board.is_webcam) {
2380 v4l2_disable_ioctl(dev->vdev, VIDIOC_QUERYSTD);
2381 v4l2_disable_ioctl(dev->vdev, VIDIOC_G_STD);
2382 v4l2_disable_ioctl(dev->vdev, VIDIOC_S_STD);
Frank Schaefer3bc85cc2013-02-07 13:39:12 -03002383 } else {
2384 v4l2_disable_ioctl(dev->vdev, VIDIOC_S_PARM);
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002385 }
Frank Schaefer66df67b2013-02-07 13:39:10 -03002386 if (dev->tuner_type == TUNER_ABSENT) {
2387 v4l2_disable_ioctl(dev->vdev, VIDIOC_G_TUNER);
2388 v4l2_disable_ioctl(dev->vdev, VIDIOC_S_TUNER);
2389 v4l2_disable_ioctl(dev->vdev, VIDIOC_G_FREQUENCY);
2390 v4l2_disable_ioctl(dev->vdev, VIDIOC_S_FREQUENCY);
2391 }
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002392 if (!dev->audio_mode.has_audio) {
2393 v4l2_disable_ioctl(dev->vdev, VIDIOC_G_AUDIO);
2394 v4l2_disable_ioctl(dev->vdev, VIDIOC_S_AUDIO);
2395 }
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002396
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002397 /* register v4l2 video video_device */
2398 ret = video_register_device(dev->vdev, VFL_TYPE_GRABBER,
2399 video_nr[dev->devno]);
2400 if (ret) {
2401 em28xx_errdev("unable to register video device (error=%i).\n",
2402 ret);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002403 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002404 }
2405
2406 /* Allocate and fill vbi video_device struct */
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002407 if (em28xx_vbi_supported(dev) == 1) {
2408 dev->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template,
2409 "vbi");
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002410
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002411 dev->vbi_dev->queue = &dev->vb_vbiq;
2412 dev->vbi_dev->queue->lock = &dev->vb_vbi_queue_lock;
2413
Frank Schaefer66df67b2013-02-07 13:39:10 -03002414 /* disable inapplicable ioctls */
Frank Schaefer83c8bcc2013-02-07 13:39:13 -03002415 v4l2_disable_ioctl(dev->vdev, VIDIOC_S_PARM);
Frank Schaefer66df67b2013-02-07 13:39:10 -03002416 if (dev->tuner_type == TUNER_ABSENT) {
2417 v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_G_TUNER);
2418 v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_S_TUNER);
2419 v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_G_FREQUENCY);
2420 v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_S_FREQUENCY);
2421 }
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002422 if (!dev->audio_mode.has_audio) {
2423 v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_G_AUDIO);
2424 v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_S_AUDIO);
2425 }
Frank Schaefer66df67b2013-02-07 13:39:10 -03002426
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002427 /* register v4l2 vbi video_device */
2428 ret = video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
2429 vbi_nr[dev->devno]);
2430 if (ret < 0) {
2431 em28xx_errdev("unable to register vbi device\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002432 goto unregister_dev;
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002433 }
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002434 }
2435
2436 if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) {
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -03002437 dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template,
2438 "radio");
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002439 if (!dev->radio_dev) {
2440 em28xx_errdev("cannot allocate video_device.\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002441 ret = -ENODEV;
2442 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002443 }
2444 ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO,
2445 radio_nr[dev->devno]);
2446 if (ret < 0) {
2447 em28xx_errdev("can't register radio device\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002448 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002449 }
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002450 em28xx_info("Registered radio device as %s\n",
2451 video_device_node_name(dev->radio_dev));
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002452 }
2453
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002454 em28xx_info("V4L2 video device registered as %s\n",
2455 video_device_node_name(dev->vdev));
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002456
2457 if (dev->vbi_dev)
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002458 em28xx_info("V4L2 VBI device registered as %s\n",
2459 video_device_node_name(dev->vbi_dev));
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002460
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002461 /* Save some power by putting tuner to sleep */
2462 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
2463
2464 /* initialize videobuf2 stuff */
2465 em28xx_vb2_setup(dev);
2466
Mauro Carvalho Chehab96346142013-12-26 12:41:03 -03002467 em28xx_info("V4L2 extension successfully initialized\n");
2468
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002469 mutex_unlock(&dev->lock);
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002470 return 0;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002471
2472unregister_dev:
2473 v4l2_ctrl_handler_free(&dev->ctrl_handler);
2474 v4l2_device_unregister(&dev->v4l2_dev);
2475err:
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002476 mutex_unlock(&dev->lock);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002477 return ret;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002478}
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002479
2480static struct em28xx_ops v4l2_ops = {
2481 .id = EM28XX_V4L2,
2482 .name = "Em28xx v4l2 Extension",
2483 .init = em28xx_v4l2_init,
2484 .fini = em28xx_v4l2_fini,
2485};
2486
2487static int __init em28xx_video_register(void)
2488{
2489 return em28xx_register_extension(&v4l2_ops);
2490}
2491
2492static void __exit em28xx_video_unregister(void)
2493{
2494 em28xx_unregister_extension(&v4l2_ops);
2495}
2496
2497module_init(em28xx_video_register);
2498module_exit(em28xx_video_unregister);