blob: 7d11a16e72b5e5ab4a420687d9d514420a1237ad [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 Chehabf7abcd32005-11-08 21:38:25 -080053#define DRIVER_DESC "Empia em28xx based USB video device driver"
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -030054
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -030055static unsigned int isoc_debug;
56module_param(isoc_debug, int, 0644);
57MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");
58
59static unsigned int disable_vbi;
60module_param(disable_vbi, int, 0644);
61MODULE_PARM_DESC(disable_vbi, "disable vbi support");
62
63static int alt;
64module_param(alt, int, 0644);
65MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint");
66
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -080067#define em28xx_videodbg(fmt, arg...) do {\
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -080068 if (video_debug) \
69 printk(KERN_INFO "%s %s :"fmt, \
Harvey Harrisond80e1342008-04-08 23:20:00 -030070 dev->name, __func__ , ##arg); } while (0)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080071
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -030072#define em28xx_isocdbg(fmt, arg...) \
73do {\
74 if (isoc_debug) { \
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -030075 printk(KERN_INFO "%s %s :"fmt, \
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -030076 dev->name, __func__ , ##arg); \
77 } \
78 } while (0)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -030079
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080080MODULE_AUTHOR(DRIVER_AUTHOR);
81MODULE_DESCRIPTION(DRIVER_DESC);
82MODULE_LICENSE("GPL");
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -030083MODULE_VERSION(EM28XX_VERSION);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080084
Frank Schaefere507e0e2013-03-26 13:38:38 -030085
86#define EM25XX_FRMDATAHDR_BYTE1 0x02
87#define EM25XX_FRMDATAHDR_BYTE2_STILL_IMAGE 0x20
88#define EM25XX_FRMDATAHDR_BYTE2_FRAME_END 0x02
89#define EM25XX_FRMDATAHDR_BYTE2_FRAME_ID 0x01
90#define EM25XX_FRMDATAHDR_BYTE2_MASK (EM25XX_FRMDATAHDR_BYTE2_STILL_IMAGE | \
91 EM25XX_FRMDATAHDR_BYTE2_FRAME_END | \
92 EM25XX_FRMDATAHDR_BYTE2_FRAME_ID)
93
94
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -030095static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
96static unsigned int vbi_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
97static unsigned int radio_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -030098
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -020099module_param_array(video_nr, int, NULL, 0444);
100module_param_array(vbi_nr, int, NULL, 0444);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -0300101module_param_array(radio_nr, int, NULL, 0444);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -0300102MODULE_PARM_DESC(video_nr, "video device numbers");
103MODULE_PARM_DESC(vbi_nr, "vbi device numbers");
104MODULE_PARM_DESC(radio_nr, "radio device numbers");
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800105
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -0300106static unsigned int video_debug;
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -0300107module_param(video_debug, int, 0644);
108MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800109
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -0300110/* supported video standards */
111static struct em28xx_fmt format[] = {
112 {
Mauro Carvalho Chehab58fc1ce2009-07-03 02:54:18 -0300113 .name = "16 bpp YUY2, 4:2:2, packed",
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -0300114 .fourcc = V4L2_PIX_FMT_YUYV,
115 .depth = 16,
Devin Heitmueller3fbf9302008-12-29 23:34:37 -0300116 .reg = EM28XX_OUTFMT_YUV422_Y0UY1V,
Mauro Carvalho Chehab43cb9fe2009-06-30 08:36:17 -0300117 }, {
Mauro Carvalho Chehab58fc1ce2009-07-03 02:54:18 -0300118 .name = "16 bpp RGB 565, LE",
Mauro Carvalho Chehab43cb9fe2009-06-30 08:36:17 -0300119 .fourcc = V4L2_PIX_FMT_RGB565,
120 .depth = 16,
Mauro Carvalho Chehab58fc1ce2009-07-03 02:54:18 -0300121 .reg = EM28XX_OUTFMT_RGB_16_656,
122 }, {
123 .name = "8 bpp Bayer BGBG..GRGR",
124 .fourcc = V4L2_PIX_FMT_SBGGR8,
125 .depth = 8,
126 .reg = EM28XX_OUTFMT_RGB_8_BGBG,
127 }, {
128 .name = "8 bpp Bayer GRGR..BGBG",
129 .fourcc = V4L2_PIX_FMT_SGRBG8,
130 .depth = 8,
131 .reg = EM28XX_OUTFMT_RGB_8_GRGR,
132 }, {
133 .name = "8 bpp Bayer GBGB..RGRG",
134 .fourcc = V4L2_PIX_FMT_SGBRG8,
135 .depth = 8,
136 .reg = EM28XX_OUTFMT_RGB_8_GBGB,
137 }, {
138 .name = "12 bpp YUV411",
139 .fourcc = V4L2_PIX_FMT_YUV411P,
140 .depth = 12,
141 .reg = EM28XX_OUTFMT_YUV411,
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -0300142 },
143};
144
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300145static int em28xx_vbi_supported(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300146{
147 /* Modprobe option to manually disable */
148 if (disable_vbi == 1)
149 return 0;
150
151 if (dev->board.is_webcam)
152 return 0;
153
154 /* FIXME: check subdevices for VBI support */
155
156 if (dev->chip_id == CHIP_ID_EM2860 ||
157 dev->chip_id == CHIP_ID_EM2883)
158 return 1;
159
160 /* Version of em28xx that does not support VBI */
161 return 0;
162}
163
164/*
165 * em28xx_wake_i2c()
166 * configure i2c attached devices
167 */
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300168static void em28xx_wake_i2c(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300169{
170 v4l2_device_call_all(&dev->v4l2_dev, 0, core, reset, 0);
171 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
172 INPUT(dev->ctl_input)->vmux, 0, 0);
173 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
174}
175
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300176static int em28xx_colorlevels_set_default(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300177{
178 em28xx_write_reg(dev, EM28XX_R20_YGAIN, CONTRAST_DEFAULT);
179 em28xx_write_reg(dev, EM28XX_R21_YOFFSET, BRIGHTNESS_DEFAULT);
180 em28xx_write_reg(dev, EM28XX_R22_UVGAIN, SATURATION_DEFAULT);
181 em28xx_write_reg(dev, EM28XX_R23_UOFFSET, BLUE_BALANCE_DEFAULT);
182 em28xx_write_reg(dev, EM28XX_R24_VOFFSET, RED_BALANCE_DEFAULT);
183 em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, SHARPNESS_DEFAULT);
184
185 em28xx_write_reg(dev, EM28XX_R14_GAMMA, 0x20);
186 em28xx_write_reg(dev, EM28XX_R15_RGAIN, 0x20);
187 em28xx_write_reg(dev, EM28XX_R16_GGAIN, 0x20);
188 em28xx_write_reg(dev, EM28XX_R17_BGAIN, 0x20);
189 em28xx_write_reg(dev, EM28XX_R18_ROFFSET, 0x00);
190 em28xx_write_reg(dev, EM28XX_R19_GOFFSET, 0x00);
191 return em28xx_write_reg(dev, EM28XX_R1A_BOFFSET, 0x00);
192}
193
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300194static int em28xx_set_outfmt(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300195{
196 int ret;
197 u8 fmt, vinctrl;
198
199 fmt = dev->format->reg;
200 if (!dev->is_em25xx)
201 fmt |= 0x20;
202 /*
203 * NOTE: it's not clear if this is really needed !
204 * The datasheets say bit 5 is a reserved bit and devices seem to work
205 * fine without it. But the Windows driver sets it for em2710/50+em28xx
206 * devices and we've always been setting it, too.
207 *
208 * em2765 (em25xx, em276x/7x/8x) devices do NOT work with this bit set,
209 * it's likely used for an additional (compressed ?) format there.
210 */
211 ret = em28xx_write_reg(dev, EM28XX_R27_OUTFMT, fmt);
212 if (ret < 0)
213 return ret;
214
215 ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, dev->vinmode);
216 if (ret < 0)
217 return ret;
218
219 vinctrl = dev->vinctl;
220 if (em28xx_vbi_supported(dev) == 1) {
221 vinctrl |= EM28XX_VINCTRL_VBI_RAW;
222 em28xx_write_reg(dev, EM28XX_R34_VBI_START_H, 0x00);
223 em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH, dev->vbi_width/4);
224 em28xx_write_reg(dev, EM28XX_R37_VBI_HEIGHT, dev->vbi_height);
225 if (dev->norm & V4L2_STD_525_60) {
226 /* NTSC */
227 em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x09);
228 } else if (dev->norm & V4L2_STD_625_50) {
229 /* PAL */
230 em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x07);
231 }
232 }
233
234 return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctrl);
235}
236
237static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax,
238 u8 ymin, u8 ymax)
239{
240 em28xx_videodbg("em28xx Scale: (%d,%d)-(%d,%d)\n",
241 xmin, ymin, xmax, ymax);
242
243 em28xx_write_regs(dev, EM28XX_R28_XMIN, &xmin, 1);
244 em28xx_write_regs(dev, EM28XX_R29_XMAX, &xmax, 1);
245 em28xx_write_regs(dev, EM28XX_R2A_YMIN, &ymin, 1);
246 return em28xx_write_regs(dev, EM28XX_R2B_YMAX, &ymax, 1);
247}
248
249static void em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
250 u16 width, u16 height)
251{
252 u8 cwidth = width >> 2;
253 u8 cheight = height >> 2;
254 u8 overflow = (height >> 9 & 0x02) | (width >> 10 & 0x01);
255 /* NOTE: size limit: 2047x1023 = 2MPix */
256
257 em28xx_videodbg("capture area set to (%d,%d): %dx%d\n",
258 hstart, vstart,
259 ((overflow & 2) << 9 | cwidth << 2),
260 ((overflow & 1) << 10 | cheight << 2));
261
262 em28xx_write_regs(dev, EM28XX_R1C_HSTART, &hstart, 1);
263 em28xx_write_regs(dev, EM28XX_R1D_VSTART, &vstart, 1);
264 em28xx_write_regs(dev, EM28XX_R1E_CWIDTH, &cwidth, 1);
265 em28xx_write_regs(dev, EM28XX_R1F_CHEIGHT, &cheight, 1);
266 em28xx_write_regs(dev, EM28XX_R1B_OFLOW, &overflow, 1);
267
268 /* FIXME: function/meaning of these registers ? */
269 /* FIXME: align width+height to multiples of 4 ?! */
270 if (dev->is_em25xx) {
271 em28xx_write_reg(dev, 0x34, width >> 4);
272 em28xx_write_reg(dev, 0x35, height >> 4);
273 }
274}
275
276static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v)
277{
278 u8 mode;
279 /* the em2800 scaler only supports scaling down to 50% */
280
281 if (dev->board.is_em2800) {
282 mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00);
283 } else {
284 u8 buf[2];
285
286 buf[0] = h;
287 buf[1] = h >> 8;
288 em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2);
289
290 buf[0] = v;
291 buf[1] = v >> 8;
292 em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2);
293 /* it seems that both H and V scalers must be active
294 to work correctly */
295 mode = (h || v) ? 0x30 : 0x00;
296 }
297 return em28xx_write_reg_bits(dev, EM28XX_R26_COMPR, mode, 0x30);
298}
299
300/* FIXME: this only function read values from dev */
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300301static int em28xx_resolution_set(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300302{
303 int width, height;
304 width = norm_maxw(dev);
305 height = norm_maxh(dev);
306
307 /* Properly setup VBI */
308 dev->vbi_width = 720;
309 if (dev->norm & V4L2_STD_525_60)
310 dev->vbi_height = 12;
311 else
312 dev->vbi_height = 18;
313
314 em28xx_set_outfmt(dev);
315
316 em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2);
317
318 /* If we don't set the start position to 2 in VBI mode, we end up
319 with line 20/21 being YUYV encoded instead of being in 8-bit
320 greyscale. The core of the issue is that line 21 (and line 23 for
321 PAL WSS) are inside of active video region, and as a result they
322 get the pixelformatting associated with that area. So by cropping
323 it out, we end up with the same format as the rest of the VBI
324 region */
325 if (em28xx_vbi_supported(dev) == 1)
326 em28xx_capture_area_set(dev, 0, 2, width, height);
327 else
328 em28xx_capture_area_set(dev, 0, 0, width, height);
329
330 return em28xx_scaler_set(dev, dev->hscale, dev->vscale);
331}
332
333/* Set USB alternate setting for analog video */
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300334static int em28xx_set_alternate(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300335{
336 int errCode;
337 int i;
338 unsigned int min_pkt_size = dev->width * 2 + 4;
339
340 /* NOTE: for isoc transfers, only alt settings > 0 are allowed
341 bulk transfers seem to work only with alt=0 ! */
342 dev->alt = 0;
343 if ((alt > 0) && (alt < dev->num_alt)) {
344 em28xx_videodbg("alternate forced to %d\n", dev->alt);
345 dev->alt = alt;
346 goto set_alt;
347 }
348 if (dev->analog_xfer_bulk)
349 goto set_alt;
350
351 /* When image size is bigger than a certain value,
352 the frame size should be increased, otherwise, only
353 green screen will be received.
354 */
355 if (dev->width * 2 * dev->height > 720 * 240 * 2)
356 min_pkt_size *= 2;
357
358 for (i = 0; i < dev->num_alt; i++) {
359 /* stop when the selected alt setting offers enough bandwidth */
360 if (dev->alt_max_pkt_size_isoc[i] >= min_pkt_size) {
361 dev->alt = i;
362 break;
363 /* otherwise make sure that we end up with the maximum bandwidth
364 because the min_pkt_size equation might be wrong...
365 */
366 } else if (dev->alt_max_pkt_size_isoc[i] >
367 dev->alt_max_pkt_size_isoc[dev->alt])
368 dev->alt = i;
369 }
370
371set_alt:
372 /* NOTE: for bulk transfers, we need to call usb_set_interface()
373 * even if the previous settings were the same. Otherwise streaming
374 * fails with all urbs having status = -EOVERFLOW ! */
375 if (dev->analog_xfer_bulk) {
376 dev->max_pkt_size = 512; /* USB 2.0 spec */
377 dev->packet_multiplier = EM28XX_BULK_PACKET_MULTIPLIER;
378 } else { /* isoc */
379 em28xx_videodbg("minimum isoc packet size: %u (alt=%d)\n",
380 min_pkt_size, dev->alt);
381 dev->max_pkt_size =
382 dev->alt_max_pkt_size_isoc[dev->alt];
383 dev->packet_multiplier = EM28XX_NUM_ISOC_PACKETS;
384 }
385 em28xx_videodbg("setting alternate %d with wMaxPacketSize=%u\n",
386 dev->alt, dev->max_pkt_size);
387 errCode = usb_set_interface(dev->udev, 0, dev->alt);
388 if (errCode < 0) {
389 em28xx_errdev("cannot change alternate number to %d (error=%i)\n",
390 dev->alt, errCode);
391 return errCode;
392 }
393 return 0;
394}
395
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300396/* ------------------------------------------------------------------
397 DMA and thread functions
398 ------------------------------------------------------------------*/
399
400/*
Frank Schaefer948a49a2012-12-08 11:31:25 -0300401 * Finish the current buffer
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300402 */
Frank Schaefer948a49a2012-12-08 11:31:25 -0300403static inline void finish_buffer(struct em28xx *dev,
404 struct em28xx_buffer *buf)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300405{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300406 em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->top_field);
407
408 buf->vb.v4l2_buf.sequence = dev->field_count++;
409 buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
410 v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
411
412 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300413}
414
415/*
Frank Schaefer36016a32012-12-08 11:31:32 -0300416 * Copy picture data from USB buffer to videobuf buffer
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300417 */
418static void em28xx_copy_video(struct em28xx *dev,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300419 struct em28xx_buffer *buf,
Frank Schaefer36016a32012-12-08 11:31:32 -0300420 unsigned char *usb_buf,
Frank Schaefer4078d622012-12-08 11:31:29 -0300421 unsigned long len)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300422{
423 void *fieldstart, *startwrite, *startread;
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300424 int linesdone, currlinedone, offset, lencopy, remain;
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300425 int bytesperline = dev->width << 1;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300426
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300427 if (buf->pos + len > buf->length)
428 len = buf->length - buf->pos;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300429
Frank Schaefer36016a32012-12-08 11:31:32 -0300430 startread = usb_buf;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300431 remain = len;
432
Frank Schaeferc02ec712012-11-08 14:11:33 -0300433 if (dev->progressive || buf->top_field)
Frank Schaefer36016a32012-12-08 11:31:32 -0300434 fieldstart = buf->vb_buf;
Frank Schaeferc02ec712012-11-08 14:11:33 -0300435 else /* interlaced mode, even nr. of lines */
Frank Schaefer36016a32012-12-08 11:31:32 -0300436 fieldstart = buf->vb_buf + bytesperline;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300437
Frank Schaefer87325332012-12-08 11:31:27 -0300438 linesdone = buf->pos / bytesperline;
439 currlinedone = buf->pos % bytesperline;
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -0300440
441 if (dev->progressive)
442 offset = linesdone * bytesperline + currlinedone;
443 else
444 offset = linesdone * bytesperline * 2 + currlinedone;
445
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300446 startwrite = fieldstart + offset;
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300447 lencopy = bytesperline - currlinedone;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300448 lencopy = lencopy > remain ? remain : lencopy;
449
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300450 if ((char *)startwrite + lencopy > (char *)buf->vb_buf + buf->length) {
Mauro Carvalho Chehabea8df7e2008-04-13 14:39:29 -0300451 em28xx_isocdbg("Overflow of %zi bytes past buffer end (1)\n",
Frank Schaefer36016a32012-12-08 11:31:32 -0300452 ((char *)startwrite + lencopy) -
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300453 ((char *)buf->vb_buf + buf->length));
454 remain = (char *)buf->vb_buf + buf->length -
Frank Schaefer36016a32012-12-08 11:31:32 -0300455 (char *)startwrite;
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -0300456 lencopy = remain;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300457 }
Aidan Thorntone0fadfd342008-04-13 14:56:02 -0300458 if (lencopy <= 0)
459 return;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300460 memcpy(startwrite, startread, lencopy);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300461
462 remain -= lencopy;
463
464 while (remain > 0) {
Frank Schaeferc02ec712012-11-08 14:11:33 -0300465 if (dev->progressive)
466 startwrite += lencopy;
467 else
468 startwrite += lencopy + bytesperline;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300469 startread += lencopy;
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300470 if (bytesperline > remain)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300471 lencopy = remain;
472 else
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300473 lencopy = bytesperline;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300474
Frank Schaefer36016a32012-12-08 11:31:32 -0300475 if ((char *)startwrite + lencopy > (char *)buf->vb_buf +
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300476 buf->length) {
Devin Heitmuellere3ba4d32009-09-15 00:18:06 -0300477 em28xx_isocdbg("Overflow of %zi bytes past buffer end"
478 "(2)\n",
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300479 ((char *)startwrite + lencopy) -
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300480 ((char *)buf->vb_buf + buf->length));
481 lencopy = remain = (char *)buf->vb_buf + buf->length -
482 (char *)startwrite;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300483 }
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300484 if (lencopy <= 0)
485 break;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300486
487 memcpy(startwrite, startread, lencopy);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300488
489 remain -= lencopy;
490 }
491
Frank Schaefer87325332012-12-08 11:31:27 -0300492 buf->pos += len;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300493}
494
Frank Schaefer36016a32012-12-08 11:31:32 -0300495/*
496 * Copy VBI data from USB buffer to videobuf buffer
497 */
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300498static void em28xx_copy_vbi(struct em28xx *dev,
Frank Schaefer87325332012-12-08 11:31:27 -0300499 struct em28xx_buffer *buf,
Frank Schaefer36016a32012-12-08 11:31:32 -0300500 unsigned char *usb_buf,
Frank Schaefer4078d622012-12-08 11:31:29 -0300501 unsigned long len)
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300502{
Frank Schaefer36016a32012-12-08 11:31:32 -0300503 unsigned int offset;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300504
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300505 if (buf->pos + len > buf->length)
506 len = buf->length - buf->pos;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300507
Frank Schaefer87325332012-12-08 11:31:27 -0300508 offset = buf->pos;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300509 /* Make sure the bottom field populates the second half of the frame */
Frank Schaefer36016a32012-12-08 11:31:32 -0300510 if (buf->top_field == 0)
511 offset += dev->vbi_width * dev->vbi_height;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300512
Frank Schaefer36016a32012-12-08 11:31:32 -0300513 memcpy(buf->vb_buf + offset, usb_buf, len);
Frank Schaefer87325332012-12-08 11:31:27 -0300514 buf->pos += len;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300515}
516
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300517static inline void print_err_status(struct em28xx *dev,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300518 int packet, int status)
519{
520 char *errmsg = "Unknown";
521
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300522 switch (status) {
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300523 case -ENOENT:
524 errmsg = "unlinked synchronuously";
525 break;
526 case -ECONNRESET:
527 errmsg = "unlinked asynchronuously";
528 break;
529 case -ENOSR:
530 errmsg = "Buffer error (overrun)";
531 break;
532 case -EPIPE:
533 errmsg = "Stalled (device not responding)";
534 break;
535 case -EOVERFLOW:
536 errmsg = "Babble (bad cable?)";
537 break;
538 case -EPROTO:
539 errmsg = "Bit-stuff error (bad cable?)";
540 break;
541 case -EILSEQ:
542 errmsg = "CRC/Timeout (could be anything)";
543 break;
544 case -ETIME:
545 errmsg = "Device does not respond";
546 break;
547 }
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300548 if (packet < 0) {
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300549 em28xx_isocdbg("URB status %d [%s].\n", status, errmsg);
550 } else {
551 em28xx_isocdbg("URB packet %d, status %d [%s].\n",
552 packet, status, errmsg);
553 }
554}
555
556/*
Frank Schaefer24a6d842012-12-08 11:31:24 -0300557 * get the next available buffer from dma queue
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300558 */
Frank Schaefer24a6d842012-12-08 11:31:24 -0300559static inline struct em28xx_buffer *get_next_buf(struct em28xx *dev,
560 struct em28xx_dmaqueue *dma_q)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300561{
Frank Schaefer24a6d842012-12-08 11:31:24 -0300562 struct em28xx_buffer *buf;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300563
Mauro Carvalho Chehabdbecb442008-04-13 15:08:55 -0300564 if (list_empty(&dma_q->active)) {
565 em28xx_isocdbg("No active queue to serve\n");
Frank Schaefer24a6d842012-12-08 11:31:24 -0300566 return NULL;
Mauro Carvalho Chehabdbecb442008-04-13 15:08:55 -0300567 }
568
Mauro Carvalho Chehabdbecb442008-04-13 15:08:55 -0300569 /* Get the next buffer */
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300570 buf = list_entry(dma_q->active.next, struct em28xx_buffer, list);
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300571 /* Cleans up buffer - Useful for testing for frame/URB loss */
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300572 list_del(&buf->list);
Frank Schaefer87325332012-12-08 11:31:27 -0300573 buf->pos = 0;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300574 buf->vb_buf = buf->mem;
Mauro Carvalho Chehabcb784722008-04-13 15:06:52 -0300575
Frank Schaefer24a6d842012-12-08 11:31:24 -0300576 return buf;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300577}
578
Frank Schaefere04c00d2012-12-08 11:31:30 -0300579/*
580 * Finish the current buffer if completed and prepare for the next field
581 */
582static struct em28xx_buffer *
583finish_field_prepare_next(struct em28xx *dev,
584 struct em28xx_buffer *buf,
585 struct em28xx_dmaqueue *dma_q)
586{
587 if (dev->progressive || dev->top_field) { /* Brand new frame */
588 if (buf != NULL)
589 finish_buffer(dev, buf);
590 buf = get_next_buf(dev, dma_q);
591 }
592 if (buf != NULL) {
593 buf->top_field = dev->top_field;
594 buf->pos = 0;
595 }
596
597 return buf;
598}
599
Frank Schaefer227b7c92012-12-08 11:31:31 -0300600/*
601 * Process data packet according to the em2710/em2750/em28xx frame data format
602 */
603static inline void process_frame_data_em28xx(struct em28xx *dev,
604 unsigned char *data_pkt,
605 unsigned int data_len)
606{
607 struct em28xx_buffer *buf = dev->usb_ctl.vid_buf;
608 struct em28xx_buffer *vbi_buf = dev->usb_ctl.vbi_buf;
609 struct em28xx_dmaqueue *dma_q = &dev->vidq;
610 struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq;
611
612 /* capture type 0 = vbi start
613 capture type 1 = vbi in progress
614 capture type 2 = video start
615 capture type 3 = video in progress */
616 if (data_len >= 4) {
617 /* NOTE: Headers are always 4 bytes and
618 * never split across packets */
619 if (data_pkt[0] == 0x88 && data_pkt[1] == 0x88 &&
620 data_pkt[2] == 0x88 && data_pkt[3] == 0x88) {
621 /* Continuation */
622 data_pkt += 4;
623 data_len -= 4;
624 } else if (data_pkt[0] == 0x33 && data_pkt[1] == 0x95) {
625 /* Field start (VBI mode) */
626 dev->capture_type = 0;
627 dev->vbi_read = 0;
628 em28xx_isocdbg("VBI START HEADER !!!\n");
629 dev->top_field = !(data_pkt[2] & 1);
630 data_pkt += 4;
631 data_len -= 4;
632 } else if (data_pkt[0] == 0x22 && data_pkt[1] == 0x5a) {
633 /* Field start (VBI disabled) */
634 dev->capture_type = 2;
635 em28xx_isocdbg("VIDEO START HEADER !!!\n");
636 dev->top_field = !(data_pkt[2] & 1);
637 data_pkt += 4;
638 data_len -= 4;
639 }
640 }
641 /* NOTE: With bulk transfers, intermediate data packets
642 * have no continuation header */
643
644 if (dev->capture_type == 0) {
645 vbi_buf = finish_field_prepare_next(dev, vbi_buf, vbi_dma_q);
646 dev->usb_ctl.vbi_buf = vbi_buf;
647 dev->capture_type = 1;
648 }
649
650 if (dev->capture_type == 1) {
651 int vbi_size = dev->vbi_width * dev->vbi_height;
652 int vbi_data_len = ((dev->vbi_read + data_len) > vbi_size) ?
653 (vbi_size - dev->vbi_read) : data_len;
654
655 /* Copy VBI data */
656 if (vbi_buf != NULL)
657 em28xx_copy_vbi(dev, vbi_buf, data_pkt, vbi_data_len);
658 dev->vbi_read += vbi_data_len;
659
660 if (vbi_data_len < data_len) {
661 /* Continue with copying video data */
662 dev->capture_type = 2;
663 data_pkt += vbi_data_len;
664 data_len -= vbi_data_len;
665 }
666 }
667
668 if (dev->capture_type == 2) {
669 buf = finish_field_prepare_next(dev, buf, dma_q);
670 dev->usb_ctl.vid_buf = buf;
671 dev->capture_type = 3;
672 }
673
674 if (dev->capture_type == 3 && buf != NULL && data_len > 0)
675 em28xx_copy_video(dev, buf, data_pkt, data_len);
676}
677
Frank Schaefere507e0e2013-03-26 13:38:38 -0300678/*
679 * Process data packet according to the em25xx/em276x/7x/8x frame data format
680 */
681static inline void process_frame_data_em25xx(struct em28xx *dev,
682 unsigned char *data_pkt,
683 unsigned int data_len)
684{
685 struct em28xx_buffer *buf = dev->usb_ctl.vid_buf;
686 struct em28xx_dmaqueue *dmaq = &dev->vidq;
687 bool frame_end = 0;
688
689 /* Check for header */
690 /* NOTE: at least with bulk transfers, only the first packet
691 * has a header and has always set the FRAME_END bit */
692 if (data_len >= 2) { /* em25xx header is only 2 bytes long */
693 if ((data_pkt[0] == EM25XX_FRMDATAHDR_BYTE1) &&
694 ((data_pkt[1] & ~EM25XX_FRMDATAHDR_BYTE2_MASK) == 0x00)) {
695 dev->top_field = !(data_pkt[1] &
696 EM25XX_FRMDATAHDR_BYTE2_FRAME_ID);
697 frame_end = data_pkt[1] &
698 EM25XX_FRMDATAHDR_BYTE2_FRAME_END;
699 data_pkt += 2;
700 data_len -= 2;
701 }
702
703 /* Finish field and prepare next (BULK only) */
704 if (dev->analog_xfer_bulk && frame_end) {
705 buf = finish_field_prepare_next(dev, buf, dmaq);
706 dev->usb_ctl.vid_buf = buf;
707 }
708 /* NOTE: in ISOC mode when a new frame starts and buf==NULL,
709 * we COULD already prepare a buffer here to avoid skipping the
710 * first frame.
711 */
712 }
713
714 /* Copy data */
715 if (buf != NULL && data_len > 0)
716 em28xx_copy_video(dev, buf, data_pkt, data_len);
717
718 /* Finish frame (ISOC only) => avoids lag of 1 frame */
719 if (!dev->analog_xfer_bulk && frame_end) {
720 buf = finish_field_prepare_next(dev, buf, dmaq);
721 dev->usb_ctl.vid_buf = buf;
722 }
723
724 /* NOTE: Tested with USB bulk transfers only !
725 * The wording in the datasheet suggests that isoc might work different.
726 * The current code assumes that with isoc transfers each packet has a
727 * header like with the other em28xx devices.
728 */
729 /* NOTE: Support for interlaced mode is pure theory. It has not been
730 * tested and it is unknown if these devices actually support it. */
731 /* NOTE: No VBI support yet (these chips likely do not support VBI). */
732}
733
Frank Schaefer960da932012-11-25 06:37:37 -0300734/* Processes and copies the URB data content (video and VBI data) */
Frank Schaefer0fa4a402012-11-08 14:11:45 -0300735static inline int em28xx_urb_data_copy(struct em28xx *dev, struct urb *urb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300736{
Frank Schaefer227b7c92012-12-08 11:31:31 -0300737 int xfer_bulk, num_packets, i;
738 unsigned char *usb_data_pkt;
739 unsigned int usb_data_len;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300740
741 if (!dev)
742 return 0;
743
Frank Schaefer2665c292012-12-27 19:02:43 -0300744 if (dev->disconnected)
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300745 return 0;
746
Frank Schaefer1653cb0c2012-11-08 14:11:44 -0300747 if (urb->status < 0)
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300748 print_err_status(dev, -1, urb->status);
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300749
Frank Schaefer4601cc32012-11-08 14:11:46 -0300750 xfer_bulk = usb_pipebulk(urb->pipe);
751
Frank Schaefer4601cc32012-11-08 14:11:46 -0300752 if (xfer_bulk) /* bulk */
753 num_packets = 1;
754 else /* isoc */
755 num_packets = urb->number_of_packets;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300756
Frank Schaefer4601cc32012-11-08 14:11:46 -0300757 for (i = 0; i < num_packets; i++) {
758 if (xfer_bulk) { /* bulk */
Frank Schaefer227b7c92012-12-08 11:31:31 -0300759 usb_data_len = urb->actual_length;
Frank Schaefer4601cc32012-11-08 14:11:46 -0300760
Frank Schaefer227b7c92012-12-08 11:31:31 -0300761 usb_data_pkt = urb->transfer_buffer;
Frank Schaefer4601cc32012-11-08 14:11:46 -0300762 } else { /* isoc */
763 if (urb->iso_frame_desc[i].status < 0) {
764 print_err_status(dev, i,
765 urb->iso_frame_desc[i].status);
766 if (urb->iso_frame_desc[i].status != -EPROTO)
767 continue;
768 }
769
Frank Schaefer227b7c92012-12-08 11:31:31 -0300770 usb_data_len = urb->iso_frame_desc[i].actual_length;
771 if (usb_data_len > dev->max_pkt_size) {
Frank Schaefer4601cc32012-11-08 14:11:46 -0300772 em28xx_isocdbg("packet bigger than packet size");
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300773 continue;
Frank Schaefer4601cc32012-11-08 14:11:46 -0300774 }
775
Frank Schaefer227b7c92012-12-08 11:31:31 -0300776 usb_data_pkt = urb->transfer_buffer +
777 urb->iso_frame_desc[i].offset;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300778 }
779
Frank Schaefer227b7c92012-12-08 11:31:31 -0300780 if (usb_data_len == 0) {
Frank Schaefer4601cc32012-11-08 14:11:46 -0300781 /* NOTE: happens very often with isoc transfers */
782 /* em28xx_usbdbg("packet %d is empty",i); - spammy */
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300783 continue;
784 }
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300785
Frank Schaefere507e0e2013-03-26 13:38:38 -0300786 if (dev->is_em25xx)
787 process_frame_data_em25xx(dev,
788 usb_data_pkt, usb_data_len);
789 else
790 process_frame_data_em28xx(dev,
791 usb_data_pkt, usb_data_len);
792
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300793 }
Frank Schaefer227b7c92012-12-08 11:31:31 -0300794 return 1;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300795}
796
797
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300798static int get_ressource(enum v4l2_buf_type f_type)
799{
800 switch (f_type) {
801 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
802 return EM28XX_RESOURCE_VIDEO;
803 case V4L2_BUF_TYPE_VBI_CAPTURE:
804 return EM28XX_RESOURCE_VBI;
805 default:
806 BUG();
807 return 0;
808 }
809}
810
811/* Usage lock check functions */
812static int res_get(struct em28xx *dev, enum v4l2_buf_type f_type)
813{
814 int res_type = get_ressource(f_type);
815
816 /* is it free? */
817 if (dev->resources & res_type) {
818 /* no, someone else uses it */
819 return -EBUSY;
820 }
821
822 /* it's free, grab it */
823 dev->resources |= res_type;
824 em28xx_videodbg("res: get %d\n", res_type);
825 return 0;
826}
827
828static void res_free(struct em28xx *dev, enum v4l2_buf_type f_type)
829{
830 int res_type = get_ressource(f_type);
831
832 dev->resources &= ~res_type;
833 em28xx_videodbg("res: put %d\n", res_type);
834}
835
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300836/* ------------------------------------------------------------------
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300837 Videobuf2 operations
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300838 ------------------------------------------------------------------*/
839
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300840static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
841 unsigned int *nbuffers, unsigned int *nplanes,
842 unsigned int sizes[], void *alloc_ctxs[])
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300843{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300844 struct em28xx *dev = vb2_get_drv_priv(vq);
845 unsigned long size;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300846
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300847 if (fmt)
848 size = fmt->fmt.pix.sizeimage;
849 else
850 size = (dev->width * dev->height * dev->format->depth + 7) >> 3;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -0300851
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300852 if (size == 0)
853 return -EINVAL;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300854
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300855 if (0 == *nbuffers)
856 *nbuffers = 32;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300857
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300858 *nplanes = 1;
859 sizes[0] = size;
Mauro Carvalho Chehabd2d9fbf2008-04-17 21:38:53 -0300860
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300861 return 0;
862}
863
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300864static int
865buffer_prepare(struct vb2_buffer *vb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300866{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300867 struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue);
868 struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
869 unsigned long size;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300870
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300871 em28xx_videodbg("%s, field=%d\n", __func__, vb->v4l2_buf.field);
Aidan Thornton3b5fa922008-04-13 15:09:36 -0300872
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300873 size = (dev->width * dev->height * dev->format->depth + 7) >> 3;
Aidan Thornton3b5fa922008-04-13 15:09:36 -0300874
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300875 if (vb2_plane_size(vb, 0) < size) {
876 em28xx_videodbg("%s data will not fit into plane (%lu < %lu)\n",
877 __func__, vb2_plane_size(vb, 0), size);
878 return -EINVAL;
879 }
880 vb2_set_plane_payload(&buf->vb, 0, size);
881
882 return 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300883}
884
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300885int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300886{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300887 struct em28xx *dev = vb2_get_drv_priv(vq);
888 struct v4l2_frequency f;
889 int rc = 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300890
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300891 em28xx_videodbg("%s\n", __func__);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300892
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300893 /* Make sure streaming is not already in progress for this type
894 of filehandle (e.g. video, vbi) */
895 rc = res_get(dev, vq->type);
896 if (rc)
897 return rc;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300898
Frank Schaefer032f1dd2013-10-10 15:31:53 -0300899 if (dev->streaming_users == 0) {
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300900 /* First active streaming user, so allocate all the URBs */
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300901
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300902 /* Allocate the USB bandwidth */
903 em28xx_set_alternate(dev);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300904
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300905 /* Needed, since GPIO might have disabled power of
906 some i2c device
907 */
908 em28xx_wake_i2c(dev);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300909
Frank Schaefer0455eeb2012-11-25 06:37:34 -0300910 dev->capture_type = -1;
Frank Schaefer960da932012-11-25 06:37:37 -0300911 rc = em28xx_init_usb_xfer(dev, EM28XX_ANALOG_MODE,
912 dev->analog_xfer_bulk,
913 EM28XX_NUM_BUFS,
914 dev->max_pkt_size,
915 dev->packet_multiplier,
916 em28xx_urb_data_copy);
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300917 if (rc < 0)
Frank Schaefer032f1dd2013-10-10 15:31:53 -0300918 return rc;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300919
920 /*
921 * djh: it's not clear whether this code is still needed. I'm
922 * leaving it in here for now entirely out of concern for
923 * backward compatibility (the old code did it)
924 */
925
926 /* Ask tuner to go to analog or radio mode */
927 memset(&f, 0, sizeof(f));
928 f.frequency = dev->ctl_freq;
929 if (vq->owner && vq->owner->vdev->vfl_type == VFL_TYPE_RADIO)
930 f.type = V4L2_TUNER_RADIO;
931 else
932 f.type = V4L2_TUNER_ANALOG_TV;
933 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300934 }
935
Frank Schaefer032f1dd2013-10-10 15:31:53 -0300936 dev->streaming_users++;
937
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300938 return rc;
939}
940
Mauro Carvalho Chehab3a799c22013-01-05 01:27:21 -0200941static int em28xx_stop_streaming(struct vb2_queue *vq)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300942{
943 struct em28xx *dev = vb2_get_drv_priv(vq);
944 struct em28xx_dmaqueue *vidq = &dev->vidq;
945 unsigned long flags = 0;
946
947 em28xx_videodbg("%s\n", __func__);
948
949 res_free(dev, vq->type);
950
951 if (dev->streaming_users-- == 1) {
952 /* Last active user, so shutdown all the URBS */
953 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
954 }
955
956 spin_lock_irqsave(&dev->slock, flags);
957 while (!list_empty(&vidq->active)) {
958 struct em28xx_buffer *buf;
959 buf = list_entry(vidq->active.next, struct em28xx_buffer, list);
960 list_del(&buf->list);
961 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
962 }
963 dev->usb_ctl.vid_buf = NULL;
964 spin_unlock_irqrestore(&dev->slock, flags);
965
966 return 0;
967}
968
969int em28xx_stop_vbi_streaming(struct vb2_queue *vq)
970{
971 struct em28xx *dev = vb2_get_drv_priv(vq);
972 struct em28xx_dmaqueue *vbiq = &dev->vbiq;
973 unsigned long flags = 0;
974
975 em28xx_videodbg("%s\n", __func__);
976
977 res_free(dev, vq->type);
978
979 if (dev->streaming_users-- == 1) {
980 /* Last active user, so shutdown all the URBS */
981 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
982 }
983
984 spin_lock_irqsave(&dev->slock, flags);
985 while (!list_empty(&vbiq->active)) {
986 struct em28xx_buffer *buf;
987 buf = list_entry(vbiq->active.next, struct em28xx_buffer, list);
988 list_del(&buf->list);
989 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
990 }
991 dev->usb_ctl.vbi_buf = NULL;
992 spin_unlock_irqrestore(&dev->slock, flags);
993
994 return 0;
995}
996
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300997static void
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300998buffer_queue(struct vb2_buffer *vb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300999{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001000 struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue);
1001 struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
1002 struct em28xx_dmaqueue *vidq = &dev->vidq;
1003 unsigned long flags = 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001004
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001005 em28xx_videodbg("%s\n", __func__);
1006 buf->mem = vb2_plane_vaddr(vb, 0);
1007 buf->length = vb2_plane_size(vb, 0);
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001008
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001009 spin_lock_irqsave(&dev->slock, flags);
1010 list_add_tail(&buf->list, &vidq->active);
1011 spin_unlock_irqrestore(&dev->slock, flags);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001012}
1013
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001014static struct vb2_ops em28xx_video_qops = {
1015 .queue_setup = queue_setup,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001016 .buf_prepare = buffer_prepare,
1017 .buf_queue = buffer_queue,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001018 .start_streaming = em28xx_start_analog_streaming,
1019 .stop_streaming = em28xx_stop_streaming,
1020 .wait_prepare = vb2_ops_wait_prepare,
1021 .wait_finish = vb2_ops_wait_finish,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001022};
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001023
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001024static int em28xx_vb2_setup(struct em28xx *dev)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001025{
1026 int rc;
1027 struct vb2_queue *q;
1028
1029 /* Setup Videobuf2 for Video capture */
1030 q = &dev->vb_vidq;
1031 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Mauro Carvalho Chehabef85cd92013-01-06 00:34:22 -02001032 q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
Frank Schaefer195281d2013-03-09 06:53:01 -03001033 q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001034 q->drv_priv = dev;
1035 q->buf_struct_size = sizeof(struct em28xx_buffer);
1036 q->ops = &em28xx_video_qops;
1037 q->mem_ops = &vb2_vmalloc_memops;
1038
1039 rc = vb2_queue_init(q);
1040 if (rc < 0)
1041 return rc;
1042
1043 /* Setup Videobuf2 for VBI capture */
1044 q = &dev->vb_vbiq;
1045 q->type = V4L2_BUF_TYPE_VBI_CAPTURE;
1046 q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR;
Frank Schaefer195281d2013-03-09 06:53:01 -03001047 q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001048 q->drv_priv = dev;
1049 q->buf_struct_size = sizeof(struct em28xx_buffer);
1050 q->ops = &em28xx_vbi_qops;
1051 q->mem_ops = &vb2_vmalloc_memops;
1052
1053 rc = vb2_queue_init(q);
1054 if (rc < 0)
1055 return rc;
1056
1057 return 0;
1058}
1059
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001060/********************* v4l2 interface **************************************/
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001061
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001062static void video_mux(struct em28xx *dev, int index)
1063{
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001064 dev->ctl_input = index;
1065 dev->ctl_ainput = INPUT(index)->amux;
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001066 dev->ctl_aoutput = INPUT(index)->aout;
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001067
Mauro Carvalho Chehabe879b8e2008-11-20 13:39:39 -03001068 if (!dev->ctl_aoutput)
1069 dev->ctl_aoutput = EM28XX_AOUT_MASTER;
1070
Hans Verkuil5325b422009-04-02 11:26:22 -03001071 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
1072 INPUT(index)->vmux, 0, 0);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001073
Mauro Carvalho Chehab505b6d02008-11-25 09:39:50 -03001074 if (dev->board.has_msp34xx) {
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001075 if (dev->i2s_speed) {
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03001076 v4l2_device_call_all(&dev->v4l2_dev, 0, audio,
1077 s_i2s_clock_freq, dev->i2s_speed);
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001078 }
Hans Verkuil2474ed42006-03-19 12:35:57 -03001079 /* Note: this is msp3400 specific */
Hans Verkuil5325b422009-04-02 11:26:22 -03001080 v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing,
1081 dev->ctl_ainput, MSP_OUTPUT(MSP_SC_IN_DSP_SCART1), 0);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001082 }
Mauro Carvalho Chehab539c96d2008-01-05 09:53:54 -03001083
Vitaly Wool2bd1d9e2009-03-04 08:27:52 -03001084 if (dev->board.adecoder != EM28XX_NOADECODER) {
Hans Verkuil5325b422009-04-02 11:26:22 -03001085 v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing,
1086 dev->ctl_ainput, dev->ctl_aoutput, 0);
Vitaly Wool2bd1d9e2009-03-04 08:27:52 -03001087 }
1088
Mauro Carvalho Chehab00b87302008-02-06 18:34:13 -03001089 em28xx_audio_analog_set(dev);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001090}
1091
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001092static void em28xx_ctrl_notify(struct v4l2_ctrl *ctrl, void *priv)
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001093{
Hans Verkuil081b9452012-09-07 05:43:59 -03001094 struct em28xx *dev = priv;
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001095
Hans Verkuil081b9452012-09-07 05:43:59 -03001096 /*
1097 * In the case of non-AC97 volume controls, we still need
1098 * to do some setups at em28xx, in order to mute/unmute
1099 * and to adjust audio volume. However, the value ranges
1100 * should be checked by the corresponding V4L subdriver.
1101 */
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001102 switch (ctrl->id) {
1103 case V4L2_CID_AUDIO_MUTE:
Hans Verkuil081b9452012-09-07 05:43:59 -03001104 dev->mute = ctrl->val;
1105 em28xx_audio_analog_set(dev);
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001106 break;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001107 case V4L2_CID_AUDIO_VOLUME:
Hans Verkuil081b9452012-09-07 05:43:59 -03001108 dev->volume = ctrl->val;
1109 em28xx_audio_analog_set(dev);
1110 break;
1111 }
1112}
1113
1114static int em28xx_s_ctrl(struct v4l2_ctrl *ctrl)
1115{
1116 struct em28xx *dev = container_of(ctrl->handler, struct em28xx, ctrl_handler);
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001117 int ret = -EINVAL;
Hans Verkuil081b9452012-09-07 05:43:59 -03001118
1119 switch (ctrl->id) {
1120 case V4L2_CID_AUDIO_MUTE:
1121 dev->mute = ctrl->val;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001122 ret = em28xx_audio_analog_set(dev);
Hans Verkuil081b9452012-09-07 05:43:59 -03001123 break;
1124 case V4L2_CID_AUDIO_VOLUME:
1125 dev->volume = ctrl->val;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001126 ret = em28xx_audio_analog_set(dev);
1127 break;
1128 case V4L2_CID_CONTRAST:
1129 ret = em28xx_write_reg(dev, EM28XX_R20_YGAIN, ctrl->val);
1130 break;
1131 case V4L2_CID_BRIGHTNESS:
1132 ret = em28xx_write_reg(dev, EM28XX_R21_YOFFSET, ctrl->val);
1133 break;
1134 case V4L2_CID_SATURATION:
1135 ret = em28xx_write_reg(dev, EM28XX_R22_UVGAIN, ctrl->val);
1136 break;
1137 case V4L2_CID_BLUE_BALANCE:
1138 ret = em28xx_write_reg(dev, EM28XX_R23_UOFFSET, ctrl->val);
1139 break;
1140 case V4L2_CID_RED_BALANCE:
1141 ret = em28xx_write_reg(dev, EM28XX_R24_VOFFSET, ctrl->val);
1142 break;
1143 case V4L2_CID_SHARPNESS:
1144 ret = em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, ctrl->val);
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001145 break;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001146 }
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001147
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001148 return (ret < 0) ? ret : 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001149}
1150
Hans Verkuil081b9452012-09-07 05:43:59 -03001151const struct v4l2_ctrl_ops em28xx_ctrl_ops = {
1152 .s_ctrl = em28xx_s_ctrl,
1153};
1154
Frank Schaefer6b09a212013-02-10 16:05:12 -03001155static void size_to_scale(struct em28xx *dev,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001156 unsigned int width, unsigned int height,
1157 unsigned int *hscale, unsigned int *vscale)
1158{
Mauro Carvalho Chehab55699962009-07-13 20:15:02 -03001159 unsigned int maxw = norm_maxw(dev);
1160 unsigned int maxh = norm_maxh(dev);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001161
1162 *hscale = (((unsigned long)maxw) << 12) / width - 4096L;
Frank Schaefer81685322013-02-10 16:05:11 -03001163 if (*hscale > EM28XX_HVSCALE_MAX)
1164 *hscale = EM28XX_HVSCALE_MAX;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001165
1166 *vscale = (((unsigned long)maxh) << 12) / height - 4096L;
Frank Schaefer81685322013-02-10 16:05:11 -03001167 if (*vscale > EM28XX_HVSCALE_MAX)
1168 *vscale = EM28XX_HVSCALE_MAX;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001169}
1170
Frank Schaeferb8374132013-02-10 16:05:13 -03001171static void scale_to_size(struct em28xx *dev,
1172 unsigned int hscale, unsigned int vscale,
1173 unsigned int *width, unsigned int *height)
1174{
1175 unsigned int maxw = norm_maxw(dev);
1176 unsigned int maxh = norm_maxh(dev);
1177
1178 *width = (((unsigned long)maxw) << 12) / (hscale + 4096L);
1179 *height = (((unsigned long)maxh) << 12) / (vscale + 4096L);
1180}
1181
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001182/* ------------------------------------------------------------------
1183 IOCTL vidioc handling
1184 ------------------------------------------------------------------*/
1185
Hans Verkuil78b526a2008-05-28 12:16:41 -03001186static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001187 struct v4l2_format *f)
1188{
1189 struct em28xx_fh *fh = priv;
1190 struct em28xx *dev = fh->dev;
1191
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001192 f->fmt.pix.width = dev->width;
1193 f->fmt.pix.height = dev->height;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001194 f->fmt.pix.pixelformat = dev->format->fourcc;
1195 f->fmt.pix.bytesperline = (dev->width * dev->format->depth + 7) >> 3;
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -03001196 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * dev->height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001197 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
1198
1199 /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -03001200 if (dev->progressive)
1201 f->fmt.pix.field = V4L2_FIELD_NONE;
1202 else
1203 f->fmt.pix.field = dev->interlaced ?
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001204 V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001205 return 0;
1206}
1207
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001208static struct em28xx_fmt *format_by_fourcc(unsigned int fourcc)
1209{
1210 unsigned int i;
1211
1212 for (i = 0; i < ARRAY_SIZE(format); i++)
1213 if (format[i].fourcc == fourcc)
1214 return &format[i];
1215
1216 return NULL;
1217}
1218
Hans Verkuil78b526a2008-05-28 12:16:41 -03001219static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001220 struct v4l2_format *f)
1221{
1222 struct em28xx_fh *fh = priv;
1223 struct em28xx *dev = fh->dev;
Trent Piephoccb83402009-05-30 21:45:46 -03001224 unsigned int width = f->fmt.pix.width;
1225 unsigned int height = f->fmt.pix.height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001226 unsigned int maxw = norm_maxw(dev);
1227 unsigned int maxh = norm_maxh(dev);
1228 unsigned int hscale, vscale;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001229 struct em28xx_fmt *fmt;
1230
1231 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
1232 if (!fmt) {
1233 em28xx_videodbg("Fourcc format (%08x) invalid.\n",
1234 f->fmt.pix.pixelformat);
1235 return -EINVAL;
1236 }
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001237
Mauro Carvalho Chehab55699962009-07-13 20:15:02 -03001238 if (dev->board.is_em2800) {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001239 /* the em2800 can only scale down to 50% */
Trent Piephoccb83402009-05-30 21:45:46 -03001240 height = height > (3 * maxh / 4) ? maxh : maxh / 2;
1241 width = width > (3 * maxw / 4) ? maxw : maxw / 2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001242 /*
1243 * MaxPacketSize for em2800 is too small to capture at full
1244 * resolution use half of maxw as the scaler can only scale
1245 * to 50%
1246 */
Sascha Sommer1020d132012-01-08 16:54:28 -03001247 if (width == maxw && height == maxh)
1248 width /= 2;
Trent Piephoccb83402009-05-30 21:45:46 -03001249 } else {
1250 /* width must even because of the YUYV format
1251 height must be even because of interlacing */
Devin Heitmuellere3ba4d32009-09-15 00:18:06 -03001252 v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh,
1253 1, 0);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001254 }
1255
Frank Schaefer6b09a212013-02-10 16:05:12 -03001256 size_to_scale(dev, width, height, &hscale, &vscale);
Hans Verkuil46f85972013-03-30 05:31:42 -03001257 scale_to_size(dev, hscale, vscale, &width, &height);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001258
1259 f->fmt.pix.width = width;
1260 f->fmt.pix.height = height;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001261 f->fmt.pix.pixelformat = fmt->fourcc;
Hans Verkuile6066db2013-02-06 08:14:47 -03001262 f->fmt.pix.bytesperline = (width * fmt->depth + 7) >> 3;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001263 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001264 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -03001265 if (dev->progressive)
1266 f->fmt.pix.field = V4L2_FIELD_NONE;
1267 else
1268 f->fmt.pix.field = dev->interlaced ?
1269 V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
Alban Browaeys51dd4d72013-07-16 19:06:46 -03001270 f->fmt.pix.priv = 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001271
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001272 return 0;
1273}
1274
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001275static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc,
1276 unsigned width, unsigned height)
1277{
1278 struct em28xx_fmt *fmt;
1279
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001280 fmt = format_by_fourcc(fourcc);
1281 if (!fmt)
1282 return -EINVAL;
1283
1284 dev->format = fmt;
1285 dev->width = width;
1286 dev->height = height;
1287
1288 /* set new image size */
Frank Schaefer6b09a212013-02-10 16:05:12 -03001289 size_to_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001290
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001291 em28xx_resolution_set(dev);
1292
1293 return 0;
1294}
1295
Hans Verkuil78b526a2008-05-28 12:16:41 -03001296static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001297 struct v4l2_format *f)
1298{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001299 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001300
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001301 if (dev->streaming_users > 0)
1302 return -EBUSY;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001303
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001304 vidioc_try_fmt_vid_cap(file, priv, f);
1305
Hans Verkuil0499a5a2010-09-26 07:34:45 -03001306 return em28xx_set_video_format(dev, f->fmt.pix.pixelformat,
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001307 f->fmt.pix.width, f->fmt.pix.height);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001308}
1309
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001310static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
1311{
1312 struct em28xx_fh *fh = priv;
1313 struct em28xx *dev = fh->dev;
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001314
1315 *norm = dev->norm;
1316
1317 return 0;
1318}
1319
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001320static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm)
1321{
1322 struct em28xx_fh *fh = priv;
1323 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001324
1325 v4l2_device_call_all(&dev->v4l2_dev, 0, video, querystd, norm);
1326
1327 return 0;
1328}
1329
Hans Verkuil314527a2013-03-15 06:10:40 -03001330static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001331{
1332 struct em28xx_fh *fh = priv;
1333 struct em28xx *dev = fh->dev;
1334 struct v4l2_format f;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001335
Hans Verkuil314527a2013-03-15 06:10:40 -03001336 if (norm == dev->norm)
Hans Verkuild8c95c02012-09-07 07:31:54 -03001337 return 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001338
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001339 if (dev->streaming_users > 0)
Hans Verkuild8c95c02012-09-07 07:31:54 -03001340 return -EBUSY;
Hans Verkuild8c95c02012-09-07 07:31:54 -03001341
Hans Verkuil314527a2013-03-15 06:10:40 -03001342 dev->norm = norm;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001343
1344 /* Adjusts width/height, if needed */
Hans Verkuild8c95c02012-09-07 07:31:54 -03001345 f.fmt.pix.width = 720;
Hans Verkuil314527a2013-03-15 06:10:40 -03001346 f.fmt.pix.height = (norm & V4L2_STD_525_60) ? 480 : 576;
Hans Verkuil78b526a2008-05-28 12:16:41 -03001347 vidioc_try_fmt_vid_cap(file, priv, &f);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001348
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001349 /* set new image size */
1350 dev->width = f.fmt.pix.width;
1351 dev->height = f.fmt.pix.height;
Frank Schaefer6b09a212013-02-10 16:05:12 -03001352 size_to_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001353
1354 em28xx_resolution_set(dev);
Hans Verkuilf41737e2009-04-01 03:52:39 -03001355 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001356
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001357 return 0;
1358}
1359
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001360static int vidioc_g_parm(struct file *file, void *priv,
1361 struct v4l2_streamparm *p)
1362{
1363 struct em28xx_fh *fh = priv;
1364 struct em28xx *dev = fh->dev;
1365 int rc = 0;
1366
Hans Verkuil86ff7f12012-09-07 06:16:03 -03001367 p->parm.capture.readbuffers = EM28XX_MIN_BUF;
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001368 if (dev->board.is_webcam)
1369 rc = v4l2_device_call_until_err(&dev->v4l2_dev, 0,
1370 video, g_parm, p);
1371 else
1372 v4l2_video_std_frame_period(dev->norm,
1373 &p->parm.capture.timeperframe);
1374
1375 return rc;
1376}
1377
1378static int vidioc_s_parm(struct file *file, void *priv,
1379 struct v4l2_streamparm *p)
1380{
1381 struct em28xx_fh *fh = priv;
1382 struct em28xx *dev = fh->dev;
1383
Hans Verkuil86ff7f12012-09-07 06:16:03 -03001384 p->parm.capture.readbuffers = EM28XX_MIN_BUF;
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001385 return v4l2_device_call_until_err(&dev->v4l2_dev, 0, video, s_parm, p);
1386}
1387
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001388static const char *iname[] = {
1389 [EM28XX_VMUX_COMPOSITE1] = "Composite1",
1390 [EM28XX_VMUX_COMPOSITE2] = "Composite2",
1391 [EM28XX_VMUX_COMPOSITE3] = "Composite3",
1392 [EM28XX_VMUX_COMPOSITE4] = "Composite4",
1393 [EM28XX_VMUX_SVIDEO] = "S-Video",
1394 [EM28XX_VMUX_TELEVISION] = "Television",
1395 [EM28XX_VMUX_CABLE] = "Cable TV",
1396 [EM28XX_VMUX_DVB] = "DVB",
1397 [EM28XX_VMUX_DEBUG] = "for debug only",
1398};
1399
1400static int vidioc_enum_input(struct file *file, void *priv,
1401 struct v4l2_input *i)
1402{
1403 struct em28xx_fh *fh = priv;
1404 struct em28xx *dev = fh->dev;
1405 unsigned int n;
1406
1407 n = i->index;
1408 if (n >= MAX_EM28XX_INPUT)
1409 return -EINVAL;
1410 if (0 == INPUT(n)->type)
1411 return -EINVAL;
1412
1413 i->index = n;
1414 i->type = V4L2_INPUT_TYPE_CAMERA;
1415
1416 strcpy(i->name, iname[INPUT(n)->type]);
1417
1418 if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type) ||
1419 (EM28XX_VMUX_CABLE == INPUT(n)->type))
1420 i->type = V4L2_INPUT_TYPE_TUNER;
1421
Mauro Carvalho Chehab7d497f82007-11-11 14:15:34 -03001422 i->std = dev->vdev->tvnorms;
Hans Verkuild8c95c02012-09-07 07:31:54 -03001423 /* webcams do not have the STD API */
1424 if (dev->board.is_webcam)
1425 i->capabilities = 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001426
1427 return 0;
1428}
1429
1430static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1431{
1432 struct em28xx_fh *fh = priv;
1433 struct em28xx *dev = fh->dev;
1434
1435 *i = dev->ctl_input;
1436
1437 return 0;
1438}
1439
1440static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
1441{
1442 struct em28xx_fh *fh = priv;
1443 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001444
1445 if (i >= MAX_EM28XX_INPUT)
1446 return -EINVAL;
1447 if (0 == INPUT(i)->type)
1448 return -EINVAL;
1449
Ezequiel García96371fc2012-03-23 18:09:34 -03001450 video_mux(dev, i);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001451 return 0;
1452}
1453
1454static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
1455{
1456 struct em28xx_fh *fh = priv;
1457 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001458
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001459 switch (a->index) {
1460 case EM28XX_AMUX_VIDEO:
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001461 strcpy(a->name, "Television");
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001462 break;
1463 case EM28XX_AMUX_LINE_IN:
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001464 strcpy(a->name, "Line In");
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001465 break;
1466 case EM28XX_AMUX_VIDEO2:
1467 strcpy(a->name, "Television alt");
1468 break;
1469 case EM28XX_AMUX_PHONE:
1470 strcpy(a->name, "Phone");
1471 break;
1472 case EM28XX_AMUX_MIC:
1473 strcpy(a->name, "Mic");
1474 break;
1475 case EM28XX_AMUX_CD:
1476 strcpy(a->name, "CD");
1477 break;
1478 case EM28XX_AMUX_AUX:
1479 strcpy(a->name, "Aux");
1480 break;
1481 case EM28XX_AMUX_PCM_OUT:
1482 strcpy(a->name, "PCM");
1483 break;
1484 default:
1485 return -EINVAL;
1486 }
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001487
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001488 a->index = dev->ctl_ainput;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001489 a->capability = V4L2_AUDCAP_STEREO;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001490
1491 return 0;
1492}
1493
Hans Verkuil0e8025b92012-09-04 11:59:31 -03001494static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001495{
1496 struct em28xx_fh *fh = priv;
1497 struct em28xx *dev = fh->dev;
1498
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03001499 if (a->index >= MAX_EM28XX_INPUT)
1500 return -EINVAL;
1501 if (0 == INPUT(a->index)->type)
1502 return -EINVAL;
1503
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001504 dev->ctl_ainput = INPUT(a->index)->amux;
1505 dev->ctl_aoutput = INPUT(a->index)->aout;
Mauro Carvalho Chehabe879b8e2008-11-20 13:39:39 -03001506
1507 if (!dev->ctl_aoutput)
1508 dev->ctl_aoutput = EM28XX_AOUT_MASTER;
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001509
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001510 return 0;
1511}
1512
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001513static int vidioc_g_tuner(struct file *file, void *priv,
1514 struct v4l2_tuner *t)
1515{
1516 struct em28xx_fh *fh = priv;
1517 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001518
1519 if (0 != t->index)
1520 return -EINVAL;
1521
1522 strcpy(t->name, "Tuner");
1523
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03001524 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001525 return 0;
1526}
1527
1528static int vidioc_s_tuner(struct file *file, void *priv,
Hans Verkuil2f73c7c2013-03-15 06:10:06 -03001529 const struct v4l2_tuner *t)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001530{
1531 struct em28xx_fh *fh = priv;
1532 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001533
1534 if (0 != t->index)
1535 return -EINVAL;
1536
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03001537 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001538 return 0;
1539}
1540
1541static int vidioc_g_frequency(struct file *file, void *priv,
1542 struct v4l2_frequency *f)
1543{
1544 struct em28xx_fh *fh = priv;
1545 struct em28xx *dev = fh->dev;
1546
Hans Verkuil20deebf2012-09-06 10:07:25 -03001547 if (0 != f->tuner)
1548 return -EINVAL;
1549
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001550 f->frequency = dev->ctl_freq;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001551 return 0;
1552}
1553
1554static int vidioc_s_frequency(struct file *file, void *priv,
Hans Verkuilb530a442013-03-19 04:09:26 -03001555 const struct v4l2_frequency *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001556{
Hans Verkuilb530a442013-03-19 04:09:26 -03001557 struct v4l2_frequency new_freq = *f;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001558 struct em28xx_fh *fh = priv;
1559 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001560
1561 if (0 != f->tuner)
1562 return -EINVAL;
1563
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03001564 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, f);
Hans Verkuilb530a442013-03-19 04:09:26 -03001565 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_frequency, &new_freq);
1566 dev->ctl_freq = new_freq.frequency;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001567
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001568 return 0;
1569}
1570
Hans Verkuilcd634f12013-03-27 08:04:23 -03001571#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuil96b03d22013-04-06 06:16:58 -03001572static int vidioc_g_chip_info(struct file *file, void *priv,
1573 struct v4l2_dbg_chip_info *chip)
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001574{
1575 struct em28xx_fh *fh = priv;
1576 struct em28xx *dev = fh->dev;
1577
1578 if (chip->match.addr > 1)
1579 return -EINVAL;
1580 if (chip->match.addr == 1)
1581 strlcpy(chip->name, "ac97", sizeof(chip->name));
1582 else
1583 strlcpy(chip->name, dev->v4l2_dev.name, sizeof(chip->name));
1584 return 0;
1585}
1586
Frank Schaefer35deba32013-02-07 13:39:19 -03001587static int em28xx_reg_len(int reg)
1588{
1589 switch (reg) {
1590 case EM28XX_R40_AC97LSB:
1591 case EM28XX_R30_HSCALELOW:
1592 case EM28XX_R32_VSCALELOW:
1593 return 2;
1594 default:
1595 return 1;
1596 }
1597}
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001598
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001599static int vidioc_g_register(struct file *file, void *priv,
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001600 struct v4l2_dbg_register *reg)
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001601{
1602 struct em28xx_fh *fh = priv;
1603 struct em28xx *dev = fh->dev;
1604 int ret;
1605
Hans Verkuilabca2052013-05-29 06:59:35 -03001606 if (reg->match.addr > 1)
1607 return -EINVAL;
1608 if (reg->match.addr) {
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001609 ret = em28xx_read_ac97(dev, reg->reg);
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001610 if (ret < 0)
1611 return ret;
1612
1613 reg->val = ret;
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001614 reg->size = 1;
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001615 return 0;
1616 }
1617
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001618 /* Match host */
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001619 reg->size = em28xx_reg_len(reg->reg);
1620 if (reg->size == 1) {
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001621 ret = em28xx_read_reg(dev, reg->reg);
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001622
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001623 if (ret < 0)
1624 return ret;
1625
1626 reg->val = ret;
1627 } else {
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001628 __le16 val = 0;
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001629 ret = dev->em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001630 reg->reg, (char *)&val, 2);
1631 if (ret < 0)
1632 return ret;
1633
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001634 reg->val = le16_to_cpu(val);
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001635 }
1636
1637 return 0;
1638}
1639
1640static int vidioc_s_register(struct file *file, void *priv,
Hans Verkuil977ba3b2013-03-24 08:28:46 -03001641 const struct v4l2_dbg_register *reg)
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001642{
1643 struct em28xx_fh *fh = priv;
1644 struct em28xx *dev = fh->dev;
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001645 __le16 buf;
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001646
Hans Verkuilabca2052013-05-29 06:59:35 -03001647 if (reg->match.addr > 1)
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001648 return -EINVAL;
Hans Verkuilabca2052013-05-29 06:59:35 -03001649 if (reg->match.addr)
1650 return em28xx_write_ac97(dev, reg->reg, reg->val);
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001651
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001652 /* Match host */
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001653 buf = cpu_to_le16(reg->val);
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001654
Hans Verkuil0499a5a2010-09-26 07:34:45 -03001655 return em28xx_write_regs(dev, reg->reg, (char *)&buf,
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001656 em28xx_reg_len(reg->reg));
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001657}
1658#endif
1659
1660
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001661static int vidioc_querycap(struct file *file, void *priv,
1662 struct v4l2_capability *cap)
1663{
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001664 struct video_device *vdev = video_devdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001665 struct em28xx_fh *fh = priv;
1666 struct em28xx *dev = fh->dev;
1667
1668 strlcpy(cap->driver, "em28xx", sizeof(cap->driver));
1669 strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card));
Thierry MERLEcb977162009-01-20 18:01:33 -03001670 usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001671
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001672 if (vdev->vfl_type == VFL_TYPE_GRABBER)
1673 cap->device_caps = V4L2_CAP_READWRITE |
1674 V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1675 else if (vdev->vfl_type == VFL_TYPE_RADIO)
1676 cap->device_caps = V4L2_CAP_RADIO;
1677 else
Hans Verkuil1d179ee2012-09-07 08:45:10 -03001678 cap->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE;
Devin Heitmueller04146142009-09-11 00:08:44 -03001679
Mauro Carvalho Chehab6c428b52009-08-04 19:52:37 -03001680 if (dev->audio_mode.has_audio)
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001681 cap->device_caps |= V4L2_CAP_AUDIO;
Mauro Carvalho Chehab6c428b52009-08-04 19:52:37 -03001682
Mauro Carvalho Chehabed086312008-01-24 06:59:20 -03001683 if (dev->tuner_type != TUNER_ABSENT)
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001684 cap->device_caps |= V4L2_CAP_TUNER;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001685
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001686 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS |
1687 V4L2_CAP_READWRITE | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1688 if (dev->vbi_dev)
Hans Verkuil1d179ee2012-09-07 08:45:10 -03001689 cap->capabilities |= V4L2_CAP_VBI_CAPTURE;
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001690 if (dev->radio_dev)
1691 cap->capabilities |= V4L2_CAP_RADIO;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001692 return 0;
1693}
1694
Hans Verkuil78b526a2008-05-28 12:16:41 -03001695static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001696 struct v4l2_fmtdesc *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001697{
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001698 if (unlikely(f->index >= ARRAY_SIZE(format)))
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001699 return -EINVAL;
1700
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001701 strlcpy(f->description, format[f->index].name, sizeof(f->description));
1702 f->pixelformat = format[f->index].fourcc;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001703
1704 return 0;
1705}
1706
Mauro Carvalho Chehab1c5c50682011-10-16 13:52:43 -02001707static int vidioc_enum_framesizes(struct file *file, void *priv,
1708 struct v4l2_frmsizeenum *fsize)
1709{
1710 struct em28xx_fh *fh = priv;
1711 struct em28xx *dev = fh->dev;
1712 struct em28xx_fmt *fmt;
1713 unsigned int maxw = norm_maxw(dev);
1714 unsigned int maxh = norm_maxh(dev);
1715
1716 fmt = format_by_fourcc(fsize->pixel_format);
1717 if (!fmt) {
1718 em28xx_videodbg("Fourcc format (%08x) invalid.\n",
1719 fsize->pixel_format);
1720 return -EINVAL;
1721 }
1722
1723 if (dev->board.is_em2800) {
1724 if (fsize->index > 1)
1725 return -EINVAL;
1726 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
1727 fsize->discrete.width = maxw / (1 + fsize->index);
1728 fsize->discrete.height = maxh / (1 + fsize->index);
1729 return 0;
1730 }
1731
1732 if (fsize->index != 0)
1733 return -EINVAL;
1734
1735 /* Report a continuous range */
1736 fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
Frank Schaefer6c3598e2013-02-10 16:05:14 -03001737 scale_to_size(dev, EM28XX_HVSCALE_MAX, EM28XX_HVSCALE_MAX,
1738 &fsize->stepwise.min_width, &fsize->stepwise.min_height);
1739 if (fsize->stepwise.min_width < 48)
1740 fsize->stepwise.min_width = 48;
1741 if (fsize->stepwise.min_height < 38)
1742 fsize->stepwise.min_height = 38;
Mauro Carvalho Chehab1c5c50682011-10-16 13:52:43 -02001743 fsize->stepwise.max_width = maxw;
1744 fsize->stepwise.max_height = maxh;
1745 fsize->stepwise.step_width = 1;
1746 fsize->stepwise.step_height = 1;
1747 return 0;
1748}
1749
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001750/* RAW VBI ioctls */
1751
1752static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
1753 struct v4l2_format *format)
1754{
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001755 struct em28xx_fh *fh = priv;
1756 struct em28xx *dev = fh->dev;
1757
1758 format->fmt.vbi.samples_per_line = dev->vbi_width;
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001759 format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
1760 format->fmt.vbi.offset = 0;
1761 format->fmt.vbi.flags = 0;
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001762 format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
1763 format->fmt.vbi.count[0] = dev->vbi_height;
1764 format->fmt.vbi.count[1] = dev->vbi_height;
Hans Verkuil2a221d32012-09-07 08:51:32 -03001765 memset(format->fmt.vbi.reserved, 0, sizeof(format->fmt.vbi.reserved));
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001766
1767 /* Varies by video standard (NTSC, PAL, etc.) */
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001768 if (dev->norm & V4L2_STD_525_60) {
1769 /* NTSC */
1770 format->fmt.vbi.start[0] = 10;
1771 format->fmt.vbi.start[1] = 273;
1772 } else if (dev->norm & V4L2_STD_625_50) {
1773 /* PAL */
1774 format->fmt.vbi.start[0] = 6;
1775 format->fmt.vbi.start[1] = 318;
1776 }
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001777
1778 return 0;
1779}
1780
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001781/* ----------------------------------------------------------- */
1782/* RADIO ESPECIFIC IOCTLS */
1783/* ----------------------------------------------------------- */
1784
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001785static int radio_g_tuner(struct file *file, void *priv,
1786 struct v4l2_tuner *t)
1787{
1788 struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;
1789
1790 if (unlikely(t->index > 0))
1791 return -EINVAL;
1792
1793 strcpy(t->name, "Radio");
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001794
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03001795 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001796
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001797 return 0;
1798}
1799
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001800static int radio_s_tuner(struct file *file, void *priv,
Hans Verkuil2f73c7c2013-03-15 06:10:06 -03001801 const struct v4l2_tuner *t)
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001802{
1803 struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;
1804
1805 if (0 != t->index)
1806 return -EINVAL;
1807
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03001808 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001809
1810 return 0;
1811}
1812
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001813/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08001814 * em28xx_v4l2_open()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001815 * inits the device and starts isoc transfer
1816 */
Hans Verkuilbec43662008-12-30 06:58:20 -03001817static int em28xx_v4l2_open(struct file *filp)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001818{
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001819 struct video_device *vdev = video_devdata(filp);
1820 struct em28xx *dev = video_drvdata(filp);
1821 enum v4l2_buf_type fh_type = 0;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001822 struct em28xx_fh *fh;
Markus Rechberger9c755412005-11-08 21:37:52 -08001823
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001824 switch (vdev->vfl_type) {
1825 case VFL_TYPE_GRABBER:
1826 fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1827 break;
1828 case VFL_TYPE_VBI:
1829 fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
1830 break;
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001831 }
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03001832
Laurent Pinchart50462eb2009-12-10 11:47:13 -02001833 em28xx_videodbg("open dev=%s type=%s users=%d\n",
1834 video_device_node_name(vdev), v4l2_type_names[fh_type],
1835 dev->users);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001836
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001837
Hans Verkuil876cb142012-06-23 08:12:47 -03001838 if (mutex_lock_interruptible(&dev->lock))
1839 return -ERESTARTSYS;
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001840 fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001841 if (!fh) {
1842 em28xx_errdev("em28xx-video.c: Out of memory?!\n");
Hans Verkuil876cb142012-06-23 08:12:47 -03001843 mutex_unlock(&dev->lock);
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001844 return -ENOMEM;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001845 }
Hans Verkuil69a61642012-09-07 05:52:40 -03001846 v4l2_fh_init(&fh->fh, vdev);
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001847 fh->dev = dev;
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001848 fh->type = fh_type;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001849 filp->private_data = fh;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001850
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001851 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001852 em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02001853 em28xx_resolution_set(dev);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001854
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001855 /* Needed, since GPIO might have disabled power of
1856 some i2c device
1857 */
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03001858 em28xx_wake_i2c(dev);
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001859
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02001860 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001861
1862 if (vdev->vfl_type == VFL_TYPE_RADIO) {
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001863 em28xx_videodbg("video_open: setting radio device\n");
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03001864 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_radio);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001865 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001866
1867 dev->users++;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001868
Hans Verkuil876cb142012-06-23 08:12:47 -03001869 mutex_unlock(&dev->lock);
Hans Verkuil69a61642012-09-07 05:52:40 -03001870 v4l2_fh_add(&fh->fh);
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001871
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001872 return 0;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001873}
1874
1875/*
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001876 * em28xx_v4l2_fini()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001877 * unregisters the v4l2,i2c and usb devices
1878 * called when the device gets disconected or at module unload
1879*/
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001880static int em28xx_v4l2_fini(struct em28xx *dev)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001881{
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001882 if (!dev->has_video) {
1883 /* This device does not support the v4l2 extension */
1884 return 0;
1885 }
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02001886
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001887 if (dev->radio_dev) {
Laurent Pinchartf0813b42009-11-27 13:57:30 -03001888 if (video_is_registered(dev->radio_dev))
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001889 video_unregister_device(dev->radio_dev);
1890 else
1891 video_device_release(dev->radio_dev);
1892 dev->radio_dev = NULL;
1893 }
1894 if (dev->vbi_dev) {
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001895 em28xx_info("V4L2 device %s deregistered\n",
1896 video_device_node_name(dev->vbi_dev));
Laurent Pinchartf0813b42009-11-27 13:57:30 -03001897 if (video_is_registered(dev->vbi_dev))
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001898 video_unregister_device(dev->vbi_dev);
1899 else
1900 video_device_release(dev->vbi_dev);
1901 dev->vbi_dev = NULL;
1902 }
1903 if (dev->vdev) {
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001904 em28xx_info("V4L2 device %s deregistered\n",
1905 video_device_node_name(dev->vdev));
Laurent Pinchartf0813b42009-11-27 13:57:30 -03001906 if (video_is_registered(dev->vdev))
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001907 video_unregister_device(dev->vdev);
1908 else
1909 video_device_release(dev->vdev);
1910 dev->vdev = NULL;
1911 }
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001912
1913 return 0;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001914}
1915
1916/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08001917 * em28xx_v4l2_close()
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001918 * stops streaming and deallocates all resources allocated by the v4l2
1919 * calls and ioctls
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001920 */
Hans Verkuilbec43662008-12-30 06:58:20 -03001921static int em28xx_v4l2_close(struct file *filp)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001922{
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001923 struct em28xx_fh *fh = filp->private_data;
1924 struct em28xx *dev = fh->dev;
1925 int errCode;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001926
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001927 em28xx_videodbg("users=%d\n", dev->users);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001928
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001929 vb2_fop_release(filp);
Ricardo Ribalda98c24dcd2013-11-06 05:39:35 -03001930 mutex_lock(&dev->lock);
Devin Heitmueller8c873d32009-09-03 00:23:27 -03001931
Devin Heitmuellere3ba4d32009-09-15 00:18:06 -03001932 if (dev->users == 1) {
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001933 /* the device is already disconnect,
1934 free the remaining resources */
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001935
Frank Schaefer2665c292012-12-27 19:02:43 -03001936 if (dev->disconnected) {
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001937 em28xx_release_resources(dev);
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001938 v4l2_ctrl_handler_free(&dev->ctrl_handler);
1939 v4l2_device_unregister(&dev->v4l2_dev);
Frank Schaefer0cf544a2012-11-08 14:11:49 -03001940 kfree(dev->alt_max_pkt_size_isoc);
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001941 goto exit;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001942 }
1943
Mauro Carvalho Chehabeb6c9632008-12-05 10:39:12 -03001944 /* Save some power by putting tuner to sleep */
Laurent Pinchart622b8282009-10-05 10:48:17 -03001945 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
Mauro Carvalho Chehabeb6c9632008-12-05 10:39:12 -03001946
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001947 /* do this before setting alternate! */
Mauro Carvalho Chehab2fe3e2e2008-11-27 09:10:40 -03001948 em28xx_set_mode(dev, EM28XX_SUSPEND);
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001949
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001950 /* set alternate 0 */
1951 dev->alt = 0;
1952 em28xx_videodbg("setting alternate 0\n");
1953 errCode = usb_set_interface(dev->udev, 0, 0);
1954 if (errCode < 0) {
1955 em28xx_errdev("cannot change alternate number to "
1956 "0 (error=%i)\n", errCode);
1957 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001958 }
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001959
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001960exit:
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001961 dev->users--;
Hans Verkuil876cb142012-06-23 08:12:47 -03001962 mutex_unlock(&dev->lock);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001963 return 0;
1964}
1965
Hans Verkuilbec43662008-12-30 06:58:20 -03001966static const struct v4l2_file_operations em28xx_v4l_fops = {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001967 .owner = THIS_MODULE,
1968 .open = em28xx_v4l2_open,
1969 .release = em28xx_v4l2_close,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001970 .read = vb2_fop_read,
1971 .poll = vb2_fop_poll,
1972 .mmap = vb2_fop_mmap,
Hans Verkuil0499a5a2010-09-26 07:34:45 -03001973 .unlocked_ioctl = video_ioctl2,
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001974};
1975
Hans Verkuila3998102008-07-21 02:57:38 -03001976static const struct v4l2_ioctl_ops video_ioctl_ops = {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001977 .vidioc_querycap = vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03001978 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1979 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1980 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1981 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001982 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Hans Verkuil2a221d32012-09-07 08:51:32 -03001983 .vidioc_try_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Frank Schaeferaab34612013-02-07 13:39:16 -03001984 .vidioc_s_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Mauro Carvalho Chehab1c5c50682011-10-16 13:52:43 -02001985 .vidioc_enum_framesizes = vidioc_enum_framesizes,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001986 .vidioc_g_audio = vidioc_g_audio,
1987 .vidioc_s_audio = vidioc_s_audio,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001988
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001989 .vidioc_reqbufs = vb2_ioctl_reqbufs,
1990 .vidioc_create_bufs = vb2_ioctl_create_bufs,
1991 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
1992 .vidioc_querybuf = vb2_ioctl_querybuf,
1993 .vidioc_qbuf = vb2_ioctl_qbuf,
1994 .vidioc_dqbuf = vb2_ioctl_dqbuf,
1995
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001996 .vidioc_g_std = vidioc_g_std,
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001997 .vidioc_querystd = vidioc_querystd,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001998 .vidioc_s_std = vidioc_s_std,
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001999 .vidioc_g_parm = vidioc_g_parm,
2000 .vidioc_s_parm = vidioc_s_parm,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002001 .vidioc_enum_input = vidioc_enum_input,
2002 .vidioc_g_input = vidioc_g_input,
2003 .vidioc_s_input = vidioc_s_input,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002004 .vidioc_streamon = vb2_ioctl_streamon,
2005 .vidioc_streamoff = vb2_ioctl_streamoff,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002006 .vidioc_g_tuner = vidioc_g_tuner,
2007 .vidioc_s_tuner = vidioc_s_tuner,
2008 .vidioc_g_frequency = vidioc_g_frequency,
2009 .vidioc_s_frequency = vidioc_s_frequency,
Hans Verkuil50fdf402012-09-07 06:10:12 -03002010 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
2011 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002012#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuil96b03d22013-04-06 06:16:58 -03002013 .vidioc_g_chip_info = vidioc_g_chip_info,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002014 .vidioc_g_register = vidioc_g_register,
2015 .vidioc_s_register = vidioc_s_register,
2016#endif
Hans Verkuila3998102008-07-21 02:57:38 -03002017};
2018
2019static const struct video_device em28xx_video_template = {
2020 .fops = &em28xx_v4l_fops,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002021 .release = video_device_release_empty,
Hans Verkuila3998102008-07-21 02:57:38 -03002022 .ioctl_ops = &video_ioctl_ops,
2023
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002024 .tvnorms = V4L2_STD_ALL,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002025};
2026
Hans Verkuilbec43662008-12-30 06:58:20 -03002027static const struct v4l2_file_operations radio_fops = {
Hans Verkuila3998102008-07-21 02:57:38 -03002028 .owner = THIS_MODULE,
2029 .open = em28xx_v4l2_open,
2030 .release = em28xx_v4l2_close,
Hans Verkuil8fd0bda2010-12-18 09:59:51 -03002031 .unlocked_ioctl = video_ioctl2,
Hans Verkuila3998102008-07-21 02:57:38 -03002032};
2033
2034static const struct v4l2_ioctl_ops radio_ioctl_ops = {
Hans Verkuila9d79fe2012-09-06 07:31:04 -03002035 .vidioc_querycap = vidioc_querycap,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002036 .vidioc_g_tuner = radio_g_tuner,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002037 .vidioc_s_tuner = radio_s_tuner,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002038 .vidioc_g_frequency = vidioc_g_frequency,
2039 .vidioc_s_frequency = vidioc_s_frequency,
Hans Verkuil50fdf402012-09-07 06:10:12 -03002040 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
2041 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002042#ifdef CONFIG_VIDEO_ADV_DEBUG
Michal Marek430c73f2013-04-16 08:06:30 -03002043 .vidioc_g_chip_info = vidioc_g_chip_info,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002044 .vidioc_g_register = vidioc_g_register,
2045 .vidioc_s_register = vidioc_s_register,
2046#endif
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002047};
2048
Hans Verkuila3998102008-07-21 02:57:38 -03002049static struct video_device em28xx_radio_template = {
2050 .name = "em28xx-radio",
Hans Verkuila3998102008-07-21 02:57:38 -03002051 .fops = &radio_fops,
2052 .ioctl_ops = &radio_ioctl_ops,
Hans Verkuila3998102008-07-21 02:57:38 -03002053};
2054
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002055/* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */
2056static unsigned short saa711x_addrs[] = {
2057 0x4a >> 1, 0x48 >> 1, /* SAA7111, SAA7111A and SAA7113 */
2058 0x42 >> 1, 0x40 >> 1, /* SAA7114, SAA7115 and SAA7118 */
2059 I2C_CLIENT_END };
2060
2061static unsigned short tvp5150_addrs[] = {
2062 0xb8 >> 1,
2063 0xba >> 1,
2064 I2C_CLIENT_END
2065};
2066
2067static unsigned short msp3400_addrs[] = {
2068 0x80 >> 1,
2069 0x88 >> 1,
2070 I2C_CLIENT_END
2071};
2072
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03002073/******************************** usb interface ******************************/
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002074
Adrian Bunk532fe652008-01-28 22:10:48 -03002075static struct video_device *em28xx_vdev_init(struct em28xx *dev,
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -03002076 const struct video_device *template,
2077 const char *type_name)
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002078{
2079 struct video_device *vfd;
2080
2081 vfd = video_device_alloc();
2082 if (NULL == vfd)
2083 return NULL;
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03002084
2085 *vfd = *template;
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03002086 vfd->v4l2_dev = &dev->v4l2_dev;
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03002087 vfd->debug = video_debug;
Hans Verkuil0499a5a2010-09-26 07:34:45 -03002088 vfd->lock = &dev->lock;
Hans Verkuil69a61642012-09-07 05:52:40 -03002089 set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
Hans Verkuild8c95c02012-09-07 07:31:54 -03002090 if (dev->board.is_webcam)
2091 vfd->tvnorms = 0;
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002092
2093 snprintf(vfd->name, sizeof(vfd->name), "%s %s",
2094 dev->name, type_name);
2095
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02002096 video_set_drvdata(vfd, dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002097 return vfd;
2098}
2099
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002100static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
2101{
2102 memset(ctl, 0, sizeof(*ctl));
2103
2104 ctl->fname = XC2028_DEFAULT_FIRMWARE;
2105 ctl->max_len = 64;
2106 ctl->mts = em28xx_boards[dev->model].mts_firmware;
2107
2108 switch (dev->model) {
2109 case EM2880_BOARD_EMPIRE_DUAL_TV:
2110 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
2111 case EM2882_BOARD_TERRATEC_HYBRID_XS:
2112 ctl->demod = XC3028_FE_ZARLINK456;
2113 break;
2114 case EM2880_BOARD_TERRATEC_HYBRID_XS:
2115 case EM2880_BOARD_TERRATEC_HYBRID_XS_FR:
2116 case EM2881_BOARD_PINNACLE_HYBRID_PRO:
2117 ctl->demod = XC3028_FE_ZARLINK456;
2118 break;
2119 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
2120 case EM2882_BOARD_PINNACLE_HYBRID_PRO_330E:
2121 ctl->demod = XC3028_FE_DEFAULT;
2122 break;
2123 case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600:
2124 ctl->demod = XC3028_FE_DEFAULT;
2125 ctl->fname = XC3028L_DEFAULT_FIRMWARE;
2126 break;
2127 case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850:
2128 case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950:
2129 case EM2880_BOARD_PINNACLE_PCTV_HD_PRO:
2130 /* FIXME: Better to specify the needed IF */
2131 ctl->demod = XC3028_FE_DEFAULT;
2132 break;
2133 case EM2883_BOARD_KWORLD_HYBRID_330U:
2134 case EM2882_BOARD_DIKOM_DK300:
2135 case EM2882_BOARD_KWORLD_VS_DVBT:
2136 ctl->demod = XC3028_FE_CHINA;
2137 ctl->fname = XC2028_DEFAULT_FIRMWARE;
2138 break;
2139 case EM2882_BOARD_EVGA_INDTUBE:
2140 ctl->demod = XC3028_FE_CHINA;
2141 ctl->fname = XC3028L_DEFAULT_FIRMWARE;
2142 break;
2143 default:
2144 ctl->demod = XC3028_FE_OREN538;
2145 }
2146}
2147
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002148static void em28xx_tuner_setup(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002149{
2150 struct tuner_setup tun_setup;
2151 struct v4l2_frequency f;
2152
2153 if (dev->tuner_type == TUNER_ABSENT)
2154 return;
2155
2156 memset(&tun_setup, 0, sizeof(tun_setup));
2157
2158 tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
2159 tun_setup.tuner_callback = em28xx_tuner_callback;
2160
2161 if (dev->board.radio.type) {
2162 tun_setup.type = dev->board.radio.type;
2163 tun_setup.addr = dev->board.radio_addr;
2164
2165 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup);
2166 }
2167
2168 if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type)) {
2169 tun_setup.type = dev->tuner_type;
2170 tun_setup.addr = dev->tuner_addr;
2171
2172 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup);
2173 }
2174
2175 if (dev->tda9887_conf) {
2176 struct v4l2_priv_tun_config tda9887_cfg;
2177
2178 tda9887_cfg.tuner = TUNER_TDA9887;
2179 tda9887_cfg.priv = &dev->tda9887_conf;
2180
2181 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, &tda9887_cfg);
2182 }
2183
2184 if (dev->tuner_type == TUNER_XC2028) {
2185 struct v4l2_priv_tun_config xc2028_cfg;
2186 struct xc2028_ctrl ctl;
2187
2188 memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
2189 memset(&ctl, 0, sizeof(ctl));
2190
2191 em28xx_setup_xc3028(dev, &ctl);
2192
2193 xc2028_cfg.tuner = TUNER_XC2028;
2194 xc2028_cfg.priv = &ctl;
2195
2196 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, &xc2028_cfg);
2197 }
2198
2199 /* configure tuner */
2200 f.tuner = 0;
2201 f.type = V4L2_TUNER_ANALOG_TV;
2202 f.frequency = 9076; /* just a magic number */
2203 dev->ctl_freq = f.frequency;
2204 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
2205}
2206
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002207static int em28xx_v4l2_init(struct em28xx *dev)
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002208{
Hans Verkuil081b9452012-09-07 05:43:59 -03002209 u8 val;
Mauro Carvalho Chehab2e5ef2d2008-12-28 22:26:36 -03002210 int ret;
Sascha Sommer1020d132012-01-08 16:54:28 -03002211 unsigned int maxw;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002212 struct v4l2_ctrl_handler *hdl = &dev->ctrl_handler;
2213
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002214 if (!dev->has_video) {
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002215 /* This device does not support the v4l2 extension */
2216 return 0;
2217 }
Mauro Carvalho Chehab2e5ef2d2008-12-28 22:26:36 -03002218
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -03002219 printk(KERN_INFO "%s: v4l2 driver version %s\n",
2220 dev->name, EM28XX_VERSION);
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002221
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002222 mutex_lock(&dev->lock);
2223
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002224 ret = v4l2_device_register(&dev->udev->dev, &dev->v4l2_dev);
2225 if (ret < 0) {
2226 em28xx_errdev("Call to v4l2_device_register() failed!\n");
2227 goto err;
2228 }
2229
2230 v4l2_ctrl_handler_init(hdl, 8);
2231 dev->v4l2_dev.ctrl_handler = hdl;
2232
2233 /*
2234 * Default format, used for tvp5150 or saa711x output formats
2235 */
2236 dev->vinmode = 0x10;
2237 dev->vinctl = EM28XX_VINCTRL_INTERLACED |
2238 EM28XX_VINCTRL_CCIR656_ENABLE;
2239
2240 /* request some modules */
2241
2242 if (dev->board.has_msp34xx)
2243 v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap[dev->def_i2c_bus],
2244 "msp3400", 0, msp3400_addrs);
2245
2246 if (dev->board.decoder == EM28XX_SAA711X)
2247 v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap[dev->def_i2c_bus],
2248 "saa7115_auto", 0, saa711x_addrs);
2249
2250 if (dev->board.decoder == EM28XX_TVP5150)
2251 v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap[dev->def_i2c_bus],
2252 "tvp5150", 0, tvp5150_addrs);
2253
2254 if (dev->board.adecoder == EM28XX_TVAUDIO)
2255 v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap[dev->def_i2c_bus],
2256 "tvaudio", dev->board.tvaudio_addr, NULL);
2257
2258 /* Initialize tuner and camera */
2259
2260 if (dev->board.tuner_type != TUNER_ABSENT) {
2261 int has_demod = (dev->tda9887_conf & TDA9887_PRESENT);
2262
2263 if (dev->board.radio.type)
2264 v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap[dev->def_i2c_bus],
2265 "tuner", dev->board.radio_addr, NULL);
2266
2267 if (has_demod)
2268 v4l2_i2c_new_subdev(&dev->v4l2_dev,
2269 &dev->i2c_adap[dev->def_i2c_bus], "tuner",
2270 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
2271 if (dev->tuner_addr == 0) {
2272 enum v4l2_i2c_tuner_type type =
2273 has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV;
2274 struct v4l2_subdev *sd;
2275
2276 sd = v4l2_i2c_new_subdev(&dev->v4l2_dev,
2277 &dev->i2c_adap[dev->def_i2c_bus], "tuner",
2278 0, v4l2_i2c_tuner_addrs(type));
2279
2280 if (sd)
2281 dev->tuner_addr = v4l2_i2c_subdev_addr(sd);
2282 } else {
2283 v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap[dev->def_i2c_bus],
2284 "tuner", dev->tuner_addr, NULL);
2285 }
2286 }
2287
2288 em28xx_tuner_setup(dev);
2289 em28xx_init_camera(dev);
2290
2291 /* Configure audio */
2292 ret = em28xx_audio_setup(dev);
2293 if (ret < 0) {
2294 em28xx_errdev("%s: Error while setting audio - error [%d]!\n",
2295 __func__, ret);
2296 goto unregister_dev;
2297 }
2298 if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
2299 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
2300 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
2301 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
2302 V4L2_CID_AUDIO_VOLUME, 0, 0x1f, 1, 0x1f);
2303 } else {
2304 /* install the em28xx notify callback */
2305 v4l2_ctrl_notify(v4l2_ctrl_find(hdl, V4L2_CID_AUDIO_MUTE),
2306 em28xx_ctrl_notify, dev);
2307 v4l2_ctrl_notify(v4l2_ctrl_find(hdl, V4L2_CID_AUDIO_VOLUME),
2308 em28xx_ctrl_notify, dev);
2309 }
2310
2311 /* wake i2c devices */
2312 em28xx_wake_i2c(dev);
2313
2314 /* init video dma queues */
2315 INIT_LIST_HEAD(&dev->vidq.active);
2316 INIT_LIST_HEAD(&dev->vbiq.active);
2317
2318 if (dev->board.has_msp34xx) {
2319 /* Send a reset to other chips via gpio */
2320 ret = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xf7);
2321 if (ret < 0) {
2322 em28xx_errdev("%s: em28xx_write_reg - msp34xx(1) failed! error [%d]\n",
2323 __func__, ret);
2324 goto unregister_dev;
2325 }
2326 msleep(3);
2327
2328 ret = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xff);
2329 if (ret < 0) {
2330 em28xx_errdev("%s: em28xx_write_reg - msp34xx(2) failed! error [%d]\n",
2331 __func__, ret);
2332 goto unregister_dev;
2333 }
2334 msleep(3);
2335 }
2336
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002337 /* set default norm */
Hans Verkuild8c95c02012-09-07 07:31:54 -03002338 dev->norm = V4L2_STD_PAL;
Hans Verkuild5906dd2010-09-26 07:45:15 -03002339 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm);
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002340 dev->interlaced = EM28XX_INTERLACED_DEFAULT;
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002341
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002342 /* Analog specific initialization */
2343 dev->format = &format[0];
Sascha Sommer1020d132012-01-08 16:54:28 -03002344
2345 maxw = norm_maxw(dev);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002346 /* MaxPacketSize for em2800 is too small to capture at full resolution
2347 * use half of maxw as the scaler can only scale to 50% */
2348 if (dev->board.is_em2800)
2349 maxw /= 2;
Sascha Sommer1020d132012-01-08 16:54:28 -03002350
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03002351 em28xx_set_video_format(dev, format[0].fourcc,
Sascha Sommer1020d132012-01-08 16:54:28 -03002352 maxw, norm_maxh(dev));
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03002353
Ezequiel García96371fc2012-03-23 18:09:34 -03002354 video_mux(dev, 0);
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002355
2356 /* Audio defaults */
2357 dev->mute = 1;
2358 dev->volume = 0x1f;
2359
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002360/* em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -03002361 val = (u8)em28xx_read_reg(dev, EM28XX_R0F_XCLK);
2362 em28xx_write_reg(dev, EM28XX_R0F_XCLK,
2363 (EM28XX_XCLK_AUDIO_UNMUTE | val));
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002364
2365 em28xx_set_outfmt(dev);
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002366 em28xx_compression_disable(dev);
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002367
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002368 /* Add image controls */
2369 /* NOTE: at this point, the subdevices are already registered, so bridge
2370 * controls are only added/enabled when no subdevice provides them */
2371 if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_CONTRAST))
2372 v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops,
2373 V4L2_CID_CONTRAST,
2374 0, 0x1f, 1, CONTRAST_DEFAULT);
2375 if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_BRIGHTNESS))
2376 v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops,
2377 V4L2_CID_BRIGHTNESS,
2378 -0x80, 0x7f, 1, BRIGHTNESS_DEFAULT);
2379 if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_SATURATION))
2380 v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops,
2381 V4L2_CID_SATURATION,
2382 0, 0x1f, 1, SATURATION_DEFAULT);
2383 if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_BLUE_BALANCE))
2384 v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops,
2385 V4L2_CID_BLUE_BALANCE,
2386 -0x30, 0x30, 1, BLUE_BALANCE_DEFAULT);
2387 if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_RED_BALANCE))
2388 v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops,
2389 V4L2_CID_RED_BALANCE,
2390 -0x30, 0x30, 1, RED_BALANCE_DEFAULT);
2391 if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_SHARPNESS))
2392 v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops,
2393 V4L2_CID_SHARPNESS,
2394 0, 0x0f, 1, SHARPNESS_DEFAULT);
2395
2396 /* Reset image controls */
2397 em28xx_colorlevels_set_default(dev);
2398 v4l2_ctrl_handler_setup(&dev->ctrl_handler);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002399 ret = dev->ctrl_handler.error;
2400 if (ret)
2401 goto unregister_dev;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002402
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002403 /* allocate and fill video video_device struct */
2404 dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video");
2405 if (!dev->vdev) {
2406 em28xx_errdev("cannot allocate video_device.\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002407 ret = -ENODEV;
2408 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002409 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002410 dev->vdev->queue = &dev->vb_vidq;
2411 dev->vdev->queue->lock = &dev->vb_queue_lock;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002412
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002413 /* disable inapplicable ioctls */
2414 if (dev->board.is_webcam) {
2415 v4l2_disable_ioctl(dev->vdev, VIDIOC_QUERYSTD);
2416 v4l2_disable_ioctl(dev->vdev, VIDIOC_G_STD);
2417 v4l2_disable_ioctl(dev->vdev, VIDIOC_S_STD);
Frank Schaefer3bc85cc2013-02-07 13:39:12 -03002418 } else {
2419 v4l2_disable_ioctl(dev->vdev, VIDIOC_S_PARM);
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002420 }
Frank Schaefer66df67b2013-02-07 13:39:10 -03002421 if (dev->tuner_type == TUNER_ABSENT) {
2422 v4l2_disable_ioctl(dev->vdev, VIDIOC_G_TUNER);
2423 v4l2_disable_ioctl(dev->vdev, VIDIOC_S_TUNER);
2424 v4l2_disable_ioctl(dev->vdev, VIDIOC_G_FREQUENCY);
2425 v4l2_disable_ioctl(dev->vdev, VIDIOC_S_FREQUENCY);
2426 }
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002427 if (!dev->audio_mode.has_audio) {
2428 v4l2_disable_ioctl(dev->vdev, VIDIOC_G_AUDIO);
2429 v4l2_disable_ioctl(dev->vdev, VIDIOC_S_AUDIO);
2430 }
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002431
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002432 /* register v4l2 video video_device */
2433 ret = video_register_device(dev->vdev, VFL_TYPE_GRABBER,
2434 video_nr[dev->devno]);
2435 if (ret) {
2436 em28xx_errdev("unable to register video device (error=%i).\n",
2437 ret);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002438 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002439 }
2440
2441 /* Allocate and fill vbi video_device struct */
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002442 if (em28xx_vbi_supported(dev) == 1) {
2443 dev->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template,
2444 "vbi");
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002445
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002446 dev->vbi_dev->queue = &dev->vb_vbiq;
2447 dev->vbi_dev->queue->lock = &dev->vb_vbi_queue_lock;
2448
Frank Schaefer66df67b2013-02-07 13:39:10 -03002449 /* disable inapplicable ioctls */
Frank Schaefer83c8bcc2013-02-07 13:39:13 -03002450 v4l2_disable_ioctl(dev->vdev, VIDIOC_S_PARM);
Frank Schaefer66df67b2013-02-07 13:39:10 -03002451 if (dev->tuner_type == TUNER_ABSENT) {
2452 v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_G_TUNER);
2453 v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_S_TUNER);
2454 v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_G_FREQUENCY);
2455 v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_S_FREQUENCY);
2456 }
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002457 if (!dev->audio_mode.has_audio) {
2458 v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_G_AUDIO);
2459 v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_S_AUDIO);
2460 }
Frank Schaefer66df67b2013-02-07 13:39:10 -03002461
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002462 /* register v4l2 vbi video_device */
2463 ret = video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
2464 vbi_nr[dev->devno]);
2465 if (ret < 0) {
2466 em28xx_errdev("unable to register vbi device\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002467 goto unregister_dev;
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002468 }
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002469 }
2470
2471 if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) {
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -03002472 dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template,
2473 "radio");
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002474 if (!dev->radio_dev) {
2475 em28xx_errdev("cannot allocate video_device.\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002476 ret = -ENODEV;
2477 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002478 }
2479 ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO,
2480 radio_nr[dev->devno]);
2481 if (ret < 0) {
2482 em28xx_errdev("can't register radio device\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002483 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002484 }
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002485 em28xx_info("Registered radio device as %s\n",
2486 video_device_node_name(dev->radio_dev));
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002487 }
2488
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002489 em28xx_info("V4L2 video device registered as %s\n",
2490 video_device_node_name(dev->vdev));
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002491
2492 if (dev->vbi_dev)
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002493 em28xx_info("V4L2 VBI device registered as %s\n",
2494 video_device_node_name(dev->vbi_dev));
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002495
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002496 /* Save some power by putting tuner to sleep */
2497 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
2498
2499 /* initialize videobuf2 stuff */
2500 em28xx_vb2_setup(dev);
2501
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002502 mutex_unlock(&dev->lock);
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002503 return 0;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002504
2505unregister_dev:
2506 v4l2_ctrl_handler_free(&dev->ctrl_handler);
2507 v4l2_device_unregister(&dev->v4l2_dev);
2508err:
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002509 mutex_unlock(&dev->lock);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002510 return ret;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002511}
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002512
2513static struct em28xx_ops v4l2_ops = {
2514 .id = EM28XX_V4L2,
2515 .name = "Em28xx v4l2 Extension",
2516 .init = em28xx_v4l2_init,
2517 .fini = em28xx_v4l2_fini,
2518};
2519
2520static int __init em28xx_video_register(void)
2521{
2522 return em28xx_register_extension(&v4l2_ops);
2523}
2524
2525static void __exit em28xx_video_unregister(void)
2526{
2527 em28xx_unregister_extension(&v4l2_ops);
2528}
2529
2530module_init(em28xx_video_register);
2531module_exit(em28xx_video_unregister);