blob: 40e7c5feb841a2eb8e77131b223160618a79ec20 [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{
Frank Schaefer52faaf72014-03-24 16:33:16 -0300158 struct em28xx_v4l2 *v4l2 = dev->v4l2;
159
Frank Schaefer25c61e42014-03-22 10:01:03 -0300160 if (dev->board.is_webcam)
161 return dev->sensor_yres;
162
163 if (dev->board.max_range_640_480)
164 return 480;
165
Frank Schaefer52faaf72014-03-24 16:33:16 -0300166 return (v4l2->norm & V4L2_STD_625_50) ? 576 : 480;
Frank Schaefer25c61e42014-03-22 10:01:03 -0300167}
168
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300169static int em28xx_vbi_supported(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300170{
171 /* Modprobe option to manually disable */
172 if (disable_vbi == 1)
173 return 0;
174
175 if (dev->board.is_webcam)
176 return 0;
177
178 /* FIXME: check subdevices for VBI support */
179
180 if (dev->chip_id == CHIP_ID_EM2860 ||
181 dev->chip_id == CHIP_ID_EM2883)
182 return 1;
183
184 /* Version of em28xx that does not support VBI */
185 return 0;
186}
187
188/*
189 * em28xx_wake_i2c()
190 * configure i2c attached devices
191 */
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300192static void em28xx_wake_i2c(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300193{
Frank Schaefer95d26082014-03-24 16:33:09 -0300194 struct v4l2_device *v4l2_dev = &dev->v4l2->v4l2_dev;
195 v4l2_device_call_all(v4l2_dev, 0, core, reset, 0);
196 v4l2_device_call_all(v4l2_dev, 0, video, s_routing,
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300197 INPUT(dev->ctl_input)->vmux, 0, 0);
Frank Schaefer95d26082014-03-24 16:33:09 -0300198 v4l2_device_call_all(v4l2_dev, 0, video, s_stream, 0);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300199}
200
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300201static int em28xx_colorlevels_set_default(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300202{
203 em28xx_write_reg(dev, EM28XX_R20_YGAIN, CONTRAST_DEFAULT);
204 em28xx_write_reg(dev, EM28XX_R21_YOFFSET, BRIGHTNESS_DEFAULT);
205 em28xx_write_reg(dev, EM28XX_R22_UVGAIN, SATURATION_DEFAULT);
206 em28xx_write_reg(dev, EM28XX_R23_UOFFSET, BLUE_BALANCE_DEFAULT);
207 em28xx_write_reg(dev, EM28XX_R24_VOFFSET, RED_BALANCE_DEFAULT);
208 em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, SHARPNESS_DEFAULT);
209
210 em28xx_write_reg(dev, EM28XX_R14_GAMMA, 0x20);
211 em28xx_write_reg(dev, EM28XX_R15_RGAIN, 0x20);
212 em28xx_write_reg(dev, EM28XX_R16_GGAIN, 0x20);
213 em28xx_write_reg(dev, EM28XX_R17_BGAIN, 0x20);
214 em28xx_write_reg(dev, EM28XX_R18_ROFFSET, 0x00);
215 em28xx_write_reg(dev, EM28XX_R19_GOFFSET, 0x00);
216 return em28xx_write_reg(dev, EM28XX_R1A_BOFFSET, 0x00);
217}
218
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300219static int em28xx_set_outfmt(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300220{
221 int ret;
222 u8 fmt, vinctrl;
Frank Schaefer753aee72014-03-24 16:33:14 -0300223 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300224
Frank Schaefer06e20672014-03-24 16:33:17 -0300225 fmt = v4l2->format->reg;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300226 if (!dev->is_em25xx)
227 fmt |= 0x20;
228 /*
229 * NOTE: it's not clear if this is really needed !
230 * The datasheets say bit 5 is a reserved bit and devices seem to work
231 * fine without it. But the Windows driver sets it for em2710/50+em28xx
232 * devices and we've always been setting it, too.
233 *
234 * em2765 (em25xx, em276x/7x/8x) devices do NOT work with this bit set,
235 * it's likely used for an additional (compressed ?) format there.
236 */
237 ret = em28xx_write_reg(dev, EM28XX_R27_OUTFMT, fmt);
238 if (ret < 0)
239 return ret;
240
Frank Schaefer92972852014-03-24 16:33:15 -0300241 ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, v4l2->vinmode);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300242 if (ret < 0)
243 return ret;
244
Frank Schaefer92972852014-03-24 16:33:15 -0300245 vinctrl = v4l2->vinctl;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300246 if (em28xx_vbi_supported(dev) == 1) {
247 vinctrl |= EM28XX_VINCTRL_VBI_RAW;
248 em28xx_write_reg(dev, EM28XX_R34_VBI_START_H, 0x00);
Frank Schaefer753aee72014-03-24 16:33:14 -0300249 em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH, v4l2->vbi_width/4);
250 em28xx_write_reg(dev, EM28XX_R37_VBI_HEIGHT, v4l2->vbi_height);
Frank Schaefer52faaf72014-03-24 16:33:16 -0300251 if (v4l2->norm & V4L2_STD_525_60) {
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300252 /* NTSC */
253 em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x09);
Frank Schaefer52faaf72014-03-24 16:33:16 -0300254 } else if (v4l2->norm & V4L2_STD_625_50) {
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300255 /* PAL */
256 em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x07);
257 }
258 }
259
260 return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctrl);
261}
262
263static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax,
264 u8 ymin, u8 ymax)
265{
266 em28xx_videodbg("em28xx Scale: (%d,%d)-(%d,%d)\n",
267 xmin, ymin, xmax, ymax);
268
269 em28xx_write_regs(dev, EM28XX_R28_XMIN, &xmin, 1);
270 em28xx_write_regs(dev, EM28XX_R29_XMAX, &xmax, 1);
271 em28xx_write_regs(dev, EM28XX_R2A_YMIN, &ymin, 1);
272 return em28xx_write_regs(dev, EM28XX_R2B_YMAX, &ymax, 1);
273}
274
275static void em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
276 u16 width, u16 height)
277{
278 u8 cwidth = width >> 2;
279 u8 cheight = height >> 2;
280 u8 overflow = (height >> 9 & 0x02) | (width >> 10 & 0x01);
281 /* NOTE: size limit: 2047x1023 = 2MPix */
282
283 em28xx_videodbg("capture area set to (%d,%d): %dx%d\n",
284 hstart, vstart,
285 ((overflow & 2) << 9 | cwidth << 2),
286 ((overflow & 1) << 10 | cheight << 2));
287
288 em28xx_write_regs(dev, EM28XX_R1C_HSTART, &hstart, 1);
289 em28xx_write_regs(dev, EM28XX_R1D_VSTART, &vstart, 1);
290 em28xx_write_regs(dev, EM28XX_R1E_CWIDTH, &cwidth, 1);
291 em28xx_write_regs(dev, EM28XX_R1F_CHEIGHT, &cheight, 1);
292 em28xx_write_regs(dev, EM28XX_R1B_OFLOW, &overflow, 1);
293
294 /* FIXME: function/meaning of these registers ? */
295 /* FIXME: align width+height to multiples of 4 ?! */
296 if (dev->is_em25xx) {
297 em28xx_write_reg(dev, 0x34, width >> 4);
298 em28xx_write_reg(dev, 0x35, height >> 4);
299 }
300}
301
302static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v)
303{
Frank Schaefercba8e9b2014-03-24 16:28:36 -0300304 u8 mode = 0x00;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300305 /* the em2800 scaler only supports scaling down to 50% */
306
307 if (dev->board.is_em2800) {
308 mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00);
309 } else {
310 u8 buf[2];
311
312 buf[0] = h;
313 buf[1] = h >> 8;
314 em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2);
315
316 buf[0] = v;
317 buf[1] = v >> 8;
318 em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2);
319 /* it seems that both H and V scalers must be active
320 to work correctly */
321 mode = (h || v) ? 0x30 : 0x00;
322 }
Frank Schaefercba8e9b2014-03-24 16:28:36 -0300323 return em28xx_write_reg(dev, EM28XX_R26_COMPR, mode);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300324}
325
326/* FIXME: this only function read values from dev */
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300327static int em28xx_resolution_set(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300328{
Frank Schaefer753aee72014-03-24 16:33:14 -0300329 struct em28xx_v4l2 *v4l2 = dev->v4l2;
330 int width = norm_maxw(dev);
331 int height = norm_maxh(dev);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300332
333 /* Properly setup VBI */
Frank Schaefer753aee72014-03-24 16:33:14 -0300334 v4l2->vbi_width = 720;
Frank Schaefer52faaf72014-03-24 16:33:16 -0300335 if (v4l2->norm & V4L2_STD_525_60)
Frank Schaefer753aee72014-03-24 16:33:14 -0300336 v4l2->vbi_height = 12;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300337 else
Frank Schaefer753aee72014-03-24 16:33:14 -0300338 v4l2->vbi_height = 18;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300339
340 em28xx_set_outfmt(dev);
341
342 em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2);
343
344 /* If we don't set the start position to 2 in VBI mode, we end up
345 with line 20/21 being YUYV encoded instead of being in 8-bit
346 greyscale. The core of the issue is that line 21 (and line 23 for
347 PAL WSS) are inside of active video region, and as a result they
348 get the pixelformatting associated with that area. So by cropping
349 it out, we end up with the same format as the rest of the VBI
350 region */
351 if (em28xx_vbi_supported(dev) == 1)
352 em28xx_capture_area_set(dev, 0, 2, width, height);
353 else
354 em28xx_capture_area_set(dev, 0, 0, width, height);
355
Frank Schaefer753aee72014-03-24 16:33:14 -0300356 return em28xx_scaler_set(dev, v4l2->hscale, v4l2->vscale);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300357}
358
359/* Set USB alternate setting for analog video */
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300360static int em28xx_set_alternate(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300361{
Frank Schaefer753aee72014-03-24 16:33:14 -0300362 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300363 int errCode;
364 int i;
Frank Schaefer753aee72014-03-24 16:33:14 -0300365 unsigned int min_pkt_size = v4l2->width * 2 + 4;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300366
367 /* NOTE: for isoc transfers, only alt settings > 0 are allowed
368 bulk transfers seem to work only with alt=0 ! */
369 dev->alt = 0;
370 if ((alt > 0) && (alt < dev->num_alt)) {
371 em28xx_videodbg("alternate forced to %d\n", dev->alt);
372 dev->alt = alt;
373 goto set_alt;
374 }
375 if (dev->analog_xfer_bulk)
376 goto set_alt;
377
378 /* When image size is bigger than a certain value,
379 the frame size should be increased, otherwise, only
380 green screen will be received.
381 */
Frank Schaefer753aee72014-03-24 16:33:14 -0300382 if (v4l2->width * 2 * v4l2->height > 720 * 240 * 2)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300383 min_pkt_size *= 2;
384
385 for (i = 0; i < dev->num_alt; i++) {
386 /* stop when the selected alt setting offers enough bandwidth */
387 if (dev->alt_max_pkt_size_isoc[i] >= min_pkt_size) {
388 dev->alt = i;
389 break;
390 /* otherwise make sure that we end up with the maximum bandwidth
391 because the min_pkt_size equation might be wrong...
392 */
393 } else if (dev->alt_max_pkt_size_isoc[i] >
394 dev->alt_max_pkt_size_isoc[dev->alt])
395 dev->alt = i;
396 }
397
398set_alt:
399 /* NOTE: for bulk transfers, we need to call usb_set_interface()
400 * even if the previous settings were the same. Otherwise streaming
401 * fails with all urbs having status = -EOVERFLOW ! */
402 if (dev->analog_xfer_bulk) {
403 dev->max_pkt_size = 512; /* USB 2.0 spec */
404 dev->packet_multiplier = EM28XX_BULK_PACKET_MULTIPLIER;
405 } else { /* isoc */
406 em28xx_videodbg("minimum isoc packet size: %u (alt=%d)\n",
407 min_pkt_size, dev->alt);
408 dev->max_pkt_size =
409 dev->alt_max_pkt_size_isoc[dev->alt];
410 dev->packet_multiplier = EM28XX_NUM_ISOC_PACKETS;
411 }
412 em28xx_videodbg("setting alternate %d with wMaxPacketSize=%u\n",
413 dev->alt, dev->max_pkt_size);
Frank Schaefer961717b2014-01-13 19:02:06 -0300414 errCode = usb_set_interface(dev->udev, dev->ifnum, dev->alt);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300415 if (errCode < 0) {
416 em28xx_errdev("cannot change alternate number to %d (error=%i)\n",
417 dev->alt, errCode);
418 return errCode;
419 }
420 return 0;
421}
422
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300423/* ------------------------------------------------------------------
424 DMA and thread functions
425 ------------------------------------------------------------------*/
426
427/*
Frank Schaefer948a49a2012-12-08 11:31:25 -0300428 * Finish the current buffer
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300429 */
Frank Schaefer948a49a2012-12-08 11:31:25 -0300430static inline void finish_buffer(struct em28xx *dev,
431 struct em28xx_buffer *buf)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300432{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300433 em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->top_field);
434
435 buf->vb.v4l2_buf.sequence = dev->field_count++;
436 buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
437 v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
438
439 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300440}
441
442/*
Frank Schaefer36016a32012-12-08 11:31:32 -0300443 * Copy picture data from USB buffer to videobuf buffer
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300444 */
445static void em28xx_copy_video(struct em28xx *dev,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300446 struct em28xx_buffer *buf,
Frank Schaefer36016a32012-12-08 11:31:32 -0300447 unsigned char *usb_buf,
Frank Schaefer4078d622012-12-08 11:31:29 -0300448 unsigned long len)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300449{
450 void *fieldstart, *startwrite, *startread;
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300451 int linesdone, currlinedone, offset, lencopy, remain;
Frank Schaefer753aee72014-03-24 16:33:14 -0300452 int bytesperline = dev->v4l2->width << 1;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300453
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300454 if (buf->pos + len > buf->length)
455 len = buf->length - buf->pos;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300456
Frank Schaefer36016a32012-12-08 11:31:32 -0300457 startread = usb_buf;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300458 remain = len;
459
Frank Schaeferc02ec712012-11-08 14:11:33 -0300460 if (dev->progressive || buf->top_field)
Frank Schaefer36016a32012-12-08 11:31:32 -0300461 fieldstart = buf->vb_buf;
Frank Schaeferc02ec712012-11-08 14:11:33 -0300462 else /* interlaced mode, even nr. of lines */
Frank Schaefer36016a32012-12-08 11:31:32 -0300463 fieldstart = buf->vb_buf + bytesperline;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300464
Frank Schaefer87325332012-12-08 11:31:27 -0300465 linesdone = buf->pos / bytesperline;
466 currlinedone = buf->pos % bytesperline;
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -0300467
468 if (dev->progressive)
469 offset = linesdone * bytesperline + currlinedone;
470 else
471 offset = linesdone * bytesperline * 2 + currlinedone;
472
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300473 startwrite = fieldstart + offset;
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300474 lencopy = bytesperline - currlinedone;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300475 lencopy = lencopy > remain ? remain : lencopy;
476
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300477 if ((char *)startwrite + lencopy > (char *)buf->vb_buf + buf->length) {
Mauro Carvalho Chehabea8df7e2008-04-13 14:39:29 -0300478 em28xx_isocdbg("Overflow of %zi bytes past buffer end (1)\n",
Frank Schaefer36016a32012-12-08 11:31:32 -0300479 ((char *)startwrite + lencopy) -
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300480 ((char *)buf->vb_buf + buf->length));
481 remain = (char *)buf->vb_buf + buf->length -
Frank Schaefer36016a32012-12-08 11:31:32 -0300482 (char *)startwrite;
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -0300483 lencopy = remain;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300484 }
Aidan Thorntone0fadfd342008-04-13 14:56:02 -0300485 if (lencopy <= 0)
486 return;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300487 memcpy(startwrite, startread, lencopy);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300488
489 remain -= lencopy;
490
491 while (remain > 0) {
Frank Schaeferc02ec712012-11-08 14:11:33 -0300492 if (dev->progressive)
493 startwrite += lencopy;
494 else
495 startwrite += lencopy + bytesperline;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300496 startread += lencopy;
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300497 if (bytesperline > remain)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300498 lencopy = remain;
499 else
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300500 lencopy = bytesperline;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300501
Frank Schaefer36016a32012-12-08 11:31:32 -0300502 if ((char *)startwrite + lencopy > (char *)buf->vb_buf +
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300503 buf->length) {
Devin Heitmuellere3ba4d32009-09-15 00:18:06 -0300504 em28xx_isocdbg("Overflow of %zi bytes past buffer end"
505 "(2)\n",
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300506 ((char *)startwrite + lencopy) -
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300507 ((char *)buf->vb_buf + buf->length));
508 lencopy = remain = (char *)buf->vb_buf + buf->length -
509 (char *)startwrite;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300510 }
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300511 if (lencopy <= 0)
512 break;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300513
514 memcpy(startwrite, startread, lencopy);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300515
516 remain -= lencopy;
517 }
518
Frank Schaefer87325332012-12-08 11:31:27 -0300519 buf->pos += len;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300520}
521
Frank Schaefer36016a32012-12-08 11:31:32 -0300522/*
523 * Copy VBI data from USB buffer to videobuf buffer
524 */
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300525static void em28xx_copy_vbi(struct em28xx *dev,
Frank Schaefer87325332012-12-08 11:31:27 -0300526 struct em28xx_buffer *buf,
Frank Schaefer36016a32012-12-08 11:31:32 -0300527 unsigned char *usb_buf,
Frank Schaefer4078d622012-12-08 11:31:29 -0300528 unsigned long len)
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300529{
Frank Schaefer36016a32012-12-08 11:31:32 -0300530 unsigned int offset;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300531
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300532 if (buf->pos + len > buf->length)
533 len = buf->length - buf->pos;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300534
Frank Schaefer87325332012-12-08 11:31:27 -0300535 offset = buf->pos;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300536 /* Make sure the bottom field populates the second half of the frame */
Frank Schaefer36016a32012-12-08 11:31:32 -0300537 if (buf->top_field == 0)
Frank Schaefer753aee72014-03-24 16:33:14 -0300538 offset += dev->v4l2->vbi_width * dev->v4l2->vbi_height;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300539
Frank Schaefer36016a32012-12-08 11:31:32 -0300540 memcpy(buf->vb_buf + offset, usb_buf, len);
Frank Schaefer87325332012-12-08 11:31:27 -0300541 buf->pos += len;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300542}
543
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300544static inline void print_err_status(struct em28xx *dev,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300545 int packet, int status)
546{
547 char *errmsg = "Unknown";
548
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300549 switch (status) {
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300550 case -ENOENT:
551 errmsg = "unlinked synchronuously";
552 break;
553 case -ECONNRESET:
554 errmsg = "unlinked asynchronuously";
555 break;
556 case -ENOSR:
557 errmsg = "Buffer error (overrun)";
558 break;
559 case -EPIPE:
560 errmsg = "Stalled (device not responding)";
561 break;
562 case -EOVERFLOW:
563 errmsg = "Babble (bad cable?)";
564 break;
565 case -EPROTO:
566 errmsg = "Bit-stuff error (bad cable?)";
567 break;
568 case -EILSEQ:
569 errmsg = "CRC/Timeout (could be anything)";
570 break;
571 case -ETIME:
572 errmsg = "Device does not respond";
573 break;
574 }
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300575 if (packet < 0) {
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300576 em28xx_isocdbg("URB status %d [%s].\n", status, errmsg);
577 } else {
578 em28xx_isocdbg("URB packet %d, status %d [%s].\n",
579 packet, status, errmsg);
580 }
581}
582
583/*
Frank Schaefer24a6d842012-12-08 11:31:24 -0300584 * get the next available buffer from dma queue
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300585 */
Frank Schaefer24a6d842012-12-08 11:31:24 -0300586static inline struct em28xx_buffer *get_next_buf(struct em28xx *dev,
587 struct em28xx_dmaqueue *dma_q)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300588{
Frank Schaefer24a6d842012-12-08 11:31:24 -0300589 struct em28xx_buffer *buf;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300590
Mauro Carvalho Chehabdbecb442008-04-13 15:08:55 -0300591 if (list_empty(&dma_q->active)) {
592 em28xx_isocdbg("No active queue to serve\n");
Frank Schaefer24a6d842012-12-08 11:31:24 -0300593 return NULL;
Mauro Carvalho Chehabdbecb442008-04-13 15:08:55 -0300594 }
595
Mauro Carvalho Chehabdbecb442008-04-13 15:08:55 -0300596 /* Get the next buffer */
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300597 buf = list_entry(dma_q->active.next, struct em28xx_buffer, list);
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300598 /* Cleans up buffer - Useful for testing for frame/URB loss */
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300599 list_del(&buf->list);
Frank Schaefer87325332012-12-08 11:31:27 -0300600 buf->pos = 0;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300601 buf->vb_buf = buf->mem;
Mauro Carvalho Chehabcb784722008-04-13 15:06:52 -0300602
Frank Schaefer24a6d842012-12-08 11:31:24 -0300603 return buf;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300604}
605
Frank Schaefere04c00d2012-12-08 11:31:30 -0300606/*
607 * Finish the current buffer if completed and prepare for the next field
608 */
609static struct em28xx_buffer *
610finish_field_prepare_next(struct em28xx *dev,
611 struct em28xx_buffer *buf,
612 struct em28xx_dmaqueue *dma_q)
613{
614 if (dev->progressive || dev->top_field) { /* Brand new frame */
615 if (buf != NULL)
616 finish_buffer(dev, buf);
617 buf = get_next_buf(dev, dma_q);
618 }
619 if (buf != NULL) {
620 buf->top_field = dev->top_field;
621 buf->pos = 0;
622 }
623
624 return buf;
625}
626
Frank Schaefer227b7c92012-12-08 11:31:31 -0300627/*
628 * Process data packet according to the em2710/em2750/em28xx frame data format
629 */
630static inline void process_frame_data_em28xx(struct em28xx *dev,
631 unsigned char *data_pkt,
632 unsigned int data_len)
633{
Frank Schaefer753aee72014-03-24 16:33:14 -0300634 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300635 struct em28xx_buffer *buf = dev->usb_ctl.vid_buf;
636 struct em28xx_buffer *vbi_buf = dev->usb_ctl.vbi_buf;
637 struct em28xx_dmaqueue *dma_q = &dev->vidq;
638 struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq;
639
640 /* capture type 0 = vbi start
641 capture type 1 = vbi in progress
642 capture type 2 = video start
643 capture type 3 = video in progress */
644 if (data_len >= 4) {
645 /* NOTE: Headers are always 4 bytes and
646 * never split across packets */
647 if (data_pkt[0] == 0x88 && data_pkt[1] == 0x88 &&
648 data_pkt[2] == 0x88 && data_pkt[3] == 0x88) {
649 /* Continuation */
650 data_pkt += 4;
651 data_len -= 4;
652 } else if (data_pkt[0] == 0x33 && data_pkt[1] == 0x95) {
653 /* Field start (VBI mode) */
654 dev->capture_type = 0;
655 dev->vbi_read = 0;
656 em28xx_isocdbg("VBI START HEADER !!!\n");
657 dev->top_field = !(data_pkt[2] & 1);
658 data_pkt += 4;
659 data_len -= 4;
660 } else if (data_pkt[0] == 0x22 && data_pkt[1] == 0x5a) {
661 /* Field start (VBI disabled) */
662 dev->capture_type = 2;
663 em28xx_isocdbg("VIDEO START HEADER !!!\n");
664 dev->top_field = !(data_pkt[2] & 1);
665 data_pkt += 4;
666 data_len -= 4;
667 }
668 }
669 /* NOTE: With bulk transfers, intermediate data packets
670 * have no continuation header */
671
672 if (dev->capture_type == 0) {
673 vbi_buf = finish_field_prepare_next(dev, vbi_buf, vbi_dma_q);
674 dev->usb_ctl.vbi_buf = vbi_buf;
675 dev->capture_type = 1;
676 }
677
678 if (dev->capture_type == 1) {
Frank Schaefer753aee72014-03-24 16:33:14 -0300679 int vbi_size = v4l2->vbi_width * v4l2->vbi_height;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300680 int vbi_data_len = ((dev->vbi_read + data_len) > vbi_size) ?
681 (vbi_size - dev->vbi_read) : data_len;
682
683 /* Copy VBI data */
684 if (vbi_buf != NULL)
685 em28xx_copy_vbi(dev, vbi_buf, data_pkt, vbi_data_len);
686 dev->vbi_read += vbi_data_len;
687
688 if (vbi_data_len < data_len) {
689 /* Continue with copying video data */
690 dev->capture_type = 2;
691 data_pkt += vbi_data_len;
692 data_len -= vbi_data_len;
693 }
694 }
695
696 if (dev->capture_type == 2) {
697 buf = finish_field_prepare_next(dev, buf, dma_q);
698 dev->usb_ctl.vid_buf = buf;
699 dev->capture_type = 3;
700 }
701
702 if (dev->capture_type == 3 && buf != NULL && data_len > 0)
703 em28xx_copy_video(dev, buf, data_pkt, data_len);
704}
705
Frank Schaefere507e0e2013-03-26 13:38:38 -0300706/*
707 * Process data packet according to the em25xx/em276x/7x/8x frame data format
708 */
709static inline void process_frame_data_em25xx(struct em28xx *dev,
710 unsigned char *data_pkt,
711 unsigned int data_len)
712{
713 struct em28xx_buffer *buf = dev->usb_ctl.vid_buf;
714 struct em28xx_dmaqueue *dmaq = &dev->vidq;
715 bool frame_end = 0;
716
717 /* Check for header */
718 /* NOTE: at least with bulk transfers, only the first packet
719 * has a header and has always set the FRAME_END bit */
720 if (data_len >= 2) { /* em25xx header is only 2 bytes long */
721 if ((data_pkt[0] == EM25XX_FRMDATAHDR_BYTE1) &&
722 ((data_pkt[1] & ~EM25XX_FRMDATAHDR_BYTE2_MASK) == 0x00)) {
723 dev->top_field = !(data_pkt[1] &
724 EM25XX_FRMDATAHDR_BYTE2_FRAME_ID);
725 frame_end = data_pkt[1] &
726 EM25XX_FRMDATAHDR_BYTE2_FRAME_END;
727 data_pkt += 2;
728 data_len -= 2;
729 }
730
731 /* Finish field and prepare next (BULK only) */
732 if (dev->analog_xfer_bulk && frame_end) {
733 buf = finish_field_prepare_next(dev, buf, dmaq);
734 dev->usb_ctl.vid_buf = buf;
735 }
736 /* NOTE: in ISOC mode when a new frame starts and buf==NULL,
737 * we COULD already prepare a buffer here to avoid skipping the
738 * first frame.
739 */
740 }
741
742 /* Copy data */
743 if (buf != NULL && data_len > 0)
744 em28xx_copy_video(dev, buf, data_pkt, data_len);
745
746 /* Finish frame (ISOC only) => avoids lag of 1 frame */
747 if (!dev->analog_xfer_bulk && frame_end) {
748 buf = finish_field_prepare_next(dev, buf, dmaq);
749 dev->usb_ctl.vid_buf = buf;
750 }
751
752 /* NOTE: Tested with USB bulk transfers only !
753 * The wording in the datasheet suggests that isoc might work different.
754 * The current code assumes that with isoc transfers each packet has a
755 * header like with the other em28xx devices.
756 */
757 /* NOTE: Support for interlaced mode is pure theory. It has not been
758 * tested and it is unknown if these devices actually support it. */
759 /* NOTE: No VBI support yet (these chips likely do not support VBI). */
760}
761
Frank Schaefer960da932012-11-25 06:37:37 -0300762/* Processes and copies the URB data content (video and VBI data) */
Frank Schaefer0fa4a402012-11-08 14:11:45 -0300763static inline int em28xx_urb_data_copy(struct em28xx *dev, struct urb *urb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300764{
Frank Schaefer227b7c92012-12-08 11:31:31 -0300765 int xfer_bulk, num_packets, i;
766 unsigned char *usb_data_pkt;
767 unsigned int usb_data_len;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300768
769 if (!dev)
770 return 0;
771
Frank Schaefer2665c292012-12-27 19:02:43 -0300772 if (dev->disconnected)
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300773 return 0;
774
Frank Schaefer1653cb0c2012-11-08 14:11:44 -0300775 if (urb->status < 0)
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300776 print_err_status(dev, -1, urb->status);
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300777
Frank Schaefer4601cc32012-11-08 14:11:46 -0300778 xfer_bulk = usb_pipebulk(urb->pipe);
779
Frank Schaefer4601cc32012-11-08 14:11:46 -0300780 if (xfer_bulk) /* bulk */
781 num_packets = 1;
782 else /* isoc */
783 num_packets = urb->number_of_packets;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300784
Frank Schaefer4601cc32012-11-08 14:11:46 -0300785 for (i = 0; i < num_packets; i++) {
786 if (xfer_bulk) { /* bulk */
Frank Schaefer227b7c92012-12-08 11:31:31 -0300787 usb_data_len = urb->actual_length;
Frank Schaefer4601cc32012-11-08 14:11:46 -0300788
Frank Schaefer227b7c92012-12-08 11:31:31 -0300789 usb_data_pkt = urb->transfer_buffer;
Frank Schaefer4601cc32012-11-08 14:11:46 -0300790 } else { /* isoc */
791 if (urb->iso_frame_desc[i].status < 0) {
792 print_err_status(dev, i,
793 urb->iso_frame_desc[i].status);
794 if (urb->iso_frame_desc[i].status != -EPROTO)
795 continue;
796 }
797
Frank Schaefer227b7c92012-12-08 11:31:31 -0300798 usb_data_len = urb->iso_frame_desc[i].actual_length;
799 if (usb_data_len > dev->max_pkt_size) {
Frank Schaefer4601cc32012-11-08 14:11:46 -0300800 em28xx_isocdbg("packet bigger than packet size");
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300801 continue;
Frank Schaefer4601cc32012-11-08 14:11:46 -0300802 }
803
Frank Schaefer227b7c92012-12-08 11:31:31 -0300804 usb_data_pkt = urb->transfer_buffer +
805 urb->iso_frame_desc[i].offset;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300806 }
807
Frank Schaefer227b7c92012-12-08 11:31:31 -0300808 if (usb_data_len == 0) {
Frank Schaefer4601cc32012-11-08 14:11:46 -0300809 /* NOTE: happens very often with isoc transfers */
810 /* em28xx_usbdbg("packet %d is empty",i); - spammy */
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300811 continue;
812 }
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300813
Frank Schaefere507e0e2013-03-26 13:38:38 -0300814 if (dev->is_em25xx)
815 process_frame_data_em25xx(dev,
816 usb_data_pkt, usb_data_len);
817 else
818 process_frame_data_em28xx(dev,
819 usb_data_pkt, usb_data_len);
820
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300821 }
Frank Schaefer227b7c92012-12-08 11:31:31 -0300822 return 1;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300823}
824
825
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300826static int get_ressource(enum v4l2_buf_type f_type)
827{
828 switch (f_type) {
829 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
830 return EM28XX_RESOURCE_VIDEO;
831 case V4L2_BUF_TYPE_VBI_CAPTURE:
832 return EM28XX_RESOURCE_VBI;
833 default:
834 BUG();
835 return 0;
836 }
837}
838
839/* Usage lock check functions */
840static int res_get(struct em28xx *dev, enum v4l2_buf_type f_type)
841{
842 int res_type = get_ressource(f_type);
843
844 /* is it free? */
845 if (dev->resources & res_type) {
846 /* no, someone else uses it */
847 return -EBUSY;
848 }
849
850 /* it's free, grab it */
851 dev->resources |= res_type;
852 em28xx_videodbg("res: get %d\n", res_type);
853 return 0;
854}
855
856static void res_free(struct em28xx *dev, enum v4l2_buf_type f_type)
857{
858 int res_type = get_ressource(f_type);
859
860 dev->resources &= ~res_type;
861 em28xx_videodbg("res: put %d\n", res_type);
862}
863
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300864/* ------------------------------------------------------------------
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300865 Videobuf2 operations
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300866 ------------------------------------------------------------------*/
867
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300868static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
869 unsigned int *nbuffers, unsigned int *nplanes,
870 unsigned int sizes[], void *alloc_ctxs[])
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300871{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300872 struct em28xx *dev = vb2_get_drv_priv(vq);
Frank Schaefer753aee72014-03-24 16:33:14 -0300873 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300874 unsigned long size;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300875
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300876 if (fmt)
877 size = fmt->fmt.pix.sizeimage;
878 else
Frank Schaefer753aee72014-03-24 16:33:14 -0300879 size =
Frank Schaefer06e20672014-03-24 16:33:17 -0300880 (v4l2->width * v4l2->height * v4l2->format->depth + 7) >> 3;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -0300881
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300882 if (size == 0)
883 return -EINVAL;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300884
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300885 if (0 == *nbuffers)
886 *nbuffers = 32;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300887
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300888 *nplanes = 1;
889 sizes[0] = size;
Mauro Carvalho Chehabd2d9fbf2008-04-17 21:38:53 -0300890
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300891 return 0;
892}
893
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300894static int
895buffer_prepare(struct vb2_buffer *vb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300896{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300897 struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue);
Frank Schaefer753aee72014-03-24 16:33:14 -0300898 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300899 struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
900 unsigned long size;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300901
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300902 em28xx_videodbg("%s, field=%d\n", __func__, vb->v4l2_buf.field);
Aidan Thornton3b5fa922008-04-13 15:09:36 -0300903
Frank Schaefer06e20672014-03-24 16:33:17 -0300904 size = (v4l2->width * v4l2->height * v4l2->format->depth + 7) >> 3;
Aidan Thornton3b5fa922008-04-13 15:09:36 -0300905
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300906 if (vb2_plane_size(vb, 0) < size) {
907 em28xx_videodbg("%s data will not fit into plane (%lu < %lu)\n",
908 __func__, vb2_plane_size(vb, 0), size);
909 return -EINVAL;
910 }
911 vb2_set_plane_payload(&buf->vb, 0, size);
912
913 return 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300914}
915
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300916int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300917{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300918 struct em28xx *dev = vb2_get_drv_priv(vq);
919 struct v4l2_frequency f;
920 int rc = 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300921
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300922 em28xx_videodbg("%s\n", __func__);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300923
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300924 /* Make sure streaming is not already in progress for this type
925 of filehandle (e.g. video, vbi) */
926 rc = res_get(dev, vq->type);
927 if (rc)
928 return rc;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300929
Frank Schaefer032f1dd2013-10-10 15:31:53 -0300930 if (dev->streaming_users == 0) {
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300931 /* First active streaming user, so allocate all the URBs */
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300932
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300933 /* Allocate the USB bandwidth */
934 em28xx_set_alternate(dev);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300935
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300936 /* Needed, since GPIO might have disabled power of
937 some i2c device
938 */
939 em28xx_wake_i2c(dev);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300940
Frank Schaefer0455eeb2012-11-25 06:37:34 -0300941 dev->capture_type = -1;
Frank Schaefer960da932012-11-25 06:37:37 -0300942 rc = em28xx_init_usb_xfer(dev, EM28XX_ANALOG_MODE,
943 dev->analog_xfer_bulk,
944 EM28XX_NUM_BUFS,
945 dev->max_pkt_size,
946 dev->packet_multiplier,
947 em28xx_urb_data_copy);
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300948 if (rc < 0)
Frank Schaefer032f1dd2013-10-10 15:31:53 -0300949 return rc;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300950
951 /*
952 * djh: it's not clear whether this code is still needed. I'm
953 * leaving it in here for now entirely out of concern for
954 * backward compatibility (the old code did it)
955 */
956
957 /* Ask tuner to go to analog or radio mode */
958 memset(&f, 0, sizeof(f));
959 f.frequency = dev->ctl_freq;
960 if (vq->owner && vq->owner->vdev->vfl_type == VFL_TYPE_RADIO)
961 f.type = V4L2_TUNER_RADIO;
962 else
963 f.type = V4L2_TUNER_ANALOG_TV;
Frank Schaefer95d26082014-03-24 16:33:09 -0300964 v4l2_device_call_all(&dev->v4l2->v4l2_dev,
965 0, tuner, s_frequency, &f);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300966 }
967
Frank Schaefer032f1dd2013-10-10 15:31:53 -0300968 dev->streaming_users++;
969
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300970 return rc;
971}
972
Hans Verkuile37559b2014-04-17 02:47:21 -0300973static void em28xx_stop_streaming(struct vb2_queue *vq)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300974{
975 struct em28xx *dev = vb2_get_drv_priv(vq);
976 struct em28xx_dmaqueue *vidq = &dev->vidq;
977 unsigned long flags = 0;
978
979 em28xx_videodbg("%s\n", __func__);
980
981 res_free(dev, vq->type);
982
983 if (dev->streaming_users-- == 1) {
984 /* Last active user, so shutdown all the URBS */
985 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
986 }
987
988 spin_lock_irqsave(&dev->slock, flags);
989 while (!list_empty(&vidq->active)) {
990 struct em28xx_buffer *buf;
991 buf = list_entry(vidq->active.next, struct em28xx_buffer, list);
992 list_del(&buf->list);
993 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
994 }
995 dev->usb_ctl.vid_buf = NULL;
996 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300997}
998
Hans Verkuile37559b2014-04-17 02:47:21 -0300999void em28xx_stop_vbi_streaming(struct vb2_queue *vq)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001000{
1001 struct em28xx *dev = vb2_get_drv_priv(vq);
1002 struct em28xx_dmaqueue *vbiq = &dev->vbiq;
1003 unsigned long flags = 0;
1004
1005 em28xx_videodbg("%s\n", __func__);
1006
1007 res_free(dev, vq->type);
1008
1009 if (dev->streaming_users-- == 1) {
1010 /* Last active user, so shutdown all the URBS */
1011 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
1012 }
1013
1014 spin_lock_irqsave(&dev->slock, flags);
1015 while (!list_empty(&vbiq->active)) {
1016 struct em28xx_buffer *buf;
1017 buf = list_entry(vbiq->active.next, struct em28xx_buffer, list);
1018 list_del(&buf->list);
1019 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
1020 }
1021 dev->usb_ctl.vbi_buf = NULL;
1022 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001023}
1024
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001025static void
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001026buffer_queue(struct vb2_buffer *vb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001027{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001028 struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue);
1029 struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
1030 struct em28xx_dmaqueue *vidq = &dev->vidq;
1031 unsigned long flags = 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001032
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001033 em28xx_videodbg("%s\n", __func__);
1034 buf->mem = vb2_plane_vaddr(vb, 0);
1035 buf->length = vb2_plane_size(vb, 0);
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001036
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001037 spin_lock_irqsave(&dev->slock, flags);
1038 list_add_tail(&buf->list, &vidq->active);
1039 spin_unlock_irqrestore(&dev->slock, flags);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001040}
1041
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001042static struct vb2_ops em28xx_video_qops = {
1043 .queue_setup = queue_setup,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001044 .buf_prepare = buffer_prepare,
1045 .buf_queue = buffer_queue,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001046 .start_streaming = em28xx_start_analog_streaming,
1047 .stop_streaming = em28xx_stop_streaming,
1048 .wait_prepare = vb2_ops_wait_prepare,
1049 .wait_finish = vb2_ops_wait_finish,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001050};
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001051
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001052static int em28xx_vb2_setup(struct em28xx *dev)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001053{
1054 int rc;
1055 struct vb2_queue *q;
Frank Schaefer27a36df2014-03-24 16:33:13 -03001056 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001057
1058 /* Setup Videobuf2 for Video capture */
Frank Schaefer27a36df2014-03-24 16:33:13 -03001059 q = &v4l2->vb_vidq;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001060 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Mauro Carvalho Chehabef85cd92013-01-06 00:34:22 -02001061 q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
Sakari Ailusade48682014-02-25 19:12:19 -03001062 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001063 q->drv_priv = dev;
1064 q->buf_struct_size = sizeof(struct em28xx_buffer);
1065 q->ops = &em28xx_video_qops;
1066 q->mem_ops = &vb2_vmalloc_memops;
1067
1068 rc = vb2_queue_init(q);
1069 if (rc < 0)
1070 return rc;
1071
1072 /* Setup Videobuf2 for VBI capture */
Frank Schaefer27a36df2014-03-24 16:33:13 -03001073 q = &v4l2->vb_vbiq;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001074 q->type = V4L2_BUF_TYPE_VBI_CAPTURE;
1075 q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR;
Sakari Ailusade48682014-02-25 19:12:19 -03001076 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001077 q->drv_priv = dev;
1078 q->buf_struct_size = sizeof(struct em28xx_buffer);
1079 q->ops = &em28xx_vbi_qops;
1080 q->mem_ops = &vb2_vmalloc_memops;
1081
1082 rc = vb2_queue_init(q);
1083 if (rc < 0)
1084 return rc;
1085
1086 return 0;
1087}
1088
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001089/********************* v4l2 interface **************************************/
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001090
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001091static void video_mux(struct em28xx *dev, int index)
1092{
Frank Schaefer95d26082014-03-24 16:33:09 -03001093 struct v4l2_device *v4l2_dev = &dev->v4l2->v4l2_dev;
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001094 dev->ctl_input = index;
1095 dev->ctl_ainput = INPUT(index)->amux;
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001096 dev->ctl_aoutput = INPUT(index)->aout;
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001097
Mauro Carvalho Chehabe879b8e2008-11-20 13:39:39 -03001098 if (!dev->ctl_aoutput)
1099 dev->ctl_aoutput = EM28XX_AOUT_MASTER;
1100
Frank Schaefer95d26082014-03-24 16:33:09 -03001101 v4l2_device_call_all(v4l2_dev, 0, video, s_routing,
Hans Verkuil5325b422009-04-02 11:26:22 -03001102 INPUT(index)->vmux, 0, 0);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001103
Mauro Carvalho Chehab505b6d02008-11-25 09:39:50 -03001104 if (dev->board.has_msp34xx) {
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001105 if (dev->i2s_speed) {
Frank Schaefer95d26082014-03-24 16:33:09 -03001106 v4l2_device_call_all(v4l2_dev, 0, audio,
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03001107 s_i2s_clock_freq, dev->i2s_speed);
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001108 }
Hans Verkuil2474ed42006-03-19 12:35:57 -03001109 /* Note: this is msp3400 specific */
Frank Schaefer95d26082014-03-24 16:33:09 -03001110 v4l2_device_call_all(v4l2_dev, 0, audio, s_routing,
Hans Verkuil5325b422009-04-02 11:26:22 -03001111 dev->ctl_ainput, MSP_OUTPUT(MSP_SC_IN_DSP_SCART1), 0);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001112 }
Mauro Carvalho Chehab539c96d2008-01-05 09:53:54 -03001113
Vitaly Wool2bd1d9e2009-03-04 08:27:52 -03001114 if (dev->board.adecoder != EM28XX_NOADECODER) {
Frank Schaefer95d26082014-03-24 16:33:09 -03001115 v4l2_device_call_all(v4l2_dev, 0, audio, s_routing,
Hans Verkuil5325b422009-04-02 11:26:22 -03001116 dev->ctl_ainput, dev->ctl_aoutput, 0);
Vitaly Wool2bd1d9e2009-03-04 08:27:52 -03001117 }
1118
Mauro Carvalho Chehab00b87302008-02-06 18:34:13 -03001119 em28xx_audio_analog_set(dev);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001120}
1121
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001122static void em28xx_ctrl_notify(struct v4l2_ctrl *ctrl, void *priv)
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001123{
Hans Verkuil081b9452012-09-07 05:43:59 -03001124 struct em28xx *dev = priv;
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001125
Hans Verkuil081b9452012-09-07 05:43:59 -03001126 /*
1127 * In the case of non-AC97 volume controls, we still need
1128 * to do some setups at em28xx, in order to mute/unmute
1129 * and to adjust audio volume. However, the value ranges
1130 * should be checked by the corresponding V4L subdriver.
1131 */
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001132 switch (ctrl->id) {
1133 case V4L2_CID_AUDIO_MUTE:
Hans Verkuil081b9452012-09-07 05:43:59 -03001134 dev->mute = ctrl->val;
1135 em28xx_audio_analog_set(dev);
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001136 break;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001137 case V4L2_CID_AUDIO_VOLUME:
Hans Verkuil081b9452012-09-07 05:43:59 -03001138 dev->volume = ctrl->val;
1139 em28xx_audio_analog_set(dev);
1140 break;
1141 }
1142}
1143
1144static int em28xx_s_ctrl(struct v4l2_ctrl *ctrl)
1145{
Frank Schaeferabc13082014-03-24 16:33:10 -03001146 struct em28xx_v4l2 *v4l2 =
1147 container_of(ctrl->handler, struct em28xx_v4l2, ctrl_handler);
1148 struct em28xx *dev = v4l2->dev;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001149 int ret = -EINVAL;
Hans Verkuil081b9452012-09-07 05:43:59 -03001150
1151 switch (ctrl->id) {
1152 case V4L2_CID_AUDIO_MUTE:
1153 dev->mute = ctrl->val;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001154 ret = em28xx_audio_analog_set(dev);
Hans Verkuil081b9452012-09-07 05:43:59 -03001155 break;
1156 case V4L2_CID_AUDIO_VOLUME:
1157 dev->volume = ctrl->val;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001158 ret = em28xx_audio_analog_set(dev);
1159 break;
1160 case V4L2_CID_CONTRAST:
1161 ret = em28xx_write_reg(dev, EM28XX_R20_YGAIN, ctrl->val);
1162 break;
1163 case V4L2_CID_BRIGHTNESS:
1164 ret = em28xx_write_reg(dev, EM28XX_R21_YOFFSET, ctrl->val);
1165 break;
1166 case V4L2_CID_SATURATION:
1167 ret = em28xx_write_reg(dev, EM28XX_R22_UVGAIN, ctrl->val);
1168 break;
1169 case V4L2_CID_BLUE_BALANCE:
1170 ret = em28xx_write_reg(dev, EM28XX_R23_UOFFSET, ctrl->val);
1171 break;
1172 case V4L2_CID_RED_BALANCE:
1173 ret = em28xx_write_reg(dev, EM28XX_R24_VOFFSET, ctrl->val);
1174 break;
1175 case V4L2_CID_SHARPNESS:
1176 ret = em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, ctrl->val);
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001177 break;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001178 }
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001179
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001180 return (ret < 0) ? ret : 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001181}
1182
Fengguang Wu8068eb82014-01-07 12:50:47 -03001183static const struct v4l2_ctrl_ops em28xx_ctrl_ops = {
Hans Verkuil081b9452012-09-07 05:43:59 -03001184 .s_ctrl = em28xx_s_ctrl,
1185};
1186
Frank Schaefer6b09a212013-02-10 16:05:12 -03001187static void size_to_scale(struct em28xx *dev,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001188 unsigned int width, unsigned int height,
1189 unsigned int *hscale, unsigned int *vscale)
1190{
Mauro Carvalho Chehab55699962009-07-13 20:15:02 -03001191 unsigned int maxw = norm_maxw(dev);
1192 unsigned int maxh = norm_maxh(dev);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001193
1194 *hscale = (((unsigned long)maxw) << 12) / width - 4096L;
Frank Schaefer81685322013-02-10 16:05:11 -03001195 if (*hscale > EM28XX_HVSCALE_MAX)
1196 *hscale = EM28XX_HVSCALE_MAX;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001197
1198 *vscale = (((unsigned long)maxh) << 12) / height - 4096L;
Frank Schaefer81685322013-02-10 16:05:11 -03001199 if (*vscale > EM28XX_HVSCALE_MAX)
1200 *vscale = EM28XX_HVSCALE_MAX;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001201}
1202
Frank Schaeferb8374132013-02-10 16:05:13 -03001203static void scale_to_size(struct em28xx *dev,
1204 unsigned int hscale, unsigned int vscale,
1205 unsigned int *width, unsigned int *height)
1206{
1207 unsigned int maxw = norm_maxw(dev);
1208 unsigned int maxh = norm_maxh(dev);
1209
1210 *width = (((unsigned long)maxw) << 12) / (hscale + 4096L);
1211 *height = (((unsigned long)maxh) << 12) / (vscale + 4096L);
1212}
1213
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001214/* ------------------------------------------------------------------
1215 IOCTL vidioc handling
1216 ------------------------------------------------------------------*/
1217
Hans Verkuil78b526a2008-05-28 12:16:41 -03001218static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001219 struct v4l2_format *f)
1220{
1221 struct em28xx_fh *fh = priv;
1222 struct em28xx *dev = fh->dev;
Frank Schaefer753aee72014-03-24 16:33:14 -03001223 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001224
Frank Schaefer753aee72014-03-24 16:33:14 -03001225 f->fmt.pix.width = v4l2->width;
1226 f->fmt.pix.height = v4l2->height;
Frank Schaefer06e20672014-03-24 16:33:17 -03001227 f->fmt.pix.pixelformat = v4l2->format->fourcc;
1228 f->fmt.pix.bytesperline = (v4l2->width * v4l2->format->depth + 7) >> 3;
Frank Schaefer753aee72014-03-24 16:33:14 -03001229 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * v4l2->height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001230 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
1231
1232 /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -03001233 if (dev->progressive)
1234 f->fmt.pix.field = V4L2_FIELD_NONE;
1235 else
1236 f->fmt.pix.field = dev->interlaced ?
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001237 V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001238 return 0;
1239}
1240
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001241static struct em28xx_fmt *format_by_fourcc(unsigned int fourcc)
1242{
1243 unsigned int i;
1244
1245 for (i = 0; i < ARRAY_SIZE(format); i++)
1246 if (format[i].fourcc == fourcc)
1247 return &format[i];
1248
1249 return NULL;
1250}
1251
Hans Verkuil78b526a2008-05-28 12:16:41 -03001252static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001253 struct v4l2_format *f)
1254{
1255 struct em28xx_fh *fh = priv;
1256 struct em28xx *dev = fh->dev;
Trent Piephoccb83402009-05-30 21:45:46 -03001257 unsigned int width = f->fmt.pix.width;
1258 unsigned int height = f->fmt.pix.height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001259 unsigned int maxw = norm_maxw(dev);
1260 unsigned int maxh = norm_maxh(dev);
1261 unsigned int hscale, vscale;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001262 struct em28xx_fmt *fmt;
1263
1264 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
1265 if (!fmt) {
1266 em28xx_videodbg("Fourcc format (%08x) invalid.\n",
1267 f->fmt.pix.pixelformat);
1268 return -EINVAL;
1269 }
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001270
Mauro Carvalho Chehab55699962009-07-13 20:15:02 -03001271 if (dev->board.is_em2800) {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001272 /* the em2800 can only scale down to 50% */
Trent Piephoccb83402009-05-30 21:45:46 -03001273 height = height > (3 * maxh / 4) ? maxh : maxh / 2;
1274 width = width > (3 * maxw / 4) ? maxw : maxw / 2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001275 /*
1276 * MaxPacketSize for em2800 is too small to capture at full
1277 * resolution use half of maxw as the scaler can only scale
1278 * to 50%
1279 */
Sascha Sommer1020d132012-01-08 16:54:28 -03001280 if (width == maxw && height == maxh)
1281 width /= 2;
Trent Piephoccb83402009-05-30 21:45:46 -03001282 } else {
1283 /* width must even because of the YUYV format
1284 height must be even because of interlacing */
Devin Heitmuellere3ba4d32009-09-15 00:18:06 -03001285 v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh,
1286 1, 0);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001287 }
1288
Frank Schaefer6b09a212013-02-10 16:05:12 -03001289 size_to_scale(dev, width, height, &hscale, &vscale);
Hans Verkuil46f85972013-03-30 05:31:42 -03001290 scale_to_size(dev, hscale, vscale, &width, &height);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001291
1292 f->fmt.pix.width = width;
1293 f->fmt.pix.height = height;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001294 f->fmt.pix.pixelformat = fmt->fourcc;
Hans Verkuile6066db2013-02-06 08:14:47 -03001295 f->fmt.pix.bytesperline = (width * fmt->depth + 7) >> 3;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001296 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001297 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -03001298 if (dev->progressive)
1299 f->fmt.pix.field = V4L2_FIELD_NONE;
1300 else
1301 f->fmt.pix.field = dev->interlaced ?
1302 V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
Alban Browaeys51dd4d72013-07-16 19:06:46 -03001303 f->fmt.pix.priv = 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001304
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001305 return 0;
1306}
1307
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001308static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc,
1309 unsigned width, unsigned height)
1310{
1311 struct em28xx_fmt *fmt;
Frank Schaefer753aee72014-03-24 16:33:14 -03001312 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001313
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001314 fmt = format_by_fourcc(fourcc);
1315 if (!fmt)
1316 return -EINVAL;
1317
Frank Schaefer06e20672014-03-24 16:33:17 -03001318 v4l2->format = fmt;
Frank Schaefer753aee72014-03-24 16:33:14 -03001319 v4l2->width = width;
1320 v4l2->height = height;
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001321
1322 /* set new image size */
Frank Schaefer753aee72014-03-24 16:33:14 -03001323 size_to_scale(dev, v4l2->width, v4l2->height,
1324 &v4l2->hscale, &v4l2->vscale);
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001325
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001326 em28xx_resolution_set(dev);
1327
1328 return 0;
1329}
1330
Hans Verkuil78b526a2008-05-28 12:16:41 -03001331static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001332 struct v4l2_format *f)
1333{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001334 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001335
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001336 if (dev->streaming_users > 0)
1337 return -EBUSY;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001338
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001339 vidioc_try_fmt_vid_cap(file, priv, f);
1340
Hans Verkuil0499a5a2010-09-26 07:34:45 -03001341 return em28xx_set_video_format(dev, f->fmt.pix.pixelformat,
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001342 f->fmt.pix.width, f->fmt.pix.height);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001343}
1344
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001345static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
1346{
1347 struct em28xx_fh *fh = priv;
1348 struct em28xx *dev = fh->dev;
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001349
Frank Schaefer52faaf72014-03-24 16:33:16 -03001350 *norm = dev->v4l2->norm;
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001351
1352 return 0;
1353}
1354
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001355static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm)
1356{
1357 struct em28xx_fh *fh = priv;
1358 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001359
Frank Schaefer95d26082014-03-24 16:33:09 -03001360 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, video, querystd, norm);
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001361
1362 return 0;
1363}
1364
Hans Verkuil314527a2013-03-15 06:10:40 -03001365static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001366{
Frank Schaefer753aee72014-03-24 16:33:14 -03001367 struct em28xx_fh *fh = priv;
1368 struct em28xx *dev = fh->dev;
1369 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001370 struct v4l2_format f;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001371
Frank Schaefer52faaf72014-03-24 16:33:16 -03001372 if (norm == v4l2->norm)
Hans Verkuild8c95c02012-09-07 07:31:54 -03001373 return 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001374
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001375 if (dev->streaming_users > 0)
Hans Verkuild8c95c02012-09-07 07:31:54 -03001376 return -EBUSY;
Hans Verkuild8c95c02012-09-07 07:31:54 -03001377
Frank Schaefer52faaf72014-03-24 16:33:16 -03001378 v4l2->norm = norm;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001379
1380 /* Adjusts width/height, if needed */
Hans Verkuild8c95c02012-09-07 07:31:54 -03001381 f.fmt.pix.width = 720;
Hans Verkuil314527a2013-03-15 06:10:40 -03001382 f.fmt.pix.height = (norm & V4L2_STD_525_60) ? 480 : 576;
Hans Verkuil78b526a2008-05-28 12:16:41 -03001383 vidioc_try_fmt_vid_cap(file, priv, &f);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001384
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001385 /* set new image size */
Frank Schaefer753aee72014-03-24 16:33:14 -03001386 v4l2->width = f.fmt.pix.width;
1387 v4l2->height = f.fmt.pix.height;
1388 size_to_scale(dev, v4l2->width, v4l2->height,
1389 &v4l2->hscale, &v4l2->vscale);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001390
1391 em28xx_resolution_set(dev);
Frank Schaefer52faaf72014-03-24 16:33:16 -03001392 v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_std, v4l2->norm);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001393
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001394 return 0;
1395}
1396
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001397static int vidioc_g_parm(struct file *file, void *priv,
1398 struct v4l2_streamparm *p)
1399{
Frank Schaefer52faaf72014-03-24 16:33:16 -03001400 struct em28xx_fh *fh = priv;
1401 struct em28xx *dev = fh->dev;
1402 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001403 int rc = 0;
1404
Hans Verkuil86ff7f12012-09-07 06:16:03 -03001405 p->parm.capture.readbuffers = EM28XX_MIN_BUF;
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001406 if (dev->board.is_webcam)
Frank Schaefer52faaf72014-03-24 16:33:16 -03001407 rc = v4l2_device_call_until_err(&v4l2->v4l2_dev, 0,
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001408 video, g_parm, p);
1409 else
Frank Schaefer52faaf72014-03-24 16:33:16 -03001410 v4l2_video_std_frame_period(v4l2->norm,
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001411 &p->parm.capture.timeperframe);
1412
1413 return rc;
1414}
1415
1416static int vidioc_s_parm(struct file *file, void *priv,
1417 struct v4l2_streamparm *p)
1418{
1419 struct em28xx_fh *fh = priv;
1420 struct em28xx *dev = fh->dev;
1421
Hans Verkuil86ff7f12012-09-07 06:16:03 -03001422 p->parm.capture.readbuffers = EM28XX_MIN_BUF;
Frank Schaefer95d26082014-03-24 16:33:09 -03001423 return v4l2_device_call_until_err(&dev->v4l2->v4l2_dev,
1424 0, video, s_parm, p);
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001425}
1426
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001427static const char *iname[] = {
1428 [EM28XX_VMUX_COMPOSITE1] = "Composite1",
1429 [EM28XX_VMUX_COMPOSITE2] = "Composite2",
1430 [EM28XX_VMUX_COMPOSITE3] = "Composite3",
1431 [EM28XX_VMUX_COMPOSITE4] = "Composite4",
1432 [EM28XX_VMUX_SVIDEO] = "S-Video",
1433 [EM28XX_VMUX_TELEVISION] = "Television",
1434 [EM28XX_VMUX_CABLE] = "Cable TV",
1435 [EM28XX_VMUX_DVB] = "DVB",
1436 [EM28XX_VMUX_DEBUG] = "for debug only",
1437};
1438
1439static int vidioc_enum_input(struct file *file, void *priv,
1440 struct v4l2_input *i)
1441{
1442 struct em28xx_fh *fh = priv;
1443 struct em28xx *dev = fh->dev;
1444 unsigned int n;
1445
1446 n = i->index;
1447 if (n >= MAX_EM28XX_INPUT)
1448 return -EINVAL;
1449 if (0 == INPUT(n)->type)
1450 return -EINVAL;
1451
1452 i->index = n;
1453 i->type = V4L2_INPUT_TYPE_CAMERA;
1454
1455 strcpy(i->name, iname[INPUT(n)->type]);
1456
1457 if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type) ||
1458 (EM28XX_VMUX_CABLE == INPUT(n)->type))
1459 i->type = V4L2_INPUT_TYPE_TUNER;
1460
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001461 i->std = dev->v4l2->vdev->tvnorms;
Hans Verkuild8c95c02012-09-07 07:31:54 -03001462 /* webcams do not have the STD API */
1463 if (dev->board.is_webcam)
1464 i->capabilities = 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001465
1466 return 0;
1467}
1468
1469static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1470{
1471 struct em28xx_fh *fh = priv;
1472 struct em28xx *dev = fh->dev;
1473
1474 *i = dev->ctl_input;
1475
1476 return 0;
1477}
1478
1479static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
1480{
1481 struct em28xx_fh *fh = priv;
1482 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001483
1484 if (i >= MAX_EM28XX_INPUT)
1485 return -EINVAL;
1486 if (0 == INPUT(i)->type)
1487 return -EINVAL;
1488
Ezequiel García96371fc2012-03-23 18:09:34 -03001489 video_mux(dev, i);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001490 return 0;
1491}
1492
1493static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
1494{
1495 struct em28xx_fh *fh = priv;
1496 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001497
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001498 switch (a->index) {
1499 case EM28XX_AMUX_VIDEO:
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001500 strcpy(a->name, "Television");
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001501 break;
1502 case EM28XX_AMUX_LINE_IN:
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001503 strcpy(a->name, "Line In");
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001504 break;
1505 case EM28XX_AMUX_VIDEO2:
1506 strcpy(a->name, "Television alt");
1507 break;
1508 case EM28XX_AMUX_PHONE:
1509 strcpy(a->name, "Phone");
1510 break;
1511 case EM28XX_AMUX_MIC:
1512 strcpy(a->name, "Mic");
1513 break;
1514 case EM28XX_AMUX_CD:
1515 strcpy(a->name, "CD");
1516 break;
1517 case EM28XX_AMUX_AUX:
1518 strcpy(a->name, "Aux");
1519 break;
1520 case EM28XX_AMUX_PCM_OUT:
1521 strcpy(a->name, "PCM");
1522 break;
1523 default:
1524 return -EINVAL;
1525 }
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001526
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001527 a->index = dev->ctl_ainput;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001528 a->capability = V4L2_AUDCAP_STEREO;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001529
1530 return 0;
1531}
1532
Hans Verkuil0e8025b92012-09-04 11:59:31 -03001533static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001534{
1535 struct em28xx_fh *fh = priv;
1536 struct em28xx *dev = fh->dev;
1537
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03001538 if (a->index >= MAX_EM28XX_INPUT)
1539 return -EINVAL;
1540 if (0 == INPUT(a->index)->type)
1541 return -EINVAL;
1542
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001543 dev->ctl_ainput = INPUT(a->index)->amux;
1544 dev->ctl_aoutput = INPUT(a->index)->aout;
Mauro Carvalho Chehabe879b8e2008-11-20 13:39:39 -03001545
1546 if (!dev->ctl_aoutput)
1547 dev->ctl_aoutput = EM28XX_AOUT_MASTER;
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001548
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001549 return 0;
1550}
1551
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001552static int vidioc_g_tuner(struct file *file, void *priv,
1553 struct v4l2_tuner *t)
1554{
1555 struct em28xx_fh *fh = priv;
1556 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001557
1558 if (0 != t->index)
1559 return -EINVAL;
1560
1561 strcpy(t->name, "Tuner");
1562
Frank Schaefer95d26082014-03-24 16:33:09 -03001563 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, g_tuner, t);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001564 return 0;
1565}
1566
1567static int vidioc_s_tuner(struct file *file, void *priv,
Hans Verkuil2f73c7c2013-03-15 06:10:06 -03001568 const struct v4l2_tuner *t)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001569{
1570 struct em28xx_fh *fh = priv;
1571 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001572
1573 if (0 != t->index)
1574 return -EINVAL;
1575
Frank Schaefer95d26082014-03-24 16:33:09 -03001576 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, s_tuner, t);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001577 return 0;
1578}
1579
1580static int vidioc_g_frequency(struct file *file, void *priv,
1581 struct v4l2_frequency *f)
1582{
1583 struct em28xx_fh *fh = priv;
1584 struct em28xx *dev = fh->dev;
1585
Hans Verkuil20deebf2012-09-06 10:07:25 -03001586 if (0 != f->tuner)
1587 return -EINVAL;
1588
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001589 f->frequency = dev->ctl_freq;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001590 return 0;
1591}
1592
1593static int vidioc_s_frequency(struct file *file, void *priv,
Hans Verkuilb530a442013-03-19 04:09:26 -03001594 const struct v4l2_frequency *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001595{
Frank Schaefer95d26082014-03-24 16:33:09 -03001596 struct v4l2_frequency new_freq = *f;
1597 struct em28xx_fh *fh = priv;
1598 struct em28xx *dev = fh->dev;
1599 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001600
1601 if (0 != f->tuner)
1602 return -EINVAL;
1603
Frank Schaefer95d26082014-03-24 16:33:09 -03001604 v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, s_frequency, f);
1605 v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, g_frequency, &new_freq);
Hans Verkuilb530a442013-03-19 04:09:26 -03001606 dev->ctl_freq = new_freq.frequency;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001607
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001608 return 0;
1609}
1610
Hans Verkuilcd634f12013-03-27 08:04:23 -03001611#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuil96b03d22013-04-06 06:16:58 -03001612static int vidioc_g_chip_info(struct file *file, void *priv,
1613 struct v4l2_dbg_chip_info *chip)
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001614{
1615 struct em28xx_fh *fh = priv;
1616 struct em28xx *dev = fh->dev;
1617
1618 if (chip->match.addr > 1)
1619 return -EINVAL;
1620 if (chip->match.addr == 1)
1621 strlcpy(chip->name, "ac97", sizeof(chip->name));
1622 else
Frank Schaefer95d26082014-03-24 16:33:09 -03001623 strlcpy(chip->name,
1624 dev->v4l2->v4l2_dev.name, sizeof(chip->name));
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001625 return 0;
1626}
1627
Frank Schaefer35deba32013-02-07 13:39:19 -03001628static int em28xx_reg_len(int reg)
1629{
1630 switch (reg) {
1631 case EM28XX_R40_AC97LSB:
1632 case EM28XX_R30_HSCALELOW:
1633 case EM28XX_R32_VSCALELOW:
1634 return 2;
1635 default:
1636 return 1;
1637 }
1638}
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001639
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001640static int vidioc_g_register(struct file *file, void *priv,
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001641 struct v4l2_dbg_register *reg)
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001642{
1643 struct em28xx_fh *fh = priv;
1644 struct em28xx *dev = fh->dev;
1645 int ret;
1646
Hans Verkuilabca2052013-05-29 06:59:35 -03001647 if (reg->match.addr > 1)
1648 return -EINVAL;
1649 if (reg->match.addr) {
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001650 ret = em28xx_read_ac97(dev, reg->reg);
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001651 if (ret < 0)
1652 return ret;
1653
1654 reg->val = ret;
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001655 reg->size = 1;
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001656 return 0;
1657 }
1658
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001659 /* Match host */
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001660 reg->size = em28xx_reg_len(reg->reg);
1661 if (reg->size == 1) {
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001662 ret = em28xx_read_reg(dev, reg->reg);
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001663
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001664 if (ret < 0)
1665 return ret;
1666
1667 reg->val = ret;
1668 } else {
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001669 __le16 val = 0;
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001670 ret = dev->em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001671 reg->reg, (char *)&val, 2);
1672 if (ret < 0)
1673 return ret;
1674
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001675 reg->val = le16_to_cpu(val);
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001676 }
1677
1678 return 0;
1679}
1680
1681static int vidioc_s_register(struct file *file, void *priv,
Hans Verkuil977ba3b2013-03-24 08:28:46 -03001682 const struct v4l2_dbg_register *reg)
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001683{
1684 struct em28xx_fh *fh = priv;
1685 struct em28xx *dev = fh->dev;
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001686 __le16 buf;
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001687
Hans Verkuilabca2052013-05-29 06:59:35 -03001688 if (reg->match.addr > 1)
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001689 return -EINVAL;
Hans Verkuilabca2052013-05-29 06:59:35 -03001690 if (reg->match.addr)
1691 return em28xx_write_ac97(dev, reg->reg, reg->val);
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001692
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001693 /* Match host */
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001694 buf = cpu_to_le16(reg->val);
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001695
Hans Verkuil0499a5a2010-09-26 07:34:45 -03001696 return em28xx_write_regs(dev, reg->reg, (char *)&buf,
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001697 em28xx_reg_len(reg->reg));
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001698}
1699#endif
1700
1701
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001702static int vidioc_querycap(struct file *file, void *priv,
1703 struct v4l2_capability *cap)
1704{
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001705 struct video_device *vdev = video_devdata(file);
1706 struct em28xx_fh *fh = priv;
1707 struct em28xx *dev = fh->dev;
1708 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001709
1710 strlcpy(cap->driver, "em28xx", sizeof(cap->driver));
1711 strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card));
Thierry MERLEcb977162009-01-20 18:01:33 -03001712 usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001713
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001714 if (vdev->vfl_type == VFL_TYPE_GRABBER)
1715 cap->device_caps = V4L2_CAP_READWRITE |
1716 V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1717 else if (vdev->vfl_type == VFL_TYPE_RADIO)
1718 cap->device_caps = V4L2_CAP_RADIO;
1719 else
Hans Verkuil1d179ee2012-09-07 08:45:10 -03001720 cap->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE;
Devin Heitmueller04146142009-09-11 00:08:44 -03001721
Mauro Carvalho Chehab6c428b52009-08-04 19:52:37 -03001722 if (dev->audio_mode.has_audio)
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001723 cap->device_caps |= V4L2_CAP_AUDIO;
Mauro Carvalho Chehab6c428b52009-08-04 19:52:37 -03001724
Mauro Carvalho Chehabed086312008-01-24 06:59:20 -03001725 if (dev->tuner_type != TUNER_ABSENT)
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001726 cap->device_caps |= V4L2_CAP_TUNER;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001727
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001728 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS |
1729 V4L2_CAP_READWRITE | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001730 if (v4l2->vbi_dev)
Hans Verkuil1d179ee2012-09-07 08:45:10 -03001731 cap->capabilities |= V4L2_CAP_VBI_CAPTURE;
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001732 if (v4l2->radio_dev)
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001733 cap->capabilities |= V4L2_CAP_RADIO;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001734 return 0;
1735}
1736
Hans Verkuil78b526a2008-05-28 12:16:41 -03001737static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001738 struct v4l2_fmtdesc *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001739{
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001740 if (unlikely(f->index >= ARRAY_SIZE(format)))
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001741 return -EINVAL;
1742
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001743 strlcpy(f->description, format[f->index].name, sizeof(f->description));
1744 f->pixelformat = format[f->index].fourcc;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001745
1746 return 0;
1747}
1748
Mauro Carvalho Chehab1c5c50682011-10-16 13:52:43 -02001749static int vidioc_enum_framesizes(struct file *file, void *priv,
1750 struct v4l2_frmsizeenum *fsize)
1751{
1752 struct em28xx_fh *fh = priv;
1753 struct em28xx *dev = fh->dev;
1754 struct em28xx_fmt *fmt;
1755 unsigned int maxw = norm_maxw(dev);
1756 unsigned int maxh = norm_maxh(dev);
1757
1758 fmt = format_by_fourcc(fsize->pixel_format);
1759 if (!fmt) {
1760 em28xx_videodbg("Fourcc format (%08x) invalid.\n",
1761 fsize->pixel_format);
1762 return -EINVAL;
1763 }
1764
1765 if (dev->board.is_em2800) {
1766 if (fsize->index > 1)
1767 return -EINVAL;
1768 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
1769 fsize->discrete.width = maxw / (1 + fsize->index);
1770 fsize->discrete.height = maxh / (1 + fsize->index);
1771 return 0;
1772 }
1773
1774 if (fsize->index != 0)
1775 return -EINVAL;
1776
1777 /* Report a continuous range */
1778 fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
Frank Schaefer6c3598e2013-02-10 16:05:14 -03001779 scale_to_size(dev, EM28XX_HVSCALE_MAX, EM28XX_HVSCALE_MAX,
1780 &fsize->stepwise.min_width, &fsize->stepwise.min_height);
1781 if (fsize->stepwise.min_width < 48)
1782 fsize->stepwise.min_width = 48;
1783 if (fsize->stepwise.min_height < 38)
1784 fsize->stepwise.min_height = 38;
Mauro Carvalho Chehab1c5c50682011-10-16 13:52:43 -02001785 fsize->stepwise.max_width = maxw;
1786 fsize->stepwise.max_height = maxh;
1787 fsize->stepwise.step_width = 1;
1788 fsize->stepwise.step_height = 1;
1789 return 0;
1790}
1791
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001792/* RAW VBI ioctls */
1793
1794static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
1795 struct v4l2_format *format)
1796{
Frank Schaefer753aee72014-03-24 16:33:14 -03001797 struct em28xx_fh *fh = priv;
1798 struct em28xx *dev = fh->dev;
1799 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001800
Frank Schaefer753aee72014-03-24 16:33:14 -03001801 format->fmt.vbi.samples_per_line = v4l2->vbi_width;
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001802 format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
1803 format->fmt.vbi.offset = 0;
1804 format->fmt.vbi.flags = 0;
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001805 format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
Frank Schaefer753aee72014-03-24 16:33:14 -03001806 format->fmt.vbi.count[0] = v4l2->vbi_height;
1807 format->fmt.vbi.count[1] = v4l2->vbi_height;
Hans Verkuil2a221d32012-09-07 08:51:32 -03001808 memset(format->fmt.vbi.reserved, 0, sizeof(format->fmt.vbi.reserved));
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001809
1810 /* Varies by video standard (NTSC, PAL, etc.) */
Frank Schaefer52faaf72014-03-24 16:33:16 -03001811 if (v4l2->norm & V4L2_STD_525_60) {
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001812 /* NTSC */
1813 format->fmt.vbi.start[0] = 10;
1814 format->fmt.vbi.start[1] = 273;
Frank Schaefer52faaf72014-03-24 16:33:16 -03001815 } else if (v4l2->norm & V4L2_STD_625_50) {
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001816 /* PAL */
1817 format->fmt.vbi.start[0] = 6;
1818 format->fmt.vbi.start[1] = 318;
1819 }
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001820
1821 return 0;
1822}
1823
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001824/* ----------------------------------------------------------- */
1825/* RADIO ESPECIFIC IOCTLS */
1826/* ----------------------------------------------------------- */
1827
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001828static int radio_g_tuner(struct file *file, void *priv,
1829 struct v4l2_tuner *t)
1830{
1831 struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;
1832
1833 if (unlikely(t->index > 0))
1834 return -EINVAL;
1835
1836 strcpy(t->name, "Radio");
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001837
Frank Schaefer95d26082014-03-24 16:33:09 -03001838 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, g_tuner, t);
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001839
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001840 return 0;
1841}
1842
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001843static int radio_s_tuner(struct file *file, void *priv,
Hans Verkuil2f73c7c2013-03-15 06:10:06 -03001844 const struct v4l2_tuner *t)
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001845{
1846 struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;
1847
1848 if (0 != t->index)
1849 return -EINVAL;
1850
Frank Schaefer95d26082014-03-24 16:33:09 -03001851 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, s_tuner, t);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001852
1853 return 0;
1854}
1855
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001856/*
Frank Schaefer95d26082014-03-24 16:33:09 -03001857 * em28xx_free_v4l2() - Free struct em28xx_v4l2
1858 *
1859 * @ref: struct kref for struct em28xx_v4l2
1860 *
1861 * Called when all users of struct em28xx_v4l2 are gone
1862 */
1863void em28xx_free_v4l2(struct kref *ref)
1864{
1865 struct em28xx_v4l2 *v4l2 = container_of(ref, struct em28xx_v4l2, ref);
1866
Frank Schaeferabc13082014-03-24 16:33:10 -03001867 v4l2->dev->v4l2 = NULL;
Frank Schaefer95d26082014-03-24 16:33:09 -03001868 kfree(v4l2);
1869}
1870
1871/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08001872 * em28xx_v4l2_open()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001873 * inits the device and starts isoc transfer
1874 */
Hans Verkuilbec43662008-12-30 06:58:20 -03001875static int em28xx_v4l2_open(struct file *filp)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001876{
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001877 struct video_device *vdev = video_devdata(filp);
1878 struct em28xx *dev = video_drvdata(filp);
Frank Schaefer95d26082014-03-24 16:33:09 -03001879 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001880 enum v4l2_buf_type fh_type = 0;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001881 struct em28xx_fh *fh;
Markus Rechberger9c755412005-11-08 21:37:52 -08001882
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001883 switch (vdev->vfl_type) {
1884 case VFL_TYPE_GRABBER:
1885 fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1886 break;
1887 case VFL_TYPE_VBI:
1888 fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
1889 break;
Frank Schaefer4e170242014-01-12 13:24:18 -03001890 case VFL_TYPE_RADIO:
1891 break;
1892 default:
1893 return -EINVAL;
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001894 }
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03001895
Laurent Pinchart50462eb2009-12-10 11:47:13 -02001896 em28xx_videodbg("open dev=%s type=%s users=%d\n",
1897 video_device_node_name(vdev), v4l2_type_names[fh_type],
1898 dev->users);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001899
Hans Verkuil876cb142012-06-23 08:12:47 -03001900 if (mutex_lock_interruptible(&dev->lock))
1901 return -ERESTARTSYS;
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001902 fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001903 if (!fh) {
1904 em28xx_errdev("em28xx-video.c: Out of memory?!\n");
Hans Verkuil876cb142012-06-23 08:12:47 -03001905 mutex_unlock(&dev->lock);
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001906 return -ENOMEM;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001907 }
Hans Verkuil69a61642012-09-07 05:52:40 -03001908 v4l2_fh_init(&fh->fh, vdev);
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001909 fh->dev = dev;
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001910 fh->type = fh_type;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001911 filp->private_data = fh;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001912
Frank Schaefer4e170242014-01-12 13:24:18 -03001913 if (dev->users == 0) {
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001914 em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001915
Frank Schaefer4e170242014-01-12 13:24:18 -03001916 if (vdev->vfl_type != VFL_TYPE_RADIO)
1917 em28xx_resolution_set(dev);
1918
1919 /*
1920 * Needed, since GPIO might have disabled power
1921 * of some i2c devices
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001922 */
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03001923 em28xx_wake_i2c(dev);
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02001924 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001925
1926 if (vdev->vfl_type == VFL_TYPE_RADIO) {
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001927 em28xx_videodbg("video_open: setting radio device\n");
Frank Schaefer95d26082014-03-24 16:33:09 -03001928 v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, s_radio);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001929 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001930
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03001931 kref_get(&dev->ref);
Frank Schaefer95d26082014-03-24 16:33:09 -03001932 kref_get(&v4l2->ref);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001933 dev->users++;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001934
Hans Verkuil876cb142012-06-23 08:12:47 -03001935 mutex_unlock(&dev->lock);
Hans Verkuil69a61642012-09-07 05:52:40 -03001936 v4l2_fh_add(&fh->fh);
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001937
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001938 return 0;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001939}
1940
1941/*
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001942 * em28xx_v4l2_fini()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001943 * unregisters the v4l2,i2c and usb devices
1944 * called when the device gets disconected or at module unload
1945*/
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001946static int em28xx_v4l2_fini(struct em28xx *dev)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001947{
Frank Schaefer95d26082014-03-24 16:33:09 -03001948 struct em28xx_v4l2 *v4l2 = dev->v4l2;
1949
Mauro Carvalho Chehab822b8de2014-01-06 05:27:47 -03001950 if (dev->is_audio_only) {
1951 /* Shouldn't initialize IR for this interface */
1952 return 0;
1953 }
1954
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001955 if (!dev->has_video) {
1956 /* This device does not support the v4l2 extension */
1957 return 0;
1958 }
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02001959
Frank Schaefer95d26082014-03-24 16:33:09 -03001960 if (v4l2 == NULL)
1961 return 0;
1962
Mauro Carvalho Chehabaa929ad2014-01-12 19:22:07 -03001963 em28xx_info("Closing video extension");
1964
Mauro Carvalho Chehabebbfbc22014-01-13 02:53:44 -03001965 mutex_lock(&dev->lock);
1966
Frank Schaefer95d26082014-03-24 16:33:09 -03001967 v4l2_device_disconnect(&v4l2->v4l2_dev);
Frank Schaefer5ad10de2014-01-12 13:24:21 -03001968
Frank Schaefer23e86422014-01-12 13:24:20 -03001969 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
1970
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001971 if (v4l2->radio_dev) {
Frank Schaefere8470222014-01-12 13:24:25 -03001972 em28xx_info("V4L2 device %s deregistered\n",
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001973 video_device_node_name(v4l2->radio_dev));
1974 video_unregister_device(v4l2->radio_dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001975 }
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001976 if (v4l2->vbi_dev) {
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001977 em28xx_info("V4L2 device %s deregistered\n",
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001978 video_device_node_name(v4l2->vbi_dev));
1979 video_unregister_device(v4l2->vbi_dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001980 }
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001981 if (v4l2->vdev) {
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001982 em28xx_info("V4L2 device %s deregistered\n",
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001983 video_device_node_name(v4l2->vdev));
1984 video_unregister_device(v4l2->vdev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001985 }
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001986
Frank Schaeferabc13082014-03-24 16:33:10 -03001987 v4l2_ctrl_handler_free(&v4l2->ctrl_handler);
Frank Schaefer95d26082014-03-24 16:33:09 -03001988 v4l2_device_unregister(&v4l2->v4l2_dev);
Frank Schaefer103f18a2014-01-17 14:45:30 -03001989
Frank Schaefer2c52a2f2014-03-24 16:33:11 -03001990 if (v4l2->clk) {
1991 v4l2_clk_unregister_fixed(v4l2->clk);
1992 v4l2->clk = NULL;
Frank Schaefer25dd1652014-01-12 13:24:23 -03001993 }
1994
Frank Schaefer95d26082014-03-24 16:33:09 -03001995 kref_put(&v4l2->ref, em28xx_free_v4l2);
1996
Mauro Carvalho Chehabebbfbc22014-01-13 02:53:44 -03001997 mutex_unlock(&dev->lock);
Frank Schaefer95d26082014-03-24 16:33:09 -03001998
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03001999 kref_put(&dev->ref, em28xx_free_device);
Frank Schaefer5ad10de2014-01-12 13:24:21 -03002000
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002001 return 0;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002002}
2003
Shuah Khana61f6812014-02-21 21:50:17 -03002004static int em28xx_v4l2_suspend(struct em28xx *dev)
2005{
2006 if (dev->is_audio_only)
2007 return 0;
2008
2009 if (!dev->has_video)
2010 return 0;
2011
2012 em28xx_info("Suspending video extension");
2013 em28xx_stop_urbs(dev);
2014 return 0;
2015}
2016
2017static int em28xx_v4l2_resume(struct em28xx *dev)
2018{
2019 if (dev->is_audio_only)
2020 return 0;
2021
2022 if (!dev->has_video)
2023 return 0;
2024
2025 em28xx_info("Resuming video extension");
2026 /* what do we do here */
2027 return 0;
2028}
2029
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002030/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002031 * em28xx_v4l2_close()
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03002032 * stops streaming and deallocates all resources allocated by the v4l2
2033 * calls and ioctls
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002034 */
Hans Verkuilbec43662008-12-30 06:58:20 -03002035static int em28xx_v4l2_close(struct file *filp)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002036{
Frank Schaefer95d26082014-03-24 16:33:09 -03002037 struct em28xx_fh *fh = filp->private_data;
2038 struct em28xx *dev = fh->dev;
2039 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03002040 int errCode;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002041
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08002042 em28xx_videodbg("users=%d\n", dev->users);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002043
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002044 vb2_fop_release(filp);
Ricardo Ribalda98c24dcd2013-11-06 05:39:35 -03002045 mutex_lock(&dev->lock);
Devin Heitmueller8c873d32009-09-03 00:23:27 -03002046
Devin Heitmuellere3ba4d32009-09-15 00:18:06 -03002047 if (dev->users == 1) {
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002048 /* No sense to try to write to the device */
2049 if (dev->disconnected)
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002050 goto exit;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03002051
Mauro Carvalho Chehabeb6c9632008-12-05 10:39:12 -03002052 /* Save some power by putting tuner to sleep */
Frank Schaefer95d26082014-03-24 16:33:09 -03002053 v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_power, 0);
Mauro Carvalho Chehabeb6c9632008-12-05 10:39:12 -03002054
Aidan Thorntond7aa8022008-04-13 14:38:47 -03002055 /* do this before setting alternate! */
Mauro Carvalho Chehab2fe3e2e2008-11-27 09:10:40 -03002056 em28xx_set_mode(dev, EM28XX_SUSPEND);
Aidan Thorntond7aa8022008-04-13 14:38:47 -03002057
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03002058 /* set alternate 0 */
2059 dev->alt = 0;
2060 em28xx_videodbg("setting alternate 0\n");
2061 errCode = usb_set_interface(dev->udev, 0, 0);
2062 if (errCode < 0) {
2063 em28xx_errdev("cannot change alternate number to "
2064 "0 (error=%i)\n", errCode);
2065 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002066 }
Devin Heitmueller28abf0832009-09-01 01:54:54 -03002067
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002068exit:
Frank Schaefer95d26082014-03-24 16:33:09 -03002069 kref_put(&v4l2->ref, em28xx_free_v4l2);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002070 dev->users--;
Hans Verkuil876cb142012-06-23 08:12:47 -03002071 mutex_unlock(&dev->lock);
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002072 kref_put(&dev->ref, em28xx_free_device);
2073
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002074 return 0;
2075}
2076
Hans Verkuilbec43662008-12-30 06:58:20 -03002077static const struct v4l2_file_operations em28xx_v4l_fops = {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002078 .owner = THIS_MODULE,
2079 .open = em28xx_v4l2_open,
2080 .release = em28xx_v4l2_close,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002081 .read = vb2_fop_read,
2082 .poll = vb2_fop_poll,
2083 .mmap = vb2_fop_mmap,
Hans Verkuil0499a5a2010-09-26 07:34:45 -03002084 .unlocked_ioctl = video_ioctl2,
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002085};
2086
Hans Verkuila3998102008-07-21 02:57:38 -03002087static const struct v4l2_ioctl_ops video_ioctl_ops = {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002088 .vidioc_querycap = vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03002089 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
2090 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
2091 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
2092 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Devin Heitmueller28abf0832009-09-01 01:54:54 -03002093 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Hans Verkuil2a221d32012-09-07 08:51:32 -03002094 .vidioc_try_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Frank Schaeferaab34612013-02-07 13:39:16 -03002095 .vidioc_s_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Mauro Carvalho Chehab1c5c50682011-10-16 13:52:43 -02002096 .vidioc_enum_framesizes = vidioc_enum_framesizes,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002097 .vidioc_g_audio = vidioc_g_audio,
2098 .vidioc_s_audio = vidioc_s_audio,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002099
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002100 .vidioc_reqbufs = vb2_ioctl_reqbufs,
2101 .vidioc_create_bufs = vb2_ioctl_create_bufs,
2102 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
2103 .vidioc_querybuf = vb2_ioctl_querybuf,
2104 .vidioc_qbuf = vb2_ioctl_qbuf,
2105 .vidioc_dqbuf = vb2_ioctl_dqbuf,
2106
Devin Heitmueller19bf0032009-09-11 00:40:18 -03002107 .vidioc_g_std = vidioc_g_std,
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03002108 .vidioc_querystd = vidioc_querystd,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002109 .vidioc_s_std = vidioc_s_std,
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03002110 .vidioc_g_parm = vidioc_g_parm,
2111 .vidioc_s_parm = vidioc_s_parm,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002112 .vidioc_enum_input = vidioc_enum_input,
2113 .vidioc_g_input = vidioc_g_input,
2114 .vidioc_s_input = vidioc_s_input,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002115 .vidioc_streamon = vb2_ioctl_streamon,
2116 .vidioc_streamoff = vb2_ioctl_streamoff,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002117 .vidioc_g_tuner = vidioc_g_tuner,
2118 .vidioc_s_tuner = vidioc_s_tuner,
2119 .vidioc_g_frequency = vidioc_g_frequency,
2120 .vidioc_s_frequency = vidioc_s_frequency,
Hans Verkuil50fdf402012-09-07 06:10:12 -03002121 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
2122 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002123#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuil96b03d22013-04-06 06:16:58 -03002124 .vidioc_g_chip_info = vidioc_g_chip_info,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002125 .vidioc_g_register = vidioc_g_register,
2126 .vidioc_s_register = vidioc_s_register,
2127#endif
Hans Verkuila3998102008-07-21 02:57:38 -03002128};
2129
2130static const struct video_device em28xx_video_template = {
Frank Schaefere8470222014-01-12 13:24:25 -03002131 .fops = &em28xx_v4l_fops,
2132 .ioctl_ops = &video_ioctl_ops,
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002133 .release = video_device_release,
Frank Schaefere8470222014-01-12 13:24:25 -03002134 .tvnorms = V4L2_STD_ALL,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002135};
2136
Hans Verkuilbec43662008-12-30 06:58:20 -03002137static const struct v4l2_file_operations radio_fops = {
Hans Verkuila3998102008-07-21 02:57:38 -03002138 .owner = THIS_MODULE,
2139 .open = em28xx_v4l2_open,
2140 .release = em28xx_v4l2_close,
Hans Verkuil8fd0bda2010-12-18 09:59:51 -03002141 .unlocked_ioctl = video_ioctl2,
Hans Verkuila3998102008-07-21 02:57:38 -03002142};
2143
2144static const struct v4l2_ioctl_ops radio_ioctl_ops = {
Hans Verkuila9d79fe2012-09-06 07:31:04 -03002145 .vidioc_querycap = vidioc_querycap,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002146 .vidioc_g_tuner = radio_g_tuner,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002147 .vidioc_s_tuner = radio_s_tuner,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002148 .vidioc_g_frequency = vidioc_g_frequency,
2149 .vidioc_s_frequency = vidioc_s_frequency,
Hans Verkuil50fdf402012-09-07 06:10:12 -03002150 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
2151 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002152#ifdef CONFIG_VIDEO_ADV_DEBUG
Michal Marek430c73f2013-04-16 08:06:30 -03002153 .vidioc_g_chip_info = vidioc_g_chip_info,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002154 .vidioc_g_register = vidioc_g_register,
2155 .vidioc_s_register = vidioc_s_register,
2156#endif
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002157};
2158
Hans Verkuila3998102008-07-21 02:57:38 -03002159static struct video_device em28xx_radio_template = {
Frank Schaefere8470222014-01-12 13:24:25 -03002160 .fops = &radio_fops,
2161 .ioctl_ops = &radio_ioctl_ops,
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002162 .release = video_device_release,
Hans Verkuila3998102008-07-21 02:57:38 -03002163};
2164
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002165/* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */
2166static unsigned short saa711x_addrs[] = {
2167 0x4a >> 1, 0x48 >> 1, /* SAA7111, SAA7111A and SAA7113 */
2168 0x42 >> 1, 0x40 >> 1, /* SAA7114, SAA7115 and SAA7118 */
2169 I2C_CLIENT_END };
2170
2171static unsigned short tvp5150_addrs[] = {
2172 0xb8 >> 1,
2173 0xba >> 1,
2174 I2C_CLIENT_END
2175};
2176
2177static unsigned short msp3400_addrs[] = {
2178 0x80 >> 1,
2179 0x88 >> 1,
2180 I2C_CLIENT_END
2181};
2182
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03002183/******************************** usb interface ******************************/
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002184
Adrian Bunk532fe652008-01-28 22:10:48 -03002185static struct video_device *em28xx_vdev_init(struct em28xx *dev,
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -03002186 const struct video_device *template,
2187 const char *type_name)
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002188{
2189 struct video_device *vfd;
2190
2191 vfd = video_device_alloc();
2192 if (NULL == vfd)
2193 return NULL;
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03002194
2195 *vfd = *template;
Frank Schaefer95d26082014-03-24 16:33:09 -03002196 vfd->v4l2_dev = &dev->v4l2->v4l2_dev;
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03002197 vfd->debug = video_debug;
Hans Verkuil0499a5a2010-09-26 07:34:45 -03002198 vfd->lock = &dev->lock;
Hans Verkuil69a61642012-09-07 05:52:40 -03002199 set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
Hans Verkuild8c95c02012-09-07 07:31:54 -03002200 if (dev->board.is_webcam)
2201 vfd->tvnorms = 0;
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002202
2203 snprintf(vfd->name, sizeof(vfd->name), "%s %s",
2204 dev->name, type_name);
2205
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02002206 video_set_drvdata(vfd, dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002207 return vfd;
2208}
2209
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002210static void em28xx_tuner_setup(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002211{
Frank Schaefer95d26082014-03-24 16:33:09 -03002212 struct v4l2_device *v4l2_dev = &dev->v4l2->v4l2_dev;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002213 struct tuner_setup tun_setup;
2214 struct v4l2_frequency f;
2215
2216 if (dev->tuner_type == TUNER_ABSENT)
2217 return;
2218
2219 memset(&tun_setup, 0, sizeof(tun_setup));
2220
2221 tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
2222 tun_setup.tuner_callback = em28xx_tuner_callback;
2223
2224 if (dev->board.radio.type) {
2225 tun_setup.type = dev->board.radio.type;
2226 tun_setup.addr = dev->board.radio_addr;
2227
Frank Schaefer95d26082014-03-24 16:33:09 -03002228 v4l2_device_call_all(v4l2_dev,
2229 0, tuner, s_type_addr, &tun_setup);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002230 }
2231
2232 if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type)) {
2233 tun_setup.type = dev->tuner_type;
2234 tun_setup.addr = dev->tuner_addr;
2235
Frank Schaefer95d26082014-03-24 16:33:09 -03002236 v4l2_device_call_all(v4l2_dev,
2237 0, tuner, s_type_addr, &tun_setup);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002238 }
2239
2240 if (dev->tda9887_conf) {
2241 struct v4l2_priv_tun_config tda9887_cfg;
2242
2243 tda9887_cfg.tuner = TUNER_TDA9887;
2244 tda9887_cfg.priv = &dev->tda9887_conf;
2245
Frank Schaefer95d26082014-03-24 16:33:09 -03002246 v4l2_device_call_all(v4l2_dev,
2247 0, tuner, s_config, &tda9887_cfg);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002248 }
2249
2250 if (dev->tuner_type == TUNER_XC2028) {
2251 struct v4l2_priv_tun_config xc2028_cfg;
2252 struct xc2028_ctrl ctl;
2253
2254 memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
2255 memset(&ctl, 0, sizeof(ctl));
2256
2257 em28xx_setup_xc3028(dev, &ctl);
2258
2259 xc2028_cfg.tuner = TUNER_XC2028;
2260 xc2028_cfg.priv = &ctl;
2261
Frank Schaefer95d26082014-03-24 16:33:09 -03002262 v4l2_device_call_all(v4l2_dev, 0, tuner, s_config, &xc2028_cfg);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002263 }
2264
2265 /* configure tuner */
2266 f.tuner = 0;
2267 f.type = V4L2_TUNER_ANALOG_TV;
2268 f.frequency = 9076; /* just a magic number */
2269 dev->ctl_freq = f.frequency;
Frank Schaefer95d26082014-03-24 16:33:09 -03002270 v4l2_device_call_all(v4l2_dev, 0, tuner, s_frequency, &f);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002271}
2272
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002273static int em28xx_v4l2_init(struct em28xx *dev)
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002274{
Hans Verkuil081b9452012-09-07 05:43:59 -03002275 u8 val;
Mauro Carvalho Chehab2e5ef2d2008-12-28 22:26:36 -03002276 int ret;
Sascha Sommer1020d132012-01-08 16:54:28 -03002277 unsigned int maxw;
Frank Schaeferabc13082014-03-24 16:33:10 -03002278 struct v4l2_ctrl_handler *hdl;
Frank Schaefer95d26082014-03-24 16:33:09 -03002279 struct em28xx_v4l2 *v4l2;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002280
Mauro Carvalho Chehab822b8de2014-01-06 05:27:47 -03002281 if (dev->is_audio_only) {
2282 /* Shouldn't initialize IR for this interface */
2283 return 0;
2284 }
2285
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002286 if (!dev->has_video) {
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002287 /* This device does not support the v4l2 extension */
2288 return 0;
2289 }
Mauro Carvalho Chehab2e5ef2d2008-12-28 22:26:36 -03002290
Mauro Carvalho Chehab96346142013-12-26 12:41:03 -03002291 em28xx_info("Registering V4L2 extension\n");
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002292
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002293 mutex_lock(&dev->lock);
2294
Frank Schaefer95d26082014-03-24 16:33:09 -03002295 v4l2 = kzalloc(sizeof(struct em28xx_v4l2), GFP_KERNEL);
2296 if (v4l2 == NULL) {
2297 em28xx_info("em28xx_v4l: memory allocation failed\n");
2298 mutex_unlock(&dev->lock);
2299 return -ENOMEM;
2300 }
2301 kref_init(&v4l2->ref);
Frank Schaeferabc13082014-03-24 16:33:10 -03002302 v4l2->dev = dev;
Frank Schaefer95d26082014-03-24 16:33:09 -03002303 dev->v4l2 = v4l2;
2304
2305 ret = v4l2_device_register(&dev->udev->dev, &v4l2->v4l2_dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002306 if (ret < 0) {
2307 em28xx_errdev("Call to v4l2_device_register() failed!\n");
2308 goto err;
2309 }
2310
Frank Schaeferabc13082014-03-24 16:33:10 -03002311 hdl = &v4l2->ctrl_handler;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002312 v4l2_ctrl_handler_init(hdl, 8);
Frank Schaefer95d26082014-03-24 16:33:09 -03002313 v4l2->v4l2_dev.ctrl_handler = hdl;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002314
2315 /*
2316 * Default format, used for tvp5150 or saa711x output formats
2317 */
Frank Schaefer92972852014-03-24 16:33:15 -03002318 v4l2->vinmode = 0x10;
2319 v4l2->vinctl = EM28XX_VINCTRL_INTERLACED |
2320 EM28XX_VINCTRL_CCIR656_ENABLE;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002321
2322 /* request some modules */
2323
2324 if (dev->board.has_msp34xx)
Frank Schaefer95d26082014-03-24 16:33:09 -03002325 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2326 &dev->i2c_adap[dev->def_i2c_bus],
2327 "msp3400", 0, msp3400_addrs);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002328
2329 if (dev->board.decoder == EM28XX_SAA711X)
Frank Schaefer95d26082014-03-24 16:33:09 -03002330 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2331 &dev->i2c_adap[dev->def_i2c_bus],
2332 "saa7115_auto", 0, saa711x_addrs);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002333
2334 if (dev->board.decoder == EM28XX_TVP5150)
Frank Schaefer95d26082014-03-24 16:33:09 -03002335 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2336 &dev->i2c_adap[dev->def_i2c_bus],
2337 "tvp5150", 0, tvp5150_addrs);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002338
2339 if (dev->board.adecoder == EM28XX_TVAUDIO)
Frank Schaefer95d26082014-03-24 16:33:09 -03002340 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2341 &dev->i2c_adap[dev->def_i2c_bus],
2342 "tvaudio", dev->board.tvaudio_addr, NULL);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002343
2344 /* Initialize tuner and camera */
2345
2346 if (dev->board.tuner_type != TUNER_ABSENT) {
2347 int has_demod = (dev->tda9887_conf & TDA9887_PRESENT);
2348
2349 if (dev->board.radio.type)
Frank Schaefer95d26082014-03-24 16:33:09 -03002350 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2351 &dev->i2c_adap[dev->def_i2c_bus],
2352 "tuner", dev->board.radio_addr, NULL);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002353
2354 if (has_demod)
Frank Schaefer95d26082014-03-24 16:33:09 -03002355 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002356 &dev->i2c_adap[dev->def_i2c_bus], "tuner",
2357 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
2358 if (dev->tuner_addr == 0) {
2359 enum v4l2_i2c_tuner_type type =
2360 has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV;
2361 struct v4l2_subdev *sd;
2362
Frank Schaefer95d26082014-03-24 16:33:09 -03002363 sd = v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002364 &dev->i2c_adap[dev->def_i2c_bus], "tuner",
2365 0, v4l2_i2c_tuner_addrs(type));
2366
2367 if (sd)
2368 dev->tuner_addr = v4l2_i2c_subdev_addr(sd);
2369 } else {
Frank Schaefer95d26082014-03-24 16:33:09 -03002370 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2371 &dev->i2c_adap[dev->def_i2c_bus],
2372 "tuner", dev->tuner_addr, NULL);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002373 }
2374 }
2375
2376 em28xx_tuner_setup(dev);
Frank Schaeferd86bc652014-01-17 14:45:32 -03002377 if (dev->em28xx_sensor != EM28XX_NOSENSOR)
2378 em28xx_init_camera(dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002379
2380 /* Configure audio */
2381 ret = em28xx_audio_setup(dev);
2382 if (ret < 0) {
2383 em28xx_errdev("%s: Error while setting audio - error [%d]!\n",
2384 __func__, ret);
2385 goto unregister_dev;
2386 }
2387 if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
2388 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
2389 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
2390 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
2391 V4L2_CID_AUDIO_VOLUME, 0, 0x1f, 1, 0x1f);
2392 } else {
2393 /* install the em28xx notify callback */
2394 v4l2_ctrl_notify(v4l2_ctrl_find(hdl, V4L2_CID_AUDIO_MUTE),
2395 em28xx_ctrl_notify, dev);
2396 v4l2_ctrl_notify(v4l2_ctrl_find(hdl, V4L2_CID_AUDIO_VOLUME),
2397 em28xx_ctrl_notify, dev);
2398 }
2399
2400 /* wake i2c devices */
2401 em28xx_wake_i2c(dev);
2402
2403 /* init video dma queues */
2404 INIT_LIST_HEAD(&dev->vidq.active);
2405 INIT_LIST_HEAD(&dev->vbiq.active);
2406
2407 if (dev->board.has_msp34xx) {
2408 /* Send a reset to other chips via gpio */
2409 ret = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xf7);
2410 if (ret < 0) {
2411 em28xx_errdev("%s: em28xx_write_reg - msp34xx(1) failed! error [%d]\n",
2412 __func__, ret);
2413 goto unregister_dev;
2414 }
2415 msleep(3);
2416
2417 ret = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xff);
2418 if (ret < 0) {
2419 em28xx_errdev("%s: em28xx_write_reg - msp34xx(2) failed! error [%d]\n",
2420 __func__, ret);
2421 goto unregister_dev;
2422 }
2423 msleep(3);
2424 }
2425
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002426 /* set default norm */
Frank Schaefer52faaf72014-03-24 16:33:16 -03002427 v4l2->norm = V4L2_STD_PAL;
2428 v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_std, v4l2->norm);
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002429 dev->interlaced = EM28XX_INTERLACED_DEFAULT;
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002430
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002431 /* Analog specific initialization */
Frank Schaefer06e20672014-03-24 16:33:17 -03002432 v4l2->format = &format[0];
Sascha Sommer1020d132012-01-08 16:54:28 -03002433
2434 maxw = norm_maxw(dev);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002435 /* MaxPacketSize for em2800 is too small to capture at full resolution
2436 * use half of maxw as the scaler can only scale to 50% */
2437 if (dev->board.is_em2800)
2438 maxw /= 2;
Sascha Sommer1020d132012-01-08 16:54:28 -03002439
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03002440 em28xx_set_video_format(dev, format[0].fourcc,
Sascha Sommer1020d132012-01-08 16:54:28 -03002441 maxw, norm_maxh(dev));
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03002442
Ezequiel García96371fc2012-03-23 18:09:34 -03002443 video_mux(dev, 0);
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002444
2445 /* Audio defaults */
2446 dev->mute = 1;
2447 dev->volume = 0x1f;
2448
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002449/* em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -03002450 val = (u8)em28xx_read_reg(dev, EM28XX_R0F_XCLK);
2451 em28xx_write_reg(dev, EM28XX_R0F_XCLK,
2452 (EM28XX_XCLK_AUDIO_UNMUTE | val));
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002453
2454 em28xx_set_outfmt(dev);
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002455
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002456 /* Add image controls */
2457 /* NOTE: at this point, the subdevices are already registered, so bridge
2458 * controls are only added/enabled when no subdevice provides them */
Frank Schaeferad298052014-03-24 16:33:08 -03002459 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_CONTRAST))
2460 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002461 V4L2_CID_CONTRAST,
2462 0, 0x1f, 1, CONTRAST_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002463 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_BRIGHTNESS))
2464 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002465 V4L2_CID_BRIGHTNESS,
2466 -0x80, 0x7f, 1, BRIGHTNESS_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002467 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_SATURATION))
2468 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002469 V4L2_CID_SATURATION,
2470 0, 0x1f, 1, SATURATION_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002471 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_BLUE_BALANCE))
2472 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002473 V4L2_CID_BLUE_BALANCE,
2474 -0x30, 0x30, 1, BLUE_BALANCE_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002475 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_RED_BALANCE))
2476 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002477 V4L2_CID_RED_BALANCE,
2478 -0x30, 0x30, 1, RED_BALANCE_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002479 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_SHARPNESS))
2480 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002481 V4L2_CID_SHARPNESS,
2482 0, 0x0f, 1, SHARPNESS_DEFAULT);
2483
2484 /* Reset image controls */
2485 em28xx_colorlevels_set_default(dev);
Frank Schaeferad298052014-03-24 16:33:08 -03002486 v4l2_ctrl_handler_setup(hdl);
2487 ret = hdl->error;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002488 if (ret)
2489 goto unregister_dev;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002490
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002491 /* allocate and fill video video_device struct */
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002492 v4l2->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video");
2493 if (!v4l2->vdev) {
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002494 em28xx_errdev("cannot allocate video_device.\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002495 ret = -ENODEV;
2496 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002497 }
Frank Schaefer27a36df2014-03-24 16:33:13 -03002498 mutex_init(&v4l2->vb_queue_lock);
2499 mutex_init(&v4l2->vb_vbi_queue_lock);
2500 v4l2->vdev->queue = &v4l2->vb_vidq;
2501 v4l2->vdev->queue->lock = &v4l2->vb_queue_lock;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002502
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002503 /* disable inapplicable ioctls */
2504 if (dev->board.is_webcam) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002505 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_QUERYSTD);
2506 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_G_STD);
2507 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_STD);
Frank Schaefer3bc85cc2013-02-07 13:39:12 -03002508 } else {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002509 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_PARM);
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002510 }
Frank Schaefer66df67b2013-02-07 13:39:10 -03002511 if (dev->tuner_type == TUNER_ABSENT) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002512 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_G_TUNER);
2513 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_TUNER);
2514 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_G_FREQUENCY);
2515 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_FREQUENCY);
Frank Schaefer66df67b2013-02-07 13:39:10 -03002516 }
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002517 if (!dev->audio_mode.has_audio) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002518 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_G_AUDIO);
2519 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_AUDIO);
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002520 }
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002521
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002522 /* register v4l2 video video_device */
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002523 ret = video_register_device(v4l2->vdev, VFL_TYPE_GRABBER,
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002524 video_nr[dev->devno]);
2525 if (ret) {
2526 em28xx_errdev("unable to register video device (error=%i).\n",
2527 ret);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002528 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002529 }
2530
2531 /* Allocate and fill vbi video_device struct */
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002532 if (em28xx_vbi_supported(dev) == 1) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002533 v4l2->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template,
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002534 "vbi");
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002535
Frank Schaefer27a36df2014-03-24 16:33:13 -03002536 v4l2->vbi_dev->queue = &v4l2->vb_vbiq;
2537 v4l2->vbi_dev->queue->lock = &v4l2->vb_vbi_queue_lock;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002538
Frank Schaefer66df67b2013-02-07 13:39:10 -03002539 /* disable inapplicable ioctls */
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002540 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_PARM);
Frank Schaefer66df67b2013-02-07 13:39:10 -03002541 if (dev->tuner_type == TUNER_ABSENT) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002542 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_G_TUNER);
2543 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_TUNER);
2544 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_G_FREQUENCY);
2545 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_FREQUENCY);
Frank Schaefer66df67b2013-02-07 13:39:10 -03002546 }
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002547 if (!dev->audio_mode.has_audio) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002548 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_G_AUDIO);
2549 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_AUDIO);
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002550 }
Frank Schaefer66df67b2013-02-07 13:39:10 -03002551
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002552 /* register v4l2 vbi video_device */
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002553 ret = video_register_device(v4l2->vbi_dev, VFL_TYPE_VBI,
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002554 vbi_nr[dev->devno]);
2555 if (ret < 0) {
2556 em28xx_errdev("unable to register vbi device\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002557 goto unregister_dev;
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002558 }
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002559 }
2560
2561 if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002562 v4l2->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template,
2563 "radio");
2564 if (!v4l2->radio_dev) {
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002565 em28xx_errdev("cannot allocate video_device.\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002566 ret = -ENODEV;
2567 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002568 }
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002569 ret = video_register_device(v4l2->radio_dev, VFL_TYPE_RADIO,
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002570 radio_nr[dev->devno]);
2571 if (ret < 0) {
2572 em28xx_errdev("can't register radio device\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002573 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002574 }
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002575 em28xx_info("Registered radio device as %s\n",
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002576 video_device_node_name(v4l2->radio_dev));
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002577 }
2578
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002579 em28xx_info("V4L2 video device registered as %s\n",
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002580 video_device_node_name(v4l2->vdev));
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002581
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002582 if (v4l2->vbi_dev)
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002583 em28xx_info("V4L2 VBI device registered as %s\n",
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002584 video_device_node_name(v4l2->vbi_dev));
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002585
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002586 /* Save some power by putting tuner to sleep */
Frank Schaefer95d26082014-03-24 16:33:09 -03002587 v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_power, 0);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002588
2589 /* initialize videobuf2 stuff */
2590 em28xx_vb2_setup(dev);
2591
Mauro Carvalho Chehab96346142013-12-26 12:41:03 -03002592 em28xx_info("V4L2 extension successfully initialized\n");
2593
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002594 kref_get(&dev->ref);
2595
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002596 mutex_unlock(&dev->lock);
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002597 return 0;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002598
2599unregister_dev:
Frank Schaeferabc13082014-03-24 16:33:10 -03002600 v4l2_ctrl_handler_free(&v4l2->ctrl_handler);
Frank Schaefer95d26082014-03-24 16:33:09 -03002601 v4l2_device_unregister(&v4l2->v4l2_dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002602err:
Frank Schaefer95d26082014-03-24 16:33:09 -03002603 dev->v4l2 = NULL;
2604 kref_put(&v4l2->ref, em28xx_free_v4l2);
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002605 mutex_unlock(&dev->lock);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002606 return ret;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002607}
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002608
2609static struct em28xx_ops v4l2_ops = {
2610 .id = EM28XX_V4L2,
2611 .name = "Em28xx v4l2 Extension",
2612 .init = em28xx_v4l2_init,
2613 .fini = em28xx_v4l2_fini,
Shuah Khana61f6812014-02-21 21:50:17 -03002614 .suspend = em28xx_v4l2_suspend,
2615 .resume = em28xx_v4l2_resume,
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002616};
2617
2618static int __init em28xx_video_register(void)
2619{
2620 return em28xx_register_extension(&v4l2_ops);
2621}
2622
2623static void __exit em28xx_video_unregister(void)
2624{
2625 em28xx_unregister_extension(&v4l2_ops);
2626}
2627
2628module_init(em28xx_video_register);
2629module_exit(em28xx_video_unregister);