blob: eeb58ebd98f6b536971b3f8ec9eb22eabbea83d3 [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>
Frank Schaefer25dd1652014-01-12 13:24:23 -030045#include <media/v4l2-clk.h>
Hans Verkuil2474ed42006-03-19 12:35:57 -030046#include <media/msp3400.h>
Mauro Carvalho Chehabed086312008-01-24 06:59:20 -030047#include <media/tuner.h>
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080048
Mauro Carvalho Chehabf7abcd32005-11-08 21:38:25 -080049#define DRIVER_AUTHOR "Ludovico Cavedon <cavedon@sssup.it>, " \
50 "Markus Rechberger <mrechberger@gmail.com>, " \
Mauro Carvalho Chehab2e7c6dc2006-04-03 07:53:40 -030051 "Mauro Carvalho Chehab <mchehab@infradead.org>, " \
Mauro Carvalho Chehabf7abcd32005-11-08 21:38:25 -080052 "Sascha Sommer <saschasommer@freenet.de>"
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080053
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -030054static unsigned int isoc_debug;
55module_param(isoc_debug, int, 0644);
56MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");
57
58static unsigned int disable_vbi;
59module_param(disable_vbi, int, 0644);
60MODULE_PARM_DESC(disable_vbi, "disable vbi support");
61
62static int alt;
63module_param(alt, int, 0644);
64MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint");
65
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -080066#define em28xx_videodbg(fmt, arg...) do {\
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -080067 if (video_debug) \
68 printk(KERN_INFO "%s %s :"fmt, \
Harvey Harrisond80e1342008-04-08 23:20:00 -030069 dev->name, __func__ , ##arg); } while (0)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080070
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -030071#define em28xx_isocdbg(fmt, arg...) \
72do {\
73 if (isoc_debug) { \
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -030074 printk(KERN_INFO "%s %s :"fmt, \
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -030075 dev->name, __func__ , ##arg); \
76 } \
77 } while (0)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -030078
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080079MODULE_AUTHOR(DRIVER_AUTHOR);
Mauro Carvalho Chehabd8992b02013-12-27 11:14:59 -030080MODULE_DESCRIPTION(DRIVER_DESC " - v4l2 interface");
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080081MODULE_LICENSE("GPL");
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -030082MODULE_VERSION(EM28XX_VERSION);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080083
Frank Schaefere507e0e2013-03-26 13:38:38 -030084
85#define EM25XX_FRMDATAHDR_BYTE1 0x02
86#define EM25XX_FRMDATAHDR_BYTE2_STILL_IMAGE 0x20
87#define EM25XX_FRMDATAHDR_BYTE2_FRAME_END 0x02
88#define EM25XX_FRMDATAHDR_BYTE2_FRAME_ID 0x01
89#define EM25XX_FRMDATAHDR_BYTE2_MASK (EM25XX_FRMDATAHDR_BYTE2_STILL_IMAGE | \
90 EM25XX_FRMDATAHDR_BYTE2_FRAME_END | \
91 EM25XX_FRMDATAHDR_BYTE2_FRAME_ID)
92
93
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -030094static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
95static unsigned int vbi_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
96static unsigned int radio_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -030097
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -020098module_param_array(video_nr, int, NULL, 0444);
99module_param_array(vbi_nr, int, NULL, 0444);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -0300100module_param_array(radio_nr, int, NULL, 0444);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -0300101MODULE_PARM_DESC(video_nr, "video device numbers");
102MODULE_PARM_DESC(vbi_nr, "vbi device numbers");
103MODULE_PARM_DESC(radio_nr, "radio device numbers");
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800104
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -0300105static unsigned int video_debug;
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -0300106module_param(video_debug, int, 0644);
107MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800108
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -0300109/* supported video standards */
110static struct em28xx_fmt format[] = {
111 {
Mauro Carvalho Chehab58fc1ce2009-07-03 02:54:18 -0300112 .name = "16 bpp YUY2, 4:2:2, packed",
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -0300113 .fourcc = V4L2_PIX_FMT_YUYV,
114 .depth = 16,
Devin Heitmueller3fbf9302008-12-29 23:34:37 -0300115 .reg = EM28XX_OUTFMT_YUV422_Y0UY1V,
Mauro Carvalho Chehab43cb9fe2009-06-30 08:36:17 -0300116 }, {
Mauro Carvalho Chehab58fc1ce2009-07-03 02:54:18 -0300117 .name = "16 bpp RGB 565, LE",
Mauro Carvalho Chehab43cb9fe2009-06-30 08:36:17 -0300118 .fourcc = V4L2_PIX_FMT_RGB565,
119 .depth = 16,
Mauro Carvalho Chehab58fc1ce2009-07-03 02:54:18 -0300120 .reg = EM28XX_OUTFMT_RGB_16_656,
121 }, {
122 .name = "8 bpp Bayer BGBG..GRGR",
123 .fourcc = V4L2_PIX_FMT_SBGGR8,
124 .depth = 8,
125 .reg = EM28XX_OUTFMT_RGB_8_BGBG,
126 }, {
127 .name = "8 bpp Bayer GRGR..BGBG",
128 .fourcc = V4L2_PIX_FMT_SGRBG8,
129 .depth = 8,
130 .reg = EM28XX_OUTFMT_RGB_8_GRGR,
131 }, {
132 .name = "8 bpp Bayer GBGB..RGRG",
133 .fourcc = V4L2_PIX_FMT_SGBRG8,
134 .depth = 8,
135 .reg = EM28XX_OUTFMT_RGB_8_GBGB,
136 }, {
137 .name = "12 bpp YUV411",
138 .fourcc = V4L2_PIX_FMT_YUV411P,
139 .depth = 12,
140 .reg = EM28XX_OUTFMT_YUV411,
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -0300141 },
142};
143
Frank Schaefer25c61e42014-03-22 10:01:03 -0300144/*FIXME: maxw should be dependent of alt mode */
145static inline unsigned int norm_maxw(struct em28xx *dev)
146{
147 if (dev->board.is_webcam)
148 return dev->sensor_xres;
149
150 if (dev->board.max_range_640_480)
151 return 640;
152
153 return 720;
154}
155
156static inline unsigned int norm_maxh(struct em28xx *dev)
157{
158 if (dev->board.is_webcam)
159 return dev->sensor_yres;
160
161 if (dev->board.max_range_640_480)
162 return 480;
163
164 return (dev->norm & V4L2_STD_625_50) ? 576 : 480;
165}
166
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300167static int em28xx_vbi_supported(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300168{
169 /* Modprobe option to manually disable */
170 if (disable_vbi == 1)
171 return 0;
172
173 if (dev->board.is_webcam)
174 return 0;
175
176 /* FIXME: check subdevices for VBI support */
177
178 if (dev->chip_id == CHIP_ID_EM2860 ||
179 dev->chip_id == CHIP_ID_EM2883)
180 return 1;
181
182 /* Version of em28xx that does not support VBI */
183 return 0;
184}
185
186/*
187 * em28xx_wake_i2c()
188 * configure i2c attached devices
189 */
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300190static void em28xx_wake_i2c(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300191{
Frank Schaefer95d26082014-03-24 16:33:09 -0300192 struct v4l2_device *v4l2_dev = &dev->v4l2->v4l2_dev;
193 v4l2_device_call_all(v4l2_dev, 0, core, reset, 0);
194 v4l2_device_call_all(v4l2_dev, 0, video, s_routing,
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300195 INPUT(dev->ctl_input)->vmux, 0, 0);
Frank Schaefer95d26082014-03-24 16:33:09 -0300196 v4l2_device_call_all(v4l2_dev, 0, video, s_stream, 0);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300197}
198
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300199static int em28xx_colorlevels_set_default(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300200{
201 em28xx_write_reg(dev, EM28XX_R20_YGAIN, CONTRAST_DEFAULT);
202 em28xx_write_reg(dev, EM28XX_R21_YOFFSET, BRIGHTNESS_DEFAULT);
203 em28xx_write_reg(dev, EM28XX_R22_UVGAIN, SATURATION_DEFAULT);
204 em28xx_write_reg(dev, EM28XX_R23_UOFFSET, BLUE_BALANCE_DEFAULT);
205 em28xx_write_reg(dev, EM28XX_R24_VOFFSET, RED_BALANCE_DEFAULT);
206 em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, SHARPNESS_DEFAULT);
207
208 em28xx_write_reg(dev, EM28XX_R14_GAMMA, 0x20);
209 em28xx_write_reg(dev, EM28XX_R15_RGAIN, 0x20);
210 em28xx_write_reg(dev, EM28XX_R16_GGAIN, 0x20);
211 em28xx_write_reg(dev, EM28XX_R17_BGAIN, 0x20);
212 em28xx_write_reg(dev, EM28XX_R18_ROFFSET, 0x00);
213 em28xx_write_reg(dev, EM28XX_R19_GOFFSET, 0x00);
214 return em28xx_write_reg(dev, EM28XX_R1A_BOFFSET, 0x00);
215}
216
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300217static int em28xx_set_outfmt(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300218{
219 int ret;
220 u8 fmt, vinctrl;
Frank Schaefer753aee72014-03-24 16:33:14 -0300221 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300222
223 fmt = dev->format->reg;
224 if (!dev->is_em25xx)
225 fmt |= 0x20;
226 /*
227 * NOTE: it's not clear if this is really needed !
228 * The datasheets say bit 5 is a reserved bit and devices seem to work
229 * fine without it. But the Windows driver sets it for em2710/50+em28xx
230 * devices and we've always been setting it, too.
231 *
232 * em2765 (em25xx, em276x/7x/8x) devices do NOT work with this bit set,
233 * it's likely used for an additional (compressed ?) format there.
234 */
235 ret = em28xx_write_reg(dev, EM28XX_R27_OUTFMT, fmt);
236 if (ret < 0)
237 return ret;
238
239 ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, dev->vinmode);
240 if (ret < 0)
241 return ret;
242
243 vinctrl = dev->vinctl;
244 if (em28xx_vbi_supported(dev) == 1) {
245 vinctrl |= EM28XX_VINCTRL_VBI_RAW;
246 em28xx_write_reg(dev, EM28XX_R34_VBI_START_H, 0x00);
Frank Schaefer753aee72014-03-24 16:33:14 -0300247 em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH, v4l2->vbi_width/4);
248 em28xx_write_reg(dev, EM28XX_R37_VBI_HEIGHT, v4l2->vbi_height);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300249 if (dev->norm & V4L2_STD_525_60) {
250 /* NTSC */
251 em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x09);
252 } else if (dev->norm & V4L2_STD_625_50) {
253 /* PAL */
254 em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x07);
255 }
256 }
257
258 return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctrl);
259}
260
261static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax,
262 u8 ymin, u8 ymax)
263{
264 em28xx_videodbg("em28xx Scale: (%d,%d)-(%d,%d)\n",
265 xmin, ymin, xmax, ymax);
266
267 em28xx_write_regs(dev, EM28XX_R28_XMIN, &xmin, 1);
268 em28xx_write_regs(dev, EM28XX_R29_XMAX, &xmax, 1);
269 em28xx_write_regs(dev, EM28XX_R2A_YMIN, &ymin, 1);
270 return em28xx_write_regs(dev, EM28XX_R2B_YMAX, &ymax, 1);
271}
272
273static void em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
274 u16 width, u16 height)
275{
276 u8 cwidth = width >> 2;
277 u8 cheight = height >> 2;
278 u8 overflow = (height >> 9 & 0x02) | (width >> 10 & 0x01);
279 /* NOTE: size limit: 2047x1023 = 2MPix */
280
281 em28xx_videodbg("capture area set to (%d,%d): %dx%d\n",
282 hstart, vstart,
283 ((overflow & 2) << 9 | cwidth << 2),
284 ((overflow & 1) << 10 | cheight << 2));
285
286 em28xx_write_regs(dev, EM28XX_R1C_HSTART, &hstart, 1);
287 em28xx_write_regs(dev, EM28XX_R1D_VSTART, &vstart, 1);
288 em28xx_write_regs(dev, EM28XX_R1E_CWIDTH, &cwidth, 1);
289 em28xx_write_regs(dev, EM28XX_R1F_CHEIGHT, &cheight, 1);
290 em28xx_write_regs(dev, EM28XX_R1B_OFLOW, &overflow, 1);
291
292 /* FIXME: function/meaning of these registers ? */
293 /* FIXME: align width+height to multiples of 4 ?! */
294 if (dev->is_em25xx) {
295 em28xx_write_reg(dev, 0x34, width >> 4);
296 em28xx_write_reg(dev, 0x35, height >> 4);
297 }
298}
299
300static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v)
301{
Frank Schaefercba8e9b2014-03-24 16:28:36 -0300302 u8 mode = 0x00;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300303 /* the em2800 scaler only supports scaling down to 50% */
304
305 if (dev->board.is_em2800) {
306 mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00);
307 } else {
308 u8 buf[2];
309
310 buf[0] = h;
311 buf[1] = h >> 8;
312 em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2);
313
314 buf[0] = v;
315 buf[1] = v >> 8;
316 em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2);
317 /* it seems that both H and V scalers must be active
318 to work correctly */
319 mode = (h || v) ? 0x30 : 0x00;
320 }
Frank Schaefercba8e9b2014-03-24 16:28:36 -0300321 return em28xx_write_reg(dev, EM28XX_R26_COMPR, mode);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300322}
323
324/* FIXME: this only function read values from dev */
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300325static int em28xx_resolution_set(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300326{
Frank Schaefer753aee72014-03-24 16:33:14 -0300327 struct em28xx_v4l2 *v4l2 = dev->v4l2;
328 int width = norm_maxw(dev);
329 int height = norm_maxh(dev);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300330
331 /* Properly setup VBI */
Frank Schaefer753aee72014-03-24 16:33:14 -0300332 v4l2->vbi_width = 720;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300333 if (dev->norm & V4L2_STD_525_60)
Frank Schaefer753aee72014-03-24 16:33:14 -0300334 v4l2->vbi_height = 12;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300335 else
Frank Schaefer753aee72014-03-24 16:33:14 -0300336 v4l2->vbi_height = 18;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300337
338 em28xx_set_outfmt(dev);
339
340 em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2);
341
342 /* If we don't set the start position to 2 in VBI mode, we end up
343 with line 20/21 being YUYV encoded instead of being in 8-bit
344 greyscale. The core of the issue is that line 21 (and line 23 for
345 PAL WSS) are inside of active video region, and as a result they
346 get the pixelformatting associated with that area. So by cropping
347 it out, we end up with the same format as the rest of the VBI
348 region */
349 if (em28xx_vbi_supported(dev) == 1)
350 em28xx_capture_area_set(dev, 0, 2, width, height);
351 else
352 em28xx_capture_area_set(dev, 0, 0, width, height);
353
Frank Schaefer753aee72014-03-24 16:33:14 -0300354 return em28xx_scaler_set(dev, v4l2->hscale, v4l2->vscale);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300355}
356
357/* Set USB alternate setting for analog video */
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300358static int em28xx_set_alternate(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300359{
Frank Schaefer753aee72014-03-24 16:33:14 -0300360 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300361 int errCode;
362 int i;
Frank Schaefer753aee72014-03-24 16:33:14 -0300363 unsigned int min_pkt_size = v4l2->width * 2 + 4;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300364
365 /* NOTE: for isoc transfers, only alt settings > 0 are allowed
366 bulk transfers seem to work only with alt=0 ! */
367 dev->alt = 0;
368 if ((alt > 0) && (alt < dev->num_alt)) {
369 em28xx_videodbg("alternate forced to %d\n", dev->alt);
370 dev->alt = alt;
371 goto set_alt;
372 }
373 if (dev->analog_xfer_bulk)
374 goto set_alt;
375
376 /* When image size is bigger than a certain value,
377 the frame size should be increased, otherwise, only
378 green screen will be received.
379 */
Frank Schaefer753aee72014-03-24 16:33:14 -0300380 if (v4l2->width * 2 * v4l2->height > 720 * 240 * 2)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300381 min_pkt_size *= 2;
382
383 for (i = 0; i < dev->num_alt; i++) {
384 /* stop when the selected alt setting offers enough bandwidth */
385 if (dev->alt_max_pkt_size_isoc[i] >= min_pkt_size) {
386 dev->alt = i;
387 break;
388 /* otherwise make sure that we end up with the maximum bandwidth
389 because the min_pkt_size equation might be wrong...
390 */
391 } else if (dev->alt_max_pkt_size_isoc[i] >
392 dev->alt_max_pkt_size_isoc[dev->alt])
393 dev->alt = i;
394 }
395
396set_alt:
397 /* NOTE: for bulk transfers, we need to call usb_set_interface()
398 * even if the previous settings were the same. Otherwise streaming
399 * fails with all urbs having status = -EOVERFLOW ! */
400 if (dev->analog_xfer_bulk) {
401 dev->max_pkt_size = 512; /* USB 2.0 spec */
402 dev->packet_multiplier = EM28XX_BULK_PACKET_MULTIPLIER;
403 } else { /* isoc */
404 em28xx_videodbg("minimum isoc packet size: %u (alt=%d)\n",
405 min_pkt_size, dev->alt);
406 dev->max_pkt_size =
407 dev->alt_max_pkt_size_isoc[dev->alt];
408 dev->packet_multiplier = EM28XX_NUM_ISOC_PACKETS;
409 }
410 em28xx_videodbg("setting alternate %d with wMaxPacketSize=%u\n",
411 dev->alt, dev->max_pkt_size);
Frank Schaefer961717b2014-01-13 19:02:06 -0300412 errCode = usb_set_interface(dev->udev, dev->ifnum, dev->alt);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300413 if (errCode < 0) {
414 em28xx_errdev("cannot change alternate number to %d (error=%i)\n",
415 dev->alt, errCode);
416 return errCode;
417 }
418 return 0;
419}
420
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300421/* ------------------------------------------------------------------
422 DMA and thread functions
423 ------------------------------------------------------------------*/
424
425/*
Frank Schaefer948a49a2012-12-08 11:31:25 -0300426 * Finish the current buffer
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300427 */
Frank Schaefer948a49a2012-12-08 11:31:25 -0300428static inline void finish_buffer(struct em28xx *dev,
429 struct em28xx_buffer *buf)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300430{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300431 em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->top_field);
432
433 buf->vb.v4l2_buf.sequence = dev->field_count++;
434 buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
435 v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
436
437 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300438}
439
440/*
Frank Schaefer36016a32012-12-08 11:31:32 -0300441 * Copy picture data from USB buffer to videobuf buffer
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300442 */
443static void em28xx_copy_video(struct em28xx *dev,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300444 struct em28xx_buffer *buf,
Frank Schaefer36016a32012-12-08 11:31:32 -0300445 unsigned char *usb_buf,
Frank Schaefer4078d622012-12-08 11:31:29 -0300446 unsigned long len)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300447{
448 void *fieldstart, *startwrite, *startread;
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300449 int linesdone, currlinedone, offset, lencopy, remain;
Frank Schaefer753aee72014-03-24 16:33:14 -0300450 int bytesperline = dev->v4l2->width << 1;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300451
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300452 if (buf->pos + len > buf->length)
453 len = buf->length - buf->pos;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300454
Frank Schaefer36016a32012-12-08 11:31:32 -0300455 startread = usb_buf;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300456 remain = len;
457
Frank Schaeferc02ec712012-11-08 14:11:33 -0300458 if (dev->progressive || buf->top_field)
Frank Schaefer36016a32012-12-08 11:31:32 -0300459 fieldstart = buf->vb_buf;
Frank Schaeferc02ec712012-11-08 14:11:33 -0300460 else /* interlaced mode, even nr. of lines */
Frank Schaefer36016a32012-12-08 11:31:32 -0300461 fieldstart = buf->vb_buf + bytesperline;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300462
Frank Schaefer87325332012-12-08 11:31:27 -0300463 linesdone = buf->pos / bytesperline;
464 currlinedone = buf->pos % bytesperline;
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -0300465
466 if (dev->progressive)
467 offset = linesdone * bytesperline + currlinedone;
468 else
469 offset = linesdone * bytesperline * 2 + currlinedone;
470
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300471 startwrite = fieldstart + offset;
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300472 lencopy = bytesperline - currlinedone;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300473 lencopy = lencopy > remain ? remain : lencopy;
474
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300475 if ((char *)startwrite + lencopy > (char *)buf->vb_buf + buf->length) {
Mauro Carvalho Chehabea8df7e2008-04-13 14:39:29 -0300476 em28xx_isocdbg("Overflow of %zi bytes past buffer end (1)\n",
Frank Schaefer36016a32012-12-08 11:31:32 -0300477 ((char *)startwrite + lencopy) -
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300478 ((char *)buf->vb_buf + buf->length));
479 remain = (char *)buf->vb_buf + buf->length -
Frank Schaefer36016a32012-12-08 11:31:32 -0300480 (char *)startwrite;
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -0300481 lencopy = remain;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300482 }
Aidan Thorntone0fadfd342008-04-13 14:56:02 -0300483 if (lencopy <= 0)
484 return;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300485 memcpy(startwrite, startread, lencopy);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300486
487 remain -= lencopy;
488
489 while (remain > 0) {
Frank Schaeferc02ec712012-11-08 14:11:33 -0300490 if (dev->progressive)
491 startwrite += lencopy;
492 else
493 startwrite += lencopy + bytesperline;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300494 startread += lencopy;
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300495 if (bytesperline > remain)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300496 lencopy = remain;
497 else
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300498 lencopy = bytesperline;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300499
Frank Schaefer36016a32012-12-08 11:31:32 -0300500 if ((char *)startwrite + lencopy > (char *)buf->vb_buf +
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300501 buf->length) {
Devin Heitmuellere3ba4d32009-09-15 00:18:06 -0300502 em28xx_isocdbg("Overflow of %zi bytes past buffer end"
503 "(2)\n",
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300504 ((char *)startwrite + lencopy) -
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300505 ((char *)buf->vb_buf + buf->length));
506 lencopy = remain = (char *)buf->vb_buf + buf->length -
507 (char *)startwrite;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300508 }
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300509 if (lencopy <= 0)
510 break;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300511
512 memcpy(startwrite, startread, lencopy);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300513
514 remain -= lencopy;
515 }
516
Frank Schaefer87325332012-12-08 11:31:27 -0300517 buf->pos += len;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300518}
519
Frank Schaefer36016a32012-12-08 11:31:32 -0300520/*
521 * Copy VBI data from USB buffer to videobuf buffer
522 */
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300523static void em28xx_copy_vbi(struct em28xx *dev,
Frank Schaefer87325332012-12-08 11:31:27 -0300524 struct em28xx_buffer *buf,
Frank Schaefer36016a32012-12-08 11:31:32 -0300525 unsigned char *usb_buf,
Frank Schaefer4078d622012-12-08 11:31:29 -0300526 unsigned long len)
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300527{
Frank Schaefer36016a32012-12-08 11:31:32 -0300528 unsigned int offset;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300529
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300530 if (buf->pos + len > buf->length)
531 len = buf->length - buf->pos;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300532
Frank Schaefer87325332012-12-08 11:31:27 -0300533 offset = buf->pos;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300534 /* Make sure the bottom field populates the second half of the frame */
Frank Schaefer36016a32012-12-08 11:31:32 -0300535 if (buf->top_field == 0)
Frank Schaefer753aee72014-03-24 16:33:14 -0300536 offset += dev->v4l2->vbi_width * dev->v4l2->vbi_height;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300537
Frank Schaefer36016a32012-12-08 11:31:32 -0300538 memcpy(buf->vb_buf + offset, usb_buf, len);
Frank Schaefer87325332012-12-08 11:31:27 -0300539 buf->pos += len;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300540}
541
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300542static inline void print_err_status(struct em28xx *dev,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300543 int packet, int status)
544{
545 char *errmsg = "Unknown";
546
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300547 switch (status) {
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300548 case -ENOENT:
549 errmsg = "unlinked synchronuously";
550 break;
551 case -ECONNRESET:
552 errmsg = "unlinked asynchronuously";
553 break;
554 case -ENOSR:
555 errmsg = "Buffer error (overrun)";
556 break;
557 case -EPIPE:
558 errmsg = "Stalled (device not responding)";
559 break;
560 case -EOVERFLOW:
561 errmsg = "Babble (bad cable?)";
562 break;
563 case -EPROTO:
564 errmsg = "Bit-stuff error (bad cable?)";
565 break;
566 case -EILSEQ:
567 errmsg = "CRC/Timeout (could be anything)";
568 break;
569 case -ETIME:
570 errmsg = "Device does not respond";
571 break;
572 }
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300573 if (packet < 0) {
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300574 em28xx_isocdbg("URB status %d [%s].\n", status, errmsg);
575 } else {
576 em28xx_isocdbg("URB packet %d, status %d [%s].\n",
577 packet, status, errmsg);
578 }
579}
580
581/*
Frank Schaefer24a6d842012-12-08 11:31:24 -0300582 * get the next available buffer from dma queue
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300583 */
Frank Schaefer24a6d842012-12-08 11:31:24 -0300584static inline struct em28xx_buffer *get_next_buf(struct em28xx *dev,
585 struct em28xx_dmaqueue *dma_q)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300586{
Frank Schaefer24a6d842012-12-08 11:31:24 -0300587 struct em28xx_buffer *buf;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300588
Mauro Carvalho Chehabdbecb442008-04-13 15:08:55 -0300589 if (list_empty(&dma_q->active)) {
590 em28xx_isocdbg("No active queue to serve\n");
Frank Schaefer24a6d842012-12-08 11:31:24 -0300591 return NULL;
Mauro Carvalho Chehabdbecb442008-04-13 15:08:55 -0300592 }
593
Mauro Carvalho Chehabdbecb442008-04-13 15:08:55 -0300594 /* Get the next buffer */
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300595 buf = list_entry(dma_q->active.next, struct em28xx_buffer, list);
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300596 /* Cleans up buffer - Useful for testing for frame/URB loss */
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300597 list_del(&buf->list);
Frank Schaefer87325332012-12-08 11:31:27 -0300598 buf->pos = 0;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300599 buf->vb_buf = buf->mem;
Mauro Carvalho Chehabcb784722008-04-13 15:06:52 -0300600
Frank Schaefer24a6d842012-12-08 11:31:24 -0300601 return buf;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300602}
603
Frank Schaefere04c00d2012-12-08 11:31:30 -0300604/*
605 * Finish the current buffer if completed and prepare for the next field
606 */
607static struct em28xx_buffer *
608finish_field_prepare_next(struct em28xx *dev,
609 struct em28xx_buffer *buf,
610 struct em28xx_dmaqueue *dma_q)
611{
612 if (dev->progressive || dev->top_field) { /* Brand new frame */
613 if (buf != NULL)
614 finish_buffer(dev, buf);
615 buf = get_next_buf(dev, dma_q);
616 }
617 if (buf != NULL) {
618 buf->top_field = dev->top_field;
619 buf->pos = 0;
620 }
621
622 return buf;
623}
624
Frank Schaefer227b7c92012-12-08 11:31:31 -0300625/*
626 * Process data packet according to the em2710/em2750/em28xx frame data format
627 */
628static inline void process_frame_data_em28xx(struct em28xx *dev,
629 unsigned char *data_pkt,
630 unsigned int data_len)
631{
Frank Schaefer753aee72014-03-24 16:33:14 -0300632 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300633 struct em28xx_buffer *buf = dev->usb_ctl.vid_buf;
634 struct em28xx_buffer *vbi_buf = dev->usb_ctl.vbi_buf;
635 struct em28xx_dmaqueue *dma_q = &dev->vidq;
636 struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq;
637
638 /* capture type 0 = vbi start
639 capture type 1 = vbi in progress
640 capture type 2 = video start
641 capture type 3 = video in progress */
642 if (data_len >= 4) {
643 /* NOTE: Headers are always 4 bytes and
644 * never split across packets */
645 if (data_pkt[0] == 0x88 && data_pkt[1] == 0x88 &&
646 data_pkt[2] == 0x88 && data_pkt[3] == 0x88) {
647 /* Continuation */
648 data_pkt += 4;
649 data_len -= 4;
650 } else if (data_pkt[0] == 0x33 && data_pkt[1] == 0x95) {
651 /* Field start (VBI mode) */
652 dev->capture_type = 0;
653 dev->vbi_read = 0;
654 em28xx_isocdbg("VBI START HEADER !!!\n");
655 dev->top_field = !(data_pkt[2] & 1);
656 data_pkt += 4;
657 data_len -= 4;
658 } else if (data_pkt[0] == 0x22 && data_pkt[1] == 0x5a) {
659 /* Field start (VBI disabled) */
660 dev->capture_type = 2;
661 em28xx_isocdbg("VIDEO START HEADER !!!\n");
662 dev->top_field = !(data_pkt[2] & 1);
663 data_pkt += 4;
664 data_len -= 4;
665 }
666 }
667 /* NOTE: With bulk transfers, intermediate data packets
668 * have no continuation header */
669
670 if (dev->capture_type == 0) {
671 vbi_buf = finish_field_prepare_next(dev, vbi_buf, vbi_dma_q);
672 dev->usb_ctl.vbi_buf = vbi_buf;
673 dev->capture_type = 1;
674 }
675
676 if (dev->capture_type == 1) {
Frank Schaefer753aee72014-03-24 16:33:14 -0300677 int vbi_size = v4l2->vbi_width * v4l2->vbi_height;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300678 int vbi_data_len = ((dev->vbi_read + data_len) > vbi_size) ?
679 (vbi_size - dev->vbi_read) : data_len;
680
681 /* Copy VBI data */
682 if (vbi_buf != NULL)
683 em28xx_copy_vbi(dev, vbi_buf, data_pkt, vbi_data_len);
684 dev->vbi_read += vbi_data_len;
685
686 if (vbi_data_len < data_len) {
687 /* Continue with copying video data */
688 dev->capture_type = 2;
689 data_pkt += vbi_data_len;
690 data_len -= vbi_data_len;
691 }
692 }
693
694 if (dev->capture_type == 2) {
695 buf = finish_field_prepare_next(dev, buf, dma_q);
696 dev->usb_ctl.vid_buf = buf;
697 dev->capture_type = 3;
698 }
699
700 if (dev->capture_type == 3 && buf != NULL && data_len > 0)
701 em28xx_copy_video(dev, buf, data_pkt, data_len);
702}
703
Frank Schaefere507e0e2013-03-26 13:38:38 -0300704/*
705 * Process data packet according to the em25xx/em276x/7x/8x frame data format
706 */
707static inline void process_frame_data_em25xx(struct em28xx *dev,
708 unsigned char *data_pkt,
709 unsigned int data_len)
710{
711 struct em28xx_buffer *buf = dev->usb_ctl.vid_buf;
712 struct em28xx_dmaqueue *dmaq = &dev->vidq;
713 bool frame_end = 0;
714
715 /* Check for header */
716 /* NOTE: at least with bulk transfers, only the first packet
717 * has a header and has always set the FRAME_END bit */
718 if (data_len >= 2) { /* em25xx header is only 2 bytes long */
719 if ((data_pkt[0] == EM25XX_FRMDATAHDR_BYTE1) &&
720 ((data_pkt[1] & ~EM25XX_FRMDATAHDR_BYTE2_MASK) == 0x00)) {
721 dev->top_field = !(data_pkt[1] &
722 EM25XX_FRMDATAHDR_BYTE2_FRAME_ID);
723 frame_end = data_pkt[1] &
724 EM25XX_FRMDATAHDR_BYTE2_FRAME_END;
725 data_pkt += 2;
726 data_len -= 2;
727 }
728
729 /* Finish field and prepare next (BULK only) */
730 if (dev->analog_xfer_bulk && frame_end) {
731 buf = finish_field_prepare_next(dev, buf, dmaq);
732 dev->usb_ctl.vid_buf = buf;
733 }
734 /* NOTE: in ISOC mode when a new frame starts and buf==NULL,
735 * we COULD already prepare a buffer here to avoid skipping the
736 * first frame.
737 */
738 }
739
740 /* Copy data */
741 if (buf != NULL && data_len > 0)
742 em28xx_copy_video(dev, buf, data_pkt, data_len);
743
744 /* Finish frame (ISOC only) => avoids lag of 1 frame */
745 if (!dev->analog_xfer_bulk && frame_end) {
746 buf = finish_field_prepare_next(dev, buf, dmaq);
747 dev->usb_ctl.vid_buf = buf;
748 }
749
750 /* NOTE: Tested with USB bulk transfers only !
751 * The wording in the datasheet suggests that isoc might work different.
752 * The current code assumes that with isoc transfers each packet has a
753 * header like with the other em28xx devices.
754 */
755 /* NOTE: Support for interlaced mode is pure theory. It has not been
756 * tested and it is unknown if these devices actually support it. */
757 /* NOTE: No VBI support yet (these chips likely do not support VBI). */
758}
759
Frank Schaefer960da932012-11-25 06:37:37 -0300760/* Processes and copies the URB data content (video and VBI data) */
Frank Schaefer0fa4a402012-11-08 14:11:45 -0300761static inline int em28xx_urb_data_copy(struct em28xx *dev, struct urb *urb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300762{
Frank Schaefer227b7c92012-12-08 11:31:31 -0300763 int xfer_bulk, num_packets, i;
764 unsigned char *usb_data_pkt;
765 unsigned int usb_data_len;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300766
767 if (!dev)
768 return 0;
769
Frank Schaefer2665c292012-12-27 19:02:43 -0300770 if (dev->disconnected)
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300771 return 0;
772
Frank Schaefer1653cb0c2012-11-08 14:11:44 -0300773 if (urb->status < 0)
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300774 print_err_status(dev, -1, urb->status);
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300775
Frank Schaefer4601cc32012-11-08 14:11:46 -0300776 xfer_bulk = usb_pipebulk(urb->pipe);
777
Frank Schaefer4601cc32012-11-08 14:11:46 -0300778 if (xfer_bulk) /* bulk */
779 num_packets = 1;
780 else /* isoc */
781 num_packets = urb->number_of_packets;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300782
Frank Schaefer4601cc32012-11-08 14:11:46 -0300783 for (i = 0; i < num_packets; i++) {
784 if (xfer_bulk) { /* bulk */
Frank Schaefer227b7c92012-12-08 11:31:31 -0300785 usb_data_len = urb->actual_length;
Frank Schaefer4601cc32012-11-08 14:11:46 -0300786
Frank Schaefer227b7c92012-12-08 11:31:31 -0300787 usb_data_pkt = urb->transfer_buffer;
Frank Schaefer4601cc32012-11-08 14:11:46 -0300788 } else { /* isoc */
789 if (urb->iso_frame_desc[i].status < 0) {
790 print_err_status(dev, i,
791 urb->iso_frame_desc[i].status);
792 if (urb->iso_frame_desc[i].status != -EPROTO)
793 continue;
794 }
795
Frank Schaefer227b7c92012-12-08 11:31:31 -0300796 usb_data_len = urb->iso_frame_desc[i].actual_length;
797 if (usb_data_len > dev->max_pkt_size) {
Frank Schaefer4601cc32012-11-08 14:11:46 -0300798 em28xx_isocdbg("packet bigger than packet size");
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300799 continue;
Frank Schaefer4601cc32012-11-08 14:11:46 -0300800 }
801
Frank Schaefer227b7c92012-12-08 11:31:31 -0300802 usb_data_pkt = urb->transfer_buffer +
803 urb->iso_frame_desc[i].offset;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300804 }
805
Frank Schaefer227b7c92012-12-08 11:31:31 -0300806 if (usb_data_len == 0) {
Frank Schaefer4601cc32012-11-08 14:11:46 -0300807 /* NOTE: happens very often with isoc transfers */
808 /* em28xx_usbdbg("packet %d is empty",i); - spammy */
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300809 continue;
810 }
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300811
Frank Schaefere507e0e2013-03-26 13:38:38 -0300812 if (dev->is_em25xx)
813 process_frame_data_em25xx(dev,
814 usb_data_pkt, usb_data_len);
815 else
816 process_frame_data_em28xx(dev,
817 usb_data_pkt, usb_data_len);
818
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300819 }
Frank Schaefer227b7c92012-12-08 11:31:31 -0300820 return 1;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300821}
822
823
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300824static int get_ressource(enum v4l2_buf_type f_type)
825{
826 switch (f_type) {
827 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
828 return EM28XX_RESOURCE_VIDEO;
829 case V4L2_BUF_TYPE_VBI_CAPTURE:
830 return EM28XX_RESOURCE_VBI;
831 default:
832 BUG();
833 return 0;
834 }
835}
836
837/* Usage lock check functions */
838static int res_get(struct em28xx *dev, enum v4l2_buf_type f_type)
839{
840 int res_type = get_ressource(f_type);
841
842 /* is it free? */
843 if (dev->resources & res_type) {
844 /* no, someone else uses it */
845 return -EBUSY;
846 }
847
848 /* it's free, grab it */
849 dev->resources |= res_type;
850 em28xx_videodbg("res: get %d\n", res_type);
851 return 0;
852}
853
854static void res_free(struct em28xx *dev, enum v4l2_buf_type f_type)
855{
856 int res_type = get_ressource(f_type);
857
858 dev->resources &= ~res_type;
859 em28xx_videodbg("res: put %d\n", res_type);
860}
861
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300862/* ------------------------------------------------------------------
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300863 Videobuf2 operations
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300864 ------------------------------------------------------------------*/
865
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300866static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
867 unsigned int *nbuffers, unsigned int *nplanes,
868 unsigned int sizes[], void *alloc_ctxs[])
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300869{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300870 struct em28xx *dev = vb2_get_drv_priv(vq);
Frank Schaefer753aee72014-03-24 16:33:14 -0300871 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300872 unsigned long size;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300873
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300874 if (fmt)
875 size = fmt->fmt.pix.sizeimage;
876 else
Frank Schaefer753aee72014-03-24 16:33:14 -0300877 size =
878 (v4l2->width * v4l2->height * dev->format->depth + 7) >> 3;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -0300879
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300880 if (size == 0)
881 return -EINVAL;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300882
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300883 if (0 == *nbuffers)
884 *nbuffers = 32;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300885
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300886 *nplanes = 1;
887 sizes[0] = size;
Mauro Carvalho Chehabd2d9fbf2008-04-17 21:38:53 -0300888
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300889 return 0;
890}
891
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300892static int
893buffer_prepare(struct vb2_buffer *vb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300894{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300895 struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue);
Frank Schaefer753aee72014-03-24 16:33:14 -0300896 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300897 struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
898 unsigned long size;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300899
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300900 em28xx_videodbg("%s, field=%d\n", __func__, vb->v4l2_buf.field);
Aidan Thornton3b5fa922008-04-13 15:09:36 -0300901
Frank Schaefer753aee72014-03-24 16:33:14 -0300902 size = (v4l2->width * v4l2->height * dev->format->depth + 7) >> 3;
Aidan Thornton3b5fa922008-04-13 15:09:36 -0300903
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300904 if (vb2_plane_size(vb, 0) < size) {
905 em28xx_videodbg("%s data will not fit into plane (%lu < %lu)\n",
906 __func__, vb2_plane_size(vb, 0), size);
907 return -EINVAL;
908 }
909 vb2_set_plane_payload(&buf->vb, 0, size);
910
911 return 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300912}
913
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300914int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300915{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300916 struct em28xx *dev = vb2_get_drv_priv(vq);
917 struct v4l2_frequency f;
918 int rc = 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300919
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300920 em28xx_videodbg("%s\n", __func__);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300921
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300922 /* Make sure streaming is not already in progress for this type
923 of filehandle (e.g. video, vbi) */
924 rc = res_get(dev, vq->type);
925 if (rc)
926 return rc;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300927
Frank Schaefer032f1dd2013-10-10 15:31:53 -0300928 if (dev->streaming_users == 0) {
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300929 /* First active streaming user, so allocate all the URBs */
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300930
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300931 /* Allocate the USB bandwidth */
932 em28xx_set_alternate(dev);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300933
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300934 /* Needed, since GPIO might have disabled power of
935 some i2c device
936 */
937 em28xx_wake_i2c(dev);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300938
Frank Schaefer0455eeb2012-11-25 06:37:34 -0300939 dev->capture_type = -1;
Frank Schaefer960da932012-11-25 06:37:37 -0300940 rc = em28xx_init_usb_xfer(dev, EM28XX_ANALOG_MODE,
941 dev->analog_xfer_bulk,
942 EM28XX_NUM_BUFS,
943 dev->max_pkt_size,
944 dev->packet_multiplier,
945 em28xx_urb_data_copy);
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300946 if (rc < 0)
Frank Schaefer032f1dd2013-10-10 15:31:53 -0300947 return rc;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300948
949 /*
950 * djh: it's not clear whether this code is still needed. I'm
951 * leaving it in here for now entirely out of concern for
952 * backward compatibility (the old code did it)
953 */
954
955 /* Ask tuner to go to analog or radio mode */
956 memset(&f, 0, sizeof(f));
957 f.frequency = dev->ctl_freq;
958 if (vq->owner && vq->owner->vdev->vfl_type == VFL_TYPE_RADIO)
959 f.type = V4L2_TUNER_RADIO;
960 else
961 f.type = V4L2_TUNER_ANALOG_TV;
Frank Schaefer95d26082014-03-24 16:33:09 -0300962 v4l2_device_call_all(&dev->v4l2->v4l2_dev,
963 0, tuner, s_frequency, &f);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300964 }
965
Frank Schaefer032f1dd2013-10-10 15:31:53 -0300966 dev->streaming_users++;
967
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300968 return rc;
969}
970
Hans Verkuile37559b2014-04-17 02:47:21 -0300971static void em28xx_stop_streaming(struct vb2_queue *vq)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300972{
973 struct em28xx *dev = vb2_get_drv_priv(vq);
974 struct em28xx_dmaqueue *vidq = &dev->vidq;
975 unsigned long flags = 0;
976
977 em28xx_videodbg("%s\n", __func__);
978
979 res_free(dev, vq->type);
980
981 if (dev->streaming_users-- == 1) {
982 /* Last active user, so shutdown all the URBS */
983 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
984 }
985
986 spin_lock_irqsave(&dev->slock, flags);
987 while (!list_empty(&vidq->active)) {
988 struct em28xx_buffer *buf;
989 buf = list_entry(vidq->active.next, struct em28xx_buffer, list);
990 list_del(&buf->list);
991 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
992 }
993 dev->usb_ctl.vid_buf = NULL;
994 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300995}
996
Hans Verkuile37559b2014-04-17 02:47:21 -0300997void em28xx_stop_vbi_streaming(struct vb2_queue *vq)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300998{
999 struct em28xx *dev = vb2_get_drv_priv(vq);
1000 struct em28xx_dmaqueue *vbiq = &dev->vbiq;
1001 unsigned long flags = 0;
1002
1003 em28xx_videodbg("%s\n", __func__);
1004
1005 res_free(dev, vq->type);
1006
1007 if (dev->streaming_users-- == 1) {
1008 /* Last active user, so shutdown all the URBS */
1009 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
1010 }
1011
1012 spin_lock_irqsave(&dev->slock, flags);
1013 while (!list_empty(&vbiq->active)) {
1014 struct em28xx_buffer *buf;
1015 buf = list_entry(vbiq->active.next, struct em28xx_buffer, list);
1016 list_del(&buf->list);
1017 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
1018 }
1019 dev->usb_ctl.vbi_buf = NULL;
1020 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001021}
1022
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001023static void
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001024buffer_queue(struct vb2_buffer *vb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001025{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001026 struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue);
1027 struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
1028 struct em28xx_dmaqueue *vidq = &dev->vidq;
1029 unsigned long flags = 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001030
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001031 em28xx_videodbg("%s\n", __func__);
1032 buf->mem = vb2_plane_vaddr(vb, 0);
1033 buf->length = vb2_plane_size(vb, 0);
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001034
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001035 spin_lock_irqsave(&dev->slock, flags);
1036 list_add_tail(&buf->list, &vidq->active);
1037 spin_unlock_irqrestore(&dev->slock, flags);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001038}
1039
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001040static struct vb2_ops em28xx_video_qops = {
1041 .queue_setup = queue_setup,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001042 .buf_prepare = buffer_prepare,
1043 .buf_queue = buffer_queue,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001044 .start_streaming = em28xx_start_analog_streaming,
1045 .stop_streaming = em28xx_stop_streaming,
1046 .wait_prepare = vb2_ops_wait_prepare,
1047 .wait_finish = vb2_ops_wait_finish,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001048};
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001049
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001050static int em28xx_vb2_setup(struct em28xx *dev)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001051{
1052 int rc;
1053 struct vb2_queue *q;
Frank Schaefer27a36df2014-03-24 16:33:13 -03001054 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001055
1056 /* Setup Videobuf2 for Video capture */
Frank Schaefer27a36df2014-03-24 16:33:13 -03001057 q = &v4l2->vb_vidq;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001058 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Mauro Carvalho Chehabef85cd92013-01-06 00:34:22 -02001059 q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
Sakari Ailusade48682014-02-25 19:12:19 -03001060 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001061 q->drv_priv = dev;
1062 q->buf_struct_size = sizeof(struct em28xx_buffer);
1063 q->ops = &em28xx_video_qops;
1064 q->mem_ops = &vb2_vmalloc_memops;
1065
1066 rc = vb2_queue_init(q);
1067 if (rc < 0)
1068 return rc;
1069
1070 /* Setup Videobuf2 for VBI capture */
Frank Schaefer27a36df2014-03-24 16:33:13 -03001071 q = &v4l2->vb_vbiq;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001072 q->type = V4L2_BUF_TYPE_VBI_CAPTURE;
1073 q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR;
Sakari Ailusade48682014-02-25 19:12:19 -03001074 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001075 q->drv_priv = dev;
1076 q->buf_struct_size = sizeof(struct em28xx_buffer);
1077 q->ops = &em28xx_vbi_qops;
1078 q->mem_ops = &vb2_vmalloc_memops;
1079
1080 rc = vb2_queue_init(q);
1081 if (rc < 0)
1082 return rc;
1083
1084 return 0;
1085}
1086
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001087/********************* v4l2 interface **************************************/
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001088
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001089static void video_mux(struct em28xx *dev, int index)
1090{
Frank Schaefer95d26082014-03-24 16:33:09 -03001091 struct v4l2_device *v4l2_dev = &dev->v4l2->v4l2_dev;
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001092 dev->ctl_input = index;
1093 dev->ctl_ainput = INPUT(index)->amux;
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001094 dev->ctl_aoutput = INPUT(index)->aout;
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001095
Mauro Carvalho Chehabe879b8e2008-11-20 13:39:39 -03001096 if (!dev->ctl_aoutput)
1097 dev->ctl_aoutput = EM28XX_AOUT_MASTER;
1098
Frank Schaefer95d26082014-03-24 16:33:09 -03001099 v4l2_device_call_all(v4l2_dev, 0, video, s_routing,
Hans Verkuil5325b422009-04-02 11:26:22 -03001100 INPUT(index)->vmux, 0, 0);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001101
Mauro Carvalho Chehab505b6d02008-11-25 09:39:50 -03001102 if (dev->board.has_msp34xx) {
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001103 if (dev->i2s_speed) {
Frank Schaefer95d26082014-03-24 16:33:09 -03001104 v4l2_device_call_all(v4l2_dev, 0, audio,
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03001105 s_i2s_clock_freq, dev->i2s_speed);
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001106 }
Hans Verkuil2474ed42006-03-19 12:35:57 -03001107 /* Note: this is msp3400 specific */
Frank Schaefer95d26082014-03-24 16:33:09 -03001108 v4l2_device_call_all(v4l2_dev, 0, audio, s_routing,
Hans Verkuil5325b422009-04-02 11:26:22 -03001109 dev->ctl_ainput, MSP_OUTPUT(MSP_SC_IN_DSP_SCART1), 0);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001110 }
Mauro Carvalho Chehab539c96d2008-01-05 09:53:54 -03001111
Vitaly Wool2bd1d9e2009-03-04 08:27:52 -03001112 if (dev->board.adecoder != EM28XX_NOADECODER) {
Frank Schaefer95d26082014-03-24 16:33:09 -03001113 v4l2_device_call_all(v4l2_dev, 0, audio, s_routing,
Hans Verkuil5325b422009-04-02 11:26:22 -03001114 dev->ctl_ainput, dev->ctl_aoutput, 0);
Vitaly Wool2bd1d9e2009-03-04 08:27:52 -03001115 }
1116
Mauro Carvalho Chehab00b87302008-02-06 18:34:13 -03001117 em28xx_audio_analog_set(dev);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001118}
1119
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001120static void em28xx_ctrl_notify(struct v4l2_ctrl *ctrl, void *priv)
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001121{
Hans Verkuil081b9452012-09-07 05:43:59 -03001122 struct em28xx *dev = priv;
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001123
Hans Verkuil081b9452012-09-07 05:43:59 -03001124 /*
1125 * In the case of non-AC97 volume controls, we still need
1126 * to do some setups at em28xx, in order to mute/unmute
1127 * and to adjust audio volume. However, the value ranges
1128 * should be checked by the corresponding V4L subdriver.
1129 */
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001130 switch (ctrl->id) {
1131 case V4L2_CID_AUDIO_MUTE:
Hans Verkuil081b9452012-09-07 05:43:59 -03001132 dev->mute = ctrl->val;
1133 em28xx_audio_analog_set(dev);
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001134 break;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001135 case V4L2_CID_AUDIO_VOLUME:
Hans Verkuil081b9452012-09-07 05:43:59 -03001136 dev->volume = ctrl->val;
1137 em28xx_audio_analog_set(dev);
1138 break;
1139 }
1140}
1141
1142static int em28xx_s_ctrl(struct v4l2_ctrl *ctrl)
1143{
Frank Schaeferabc13082014-03-24 16:33:10 -03001144 struct em28xx_v4l2 *v4l2 =
1145 container_of(ctrl->handler, struct em28xx_v4l2, ctrl_handler);
1146 struct em28xx *dev = v4l2->dev;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001147 int ret = -EINVAL;
Hans Verkuil081b9452012-09-07 05:43:59 -03001148
1149 switch (ctrl->id) {
1150 case V4L2_CID_AUDIO_MUTE:
1151 dev->mute = ctrl->val;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001152 ret = em28xx_audio_analog_set(dev);
Hans Verkuil081b9452012-09-07 05:43:59 -03001153 break;
1154 case V4L2_CID_AUDIO_VOLUME:
1155 dev->volume = ctrl->val;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001156 ret = em28xx_audio_analog_set(dev);
1157 break;
1158 case V4L2_CID_CONTRAST:
1159 ret = em28xx_write_reg(dev, EM28XX_R20_YGAIN, ctrl->val);
1160 break;
1161 case V4L2_CID_BRIGHTNESS:
1162 ret = em28xx_write_reg(dev, EM28XX_R21_YOFFSET, ctrl->val);
1163 break;
1164 case V4L2_CID_SATURATION:
1165 ret = em28xx_write_reg(dev, EM28XX_R22_UVGAIN, ctrl->val);
1166 break;
1167 case V4L2_CID_BLUE_BALANCE:
1168 ret = em28xx_write_reg(dev, EM28XX_R23_UOFFSET, ctrl->val);
1169 break;
1170 case V4L2_CID_RED_BALANCE:
1171 ret = em28xx_write_reg(dev, EM28XX_R24_VOFFSET, ctrl->val);
1172 break;
1173 case V4L2_CID_SHARPNESS:
1174 ret = em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, ctrl->val);
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001175 break;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001176 }
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001177
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001178 return (ret < 0) ? ret : 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001179}
1180
Fengguang Wu8068eb82014-01-07 12:50:47 -03001181static const struct v4l2_ctrl_ops em28xx_ctrl_ops = {
Hans Verkuil081b9452012-09-07 05:43:59 -03001182 .s_ctrl = em28xx_s_ctrl,
1183};
1184
Frank Schaefer6b09a212013-02-10 16:05:12 -03001185static void size_to_scale(struct em28xx *dev,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001186 unsigned int width, unsigned int height,
1187 unsigned int *hscale, unsigned int *vscale)
1188{
Mauro Carvalho Chehab55699962009-07-13 20:15:02 -03001189 unsigned int maxw = norm_maxw(dev);
1190 unsigned int maxh = norm_maxh(dev);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001191
1192 *hscale = (((unsigned long)maxw) << 12) / width - 4096L;
Frank Schaefer81685322013-02-10 16:05:11 -03001193 if (*hscale > EM28XX_HVSCALE_MAX)
1194 *hscale = EM28XX_HVSCALE_MAX;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001195
1196 *vscale = (((unsigned long)maxh) << 12) / height - 4096L;
Frank Schaefer81685322013-02-10 16:05:11 -03001197 if (*vscale > EM28XX_HVSCALE_MAX)
1198 *vscale = EM28XX_HVSCALE_MAX;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001199}
1200
Frank Schaeferb8374132013-02-10 16:05:13 -03001201static void scale_to_size(struct em28xx *dev,
1202 unsigned int hscale, unsigned int vscale,
1203 unsigned int *width, unsigned int *height)
1204{
1205 unsigned int maxw = norm_maxw(dev);
1206 unsigned int maxh = norm_maxh(dev);
1207
1208 *width = (((unsigned long)maxw) << 12) / (hscale + 4096L);
1209 *height = (((unsigned long)maxh) << 12) / (vscale + 4096L);
1210}
1211
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001212/* ------------------------------------------------------------------
1213 IOCTL vidioc handling
1214 ------------------------------------------------------------------*/
1215
Hans Verkuil78b526a2008-05-28 12:16:41 -03001216static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001217 struct v4l2_format *f)
1218{
1219 struct em28xx_fh *fh = priv;
1220 struct em28xx *dev = fh->dev;
Frank Schaefer753aee72014-03-24 16:33:14 -03001221 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001222
Frank Schaefer753aee72014-03-24 16:33:14 -03001223 f->fmt.pix.width = v4l2->width;
1224 f->fmt.pix.height = v4l2->height;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001225 f->fmt.pix.pixelformat = dev->format->fourcc;
Frank Schaefer753aee72014-03-24 16:33:14 -03001226 f->fmt.pix.bytesperline = (v4l2->width * dev->format->depth + 7) >> 3;
1227 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * v4l2->height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001228 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
1229
1230 /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -03001231 if (dev->progressive)
1232 f->fmt.pix.field = V4L2_FIELD_NONE;
1233 else
1234 f->fmt.pix.field = dev->interlaced ?
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001235 V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001236 return 0;
1237}
1238
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001239static struct em28xx_fmt *format_by_fourcc(unsigned int fourcc)
1240{
1241 unsigned int i;
1242
1243 for (i = 0; i < ARRAY_SIZE(format); i++)
1244 if (format[i].fourcc == fourcc)
1245 return &format[i];
1246
1247 return NULL;
1248}
1249
Hans Verkuil78b526a2008-05-28 12:16:41 -03001250static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001251 struct v4l2_format *f)
1252{
1253 struct em28xx_fh *fh = priv;
1254 struct em28xx *dev = fh->dev;
Trent Piephoccb83402009-05-30 21:45:46 -03001255 unsigned int width = f->fmt.pix.width;
1256 unsigned int height = f->fmt.pix.height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001257 unsigned int maxw = norm_maxw(dev);
1258 unsigned int maxh = norm_maxh(dev);
1259 unsigned int hscale, vscale;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001260 struct em28xx_fmt *fmt;
1261
1262 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
1263 if (!fmt) {
1264 em28xx_videodbg("Fourcc format (%08x) invalid.\n",
1265 f->fmt.pix.pixelformat);
1266 return -EINVAL;
1267 }
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001268
Mauro Carvalho Chehab55699962009-07-13 20:15:02 -03001269 if (dev->board.is_em2800) {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001270 /* the em2800 can only scale down to 50% */
Trent Piephoccb83402009-05-30 21:45:46 -03001271 height = height > (3 * maxh / 4) ? maxh : maxh / 2;
1272 width = width > (3 * maxw / 4) ? maxw : maxw / 2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001273 /*
1274 * MaxPacketSize for em2800 is too small to capture at full
1275 * resolution use half of maxw as the scaler can only scale
1276 * to 50%
1277 */
Sascha Sommer1020d132012-01-08 16:54:28 -03001278 if (width == maxw && height == maxh)
1279 width /= 2;
Trent Piephoccb83402009-05-30 21:45:46 -03001280 } else {
1281 /* width must even because of the YUYV format
1282 height must be even because of interlacing */
Devin Heitmuellere3ba4d32009-09-15 00:18:06 -03001283 v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh,
1284 1, 0);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001285 }
1286
Frank Schaefer6b09a212013-02-10 16:05:12 -03001287 size_to_scale(dev, width, height, &hscale, &vscale);
Hans Verkuil46f85972013-03-30 05:31:42 -03001288 scale_to_size(dev, hscale, vscale, &width, &height);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001289
1290 f->fmt.pix.width = width;
1291 f->fmt.pix.height = height;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001292 f->fmt.pix.pixelformat = fmt->fourcc;
Hans Verkuile6066db2013-02-06 08:14:47 -03001293 f->fmt.pix.bytesperline = (width * fmt->depth + 7) >> 3;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001294 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001295 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -03001296 if (dev->progressive)
1297 f->fmt.pix.field = V4L2_FIELD_NONE;
1298 else
1299 f->fmt.pix.field = dev->interlaced ?
1300 V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
Alban Browaeys51dd4d72013-07-16 19:06:46 -03001301 f->fmt.pix.priv = 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001302
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001303 return 0;
1304}
1305
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001306static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc,
1307 unsigned width, unsigned height)
1308{
1309 struct em28xx_fmt *fmt;
Frank Schaefer753aee72014-03-24 16:33:14 -03001310 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001311
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001312 fmt = format_by_fourcc(fourcc);
1313 if (!fmt)
1314 return -EINVAL;
1315
1316 dev->format = fmt;
Frank Schaefer753aee72014-03-24 16:33:14 -03001317 v4l2->width = width;
1318 v4l2->height = height;
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001319
1320 /* set new image size */
Frank Schaefer753aee72014-03-24 16:33:14 -03001321 size_to_scale(dev, v4l2->width, v4l2->height,
1322 &v4l2->hscale, &v4l2->vscale);
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001323
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001324 em28xx_resolution_set(dev);
1325
1326 return 0;
1327}
1328
Hans Verkuil78b526a2008-05-28 12:16:41 -03001329static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001330 struct v4l2_format *f)
1331{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001332 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001333
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001334 if (dev->streaming_users > 0)
1335 return -EBUSY;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001336
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001337 vidioc_try_fmt_vid_cap(file, priv, f);
1338
Hans Verkuil0499a5a2010-09-26 07:34:45 -03001339 return em28xx_set_video_format(dev, f->fmt.pix.pixelformat,
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001340 f->fmt.pix.width, f->fmt.pix.height);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001341}
1342
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001343static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
1344{
1345 struct em28xx_fh *fh = priv;
1346 struct em28xx *dev = fh->dev;
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001347
1348 *norm = dev->norm;
1349
1350 return 0;
1351}
1352
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001353static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm)
1354{
1355 struct em28xx_fh *fh = priv;
1356 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001357
Frank Schaefer95d26082014-03-24 16:33:09 -03001358 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, video, querystd, norm);
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001359
1360 return 0;
1361}
1362
Hans Verkuil314527a2013-03-15 06:10:40 -03001363static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001364{
Frank Schaefer753aee72014-03-24 16:33:14 -03001365 struct em28xx_fh *fh = priv;
1366 struct em28xx *dev = fh->dev;
1367 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001368 struct v4l2_format f;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001369
Hans Verkuil314527a2013-03-15 06:10:40 -03001370 if (norm == dev->norm)
Hans Verkuild8c95c02012-09-07 07:31:54 -03001371 return 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001372
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001373 if (dev->streaming_users > 0)
Hans Verkuild8c95c02012-09-07 07:31:54 -03001374 return -EBUSY;
Hans Verkuild8c95c02012-09-07 07:31:54 -03001375
Hans Verkuil314527a2013-03-15 06:10:40 -03001376 dev->norm = norm;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001377
1378 /* Adjusts width/height, if needed */
Hans Verkuild8c95c02012-09-07 07:31:54 -03001379 f.fmt.pix.width = 720;
Hans Verkuil314527a2013-03-15 06:10:40 -03001380 f.fmt.pix.height = (norm & V4L2_STD_525_60) ? 480 : 576;
Hans Verkuil78b526a2008-05-28 12:16:41 -03001381 vidioc_try_fmt_vid_cap(file, priv, &f);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001382
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001383 /* set new image size */
Frank Schaefer753aee72014-03-24 16:33:14 -03001384 v4l2->width = f.fmt.pix.width;
1385 v4l2->height = f.fmt.pix.height;
1386 size_to_scale(dev, v4l2->width, v4l2->height,
1387 &v4l2->hscale, &v4l2->vscale);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001388
1389 em28xx_resolution_set(dev);
Frank Schaefer753aee72014-03-24 16:33:14 -03001390 v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_std, dev->norm);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001391
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001392 return 0;
1393}
1394
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001395static int vidioc_g_parm(struct file *file, void *priv,
1396 struct v4l2_streamparm *p)
1397{
1398 struct em28xx_fh *fh = priv;
1399 struct em28xx *dev = fh->dev;
1400 int rc = 0;
1401
Hans Verkuil86ff7f12012-09-07 06:16:03 -03001402 p->parm.capture.readbuffers = EM28XX_MIN_BUF;
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001403 if (dev->board.is_webcam)
Frank Schaefer95d26082014-03-24 16:33:09 -03001404 rc = v4l2_device_call_until_err(&dev->v4l2->v4l2_dev, 0,
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001405 video, g_parm, p);
1406 else
1407 v4l2_video_std_frame_period(dev->norm,
1408 &p->parm.capture.timeperframe);
1409
1410 return rc;
1411}
1412
1413static int vidioc_s_parm(struct file *file, void *priv,
1414 struct v4l2_streamparm *p)
1415{
1416 struct em28xx_fh *fh = priv;
1417 struct em28xx *dev = fh->dev;
1418
Hans Verkuil86ff7f12012-09-07 06:16:03 -03001419 p->parm.capture.readbuffers = EM28XX_MIN_BUF;
Frank Schaefer95d26082014-03-24 16:33:09 -03001420 return v4l2_device_call_until_err(&dev->v4l2->v4l2_dev,
1421 0, video, s_parm, p);
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001422}
1423
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001424static const char *iname[] = {
1425 [EM28XX_VMUX_COMPOSITE1] = "Composite1",
1426 [EM28XX_VMUX_COMPOSITE2] = "Composite2",
1427 [EM28XX_VMUX_COMPOSITE3] = "Composite3",
1428 [EM28XX_VMUX_COMPOSITE4] = "Composite4",
1429 [EM28XX_VMUX_SVIDEO] = "S-Video",
1430 [EM28XX_VMUX_TELEVISION] = "Television",
1431 [EM28XX_VMUX_CABLE] = "Cable TV",
1432 [EM28XX_VMUX_DVB] = "DVB",
1433 [EM28XX_VMUX_DEBUG] = "for debug only",
1434};
1435
1436static int vidioc_enum_input(struct file *file, void *priv,
1437 struct v4l2_input *i)
1438{
1439 struct em28xx_fh *fh = priv;
1440 struct em28xx *dev = fh->dev;
1441 unsigned int n;
1442
1443 n = i->index;
1444 if (n >= MAX_EM28XX_INPUT)
1445 return -EINVAL;
1446 if (0 == INPUT(n)->type)
1447 return -EINVAL;
1448
1449 i->index = n;
1450 i->type = V4L2_INPUT_TYPE_CAMERA;
1451
1452 strcpy(i->name, iname[INPUT(n)->type]);
1453
1454 if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type) ||
1455 (EM28XX_VMUX_CABLE == INPUT(n)->type))
1456 i->type = V4L2_INPUT_TYPE_TUNER;
1457
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001458 i->std = dev->v4l2->vdev->tvnorms;
Hans Verkuild8c95c02012-09-07 07:31:54 -03001459 /* webcams do not have the STD API */
1460 if (dev->board.is_webcam)
1461 i->capabilities = 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001462
1463 return 0;
1464}
1465
1466static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1467{
1468 struct em28xx_fh *fh = priv;
1469 struct em28xx *dev = fh->dev;
1470
1471 *i = dev->ctl_input;
1472
1473 return 0;
1474}
1475
1476static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
1477{
1478 struct em28xx_fh *fh = priv;
1479 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001480
1481 if (i >= MAX_EM28XX_INPUT)
1482 return -EINVAL;
1483 if (0 == INPUT(i)->type)
1484 return -EINVAL;
1485
Ezequiel García96371fc2012-03-23 18:09:34 -03001486 video_mux(dev, i);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001487 return 0;
1488}
1489
1490static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
1491{
1492 struct em28xx_fh *fh = priv;
1493 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001494
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001495 switch (a->index) {
1496 case EM28XX_AMUX_VIDEO:
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001497 strcpy(a->name, "Television");
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001498 break;
1499 case EM28XX_AMUX_LINE_IN:
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001500 strcpy(a->name, "Line In");
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001501 break;
1502 case EM28XX_AMUX_VIDEO2:
1503 strcpy(a->name, "Television alt");
1504 break;
1505 case EM28XX_AMUX_PHONE:
1506 strcpy(a->name, "Phone");
1507 break;
1508 case EM28XX_AMUX_MIC:
1509 strcpy(a->name, "Mic");
1510 break;
1511 case EM28XX_AMUX_CD:
1512 strcpy(a->name, "CD");
1513 break;
1514 case EM28XX_AMUX_AUX:
1515 strcpy(a->name, "Aux");
1516 break;
1517 case EM28XX_AMUX_PCM_OUT:
1518 strcpy(a->name, "PCM");
1519 break;
1520 default:
1521 return -EINVAL;
1522 }
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001523
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001524 a->index = dev->ctl_ainput;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001525 a->capability = V4L2_AUDCAP_STEREO;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001526
1527 return 0;
1528}
1529
Hans Verkuil0e8025b92012-09-04 11:59:31 -03001530static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001531{
1532 struct em28xx_fh *fh = priv;
1533 struct em28xx *dev = fh->dev;
1534
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03001535 if (a->index >= MAX_EM28XX_INPUT)
1536 return -EINVAL;
1537 if (0 == INPUT(a->index)->type)
1538 return -EINVAL;
1539
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001540 dev->ctl_ainput = INPUT(a->index)->amux;
1541 dev->ctl_aoutput = INPUT(a->index)->aout;
Mauro Carvalho Chehabe879b8e2008-11-20 13:39:39 -03001542
1543 if (!dev->ctl_aoutput)
1544 dev->ctl_aoutput = EM28XX_AOUT_MASTER;
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001545
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001546 return 0;
1547}
1548
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001549static int vidioc_g_tuner(struct file *file, void *priv,
1550 struct v4l2_tuner *t)
1551{
1552 struct em28xx_fh *fh = priv;
1553 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001554
1555 if (0 != t->index)
1556 return -EINVAL;
1557
1558 strcpy(t->name, "Tuner");
1559
Frank Schaefer95d26082014-03-24 16:33:09 -03001560 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, g_tuner, t);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001561 return 0;
1562}
1563
1564static int vidioc_s_tuner(struct file *file, void *priv,
Hans Verkuil2f73c7c2013-03-15 06:10:06 -03001565 const struct v4l2_tuner *t)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001566{
1567 struct em28xx_fh *fh = priv;
1568 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001569
1570 if (0 != t->index)
1571 return -EINVAL;
1572
Frank Schaefer95d26082014-03-24 16:33:09 -03001573 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, s_tuner, t);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001574 return 0;
1575}
1576
1577static int vidioc_g_frequency(struct file *file, void *priv,
1578 struct v4l2_frequency *f)
1579{
1580 struct em28xx_fh *fh = priv;
1581 struct em28xx *dev = fh->dev;
1582
Hans Verkuil20deebf2012-09-06 10:07:25 -03001583 if (0 != f->tuner)
1584 return -EINVAL;
1585
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001586 f->frequency = dev->ctl_freq;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001587 return 0;
1588}
1589
1590static int vidioc_s_frequency(struct file *file, void *priv,
Hans Verkuilb530a442013-03-19 04:09:26 -03001591 const struct v4l2_frequency *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001592{
Frank Schaefer95d26082014-03-24 16:33:09 -03001593 struct v4l2_frequency new_freq = *f;
1594 struct em28xx_fh *fh = priv;
1595 struct em28xx *dev = fh->dev;
1596 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001597
1598 if (0 != f->tuner)
1599 return -EINVAL;
1600
Frank Schaefer95d26082014-03-24 16:33:09 -03001601 v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, s_frequency, f);
1602 v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, g_frequency, &new_freq);
Hans Verkuilb530a442013-03-19 04:09:26 -03001603 dev->ctl_freq = new_freq.frequency;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001604
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001605 return 0;
1606}
1607
Hans Verkuilcd634f12013-03-27 08:04:23 -03001608#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuil96b03d22013-04-06 06:16:58 -03001609static int vidioc_g_chip_info(struct file *file, void *priv,
1610 struct v4l2_dbg_chip_info *chip)
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001611{
1612 struct em28xx_fh *fh = priv;
1613 struct em28xx *dev = fh->dev;
1614
1615 if (chip->match.addr > 1)
1616 return -EINVAL;
1617 if (chip->match.addr == 1)
1618 strlcpy(chip->name, "ac97", sizeof(chip->name));
1619 else
Frank Schaefer95d26082014-03-24 16:33:09 -03001620 strlcpy(chip->name,
1621 dev->v4l2->v4l2_dev.name, sizeof(chip->name));
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001622 return 0;
1623}
1624
Frank Schaefer35deba32013-02-07 13:39:19 -03001625static int em28xx_reg_len(int reg)
1626{
1627 switch (reg) {
1628 case EM28XX_R40_AC97LSB:
1629 case EM28XX_R30_HSCALELOW:
1630 case EM28XX_R32_VSCALELOW:
1631 return 2;
1632 default:
1633 return 1;
1634 }
1635}
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001636
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001637static int vidioc_g_register(struct file *file, void *priv,
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001638 struct v4l2_dbg_register *reg)
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001639{
1640 struct em28xx_fh *fh = priv;
1641 struct em28xx *dev = fh->dev;
1642 int ret;
1643
Hans Verkuilabca2052013-05-29 06:59:35 -03001644 if (reg->match.addr > 1)
1645 return -EINVAL;
1646 if (reg->match.addr) {
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001647 ret = em28xx_read_ac97(dev, reg->reg);
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001648 if (ret < 0)
1649 return ret;
1650
1651 reg->val = ret;
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001652 reg->size = 1;
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001653 return 0;
1654 }
1655
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001656 /* Match host */
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001657 reg->size = em28xx_reg_len(reg->reg);
1658 if (reg->size == 1) {
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001659 ret = em28xx_read_reg(dev, reg->reg);
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001660
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001661 if (ret < 0)
1662 return ret;
1663
1664 reg->val = ret;
1665 } else {
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001666 __le16 val = 0;
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001667 ret = dev->em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001668 reg->reg, (char *)&val, 2);
1669 if (ret < 0)
1670 return ret;
1671
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001672 reg->val = le16_to_cpu(val);
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001673 }
1674
1675 return 0;
1676}
1677
1678static int vidioc_s_register(struct file *file, void *priv,
Hans Verkuil977ba3b2013-03-24 08:28:46 -03001679 const struct v4l2_dbg_register *reg)
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001680{
1681 struct em28xx_fh *fh = priv;
1682 struct em28xx *dev = fh->dev;
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001683 __le16 buf;
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001684
Hans Verkuilabca2052013-05-29 06:59:35 -03001685 if (reg->match.addr > 1)
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001686 return -EINVAL;
Hans Verkuilabca2052013-05-29 06:59:35 -03001687 if (reg->match.addr)
1688 return em28xx_write_ac97(dev, reg->reg, reg->val);
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001689
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001690 /* Match host */
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001691 buf = cpu_to_le16(reg->val);
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001692
Hans Verkuil0499a5a2010-09-26 07:34:45 -03001693 return em28xx_write_regs(dev, reg->reg, (char *)&buf,
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001694 em28xx_reg_len(reg->reg));
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001695}
1696#endif
1697
1698
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001699static int vidioc_querycap(struct file *file, void *priv,
1700 struct v4l2_capability *cap)
1701{
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001702 struct video_device *vdev = video_devdata(file);
1703 struct em28xx_fh *fh = priv;
1704 struct em28xx *dev = fh->dev;
1705 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001706
1707 strlcpy(cap->driver, "em28xx", sizeof(cap->driver));
1708 strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card));
Thierry MERLEcb977162009-01-20 18:01:33 -03001709 usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001710
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001711 if (vdev->vfl_type == VFL_TYPE_GRABBER)
1712 cap->device_caps = V4L2_CAP_READWRITE |
1713 V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1714 else if (vdev->vfl_type == VFL_TYPE_RADIO)
1715 cap->device_caps = V4L2_CAP_RADIO;
1716 else
Hans Verkuil1d179ee2012-09-07 08:45:10 -03001717 cap->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE;
Devin Heitmueller04146142009-09-11 00:08:44 -03001718
Mauro Carvalho Chehab6c428b52009-08-04 19:52:37 -03001719 if (dev->audio_mode.has_audio)
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001720 cap->device_caps |= V4L2_CAP_AUDIO;
Mauro Carvalho Chehab6c428b52009-08-04 19:52:37 -03001721
Mauro Carvalho Chehabed086312008-01-24 06:59:20 -03001722 if (dev->tuner_type != TUNER_ABSENT)
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001723 cap->device_caps |= V4L2_CAP_TUNER;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001724
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001725 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS |
1726 V4L2_CAP_READWRITE | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001727 if (v4l2->vbi_dev)
Hans Verkuil1d179ee2012-09-07 08:45:10 -03001728 cap->capabilities |= V4L2_CAP_VBI_CAPTURE;
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001729 if (v4l2->radio_dev)
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001730 cap->capabilities |= V4L2_CAP_RADIO;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001731 return 0;
1732}
1733
Hans Verkuil78b526a2008-05-28 12:16:41 -03001734static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001735 struct v4l2_fmtdesc *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001736{
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001737 if (unlikely(f->index >= ARRAY_SIZE(format)))
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001738 return -EINVAL;
1739
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001740 strlcpy(f->description, format[f->index].name, sizeof(f->description));
1741 f->pixelformat = format[f->index].fourcc;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001742
1743 return 0;
1744}
1745
Mauro Carvalho Chehab1c5c50682011-10-16 13:52:43 -02001746static int vidioc_enum_framesizes(struct file *file, void *priv,
1747 struct v4l2_frmsizeenum *fsize)
1748{
1749 struct em28xx_fh *fh = priv;
1750 struct em28xx *dev = fh->dev;
1751 struct em28xx_fmt *fmt;
1752 unsigned int maxw = norm_maxw(dev);
1753 unsigned int maxh = norm_maxh(dev);
1754
1755 fmt = format_by_fourcc(fsize->pixel_format);
1756 if (!fmt) {
1757 em28xx_videodbg("Fourcc format (%08x) invalid.\n",
1758 fsize->pixel_format);
1759 return -EINVAL;
1760 }
1761
1762 if (dev->board.is_em2800) {
1763 if (fsize->index > 1)
1764 return -EINVAL;
1765 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
1766 fsize->discrete.width = maxw / (1 + fsize->index);
1767 fsize->discrete.height = maxh / (1 + fsize->index);
1768 return 0;
1769 }
1770
1771 if (fsize->index != 0)
1772 return -EINVAL;
1773
1774 /* Report a continuous range */
1775 fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
Frank Schaefer6c3598e2013-02-10 16:05:14 -03001776 scale_to_size(dev, EM28XX_HVSCALE_MAX, EM28XX_HVSCALE_MAX,
1777 &fsize->stepwise.min_width, &fsize->stepwise.min_height);
1778 if (fsize->stepwise.min_width < 48)
1779 fsize->stepwise.min_width = 48;
1780 if (fsize->stepwise.min_height < 38)
1781 fsize->stepwise.min_height = 38;
Mauro Carvalho Chehab1c5c50682011-10-16 13:52:43 -02001782 fsize->stepwise.max_width = maxw;
1783 fsize->stepwise.max_height = maxh;
1784 fsize->stepwise.step_width = 1;
1785 fsize->stepwise.step_height = 1;
1786 return 0;
1787}
1788
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001789/* RAW VBI ioctls */
1790
1791static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
1792 struct v4l2_format *format)
1793{
Frank Schaefer753aee72014-03-24 16:33:14 -03001794 struct em28xx_fh *fh = priv;
1795 struct em28xx *dev = fh->dev;
1796 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001797
Frank Schaefer753aee72014-03-24 16:33:14 -03001798 format->fmt.vbi.samples_per_line = v4l2->vbi_width;
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001799 format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
1800 format->fmt.vbi.offset = 0;
1801 format->fmt.vbi.flags = 0;
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001802 format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
Frank Schaefer753aee72014-03-24 16:33:14 -03001803 format->fmt.vbi.count[0] = v4l2->vbi_height;
1804 format->fmt.vbi.count[1] = v4l2->vbi_height;
Hans Verkuil2a221d32012-09-07 08:51:32 -03001805 memset(format->fmt.vbi.reserved, 0, sizeof(format->fmt.vbi.reserved));
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001806
1807 /* Varies by video standard (NTSC, PAL, etc.) */
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001808 if (dev->norm & V4L2_STD_525_60) {
1809 /* NTSC */
1810 format->fmt.vbi.start[0] = 10;
1811 format->fmt.vbi.start[1] = 273;
1812 } else if (dev->norm & V4L2_STD_625_50) {
1813 /* PAL */
1814 format->fmt.vbi.start[0] = 6;
1815 format->fmt.vbi.start[1] = 318;
1816 }
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001817
1818 return 0;
1819}
1820
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001821/* ----------------------------------------------------------- */
1822/* RADIO ESPECIFIC IOCTLS */
1823/* ----------------------------------------------------------- */
1824
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001825static int radio_g_tuner(struct file *file, void *priv,
1826 struct v4l2_tuner *t)
1827{
1828 struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;
1829
1830 if (unlikely(t->index > 0))
1831 return -EINVAL;
1832
1833 strcpy(t->name, "Radio");
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001834
Frank Schaefer95d26082014-03-24 16:33:09 -03001835 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, g_tuner, t);
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001836
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001837 return 0;
1838}
1839
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001840static int radio_s_tuner(struct file *file, void *priv,
Hans Verkuil2f73c7c2013-03-15 06:10:06 -03001841 const struct v4l2_tuner *t)
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001842{
1843 struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;
1844
1845 if (0 != t->index)
1846 return -EINVAL;
1847
Frank Schaefer95d26082014-03-24 16:33:09 -03001848 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, s_tuner, t);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001849
1850 return 0;
1851}
1852
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001853/*
Frank Schaefer95d26082014-03-24 16:33:09 -03001854 * em28xx_free_v4l2() - Free struct em28xx_v4l2
1855 *
1856 * @ref: struct kref for struct em28xx_v4l2
1857 *
1858 * Called when all users of struct em28xx_v4l2 are gone
1859 */
1860void em28xx_free_v4l2(struct kref *ref)
1861{
1862 struct em28xx_v4l2 *v4l2 = container_of(ref, struct em28xx_v4l2, ref);
1863
Frank Schaeferabc13082014-03-24 16:33:10 -03001864 v4l2->dev->v4l2 = NULL;
Frank Schaefer95d26082014-03-24 16:33:09 -03001865 kfree(v4l2);
1866}
1867
1868/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08001869 * em28xx_v4l2_open()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001870 * inits the device and starts isoc transfer
1871 */
Hans Verkuilbec43662008-12-30 06:58:20 -03001872static int em28xx_v4l2_open(struct file *filp)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001873{
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001874 struct video_device *vdev = video_devdata(filp);
1875 struct em28xx *dev = video_drvdata(filp);
Frank Schaefer95d26082014-03-24 16:33:09 -03001876 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001877 enum v4l2_buf_type fh_type = 0;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001878 struct em28xx_fh *fh;
Markus Rechberger9c755412005-11-08 21:37:52 -08001879
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001880 switch (vdev->vfl_type) {
1881 case VFL_TYPE_GRABBER:
1882 fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1883 break;
1884 case VFL_TYPE_VBI:
1885 fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
1886 break;
Frank Schaefer4e170242014-01-12 13:24:18 -03001887 case VFL_TYPE_RADIO:
1888 break;
1889 default:
1890 return -EINVAL;
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001891 }
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03001892
Laurent Pinchart50462eb2009-12-10 11:47:13 -02001893 em28xx_videodbg("open dev=%s type=%s users=%d\n",
1894 video_device_node_name(vdev), v4l2_type_names[fh_type],
1895 dev->users);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001896
Hans Verkuil876cb142012-06-23 08:12:47 -03001897 if (mutex_lock_interruptible(&dev->lock))
1898 return -ERESTARTSYS;
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001899 fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001900 if (!fh) {
1901 em28xx_errdev("em28xx-video.c: Out of memory?!\n");
Hans Verkuil876cb142012-06-23 08:12:47 -03001902 mutex_unlock(&dev->lock);
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001903 return -ENOMEM;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001904 }
Hans Verkuil69a61642012-09-07 05:52:40 -03001905 v4l2_fh_init(&fh->fh, vdev);
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001906 fh->dev = dev;
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001907 fh->type = fh_type;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001908 filp->private_data = fh;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001909
Frank Schaefer4e170242014-01-12 13:24:18 -03001910 if (dev->users == 0) {
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001911 em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001912
Frank Schaefer4e170242014-01-12 13:24:18 -03001913 if (vdev->vfl_type != VFL_TYPE_RADIO)
1914 em28xx_resolution_set(dev);
1915
1916 /*
1917 * Needed, since GPIO might have disabled power
1918 * of some i2c devices
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001919 */
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03001920 em28xx_wake_i2c(dev);
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02001921 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001922
1923 if (vdev->vfl_type == VFL_TYPE_RADIO) {
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001924 em28xx_videodbg("video_open: setting radio device\n");
Frank Schaefer95d26082014-03-24 16:33:09 -03001925 v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, s_radio);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001926 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001927
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03001928 kref_get(&dev->ref);
Frank Schaefer95d26082014-03-24 16:33:09 -03001929 kref_get(&v4l2->ref);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001930 dev->users++;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001931
Hans Verkuil876cb142012-06-23 08:12:47 -03001932 mutex_unlock(&dev->lock);
Hans Verkuil69a61642012-09-07 05:52:40 -03001933 v4l2_fh_add(&fh->fh);
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001934
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001935 return 0;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001936}
1937
1938/*
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001939 * em28xx_v4l2_fini()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001940 * unregisters the v4l2,i2c and usb devices
1941 * called when the device gets disconected or at module unload
1942*/
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001943static int em28xx_v4l2_fini(struct em28xx *dev)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001944{
Frank Schaefer95d26082014-03-24 16:33:09 -03001945 struct em28xx_v4l2 *v4l2 = dev->v4l2;
1946
Mauro Carvalho Chehab822b8de2014-01-06 05:27:47 -03001947 if (dev->is_audio_only) {
1948 /* Shouldn't initialize IR for this interface */
1949 return 0;
1950 }
1951
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001952 if (!dev->has_video) {
1953 /* This device does not support the v4l2 extension */
1954 return 0;
1955 }
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02001956
Frank Schaefer95d26082014-03-24 16:33:09 -03001957 if (v4l2 == NULL)
1958 return 0;
1959
Mauro Carvalho Chehabaa929ad2014-01-12 19:22:07 -03001960 em28xx_info("Closing video extension");
1961
Mauro Carvalho Chehabebbfbc22014-01-13 02:53:44 -03001962 mutex_lock(&dev->lock);
1963
Frank Schaefer95d26082014-03-24 16:33:09 -03001964 v4l2_device_disconnect(&v4l2->v4l2_dev);
Frank Schaefer5ad10de2014-01-12 13:24:21 -03001965
Frank Schaefer23e86422014-01-12 13:24:20 -03001966 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
1967
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001968 if (v4l2->radio_dev) {
Frank Schaefere8470222014-01-12 13:24:25 -03001969 em28xx_info("V4L2 device %s deregistered\n",
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001970 video_device_node_name(v4l2->radio_dev));
1971 video_unregister_device(v4l2->radio_dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001972 }
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001973 if (v4l2->vbi_dev) {
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001974 em28xx_info("V4L2 device %s deregistered\n",
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001975 video_device_node_name(v4l2->vbi_dev));
1976 video_unregister_device(v4l2->vbi_dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001977 }
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001978 if (v4l2->vdev) {
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001979 em28xx_info("V4L2 device %s deregistered\n",
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001980 video_device_node_name(v4l2->vdev));
1981 video_unregister_device(v4l2->vdev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001982 }
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001983
Frank Schaeferabc13082014-03-24 16:33:10 -03001984 v4l2_ctrl_handler_free(&v4l2->ctrl_handler);
Frank Schaefer95d26082014-03-24 16:33:09 -03001985 v4l2_device_unregister(&v4l2->v4l2_dev);
Frank Schaefer103f18a2014-01-17 14:45:30 -03001986
Frank Schaefer2c52a2f2014-03-24 16:33:11 -03001987 if (v4l2->clk) {
1988 v4l2_clk_unregister_fixed(v4l2->clk);
1989 v4l2->clk = NULL;
Frank Schaefer25dd1652014-01-12 13:24:23 -03001990 }
1991
Frank Schaefer95d26082014-03-24 16:33:09 -03001992 kref_put(&v4l2->ref, em28xx_free_v4l2);
1993
Mauro Carvalho Chehabebbfbc22014-01-13 02:53:44 -03001994 mutex_unlock(&dev->lock);
Frank Schaefer95d26082014-03-24 16:33:09 -03001995
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03001996 kref_put(&dev->ref, em28xx_free_device);
Frank Schaefer5ad10de2014-01-12 13:24:21 -03001997
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001998 return 0;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001999}
2000
Shuah Khana61f6812014-02-21 21:50:17 -03002001static int em28xx_v4l2_suspend(struct em28xx *dev)
2002{
2003 if (dev->is_audio_only)
2004 return 0;
2005
2006 if (!dev->has_video)
2007 return 0;
2008
2009 em28xx_info("Suspending video extension");
2010 em28xx_stop_urbs(dev);
2011 return 0;
2012}
2013
2014static int em28xx_v4l2_resume(struct em28xx *dev)
2015{
2016 if (dev->is_audio_only)
2017 return 0;
2018
2019 if (!dev->has_video)
2020 return 0;
2021
2022 em28xx_info("Resuming video extension");
2023 /* what do we do here */
2024 return 0;
2025}
2026
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002027/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002028 * em28xx_v4l2_close()
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03002029 * stops streaming and deallocates all resources allocated by the v4l2
2030 * calls and ioctls
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002031 */
Hans Verkuilbec43662008-12-30 06:58:20 -03002032static int em28xx_v4l2_close(struct file *filp)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002033{
Frank Schaefer95d26082014-03-24 16:33:09 -03002034 struct em28xx_fh *fh = filp->private_data;
2035 struct em28xx *dev = fh->dev;
2036 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03002037 int errCode;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002038
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08002039 em28xx_videodbg("users=%d\n", dev->users);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002040
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002041 vb2_fop_release(filp);
Ricardo Ribalda98c24dcd2013-11-06 05:39:35 -03002042 mutex_lock(&dev->lock);
Devin Heitmueller8c873d32009-09-03 00:23:27 -03002043
Devin Heitmuellere3ba4d32009-09-15 00:18:06 -03002044 if (dev->users == 1) {
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002045 /* No sense to try to write to the device */
2046 if (dev->disconnected)
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002047 goto exit;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03002048
Mauro Carvalho Chehabeb6c9632008-12-05 10:39:12 -03002049 /* Save some power by putting tuner to sleep */
Frank Schaefer95d26082014-03-24 16:33:09 -03002050 v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_power, 0);
Mauro Carvalho Chehabeb6c9632008-12-05 10:39:12 -03002051
Aidan Thorntond7aa8022008-04-13 14:38:47 -03002052 /* do this before setting alternate! */
Mauro Carvalho Chehab2fe3e2e2008-11-27 09:10:40 -03002053 em28xx_set_mode(dev, EM28XX_SUSPEND);
Aidan Thorntond7aa8022008-04-13 14:38:47 -03002054
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03002055 /* set alternate 0 */
2056 dev->alt = 0;
2057 em28xx_videodbg("setting alternate 0\n");
2058 errCode = usb_set_interface(dev->udev, 0, 0);
2059 if (errCode < 0) {
2060 em28xx_errdev("cannot change alternate number to "
2061 "0 (error=%i)\n", errCode);
2062 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002063 }
Devin Heitmueller28abf0832009-09-01 01:54:54 -03002064
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002065exit:
Frank Schaefer95d26082014-03-24 16:33:09 -03002066 kref_put(&v4l2->ref, em28xx_free_v4l2);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002067 dev->users--;
Hans Verkuil876cb142012-06-23 08:12:47 -03002068 mutex_unlock(&dev->lock);
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002069 kref_put(&dev->ref, em28xx_free_device);
2070
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002071 return 0;
2072}
2073
Hans Verkuilbec43662008-12-30 06:58:20 -03002074static const struct v4l2_file_operations em28xx_v4l_fops = {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002075 .owner = THIS_MODULE,
2076 .open = em28xx_v4l2_open,
2077 .release = em28xx_v4l2_close,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002078 .read = vb2_fop_read,
2079 .poll = vb2_fop_poll,
2080 .mmap = vb2_fop_mmap,
Hans Verkuil0499a5a2010-09-26 07:34:45 -03002081 .unlocked_ioctl = video_ioctl2,
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002082};
2083
Hans Verkuila3998102008-07-21 02:57:38 -03002084static const struct v4l2_ioctl_ops video_ioctl_ops = {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002085 .vidioc_querycap = vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03002086 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
2087 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
2088 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
2089 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Devin Heitmueller28abf0832009-09-01 01:54:54 -03002090 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Hans Verkuil2a221d32012-09-07 08:51:32 -03002091 .vidioc_try_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Frank Schaeferaab34612013-02-07 13:39:16 -03002092 .vidioc_s_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Mauro Carvalho Chehab1c5c50682011-10-16 13:52:43 -02002093 .vidioc_enum_framesizes = vidioc_enum_framesizes,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002094 .vidioc_g_audio = vidioc_g_audio,
2095 .vidioc_s_audio = vidioc_s_audio,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002096
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002097 .vidioc_reqbufs = vb2_ioctl_reqbufs,
2098 .vidioc_create_bufs = vb2_ioctl_create_bufs,
2099 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
2100 .vidioc_querybuf = vb2_ioctl_querybuf,
2101 .vidioc_qbuf = vb2_ioctl_qbuf,
2102 .vidioc_dqbuf = vb2_ioctl_dqbuf,
2103
Devin Heitmueller19bf0032009-09-11 00:40:18 -03002104 .vidioc_g_std = vidioc_g_std,
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03002105 .vidioc_querystd = vidioc_querystd,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002106 .vidioc_s_std = vidioc_s_std,
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03002107 .vidioc_g_parm = vidioc_g_parm,
2108 .vidioc_s_parm = vidioc_s_parm,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002109 .vidioc_enum_input = vidioc_enum_input,
2110 .vidioc_g_input = vidioc_g_input,
2111 .vidioc_s_input = vidioc_s_input,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002112 .vidioc_streamon = vb2_ioctl_streamon,
2113 .vidioc_streamoff = vb2_ioctl_streamoff,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002114 .vidioc_g_tuner = vidioc_g_tuner,
2115 .vidioc_s_tuner = vidioc_s_tuner,
2116 .vidioc_g_frequency = vidioc_g_frequency,
2117 .vidioc_s_frequency = vidioc_s_frequency,
Hans Verkuil50fdf402012-09-07 06:10:12 -03002118 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
2119 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002120#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuil96b03d22013-04-06 06:16:58 -03002121 .vidioc_g_chip_info = vidioc_g_chip_info,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002122 .vidioc_g_register = vidioc_g_register,
2123 .vidioc_s_register = vidioc_s_register,
2124#endif
Hans Verkuila3998102008-07-21 02:57:38 -03002125};
2126
2127static const struct video_device em28xx_video_template = {
Frank Schaefere8470222014-01-12 13:24:25 -03002128 .fops = &em28xx_v4l_fops,
2129 .ioctl_ops = &video_ioctl_ops,
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002130 .release = video_device_release,
Frank Schaefere8470222014-01-12 13:24:25 -03002131 .tvnorms = V4L2_STD_ALL,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002132};
2133
Hans Verkuilbec43662008-12-30 06:58:20 -03002134static const struct v4l2_file_operations radio_fops = {
Hans Verkuila3998102008-07-21 02:57:38 -03002135 .owner = THIS_MODULE,
2136 .open = em28xx_v4l2_open,
2137 .release = em28xx_v4l2_close,
Hans Verkuil8fd0bda2010-12-18 09:59:51 -03002138 .unlocked_ioctl = video_ioctl2,
Hans Verkuila3998102008-07-21 02:57:38 -03002139};
2140
2141static const struct v4l2_ioctl_ops radio_ioctl_ops = {
Hans Verkuila9d79fe2012-09-06 07:31:04 -03002142 .vidioc_querycap = vidioc_querycap,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002143 .vidioc_g_tuner = radio_g_tuner,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002144 .vidioc_s_tuner = radio_s_tuner,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002145 .vidioc_g_frequency = vidioc_g_frequency,
2146 .vidioc_s_frequency = vidioc_s_frequency,
Hans Verkuil50fdf402012-09-07 06:10:12 -03002147 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
2148 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002149#ifdef CONFIG_VIDEO_ADV_DEBUG
Michal Marek430c73f2013-04-16 08:06:30 -03002150 .vidioc_g_chip_info = vidioc_g_chip_info,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002151 .vidioc_g_register = vidioc_g_register,
2152 .vidioc_s_register = vidioc_s_register,
2153#endif
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002154};
2155
Hans Verkuila3998102008-07-21 02:57:38 -03002156static struct video_device em28xx_radio_template = {
Frank Schaefere8470222014-01-12 13:24:25 -03002157 .fops = &radio_fops,
2158 .ioctl_ops = &radio_ioctl_ops,
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002159 .release = video_device_release,
Hans Verkuila3998102008-07-21 02:57:38 -03002160};
2161
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002162/* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */
2163static unsigned short saa711x_addrs[] = {
2164 0x4a >> 1, 0x48 >> 1, /* SAA7111, SAA7111A and SAA7113 */
2165 0x42 >> 1, 0x40 >> 1, /* SAA7114, SAA7115 and SAA7118 */
2166 I2C_CLIENT_END };
2167
2168static unsigned short tvp5150_addrs[] = {
2169 0xb8 >> 1,
2170 0xba >> 1,
2171 I2C_CLIENT_END
2172};
2173
2174static unsigned short msp3400_addrs[] = {
2175 0x80 >> 1,
2176 0x88 >> 1,
2177 I2C_CLIENT_END
2178};
2179
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03002180/******************************** usb interface ******************************/
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002181
Adrian Bunk532fe652008-01-28 22:10:48 -03002182static struct video_device *em28xx_vdev_init(struct em28xx *dev,
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -03002183 const struct video_device *template,
2184 const char *type_name)
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002185{
2186 struct video_device *vfd;
2187
2188 vfd = video_device_alloc();
2189 if (NULL == vfd)
2190 return NULL;
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03002191
2192 *vfd = *template;
Frank Schaefer95d26082014-03-24 16:33:09 -03002193 vfd->v4l2_dev = &dev->v4l2->v4l2_dev;
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03002194 vfd->debug = video_debug;
Hans Verkuil0499a5a2010-09-26 07:34:45 -03002195 vfd->lock = &dev->lock;
Hans Verkuil69a61642012-09-07 05:52:40 -03002196 set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
Hans Verkuild8c95c02012-09-07 07:31:54 -03002197 if (dev->board.is_webcam)
2198 vfd->tvnorms = 0;
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002199
2200 snprintf(vfd->name, sizeof(vfd->name), "%s %s",
2201 dev->name, type_name);
2202
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02002203 video_set_drvdata(vfd, dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002204 return vfd;
2205}
2206
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002207static void em28xx_tuner_setup(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002208{
Frank Schaefer95d26082014-03-24 16:33:09 -03002209 struct v4l2_device *v4l2_dev = &dev->v4l2->v4l2_dev;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002210 struct tuner_setup tun_setup;
2211 struct v4l2_frequency f;
2212
2213 if (dev->tuner_type == TUNER_ABSENT)
2214 return;
2215
2216 memset(&tun_setup, 0, sizeof(tun_setup));
2217
2218 tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
2219 tun_setup.tuner_callback = em28xx_tuner_callback;
2220
2221 if (dev->board.radio.type) {
2222 tun_setup.type = dev->board.radio.type;
2223 tun_setup.addr = dev->board.radio_addr;
2224
Frank Schaefer95d26082014-03-24 16:33:09 -03002225 v4l2_device_call_all(v4l2_dev,
2226 0, tuner, s_type_addr, &tun_setup);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002227 }
2228
2229 if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type)) {
2230 tun_setup.type = dev->tuner_type;
2231 tun_setup.addr = dev->tuner_addr;
2232
Frank Schaefer95d26082014-03-24 16:33:09 -03002233 v4l2_device_call_all(v4l2_dev,
2234 0, tuner, s_type_addr, &tun_setup);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002235 }
2236
2237 if (dev->tda9887_conf) {
2238 struct v4l2_priv_tun_config tda9887_cfg;
2239
2240 tda9887_cfg.tuner = TUNER_TDA9887;
2241 tda9887_cfg.priv = &dev->tda9887_conf;
2242
Frank Schaefer95d26082014-03-24 16:33:09 -03002243 v4l2_device_call_all(v4l2_dev,
2244 0, tuner, s_config, &tda9887_cfg);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002245 }
2246
2247 if (dev->tuner_type == TUNER_XC2028) {
2248 struct v4l2_priv_tun_config xc2028_cfg;
2249 struct xc2028_ctrl ctl;
2250
2251 memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
2252 memset(&ctl, 0, sizeof(ctl));
2253
2254 em28xx_setup_xc3028(dev, &ctl);
2255
2256 xc2028_cfg.tuner = TUNER_XC2028;
2257 xc2028_cfg.priv = &ctl;
2258
Frank Schaefer95d26082014-03-24 16:33:09 -03002259 v4l2_device_call_all(v4l2_dev, 0, tuner, s_config, &xc2028_cfg);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002260 }
2261
2262 /* configure tuner */
2263 f.tuner = 0;
2264 f.type = V4L2_TUNER_ANALOG_TV;
2265 f.frequency = 9076; /* just a magic number */
2266 dev->ctl_freq = f.frequency;
Frank Schaefer95d26082014-03-24 16:33:09 -03002267 v4l2_device_call_all(v4l2_dev, 0, tuner, s_frequency, &f);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002268}
2269
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002270static int em28xx_v4l2_init(struct em28xx *dev)
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002271{
Hans Verkuil081b9452012-09-07 05:43:59 -03002272 u8 val;
Mauro Carvalho Chehab2e5ef2d2008-12-28 22:26:36 -03002273 int ret;
Sascha Sommer1020d132012-01-08 16:54:28 -03002274 unsigned int maxw;
Frank Schaeferabc13082014-03-24 16:33:10 -03002275 struct v4l2_ctrl_handler *hdl;
Frank Schaefer95d26082014-03-24 16:33:09 -03002276 struct em28xx_v4l2 *v4l2;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002277
Mauro Carvalho Chehab822b8de2014-01-06 05:27:47 -03002278 if (dev->is_audio_only) {
2279 /* Shouldn't initialize IR for this interface */
2280 return 0;
2281 }
2282
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002283 if (!dev->has_video) {
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002284 /* This device does not support the v4l2 extension */
2285 return 0;
2286 }
Mauro Carvalho Chehab2e5ef2d2008-12-28 22:26:36 -03002287
Mauro Carvalho Chehab96346142013-12-26 12:41:03 -03002288 em28xx_info("Registering V4L2 extension\n");
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002289
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002290 mutex_lock(&dev->lock);
2291
Frank Schaefer95d26082014-03-24 16:33:09 -03002292 v4l2 = kzalloc(sizeof(struct em28xx_v4l2), GFP_KERNEL);
2293 if (v4l2 == NULL) {
2294 em28xx_info("em28xx_v4l: memory allocation failed\n");
2295 mutex_unlock(&dev->lock);
2296 return -ENOMEM;
2297 }
2298 kref_init(&v4l2->ref);
Frank Schaeferabc13082014-03-24 16:33:10 -03002299 v4l2->dev = dev;
Frank Schaefer95d26082014-03-24 16:33:09 -03002300 dev->v4l2 = v4l2;
2301
2302 ret = v4l2_device_register(&dev->udev->dev, &v4l2->v4l2_dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002303 if (ret < 0) {
2304 em28xx_errdev("Call to v4l2_device_register() failed!\n");
2305 goto err;
2306 }
2307
Frank Schaeferabc13082014-03-24 16:33:10 -03002308 hdl = &v4l2->ctrl_handler;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002309 v4l2_ctrl_handler_init(hdl, 8);
Frank Schaefer95d26082014-03-24 16:33:09 -03002310 v4l2->v4l2_dev.ctrl_handler = hdl;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002311
2312 /*
2313 * Default format, used for tvp5150 or saa711x output formats
2314 */
2315 dev->vinmode = 0x10;
2316 dev->vinctl = EM28XX_VINCTRL_INTERLACED |
2317 EM28XX_VINCTRL_CCIR656_ENABLE;
2318
2319 /* request some modules */
2320
2321 if (dev->board.has_msp34xx)
Frank Schaefer95d26082014-03-24 16:33:09 -03002322 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2323 &dev->i2c_adap[dev->def_i2c_bus],
2324 "msp3400", 0, msp3400_addrs);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002325
2326 if (dev->board.decoder == EM28XX_SAA711X)
Frank Schaefer95d26082014-03-24 16:33:09 -03002327 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2328 &dev->i2c_adap[dev->def_i2c_bus],
2329 "saa7115_auto", 0, saa711x_addrs);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002330
2331 if (dev->board.decoder == EM28XX_TVP5150)
Frank Schaefer95d26082014-03-24 16:33:09 -03002332 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2333 &dev->i2c_adap[dev->def_i2c_bus],
2334 "tvp5150", 0, tvp5150_addrs);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002335
2336 if (dev->board.adecoder == EM28XX_TVAUDIO)
Frank Schaefer95d26082014-03-24 16:33:09 -03002337 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2338 &dev->i2c_adap[dev->def_i2c_bus],
2339 "tvaudio", dev->board.tvaudio_addr, NULL);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002340
2341 /* Initialize tuner and camera */
2342
2343 if (dev->board.tuner_type != TUNER_ABSENT) {
2344 int has_demod = (dev->tda9887_conf & TDA9887_PRESENT);
2345
2346 if (dev->board.radio.type)
Frank Schaefer95d26082014-03-24 16:33:09 -03002347 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2348 &dev->i2c_adap[dev->def_i2c_bus],
2349 "tuner", dev->board.radio_addr, NULL);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002350
2351 if (has_demod)
Frank Schaefer95d26082014-03-24 16:33:09 -03002352 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002353 &dev->i2c_adap[dev->def_i2c_bus], "tuner",
2354 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
2355 if (dev->tuner_addr == 0) {
2356 enum v4l2_i2c_tuner_type type =
2357 has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV;
2358 struct v4l2_subdev *sd;
2359
Frank Schaefer95d26082014-03-24 16:33:09 -03002360 sd = v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002361 &dev->i2c_adap[dev->def_i2c_bus], "tuner",
2362 0, v4l2_i2c_tuner_addrs(type));
2363
2364 if (sd)
2365 dev->tuner_addr = v4l2_i2c_subdev_addr(sd);
2366 } else {
Frank Schaefer95d26082014-03-24 16:33:09 -03002367 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2368 &dev->i2c_adap[dev->def_i2c_bus],
2369 "tuner", dev->tuner_addr, NULL);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002370 }
2371 }
2372
2373 em28xx_tuner_setup(dev);
Frank Schaeferd86bc652014-01-17 14:45:32 -03002374 if (dev->em28xx_sensor != EM28XX_NOSENSOR)
2375 em28xx_init_camera(dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002376
2377 /* Configure audio */
2378 ret = em28xx_audio_setup(dev);
2379 if (ret < 0) {
2380 em28xx_errdev("%s: Error while setting audio - error [%d]!\n",
2381 __func__, ret);
2382 goto unregister_dev;
2383 }
2384 if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
2385 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
2386 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
2387 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
2388 V4L2_CID_AUDIO_VOLUME, 0, 0x1f, 1, 0x1f);
2389 } else {
2390 /* install the em28xx notify callback */
2391 v4l2_ctrl_notify(v4l2_ctrl_find(hdl, V4L2_CID_AUDIO_MUTE),
2392 em28xx_ctrl_notify, dev);
2393 v4l2_ctrl_notify(v4l2_ctrl_find(hdl, V4L2_CID_AUDIO_VOLUME),
2394 em28xx_ctrl_notify, dev);
2395 }
2396
2397 /* wake i2c devices */
2398 em28xx_wake_i2c(dev);
2399
2400 /* init video dma queues */
2401 INIT_LIST_HEAD(&dev->vidq.active);
2402 INIT_LIST_HEAD(&dev->vbiq.active);
2403
2404 if (dev->board.has_msp34xx) {
2405 /* Send a reset to other chips via gpio */
2406 ret = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xf7);
2407 if (ret < 0) {
2408 em28xx_errdev("%s: em28xx_write_reg - msp34xx(1) failed! error [%d]\n",
2409 __func__, ret);
2410 goto unregister_dev;
2411 }
2412 msleep(3);
2413
2414 ret = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xff);
2415 if (ret < 0) {
2416 em28xx_errdev("%s: em28xx_write_reg - msp34xx(2) failed! error [%d]\n",
2417 __func__, ret);
2418 goto unregister_dev;
2419 }
2420 msleep(3);
2421 }
2422
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002423 /* set default norm */
Hans Verkuild8c95c02012-09-07 07:31:54 -03002424 dev->norm = V4L2_STD_PAL;
Frank Schaefer95d26082014-03-24 16:33:09 -03002425 v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_std, dev->norm);
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002426 dev->interlaced = EM28XX_INTERLACED_DEFAULT;
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002427
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002428 /* Analog specific initialization */
2429 dev->format = &format[0];
Sascha Sommer1020d132012-01-08 16:54:28 -03002430
2431 maxw = norm_maxw(dev);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002432 /* MaxPacketSize for em2800 is too small to capture at full resolution
2433 * use half of maxw as the scaler can only scale to 50% */
2434 if (dev->board.is_em2800)
2435 maxw /= 2;
Sascha Sommer1020d132012-01-08 16:54:28 -03002436
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03002437 em28xx_set_video_format(dev, format[0].fourcc,
Sascha Sommer1020d132012-01-08 16:54:28 -03002438 maxw, norm_maxh(dev));
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03002439
Ezequiel García96371fc2012-03-23 18:09:34 -03002440 video_mux(dev, 0);
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002441
2442 /* Audio defaults */
2443 dev->mute = 1;
2444 dev->volume = 0x1f;
2445
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002446/* em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -03002447 val = (u8)em28xx_read_reg(dev, EM28XX_R0F_XCLK);
2448 em28xx_write_reg(dev, EM28XX_R0F_XCLK,
2449 (EM28XX_XCLK_AUDIO_UNMUTE | val));
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002450
2451 em28xx_set_outfmt(dev);
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002452
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002453 /* Add image controls */
2454 /* NOTE: at this point, the subdevices are already registered, so bridge
2455 * controls are only added/enabled when no subdevice provides them */
Frank Schaeferad298052014-03-24 16:33:08 -03002456 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_CONTRAST))
2457 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002458 V4L2_CID_CONTRAST,
2459 0, 0x1f, 1, CONTRAST_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002460 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_BRIGHTNESS))
2461 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002462 V4L2_CID_BRIGHTNESS,
2463 -0x80, 0x7f, 1, BRIGHTNESS_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002464 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_SATURATION))
2465 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002466 V4L2_CID_SATURATION,
2467 0, 0x1f, 1, SATURATION_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002468 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_BLUE_BALANCE))
2469 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002470 V4L2_CID_BLUE_BALANCE,
2471 -0x30, 0x30, 1, BLUE_BALANCE_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002472 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_RED_BALANCE))
2473 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002474 V4L2_CID_RED_BALANCE,
2475 -0x30, 0x30, 1, RED_BALANCE_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002476 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_SHARPNESS))
2477 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002478 V4L2_CID_SHARPNESS,
2479 0, 0x0f, 1, SHARPNESS_DEFAULT);
2480
2481 /* Reset image controls */
2482 em28xx_colorlevels_set_default(dev);
Frank Schaeferad298052014-03-24 16:33:08 -03002483 v4l2_ctrl_handler_setup(hdl);
2484 ret = hdl->error;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002485 if (ret)
2486 goto unregister_dev;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002487
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002488 /* allocate and fill video video_device struct */
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002489 v4l2->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video");
2490 if (!v4l2->vdev) {
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002491 em28xx_errdev("cannot allocate video_device.\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002492 ret = -ENODEV;
2493 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002494 }
Frank Schaefer27a36df2014-03-24 16:33:13 -03002495 mutex_init(&v4l2->vb_queue_lock);
2496 mutex_init(&v4l2->vb_vbi_queue_lock);
2497 v4l2->vdev->queue = &v4l2->vb_vidq;
2498 v4l2->vdev->queue->lock = &v4l2->vb_queue_lock;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002499
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002500 /* disable inapplicable ioctls */
2501 if (dev->board.is_webcam) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002502 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_QUERYSTD);
2503 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_G_STD);
2504 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_STD);
Frank Schaefer3bc85cc2013-02-07 13:39:12 -03002505 } else {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002506 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_PARM);
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002507 }
Frank Schaefer66df67b2013-02-07 13:39:10 -03002508 if (dev->tuner_type == TUNER_ABSENT) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002509 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_G_TUNER);
2510 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_TUNER);
2511 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_G_FREQUENCY);
2512 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_FREQUENCY);
Frank Schaefer66df67b2013-02-07 13:39:10 -03002513 }
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002514 if (!dev->audio_mode.has_audio) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002515 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_G_AUDIO);
2516 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_AUDIO);
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002517 }
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002518
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002519 /* register v4l2 video video_device */
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002520 ret = video_register_device(v4l2->vdev, VFL_TYPE_GRABBER,
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002521 video_nr[dev->devno]);
2522 if (ret) {
2523 em28xx_errdev("unable to register video device (error=%i).\n",
2524 ret);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002525 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002526 }
2527
2528 /* Allocate and fill vbi video_device struct */
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002529 if (em28xx_vbi_supported(dev) == 1) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002530 v4l2->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template,
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002531 "vbi");
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002532
Frank Schaefer27a36df2014-03-24 16:33:13 -03002533 v4l2->vbi_dev->queue = &v4l2->vb_vbiq;
2534 v4l2->vbi_dev->queue->lock = &v4l2->vb_vbi_queue_lock;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002535
Frank Schaefer66df67b2013-02-07 13:39:10 -03002536 /* disable inapplicable ioctls */
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002537 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_PARM);
Frank Schaefer66df67b2013-02-07 13:39:10 -03002538 if (dev->tuner_type == TUNER_ABSENT) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002539 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_G_TUNER);
2540 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_TUNER);
2541 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_G_FREQUENCY);
2542 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_FREQUENCY);
Frank Schaefer66df67b2013-02-07 13:39:10 -03002543 }
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002544 if (!dev->audio_mode.has_audio) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002545 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_G_AUDIO);
2546 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_AUDIO);
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002547 }
Frank Schaefer66df67b2013-02-07 13:39:10 -03002548
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002549 /* register v4l2 vbi video_device */
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002550 ret = video_register_device(v4l2->vbi_dev, VFL_TYPE_VBI,
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002551 vbi_nr[dev->devno]);
2552 if (ret < 0) {
2553 em28xx_errdev("unable to register vbi device\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002554 goto unregister_dev;
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002555 }
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002556 }
2557
2558 if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002559 v4l2->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template,
2560 "radio");
2561 if (!v4l2->radio_dev) {
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002562 em28xx_errdev("cannot allocate video_device.\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002563 ret = -ENODEV;
2564 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002565 }
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002566 ret = video_register_device(v4l2->radio_dev, VFL_TYPE_RADIO,
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002567 radio_nr[dev->devno]);
2568 if (ret < 0) {
2569 em28xx_errdev("can't register radio device\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002570 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002571 }
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002572 em28xx_info("Registered radio device as %s\n",
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002573 video_device_node_name(v4l2->radio_dev));
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002574 }
2575
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002576 em28xx_info("V4L2 video device registered as %s\n",
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002577 video_device_node_name(v4l2->vdev));
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002578
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002579 if (v4l2->vbi_dev)
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002580 em28xx_info("V4L2 VBI device registered as %s\n",
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002581 video_device_node_name(v4l2->vbi_dev));
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002582
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002583 /* Save some power by putting tuner to sleep */
Frank Schaefer95d26082014-03-24 16:33:09 -03002584 v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_power, 0);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002585
2586 /* initialize videobuf2 stuff */
2587 em28xx_vb2_setup(dev);
2588
Mauro Carvalho Chehab96346142013-12-26 12:41:03 -03002589 em28xx_info("V4L2 extension successfully initialized\n");
2590
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002591 kref_get(&dev->ref);
2592
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002593 mutex_unlock(&dev->lock);
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002594 return 0;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002595
2596unregister_dev:
Frank Schaeferabc13082014-03-24 16:33:10 -03002597 v4l2_ctrl_handler_free(&v4l2->ctrl_handler);
Frank Schaefer95d26082014-03-24 16:33:09 -03002598 v4l2_device_unregister(&v4l2->v4l2_dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002599err:
Frank Schaefer95d26082014-03-24 16:33:09 -03002600 dev->v4l2 = NULL;
2601 kref_put(&v4l2->ref, em28xx_free_v4l2);
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002602 mutex_unlock(&dev->lock);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002603 return ret;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002604}
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002605
2606static struct em28xx_ops v4l2_ops = {
2607 .id = EM28XX_V4L2,
2608 .name = "Em28xx v4l2 Extension",
2609 .init = em28xx_v4l2_init,
2610 .fini = em28xx_v4l2_fini,
Shuah Khana61f6812014-02-21 21:50:17 -03002611 .suspend = em28xx_v4l2_suspend,
2612 .resume = em28xx_v4l2_resume,
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002613};
2614
2615static int __init em28xx_video_register(void)
2616{
2617 return em28xx_register_extension(&v4l2_ops);
2618}
2619
2620static void __exit em28xx_video_unregister(void)
2621{
2622 em28xx_unregister_extension(&v4l2_ops);
2623}
2624
2625module_init(em28xx_video_register);
2626module_exit(em28xx_video_unregister);