blob: 9db219d513dbab5c5b3cf8027c3152ac38e0460e [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{
Frank Schaeferd7dc18d2014-03-24 16:33:19 -0300147 struct em28xx_v4l2 *v4l2 = dev->v4l2;
148
Frank Schaefer25c61e42014-03-22 10:01:03 -0300149 if (dev->board.is_webcam)
Frank Schaeferd7dc18d2014-03-24 16:33:19 -0300150 return v4l2->sensor_xres;
Frank Schaefer25c61e42014-03-22 10:01:03 -0300151
152 if (dev->board.max_range_640_480)
153 return 640;
154
155 return 720;
156}
157
158static inline unsigned int norm_maxh(struct em28xx *dev)
159{
Frank Schaefer52faaf72014-03-24 16:33:16 -0300160 struct em28xx_v4l2 *v4l2 = dev->v4l2;
161
Frank Schaefer25c61e42014-03-22 10:01:03 -0300162 if (dev->board.is_webcam)
Frank Schaeferd7dc18d2014-03-24 16:33:19 -0300163 return v4l2->sensor_yres;
Frank Schaefer25c61e42014-03-22 10:01:03 -0300164
165 if (dev->board.max_range_640_480)
166 return 480;
167
Frank Schaefer52faaf72014-03-24 16:33:16 -0300168 return (v4l2->norm & V4L2_STD_625_50) ? 576 : 480;
Frank Schaefer25c61e42014-03-22 10:01:03 -0300169}
170
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300171static int em28xx_vbi_supported(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300172{
173 /* Modprobe option to manually disable */
174 if (disable_vbi == 1)
175 return 0;
176
177 if (dev->board.is_webcam)
178 return 0;
179
180 /* FIXME: check subdevices for VBI support */
181
182 if (dev->chip_id == CHIP_ID_EM2860 ||
183 dev->chip_id == CHIP_ID_EM2883)
184 return 1;
185
186 /* Version of em28xx that does not support VBI */
187 return 0;
188}
189
190/*
191 * em28xx_wake_i2c()
192 * configure i2c attached devices
193 */
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300194static void em28xx_wake_i2c(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300195{
Frank Schaefer95d26082014-03-24 16:33:09 -0300196 struct v4l2_device *v4l2_dev = &dev->v4l2->v4l2_dev;
197 v4l2_device_call_all(v4l2_dev, 0, core, reset, 0);
198 v4l2_device_call_all(v4l2_dev, 0, video, s_routing,
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300199 INPUT(dev->ctl_input)->vmux, 0, 0);
Frank Schaefer95d26082014-03-24 16:33:09 -0300200 v4l2_device_call_all(v4l2_dev, 0, video, s_stream, 0);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300201}
202
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300203static int em28xx_colorlevels_set_default(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300204{
205 em28xx_write_reg(dev, EM28XX_R20_YGAIN, CONTRAST_DEFAULT);
206 em28xx_write_reg(dev, EM28XX_R21_YOFFSET, BRIGHTNESS_DEFAULT);
207 em28xx_write_reg(dev, EM28XX_R22_UVGAIN, SATURATION_DEFAULT);
208 em28xx_write_reg(dev, EM28XX_R23_UOFFSET, BLUE_BALANCE_DEFAULT);
209 em28xx_write_reg(dev, EM28XX_R24_VOFFSET, RED_BALANCE_DEFAULT);
210 em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, SHARPNESS_DEFAULT);
211
212 em28xx_write_reg(dev, EM28XX_R14_GAMMA, 0x20);
213 em28xx_write_reg(dev, EM28XX_R15_RGAIN, 0x20);
214 em28xx_write_reg(dev, EM28XX_R16_GGAIN, 0x20);
215 em28xx_write_reg(dev, EM28XX_R17_BGAIN, 0x20);
216 em28xx_write_reg(dev, EM28XX_R18_ROFFSET, 0x00);
217 em28xx_write_reg(dev, EM28XX_R19_GOFFSET, 0x00);
218 return em28xx_write_reg(dev, EM28XX_R1A_BOFFSET, 0x00);
219}
220
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300221static int em28xx_set_outfmt(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300222{
223 int ret;
224 u8 fmt, vinctrl;
Frank Schaefer753aee72014-03-24 16:33:14 -0300225 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300226
Frank Schaefer06e20672014-03-24 16:33:17 -0300227 fmt = v4l2->format->reg;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300228 if (!dev->is_em25xx)
229 fmt |= 0x20;
230 /*
231 * NOTE: it's not clear if this is really needed !
232 * The datasheets say bit 5 is a reserved bit and devices seem to work
233 * fine without it. But the Windows driver sets it for em2710/50+em28xx
234 * devices and we've always been setting it, too.
235 *
236 * em2765 (em25xx, em276x/7x/8x) devices do NOT work with this bit set,
237 * it's likely used for an additional (compressed ?) format there.
238 */
239 ret = em28xx_write_reg(dev, EM28XX_R27_OUTFMT, fmt);
240 if (ret < 0)
241 return ret;
242
Frank Schaefer92972852014-03-24 16:33:15 -0300243 ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, v4l2->vinmode);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300244 if (ret < 0)
245 return ret;
246
Frank Schaefer92972852014-03-24 16:33:15 -0300247 vinctrl = v4l2->vinctl;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300248 if (em28xx_vbi_supported(dev) == 1) {
249 vinctrl |= EM28XX_VINCTRL_VBI_RAW;
250 em28xx_write_reg(dev, EM28XX_R34_VBI_START_H, 0x00);
Frank Schaefer753aee72014-03-24 16:33:14 -0300251 em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH, v4l2->vbi_width/4);
252 em28xx_write_reg(dev, EM28XX_R37_VBI_HEIGHT, v4l2->vbi_height);
Frank Schaefer52faaf72014-03-24 16:33:16 -0300253 if (v4l2->norm & V4L2_STD_525_60) {
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300254 /* NTSC */
255 em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x09);
Frank Schaefer52faaf72014-03-24 16:33:16 -0300256 } else if (v4l2->norm & V4L2_STD_625_50) {
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300257 /* PAL */
258 em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x07);
259 }
260 }
261
262 return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctrl);
263}
264
265static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax,
266 u8 ymin, u8 ymax)
267{
268 em28xx_videodbg("em28xx Scale: (%d,%d)-(%d,%d)\n",
269 xmin, ymin, xmax, ymax);
270
271 em28xx_write_regs(dev, EM28XX_R28_XMIN, &xmin, 1);
272 em28xx_write_regs(dev, EM28XX_R29_XMAX, &xmax, 1);
273 em28xx_write_regs(dev, EM28XX_R2A_YMIN, &ymin, 1);
274 return em28xx_write_regs(dev, EM28XX_R2B_YMAX, &ymax, 1);
275}
276
277static void em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
278 u16 width, u16 height)
279{
280 u8 cwidth = width >> 2;
281 u8 cheight = height >> 2;
282 u8 overflow = (height >> 9 & 0x02) | (width >> 10 & 0x01);
283 /* NOTE: size limit: 2047x1023 = 2MPix */
284
285 em28xx_videodbg("capture area set to (%d,%d): %dx%d\n",
286 hstart, vstart,
287 ((overflow & 2) << 9 | cwidth << 2),
288 ((overflow & 1) << 10 | cheight << 2));
289
290 em28xx_write_regs(dev, EM28XX_R1C_HSTART, &hstart, 1);
291 em28xx_write_regs(dev, EM28XX_R1D_VSTART, &vstart, 1);
292 em28xx_write_regs(dev, EM28XX_R1E_CWIDTH, &cwidth, 1);
293 em28xx_write_regs(dev, EM28XX_R1F_CHEIGHT, &cheight, 1);
294 em28xx_write_regs(dev, EM28XX_R1B_OFLOW, &overflow, 1);
295
296 /* FIXME: function/meaning of these registers ? */
297 /* FIXME: align width+height to multiples of 4 ?! */
298 if (dev->is_em25xx) {
299 em28xx_write_reg(dev, 0x34, width >> 4);
300 em28xx_write_reg(dev, 0x35, height >> 4);
301 }
302}
303
304static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v)
305{
Frank Schaefercba8e9b2014-03-24 16:28:36 -0300306 u8 mode = 0x00;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300307 /* the em2800 scaler only supports scaling down to 50% */
308
309 if (dev->board.is_em2800) {
310 mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00);
311 } else {
312 u8 buf[2];
313
314 buf[0] = h;
315 buf[1] = h >> 8;
316 em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2);
317
318 buf[0] = v;
319 buf[1] = v >> 8;
320 em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2);
321 /* it seems that both H and V scalers must be active
322 to work correctly */
323 mode = (h || v) ? 0x30 : 0x00;
324 }
Frank Schaefercba8e9b2014-03-24 16:28:36 -0300325 return em28xx_write_reg(dev, EM28XX_R26_COMPR, mode);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300326}
327
328/* FIXME: this only function read values from dev */
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300329static int em28xx_resolution_set(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300330{
Frank Schaefer753aee72014-03-24 16:33:14 -0300331 struct em28xx_v4l2 *v4l2 = dev->v4l2;
332 int width = norm_maxw(dev);
333 int height = norm_maxh(dev);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300334
335 /* Properly setup VBI */
Frank Schaefer753aee72014-03-24 16:33:14 -0300336 v4l2->vbi_width = 720;
Frank Schaefer52faaf72014-03-24 16:33:16 -0300337 if (v4l2->norm & V4L2_STD_525_60)
Frank Schaefer753aee72014-03-24 16:33:14 -0300338 v4l2->vbi_height = 12;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300339 else
Frank Schaefer753aee72014-03-24 16:33:14 -0300340 v4l2->vbi_height = 18;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300341
342 em28xx_set_outfmt(dev);
343
344 em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2);
345
346 /* If we don't set the start position to 2 in VBI mode, we end up
347 with line 20/21 being YUYV encoded instead of being in 8-bit
348 greyscale. The core of the issue is that line 21 (and line 23 for
349 PAL WSS) are inside of active video region, and as a result they
350 get the pixelformatting associated with that area. So by cropping
351 it out, we end up with the same format as the rest of the VBI
352 region */
353 if (em28xx_vbi_supported(dev) == 1)
354 em28xx_capture_area_set(dev, 0, 2, width, height);
355 else
356 em28xx_capture_area_set(dev, 0, 0, width, height);
357
Frank Schaefer753aee72014-03-24 16:33:14 -0300358 return em28xx_scaler_set(dev, v4l2->hscale, v4l2->vscale);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300359}
360
361/* Set USB alternate setting for analog video */
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300362static int em28xx_set_alternate(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300363{
Frank Schaefer753aee72014-03-24 16:33:14 -0300364 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300365 int errCode;
366 int i;
Frank Schaefer753aee72014-03-24 16:33:14 -0300367 unsigned int min_pkt_size = v4l2->width * 2 + 4;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300368
369 /* NOTE: for isoc transfers, only alt settings > 0 are allowed
370 bulk transfers seem to work only with alt=0 ! */
371 dev->alt = 0;
372 if ((alt > 0) && (alt < dev->num_alt)) {
373 em28xx_videodbg("alternate forced to %d\n", dev->alt);
374 dev->alt = alt;
375 goto set_alt;
376 }
377 if (dev->analog_xfer_bulk)
378 goto set_alt;
379
380 /* When image size is bigger than a certain value,
381 the frame size should be increased, otherwise, only
382 green screen will be received.
383 */
Frank Schaefer753aee72014-03-24 16:33:14 -0300384 if (v4l2->width * 2 * v4l2->height > 720 * 240 * 2)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300385 min_pkt_size *= 2;
386
387 for (i = 0; i < dev->num_alt; i++) {
388 /* stop when the selected alt setting offers enough bandwidth */
389 if (dev->alt_max_pkt_size_isoc[i] >= min_pkt_size) {
390 dev->alt = i;
391 break;
392 /* otherwise make sure that we end up with the maximum bandwidth
393 because the min_pkt_size equation might be wrong...
394 */
395 } else if (dev->alt_max_pkt_size_isoc[i] >
396 dev->alt_max_pkt_size_isoc[dev->alt])
397 dev->alt = i;
398 }
399
400set_alt:
401 /* NOTE: for bulk transfers, we need to call usb_set_interface()
402 * even if the previous settings were the same. Otherwise streaming
403 * fails with all urbs having status = -EOVERFLOW ! */
404 if (dev->analog_xfer_bulk) {
405 dev->max_pkt_size = 512; /* USB 2.0 spec */
406 dev->packet_multiplier = EM28XX_BULK_PACKET_MULTIPLIER;
407 } else { /* isoc */
408 em28xx_videodbg("minimum isoc packet size: %u (alt=%d)\n",
409 min_pkt_size, dev->alt);
410 dev->max_pkt_size =
411 dev->alt_max_pkt_size_isoc[dev->alt];
412 dev->packet_multiplier = EM28XX_NUM_ISOC_PACKETS;
413 }
414 em28xx_videodbg("setting alternate %d with wMaxPacketSize=%u\n",
415 dev->alt, dev->max_pkt_size);
Frank Schaefer961717b2014-01-13 19:02:06 -0300416 errCode = usb_set_interface(dev->udev, dev->ifnum, dev->alt);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300417 if (errCode < 0) {
418 em28xx_errdev("cannot change alternate number to %d (error=%i)\n",
419 dev->alt, errCode);
420 return errCode;
421 }
422 return 0;
423}
424
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300425/* ------------------------------------------------------------------
426 DMA and thread functions
427 ------------------------------------------------------------------*/
428
429/*
Frank Schaefer948a49a2012-12-08 11:31:25 -0300430 * Finish the current buffer
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300431 */
Frank Schaefer948a49a2012-12-08 11:31:25 -0300432static inline void finish_buffer(struct em28xx *dev,
433 struct em28xx_buffer *buf)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300434{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300435 em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->top_field);
436
Frank Schaeferf0e38232014-03-24 16:33:20 -0300437 buf->vb.v4l2_buf.sequence = dev->v4l2->field_count++;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300438 buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
439 v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
440
441 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300442}
443
444/*
Frank Schaefer36016a32012-12-08 11:31:32 -0300445 * Copy picture data from USB buffer to videobuf buffer
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300446 */
447static void em28xx_copy_video(struct em28xx *dev,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300448 struct em28xx_buffer *buf,
Frank Schaefer36016a32012-12-08 11:31:32 -0300449 unsigned char *usb_buf,
Frank Schaefer4078d622012-12-08 11:31:29 -0300450 unsigned long len)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300451{
Frank Schaefer58159172014-03-24 16:33:18 -0300452 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300453 void *fieldstart, *startwrite, *startread;
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300454 int linesdone, currlinedone, offset, lencopy, remain;
Frank Schaefer58159172014-03-24 16:33:18 -0300455 int bytesperline = v4l2->width << 1;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300456
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300457 if (buf->pos + len > buf->length)
458 len = buf->length - buf->pos;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300459
Frank Schaefer36016a32012-12-08 11:31:32 -0300460 startread = usb_buf;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300461 remain = len;
462
Frank Schaefer58159172014-03-24 16:33:18 -0300463 if (v4l2->progressive || buf->top_field)
Frank Schaefer36016a32012-12-08 11:31:32 -0300464 fieldstart = buf->vb_buf;
Frank Schaeferc02ec712012-11-08 14:11:33 -0300465 else /* interlaced mode, even nr. of lines */
Frank Schaefer36016a32012-12-08 11:31:32 -0300466 fieldstart = buf->vb_buf + bytesperline;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300467
Frank Schaefer87325332012-12-08 11:31:27 -0300468 linesdone = buf->pos / bytesperline;
469 currlinedone = buf->pos % bytesperline;
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -0300470
Frank Schaefer58159172014-03-24 16:33:18 -0300471 if (v4l2->progressive)
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -0300472 offset = linesdone * bytesperline + currlinedone;
473 else
474 offset = linesdone * bytesperline * 2 + currlinedone;
475
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300476 startwrite = fieldstart + offset;
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300477 lencopy = bytesperline - currlinedone;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300478 lencopy = lencopy > remain ? remain : lencopy;
479
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300480 if ((char *)startwrite + lencopy > (char *)buf->vb_buf + buf->length) {
Mauro Carvalho Chehabea8df7e2008-04-13 14:39:29 -0300481 em28xx_isocdbg("Overflow of %zi bytes past buffer end (1)\n",
Frank Schaefer36016a32012-12-08 11:31:32 -0300482 ((char *)startwrite + lencopy) -
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300483 ((char *)buf->vb_buf + buf->length));
484 remain = (char *)buf->vb_buf + buf->length -
Frank Schaefer36016a32012-12-08 11:31:32 -0300485 (char *)startwrite;
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -0300486 lencopy = remain;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300487 }
Aidan Thorntone0fadfd342008-04-13 14:56:02 -0300488 if (lencopy <= 0)
489 return;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300490 memcpy(startwrite, startread, lencopy);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300491
492 remain -= lencopy;
493
494 while (remain > 0) {
Frank Schaefer58159172014-03-24 16:33:18 -0300495 if (v4l2->progressive)
Frank Schaeferc02ec712012-11-08 14:11:33 -0300496 startwrite += lencopy;
497 else
498 startwrite += lencopy + bytesperline;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300499 startread += lencopy;
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300500 if (bytesperline > remain)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300501 lencopy = remain;
502 else
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300503 lencopy = bytesperline;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300504
Frank Schaefer36016a32012-12-08 11:31:32 -0300505 if ((char *)startwrite + lencopy > (char *)buf->vb_buf +
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300506 buf->length) {
Devin Heitmuellere3ba4d32009-09-15 00:18:06 -0300507 em28xx_isocdbg("Overflow of %zi bytes past buffer end"
508 "(2)\n",
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300509 ((char *)startwrite + lencopy) -
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300510 ((char *)buf->vb_buf + buf->length));
511 lencopy = remain = (char *)buf->vb_buf + buf->length -
512 (char *)startwrite;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300513 }
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300514 if (lencopy <= 0)
515 break;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300516
517 memcpy(startwrite, startread, lencopy);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300518
519 remain -= lencopy;
520 }
521
Frank Schaefer87325332012-12-08 11:31:27 -0300522 buf->pos += len;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300523}
524
Frank Schaefer36016a32012-12-08 11:31:32 -0300525/*
526 * Copy VBI data from USB buffer to videobuf buffer
527 */
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300528static void em28xx_copy_vbi(struct em28xx *dev,
Frank Schaefer87325332012-12-08 11:31:27 -0300529 struct em28xx_buffer *buf,
Frank Schaefer36016a32012-12-08 11:31:32 -0300530 unsigned char *usb_buf,
Frank Schaefer4078d622012-12-08 11:31:29 -0300531 unsigned long len)
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300532{
Frank Schaefer36016a32012-12-08 11:31:32 -0300533 unsigned int offset;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300534
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300535 if (buf->pos + len > buf->length)
536 len = buf->length - buf->pos;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300537
Frank Schaefer87325332012-12-08 11:31:27 -0300538 offset = buf->pos;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300539 /* Make sure the bottom field populates the second half of the frame */
Frank Schaefer36016a32012-12-08 11:31:32 -0300540 if (buf->top_field == 0)
Frank Schaefer753aee72014-03-24 16:33:14 -0300541 offset += dev->v4l2->vbi_width * dev->v4l2->vbi_height;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300542
Frank Schaefer36016a32012-12-08 11:31:32 -0300543 memcpy(buf->vb_buf + offset, usb_buf, len);
Frank Schaefer87325332012-12-08 11:31:27 -0300544 buf->pos += len;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300545}
546
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300547static inline void print_err_status(struct em28xx *dev,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300548 int packet, int status)
549{
550 char *errmsg = "Unknown";
551
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300552 switch (status) {
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300553 case -ENOENT:
554 errmsg = "unlinked synchronuously";
555 break;
556 case -ECONNRESET:
557 errmsg = "unlinked asynchronuously";
558 break;
559 case -ENOSR:
560 errmsg = "Buffer error (overrun)";
561 break;
562 case -EPIPE:
563 errmsg = "Stalled (device not responding)";
564 break;
565 case -EOVERFLOW:
566 errmsg = "Babble (bad cable?)";
567 break;
568 case -EPROTO:
569 errmsg = "Bit-stuff error (bad cable?)";
570 break;
571 case -EILSEQ:
572 errmsg = "CRC/Timeout (could be anything)";
573 break;
574 case -ETIME:
575 errmsg = "Device does not respond";
576 break;
577 }
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300578 if (packet < 0) {
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300579 em28xx_isocdbg("URB status %d [%s].\n", status, errmsg);
580 } else {
581 em28xx_isocdbg("URB packet %d, status %d [%s].\n",
582 packet, status, errmsg);
583 }
584}
585
586/*
Frank Schaefer24a6d842012-12-08 11:31:24 -0300587 * get the next available buffer from dma queue
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300588 */
Frank Schaefer24a6d842012-12-08 11:31:24 -0300589static inline struct em28xx_buffer *get_next_buf(struct em28xx *dev,
590 struct em28xx_dmaqueue *dma_q)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300591{
Frank Schaefer24a6d842012-12-08 11:31:24 -0300592 struct em28xx_buffer *buf;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300593
Mauro Carvalho Chehabdbecb442008-04-13 15:08:55 -0300594 if (list_empty(&dma_q->active)) {
595 em28xx_isocdbg("No active queue to serve\n");
Frank Schaefer24a6d842012-12-08 11:31:24 -0300596 return NULL;
Mauro Carvalho Chehabdbecb442008-04-13 15:08:55 -0300597 }
598
Mauro Carvalho Chehabdbecb442008-04-13 15:08:55 -0300599 /* Get the next buffer */
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300600 buf = list_entry(dma_q->active.next, struct em28xx_buffer, list);
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300601 /* Cleans up buffer - Useful for testing for frame/URB loss */
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300602 list_del(&buf->list);
Frank Schaefer87325332012-12-08 11:31:27 -0300603 buf->pos = 0;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300604 buf->vb_buf = buf->mem;
Mauro Carvalho Chehabcb784722008-04-13 15:06:52 -0300605
Frank Schaefer24a6d842012-12-08 11:31:24 -0300606 return buf;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300607}
608
Frank Schaefere04c00d2012-12-08 11:31:30 -0300609/*
610 * Finish the current buffer if completed and prepare for the next field
611 */
612static struct em28xx_buffer *
613finish_field_prepare_next(struct em28xx *dev,
614 struct em28xx_buffer *buf,
615 struct em28xx_dmaqueue *dma_q)
616{
Frank Schaefer58159172014-03-24 16:33:18 -0300617 struct em28xx_v4l2 *v4l2 = dev->v4l2;
618
Frank Schaeferf0e38232014-03-24 16:33:20 -0300619 if (v4l2->progressive || v4l2->top_field) { /* Brand new frame */
Frank Schaefere04c00d2012-12-08 11:31:30 -0300620 if (buf != NULL)
621 finish_buffer(dev, buf);
622 buf = get_next_buf(dev, dma_q);
623 }
624 if (buf != NULL) {
Frank Schaeferf0e38232014-03-24 16:33:20 -0300625 buf->top_field = v4l2->top_field;
Frank Schaefere04c00d2012-12-08 11:31:30 -0300626 buf->pos = 0;
627 }
628
629 return buf;
630}
631
Frank Schaefer227b7c92012-12-08 11:31:31 -0300632/*
633 * Process data packet according to the em2710/em2750/em28xx frame data format
634 */
635static inline void process_frame_data_em28xx(struct em28xx *dev,
636 unsigned char *data_pkt,
637 unsigned int data_len)
638{
Frank Schaefer753aee72014-03-24 16:33:14 -0300639 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300640 struct em28xx_buffer *buf = dev->usb_ctl.vid_buf;
641 struct em28xx_buffer *vbi_buf = dev->usb_ctl.vbi_buf;
642 struct em28xx_dmaqueue *dma_q = &dev->vidq;
643 struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq;
644
645 /* capture type 0 = vbi start
646 capture type 1 = vbi in progress
647 capture type 2 = video start
648 capture type 3 = video in progress */
649 if (data_len >= 4) {
650 /* NOTE: Headers are always 4 bytes and
651 * never split across packets */
652 if (data_pkt[0] == 0x88 && data_pkt[1] == 0x88 &&
653 data_pkt[2] == 0x88 && data_pkt[3] == 0x88) {
654 /* Continuation */
655 data_pkt += 4;
656 data_len -= 4;
657 } else if (data_pkt[0] == 0x33 && data_pkt[1] == 0x95) {
658 /* Field start (VBI mode) */
Frank Schaeferf0e38232014-03-24 16:33:20 -0300659 v4l2->capture_type = 0;
660 v4l2->vbi_read = 0;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300661 em28xx_isocdbg("VBI START HEADER !!!\n");
Frank Schaeferf0e38232014-03-24 16:33:20 -0300662 v4l2->top_field = !(data_pkt[2] & 1);
Frank Schaefer227b7c92012-12-08 11:31:31 -0300663 data_pkt += 4;
664 data_len -= 4;
665 } else if (data_pkt[0] == 0x22 && data_pkt[1] == 0x5a) {
666 /* Field start (VBI disabled) */
Frank Schaeferf0e38232014-03-24 16:33:20 -0300667 v4l2->capture_type = 2;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300668 em28xx_isocdbg("VIDEO START HEADER !!!\n");
Frank Schaeferf0e38232014-03-24 16:33:20 -0300669 v4l2->top_field = !(data_pkt[2] & 1);
Frank Schaefer227b7c92012-12-08 11:31:31 -0300670 data_pkt += 4;
671 data_len -= 4;
672 }
673 }
674 /* NOTE: With bulk transfers, intermediate data packets
675 * have no continuation header */
676
Frank Schaeferf0e38232014-03-24 16:33:20 -0300677 if (v4l2->capture_type == 0) {
Frank Schaefer227b7c92012-12-08 11:31:31 -0300678 vbi_buf = finish_field_prepare_next(dev, vbi_buf, vbi_dma_q);
679 dev->usb_ctl.vbi_buf = vbi_buf;
Frank Schaeferf0e38232014-03-24 16:33:20 -0300680 v4l2->capture_type = 1;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300681 }
682
Frank Schaeferf0e38232014-03-24 16:33:20 -0300683 if (v4l2->capture_type == 1) {
Frank Schaefer753aee72014-03-24 16:33:14 -0300684 int vbi_size = v4l2->vbi_width * v4l2->vbi_height;
Frank Schaeferf0e38232014-03-24 16:33:20 -0300685 int vbi_data_len = ((v4l2->vbi_read + data_len) > vbi_size) ?
686 (vbi_size - v4l2->vbi_read) : data_len;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300687
688 /* Copy VBI data */
689 if (vbi_buf != NULL)
690 em28xx_copy_vbi(dev, vbi_buf, data_pkt, vbi_data_len);
Frank Schaeferf0e38232014-03-24 16:33:20 -0300691 v4l2->vbi_read += vbi_data_len;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300692
693 if (vbi_data_len < data_len) {
694 /* Continue with copying video data */
Frank Schaeferf0e38232014-03-24 16:33:20 -0300695 v4l2->capture_type = 2;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300696 data_pkt += vbi_data_len;
697 data_len -= vbi_data_len;
698 }
699 }
700
Frank Schaeferf0e38232014-03-24 16:33:20 -0300701 if (v4l2->capture_type == 2) {
Frank Schaefer227b7c92012-12-08 11:31:31 -0300702 buf = finish_field_prepare_next(dev, buf, dma_q);
703 dev->usb_ctl.vid_buf = buf;
Frank Schaeferf0e38232014-03-24 16:33:20 -0300704 v4l2->capture_type = 3;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300705 }
706
Frank Schaeferf0e38232014-03-24 16:33:20 -0300707 if (v4l2->capture_type == 3 && buf != NULL && data_len > 0)
Frank Schaefer227b7c92012-12-08 11:31:31 -0300708 em28xx_copy_video(dev, buf, data_pkt, data_len);
709}
710
Frank Schaefere507e0e2013-03-26 13:38:38 -0300711/*
712 * Process data packet according to the em25xx/em276x/7x/8x frame data format
713 */
714static inline void process_frame_data_em25xx(struct em28xx *dev,
715 unsigned char *data_pkt,
716 unsigned int data_len)
717{
718 struct em28xx_buffer *buf = dev->usb_ctl.vid_buf;
719 struct em28xx_dmaqueue *dmaq = &dev->vidq;
Frank Schaeferf0e38232014-03-24 16:33:20 -0300720 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Frank Schaefere507e0e2013-03-26 13:38:38 -0300721 bool frame_end = 0;
722
723 /* Check for header */
724 /* NOTE: at least with bulk transfers, only the first packet
725 * has a header and has always set the FRAME_END bit */
726 if (data_len >= 2) { /* em25xx header is only 2 bytes long */
727 if ((data_pkt[0] == EM25XX_FRMDATAHDR_BYTE1) &&
728 ((data_pkt[1] & ~EM25XX_FRMDATAHDR_BYTE2_MASK) == 0x00)) {
Frank Schaeferf0e38232014-03-24 16:33:20 -0300729 v4l2->top_field = !(data_pkt[1] &
Frank Schaefere507e0e2013-03-26 13:38:38 -0300730 EM25XX_FRMDATAHDR_BYTE2_FRAME_ID);
731 frame_end = data_pkt[1] &
732 EM25XX_FRMDATAHDR_BYTE2_FRAME_END;
733 data_pkt += 2;
734 data_len -= 2;
735 }
736
737 /* Finish field and prepare next (BULK only) */
738 if (dev->analog_xfer_bulk && frame_end) {
739 buf = finish_field_prepare_next(dev, buf, dmaq);
740 dev->usb_ctl.vid_buf = buf;
741 }
742 /* NOTE: in ISOC mode when a new frame starts and buf==NULL,
743 * we COULD already prepare a buffer here to avoid skipping the
744 * first frame.
745 */
746 }
747
748 /* Copy data */
749 if (buf != NULL && data_len > 0)
750 em28xx_copy_video(dev, buf, data_pkt, data_len);
751
752 /* Finish frame (ISOC only) => avoids lag of 1 frame */
753 if (!dev->analog_xfer_bulk && frame_end) {
754 buf = finish_field_prepare_next(dev, buf, dmaq);
755 dev->usb_ctl.vid_buf = buf;
756 }
757
758 /* NOTE: Tested with USB bulk transfers only !
759 * The wording in the datasheet suggests that isoc might work different.
760 * The current code assumes that with isoc transfers each packet has a
761 * header like with the other em28xx devices.
762 */
763 /* NOTE: Support for interlaced mode is pure theory. It has not been
764 * tested and it is unknown if these devices actually support it. */
765 /* NOTE: No VBI support yet (these chips likely do not support VBI). */
766}
767
Frank Schaefer960da932012-11-25 06:37:37 -0300768/* Processes and copies the URB data content (video and VBI data) */
Frank Schaefer0fa4a402012-11-08 14:11:45 -0300769static inline int em28xx_urb_data_copy(struct em28xx *dev, struct urb *urb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300770{
Frank Schaefer227b7c92012-12-08 11:31:31 -0300771 int xfer_bulk, num_packets, i;
772 unsigned char *usb_data_pkt;
773 unsigned int usb_data_len;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300774
775 if (!dev)
776 return 0;
777
Frank Schaefer2665c292012-12-27 19:02:43 -0300778 if (dev->disconnected)
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300779 return 0;
780
Frank Schaefer1653cb0c2012-11-08 14:11:44 -0300781 if (urb->status < 0)
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300782 print_err_status(dev, -1, urb->status);
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300783
Frank Schaefer4601cc32012-11-08 14:11:46 -0300784 xfer_bulk = usb_pipebulk(urb->pipe);
785
Frank Schaefer4601cc32012-11-08 14:11:46 -0300786 if (xfer_bulk) /* bulk */
787 num_packets = 1;
788 else /* isoc */
789 num_packets = urb->number_of_packets;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300790
Frank Schaefer4601cc32012-11-08 14:11:46 -0300791 for (i = 0; i < num_packets; i++) {
792 if (xfer_bulk) { /* bulk */
Frank Schaefer227b7c92012-12-08 11:31:31 -0300793 usb_data_len = urb->actual_length;
Frank Schaefer4601cc32012-11-08 14:11:46 -0300794
Frank Schaefer227b7c92012-12-08 11:31:31 -0300795 usb_data_pkt = urb->transfer_buffer;
Frank Schaefer4601cc32012-11-08 14:11:46 -0300796 } else { /* isoc */
797 if (urb->iso_frame_desc[i].status < 0) {
798 print_err_status(dev, i,
799 urb->iso_frame_desc[i].status);
800 if (urb->iso_frame_desc[i].status != -EPROTO)
801 continue;
802 }
803
Frank Schaefer227b7c92012-12-08 11:31:31 -0300804 usb_data_len = urb->iso_frame_desc[i].actual_length;
805 if (usb_data_len > dev->max_pkt_size) {
Frank Schaefer4601cc32012-11-08 14:11:46 -0300806 em28xx_isocdbg("packet bigger than packet size");
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300807 continue;
Frank Schaefer4601cc32012-11-08 14:11:46 -0300808 }
809
Frank Schaefer227b7c92012-12-08 11:31:31 -0300810 usb_data_pkt = urb->transfer_buffer +
811 urb->iso_frame_desc[i].offset;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300812 }
813
Frank Schaefer227b7c92012-12-08 11:31:31 -0300814 if (usb_data_len == 0) {
Frank Schaefer4601cc32012-11-08 14:11:46 -0300815 /* NOTE: happens very often with isoc transfers */
816 /* em28xx_usbdbg("packet %d is empty",i); - spammy */
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300817 continue;
818 }
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300819
Frank Schaefere507e0e2013-03-26 13:38:38 -0300820 if (dev->is_em25xx)
821 process_frame_data_em25xx(dev,
822 usb_data_pkt, usb_data_len);
823 else
824 process_frame_data_em28xx(dev,
825 usb_data_pkt, usb_data_len);
826
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300827 }
Frank Schaefer227b7c92012-12-08 11:31:31 -0300828 return 1;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300829}
830
831
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300832static int get_ressource(enum v4l2_buf_type f_type)
833{
834 switch (f_type) {
835 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
836 return EM28XX_RESOURCE_VIDEO;
837 case V4L2_BUF_TYPE_VBI_CAPTURE:
838 return EM28XX_RESOURCE_VBI;
839 default:
840 BUG();
841 return 0;
842 }
843}
844
845/* Usage lock check functions */
846static int res_get(struct em28xx *dev, enum v4l2_buf_type f_type)
847{
848 int res_type = get_ressource(f_type);
849
850 /* is it free? */
851 if (dev->resources & res_type) {
852 /* no, someone else uses it */
853 return -EBUSY;
854 }
855
856 /* it's free, grab it */
857 dev->resources |= res_type;
858 em28xx_videodbg("res: get %d\n", res_type);
859 return 0;
860}
861
862static void res_free(struct em28xx *dev, enum v4l2_buf_type f_type)
863{
864 int res_type = get_ressource(f_type);
865
866 dev->resources &= ~res_type;
867 em28xx_videodbg("res: put %d\n", res_type);
868}
869
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300870/* ------------------------------------------------------------------
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300871 Videobuf2 operations
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300872 ------------------------------------------------------------------*/
873
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300874static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
875 unsigned int *nbuffers, unsigned int *nplanes,
876 unsigned int sizes[], void *alloc_ctxs[])
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300877{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300878 struct em28xx *dev = vb2_get_drv_priv(vq);
Frank Schaefer753aee72014-03-24 16:33:14 -0300879 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300880 unsigned long size;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300881
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300882 if (fmt)
883 size = fmt->fmt.pix.sizeimage;
884 else
Frank Schaefer753aee72014-03-24 16:33:14 -0300885 size =
Frank Schaefer06e20672014-03-24 16:33:17 -0300886 (v4l2->width * v4l2->height * v4l2->format->depth + 7) >> 3;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -0300887
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300888 if (size == 0)
889 return -EINVAL;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300890
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300891 if (0 == *nbuffers)
892 *nbuffers = 32;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300893
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300894 *nplanes = 1;
895 sizes[0] = size;
Mauro Carvalho Chehabd2d9fbf2008-04-17 21:38:53 -0300896
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300897 return 0;
898}
899
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300900static int
901buffer_prepare(struct vb2_buffer *vb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300902{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300903 struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue);
Frank Schaefer753aee72014-03-24 16:33:14 -0300904 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300905 struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
906 unsigned long size;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300907
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300908 em28xx_videodbg("%s, field=%d\n", __func__, vb->v4l2_buf.field);
Aidan Thornton3b5fa922008-04-13 15:09:36 -0300909
Frank Schaefer06e20672014-03-24 16:33:17 -0300910 size = (v4l2->width * v4l2->height * v4l2->format->depth + 7) >> 3;
Aidan Thornton3b5fa922008-04-13 15:09:36 -0300911
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300912 if (vb2_plane_size(vb, 0) < size) {
913 em28xx_videodbg("%s data will not fit into plane (%lu < %lu)\n",
914 __func__, vb2_plane_size(vb, 0), size);
915 return -EINVAL;
916 }
917 vb2_set_plane_payload(&buf->vb, 0, size);
918
919 return 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300920}
921
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300922int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300923{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300924 struct em28xx *dev = vb2_get_drv_priv(vq);
Frank Schaeferf0e38232014-03-24 16:33:20 -0300925 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300926 struct v4l2_frequency f;
927 int rc = 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300928
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300929 em28xx_videodbg("%s\n", __func__);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300930
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300931 /* Make sure streaming is not already in progress for this type
932 of filehandle (e.g. video, vbi) */
933 rc = res_get(dev, vq->type);
934 if (rc)
935 return rc;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300936
Frank Schaefer8139a4d2014-05-11 17:59:04 -0300937 if (v4l2->streaming_users == 0) {
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300938 /* First active streaming user, so allocate all the URBs */
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300939
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300940 /* Allocate the USB bandwidth */
941 em28xx_set_alternate(dev);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300942
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300943 /* Needed, since GPIO might have disabled power of
944 some i2c device
945 */
946 em28xx_wake_i2c(dev);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300947
Frank Schaeferf0e38232014-03-24 16:33:20 -0300948 v4l2->capture_type = -1;
Frank Schaefer960da932012-11-25 06:37:37 -0300949 rc = em28xx_init_usb_xfer(dev, EM28XX_ANALOG_MODE,
950 dev->analog_xfer_bulk,
951 EM28XX_NUM_BUFS,
952 dev->max_pkt_size,
953 dev->packet_multiplier,
954 em28xx_urb_data_copy);
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300955 if (rc < 0)
Frank Schaefer032f1dd2013-10-10 15:31:53 -0300956 return rc;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300957
958 /*
959 * djh: it's not clear whether this code is still needed. I'm
960 * leaving it in here for now entirely out of concern for
961 * backward compatibility (the old code did it)
962 */
963
964 /* Ask tuner to go to analog or radio mode */
965 memset(&f, 0, sizeof(f));
Frank Schaefer3854b0d2014-03-24 16:33:22 -0300966 f.frequency = v4l2->frequency;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300967 if (vq->owner && vq->owner->vdev->vfl_type == VFL_TYPE_RADIO)
968 f.type = V4L2_TUNER_RADIO;
969 else
970 f.type = V4L2_TUNER_ANALOG_TV;
Frank Schaeferf0e38232014-03-24 16:33:20 -0300971 v4l2_device_call_all(&v4l2->v4l2_dev,
Frank Schaefer95d26082014-03-24 16:33:09 -0300972 0, tuner, s_frequency, &f);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300973 }
974
Frank Schaefer8139a4d2014-05-11 17:59:04 -0300975 v4l2->streaming_users++;
Frank Schaefer032f1dd2013-10-10 15:31:53 -0300976
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300977 return rc;
978}
979
Hans Verkuile37559b2014-04-17 02:47:21 -0300980static void em28xx_stop_streaming(struct vb2_queue *vq)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300981{
982 struct em28xx *dev = vb2_get_drv_priv(vq);
Frank Schaefer8139a4d2014-05-11 17:59:04 -0300983 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300984 struct em28xx_dmaqueue *vidq = &dev->vidq;
985 unsigned long flags = 0;
986
987 em28xx_videodbg("%s\n", __func__);
988
989 res_free(dev, vq->type);
990
Frank Schaefer8139a4d2014-05-11 17:59:04 -0300991 if (v4l2->streaming_users-- == 1) {
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300992 /* Last active user, so shutdown all the URBS */
993 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
994 }
995
996 spin_lock_irqsave(&dev->slock, flags);
Frank Schaefer627530c2014-08-09 06:37:20 -0300997 if (dev->usb_ctl.vid_buf != NULL) {
998 vb2_buffer_done(&dev->usb_ctl.vid_buf->vb, VB2_BUF_STATE_ERROR);
999 dev->usb_ctl.vid_buf = NULL;
1000 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001001 while (!list_empty(&vidq->active)) {
1002 struct em28xx_buffer *buf;
1003 buf = list_entry(vidq->active.next, struct em28xx_buffer, list);
1004 list_del(&buf->list);
1005 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
1006 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001007 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001008}
1009
Hans Verkuile37559b2014-04-17 02:47:21 -03001010void em28xx_stop_vbi_streaming(struct vb2_queue *vq)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001011{
1012 struct em28xx *dev = vb2_get_drv_priv(vq);
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001013 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001014 struct em28xx_dmaqueue *vbiq = &dev->vbiq;
1015 unsigned long flags = 0;
1016
1017 em28xx_videodbg("%s\n", __func__);
1018
1019 res_free(dev, vq->type);
1020
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001021 if (v4l2->streaming_users-- == 1) {
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001022 /* Last active user, so shutdown all the URBS */
1023 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
1024 }
1025
1026 spin_lock_irqsave(&dev->slock, flags);
Frank Schaefer627530c2014-08-09 06:37:20 -03001027 if (dev->usb_ctl.vbi_buf != NULL) {
1028 vb2_buffer_done(&dev->usb_ctl.vbi_buf->vb, VB2_BUF_STATE_ERROR);
1029 dev->usb_ctl.vbi_buf = NULL;
1030 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001031 while (!list_empty(&vbiq->active)) {
1032 struct em28xx_buffer *buf;
1033 buf = list_entry(vbiq->active.next, struct em28xx_buffer, list);
1034 list_del(&buf->list);
1035 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
1036 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001037 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001038}
1039
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001040static void
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001041buffer_queue(struct vb2_buffer *vb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001042{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001043 struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue);
1044 struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
1045 struct em28xx_dmaqueue *vidq = &dev->vidq;
1046 unsigned long flags = 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001047
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001048 em28xx_videodbg("%s\n", __func__);
1049 buf->mem = vb2_plane_vaddr(vb, 0);
1050 buf->length = vb2_plane_size(vb, 0);
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001051
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001052 spin_lock_irqsave(&dev->slock, flags);
1053 list_add_tail(&buf->list, &vidq->active);
1054 spin_unlock_irqrestore(&dev->slock, flags);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001055}
1056
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001057static struct vb2_ops em28xx_video_qops = {
1058 .queue_setup = queue_setup,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001059 .buf_prepare = buffer_prepare,
1060 .buf_queue = buffer_queue,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001061 .start_streaming = em28xx_start_analog_streaming,
1062 .stop_streaming = em28xx_stop_streaming,
1063 .wait_prepare = vb2_ops_wait_prepare,
1064 .wait_finish = vb2_ops_wait_finish,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001065};
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001066
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001067static int em28xx_vb2_setup(struct em28xx *dev)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001068{
1069 int rc;
1070 struct vb2_queue *q;
Frank Schaefer27a36df2014-03-24 16:33:13 -03001071 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001072
1073 /* Setup Videobuf2 for Video capture */
Frank Schaefer27a36df2014-03-24 16:33:13 -03001074 q = &v4l2->vb_vidq;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001075 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Mauro Carvalho Chehabef85cd92013-01-06 00:34:22 -02001076 q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
Sakari Ailusade48682014-02-25 19:12:19 -03001077 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001078 q->drv_priv = dev;
1079 q->buf_struct_size = sizeof(struct em28xx_buffer);
1080 q->ops = &em28xx_video_qops;
1081 q->mem_ops = &vb2_vmalloc_memops;
1082
1083 rc = vb2_queue_init(q);
1084 if (rc < 0)
1085 return rc;
1086
1087 /* Setup Videobuf2 for VBI capture */
Frank Schaefer27a36df2014-03-24 16:33:13 -03001088 q = &v4l2->vb_vbiq;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001089 q->type = V4L2_BUF_TYPE_VBI_CAPTURE;
1090 q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR;
Sakari Ailusade48682014-02-25 19:12:19 -03001091 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001092 q->drv_priv = dev;
1093 q->buf_struct_size = sizeof(struct em28xx_buffer);
1094 q->ops = &em28xx_vbi_qops;
1095 q->mem_ops = &vb2_vmalloc_memops;
1096
1097 rc = vb2_queue_init(q);
1098 if (rc < 0)
1099 return rc;
1100
1101 return 0;
1102}
1103
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001104/********************* v4l2 interface **************************************/
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001105
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001106static void video_mux(struct em28xx *dev, int index)
1107{
Frank Schaefer95d26082014-03-24 16:33:09 -03001108 struct v4l2_device *v4l2_dev = &dev->v4l2->v4l2_dev;
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001109 dev->ctl_input = index;
1110 dev->ctl_ainput = INPUT(index)->amux;
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001111 dev->ctl_aoutput = INPUT(index)->aout;
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001112
Mauro Carvalho Chehabe879b8e2008-11-20 13:39:39 -03001113 if (!dev->ctl_aoutput)
1114 dev->ctl_aoutput = EM28XX_AOUT_MASTER;
1115
Frank Schaefer95d26082014-03-24 16:33:09 -03001116 v4l2_device_call_all(v4l2_dev, 0, video, s_routing,
Hans Verkuil5325b422009-04-02 11:26:22 -03001117 INPUT(index)->vmux, 0, 0);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001118
Mauro Carvalho Chehab505b6d02008-11-25 09:39:50 -03001119 if (dev->board.has_msp34xx) {
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001120 if (dev->i2s_speed) {
Frank Schaefer95d26082014-03-24 16:33:09 -03001121 v4l2_device_call_all(v4l2_dev, 0, audio,
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03001122 s_i2s_clock_freq, dev->i2s_speed);
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001123 }
Hans Verkuil2474ed42006-03-19 12:35:57 -03001124 /* Note: this is msp3400 specific */
Frank Schaefer95d26082014-03-24 16:33:09 -03001125 v4l2_device_call_all(v4l2_dev, 0, audio, s_routing,
Hans Verkuil5325b422009-04-02 11:26:22 -03001126 dev->ctl_ainput, MSP_OUTPUT(MSP_SC_IN_DSP_SCART1), 0);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001127 }
Mauro Carvalho Chehab539c96d2008-01-05 09:53:54 -03001128
Vitaly Wool2bd1d9e2009-03-04 08:27:52 -03001129 if (dev->board.adecoder != EM28XX_NOADECODER) {
Frank Schaefer95d26082014-03-24 16:33:09 -03001130 v4l2_device_call_all(v4l2_dev, 0, audio, s_routing,
Hans Verkuil5325b422009-04-02 11:26:22 -03001131 dev->ctl_ainput, dev->ctl_aoutput, 0);
Vitaly Wool2bd1d9e2009-03-04 08:27:52 -03001132 }
1133
Mauro Carvalho Chehab00b87302008-02-06 18:34:13 -03001134 em28xx_audio_analog_set(dev);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001135}
1136
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001137static void em28xx_ctrl_notify(struct v4l2_ctrl *ctrl, void *priv)
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001138{
Hans Verkuil081b9452012-09-07 05:43:59 -03001139 struct em28xx *dev = priv;
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001140
Hans Verkuil081b9452012-09-07 05:43:59 -03001141 /*
1142 * In the case of non-AC97 volume controls, we still need
1143 * to do some setups at em28xx, in order to mute/unmute
1144 * and to adjust audio volume. However, the value ranges
1145 * should be checked by the corresponding V4L subdriver.
1146 */
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001147 switch (ctrl->id) {
1148 case V4L2_CID_AUDIO_MUTE:
Hans Verkuil081b9452012-09-07 05:43:59 -03001149 dev->mute = ctrl->val;
1150 em28xx_audio_analog_set(dev);
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001151 break;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001152 case V4L2_CID_AUDIO_VOLUME:
Hans Verkuil081b9452012-09-07 05:43:59 -03001153 dev->volume = ctrl->val;
1154 em28xx_audio_analog_set(dev);
1155 break;
1156 }
1157}
1158
1159static int em28xx_s_ctrl(struct v4l2_ctrl *ctrl)
1160{
Frank Schaeferabc13082014-03-24 16:33:10 -03001161 struct em28xx_v4l2 *v4l2 =
1162 container_of(ctrl->handler, struct em28xx_v4l2, ctrl_handler);
1163 struct em28xx *dev = v4l2->dev;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001164 int ret = -EINVAL;
Hans Verkuil081b9452012-09-07 05:43:59 -03001165
1166 switch (ctrl->id) {
1167 case V4L2_CID_AUDIO_MUTE:
1168 dev->mute = ctrl->val;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001169 ret = em28xx_audio_analog_set(dev);
Hans Verkuil081b9452012-09-07 05:43:59 -03001170 break;
1171 case V4L2_CID_AUDIO_VOLUME:
1172 dev->volume = ctrl->val;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001173 ret = em28xx_audio_analog_set(dev);
1174 break;
1175 case V4L2_CID_CONTRAST:
1176 ret = em28xx_write_reg(dev, EM28XX_R20_YGAIN, ctrl->val);
1177 break;
1178 case V4L2_CID_BRIGHTNESS:
1179 ret = em28xx_write_reg(dev, EM28XX_R21_YOFFSET, ctrl->val);
1180 break;
1181 case V4L2_CID_SATURATION:
1182 ret = em28xx_write_reg(dev, EM28XX_R22_UVGAIN, ctrl->val);
1183 break;
1184 case V4L2_CID_BLUE_BALANCE:
1185 ret = em28xx_write_reg(dev, EM28XX_R23_UOFFSET, ctrl->val);
1186 break;
1187 case V4L2_CID_RED_BALANCE:
1188 ret = em28xx_write_reg(dev, EM28XX_R24_VOFFSET, ctrl->val);
1189 break;
1190 case V4L2_CID_SHARPNESS:
1191 ret = em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, ctrl->val);
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001192 break;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001193 }
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001194
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001195 return (ret < 0) ? ret : 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001196}
1197
Fengguang Wu8068eb82014-01-07 12:50:47 -03001198static const struct v4l2_ctrl_ops em28xx_ctrl_ops = {
Hans Verkuil081b9452012-09-07 05:43:59 -03001199 .s_ctrl = em28xx_s_ctrl,
1200};
1201
Frank Schaefer6b09a212013-02-10 16:05:12 -03001202static void size_to_scale(struct em28xx *dev,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001203 unsigned int width, unsigned int height,
1204 unsigned int *hscale, unsigned int *vscale)
1205{
Mauro Carvalho Chehab55699962009-07-13 20:15:02 -03001206 unsigned int maxw = norm_maxw(dev);
1207 unsigned int maxh = norm_maxh(dev);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001208
1209 *hscale = (((unsigned long)maxw) << 12) / width - 4096L;
Frank Schaefer81685322013-02-10 16:05:11 -03001210 if (*hscale > EM28XX_HVSCALE_MAX)
1211 *hscale = EM28XX_HVSCALE_MAX;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001212
1213 *vscale = (((unsigned long)maxh) << 12) / height - 4096L;
Frank Schaefer81685322013-02-10 16:05:11 -03001214 if (*vscale > EM28XX_HVSCALE_MAX)
1215 *vscale = EM28XX_HVSCALE_MAX;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001216}
1217
Frank Schaeferb8374132013-02-10 16:05:13 -03001218static void scale_to_size(struct em28xx *dev,
1219 unsigned int hscale, unsigned int vscale,
1220 unsigned int *width, unsigned int *height)
1221{
1222 unsigned int maxw = norm_maxw(dev);
1223 unsigned int maxh = norm_maxh(dev);
1224
1225 *width = (((unsigned long)maxw) << 12) / (hscale + 4096L);
1226 *height = (((unsigned long)maxh) << 12) / (vscale + 4096L);
1227}
1228
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001229/* ------------------------------------------------------------------
1230 IOCTL vidioc handling
1231 ------------------------------------------------------------------*/
1232
Hans Verkuil78b526a2008-05-28 12:16:41 -03001233static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001234 struct v4l2_format *f)
1235{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001236 struct em28xx *dev = video_drvdata(file);
Frank Schaefer753aee72014-03-24 16:33:14 -03001237 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001238
Frank Schaefer753aee72014-03-24 16:33:14 -03001239 f->fmt.pix.width = v4l2->width;
1240 f->fmt.pix.height = v4l2->height;
Frank Schaefer06e20672014-03-24 16:33:17 -03001241 f->fmt.pix.pixelformat = v4l2->format->fourcc;
1242 f->fmt.pix.bytesperline = (v4l2->width * v4l2->format->depth + 7) >> 3;
Frank Schaefer753aee72014-03-24 16:33:14 -03001243 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * v4l2->height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001244 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
1245
1246 /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */
Frank Schaefer58159172014-03-24 16:33:18 -03001247 if (v4l2->progressive)
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -03001248 f->fmt.pix.field = V4L2_FIELD_NONE;
1249 else
Frank Schaefer58159172014-03-24 16:33:18 -03001250 f->fmt.pix.field = v4l2->interlaced_fieldmode ?
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001251 V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001252 return 0;
1253}
1254
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001255static struct em28xx_fmt *format_by_fourcc(unsigned int fourcc)
1256{
1257 unsigned int i;
1258
1259 for (i = 0; i < ARRAY_SIZE(format); i++)
1260 if (format[i].fourcc == fourcc)
1261 return &format[i];
1262
1263 return NULL;
1264}
1265
Hans Verkuil78b526a2008-05-28 12:16:41 -03001266static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001267 struct v4l2_format *f)
1268{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001269 struct em28xx *dev = video_drvdata(file);
Frank Schaefer58159172014-03-24 16:33:18 -03001270 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Trent Piephoccb83402009-05-30 21:45:46 -03001271 unsigned int width = f->fmt.pix.width;
1272 unsigned int height = f->fmt.pix.height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001273 unsigned int maxw = norm_maxw(dev);
1274 unsigned int maxh = norm_maxh(dev);
1275 unsigned int hscale, vscale;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001276 struct em28xx_fmt *fmt;
1277
1278 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
1279 if (!fmt) {
1280 em28xx_videodbg("Fourcc format (%08x) invalid.\n",
1281 f->fmt.pix.pixelformat);
1282 return -EINVAL;
1283 }
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001284
Mauro Carvalho Chehab55699962009-07-13 20:15:02 -03001285 if (dev->board.is_em2800) {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001286 /* the em2800 can only scale down to 50% */
Trent Piephoccb83402009-05-30 21:45:46 -03001287 height = height > (3 * maxh / 4) ? maxh : maxh / 2;
1288 width = width > (3 * maxw / 4) ? maxw : maxw / 2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001289 /*
1290 * MaxPacketSize for em2800 is too small to capture at full
1291 * resolution use half of maxw as the scaler can only scale
1292 * to 50%
1293 */
Sascha Sommer1020d132012-01-08 16:54:28 -03001294 if (width == maxw && height == maxh)
1295 width /= 2;
Trent Piephoccb83402009-05-30 21:45:46 -03001296 } else {
1297 /* width must even because of the YUYV format
1298 height must be even because of interlacing */
Devin Heitmuellere3ba4d32009-09-15 00:18:06 -03001299 v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh,
1300 1, 0);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001301 }
1302
Frank Schaefer6b09a212013-02-10 16:05:12 -03001303 size_to_scale(dev, width, height, &hscale, &vscale);
Hans Verkuil46f85972013-03-30 05:31:42 -03001304 scale_to_size(dev, hscale, vscale, &width, &height);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001305
1306 f->fmt.pix.width = width;
1307 f->fmt.pix.height = height;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001308 f->fmt.pix.pixelformat = fmt->fourcc;
Hans Verkuile6066db2013-02-06 08:14:47 -03001309 f->fmt.pix.bytesperline = (width * fmt->depth + 7) >> 3;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001310 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001311 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
Frank Schaefer58159172014-03-24 16:33:18 -03001312 if (v4l2->progressive)
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -03001313 f->fmt.pix.field = V4L2_FIELD_NONE;
1314 else
Frank Schaefer58159172014-03-24 16:33:18 -03001315 f->fmt.pix.field = v4l2->interlaced_fieldmode ?
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -03001316 V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
Alban Browaeys51dd4d72013-07-16 19:06:46 -03001317 f->fmt.pix.priv = 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001318
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001319 return 0;
1320}
1321
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001322static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc,
1323 unsigned width, unsigned height)
1324{
1325 struct em28xx_fmt *fmt;
Frank Schaefer753aee72014-03-24 16:33:14 -03001326 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001327
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001328 fmt = format_by_fourcc(fourcc);
1329 if (!fmt)
1330 return -EINVAL;
1331
Frank Schaefer06e20672014-03-24 16:33:17 -03001332 v4l2->format = fmt;
Frank Schaefer753aee72014-03-24 16:33:14 -03001333 v4l2->width = width;
1334 v4l2->height = height;
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001335
1336 /* set new image size */
Frank Schaefer753aee72014-03-24 16:33:14 -03001337 size_to_scale(dev, v4l2->width, v4l2->height,
1338 &v4l2->hscale, &v4l2->vscale);
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001339
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001340 em28xx_resolution_set(dev);
1341
1342 return 0;
1343}
1344
Hans Verkuil78b526a2008-05-28 12:16:41 -03001345static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001346 struct v4l2_format *f)
1347{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001348 struct em28xx *dev = video_drvdata(file);
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001349 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001350
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001351 if (v4l2->streaming_users > 0)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001352 return -EBUSY;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001353
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001354 vidioc_try_fmt_vid_cap(file, priv, f);
1355
Hans Verkuil0499a5a2010-09-26 07:34:45 -03001356 return em28xx_set_video_format(dev, f->fmt.pix.pixelformat,
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001357 f->fmt.pix.width, f->fmt.pix.height);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001358}
1359
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001360static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
1361{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001362 struct em28xx *dev = video_drvdata(file);
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001363
Frank Schaefer52faaf72014-03-24 16:33:16 -03001364 *norm = dev->v4l2->norm;
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001365
1366 return 0;
1367}
1368
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001369static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm)
1370{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001371 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001372
Frank Schaefer95d26082014-03-24 16:33:09 -03001373 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, video, querystd, norm);
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001374
1375 return 0;
1376}
1377
Hans Verkuil314527a2013-03-15 06:10:40 -03001378static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001379{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001380 struct em28xx *dev = video_drvdata(file);
Frank Schaefer753aee72014-03-24 16:33:14 -03001381 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001382 struct v4l2_format f;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001383
Frank Schaefer52faaf72014-03-24 16:33:16 -03001384 if (norm == v4l2->norm)
Hans Verkuild8c95c02012-09-07 07:31:54 -03001385 return 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001386
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001387 if (v4l2->streaming_users > 0)
Hans Verkuild8c95c02012-09-07 07:31:54 -03001388 return -EBUSY;
Hans Verkuild8c95c02012-09-07 07:31:54 -03001389
Frank Schaefer52faaf72014-03-24 16:33:16 -03001390 v4l2->norm = norm;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001391
1392 /* Adjusts width/height, if needed */
Hans Verkuild8c95c02012-09-07 07:31:54 -03001393 f.fmt.pix.width = 720;
Hans Verkuil314527a2013-03-15 06:10:40 -03001394 f.fmt.pix.height = (norm & V4L2_STD_525_60) ? 480 : 576;
Hans Verkuil78b526a2008-05-28 12:16:41 -03001395 vidioc_try_fmt_vid_cap(file, priv, &f);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001396
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001397 /* set new image size */
Frank Schaefer753aee72014-03-24 16:33:14 -03001398 v4l2->width = f.fmt.pix.width;
1399 v4l2->height = f.fmt.pix.height;
1400 size_to_scale(dev, v4l2->width, v4l2->height,
1401 &v4l2->hscale, &v4l2->vscale);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001402
1403 em28xx_resolution_set(dev);
Laurent Pinchart8774bed2014-04-28 16:53:01 -03001404 v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_std, v4l2->norm);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001405
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001406 return 0;
1407}
1408
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001409static int vidioc_g_parm(struct file *file, void *priv,
1410 struct v4l2_streamparm *p)
1411{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001412 struct em28xx *dev = video_drvdata(file);
Frank Schaefer52faaf72014-03-24 16:33:16 -03001413 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001414 int rc = 0;
1415
Hans Verkuil86ff7f12012-09-07 06:16:03 -03001416 p->parm.capture.readbuffers = EM28XX_MIN_BUF;
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001417 if (dev->board.is_webcam)
Frank Schaefer52faaf72014-03-24 16:33:16 -03001418 rc = v4l2_device_call_until_err(&v4l2->v4l2_dev, 0,
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001419 video, g_parm, p);
1420 else
Frank Schaefer52faaf72014-03-24 16:33:16 -03001421 v4l2_video_std_frame_period(v4l2->norm,
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001422 &p->parm.capture.timeperframe);
1423
1424 return rc;
1425}
1426
1427static int vidioc_s_parm(struct file *file, void *priv,
1428 struct v4l2_streamparm *p)
1429{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001430 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001431
Hans Verkuil86ff7f12012-09-07 06:16:03 -03001432 p->parm.capture.readbuffers = EM28XX_MIN_BUF;
Frank Schaefer95d26082014-03-24 16:33:09 -03001433 return v4l2_device_call_until_err(&dev->v4l2->v4l2_dev,
1434 0, video, s_parm, p);
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001435}
1436
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001437static const char *iname[] = {
1438 [EM28XX_VMUX_COMPOSITE1] = "Composite1",
1439 [EM28XX_VMUX_COMPOSITE2] = "Composite2",
1440 [EM28XX_VMUX_COMPOSITE3] = "Composite3",
1441 [EM28XX_VMUX_COMPOSITE4] = "Composite4",
1442 [EM28XX_VMUX_SVIDEO] = "S-Video",
1443 [EM28XX_VMUX_TELEVISION] = "Television",
1444 [EM28XX_VMUX_CABLE] = "Cable TV",
1445 [EM28XX_VMUX_DVB] = "DVB",
1446 [EM28XX_VMUX_DEBUG] = "for debug only",
1447};
1448
1449static int vidioc_enum_input(struct file *file, void *priv,
1450 struct v4l2_input *i)
1451{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001452 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001453 unsigned int n;
1454
1455 n = i->index;
1456 if (n >= MAX_EM28XX_INPUT)
1457 return -EINVAL;
1458 if (0 == INPUT(n)->type)
1459 return -EINVAL;
1460
1461 i->index = n;
1462 i->type = V4L2_INPUT_TYPE_CAMERA;
1463
1464 strcpy(i->name, iname[INPUT(n)->type]);
1465
1466 if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type) ||
1467 (EM28XX_VMUX_CABLE == INPUT(n)->type))
1468 i->type = V4L2_INPUT_TYPE_TUNER;
1469
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001470 i->std = dev->v4l2->vdev->tvnorms;
Hans Verkuild8c95c02012-09-07 07:31:54 -03001471 /* webcams do not have the STD API */
1472 if (dev->board.is_webcam)
1473 i->capabilities = 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001474
1475 return 0;
1476}
1477
1478static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1479{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001480 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001481
1482 *i = dev->ctl_input;
1483
1484 return 0;
1485}
1486
1487static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
1488{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001489 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001490
1491 if (i >= MAX_EM28XX_INPUT)
1492 return -EINVAL;
1493 if (0 == INPUT(i)->type)
1494 return -EINVAL;
1495
Ezequiel García96371fc2012-03-23 18:09:34 -03001496 video_mux(dev, i);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001497 return 0;
1498}
1499
1500static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
1501{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001502 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001503
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001504 switch (a->index) {
1505 case EM28XX_AMUX_VIDEO:
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001506 strcpy(a->name, "Television");
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001507 break;
1508 case EM28XX_AMUX_LINE_IN:
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001509 strcpy(a->name, "Line In");
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001510 break;
1511 case EM28XX_AMUX_VIDEO2:
1512 strcpy(a->name, "Television alt");
1513 break;
1514 case EM28XX_AMUX_PHONE:
1515 strcpy(a->name, "Phone");
1516 break;
1517 case EM28XX_AMUX_MIC:
1518 strcpy(a->name, "Mic");
1519 break;
1520 case EM28XX_AMUX_CD:
1521 strcpy(a->name, "CD");
1522 break;
1523 case EM28XX_AMUX_AUX:
1524 strcpy(a->name, "Aux");
1525 break;
1526 case EM28XX_AMUX_PCM_OUT:
1527 strcpy(a->name, "PCM");
1528 break;
1529 default:
1530 return -EINVAL;
1531 }
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001532
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001533 a->index = dev->ctl_ainput;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001534 a->capability = V4L2_AUDCAP_STEREO;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001535
1536 return 0;
1537}
1538
Hans Verkuil0e8025b92012-09-04 11:59:31 -03001539static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001540{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001541 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001542
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03001543 if (a->index >= MAX_EM28XX_INPUT)
1544 return -EINVAL;
1545 if (0 == INPUT(a->index)->type)
1546 return -EINVAL;
1547
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001548 dev->ctl_ainput = INPUT(a->index)->amux;
1549 dev->ctl_aoutput = INPUT(a->index)->aout;
Mauro Carvalho Chehabe879b8e2008-11-20 13:39:39 -03001550
1551 if (!dev->ctl_aoutput)
1552 dev->ctl_aoutput = EM28XX_AOUT_MASTER;
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001553
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001554 return 0;
1555}
1556
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001557static int vidioc_g_tuner(struct file *file, void *priv,
1558 struct v4l2_tuner *t)
1559{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001560 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001561
1562 if (0 != t->index)
1563 return -EINVAL;
1564
1565 strcpy(t->name, "Tuner");
1566
Frank Schaefer95d26082014-03-24 16:33:09 -03001567 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, g_tuner, t);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001568 return 0;
1569}
1570
1571static int vidioc_s_tuner(struct file *file, void *priv,
Hans Verkuil2f73c7c2013-03-15 06:10:06 -03001572 const struct v4l2_tuner *t)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001573{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001574 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001575
1576 if (0 != t->index)
1577 return -EINVAL;
1578
Frank Schaefer95d26082014-03-24 16:33:09 -03001579 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, s_tuner, t);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001580 return 0;
1581}
1582
1583static int vidioc_g_frequency(struct file *file, void *priv,
1584 struct v4l2_frequency *f)
1585{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001586 struct em28xx *dev = video_drvdata(file);
Frank Schaefer3854b0d2014-03-24 16:33:22 -03001587 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001588
Hans Verkuil20deebf2012-09-06 10:07:25 -03001589 if (0 != f->tuner)
1590 return -EINVAL;
1591
Frank Schaefer3854b0d2014-03-24 16:33:22 -03001592 f->frequency = v4l2->frequency;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001593 return 0;
1594}
1595
1596static int vidioc_s_frequency(struct file *file, void *priv,
Hans Verkuilb530a442013-03-19 04:09:26 -03001597 const struct v4l2_frequency *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001598{
Frank Schaefer95d26082014-03-24 16:33:09 -03001599 struct v4l2_frequency new_freq = *f;
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001600 struct em28xx *dev = video_drvdata(file);
Frank Schaefer95d26082014-03-24 16:33:09 -03001601 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001602
1603 if (0 != f->tuner)
1604 return -EINVAL;
1605
Frank Schaefer95d26082014-03-24 16:33:09 -03001606 v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, s_frequency, f);
1607 v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, g_frequency, &new_freq);
Frank Schaefer3854b0d2014-03-24 16:33:22 -03001608 v4l2->frequency = new_freq.frequency;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001609
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001610 return 0;
1611}
1612
Hans Verkuilcd634f12013-03-27 08:04:23 -03001613#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuil96b03d22013-04-06 06:16:58 -03001614static int vidioc_g_chip_info(struct file *file, void *priv,
1615 struct v4l2_dbg_chip_info *chip)
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001616{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001617 struct em28xx *dev = video_drvdata(file);
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001618
1619 if (chip->match.addr > 1)
1620 return -EINVAL;
1621 if (chip->match.addr == 1)
1622 strlcpy(chip->name, "ac97", sizeof(chip->name));
1623 else
Frank Schaefer95d26082014-03-24 16:33:09 -03001624 strlcpy(chip->name,
1625 dev->v4l2->v4l2_dev.name, sizeof(chip->name));
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001626 return 0;
1627}
1628
Frank Schaefer35deba32013-02-07 13:39:19 -03001629static int em28xx_reg_len(int reg)
1630{
1631 switch (reg) {
1632 case EM28XX_R40_AC97LSB:
1633 case EM28XX_R30_HSCALELOW:
1634 case EM28XX_R32_VSCALELOW:
1635 return 2;
1636 default:
1637 return 1;
1638 }
1639}
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001640
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001641static int vidioc_g_register(struct file *file, void *priv,
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001642 struct v4l2_dbg_register *reg)
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001643{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001644 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001645 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{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001684 struct em28xx *dev = video_drvdata(file);
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001685 __le16 buf;
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001686
Hans Verkuilabca2052013-05-29 06:59:35 -03001687 if (reg->match.addr > 1)
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001688 return -EINVAL;
Hans Verkuilabca2052013-05-29 06:59:35 -03001689 if (reg->match.addr)
1690 return em28xx_write_ac97(dev, reg->reg, reg->val);
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001691
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001692 /* Match host */
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001693 buf = cpu_to_le16(reg->val);
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001694
Hans Verkuil0499a5a2010-09-26 07:34:45 -03001695 return em28xx_write_regs(dev, reg->reg, (char *)&buf,
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001696 em28xx_reg_len(reg->reg));
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001697}
1698#endif
1699
1700
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001701static int vidioc_querycap(struct file *file, void *priv,
1702 struct v4l2_capability *cap)
1703{
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001704 struct video_device *vdev = video_devdata(file);
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001705 struct em28xx *dev = video_drvdata(file);
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001706 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001707
1708 strlcpy(cap->driver, "em28xx", sizeof(cap->driver));
1709 strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card));
Thierry MERLEcb977162009-01-20 18:01:33 -03001710 usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001711
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001712 if (vdev->vfl_type == VFL_TYPE_GRABBER)
1713 cap->device_caps = V4L2_CAP_READWRITE |
1714 V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1715 else if (vdev->vfl_type == VFL_TYPE_RADIO)
1716 cap->device_caps = V4L2_CAP_RADIO;
1717 else
Hans Verkuil1d179ee2012-09-07 08:45:10 -03001718 cap->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE;
Devin Heitmueller04146142009-09-11 00:08:44 -03001719
Mauro Carvalho Chehab6c428b52009-08-04 19:52:37 -03001720 if (dev->audio_mode.has_audio)
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001721 cap->device_caps |= V4L2_CAP_AUDIO;
Mauro Carvalho Chehab6c428b52009-08-04 19:52:37 -03001722
Mauro Carvalho Chehabed086312008-01-24 06:59:20 -03001723 if (dev->tuner_type != TUNER_ABSENT)
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001724 cap->device_caps |= V4L2_CAP_TUNER;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001725
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001726 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS |
1727 V4L2_CAP_READWRITE | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001728 if (v4l2->vbi_dev)
Hans Verkuil1d179ee2012-09-07 08:45:10 -03001729 cap->capabilities |= V4L2_CAP_VBI_CAPTURE;
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001730 if (v4l2->radio_dev)
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001731 cap->capabilities |= V4L2_CAP_RADIO;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001732 return 0;
1733}
1734
Hans Verkuil78b526a2008-05-28 12:16:41 -03001735static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001736 struct v4l2_fmtdesc *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001737{
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001738 if (unlikely(f->index >= ARRAY_SIZE(format)))
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001739 return -EINVAL;
1740
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001741 strlcpy(f->description, format[f->index].name, sizeof(f->description));
1742 f->pixelformat = format[f->index].fourcc;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001743
1744 return 0;
1745}
1746
Mauro Carvalho Chehab1c5c5062011-10-16 13:52:43 -02001747static int vidioc_enum_framesizes(struct file *file, void *priv,
1748 struct v4l2_frmsizeenum *fsize)
1749{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001750 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab1c5c5062011-10-16 13:52:43 -02001751 struct em28xx_fmt *fmt;
1752 unsigned int maxw = norm_maxw(dev);
1753 unsigned int maxh = norm_maxh(dev);
1754
1755 fmt = format_by_fourcc(fsize->pixel_format);
1756 if (!fmt) {
1757 em28xx_videodbg("Fourcc format (%08x) invalid.\n",
1758 fsize->pixel_format);
1759 return -EINVAL;
1760 }
1761
1762 if (dev->board.is_em2800) {
1763 if (fsize->index > 1)
1764 return -EINVAL;
1765 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
1766 fsize->discrete.width = maxw / (1 + fsize->index);
1767 fsize->discrete.height = maxh / (1 + fsize->index);
1768 return 0;
1769 }
1770
1771 if (fsize->index != 0)
1772 return -EINVAL;
1773
1774 /* Report a continuous range */
1775 fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
Frank Schaefer6c3598e2013-02-10 16:05:14 -03001776 scale_to_size(dev, EM28XX_HVSCALE_MAX, EM28XX_HVSCALE_MAX,
1777 &fsize->stepwise.min_width, &fsize->stepwise.min_height);
1778 if (fsize->stepwise.min_width < 48)
1779 fsize->stepwise.min_width = 48;
1780 if (fsize->stepwise.min_height < 38)
1781 fsize->stepwise.min_height = 38;
Mauro Carvalho Chehab1c5c5062011-10-16 13:52:43 -02001782 fsize->stepwise.max_width = maxw;
1783 fsize->stepwise.max_height = maxh;
1784 fsize->stepwise.step_width = 1;
1785 fsize->stepwise.step_height = 1;
1786 return 0;
1787}
1788
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001789/* RAW VBI ioctls */
1790
1791static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
1792 struct v4l2_format *format)
1793{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001794 struct em28xx *dev = video_drvdata(file);
Frank Schaefer753aee72014-03-24 16:33:14 -03001795 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001796
Frank Schaefer753aee72014-03-24 16:33:14 -03001797 format->fmt.vbi.samples_per_line = v4l2->vbi_width;
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001798 format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
1799 format->fmt.vbi.offset = 0;
1800 format->fmt.vbi.flags = 0;
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001801 format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
Frank Schaefer753aee72014-03-24 16:33:14 -03001802 format->fmt.vbi.count[0] = v4l2->vbi_height;
1803 format->fmt.vbi.count[1] = v4l2->vbi_height;
Hans Verkuil2a221d32012-09-07 08:51:32 -03001804 memset(format->fmt.vbi.reserved, 0, sizeof(format->fmt.vbi.reserved));
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001805
1806 /* Varies by video standard (NTSC, PAL, etc.) */
Frank Schaefer52faaf72014-03-24 16:33:16 -03001807 if (v4l2->norm & V4L2_STD_525_60) {
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001808 /* NTSC */
1809 format->fmt.vbi.start[0] = 10;
1810 format->fmt.vbi.start[1] = 273;
Frank Schaefer52faaf72014-03-24 16:33:16 -03001811 } else if (v4l2->norm & V4L2_STD_625_50) {
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001812 /* PAL */
1813 format->fmt.vbi.start[0] = 6;
1814 format->fmt.vbi.start[1] = 318;
1815 }
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001816
1817 return 0;
1818}
1819
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001820/* ----------------------------------------------------------- */
1821/* RADIO ESPECIFIC IOCTLS */
1822/* ----------------------------------------------------------- */
1823
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001824static int radio_g_tuner(struct file *file, void *priv,
1825 struct v4l2_tuner *t)
1826{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001827 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001828
1829 if (unlikely(t->index > 0))
1830 return -EINVAL;
1831
1832 strcpy(t->name, "Radio");
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001833
Frank Schaefer95d26082014-03-24 16:33:09 -03001834 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, g_tuner, t);
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001835
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001836 return 0;
1837}
1838
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001839static int radio_s_tuner(struct file *file, void *priv,
Hans Verkuil2f73c7c2013-03-15 06:10:06 -03001840 const struct v4l2_tuner *t)
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001841{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001842 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001843
1844 if (0 != t->index)
1845 return -EINVAL;
1846
Frank Schaefer95d26082014-03-24 16:33:09 -03001847 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, s_tuner, t);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001848
1849 return 0;
1850}
1851
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001852/*
Frank Schaefer95d26082014-03-24 16:33:09 -03001853 * em28xx_free_v4l2() - Free struct em28xx_v4l2
1854 *
1855 * @ref: struct kref for struct em28xx_v4l2
1856 *
1857 * Called when all users of struct em28xx_v4l2 are gone
1858 */
Mauro Carvalho Chehabf472c0b2014-05-23 14:29:44 -03001859static void em28xx_free_v4l2(struct kref *ref)
Frank Schaefer95d26082014-03-24 16:33:09 -03001860{
1861 struct em28xx_v4l2 *v4l2 = container_of(ref, struct em28xx_v4l2, ref);
1862
Frank Schaeferabc13082014-03-24 16:33:10 -03001863 v4l2->dev->v4l2 = NULL;
Frank Schaefer95d26082014-03-24 16:33:09 -03001864 kfree(v4l2);
1865}
1866
1867/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08001868 * em28xx_v4l2_open()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001869 * inits the device and starts isoc transfer
1870 */
Hans Verkuilbec43662008-12-30 06:58:20 -03001871static int em28xx_v4l2_open(struct file *filp)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001872{
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001873 struct video_device *vdev = video_devdata(filp);
1874 struct em28xx *dev = video_drvdata(filp);
Frank Schaefer95d26082014-03-24 16:33:09 -03001875 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001876 enum v4l2_buf_type fh_type = 0;
Frank Schaefer3c0f90e2014-07-25 14:48:57 -03001877 int ret;
Markus Rechberger9c755412005-11-08 21:37:52 -08001878
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001879 switch (vdev->vfl_type) {
1880 case VFL_TYPE_GRABBER:
1881 fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1882 break;
1883 case VFL_TYPE_VBI:
1884 fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
1885 break;
Frank Schaefer4e170242014-01-12 13:24:18 -03001886 case VFL_TYPE_RADIO:
1887 break;
1888 default:
1889 return -EINVAL;
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001890 }
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03001891
Frank Schaefer747dba72014-07-25 14:48:58 -03001892 em28xx_videodbg("open dev=%s type=%s\n",
1893 video_device_node_name(vdev), v4l2_type_names[fh_type]);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001894
Hans Verkuil876cb142012-06-23 08:12:47 -03001895 if (mutex_lock_interruptible(&dev->lock))
1896 return -ERESTARTSYS;
Frank Schaefer3c0f90e2014-07-25 14:48:57 -03001897
1898 ret = v4l2_fh_open(filp);
1899 if (ret) {
1900 em28xx_errdev("%s: v4l2_fh_open() returned error %d\n",
1901 __func__, ret);
Hans Verkuil876cb142012-06-23 08:12:47 -03001902 mutex_unlock(&dev->lock);
Frank Schaefer3c0f90e2014-07-25 14:48:57 -03001903 return ret;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001904 }
1905
Frank Schaefer747dba72014-07-25 14:48:58 -03001906 if (v4l2_fh_is_singular_file(filp)) {
1907 em28xx_videodbg("first opened filehandle, initializing device\n");
1908
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001909 em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001910
Frank Schaefer4e170242014-01-12 13:24:18 -03001911 if (vdev->vfl_type != VFL_TYPE_RADIO)
1912 em28xx_resolution_set(dev);
1913
1914 /*
1915 * Needed, since GPIO might have disabled power
1916 * of some i2c devices
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001917 */
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03001918 em28xx_wake_i2c(dev);
Frank Schaefer747dba72014-07-25 14:48:58 -03001919 } else {
1920 em28xx_videodbg("further filehandles are already opened\n");
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02001921 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001922
1923 if (vdev->vfl_type == VFL_TYPE_RADIO) {
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001924 em28xx_videodbg("video_open: setting radio device\n");
Frank Schaefer95d26082014-03-24 16:33:09 -03001925 v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, s_radio);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001926 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001927
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03001928 kref_get(&dev->ref);
Frank Schaefer95d26082014-03-24 16:33:09 -03001929 kref_get(&v4l2->ref);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001930
Hans Verkuil876cb142012-06-23 08:12:47 -03001931 mutex_unlock(&dev->lock);
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001932
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001933 return 0;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001934}
1935
1936/*
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001937 * em28xx_v4l2_fini()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001938 * unregisters the v4l2,i2c and usb devices
1939 * called when the device gets disconected or at module unload
1940*/
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001941static int em28xx_v4l2_fini(struct em28xx *dev)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001942{
Frank Schaefer95d26082014-03-24 16:33:09 -03001943 struct em28xx_v4l2 *v4l2 = dev->v4l2;
1944
Mauro Carvalho Chehab822b8de2014-01-06 05:27:47 -03001945 if (dev->is_audio_only) {
1946 /* Shouldn't initialize IR for this interface */
1947 return 0;
1948 }
1949
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001950 if (!dev->has_video) {
1951 /* This device does not support the v4l2 extension */
1952 return 0;
1953 }
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02001954
Frank Schaefer95d26082014-03-24 16:33:09 -03001955 if (v4l2 == NULL)
1956 return 0;
1957
Mauro Carvalho Chehabaa929ad2014-01-12 19:22:07 -03001958 em28xx_info("Closing video extension");
1959
Mauro Carvalho Chehabebbfbc22014-01-13 02:53:44 -03001960 mutex_lock(&dev->lock);
1961
Frank Schaefer95d26082014-03-24 16:33:09 -03001962 v4l2_device_disconnect(&v4l2->v4l2_dev);
Frank Schaefer5ad10de2014-01-12 13:24:21 -03001963
Frank Schaefer23e86422014-01-12 13:24:20 -03001964 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
1965
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001966 if (v4l2->radio_dev) {
Frank Schaefere8470222014-01-12 13:24:25 -03001967 em28xx_info("V4L2 device %s deregistered\n",
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001968 video_device_node_name(v4l2->radio_dev));
1969 video_unregister_device(v4l2->radio_dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001970 }
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001971 if (v4l2->vbi_dev) {
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001972 em28xx_info("V4L2 device %s deregistered\n",
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001973 video_device_node_name(v4l2->vbi_dev));
1974 video_unregister_device(v4l2->vbi_dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001975 }
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001976 if (v4l2->vdev) {
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->vdev));
1979 video_unregister_device(v4l2->vdev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001980 }
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001981
Frank Schaeferabc13082014-03-24 16:33:10 -03001982 v4l2_ctrl_handler_free(&v4l2->ctrl_handler);
Frank Schaefer95d26082014-03-24 16:33:09 -03001983 v4l2_device_unregister(&v4l2->v4l2_dev);
Frank Schaefer103f18a2014-01-17 14:45:30 -03001984
Frank Schaefer2c52a2f2014-03-24 16:33:11 -03001985 if (v4l2->clk) {
1986 v4l2_clk_unregister_fixed(v4l2->clk);
1987 v4l2->clk = NULL;
Frank Schaefer25dd1652014-01-12 13:24:23 -03001988 }
1989
Frank Schaefer95d26082014-03-24 16:33:09 -03001990 kref_put(&v4l2->ref, em28xx_free_v4l2);
1991
Mauro Carvalho Chehabebbfbc22014-01-13 02:53:44 -03001992 mutex_unlock(&dev->lock);
Frank Schaefer95d26082014-03-24 16:33:09 -03001993
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03001994 kref_put(&dev->ref, em28xx_free_device);
Frank Schaefer5ad10de2014-01-12 13:24:21 -03001995
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001996 return 0;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001997}
1998
Shuah Khana61f6812014-02-21 21:50:17 -03001999static int em28xx_v4l2_suspend(struct em28xx *dev)
2000{
2001 if (dev->is_audio_only)
2002 return 0;
2003
2004 if (!dev->has_video)
2005 return 0;
2006
2007 em28xx_info("Suspending video extension");
2008 em28xx_stop_urbs(dev);
2009 return 0;
2010}
2011
2012static int em28xx_v4l2_resume(struct em28xx *dev)
2013{
2014 if (dev->is_audio_only)
2015 return 0;
2016
2017 if (!dev->has_video)
2018 return 0;
2019
2020 em28xx_info("Resuming video extension");
2021 /* what do we do here */
2022 return 0;
2023}
2024
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002025/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002026 * em28xx_v4l2_close()
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03002027 * stops streaming and deallocates all resources allocated by the v4l2
2028 * calls and ioctls
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002029 */
Hans Verkuilbec43662008-12-30 06:58:20 -03002030static int em28xx_v4l2_close(struct file *filp)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002031{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03002032 struct em28xx *dev = video_drvdata(filp);
Frank Schaefer95d26082014-03-24 16:33:09 -03002033 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03002034 int errCode;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002035
Ricardo Ribalda98c24dcd2013-11-06 05:39:35 -03002036 mutex_lock(&dev->lock);
Devin Heitmueller8c873d32009-09-03 00:23:27 -03002037
Frank Schaefer747dba72014-07-25 14:48:58 -03002038 if (v4l2_fh_is_singular_file(filp)) {
2039 em28xx_videodbg("last opened filehandle, shutting down device\n");
2040
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002041 /* No sense to try to write to the device */
2042 if (dev->disconnected)
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002043 goto exit;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03002044
Mauro Carvalho Chehabeb6c9632008-12-05 10:39:12 -03002045 /* Save some power by putting tuner to sleep */
Frank Schaefer95d26082014-03-24 16:33:09 -03002046 v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_power, 0);
Mauro Carvalho Chehabeb6c9632008-12-05 10:39:12 -03002047
Aidan Thorntond7aa8022008-04-13 14:38:47 -03002048 /* do this before setting alternate! */
Mauro Carvalho Chehab2fe3e2e2008-11-27 09:10:40 -03002049 em28xx_set_mode(dev, EM28XX_SUSPEND);
Aidan Thorntond7aa8022008-04-13 14:38:47 -03002050
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03002051 /* set alternate 0 */
2052 dev->alt = 0;
2053 em28xx_videodbg("setting alternate 0\n");
2054 errCode = usb_set_interface(dev->udev, 0, 0);
2055 if (errCode < 0) {
2056 em28xx_errdev("cannot change alternate number to "
2057 "0 (error=%i)\n", errCode);
2058 }
Frank Schaefer747dba72014-07-25 14:48:58 -03002059 } else {
2060 em28xx_videodbg("further opened filehandles left\n");
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002061 }
Devin Heitmueller28abf0832009-09-01 01:54:54 -03002062
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002063exit:
Frank Schaefer747dba72014-07-25 14:48:58 -03002064 vb2_fop_release(filp);
Frank Schaefer95d26082014-03-24 16:33:09 -03002065 kref_put(&v4l2->ref, em28xx_free_v4l2);
Hans Verkuil876cb142012-06-23 08:12:47 -03002066 mutex_unlock(&dev->lock);
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002067 kref_put(&dev->ref, em28xx_free_device);
2068
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002069 return 0;
2070}
2071
Hans Verkuilbec43662008-12-30 06:58:20 -03002072static const struct v4l2_file_operations em28xx_v4l_fops = {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002073 .owner = THIS_MODULE,
2074 .open = em28xx_v4l2_open,
2075 .release = em28xx_v4l2_close,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002076 .read = vb2_fop_read,
2077 .poll = vb2_fop_poll,
2078 .mmap = vb2_fop_mmap,
Hans Verkuil0499a5a2010-09-26 07:34:45 -03002079 .unlocked_ioctl = video_ioctl2,
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002080};
2081
Hans Verkuila3998102008-07-21 02:57:38 -03002082static const struct v4l2_ioctl_ops video_ioctl_ops = {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002083 .vidioc_querycap = vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03002084 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
2085 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
2086 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
2087 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Devin Heitmueller28abf0832009-09-01 01:54:54 -03002088 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Hans Verkuil2a221d32012-09-07 08:51:32 -03002089 .vidioc_try_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Frank Schaeferaab34612013-02-07 13:39:16 -03002090 .vidioc_s_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Mauro Carvalho Chehab1c5c5062011-10-16 13:52:43 -02002091 .vidioc_enum_framesizes = vidioc_enum_framesizes,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002092 .vidioc_g_audio = vidioc_g_audio,
2093 .vidioc_s_audio = vidioc_s_audio,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002094
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002095 .vidioc_reqbufs = vb2_ioctl_reqbufs,
2096 .vidioc_create_bufs = vb2_ioctl_create_bufs,
2097 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
2098 .vidioc_querybuf = vb2_ioctl_querybuf,
2099 .vidioc_qbuf = vb2_ioctl_qbuf,
2100 .vidioc_dqbuf = vb2_ioctl_dqbuf,
2101
Devin Heitmueller19bf0032009-09-11 00:40:18 -03002102 .vidioc_g_std = vidioc_g_std,
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03002103 .vidioc_querystd = vidioc_querystd,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002104 .vidioc_s_std = vidioc_s_std,
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03002105 .vidioc_g_parm = vidioc_g_parm,
2106 .vidioc_s_parm = vidioc_s_parm,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002107 .vidioc_enum_input = vidioc_enum_input,
2108 .vidioc_g_input = vidioc_g_input,
2109 .vidioc_s_input = vidioc_s_input,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002110 .vidioc_streamon = vb2_ioctl_streamon,
2111 .vidioc_streamoff = vb2_ioctl_streamoff,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002112 .vidioc_g_tuner = vidioc_g_tuner,
2113 .vidioc_s_tuner = vidioc_s_tuner,
2114 .vidioc_g_frequency = vidioc_g_frequency,
2115 .vidioc_s_frequency = vidioc_s_frequency,
Hans Verkuil50fdf402012-09-07 06:10:12 -03002116 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
2117 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002118#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuil96b03d22013-04-06 06:16:58 -03002119 .vidioc_g_chip_info = vidioc_g_chip_info,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002120 .vidioc_g_register = vidioc_g_register,
2121 .vidioc_s_register = vidioc_s_register,
2122#endif
Hans Verkuila3998102008-07-21 02:57:38 -03002123};
2124
2125static const struct video_device em28xx_video_template = {
Frank Schaefere8470222014-01-12 13:24:25 -03002126 .fops = &em28xx_v4l_fops,
2127 .ioctl_ops = &video_ioctl_ops,
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002128 .release = video_device_release,
Frank Schaefere8470222014-01-12 13:24:25 -03002129 .tvnorms = V4L2_STD_ALL,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002130};
2131
Hans Verkuilbec43662008-12-30 06:58:20 -03002132static const struct v4l2_file_operations radio_fops = {
Hans Verkuila3998102008-07-21 02:57:38 -03002133 .owner = THIS_MODULE,
2134 .open = em28xx_v4l2_open,
2135 .release = em28xx_v4l2_close,
Hans Verkuil8fd0bda2010-12-18 09:59:51 -03002136 .unlocked_ioctl = video_ioctl2,
Hans Verkuila3998102008-07-21 02:57:38 -03002137};
2138
2139static const struct v4l2_ioctl_ops radio_ioctl_ops = {
Hans Verkuila9d79fe2012-09-06 07:31:04 -03002140 .vidioc_querycap = vidioc_querycap,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002141 .vidioc_g_tuner = radio_g_tuner,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002142 .vidioc_s_tuner = radio_s_tuner,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002143 .vidioc_g_frequency = vidioc_g_frequency,
2144 .vidioc_s_frequency = vidioc_s_frequency,
Hans Verkuil50fdf402012-09-07 06:10:12 -03002145 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
2146 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002147#ifdef CONFIG_VIDEO_ADV_DEBUG
Michal Marek430c73f2013-04-16 08:06:30 -03002148 .vidioc_g_chip_info = vidioc_g_chip_info,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002149 .vidioc_g_register = vidioc_g_register,
2150 .vidioc_s_register = vidioc_s_register,
2151#endif
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002152};
2153
Hans Verkuila3998102008-07-21 02:57:38 -03002154static struct video_device em28xx_radio_template = {
Frank Schaefere8470222014-01-12 13:24:25 -03002155 .fops = &radio_fops,
2156 .ioctl_ops = &radio_ioctl_ops,
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002157 .release = video_device_release,
Hans Verkuila3998102008-07-21 02:57:38 -03002158};
2159
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002160/* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */
2161static unsigned short saa711x_addrs[] = {
2162 0x4a >> 1, 0x48 >> 1, /* SAA7111, SAA7111A and SAA7113 */
2163 0x42 >> 1, 0x40 >> 1, /* SAA7114, SAA7115 and SAA7118 */
2164 I2C_CLIENT_END };
2165
2166static unsigned short tvp5150_addrs[] = {
2167 0xb8 >> 1,
2168 0xba >> 1,
2169 I2C_CLIENT_END
2170};
2171
2172static unsigned short msp3400_addrs[] = {
2173 0x80 >> 1,
2174 0x88 >> 1,
2175 I2C_CLIENT_END
2176};
2177
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03002178/******************************** usb interface ******************************/
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002179
Adrian Bunk532fe652008-01-28 22:10:48 -03002180static struct video_device *em28xx_vdev_init(struct em28xx *dev,
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -03002181 const struct video_device *template,
2182 const char *type_name)
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002183{
2184 struct video_device *vfd;
2185
2186 vfd = video_device_alloc();
2187 if (NULL == vfd)
2188 return NULL;
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03002189
2190 *vfd = *template;
Frank Schaefer95d26082014-03-24 16:33:09 -03002191 vfd->v4l2_dev = &dev->v4l2->v4l2_dev;
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03002192 vfd->debug = video_debug;
Hans Verkuil0499a5a2010-09-26 07:34:45 -03002193 vfd->lock = &dev->lock;
Hans Verkuild8c95c02012-09-07 07:31:54 -03002194 if (dev->board.is_webcam)
2195 vfd->tvnorms = 0;
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002196
2197 snprintf(vfd->name, sizeof(vfd->name), "%s %s",
2198 dev->name, type_name);
2199
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02002200 video_set_drvdata(vfd, dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002201 return vfd;
2202}
2203
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002204static void em28xx_tuner_setup(struct em28xx *dev, unsigned short tuner_addr)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002205{
Frank Schaefer3854b0d2014-03-24 16:33:22 -03002206 struct em28xx_v4l2 *v4l2 = dev->v4l2;
2207 struct v4l2_device *v4l2_dev = &v4l2->v4l2_dev;
2208 struct tuner_setup tun_setup;
2209 struct v4l2_frequency f;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002210
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002211 memset(&tun_setup, 0, sizeof(tun_setup));
2212
2213 tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
2214 tun_setup.tuner_callback = em28xx_tuner_callback;
2215
2216 if (dev->board.radio.type) {
2217 tun_setup.type = dev->board.radio.type;
2218 tun_setup.addr = dev->board.radio_addr;
2219
Frank Schaefer95d26082014-03-24 16:33:09 -03002220 v4l2_device_call_all(v4l2_dev,
2221 0, tuner, s_type_addr, &tun_setup);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002222 }
2223
2224 if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type)) {
2225 tun_setup.type = dev->tuner_type;
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002226 tun_setup.addr = tuner_addr;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002227
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
Frank Schaefer6867bd5a2014-03-24 16:33:23 -03002232 if (dev->board.tda9887_conf) {
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002233 struct v4l2_priv_tun_config tda9887_cfg;
2234
2235 tda9887_cfg.tuner = TUNER_TDA9887;
Frank Schaefer6867bd5a2014-03-24 16:33:23 -03002236 tda9887_cfg.priv = &dev->board.tda9887_conf;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002237
Frank Schaefer95d26082014-03-24 16:33:09 -03002238 v4l2_device_call_all(v4l2_dev,
2239 0, tuner, s_config, &tda9887_cfg);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002240 }
2241
2242 if (dev->tuner_type == TUNER_XC2028) {
2243 struct v4l2_priv_tun_config xc2028_cfg;
2244 struct xc2028_ctrl ctl;
2245
2246 memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
2247 memset(&ctl, 0, sizeof(ctl));
2248
2249 em28xx_setup_xc3028(dev, &ctl);
2250
2251 xc2028_cfg.tuner = TUNER_XC2028;
2252 xc2028_cfg.priv = &ctl;
2253
Frank Schaefer95d26082014-03-24 16:33:09 -03002254 v4l2_device_call_all(v4l2_dev, 0, tuner, s_config, &xc2028_cfg);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002255 }
2256
2257 /* configure tuner */
2258 f.tuner = 0;
2259 f.type = V4L2_TUNER_ANALOG_TV;
2260 f.frequency = 9076; /* just a magic number */
Frank Schaefer3854b0d2014-03-24 16:33:22 -03002261 v4l2->frequency = f.frequency;
Frank Schaefer95d26082014-03-24 16:33:09 -03002262 v4l2_device_call_all(v4l2_dev, 0, tuner, s_frequency, &f);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002263}
2264
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002265static int em28xx_v4l2_init(struct em28xx *dev)
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002266{
Hans Verkuil081b9452012-09-07 05:43:59 -03002267 u8 val;
Mauro Carvalho Chehab2e5ef2d2008-12-28 22:26:36 -03002268 int ret;
Sascha Sommer1020d132012-01-08 16:54:28 -03002269 unsigned int maxw;
Frank Schaeferabc13082014-03-24 16:33:10 -03002270 struct v4l2_ctrl_handler *hdl;
Frank Schaefer95d26082014-03-24 16:33:09 -03002271 struct em28xx_v4l2 *v4l2;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002272
Mauro Carvalho Chehab822b8de2014-01-06 05:27:47 -03002273 if (dev->is_audio_only) {
2274 /* Shouldn't initialize IR for this interface */
2275 return 0;
2276 }
2277
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002278 if (!dev->has_video) {
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002279 /* This device does not support the v4l2 extension */
2280 return 0;
2281 }
Mauro Carvalho Chehab2e5ef2d2008-12-28 22:26:36 -03002282
Mauro Carvalho Chehab96346142013-12-26 12:41:03 -03002283 em28xx_info("Registering V4L2 extension\n");
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002284
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002285 mutex_lock(&dev->lock);
2286
Frank Schaefer95d26082014-03-24 16:33:09 -03002287 v4l2 = kzalloc(sizeof(struct em28xx_v4l2), GFP_KERNEL);
2288 if (v4l2 == NULL) {
2289 em28xx_info("em28xx_v4l: memory allocation failed\n");
2290 mutex_unlock(&dev->lock);
2291 return -ENOMEM;
2292 }
2293 kref_init(&v4l2->ref);
Frank Schaeferabc13082014-03-24 16:33:10 -03002294 v4l2->dev = dev;
Frank Schaefer95d26082014-03-24 16:33:09 -03002295 dev->v4l2 = v4l2;
2296
2297 ret = v4l2_device_register(&dev->udev->dev, &v4l2->v4l2_dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002298 if (ret < 0) {
2299 em28xx_errdev("Call to v4l2_device_register() failed!\n");
2300 goto err;
2301 }
2302
Frank Schaeferabc13082014-03-24 16:33:10 -03002303 hdl = &v4l2->ctrl_handler;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002304 v4l2_ctrl_handler_init(hdl, 8);
Frank Schaefer95d26082014-03-24 16:33:09 -03002305 v4l2->v4l2_dev.ctrl_handler = hdl;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002306
Frank Schaefer58159172014-03-24 16:33:18 -03002307 if (dev->board.is_webcam)
2308 v4l2->progressive = 1;
2309
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002310 /*
2311 * Default format, used for tvp5150 or saa711x output formats
2312 */
Frank Schaefer92972852014-03-24 16:33:15 -03002313 v4l2->vinmode = 0x10;
2314 v4l2->vinctl = EM28XX_VINCTRL_INTERLACED |
2315 EM28XX_VINCTRL_CCIR656_ENABLE;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002316
2317 /* request some modules */
2318
2319 if (dev->board.has_msp34xx)
Frank Schaefer95d26082014-03-24 16:33:09 -03002320 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2321 &dev->i2c_adap[dev->def_i2c_bus],
2322 "msp3400", 0, msp3400_addrs);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002323
2324 if (dev->board.decoder == EM28XX_SAA711X)
Frank Schaefer95d26082014-03-24 16:33:09 -03002325 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2326 &dev->i2c_adap[dev->def_i2c_bus],
2327 "saa7115_auto", 0, saa711x_addrs);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002328
2329 if (dev->board.decoder == EM28XX_TVP5150)
Frank Schaefer95d26082014-03-24 16:33:09 -03002330 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2331 &dev->i2c_adap[dev->def_i2c_bus],
2332 "tvp5150", 0, tvp5150_addrs);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002333
2334 if (dev->board.adecoder == EM28XX_TVAUDIO)
Frank Schaefer95d26082014-03-24 16:33:09 -03002335 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2336 &dev->i2c_adap[dev->def_i2c_bus],
2337 "tvaudio", dev->board.tvaudio_addr, NULL);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002338
2339 /* Initialize tuner and camera */
2340
2341 if (dev->board.tuner_type != TUNER_ABSENT) {
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002342 unsigned short tuner_addr = dev->board.tuner_addr;
Frank Schaefer6867bd5a2014-03-24 16:33:23 -03002343 int has_demod = (dev->board.tda9887_conf & TDA9887_PRESENT);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002344
2345 if (dev->board.radio.type)
Frank Schaefer95d26082014-03-24 16:33:09 -03002346 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2347 &dev->i2c_adap[dev->def_i2c_bus],
2348 "tuner", dev->board.radio_addr, NULL);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002349
2350 if (has_demod)
Frank Schaefer95d26082014-03-24 16:33:09 -03002351 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002352 &dev->i2c_adap[dev->def_i2c_bus], "tuner",
2353 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002354 if (tuner_addr == 0) {
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002355 enum v4l2_i2c_tuner_type type =
2356 has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV;
2357 struct v4l2_subdev *sd;
2358
Frank Schaefer95d26082014-03-24 16:33:09 -03002359 sd = v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002360 &dev->i2c_adap[dev->def_i2c_bus], "tuner",
2361 0, v4l2_i2c_tuner_addrs(type));
2362
2363 if (sd)
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002364 tuner_addr = v4l2_i2c_subdev_addr(sd);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002365 } else {
Frank Schaefer95d26082014-03-24 16:33:09 -03002366 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2367 &dev->i2c_adap[dev->def_i2c_bus],
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002368 "tuner", tuner_addr, NULL);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002369 }
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002370
2371 em28xx_tuner_setup(dev, tuner_addr);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002372 }
2373
Frank Schaeferd86bc652014-01-17 14:45:32 -03002374 if (dev->em28xx_sensor != EM28XX_NOSENSOR)
2375 em28xx_init_camera(dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002376
2377 /* Configure audio */
2378 ret = em28xx_audio_setup(dev);
2379 if (ret < 0) {
2380 em28xx_errdev("%s: Error while setting audio - error [%d]!\n",
2381 __func__, ret);
2382 goto unregister_dev;
2383 }
2384 if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
2385 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
2386 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
2387 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
2388 V4L2_CID_AUDIO_VOLUME, 0, 0x1f, 1, 0x1f);
2389 } else {
2390 /* install the em28xx notify callback */
2391 v4l2_ctrl_notify(v4l2_ctrl_find(hdl, V4L2_CID_AUDIO_MUTE),
2392 em28xx_ctrl_notify, dev);
2393 v4l2_ctrl_notify(v4l2_ctrl_find(hdl, V4L2_CID_AUDIO_VOLUME),
2394 em28xx_ctrl_notify, dev);
2395 }
2396
2397 /* wake i2c devices */
2398 em28xx_wake_i2c(dev);
2399
2400 /* init video dma queues */
2401 INIT_LIST_HEAD(&dev->vidq.active);
2402 INIT_LIST_HEAD(&dev->vbiq.active);
2403
2404 if (dev->board.has_msp34xx) {
2405 /* Send a reset to other chips via gpio */
2406 ret = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xf7);
2407 if (ret < 0) {
2408 em28xx_errdev("%s: em28xx_write_reg - msp34xx(1) failed! error [%d]\n",
2409 __func__, ret);
2410 goto unregister_dev;
2411 }
2412 msleep(3);
2413
2414 ret = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xff);
2415 if (ret < 0) {
2416 em28xx_errdev("%s: em28xx_write_reg - msp34xx(2) failed! error [%d]\n",
2417 __func__, ret);
2418 goto unregister_dev;
2419 }
2420 msleep(3);
2421 }
2422
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002423 /* set default norm */
Frank Schaefer52faaf72014-03-24 16:33:16 -03002424 v4l2->norm = V4L2_STD_PAL;
Laurent Pinchart8774bed2014-04-28 16:53:01 -03002425 v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_std, v4l2->norm);
Frank Schaefer58159172014-03-24 16:33:18 -03002426 v4l2->interlaced_fieldmode = EM28XX_INTERLACED_DEFAULT;
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002427
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002428 /* Analog specific initialization */
Frank Schaefer06e20672014-03-24 16:33:17 -03002429 v4l2->format = &format[0];
Sascha Sommer1020d132012-01-08 16:54:28 -03002430
2431 maxw = norm_maxw(dev);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002432 /* MaxPacketSize for em2800 is too small to capture at full resolution
2433 * use half of maxw as the scaler can only scale to 50% */
2434 if (dev->board.is_em2800)
2435 maxw /= 2;
Sascha Sommer1020d132012-01-08 16:54:28 -03002436
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03002437 em28xx_set_video_format(dev, format[0].fourcc,
Sascha Sommer1020d132012-01-08 16:54:28 -03002438 maxw, norm_maxh(dev));
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03002439
Ezequiel García96371fc2012-03-23 18:09:34 -03002440 video_mux(dev, 0);
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002441
2442 /* Audio defaults */
2443 dev->mute = 1;
2444 dev->volume = 0x1f;
2445
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002446/* em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -03002447 val = (u8)em28xx_read_reg(dev, EM28XX_R0F_XCLK);
2448 em28xx_write_reg(dev, EM28XX_R0F_XCLK,
2449 (EM28XX_XCLK_AUDIO_UNMUTE | val));
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002450
2451 em28xx_set_outfmt(dev);
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002452
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002453 /* Add image controls */
2454 /* NOTE: at this point, the subdevices are already registered, so bridge
2455 * controls are only added/enabled when no subdevice provides them */
Frank Schaeferad298052014-03-24 16:33:08 -03002456 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_CONTRAST))
2457 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002458 V4L2_CID_CONTRAST,
2459 0, 0x1f, 1, CONTRAST_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002460 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_BRIGHTNESS))
2461 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002462 V4L2_CID_BRIGHTNESS,
2463 -0x80, 0x7f, 1, BRIGHTNESS_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002464 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_SATURATION))
2465 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002466 V4L2_CID_SATURATION,
2467 0, 0x1f, 1, SATURATION_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002468 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_BLUE_BALANCE))
2469 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002470 V4L2_CID_BLUE_BALANCE,
2471 -0x30, 0x30, 1, BLUE_BALANCE_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002472 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_RED_BALANCE))
2473 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002474 V4L2_CID_RED_BALANCE,
2475 -0x30, 0x30, 1, RED_BALANCE_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002476 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_SHARPNESS))
2477 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002478 V4L2_CID_SHARPNESS,
2479 0, 0x0f, 1, SHARPNESS_DEFAULT);
2480
2481 /* Reset image controls */
2482 em28xx_colorlevels_set_default(dev);
Frank Schaeferad298052014-03-24 16:33:08 -03002483 v4l2_ctrl_handler_setup(hdl);
2484 ret = hdl->error;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002485 if (ret)
2486 goto unregister_dev;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002487
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002488 /* allocate and fill video video_device struct */
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002489 v4l2->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video");
2490 if (!v4l2->vdev) {
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002491 em28xx_errdev("cannot allocate video_device.\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002492 ret = -ENODEV;
2493 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002494 }
Frank Schaefer27a36df2014-03-24 16:33:13 -03002495 mutex_init(&v4l2->vb_queue_lock);
2496 mutex_init(&v4l2->vb_vbi_queue_lock);
2497 v4l2->vdev->queue = &v4l2->vb_vidq;
2498 v4l2->vdev->queue->lock = &v4l2->vb_queue_lock;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002499
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002500 /* disable inapplicable ioctls */
2501 if (dev->board.is_webcam) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002502 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_QUERYSTD);
2503 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_G_STD);
2504 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_STD);
Frank Schaefer3bc85cc2013-02-07 13:39:12 -03002505 } else {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002506 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_PARM);
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002507 }
Frank Schaefer66df67b2013-02-07 13:39:10 -03002508 if (dev->tuner_type == TUNER_ABSENT) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002509 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_G_TUNER);
2510 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_TUNER);
2511 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_G_FREQUENCY);
2512 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_FREQUENCY);
Frank Schaefer66df67b2013-02-07 13:39:10 -03002513 }
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002514 if (!dev->audio_mode.has_audio) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002515 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_G_AUDIO);
2516 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_AUDIO);
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002517 }
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002518
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002519 /* register v4l2 video video_device */
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002520 ret = video_register_device(v4l2->vdev, VFL_TYPE_GRABBER,
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002521 video_nr[dev->devno]);
2522 if (ret) {
2523 em28xx_errdev("unable to register video device (error=%i).\n",
2524 ret);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002525 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002526 }
2527
2528 /* Allocate and fill vbi video_device struct */
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002529 if (em28xx_vbi_supported(dev) == 1) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002530 v4l2->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template,
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002531 "vbi");
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002532
Frank Schaefer27a36df2014-03-24 16:33:13 -03002533 v4l2->vbi_dev->queue = &v4l2->vb_vbiq;
2534 v4l2->vbi_dev->queue->lock = &v4l2->vb_vbi_queue_lock;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002535
Frank Schaefer66df67b2013-02-07 13:39:10 -03002536 /* disable inapplicable ioctls */
Frank Schaefer3d3a4102014-07-25 15:08:30 -03002537 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_PARM);
Frank Schaefer66df67b2013-02-07 13:39:10 -03002538 if (dev->tuner_type == TUNER_ABSENT) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002539 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_G_TUNER);
2540 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_TUNER);
2541 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_G_FREQUENCY);
2542 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_FREQUENCY);
Frank Schaefer66df67b2013-02-07 13:39:10 -03002543 }
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002544 if (!dev->audio_mode.has_audio) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002545 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_G_AUDIO);
2546 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_AUDIO);
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002547 }
Frank Schaefer66df67b2013-02-07 13:39:10 -03002548
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002549 /* register v4l2 vbi video_device */
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002550 ret = video_register_device(v4l2->vbi_dev, VFL_TYPE_VBI,
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002551 vbi_nr[dev->devno]);
2552 if (ret < 0) {
2553 em28xx_errdev("unable to register vbi device\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002554 goto unregister_dev;
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002555 }
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002556 }
2557
2558 if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002559 v4l2->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template,
2560 "radio");
2561 if (!v4l2->radio_dev) {
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002562 em28xx_errdev("cannot allocate video_device.\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002563 ret = -ENODEV;
2564 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002565 }
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002566 ret = video_register_device(v4l2->radio_dev, VFL_TYPE_RADIO,
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002567 radio_nr[dev->devno]);
2568 if (ret < 0) {
2569 em28xx_errdev("can't register radio device\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002570 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002571 }
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002572 em28xx_info("Registered radio device as %s\n",
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002573 video_device_node_name(v4l2->radio_dev));
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002574 }
2575
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002576 em28xx_info("V4L2 video device registered as %s\n",
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002577 video_device_node_name(v4l2->vdev));
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002578
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002579 if (v4l2->vbi_dev)
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002580 em28xx_info("V4L2 VBI device registered as %s\n",
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002581 video_device_node_name(v4l2->vbi_dev));
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002582
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002583 /* Save some power by putting tuner to sleep */
Frank Schaefer95d26082014-03-24 16:33:09 -03002584 v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_power, 0);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002585
2586 /* initialize videobuf2 stuff */
2587 em28xx_vb2_setup(dev);
2588
Mauro Carvalho Chehab96346142013-12-26 12:41:03 -03002589 em28xx_info("V4L2 extension successfully initialized\n");
2590
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002591 kref_get(&dev->ref);
2592
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002593 mutex_unlock(&dev->lock);
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002594 return 0;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002595
2596unregister_dev:
Frank Schaeferabc13082014-03-24 16:33:10 -03002597 v4l2_ctrl_handler_free(&v4l2->ctrl_handler);
Frank Schaefer95d26082014-03-24 16:33:09 -03002598 v4l2_device_unregister(&v4l2->v4l2_dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002599err:
Frank Schaefer95d26082014-03-24 16:33:09 -03002600 dev->v4l2 = NULL;
2601 kref_put(&v4l2->ref, em28xx_free_v4l2);
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002602 mutex_unlock(&dev->lock);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002603 return ret;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002604}
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002605
2606static struct em28xx_ops v4l2_ops = {
2607 .id = EM28XX_V4L2,
2608 .name = "Em28xx v4l2 Extension",
2609 .init = em28xx_v4l2_init,
2610 .fini = em28xx_v4l2_fini,
Shuah Khana61f6812014-02-21 21:50:17 -03002611 .suspend = em28xx_v4l2_suspend,
2612 .resume = em28xx_v4l2_resume,
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002613};
2614
2615static int __init em28xx_video_register(void)
2616{
2617 return em28xx_register_extension(&v4l2_ops);
2618}
2619
2620static void __exit em28xx_video_unregister(void)
2621{
2622 em28xx_unregister_extension(&v4l2_ops);
2623}
2624
2625module_init(em28xx_video_register);
2626module_exit(em28xx_video_unregister);