blob: 9ecf65629b3d219cb6b1a33d5380c24f69cf0c9a [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#define EM25XX_FRMDATAHDR_BYTE1 0x02
85#define EM25XX_FRMDATAHDR_BYTE2_STILL_IMAGE 0x20
86#define EM25XX_FRMDATAHDR_BYTE2_FRAME_END 0x02
87#define EM25XX_FRMDATAHDR_BYTE2_FRAME_ID 0x01
88#define EM25XX_FRMDATAHDR_BYTE2_MASK (EM25XX_FRMDATAHDR_BYTE2_STILL_IMAGE | \
89 EM25XX_FRMDATAHDR_BYTE2_FRAME_END | \
90 EM25XX_FRMDATAHDR_BYTE2_FRAME_ID)
91
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -030092static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
93static unsigned int vbi_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
94static unsigned int radio_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -030095
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -020096module_param_array(video_nr, int, NULL, 0444);
97module_param_array(vbi_nr, int, NULL, 0444);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -030098module_param_array(radio_nr, int, NULL, 0444);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -030099MODULE_PARM_DESC(video_nr, "video device numbers");
100MODULE_PARM_DESC(vbi_nr, "vbi device numbers");
101MODULE_PARM_DESC(radio_nr, "radio device numbers");
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800102
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -0300103static unsigned int video_debug;
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -0300104module_param(video_debug, int, 0644);
105MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800106
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -0300107/* supported video standards */
108static struct em28xx_fmt format[] = {
109 {
Mauro Carvalho Chehab58fc1ce2009-07-03 02:54:18 -0300110 .name = "16 bpp YUY2, 4:2:2, packed",
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -0300111 .fourcc = V4L2_PIX_FMT_YUYV,
112 .depth = 16,
Devin Heitmueller3fbf9302008-12-29 23:34:37 -0300113 .reg = EM28XX_OUTFMT_YUV422_Y0UY1V,
Mauro Carvalho Chehab43cb9fe2009-06-30 08:36:17 -0300114 }, {
Mauro Carvalho Chehab58fc1ce2009-07-03 02:54:18 -0300115 .name = "16 bpp RGB 565, LE",
Mauro Carvalho Chehab43cb9fe2009-06-30 08:36:17 -0300116 .fourcc = V4L2_PIX_FMT_RGB565,
117 .depth = 16,
Mauro Carvalho Chehab58fc1ce2009-07-03 02:54:18 -0300118 .reg = EM28XX_OUTFMT_RGB_16_656,
119 }, {
120 .name = "8 bpp Bayer BGBG..GRGR",
121 .fourcc = V4L2_PIX_FMT_SBGGR8,
122 .depth = 8,
123 .reg = EM28XX_OUTFMT_RGB_8_BGBG,
124 }, {
125 .name = "8 bpp Bayer GRGR..BGBG",
126 .fourcc = V4L2_PIX_FMT_SGRBG8,
127 .depth = 8,
128 .reg = EM28XX_OUTFMT_RGB_8_GRGR,
129 }, {
130 .name = "8 bpp Bayer GBGB..RGRG",
131 .fourcc = V4L2_PIX_FMT_SGBRG8,
132 .depth = 8,
133 .reg = EM28XX_OUTFMT_RGB_8_GBGB,
134 }, {
135 .name = "12 bpp YUV411",
136 .fourcc = V4L2_PIX_FMT_YUV411P,
137 .depth = 12,
138 .reg = EM28XX_OUTFMT_YUV411,
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -0300139 },
140};
141
Frank Schaefer25c61e42014-03-22 10:01:03 -0300142/*FIXME: maxw should be dependent of alt mode */
143static inline unsigned int norm_maxw(struct em28xx *dev)
144{
Frank Schaeferd7dc18d2014-03-24 16:33:19 -0300145 struct em28xx_v4l2 *v4l2 = dev->v4l2;
146
Frank Schaefer25c61e42014-03-22 10:01:03 -0300147 if (dev->board.is_webcam)
Frank Schaeferd7dc18d2014-03-24 16:33:19 -0300148 return v4l2->sensor_xres;
Frank Schaefer25c61e42014-03-22 10:01:03 -0300149
150 if (dev->board.max_range_640_480)
151 return 640;
152
153 return 720;
154}
155
156static inline unsigned int norm_maxh(struct em28xx *dev)
157{
Frank Schaefer52faaf72014-03-24 16:33:16 -0300158 struct em28xx_v4l2 *v4l2 = dev->v4l2;
159
Frank Schaefer25c61e42014-03-22 10:01:03 -0300160 if (dev->board.is_webcam)
Frank Schaeferd7dc18d2014-03-24 16:33:19 -0300161 return v4l2->sensor_yres;
Frank Schaefer25c61e42014-03-22 10:01:03 -0300162
163 if (dev->board.max_range_640_480)
164 return 480;
165
Frank Schaefer52faaf72014-03-24 16:33:16 -0300166 return (v4l2->norm & V4L2_STD_625_50) ? 576 : 480;
Frank Schaefer25c61e42014-03-22 10:01:03 -0300167}
168
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300169static int em28xx_vbi_supported(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300170{
171 /* Modprobe option to manually disable */
172 if (disable_vbi == 1)
173 return 0;
174
175 if (dev->board.is_webcam)
176 return 0;
177
178 /* FIXME: check subdevices for VBI support */
179
180 if (dev->chip_id == CHIP_ID_EM2860 ||
181 dev->chip_id == CHIP_ID_EM2883)
182 return 1;
183
184 /* Version of em28xx that does not support VBI */
185 return 0;
186}
187
188/*
189 * em28xx_wake_i2c()
190 * configure i2c attached devices
191 */
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300192static void em28xx_wake_i2c(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300193{
Frank Schaefer95d26082014-03-24 16:33:09 -0300194 struct v4l2_device *v4l2_dev = &dev->v4l2->v4l2_dev;
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -0300195
Frank Schaefer95d26082014-03-24 16:33:09 -0300196 v4l2_device_call_all(v4l2_dev, 0, core, reset, 0);
197 v4l2_device_call_all(v4l2_dev, 0, video, s_routing,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -0300198 INPUT(dev->ctl_input)->vmux, 0, 0);
Frank Schaefer95d26082014-03-24 16:33:09 -0300199 v4l2_device_call_all(v4l2_dev, 0, video, s_stream, 0);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300200}
201
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300202static int em28xx_colorlevels_set_default(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300203{
204 em28xx_write_reg(dev, EM28XX_R20_YGAIN, CONTRAST_DEFAULT);
205 em28xx_write_reg(dev, EM28XX_R21_YOFFSET, BRIGHTNESS_DEFAULT);
206 em28xx_write_reg(dev, EM28XX_R22_UVGAIN, SATURATION_DEFAULT);
207 em28xx_write_reg(dev, EM28XX_R23_UOFFSET, BLUE_BALANCE_DEFAULT);
208 em28xx_write_reg(dev, EM28XX_R24_VOFFSET, RED_BALANCE_DEFAULT);
209 em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, SHARPNESS_DEFAULT);
210
211 em28xx_write_reg(dev, EM28XX_R14_GAMMA, 0x20);
212 em28xx_write_reg(dev, EM28XX_R15_RGAIN, 0x20);
213 em28xx_write_reg(dev, EM28XX_R16_GGAIN, 0x20);
214 em28xx_write_reg(dev, EM28XX_R17_BGAIN, 0x20);
215 em28xx_write_reg(dev, EM28XX_R18_ROFFSET, 0x00);
216 em28xx_write_reg(dev, EM28XX_R19_GOFFSET, 0x00);
217 return em28xx_write_reg(dev, EM28XX_R1A_BOFFSET, 0x00);
218}
219
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300220static int em28xx_set_outfmt(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300221{
222 int ret;
223 u8 fmt, vinctrl;
Frank Schaefer753aee72014-03-24 16:33:14 -0300224 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300225
Frank Schaefer06e20672014-03-24 16:33:17 -0300226 fmt = v4l2->format->reg;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300227 if (!dev->is_em25xx)
228 fmt |= 0x20;
229 /*
230 * NOTE: it's not clear if this is really needed !
231 * The datasheets say bit 5 is a reserved bit and devices seem to work
232 * fine without it. But the Windows driver sets it for em2710/50+em28xx
233 * devices and we've always been setting it, too.
234 *
235 * em2765 (em25xx, em276x/7x/8x) devices do NOT work with this bit set,
236 * it's likely used for an additional (compressed ?) format there.
237 */
238 ret = em28xx_write_reg(dev, EM28XX_R27_OUTFMT, fmt);
239 if (ret < 0)
240 return ret;
241
Frank Schaefer92972852014-03-24 16:33:15 -0300242 ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, v4l2->vinmode);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300243 if (ret < 0)
244 return ret;
245
Frank Schaefer92972852014-03-24 16:33:15 -0300246 vinctrl = v4l2->vinctl;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300247 if (em28xx_vbi_supported(dev) == 1) {
248 vinctrl |= EM28XX_VINCTRL_VBI_RAW;
249 em28xx_write_reg(dev, EM28XX_R34_VBI_START_H, 0x00);
Frank Schaefer753aee72014-03-24 16:33:14 -0300250 em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH, v4l2->vbi_width/4);
251 em28xx_write_reg(dev, EM28XX_R37_VBI_HEIGHT, v4l2->vbi_height);
Frank Schaefer52faaf72014-03-24 16:33:16 -0300252 if (v4l2->norm & V4L2_STD_525_60) {
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300253 /* NTSC */
254 em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x09);
Frank Schaefer52faaf72014-03-24 16:33:16 -0300255 } else if (v4l2->norm & V4L2_STD_625_50) {
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300256 /* PAL */
257 em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x07);
258 }
259 }
260
261 return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctrl);
262}
263
264static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax,
265 u8 ymin, u8 ymax)
266{
267 em28xx_videodbg("em28xx Scale: (%d,%d)-(%d,%d)\n",
268 xmin, ymin, xmax, ymax);
269
270 em28xx_write_regs(dev, EM28XX_R28_XMIN, &xmin, 1);
271 em28xx_write_regs(dev, EM28XX_R29_XMAX, &xmax, 1);
272 em28xx_write_regs(dev, EM28XX_R2A_YMIN, &ymin, 1);
273 return em28xx_write_regs(dev, EM28XX_R2B_YMAX, &ymax, 1);
274}
275
276static void em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -0300277 u16 width, u16 height)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300278{
279 u8 cwidth = width >> 2;
280 u8 cheight = height >> 2;
281 u8 overflow = (height >> 9 & 0x02) | (width >> 10 & 0x01);
282 /* NOTE: size limit: 2047x1023 = 2MPix */
283
284 em28xx_videodbg("capture area set to (%d,%d): %dx%d\n",
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -0300285 hstart, vstart,
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300286 ((overflow & 2) << 9 | cwidth << 2),
287 ((overflow & 1) << 10 | cheight << 2));
288
289 em28xx_write_regs(dev, EM28XX_R1C_HSTART, &hstart, 1);
290 em28xx_write_regs(dev, EM28XX_R1D_VSTART, &vstart, 1);
291 em28xx_write_regs(dev, EM28XX_R1E_CWIDTH, &cwidth, 1);
292 em28xx_write_regs(dev, EM28XX_R1F_CHEIGHT, &cheight, 1);
293 em28xx_write_regs(dev, EM28XX_R1B_OFLOW, &overflow, 1);
294
295 /* FIXME: function/meaning of these registers ? */
296 /* FIXME: align width+height to multiples of 4 ?! */
297 if (dev->is_em25xx) {
298 em28xx_write_reg(dev, 0x34, width >> 4);
299 em28xx_write_reg(dev, 0x35, height >> 4);
300 }
301}
302
303static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v)
304{
Frank Schaefercba8e9b2014-03-24 16:28:36 -0300305 u8 mode = 0x00;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300306 /* the em2800 scaler only supports scaling down to 50% */
307
308 if (dev->board.is_em2800) {
309 mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00);
310 } else {
311 u8 buf[2];
312
313 buf[0] = h;
314 buf[1] = h >> 8;
315 em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2);
316
317 buf[0] = v;
318 buf[1] = v >> 8;
319 em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2);
320 /* it seems that both H and V scalers must be active
321 to work correctly */
322 mode = (h || v) ? 0x30 : 0x00;
323 }
Frank Schaefercba8e9b2014-03-24 16:28:36 -0300324 return em28xx_write_reg(dev, EM28XX_R26_COMPR, mode);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300325}
326
327/* FIXME: this only function read values from dev */
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300328static int em28xx_resolution_set(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300329{
Frank Schaefer753aee72014-03-24 16:33:14 -0300330 struct em28xx_v4l2 *v4l2 = dev->v4l2;
331 int width = norm_maxw(dev);
332 int height = norm_maxh(dev);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300333
334 /* Properly setup VBI */
Frank Schaefer753aee72014-03-24 16:33:14 -0300335 v4l2->vbi_width = 720;
Frank Schaefer52faaf72014-03-24 16:33:16 -0300336 if (v4l2->norm & V4L2_STD_525_60)
Frank Schaefer753aee72014-03-24 16:33:14 -0300337 v4l2->vbi_height = 12;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300338 else
Frank Schaefer753aee72014-03-24 16:33:14 -0300339 v4l2->vbi_height = 18;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300340
341 em28xx_set_outfmt(dev);
342
343 em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2);
344
345 /* If we don't set the start position to 2 in VBI mode, we end up
346 with line 20/21 being YUYV encoded instead of being in 8-bit
347 greyscale. The core of the issue is that line 21 (and line 23 for
348 PAL WSS) are inside of active video region, and as a result they
349 get the pixelformatting associated with that area. So by cropping
350 it out, we end up with the same format as the rest of the VBI
351 region */
352 if (em28xx_vbi_supported(dev) == 1)
353 em28xx_capture_area_set(dev, 0, 2, width, height);
354 else
355 em28xx_capture_area_set(dev, 0, 0, width, height);
356
Frank Schaefer753aee72014-03-24 16:33:14 -0300357 return em28xx_scaler_set(dev, v4l2->hscale, v4l2->vscale);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300358}
359
360/* Set USB alternate setting for analog video */
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300361static int em28xx_set_alternate(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300362{
Frank Schaefer753aee72014-03-24 16:33:14 -0300363 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300364 int errCode;
365 int i;
Frank Schaefer753aee72014-03-24 16:33:14 -0300366 unsigned int min_pkt_size = v4l2->width * 2 + 4;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300367
368 /* NOTE: for isoc transfers, only alt settings > 0 are allowed
369 bulk transfers seem to work only with alt=0 ! */
370 dev->alt = 0;
371 if ((alt > 0) && (alt < dev->num_alt)) {
372 em28xx_videodbg("alternate forced to %d\n", dev->alt);
373 dev->alt = alt;
374 goto set_alt;
375 }
376 if (dev->analog_xfer_bulk)
377 goto set_alt;
378
379 /* When image size is bigger than a certain value,
380 the frame size should be increased, otherwise, only
381 green screen will be received.
382 */
Frank Schaefer753aee72014-03-24 16:33:14 -0300383 if (v4l2->width * 2 * v4l2->height > 720 * 240 * 2)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300384 min_pkt_size *= 2;
385
386 for (i = 0; i < dev->num_alt; i++) {
387 /* stop when the selected alt setting offers enough bandwidth */
388 if (dev->alt_max_pkt_size_isoc[i] >= min_pkt_size) {
389 dev->alt = i;
390 break;
391 /* otherwise make sure that we end up with the maximum bandwidth
392 because the min_pkt_size equation might be wrong...
393 */
394 } else if (dev->alt_max_pkt_size_isoc[i] >
395 dev->alt_max_pkt_size_isoc[dev->alt])
396 dev->alt = i;
397 }
398
399set_alt:
400 /* NOTE: for bulk transfers, we need to call usb_set_interface()
401 * even if the previous settings were the same. Otherwise streaming
402 * fails with all urbs having status = -EOVERFLOW ! */
403 if (dev->analog_xfer_bulk) {
404 dev->max_pkt_size = 512; /* USB 2.0 spec */
405 dev->packet_multiplier = EM28XX_BULK_PACKET_MULTIPLIER;
406 } else { /* isoc */
407 em28xx_videodbg("minimum isoc packet size: %u (alt=%d)\n",
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -0300408 min_pkt_size, dev->alt);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300409 dev->max_pkt_size =
410 dev->alt_max_pkt_size_isoc[dev->alt];
411 dev->packet_multiplier = EM28XX_NUM_ISOC_PACKETS;
412 }
413 em28xx_videodbg("setting alternate %d with wMaxPacketSize=%u\n",
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -0300414 dev->alt, dev->max_pkt_size);
Frank Schaefer961717b2014-01-13 19:02:06 -0300415 errCode = usb_set_interface(dev->udev, dev->ifnum, dev->alt);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300416 if (errCode < 0) {
417 em28xx_errdev("cannot change alternate number to %d (error=%i)\n",
418 dev->alt, errCode);
419 return errCode;
420 }
421 return 0;
422}
423
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300424/* ------------------------------------------------------------------
425 DMA and thread functions
426 ------------------------------------------------------------------*/
427
428/*
Frank Schaefer948a49a2012-12-08 11:31:25 -0300429 * Finish the current buffer
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300430 */
Frank Schaefer948a49a2012-12-08 11:31:25 -0300431static inline void finish_buffer(struct em28xx *dev,
432 struct em28xx_buffer *buf)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300433{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300434 em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->top_field);
435
Frank Schaeferf0e38232014-03-24 16:33:20 -0300436 buf->vb.v4l2_buf.sequence = dev->v4l2->field_count++;
Frank Schaefer662c97c2014-08-09 06:37:21 -0300437 if (dev->v4l2->progressive)
438 buf->vb.v4l2_buf.field = V4L2_FIELD_NONE;
439 else
440 buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300441 v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
442
443 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300444}
445
446/*
Frank Schaefer36016a32012-12-08 11:31:32 -0300447 * Copy picture data from USB buffer to videobuf buffer
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300448 */
449static void em28xx_copy_video(struct em28xx *dev,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300450 struct em28xx_buffer *buf,
Frank Schaefer36016a32012-12-08 11:31:32 -0300451 unsigned char *usb_buf,
Frank Schaefer4078d622012-12-08 11:31:29 -0300452 unsigned long len)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300453{
Frank Schaefer58159172014-03-24 16:33:18 -0300454 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300455 void *fieldstart, *startwrite, *startread;
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300456 int linesdone, currlinedone, offset, lencopy, remain;
Frank Schaefer58159172014-03-24 16:33:18 -0300457 int bytesperline = v4l2->width << 1;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300458
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300459 if (buf->pos + len > buf->length)
460 len = buf->length - buf->pos;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300461
Frank Schaefer36016a32012-12-08 11:31:32 -0300462 startread = usb_buf;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300463 remain = len;
464
Frank Schaefer58159172014-03-24 16:33:18 -0300465 if (v4l2->progressive || buf->top_field)
Frank Schaefer36016a32012-12-08 11:31:32 -0300466 fieldstart = buf->vb_buf;
Frank Schaeferc02ec712012-11-08 14:11:33 -0300467 else /* interlaced mode, even nr. of lines */
Frank Schaefer36016a32012-12-08 11:31:32 -0300468 fieldstart = buf->vb_buf + bytesperline;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300469
Frank Schaefer87325332012-12-08 11:31:27 -0300470 linesdone = buf->pos / bytesperline;
471 currlinedone = buf->pos % bytesperline;
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -0300472
Frank Schaefer58159172014-03-24 16:33:18 -0300473 if (v4l2->progressive)
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -0300474 offset = linesdone * bytesperline + currlinedone;
475 else
476 offset = linesdone * bytesperline * 2 + currlinedone;
477
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300478 startwrite = fieldstart + offset;
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300479 lencopy = bytesperline - currlinedone;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300480 lencopy = lencopy > remain ? remain : lencopy;
481
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300482 if ((char *)startwrite + lencopy > (char *)buf->vb_buf + buf->length) {
Mauro Carvalho Chehab7983b772014-09-24 20:36:07 -0300483 em28xx_isocdbg("Overflow of %zu bytes past buffer end (1)\n",
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -0300484 ((char *)startwrite + lencopy) -
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300485 ((char *)buf->vb_buf + buf->length));
486 remain = (char *)buf->vb_buf + buf->length -
Frank Schaefer36016a32012-12-08 11:31:32 -0300487 (char *)startwrite;
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -0300488 lencopy = remain;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300489 }
Aidan Thorntone0fadfd342008-04-13 14:56:02 -0300490 if (lencopy <= 0)
491 return;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300492 memcpy(startwrite, startread, lencopy);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300493
494 remain -= lencopy;
495
496 while (remain > 0) {
Frank Schaefer58159172014-03-24 16:33:18 -0300497 if (v4l2->progressive)
Frank Schaeferc02ec712012-11-08 14:11:33 -0300498 startwrite += lencopy;
499 else
500 startwrite += lencopy + bytesperline;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300501 startread += lencopy;
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300502 if (bytesperline > remain)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300503 lencopy = remain;
504 else
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300505 lencopy = bytesperline;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300506
Frank Schaefer36016a32012-12-08 11:31:32 -0300507 if ((char *)startwrite + lencopy > (char *)buf->vb_buf +
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300508 buf->length) {
Mauro Carvalho Chehab7983b772014-09-24 20:36:07 -0300509 em28xx_isocdbg("Overflow of %zu bytes past buffer end"
Devin Heitmuellere3ba4d32009-09-15 00:18:06 -0300510 "(2)\n",
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300511 ((char *)startwrite + lencopy) -
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300512 ((char *)buf->vb_buf + buf->length));
513 lencopy = remain = (char *)buf->vb_buf + buf->length -
514 (char *)startwrite;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300515 }
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300516 if (lencopy <= 0)
517 break;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300518
519 memcpy(startwrite, startread, lencopy);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300520
521 remain -= lencopy;
522 }
523
Frank Schaefer87325332012-12-08 11:31:27 -0300524 buf->pos += len;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300525}
526
Frank Schaefer36016a32012-12-08 11:31:32 -0300527/*
528 * Copy VBI data from USB buffer to videobuf buffer
529 */
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300530static void em28xx_copy_vbi(struct em28xx *dev,
Frank Schaefer87325332012-12-08 11:31:27 -0300531 struct em28xx_buffer *buf,
Frank Schaefer36016a32012-12-08 11:31:32 -0300532 unsigned char *usb_buf,
Frank Schaefer4078d622012-12-08 11:31:29 -0300533 unsigned long len)
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300534{
Frank Schaefer36016a32012-12-08 11:31:32 -0300535 unsigned int offset;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300536
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300537 if (buf->pos + len > buf->length)
538 len = buf->length - buf->pos;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300539
Frank Schaefer87325332012-12-08 11:31:27 -0300540 offset = buf->pos;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300541 /* Make sure the bottom field populates the second half of the frame */
Frank Schaefer36016a32012-12-08 11:31:32 -0300542 if (buf->top_field == 0)
Frank Schaefer753aee72014-03-24 16:33:14 -0300543 offset += dev->v4l2->vbi_width * dev->v4l2->vbi_height;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300544
Frank Schaefer36016a32012-12-08 11:31:32 -0300545 memcpy(buf->vb_buf + offset, usb_buf, len);
Frank Schaefer87325332012-12-08 11:31:27 -0300546 buf->pos += len;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300547}
548
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300549static inline void print_err_status(struct em28xx *dev,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -0300550 int packet, int status)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300551{
552 char *errmsg = "Unknown";
553
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300554 switch (status) {
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300555 case -ENOENT:
556 errmsg = "unlinked synchronuously";
557 break;
558 case -ECONNRESET:
559 errmsg = "unlinked asynchronuously";
560 break;
561 case -ENOSR:
562 errmsg = "Buffer error (overrun)";
563 break;
564 case -EPIPE:
565 errmsg = "Stalled (device not responding)";
566 break;
567 case -EOVERFLOW:
568 errmsg = "Babble (bad cable?)";
569 break;
570 case -EPROTO:
571 errmsg = "Bit-stuff error (bad cable?)";
572 break;
573 case -EILSEQ:
574 errmsg = "CRC/Timeout (could be anything)";
575 break;
576 case -ETIME:
577 errmsg = "Device does not respond";
578 break;
579 }
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300580 if (packet < 0) {
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300581 em28xx_isocdbg("URB status %d [%s].\n", status, errmsg);
582 } else {
583 em28xx_isocdbg("URB packet %d, status %d [%s].\n",
584 packet, status, errmsg);
585 }
586}
587
588/*
Frank Schaefer24a6d842012-12-08 11:31:24 -0300589 * get the next available buffer from dma queue
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300590 */
Frank Schaefer24a6d842012-12-08 11:31:24 -0300591static inline struct em28xx_buffer *get_next_buf(struct em28xx *dev,
592 struct em28xx_dmaqueue *dma_q)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300593{
Frank Schaefer24a6d842012-12-08 11:31:24 -0300594 struct em28xx_buffer *buf;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300595
Mauro Carvalho Chehabdbecb442008-04-13 15:08:55 -0300596 if (list_empty(&dma_q->active)) {
597 em28xx_isocdbg("No active queue to serve\n");
Frank Schaefer24a6d842012-12-08 11:31:24 -0300598 return NULL;
Mauro Carvalho Chehabdbecb442008-04-13 15:08:55 -0300599 }
600
Mauro Carvalho Chehabdbecb442008-04-13 15:08:55 -0300601 /* Get the next buffer */
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300602 buf = list_entry(dma_q->active.next, struct em28xx_buffer, list);
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300603 /* Cleans up buffer - Useful for testing for frame/URB loss */
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300604 list_del(&buf->list);
Frank Schaefer87325332012-12-08 11:31:27 -0300605 buf->pos = 0;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300606 buf->vb_buf = buf->mem;
Mauro Carvalho Chehabcb784722008-04-13 15:06:52 -0300607
Frank Schaefer24a6d842012-12-08 11:31:24 -0300608 return buf;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300609}
610
Frank Schaefere04c00d2012-12-08 11:31:30 -0300611/*
612 * Finish the current buffer if completed and prepare for the next field
613 */
614static struct em28xx_buffer *
615finish_field_prepare_next(struct em28xx *dev,
616 struct em28xx_buffer *buf,
617 struct em28xx_dmaqueue *dma_q)
618{
Frank Schaefer58159172014-03-24 16:33:18 -0300619 struct em28xx_v4l2 *v4l2 = dev->v4l2;
620
Frank Schaeferf0e38232014-03-24 16:33:20 -0300621 if (v4l2->progressive || v4l2->top_field) { /* Brand new frame */
Frank Schaefere04c00d2012-12-08 11:31:30 -0300622 if (buf != NULL)
623 finish_buffer(dev, buf);
624 buf = get_next_buf(dev, dma_q);
625 }
626 if (buf != NULL) {
Frank Schaeferf0e38232014-03-24 16:33:20 -0300627 buf->top_field = v4l2->top_field;
Frank Schaefere04c00d2012-12-08 11:31:30 -0300628 buf->pos = 0;
629 }
630
631 return buf;
632}
633
Frank Schaefer227b7c92012-12-08 11:31:31 -0300634/*
635 * Process data packet according to the em2710/em2750/em28xx frame data format
636 */
637static inline void process_frame_data_em28xx(struct em28xx *dev,
638 unsigned char *data_pkt,
639 unsigned int data_len)
640{
Frank Schaefer753aee72014-03-24 16:33:14 -0300641 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300642 struct em28xx_buffer *buf = dev->usb_ctl.vid_buf;
643 struct em28xx_buffer *vbi_buf = dev->usb_ctl.vbi_buf;
644 struct em28xx_dmaqueue *dma_q = &dev->vidq;
645 struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq;
646
647 /* capture type 0 = vbi start
648 capture type 1 = vbi in progress
649 capture type 2 = video start
650 capture type 3 = video in progress */
651 if (data_len >= 4) {
652 /* NOTE: Headers are always 4 bytes and
653 * never split across packets */
654 if (data_pkt[0] == 0x88 && data_pkt[1] == 0x88 &&
655 data_pkt[2] == 0x88 && data_pkt[3] == 0x88) {
656 /* Continuation */
657 data_pkt += 4;
658 data_len -= 4;
659 } else if (data_pkt[0] == 0x33 && data_pkt[1] == 0x95) {
660 /* Field start (VBI mode) */
Frank Schaeferf0e38232014-03-24 16:33:20 -0300661 v4l2->capture_type = 0;
662 v4l2->vbi_read = 0;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300663 em28xx_isocdbg("VBI START HEADER !!!\n");
Frank Schaeferf0e38232014-03-24 16:33:20 -0300664 v4l2->top_field = !(data_pkt[2] & 1);
Frank Schaefer227b7c92012-12-08 11:31:31 -0300665 data_pkt += 4;
666 data_len -= 4;
667 } else if (data_pkt[0] == 0x22 && data_pkt[1] == 0x5a) {
668 /* Field start (VBI disabled) */
Frank Schaeferf0e38232014-03-24 16:33:20 -0300669 v4l2->capture_type = 2;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300670 em28xx_isocdbg("VIDEO START HEADER !!!\n");
Frank Schaeferf0e38232014-03-24 16:33:20 -0300671 v4l2->top_field = !(data_pkt[2] & 1);
Frank Schaefer227b7c92012-12-08 11:31:31 -0300672 data_pkt += 4;
673 data_len -= 4;
674 }
675 }
676 /* NOTE: With bulk transfers, intermediate data packets
677 * have no continuation header */
678
Frank Schaeferf0e38232014-03-24 16:33:20 -0300679 if (v4l2->capture_type == 0) {
Frank Schaefer227b7c92012-12-08 11:31:31 -0300680 vbi_buf = finish_field_prepare_next(dev, vbi_buf, vbi_dma_q);
681 dev->usb_ctl.vbi_buf = vbi_buf;
Frank Schaeferf0e38232014-03-24 16:33:20 -0300682 v4l2->capture_type = 1;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300683 }
684
Frank Schaeferf0e38232014-03-24 16:33:20 -0300685 if (v4l2->capture_type == 1) {
Frank Schaefer753aee72014-03-24 16:33:14 -0300686 int vbi_size = v4l2->vbi_width * v4l2->vbi_height;
Frank Schaeferf0e38232014-03-24 16:33:20 -0300687 int vbi_data_len = ((v4l2->vbi_read + data_len) > vbi_size) ?
688 (vbi_size - v4l2->vbi_read) : data_len;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300689
690 /* Copy VBI data */
691 if (vbi_buf != NULL)
692 em28xx_copy_vbi(dev, vbi_buf, data_pkt, vbi_data_len);
Frank Schaeferf0e38232014-03-24 16:33:20 -0300693 v4l2->vbi_read += vbi_data_len;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300694
695 if (vbi_data_len < data_len) {
696 /* Continue with copying video data */
Frank Schaeferf0e38232014-03-24 16:33:20 -0300697 v4l2->capture_type = 2;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300698 data_pkt += vbi_data_len;
699 data_len -= vbi_data_len;
700 }
701 }
702
Frank Schaeferf0e38232014-03-24 16:33:20 -0300703 if (v4l2->capture_type == 2) {
Frank Schaefer227b7c92012-12-08 11:31:31 -0300704 buf = finish_field_prepare_next(dev, buf, dma_q);
705 dev->usb_ctl.vid_buf = buf;
Frank Schaeferf0e38232014-03-24 16:33:20 -0300706 v4l2->capture_type = 3;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300707 }
708
Frank Schaeferf0e38232014-03-24 16:33:20 -0300709 if (v4l2->capture_type == 3 && buf != NULL && data_len > 0)
Frank Schaefer227b7c92012-12-08 11:31:31 -0300710 em28xx_copy_video(dev, buf, data_pkt, data_len);
711}
712
Frank Schaefere507e0e2013-03-26 13:38:38 -0300713/*
714 * Process data packet according to the em25xx/em276x/7x/8x frame data format
715 */
716static inline void process_frame_data_em25xx(struct em28xx *dev,
717 unsigned char *data_pkt,
718 unsigned int data_len)
719{
720 struct em28xx_buffer *buf = dev->usb_ctl.vid_buf;
721 struct em28xx_dmaqueue *dmaq = &dev->vidq;
Frank Schaeferf0e38232014-03-24 16:33:20 -0300722 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab7e6c8c12014-09-03 15:06:13 -0300723 bool frame_end = false;
Frank Schaefere507e0e2013-03-26 13:38:38 -0300724
725 /* Check for header */
726 /* NOTE: at least with bulk transfers, only the first packet
727 * has a header and has always set the FRAME_END bit */
728 if (data_len >= 2) { /* em25xx header is only 2 bytes long */
729 if ((data_pkt[0] == EM25XX_FRMDATAHDR_BYTE1) &&
730 ((data_pkt[1] & ~EM25XX_FRMDATAHDR_BYTE2_MASK) == 0x00)) {
Frank Schaeferf0e38232014-03-24 16:33:20 -0300731 v4l2->top_field = !(data_pkt[1] &
Frank Schaefere507e0e2013-03-26 13:38:38 -0300732 EM25XX_FRMDATAHDR_BYTE2_FRAME_ID);
733 frame_end = data_pkt[1] &
734 EM25XX_FRMDATAHDR_BYTE2_FRAME_END;
735 data_pkt += 2;
736 data_len -= 2;
737 }
738
739 /* Finish field and prepare next (BULK only) */
740 if (dev->analog_xfer_bulk && frame_end) {
741 buf = finish_field_prepare_next(dev, buf, dmaq);
742 dev->usb_ctl.vid_buf = buf;
743 }
744 /* NOTE: in ISOC mode when a new frame starts and buf==NULL,
745 * we COULD already prepare a buffer here to avoid skipping the
746 * first frame.
747 */
748 }
749
750 /* Copy data */
751 if (buf != NULL && data_len > 0)
752 em28xx_copy_video(dev, buf, data_pkt, data_len);
753
754 /* Finish frame (ISOC only) => avoids lag of 1 frame */
755 if (!dev->analog_xfer_bulk && frame_end) {
756 buf = finish_field_prepare_next(dev, buf, dmaq);
757 dev->usb_ctl.vid_buf = buf;
758 }
759
760 /* NOTE: Tested with USB bulk transfers only !
761 * The wording in the datasheet suggests that isoc might work different.
762 * The current code assumes that with isoc transfers each packet has a
763 * header like with the other em28xx devices.
764 */
765 /* NOTE: Support for interlaced mode is pure theory. It has not been
766 * tested and it is unknown if these devices actually support it. */
767 /* NOTE: No VBI support yet (these chips likely do not support VBI). */
768}
769
Frank Schaefer960da932012-11-25 06:37:37 -0300770/* Processes and copies the URB data content (video and VBI data) */
Frank Schaefer0fa4a402012-11-08 14:11:45 -0300771static inline int em28xx_urb_data_copy(struct em28xx *dev, struct urb *urb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300772{
Frank Schaefer227b7c92012-12-08 11:31:31 -0300773 int xfer_bulk, num_packets, i;
774 unsigned char *usb_data_pkt;
775 unsigned int usb_data_len;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300776
777 if (!dev)
778 return 0;
779
Frank Schaefer2665c292012-12-27 19:02:43 -0300780 if (dev->disconnected)
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300781 return 0;
782
Frank Schaefer1653cb0c2012-11-08 14:11:44 -0300783 if (urb->status < 0)
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300784 print_err_status(dev, -1, urb->status);
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300785
Frank Schaefer4601cc32012-11-08 14:11:46 -0300786 xfer_bulk = usb_pipebulk(urb->pipe);
787
Frank Schaefer4601cc32012-11-08 14:11:46 -0300788 if (xfer_bulk) /* bulk */
789 num_packets = 1;
790 else /* isoc */
791 num_packets = urb->number_of_packets;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300792
Frank Schaefer4601cc32012-11-08 14:11:46 -0300793 for (i = 0; i < num_packets; i++) {
794 if (xfer_bulk) { /* bulk */
Frank Schaefer227b7c92012-12-08 11:31:31 -0300795 usb_data_len = urb->actual_length;
Frank Schaefer4601cc32012-11-08 14:11:46 -0300796
Frank Schaefer227b7c92012-12-08 11:31:31 -0300797 usb_data_pkt = urb->transfer_buffer;
Frank Schaefer4601cc32012-11-08 14:11:46 -0300798 } else { /* isoc */
799 if (urb->iso_frame_desc[i].status < 0) {
800 print_err_status(dev, i,
801 urb->iso_frame_desc[i].status);
802 if (urb->iso_frame_desc[i].status != -EPROTO)
803 continue;
804 }
805
Frank Schaefer227b7c92012-12-08 11:31:31 -0300806 usb_data_len = urb->iso_frame_desc[i].actual_length;
807 if (usb_data_len > dev->max_pkt_size) {
Frank Schaefer4601cc32012-11-08 14:11:46 -0300808 em28xx_isocdbg("packet bigger than packet size");
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300809 continue;
Frank Schaefer4601cc32012-11-08 14:11:46 -0300810 }
811
Frank Schaefer227b7c92012-12-08 11:31:31 -0300812 usb_data_pkt = urb->transfer_buffer +
813 urb->iso_frame_desc[i].offset;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300814 }
815
Frank Schaefer227b7c92012-12-08 11:31:31 -0300816 if (usb_data_len == 0) {
Frank Schaefer4601cc32012-11-08 14:11:46 -0300817 /* NOTE: happens very often with isoc transfers */
818 /* em28xx_usbdbg("packet %d is empty",i); - spammy */
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300819 continue;
820 }
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300821
Frank Schaefere507e0e2013-03-26 13:38:38 -0300822 if (dev->is_em25xx)
823 process_frame_data_em25xx(dev,
824 usb_data_pkt, usb_data_len);
825 else
826 process_frame_data_em28xx(dev,
827 usb_data_pkt, usb_data_len);
828
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300829 }
Frank Schaefer227b7c92012-12-08 11:31:31 -0300830 return 1;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300831}
832
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300833static int get_ressource(enum v4l2_buf_type f_type)
834{
835 switch (f_type) {
836 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
837 return EM28XX_RESOURCE_VIDEO;
838 case V4L2_BUF_TYPE_VBI_CAPTURE:
839 return EM28XX_RESOURCE_VBI;
840 default:
841 BUG();
842 return 0;
843 }
844}
845
846/* Usage lock check functions */
847static int res_get(struct em28xx *dev, enum v4l2_buf_type f_type)
848{
849 int res_type = get_ressource(f_type);
850
851 /* is it free? */
852 if (dev->resources & res_type) {
853 /* no, someone else uses it */
854 return -EBUSY;
855 }
856
857 /* it's free, grab it */
858 dev->resources |= res_type;
859 em28xx_videodbg("res: get %d\n", res_type);
860 return 0;
861}
862
863static void res_free(struct em28xx *dev, enum v4l2_buf_type f_type)
864{
865 int res_type = get_ressource(f_type);
866
867 dev->resources &= ~res_type;
868 em28xx_videodbg("res: put %d\n", res_type);
869}
870
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300871/* ------------------------------------------------------------------
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300872 Videobuf2 operations
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300873 ------------------------------------------------------------------*/
874
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300875static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
876 unsigned int *nbuffers, unsigned int *nplanes,
877 unsigned int sizes[], void *alloc_ctxs[])
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300878{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300879 struct em28xx *dev = vb2_get_drv_priv(vq);
Frank Schaefer753aee72014-03-24 16:33:14 -0300880 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300881 unsigned long size;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300882
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300883 if (fmt)
884 size = fmt->fmt.pix.sizeimage;
885 else
Frank Schaefer753aee72014-03-24 16:33:14 -0300886 size =
Frank Schaefer06e20672014-03-24 16:33:17 -0300887 (v4l2->width * v4l2->height * v4l2->format->depth + 7) >> 3;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -0300888
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300889 if (size == 0)
890 return -EINVAL;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300891
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300892 if (0 == *nbuffers)
893 *nbuffers = 32;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300894
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300895 *nplanes = 1;
896 sizes[0] = size;
Mauro Carvalho Chehabd2d9fbf2008-04-17 21:38:53 -0300897
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300898 return 0;
899}
900
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300901static int
902buffer_prepare(struct vb2_buffer *vb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300903{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300904 struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue);
Frank Schaefer753aee72014-03-24 16:33:14 -0300905 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300906 struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
907 unsigned long size;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300908
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300909 em28xx_videodbg("%s, field=%d\n", __func__, vb->v4l2_buf.field);
Aidan Thornton3b5fa922008-04-13 15:09:36 -0300910
Frank Schaefer06e20672014-03-24 16:33:17 -0300911 size = (v4l2->width * v4l2->height * v4l2->format->depth + 7) >> 3;
Aidan Thornton3b5fa922008-04-13 15:09:36 -0300912
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300913 if (vb2_plane_size(vb, 0) < size) {
914 em28xx_videodbg("%s data will not fit into plane (%lu < %lu)\n",
915 __func__, vb2_plane_size(vb, 0), size);
916 return -EINVAL;
917 }
918 vb2_set_plane_payload(&buf->vb, 0, size);
919
920 return 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300921}
922
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300923int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300924{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300925 struct em28xx *dev = vb2_get_drv_priv(vq);
Frank Schaeferf0e38232014-03-24 16:33:20 -0300926 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300927 struct v4l2_frequency f;
928 int rc = 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300929
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300930 em28xx_videodbg("%s\n", __func__);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300931
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300932 /* Make sure streaming is not already in progress for this type
933 of filehandle (e.g. video, vbi) */
934 rc = res_get(dev, vq->type);
935 if (rc)
936 return rc;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300937
Frank Schaefer8139a4d2014-05-11 17:59:04 -0300938 if (v4l2->streaming_users == 0) {
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300939 /* First active streaming user, so allocate all the URBs */
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300940
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300941 /* Allocate the USB bandwidth */
942 em28xx_set_alternate(dev);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300943
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300944 /* Needed, since GPIO might have disabled power of
945 some i2c device
946 */
947 em28xx_wake_i2c(dev);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300948
Frank Schaeferf0e38232014-03-24 16:33:20 -0300949 v4l2->capture_type = -1;
Frank Schaefer960da932012-11-25 06:37:37 -0300950 rc = em28xx_init_usb_xfer(dev, EM28XX_ANALOG_MODE,
951 dev->analog_xfer_bulk,
952 EM28XX_NUM_BUFS,
953 dev->max_pkt_size,
954 dev->packet_multiplier,
955 em28xx_urb_data_copy);
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300956 if (rc < 0)
Frank Schaefer032f1dd2013-10-10 15:31:53 -0300957 return rc;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300958
959 /*
960 * djh: it's not clear whether this code is still needed. I'm
961 * leaving it in here for now entirely out of concern for
962 * backward compatibility (the old code did it)
963 */
964
965 /* Ask tuner to go to analog or radio mode */
966 memset(&f, 0, sizeof(f));
Frank Schaefer3854b0d2014-03-24 16:33:22 -0300967 f.frequency = v4l2->frequency;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300968 if (vq->owner && vq->owner->vdev->vfl_type == VFL_TYPE_RADIO)
969 f.type = V4L2_TUNER_RADIO;
970 else
971 f.type = V4L2_TUNER_ANALOG_TV;
Frank Schaeferf0e38232014-03-24 16:33:20 -0300972 v4l2_device_call_all(&v4l2->v4l2_dev,
Frank Schaefer95d26082014-03-24 16:33:09 -0300973 0, tuner, s_frequency, &f);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300974 }
975
Frank Schaefer8139a4d2014-05-11 17:59:04 -0300976 v4l2->streaming_users++;
Frank Schaefer032f1dd2013-10-10 15:31:53 -0300977
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300978 return rc;
979}
980
Hans Verkuile37559b2014-04-17 02:47:21 -0300981static void em28xx_stop_streaming(struct vb2_queue *vq)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300982{
983 struct em28xx *dev = vb2_get_drv_priv(vq);
Frank Schaefer8139a4d2014-05-11 17:59:04 -0300984 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300985 struct em28xx_dmaqueue *vidq = &dev->vidq;
986 unsigned long flags = 0;
987
988 em28xx_videodbg("%s\n", __func__);
989
990 res_free(dev, vq->type);
991
Frank Schaefer8139a4d2014-05-11 17:59:04 -0300992 if (v4l2->streaming_users-- == 1) {
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300993 /* Last active user, so shutdown all the URBS */
994 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
995 }
996
997 spin_lock_irqsave(&dev->slock, flags);
Frank Schaefer627530c2014-08-09 06:37:20 -0300998 if (dev->usb_ctl.vid_buf != NULL) {
999 vb2_buffer_done(&dev->usb_ctl.vid_buf->vb, VB2_BUF_STATE_ERROR);
1000 dev->usb_ctl.vid_buf = NULL;
1001 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001002 while (!list_empty(&vidq->active)) {
1003 struct em28xx_buffer *buf;
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001004
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001005 buf = list_entry(vidq->active.next, struct em28xx_buffer, list);
1006 list_del(&buf->list);
1007 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
1008 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001009 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001010}
1011
Hans Verkuile37559b2014-04-17 02:47:21 -03001012void em28xx_stop_vbi_streaming(struct vb2_queue *vq)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001013{
1014 struct em28xx *dev = vb2_get_drv_priv(vq);
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001015 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001016 struct em28xx_dmaqueue *vbiq = &dev->vbiq;
1017 unsigned long flags = 0;
1018
1019 em28xx_videodbg("%s\n", __func__);
1020
1021 res_free(dev, vq->type);
1022
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001023 if (v4l2->streaming_users-- == 1) {
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001024 /* Last active user, so shutdown all the URBS */
1025 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
1026 }
1027
1028 spin_lock_irqsave(&dev->slock, flags);
Frank Schaefer627530c2014-08-09 06:37:20 -03001029 if (dev->usb_ctl.vbi_buf != NULL) {
1030 vb2_buffer_done(&dev->usb_ctl.vbi_buf->vb, VB2_BUF_STATE_ERROR);
1031 dev->usb_ctl.vbi_buf = NULL;
1032 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001033 while (!list_empty(&vbiq->active)) {
1034 struct em28xx_buffer *buf;
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001035
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001036 buf = list_entry(vbiq->active.next, struct em28xx_buffer, list);
1037 list_del(&buf->list);
1038 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
1039 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001040 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001041}
1042
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001043static void
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001044buffer_queue(struct vb2_buffer *vb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001045{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001046 struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue);
1047 struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
1048 struct em28xx_dmaqueue *vidq = &dev->vidq;
1049 unsigned long flags = 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001050
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001051 em28xx_videodbg("%s\n", __func__);
1052 buf->mem = vb2_plane_vaddr(vb, 0);
1053 buf->length = vb2_plane_size(vb, 0);
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001054
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001055 spin_lock_irqsave(&dev->slock, flags);
1056 list_add_tail(&buf->list, &vidq->active);
1057 spin_unlock_irqrestore(&dev->slock, flags);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001058}
1059
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001060static struct vb2_ops em28xx_video_qops = {
1061 .queue_setup = queue_setup,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001062 .buf_prepare = buffer_prepare,
1063 .buf_queue = buffer_queue,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001064 .start_streaming = em28xx_start_analog_streaming,
1065 .stop_streaming = em28xx_stop_streaming,
1066 .wait_prepare = vb2_ops_wait_prepare,
1067 .wait_finish = vb2_ops_wait_finish,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001068};
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001069
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001070static int em28xx_vb2_setup(struct em28xx *dev)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001071{
1072 int rc;
1073 struct vb2_queue *q;
Frank Schaefer27a36df2014-03-24 16:33:13 -03001074 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001075
1076 /* Setup Videobuf2 for Video capture */
Frank Schaefer27a36df2014-03-24 16:33:13 -03001077 q = &v4l2->vb_vidq;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001078 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Mauro Carvalho Chehabef85cd92013-01-06 00:34:22 -02001079 q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
Sakari Ailusade48682014-02-25 19:12:19 -03001080 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001081 q->drv_priv = dev;
1082 q->buf_struct_size = sizeof(struct em28xx_buffer);
1083 q->ops = &em28xx_video_qops;
1084 q->mem_ops = &vb2_vmalloc_memops;
1085
1086 rc = vb2_queue_init(q);
1087 if (rc < 0)
1088 return rc;
1089
1090 /* Setup Videobuf2 for VBI capture */
Frank Schaefer27a36df2014-03-24 16:33:13 -03001091 q = &v4l2->vb_vbiq;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001092 q->type = V4L2_BUF_TYPE_VBI_CAPTURE;
1093 q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR;
Sakari Ailusade48682014-02-25 19:12:19 -03001094 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001095 q->drv_priv = dev;
1096 q->buf_struct_size = sizeof(struct em28xx_buffer);
1097 q->ops = &em28xx_vbi_qops;
1098 q->mem_ops = &vb2_vmalloc_memops;
1099
1100 rc = vb2_queue_init(q);
1101 if (rc < 0)
1102 return rc;
1103
1104 return 0;
1105}
1106
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001107/********************* v4l2 interface **************************************/
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001108
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001109static void video_mux(struct em28xx *dev, int index)
1110{
Frank Schaefer95d26082014-03-24 16:33:09 -03001111 struct v4l2_device *v4l2_dev = &dev->v4l2->v4l2_dev;
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001112
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001113 dev->ctl_input = index;
1114 dev->ctl_ainput = INPUT(index)->amux;
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001115 dev->ctl_aoutput = INPUT(index)->aout;
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001116
Mauro Carvalho Chehabe879b8e2008-11-20 13:39:39 -03001117 if (!dev->ctl_aoutput)
1118 dev->ctl_aoutput = EM28XX_AOUT_MASTER;
1119
Frank Schaefer95d26082014-03-24 16:33:09 -03001120 v4l2_device_call_all(v4l2_dev, 0, video, s_routing,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001121 INPUT(index)->vmux, 0, 0);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001122
Mauro Carvalho Chehab505b6d02008-11-25 09:39:50 -03001123 if (dev->board.has_msp34xx) {
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001124 if (dev->i2s_speed) {
Frank Schaefer95d26082014-03-24 16:33:09 -03001125 v4l2_device_call_all(v4l2_dev, 0, audio,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001126 s_i2s_clock_freq, dev->i2s_speed);
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001127 }
Hans Verkuil2474ed42006-03-19 12:35:57 -03001128 /* Note: this is msp3400 specific */
Frank Schaefer95d26082014-03-24 16:33:09 -03001129 v4l2_device_call_all(v4l2_dev, 0, audio, s_routing,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001130 dev->ctl_ainput,
1131 MSP_OUTPUT(MSP_SC_IN_DSP_SCART1), 0);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001132 }
Mauro Carvalho Chehab539c96d2008-01-05 09:53:54 -03001133
Vitaly Wool2bd1d9e2009-03-04 08:27:52 -03001134 if (dev->board.adecoder != EM28XX_NOADECODER) {
Frank Schaefer95d26082014-03-24 16:33:09 -03001135 v4l2_device_call_all(v4l2_dev, 0, audio, s_routing,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001136 dev->ctl_ainput, dev->ctl_aoutput, 0);
Vitaly Wool2bd1d9e2009-03-04 08:27:52 -03001137 }
1138
Mauro Carvalho Chehab00b87302008-02-06 18:34:13 -03001139 em28xx_audio_analog_set(dev);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001140}
1141
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001142static void em28xx_ctrl_notify(struct v4l2_ctrl *ctrl, void *priv)
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001143{
Hans Verkuil081b9452012-09-07 05:43:59 -03001144 struct em28xx *dev = priv;
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001145
Hans Verkuil081b9452012-09-07 05:43:59 -03001146 /*
1147 * In the case of non-AC97 volume controls, we still need
1148 * to do some setups at em28xx, in order to mute/unmute
1149 * and to adjust audio volume. However, the value ranges
1150 * should be checked by the corresponding V4L subdriver.
1151 */
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001152 switch (ctrl->id) {
1153 case V4L2_CID_AUDIO_MUTE:
Hans Verkuil081b9452012-09-07 05:43:59 -03001154 dev->mute = ctrl->val;
1155 em28xx_audio_analog_set(dev);
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001156 break;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001157 case V4L2_CID_AUDIO_VOLUME:
Hans Verkuil081b9452012-09-07 05:43:59 -03001158 dev->volume = ctrl->val;
1159 em28xx_audio_analog_set(dev);
1160 break;
1161 }
1162}
1163
1164static int em28xx_s_ctrl(struct v4l2_ctrl *ctrl)
1165{
Frank Schaeferabc13082014-03-24 16:33:10 -03001166 struct em28xx_v4l2 *v4l2 =
1167 container_of(ctrl->handler, struct em28xx_v4l2, ctrl_handler);
1168 struct em28xx *dev = v4l2->dev;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001169 int ret = -EINVAL;
Hans Verkuil081b9452012-09-07 05:43:59 -03001170
1171 switch (ctrl->id) {
1172 case V4L2_CID_AUDIO_MUTE:
1173 dev->mute = ctrl->val;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001174 ret = em28xx_audio_analog_set(dev);
Hans Verkuil081b9452012-09-07 05:43:59 -03001175 break;
1176 case V4L2_CID_AUDIO_VOLUME:
1177 dev->volume = ctrl->val;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001178 ret = em28xx_audio_analog_set(dev);
1179 break;
1180 case V4L2_CID_CONTRAST:
1181 ret = em28xx_write_reg(dev, EM28XX_R20_YGAIN, ctrl->val);
1182 break;
1183 case V4L2_CID_BRIGHTNESS:
1184 ret = em28xx_write_reg(dev, EM28XX_R21_YOFFSET, ctrl->val);
1185 break;
1186 case V4L2_CID_SATURATION:
1187 ret = em28xx_write_reg(dev, EM28XX_R22_UVGAIN, ctrl->val);
1188 break;
1189 case V4L2_CID_BLUE_BALANCE:
1190 ret = em28xx_write_reg(dev, EM28XX_R23_UOFFSET, ctrl->val);
1191 break;
1192 case V4L2_CID_RED_BALANCE:
1193 ret = em28xx_write_reg(dev, EM28XX_R24_VOFFSET, ctrl->val);
1194 break;
1195 case V4L2_CID_SHARPNESS:
1196 ret = em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, ctrl->val);
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001197 break;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001198 }
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001199
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001200 return (ret < 0) ? ret : 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001201}
1202
Fengguang Wu8068eb82014-01-07 12:50:47 -03001203static const struct v4l2_ctrl_ops em28xx_ctrl_ops = {
Hans Verkuil081b9452012-09-07 05:43:59 -03001204 .s_ctrl = em28xx_s_ctrl,
1205};
1206
Frank Schaefer6b09a212013-02-10 16:05:12 -03001207static void size_to_scale(struct em28xx *dev,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001208 unsigned int width, unsigned int height,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001209 unsigned int *hscale, unsigned int *vscale)
1210{
Mauro Carvalho Chehab55699962009-07-13 20:15:02 -03001211 unsigned int maxw = norm_maxw(dev);
1212 unsigned int maxh = norm_maxh(dev);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001213
1214 *hscale = (((unsigned long)maxw) << 12) / width - 4096L;
Frank Schaefer81685322013-02-10 16:05:11 -03001215 if (*hscale > EM28XX_HVSCALE_MAX)
1216 *hscale = EM28XX_HVSCALE_MAX;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001217
1218 *vscale = (((unsigned long)maxh) << 12) / height - 4096L;
Frank Schaefer81685322013-02-10 16:05:11 -03001219 if (*vscale > EM28XX_HVSCALE_MAX)
1220 *vscale = EM28XX_HVSCALE_MAX;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001221}
1222
Frank Schaeferb8374132013-02-10 16:05:13 -03001223static void scale_to_size(struct em28xx *dev,
1224 unsigned int hscale, unsigned int vscale,
1225 unsigned int *width, unsigned int *height)
1226{
1227 unsigned int maxw = norm_maxw(dev);
1228 unsigned int maxh = norm_maxh(dev);
1229
1230 *width = (((unsigned long)maxw) << 12) / (hscale + 4096L);
1231 *height = (((unsigned long)maxh) << 12) / (vscale + 4096L);
1232}
1233
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001234/* ------------------------------------------------------------------
1235 IOCTL vidioc handling
1236 ------------------------------------------------------------------*/
1237
Hans Verkuil78b526a2008-05-28 12:16:41 -03001238static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001239 struct v4l2_format *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001240{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001241 struct em28xx *dev = video_drvdata(file);
Frank Schaefer753aee72014-03-24 16:33:14 -03001242 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001243
Frank Schaefer753aee72014-03-24 16:33:14 -03001244 f->fmt.pix.width = v4l2->width;
1245 f->fmt.pix.height = v4l2->height;
Frank Schaefer06e20672014-03-24 16:33:17 -03001246 f->fmt.pix.pixelformat = v4l2->format->fourcc;
1247 f->fmt.pix.bytesperline = (v4l2->width * v4l2->format->depth + 7) >> 3;
Frank Schaefer753aee72014-03-24 16:33:14 -03001248 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * v4l2->height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001249 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
1250
1251 /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */
Frank Schaefer58159172014-03-24 16:33:18 -03001252 if (v4l2->progressive)
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -03001253 f->fmt.pix.field = V4L2_FIELD_NONE;
1254 else
Frank Schaefer58159172014-03-24 16:33:18 -03001255 f->fmt.pix.field = v4l2->interlaced_fieldmode ?
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001256 V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001257 return 0;
1258}
1259
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001260static struct em28xx_fmt *format_by_fourcc(unsigned int fourcc)
1261{
1262 unsigned int i;
1263
1264 for (i = 0; i < ARRAY_SIZE(format); i++)
1265 if (format[i].fourcc == fourcc)
1266 return &format[i];
1267
1268 return NULL;
1269}
1270
Hans Verkuil78b526a2008-05-28 12:16:41 -03001271static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001272 struct v4l2_format *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001273{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001274 struct em28xx *dev = video_drvdata(file);
Frank Schaefer58159172014-03-24 16:33:18 -03001275 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Trent Piephoccb83402009-05-30 21:45:46 -03001276 unsigned int width = f->fmt.pix.width;
1277 unsigned int height = f->fmt.pix.height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001278 unsigned int maxw = norm_maxw(dev);
1279 unsigned int maxh = norm_maxh(dev);
1280 unsigned int hscale, vscale;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001281 struct em28xx_fmt *fmt;
1282
1283 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
1284 if (!fmt) {
1285 em28xx_videodbg("Fourcc format (%08x) invalid.\n",
1286 f->fmt.pix.pixelformat);
1287 return -EINVAL;
1288 }
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001289
Mauro Carvalho Chehab55699962009-07-13 20:15:02 -03001290 if (dev->board.is_em2800) {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001291 /* the em2800 can only scale down to 50% */
Trent Piephoccb83402009-05-30 21:45:46 -03001292 height = height > (3 * maxh / 4) ? maxh : maxh / 2;
1293 width = width > (3 * maxw / 4) ? maxw : maxw / 2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001294 /*
1295 * MaxPacketSize for em2800 is too small to capture at full
1296 * resolution use half of maxw as the scaler can only scale
1297 * to 50%
1298 */
Sascha Sommer1020d132012-01-08 16:54:28 -03001299 if (width == maxw && height == maxh)
1300 width /= 2;
Trent Piephoccb83402009-05-30 21:45:46 -03001301 } else {
1302 /* width must even because of the YUYV format
1303 height must be even because of interlacing */
Devin Heitmuellere3ba4d32009-09-15 00:18:06 -03001304 v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh,
1305 1, 0);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001306 }
1307
Frank Schaefer6b09a212013-02-10 16:05:12 -03001308 size_to_scale(dev, width, height, &hscale, &vscale);
Hans Verkuil46f85972013-03-30 05:31:42 -03001309 scale_to_size(dev, hscale, vscale, &width, &height);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001310
1311 f->fmt.pix.width = width;
1312 f->fmt.pix.height = height;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001313 f->fmt.pix.pixelformat = fmt->fourcc;
Hans Verkuile6066db2013-02-06 08:14:47 -03001314 f->fmt.pix.bytesperline = (width * fmt->depth + 7) >> 3;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001315 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001316 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
Frank Schaefer58159172014-03-24 16:33:18 -03001317 if (v4l2->progressive)
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -03001318 f->fmt.pix.field = V4L2_FIELD_NONE;
1319 else
Frank Schaefer58159172014-03-24 16:33:18 -03001320 f->fmt.pix.field = v4l2->interlaced_fieldmode ?
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -03001321 V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
Alban Browaeys51dd4d72013-07-16 19:06:46 -03001322 f->fmt.pix.priv = 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001323
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001324 return 0;
1325}
1326
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001327static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc,
1328 unsigned width, unsigned height)
1329{
1330 struct em28xx_fmt *fmt;
Frank Schaefer753aee72014-03-24 16:33:14 -03001331 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001332
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001333 fmt = format_by_fourcc(fourcc);
1334 if (!fmt)
1335 return -EINVAL;
1336
Frank Schaefer06e20672014-03-24 16:33:17 -03001337 v4l2->format = fmt;
Frank Schaefer753aee72014-03-24 16:33:14 -03001338 v4l2->width = width;
1339 v4l2->height = height;
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001340
1341 /* set new image size */
Frank Schaefer753aee72014-03-24 16:33:14 -03001342 size_to_scale(dev, v4l2->width, v4l2->height,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001343 &v4l2->hscale, &v4l2->vscale);
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001344
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001345 em28xx_resolution_set(dev);
1346
1347 return 0;
1348}
1349
Hans Verkuil78b526a2008-05-28 12:16:41 -03001350static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001351 struct v4l2_format *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001352{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001353 struct em28xx *dev = video_drvdata(file);
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001354 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001355
Mauro Carvalho Chehabc7854c22014-09-19 13:02:12 -03001356 if (vb2_is_busy(&v4l2->vb_vidq))
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001357 return -EBUSY;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001358
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001359 vidioc_try_fmt_vid_cap(file, priv, f);
1360
Hans Verkuil0499a5a2010-09-26 07:34:45 -03001361 return em28xx_set_video_format(dev, f->fmt.pix.pixelformat,
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001362 f->fmt.pix.width, f->fmt.pix.height);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001363}
1364
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001365static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
1366{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001367 struct em28xx *dev = video_drvdata(file);
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001368
Frank Schaefer52faaf72014-03-24 16:33:16 -03001369 *norm = dev->v4l2->norm;
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001370
1371 return 0;
1372}
1373
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001374static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm)
1375{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001376 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001377
Frank Schaefer95d26082014-03-24 16:33:09 -03001378 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, video, querystd, norm);
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001379
1380 return 0;
1381}
1382
Hans Verkuil314527a2013-03-15 06:10:40 -03001383static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001384{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001385 struct em28xx *dev = video_drvdata(file);
Frank Schaefer753aee72014-03-24 16:33:14 -03001386 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001387 struct v4l2_format f;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001388
Frank Schaefer52faaf72014-03-24 16:33:16 -03001389 if (norm == v4l2->norm)
Hans Verkuild8c95c02012-09-07 07:31:54 -03001390 return 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001391
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001392 if (v4l2->streaming_users > 0)
Hans Verkuild8c95c02012-09-07 07:31:54 -03001393 return -EBUSY;
Hans Verkuild8c95c02012-09-07 07:31:54 -03001394
Frank Schaefer52faaf72014-03-24 16:33:16 -03001395 v4l2->norm = norm;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001396
1397 /* Adjusts width/height, if needed */
Hans Verkuild8c95c02012-09-07 07:31:54 -03001398 f.fmt.pix.width = 720;
Hans Verkuil314527a2013-03-15 06:10:40 -03001399 f.fmt.pix.height = (norm & V4L2_STD_525_60) ? 480 : 576;
Hans Verkuil78b526a2008-05-28 12:16:41 -03001400 vidioc_try_fmt_vid_cap(file, priv, &f);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001401
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001402 /* set new image size */
Frank Schaefer753aee72014-03-24 16:33:14 -03001403 v4l2->width = f.fmt.pix.width;
1404 v4l2->height = f.fmt.pix.height;
1405 size_to_scale(dev, v4l2->width, v4l2->height,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001406 &v4l2->hscale, &v4l2->vscale);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001407
1408 em28xx_resolution_set(dev);
Laurent Pinchart8774bed2014-04-28 16:53:01 -03001409 v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_std, v4l2->norm);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001410
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001411 return 0;
1412}
1413
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001414static int vidioc_g_parm(struct file *file, void *priv,
1415 struct v4l2_streamparm *p)
1416{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001417 struct em28xx *dev = video_drvdata(file);
Frank Schaefer52faaf72014-03-24 16:33:16 -03001418 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001419 int rc = 0;
1420
Hans Verkuil86ff7f12012-09-07 06:16:03 -03001421 p->parm.capture.readbuffers = EM28XX_MIN_BUF;
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001422 if (dev->board.is_webcam)
Frank Schaefer52faaf72014-03-24 16:33:16 -03001423 rc = v4l2_device_call_until_err(&v4l2->v4l2_dev, 0,
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001424 video, g_parm, p);
1425 else
Frank Schaefer52faaf72014-03-24 16:33:16 -03001426 v4l2_video_std_frame_period(v4l2->norm,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001427 &p->parm.capture.timeperframe);
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001428
1429 return rc;
1430}
1431
1432static int vidioc_s_parm(struct file *file, void *priv,
1433 struct v4l2_streamparm *p)
1434{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001435 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001436
Hans Verkuil86ff7f12012-09-07 06:16:03 -03001437 p->parm.capture.readbuffers = EM28XX_MIN_BUF;
Frank Schaefer95d26082014-03-24 16:33:09 -03001438 return v4l2_device_call_until_err(&dev->v4l2->v4l2_dev,
1439 0, video, s_parm, p);
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001440}
1441
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001442static const char *iname[] = {
1443 [EM28XX_VMUX_COMPOSITE1] = "Composite1",
1444 [EM28XX_VMUX_COMPOSITE2] = "Composite2",
1445 [EM28XX_VMUX_COMPOSITE3] = "Composite3",
1446 [EM28XX_VMUX_COMPOSITE4] = "Composite4",
1447 [EM28XX_VMUX_SVIDEO] = "S-Video",
1448 [EM28XX_VMUX_TELEVISION] = "Television",
1449 [EM28XX_VMUX_CABLE] = "Cable TV",
1450 [EM28XX_VMUX_DVB] = "DVB",
1451 [EM28XX_VMUX_DEBUG] = "for debug only",
1452};
1453
1454static int vidioc_enum_input(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001455 struct v4l2_input *i)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001456{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001457 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001458 unsigned int n;
1459
1460 n = i->index;
1461 if (n >= MAX_EM28XX_INPUT)
1462 return -EINVAL;
1463 if (0 == INPUT(n)->type)
1464 return -EINVAL;
1465
1466 i->index = n;
1467 i->type = V4L2_INPUT_TYPE_CAMERA;
1468
1469 strcpy(i->name, iname[INPUT(n)->type]);
1470
1471 if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type) ||
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001472 (EM28XX_VMUX_CABLE == INPUT(n)->type))
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001473 i->type = V4L2_INPUT_TYPE_TUNER;
1474
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001475 i->std = dev->v4l2->vdev->tvnorms;
Hans Verkuild8c95c02012-09-07 07:31:54 -03001476 /* webcams do not have the STD API */
1477 if (dev->board.is_webcam)
1478 i->capabilities = 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001479
1480 return 0;
1481}
1482
1483static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1484{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001485 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001486
1487 *i = dev->ctl_input;
1488
1489 return 0;
1490}
1491
1492static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
1493{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001494 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001495
1496 if (i >= MAX_EM28XX_INPUT)
1497 return -EINVAL;
1498 if (0 == INPUT(i)->type)
1499 return -EINVAL;
1500
Ezequiel García96371fc2012-03-23 18:09:34 -03001501 video_mux(dev, i);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001502 return 0;
1503}
1504
1505static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
1506{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001507 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001508
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001509 switch (a->index) {
1510 case EM28XX_AMUX_VIDEO:
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001511 strcpy(a->name, "Television");
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001512 break;
1513 case EM28XX_AMUX_LINE_IN:
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001514 strcpy(a->name, "Line In");
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001515 break;
1516 case EM28XX_AMUX_VIDEO2:
1517 strcpy(a->name, "Television alt");
1518 break;
1519 case EM28XX_AMUX_PHONE:
1520 strcpy(a->name, "Phone");
1521 break;
1522 case EM28XX_AMUX_MIC:
1523 strcpy(a->name, "Mic");
1524 break;
1525 case EM28XX_AMUX_CD:
1526 strcpy(a->name, "CD");
1527 break;
1528 case EM28XX_AMUX_AUX:
1529 strcpy(a->name, "Aux");
1530 break;
1531 case EM28XX_AMUX_PCM_OUT:
1532 strcpy(a->name, "PCM");
1533 break;
1534 default:
1535 return -EINVAL;
1536 }
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001537
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001538 a->index = dev->ctl_ainput;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001539 a->capability = V4L2_AUDCAP_STEREO;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001540
1541 return 0;
1542}
1543
Hans Verkuil0e8025b92012-09-04 11:59:31 -03001544static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001545{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001546 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001547
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03001548 if (a->index >= MAX_EM28XX_INPUT)
1549 return -EINVAL;
1550 if (0 == INPUT(a->index)->type)
1551 return -EINVAL;
1552
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001553 dev->ctl_ainput = INPUT(a->index)->amux;
1554 dev->ctl_aoutput = INPUT(a->index)->aout;
Mauro Carvalho Chehabe879b8e2008-11-20 13:39:39 -03001555
1556 if (!dev->ctl_aoutput)
1557 dev->ctl_aoutput = EM28XX_AOUT_MASTER;
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001558
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001559 return 0;
1560}
1561
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001562static int vidioc_g_tuner(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001563 struct v4l2_tuner *t)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001564{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001565 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001566
1567 if (0 != t->index)
1568 return -EINVAL;
1569
1570 strcpy(t->name, "Tuner");
1571
Frank Schaefer95d26082014-03-24 16:33:09 -03001572 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, g_tuner, t);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001573 return 0;
1574}
1575
1576static int vidioc_s_tuner(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001577 const struct v4l2_tuner *t)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001578{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001579 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001580
1581 if (0 != t->index)
1582 return -EINVAL;
1583
Frank Schaefer95d26082014-03-24 16:33:09 -03001584 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, s_tuner, t);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001585 return 0;
1586}
1587
1588static int vidioc_g_frequency(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001589 struct v4l2_frequency *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001590{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001591 struct em28xx *dev = video_drvdata(file);
Frank Schaefer3854b0d2014-03-24 16:33:22 -03001592 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001593
Hans Verkuil20deebf2012-09-06 10:07:25 -03001594 if (0 != f->tuner)
1595 return -EINVAL;
1596
Frank Schaefer3854b0d2014-03-24 16:33:22 -03001597 f->frequency = v4l2->frequency;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001598 return 0;
1599}
1600
1601static int vidioc_s_frequency(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001602 const struct v4l2_frequency *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001603{
Frank Schaefer95d26082014-03-24 16:33:09 -03001604 struct v4l2_frequency new_freq = *f;
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001605 struct em28xx *dev = video_drvdata(file);
Frank Schaefer95d26082014-03-24 16:33:09 -03001606 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001607
1608 if (0 != f->tuner)
1609 return -EINVAL;
1610
Frank Schaefer95d26082014-03-24 16:33:09 -03001611 v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, s_frequency, f);
1612 v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, g_frequency, &new_freq);
Frank Schaefer3854b0d2014-03-24 16:33:22 -03001613 v4l2->frequency = new_freq.frequency;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001614
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001615 return 0;
1616}
1617
Hans Verkuilcd634f12013-03-27 08:04:23 -03001618#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuil96b03d22013-04-06 06:16:58 -03001619static int vidioc_g_chip_info(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001620 struct v4l2_dbg_chip_info *chip)
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001621{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001622 struct em28xx *dev = video_drvdata(file);
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001623
1624 if (chip->match.addr > 1)
1625 return -EINVAL;
1626 if (chip->match.addr == 1)
1627 strlcpy(chip->name, "ac97", sizeof(chip->name));
1628 else
Frank Schaefer95d26082014-03-24 16:33:09 -03001629 strlcpy(chip->name,
1630 dev->v4l2->v4l2_dev.name, sizeof(chip->name));
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001631 return 0;
1632}
1633
Frank Schaefer35deba32013-02-07 13:39:19 -03001634static int em28xx_reg_len(int reg)
1635{
1636 switch (reg) {
1637 case EM28XX_R40_AC97LSB:
1638 case EM28XX_R30_HSCALELOW:
1639 case EM28XX_R32_VSCALELOW:
1640 return 2;
1641 default:
1642 return 1;
1643 }
1644}
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001645
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001646static int vidioc_g_register(struct file *file, void *priv,
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001647 struct v4l2_dbg_register *reg)
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001648{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001649 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001650 int ret;
1651
Hans Verkuilabca2052013-05-29 06:59:35 -03001652 if (reg->match.addr > 1)
1653 return -EINVAL;
1654 if (reg->match.addr) {
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001655 ret = em28xx_read_ac97(dev, reg->reg);
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001656 if (ret < 0)
1657 return ret;
1658
1659 reg->val = ret;
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001660 reg->size = 1;
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001661 return 0;
1662 }
1663
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001664 /* Match host */
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001665 reg->size = em28xx_reg_len(reg->reg);
1666 if (reg->size == 1) {
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001667 ret = em28xx_read_reg(dev, reg->reg);
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001668
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001669 if (ret < 0)
1670 return ret;
1671
1672 reg->val = ret;
1673 } else {
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001674 __le16 val = 0;
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001675
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001676 ret = dev->em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001677 reg->reg, (char *)&val, 2);
1678 if (ret < 0)
1679 return ret;
1680
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001681 reg->val = le16_to_cpu(val);
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001682 }
1683
1684 return 0;
1685}
1686
1687static int vidioc_s_register(struct file *file, void *priv,
Hans Verkuil977ba3b2013-03-24 08:28:46 -03001688 const struct v4l2_dbg_register *reg)
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001689{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001690 struct em28xx *dev = video_drvdata(file);
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001691 __le16 buf;
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001692
Hans Verkuilabca2052013-05-29 06:59:35 -03001693 if (reg->match.addr > 1)
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001694 return -EINVAL;
Hans Verkuilabca2052013-05-29 06:59:35 -03001695 if (reg->match.addr)
1696 return em28xx_write_ac97(dev, reg->reg, reg->val);
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001697
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001698 /* Match host */
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001699 buf = cpu_to_le16(reg->val);
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001700
Hans Verkuil0499a5a2010-09-26 07:34:45 -03001701 return em28xx_write_regs(dev, reg->reg, (char *)&buf,
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001702 em28xx_reg_len(reg->reg));
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001703}
1704#endif
1705
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001706static int vidioc_querycap(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001707 struct v4l2_capability *cap)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001708{
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001709 struct video_device *vdev = video_devdata(file);
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001710 struct em28xx *dev = video_drvdata(file);
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001711 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001712
1713 strlcpy(cap->driver, "em28xx", sizeof(cap->driver));
1714 strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card));
Thierry MERLEcb977162009-01-20 18:01:33 -03001715 usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001716
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001717 if (vdev->vfl_type == VFL_TYPE_GRABBER)
1718 cap->device_caps = V4L2_CAP_READWRITE |
1719 V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1720 else if (vdev->vfl_type == VFL_TYPE_RADIO)
1721 cap->device_caps = V4L2_CAP_RADIO;
1722 else
Hans Verkuil1d179ee2012-09-07 08:45:10 -03001723 cap->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE;
Devin Heitmueller04146142009-09-11 00:08:44 -03001724
Frank Schaefer920f1e42014-09-13 05:52:21 -03001725 if (dev->int_audio_type != EM28XX_INT_AUDIO_NONE)
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001726 cap->device_caps |= V4L2_CAP_AUDIO;
Mauro Carvalho Chehab6c428b52009-08-04 19:52:37 -03001727
Mauro Carvalho Chehabed086312008-01-24 06:59:20 -03001728 if (dev->tuner_type != TUNER_ABSENT)
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001729 cap->device_caps |= V4L2_CAP_TUNER;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001730
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001731 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS |
1732 V4L2_CAP_READWRITE | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001733 if (v4l2->vbi_dev)
Hans Verkuil1d179ee2012-09-07 08:45:10 -03001734 cap->capabilities |= V4L2_CAP_VBI_CAPTURE;
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001735 if (v4l2->radio_dev)
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001736 cap->capabilities |= V4L2_CAP_RADIO;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001737 return 0;
1738}
1739
Hans Verkuil78b526a2008-05-28 12:16:41 -03001740static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001741 struct v4l2_fmtdesc *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001742{
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001743 if (unlikely(f->index >= ARRAY_SIZE(format)))
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001744 return -EINVAL;
1745
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001746 strlcpy(f->description, format[f->index].name, sizeof(f->description));
1747 f->pixelformat = format[f->index].fourcc;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001748
1749 return 0;
1750}
1751
Mauro Carvalho Chehab1c5c5062011-10-16 13:52:43 -02001752static int vidioc_enum_framesizes(struct file *file, void *priv,
1753 struct v4l2_frmsizeenum *fsize)
1754{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001755 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab1c5c5062011-10-16 13:52:43 -02001756 struct em28xx_fmt *fmt;
1757 unsigned int maxw = norm_maxw(dev);
1758 unsigned int maxh = norm_maxh(dev);
1759
1760 fmt = format_by_fourcc(fsize->pixel_format);
1761 if (!fmt) {
1762 em28xx_videodbg("Fourcc format (%08x) invalid.\n",
1763 fsize->pixel_format);
1764 return -EINVAL;
1765 }
1766
1767 if (dev->board.is_em2800) {
1768 if (fsize->index > 1)
1769 return -EINVAL;
1770 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
1771 fsize->discrete.width = maxw / (1 + fsize->index);
1772 fsize->discrete.height = maxh / (1 + fsize->index);
1773 return 0;
1774 }
1775
1776 if (fsize->index != 0)
1777 return -EINVAL;
1778
1779 /* Report a continuous range */
1780 fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
Frank Schaefer6c3598e2013-02-10 16:05:14 -03001781 scale_to_size(dev, EM28XX_HVSCALE_MAX, EM28XX_HVSCALE_MAX,
1782 &fsize->stepwise.min_width, &fsize->stepwise.min_height);
1783 if (fsize->stepwise.min_width < 48)
1784 fsize->stepwise.min_width = 48;
1785 if (fsize->stepwise.min_height < 38)
1786 fsize->stepwise.min_height = 38;
Mauro Carvalho Chehab1c5c5062011-10-16 13:52:43 -02001787 fsize->stepwise.max_width = maxw;
1788 fsize->stepwise.max_height = maxh;
1789 fsize->stepwise.step_width = 1;
1790 fsize->stepwise.step_height = 1;
1791 return 0;
1792}
1793
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001794/* RAW VBI ioctls */
1795
1796static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
1797 struct v4l2_format *format)
1798{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001799 struct em28xx *dev = video_drvdata(file);
Frank Schaefer753aee72014-03-24 16:33:14 -03001800 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001801
Frank Schaefer753aee72014-03-24 16:33:14 -03001802 format->fmt.vbi.samples_per_line = v4l2->vbi_width;
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001803 format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
1804 format->fmt.vbi.offset = 0;
1805 format->fmt.vbi.flags = 0;
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001806 format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
Frank Schaefer753aee72014-03-24 16:33:14 -03001807 format->fmt.vbi.count[0] = v4l2->vbi_height;
1808 format->fmt.vbi.count[1] = v4l2->vbi_height;
Hans Verkuil2a221d32012-09-07 08:51:32 -03001809 memset(format->fmt.vbi.reserved, 0, sizeof(format->fmt.vbi.reserved));
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001810
1811 /* Varies by video standard (NTSC, PAL, etc.) */
Frank Schaefer52faaf72014-03-24 16:33:16 -03001812 if (v4l2->norm & V4L2_STD_525_60) {
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001813 /* NTSC */
1814 format->fmt.vbi.start[0] = 10;
1815 format->fmt.vbi.start[1] = 273;
Frank Schaefer52faaf72014-03-24 16:33:16 -03001816 } else if (v4l2->norm & V4L2_STD_625_50) {
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001817 /* PAL */
1818 format->fmt.vbi.start[0] = 6;
1819 format->fmt.vbi.start[1] = 318;
1820 }
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001821
1822 return 0;
1823}
1824
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001825/* ----------------------------------------------------------- */
1826/* RADIO ESPECIFIC IOCTLS */
1827/* ----------------------------------------------------------- */
1828
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001829static int radio_g_tuner(struct file *file, void *priv,
1830 struct v4l2_tuner *t)
1831{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001832 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001833
1834 if (unlikely(t->index > 0))
1835 return -EINVAL;
1836
1837 strcpy(t->name, "Radio");
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001838
Frank Schaefer95d26082014-03-24 16:33:09 -03001839 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, g_tuner, t);
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001840
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001841 return 0;
1842}
1843
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001844static int radio_s_tuner(struct file *file, void *priv,
Hans Verkuil2f73c7c2013-03-15 06:10:06 -03001845 const struct v4l2_tuner *t)
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001846{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001847 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001848
1849 if (0 != t->index)
1850 return -EINVAL;
1851
Frank Schaefer95d26082014-03-24 16:33:09 -03001852 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, s_tuner, t);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001853
1854 return 0;
1855}
1856
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001857/*
Frank Schaefer95d26082014-03-24 16:33:09 -03001858 * em28xx_free_v4l2() - Free struct em28xx_v4l2
1859 *
1860 * @ref: struct kref for struct em28xx_v4l2
1861 *
1862 * Called when all users of struct em28xx_v4l2 are gone
1863 */
Mauro Carvalho Chehabf472c0b2014-05-23 14:29:44 -03001864static void em28xx_free_v4l2(struct kref *ref)
Frank Schaefer95d26082014-03-24 16:33:09 -03001865{
1866 struct em28xx_v4l2 *v4l2 = container_of(ref, struct em28xx_v4l2, ref);
1867
Frank Schaeferabc13082014-03-24 16:33:10 -03001868 v4l2->dev->v4l2 = NULL;
Frank Schaefer95d26082014-03-24 16:33:09 -03001869 kfree(v4l2);
1870}
1871
1872/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08001873 * em28xx_v4l2_open()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001874 * inits the device and starts isoc transfer
1875 */
Hans Verkuilbec43662008-12-30 06:58:20 -03001876static int em28xx_v4l2_open(struct file *filp)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001877{
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001878 struct video_device *vdev = video_devdata(filp);
1879 struct em28xx *dev = video_drvdata(filp);
Frank Schaefer95d26082014-03-24 16:33:09 -03001880 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001881 enum v4l2_buf_type fh_type = 0;
Frank Schaefer3c0f90e2014-07-25 14:48:57 -03001882 int ret;
Markus Rechberger9c755412005-11-08 21:37:52 -08001883
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001884 switch (vdev->vfl_type) {
1885 case VFL_TYPE_GRABBER:
1886 fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1887 break;
1888 case VFL_TYPE_VBI:
1889 fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
1890 break;
Frank Schaefer4e170242014-01-12 13:24:18 -03001891 case VFL_TYPE_RADIO:
1892 break;
1893 default:
1894 return -EINVAL;
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001895 }
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03001896
Frank Schaefer8e2c8712014-09-18 17:55:45 -03001897 em28xx_videodbg("open dev=%s type=%s users=%d\n",
1898 video_device_node_name(vdev), v4l2_type_names[fh_type],
1899 v4l2->users);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001900
Hans Verkuil876cb142012-06-23 08:12:47 -03001901 if (mutex_lock_interruptible(&dev->lock))
1902 return -ERESTARTSYS;
Frank Schaefer3c0f90e2014-07-25 14:48:57 -03001903
1904 ret = v4l2_fh_open(filp);
1905 if (ret) {
1906 em28xx_errdev("%s: v4l2_fh_open() returned error %d\n",
1907 __func__, ret);
Hans Verkuil876cb142012-06-23 08:12:47 -03001908 mutex_unlock(&dev->lock);
Frank Schaefer3c0f90e2014-07-25 14:48:57 -03001909 return ret;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001910 }
1911
Frank Schaefer8e2c8712014-09-18 17:55:45 -03001912 if (v4l2->users == 0) {
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001913 em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001914
Frank Schaefer4e170242014-01-12 13:24:18 -03001915 if (vdev->vfl_type != VFL_TYPE_RADIO)
1916 em28xx_resolution_set(dev);
1917
1918 /*
1919 * Needed, since GPIO might have disabled power
1920 * of some i2c devices
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001921 */
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03001922 em28xx_wake_i2c(dev);
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02001923 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001924
1925 if (vdev->vfl_type == VFL_TYPE_RADIO) {
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001926 em28xx_videodbg("video_open: setting radio device\n");
Frank Schaefer95d26082014-03-24 16:33:09 -03001927 v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, s_radio);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001928 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001929
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03001930 kref_get(&dev->ref);
Frank Schaefer95d26082014-03-24 16:33:09 -03001931 kref_get(&v4l2->ref);
Frank Schaefer8e2c8712014-09-18 17:55:45 -03001932 v4l2->users++;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001933
Hans Verkuil876cb142012-06-23 08:12:47 -03001934 mutex_unlock(&dev->lock);
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001935
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001936 return 0;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001937}
1938
1939/*
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001940 * em28xx_v4l2_fini()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001941 * unregisters the v4l2,i2c and usb devices
1942 * called when the device gets disconected or at module unload
1943*/
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001944static int em28xx_v4l2_fini(struct em28xx *dev)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001945{
Frank Schaefer95d26082014-03-24 16:33:09 -03001946 struct em28xx_v4l2 *v4l2 = dev->v4l2;
1947
Mauro Carvalho Chehab822b8de2014-01-06 05:27:47 -03001948 if (dev->is_audio_only) {
1949 /* Shouldn't initialize IR for this interface */
1950 return 0;
1951 }
1952
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001953 if (!dev->has_video) {
1954 /* This device does not support the v4l2 extension */
1955 return 0;
1956 }
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02001957
Frank Schaefer95d26082014-03-24 16:33:09 -03001958 if (v4l2 == NULL)
1959 return 0;
1960
Russell King0418ca62014-12-20 09:45:20 -03001961 em28xx_info("Closing video extension\n");
Mauro Carvalho Chehabaa929ad2014-01-12 19:22:07 -03001962
Mauro Carvalho Chehabebbfbc22014-01-13 02:53:44 -03001963 mutex_lock(&dev->lock);
1964
Frank Schaefer95d26082014-03-24 16:33:09 -03001965 v4l2_device_disconnect(&v4l2->v4l2_dev);
Frank Schaefer5ad10de2014-01-12 13:24:21 -03001966
Frank Schaefer23e86422014-01-12 13:24:20 -03001967 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
1968
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001969 if (v4l2->radio_dev) {
Frank Schaefere8470222014-01-12 13:24:25 -03001970 em28xx_info("V4L2 device %s deregistered\n",
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001971 video_device_node_name(v4l2->radio_dev));
1972 video_unregister_device(v4l2->radio_dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001973 }
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001974 if (v4l2->vbi_dev) {
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001975 em28xx_info("V4L2 device %s deregistered\n",
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001976 video_device_node_name(v4l2->vbi_dev));
1977 video_unregister_device(v4l2->vbi_dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001978 }
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001979 if (v4l2->vdev) {
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001980 em28xx_info("V4L2 device %s deregistered\n",
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001981 video_device_node_name(v4l2->vdev));
1982 video_unregister_device(v4l2->vdev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001983 }
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001984
Frank Schaeferabc13082014-03-24 16:33:10 -03001985 v4l2_ctrl_handler_free(&v4l2->ctrl_handler);
Frank Schaefer95d26082014-03-24 16:33:09 -03001986 v4l2_device_unregister(&v4l2->v4l2_dev);
Frank Schaefer103f18a2014-01-17 14:45:30 -03001987
Frank Schaefer2c52a2f2014-03-24 16:33:11 -03001988 if (v4l2->clk) {
1989 v4l2_clk_unregister_fixed(v4l2->clk);
1990 v4l2->clk = NULL;
Frank Schaefer25dd1652014-01-12 13:24:23 -03001991 }
1992
Frank Schaefer95d26082014-03-24 16:33:09 -03001993 kref_put(&v4l2->ref, em28xx_free_v4l2);
1994
Mauro Carvalho Chehabebbfbc22014-01-13 02:53:44 -03001995 mutex_unlock(&dev->lock);
Frank Schaefer95d26082014-03-24 16:33:09 -03001996
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03001997 kref_put(&dev->ref, em28xx_free_device);
Frank Schaefer5ad10de2014-01-12 13:24:21 -03001998
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001999 return 0;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002000}
2001
Shuah Khana61f6812014-02-21 21:50:17 -03002002static int em28xx_v4l2_suspend(struct em28xx *dev)
2003{
2004 if (dev->is_audio_only)
2005 return 0;
2006
2007 if (!dev->has_video)
2008 return 0;
2009
Russell King32e63f02014-12-20 09:45:51 -03002010 em28xx_info("Suspending video extension\n");
Shuah Khana61f6812014-02-21 21:50:17 -03002011 em28xx_stop_urbs(dev);
2012 return 0;
2013}
2014
2015static int em28xx_v4l2_resume(struct em28xx *dev)
2016{
2017 if (dev->is_audio_only)
2018 return 0;
2019
2020 if (!dev->has_video)
2021 return 0;
2022
Russell King32e63f02014-12-20 09:45:51 -03002023 em28xx_info("Resuming video extension\n");
Shuah Khana61f6812014-02-21 21:50:17 -03002024 /* what do we do here */
2025 return 0;
2026}
2027
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002028/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002029 * em28xx_v4l2_close()
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03002030 * stops streaming and deallocates all resources allocated by the v4l2
2031 * calls and ioctls
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002032 */
Hans Verkuilbec43662008-12-30 06:58:20 -03002033static int em28xx_v4l2_close(struct file *filp)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002034{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03002035 struct em28xx *dev = video_drvdata(filp);
Frank Schaefer95d26082014-03-24 16:33:09 -03002036 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03002037 int errCode;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002038
Frank Schaefer8e2c8712014-09-18 17:55:45 -03002039 em28xx_videodbg("users=%d\n", v4l2->users);
2040
2041 vb2_fop_release(filp);
Ricardo Ribalda98c24dcd2013-11-06 05:39:35 -03002042 mutex_lock(&dev->lock);
Devin Heitmueller8c873d32009-09-03 00:23:27 -03002043
Frank Schaefer8e2c8712014-09-18 17:55:45 -03002044 if (v4l2->users == 1) {
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002045 /* No sense to try to write to the device */
2046 if (dev->disconnected)
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002047 goto exit;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03002048
Mauro Carvalho Chehabeb6c9632008-12-05 10:39:12 -03002049 /* Save some power by putting tuner to sleep */
Frank Schaefer95d26082014-03-24 16:33:09 -03002050 v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_power, 0);
Mauro Carvalho Chehabeb6c9632008-12-05 10:39:12 -03002051
Aidan Thorntond7aa8022008-04-13 14:38:47 -03002052 /* do this before setting alternate! */
Mauro Carvalho Chehab2fe3e2e2008-11-27 09:10:40 -03002053 em28xx_set_mode(dev, EM28XX_SUSPEND);
Aidan Thorntond7aa8022008-04-13 14:38:47 -03002054
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03002055 /* set alternate 0 */
2056 dev->alt = 0;
2057 em28xx_videodbg("setting alternate 0\n");
2058 errCode = usb_set_interface(dev->udev, 0, 0);
2059 if (errCode < 0) {
2060 em28xx_errdev("cannot change alternate number to "
2061 "0 (error=%i)\n", errCode);
2062 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002063 }
Devin Heitmueller28abf0832009-09-01 01:54:54 -03002064
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002065exit:
Frank Schaefer8e2c8712014-09-18 17:55:45 -03002066 v4l2->users--;
Frank Schaefer95d26082014-03-24 16:33:09 -03002067 kref_put(&v4l2->ref, em28xx_free_v4l2);
Hans Verkuil876cb142012-06-23 08:12:47 -03002068 mutex_unlock(&dev->lock);
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002069 kref_put(&dev->ref, em28xx_free_device);
2070
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002071 return 0;
2072}
2073
Hans Verkuilbec43662008-12-30 06:58:20 -03002074static const struct v4l2_file_operations em28xx_v4l_fops = {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002075 .owner = THIS_MODULE,
2076 .open = em28xx_v4l2_open,
2077 .release = em28xx_v4l2_close,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002078 .read = vb2_fop_read,
2079 .poll = vb2_fop_poll,
2080 .mmap = vb2_fop_mmap,
Hans Verkuil0499a5a2010-09-26 07:34:45 -03002081 .unlocked_ioctl = video_ioctl2,
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002082};
2083
Hans Verkuila3998102008-07-21 02:57:38 -03002084static const struct v4l2_ioctl_ops video_ioctl_ops = {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002085 .vidioc_querycap = vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03002086 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
2087 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
2088 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
2089 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Devin Heitmueller28abf0832009-09-01 01:54:54 -03002090 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Hans Verkuil2a221d32012-09-07 08:51:32 -03002091 .vidioc_try_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Frank Schaeferaab34612013-02-07 13:39:16 -03002092 .vidioc_s_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Mauro Carvalho Chehab1c5c5062011-10-16 13:52:43 -02002093 .vidioc_enum_framesizes = vidioc_enum_framesizes,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002094 .vidioc_g_audio = vidioc_g_audio,
2095 .vidioc_s_audio = vidioc_s_audio,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002096
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002097 .vidioc_reqbufs = vb2_ioctl_reqbufs,
2098 .vidioc_create_bufs = vb2_ioctl_create_bufs,
2099 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
2100 .vidioc_querybuf = vb2_ioctl_querybuf,
2101 .vidioc_qbuf = vb2_ioctl_qbuf,
2102 .vidioc_dqbuf = vb2_ioctl_dqbuf,
2103
Devin Heitmueller19bf0032009-09-11 00:40:18 -03002104 .vidioc_g_std = vidioc_g_std,
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03002105 .vidioc_querystd = vidioc_querystd,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002106 .vidioc_s_std = vidioc_s_std,
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03002107 .vidioc_g_parm = vidioc_g_parm,
2108 .vidioc_s_parm = vidioc_s_parm,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002109 .vidioc_enum_input = vidioc_enum_input,
2110 .vidioc_g_input = vidioc_g_input,
2111 .vidioc_s_input = vidioc_s_input,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002112 .vidioc_streamon = vb2_ioctl_streamon,
2113 .vidioc_streamoff = vb2_ioctl_streamoff,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002114 .vidioc_g_tuner = vidioc_g_tuner,
2115 .vidioc_s_tuner = vidioc_s_tuner,
2116 .vidioc_g_frequency = vidioc_g_frequency,
2117 .vidioc_s_frequency = vidioc_s_frequency,
Hans Verkuil50fdf402012-09-07 06:10:12 -03002118 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
2119 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002120#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuil96b03d22013-04-06 06:16:58 -03002121 .vidioc_g_chip_info = vidioc_g_chip_info,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002122 .vidioc_g_register = vidioc_g_register,
2123 .vidioc_s_register = vidioc_s_register,
2124#endif
Hans Verkuila3998102008-07-21 02:57:38 -03002125};
2126
2127static const struct video_device em28xx_video_template = {
Frank Schaefere8470222014-01-12 13:24:25 -03002128 .fops = &em28xx_v4l_fops,
2129 .ioctl_ops = &video_ioctl_ops,
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002130 .release = video_device_release,
Frank Schaefere8470222014-01-12 13:24:25 -03002131 .tvnorms = V4L2_STD_ALL,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002132};
2133
Hans Verkuilbec43662008-12-30 06:58:20 -03002134static const struct v4l2_file_operations radio_fops = {
Hans Verkuila3998102008-07-21 02:57:38 -03002135 .owner = THIS_MODULE,
2136 .open = em28xx_v4l2_open,
2137 .release = em28xx_v4l2_close,
Hans Verkuil8fd0bda2010-12-18 09:59:51 -03002138 .unlocked_ioctl = video_ioctl2,
Hans Verkuila3998102008-07-21 02:57:38 -03002139};
2140
2141static const struct v4l2_ioctl_ops radio_ioctl_ops = {
Hans Verkuila9d79fe2012-09-06 07:31:04 -03002142 .vidioc_querycap = vidioc_querycap,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002143 .vidioc_g_tuner = radio_g_tuner,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002144 .vidioc_s_tuner = radio_s_tuner,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002145 .vidioc_g_frequency = vidioc_g_frequency,
2146 .vidioc_s_frequency = vidioc_s_frequency,
Hans Verkuil50fdf402012-09-07 06:10:12 -03002147 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
2148 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002149#ifdef CONFIG_VIDEO_ADV_DEBUG
Michal Marek430c73f2013-04-16 08:06:30 -03002150 .vidioc_g_chip_info = vidioc_g_chip_info,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002151 .vidioc_g_register = vidioc_g_register,
2152 .vidioc_s_register = vidioc_s_register,
2153#endif
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002154};
2155
Hans Verkuila3998102008-07-21 02:57:38 -03002156static struct video_device em28xx_radio_template = {
Frank Schaefere8470222014-01-12 13:24:25 -03002157 .fops = &radio_fops,
2158 .ioctl_ops = &radio_ioctl_ops,
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002159 .release = video_device_release,
Hans Verkuila3998102008-07-21 02:57:38 -03002160};
2161
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002162/* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */
2163static unsigned short saa711x_addrs[] = {
2164 0x4a >> 1, 0x48 >> 1, /* SAA7111, SAA7111A and SAA7113 */
2165 0x42 >> 1, 0x40 >> 1, /* SAA7114, SAA7115 and SAA7118 */
2166 I2C_CLIENT_END };
2167
2168static unsigned short tvp5150_addrs[] = {
2169 0xb8 >> 1,
2170 0xba >> 1,
2171 I2C_CLIENT_END
2172};
2173
2174static unsigned short msp3400_addrs[] = {
2175 0x80 >> 1,
2176 0x88 >> 1,
2177 I2C_CLIENT_END
2178};
2179
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03002180/******************************** usb interface ******************************/
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002181
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002182static struct video_device
2183*em28xx_vdev_init(struct em28xx *dev,
2184 const struct video_device *template,
2185 const char *type_name)
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002186{
2187 struct video_device *vfd;
2188
2189 vfd = video_device_alloc();
2190 if (NULL == vfd)
2191 return NULL;
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03002192
2193 *vfd = *template;
Frank Schaefer95d26082014-03-24 16:33:09 -03002194 vfd->v4l2_dev = &dev->v4l2->v4l2_dev;
Hans Verkuil0499a5a2010-09-26 07:34:45 -03002195 vfd->lock = &dev->lock;
Hans Verkuild8c95c02012-09-07 07:31:54 -03002196 if (dev->board.is_webcam)
2197 vfd->tvnorms = 0;
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002198
2199 snprintf(vfd->name, sizeof(vfd->name), "%s %s",
2200 dev->name, type_name);
2201
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02002202 video_set_drvdata(vfd, dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002203 return vfd;
2204}
2205
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002206static void em28xx_tuner_setup(struct em28xx *dev, unsigned short tuner_addr)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002207{
Frank Schaefer3854b0d2014-03-24 16:33:22 -03002208 struct em28xx_v4l2 *v4l2 = dev->v4l2;
2209 struct v4l2_device *v4l2_dev = &v4l2->v4l2_dev;
2210 struct tuner_setup tun_setup;
2211 struct v4l2_frequency f;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002212
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002213 memset(&tun_setup, 0, sizeof(tun_setup));
2214
2215 tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
2216 tun_setup.tuner_callback = em28xx_tuner_callback;
2217
2218 if (dev->board.radio.type) {
2219 tun_setup.type = dev->board.radio.type;
2220 tun_setup.addr = dev->board.radio_addr;
2221
Frank Schaefer95d26082014-03-24 16:33:09 -03002222 v4l2_device_call_all(v4l2_dev,
2223 0, tuner, s_type_addr, &tun_setup);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002224 }
2225
2226 if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type)) {
2227 tun_setup.type = dev->tuner_type;
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002228 tun_setup.addr = tuner_addr;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002229
Frank Schaefer95d26082014-03-24 16:33:09 -03002230 v4l2_device_call_all(v4l2_dev,
2231 0, tuner, s_type_addr, &tun_setup);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002232 }
2233
Frank Schaefer6867bd5a2014-03-24 16:33:23 -03002234 if (dev->board.tda9887_conf) {
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002235 struct v4l2_priv_tun_config tda9887_cfg;
2236
2237 tda9887_cfg.tuner = TUNER_TDA9887;
Frank Schaefer6867bd5a2014-03-24 16:33:23 -03002238 tda9887_cfg.priv = &dev->board.tda9887_conf;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002239
Frank Schaefer95d26082014-03-24 16:33:09 -03002240 v4l2_device_call_all(v4l2_dev,
2241 0, tuner, s_config, &tda9887_cfg);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002242 }
2243
2244 if (dev->tuner_type == TUNER_XC2028) {
2245 struct v4l2_priv_tun_config xc2028_cfg;
2246 struct xc2028_ctrl ctl;
2247
2248 memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
2249 memset(&ctl, 0, sizeof(ctl));
2250
2251 em28xx_setup_xc3028(dev, &ctl);
2252
2253 xc2028_cfg.tuner = TUNER_XC2028;
2254 xc2028_cfg.priv = &ctl;
2255
Frank Schaefer95d26082014-03-24 16:33:09 -03002256 v4l2_device_call_all(v4l2_dev, 0, tuner, s_config, &xc2028_cfg);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002257 }
2258
2259 /* configure tuner */
2260 f.tuner = 0;
2261 f.type = V4L2_TUNER_ANALOG_TV;
2262 f.frequency = 9076; /* just a magic number */
Frank Schaefer3854b0d2014-03-24 16:33:22 -03002263 v4l2->frequency = f.frequency;
Frank Schaefer95d26082014-03-24 16:33:09 -03002264 v4l2_device_call_all(v4l2_dev, 0, tuner, s_frequency, &f);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002265}
2266
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002267static int em28xx_v4l2_init(struct em28xx *dev)
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002268{
Hans Verkuil081b9452012-09-07 05:43:59 -03002269 u8 val;
Mauro Carvalho Chehab2e5ef2d2008-12-28 22:26:36 -03002270 int ret;
Sascha Sommer1020d132012-01-08 16:54:28 -03002271 unsigned int maxw;
Frank Schaeferabc13082014-03-24 16:33:10 -03002272 struct v4l2_ctrl_handler *hdl;
Frank Schaefer95d26082014-03-24 16:33:09 -03002273 struct em28xx_v4l2 *v4l2;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002274
Mauro Carvalho Chehab822b8de2014-01-06 05:27:47 -03002275 if (dev->is_audio_only) {
2276 /* Shouldn't initialize IR for this interface */
2277 return 0;
2278 }
2279
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002280 if (!dev->has_video) {
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002281 /* This device does not support the v4l2 extension */
2282 return 0;
2283 }
Mauro Carvalho Chehab2e5ef2d2008-12-28 22:26:36 -03002284
Mauro Carvalho Chehab96346142013-12-26 12:41:03 -03002285 em28xx_info("Registering V4L2 extension\n");
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002286
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002287 mutex_lock(&dev->lock);
2288
Frank Schaefer95d26082014-03-24 16:33:09 -03002289 v4l2 = kzalloc(sizeof(struct em28xx_v4l2), GFP_KERNEL);
2290 if (v4l2 == NULL) {
2291 em28xx_info("em28xx_v4l: memory allocation failed\n");
2292 mutex_unlock(&dev->lock);
2293 return -ENOMEM;
2294 }
2295 kref_init(&v4l2->ref);
Frank Schaeferabc13082014-03-24 16:33:10 -03002296 v4l2->dev = dev;
Frank Schaefer95d26082014-03-24 16:33:09 -03002297 dev->v4l2 = v4l2;
2298
2299 ret = v4l2_device_register(&dev->udev->dev, &v4l2->v4l2_dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002300 if (ret < 0) {
2301 em28xx_errdev("Call to v4l2_device_register() failed!\n");
2302 goto err;
2303 }
2304
Frank Schaeferabc13082014-03-24 16:33:10 -03002305 hdl = &v4l2->ctrl_handler;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002306 v4l2_ctrl_handler_init(hdl, 8);
Frank Schaefer95d26082014-03-24 16:33:09 -03002307 v4l2->v4l2_dev.ctrl_handler = hdl;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002308
Frank Schaefer58159172014-03-24 16:33:18 -03002309 if (dev->board.is_webcam)
Mauro Carvalho Chehab7e6c8c12014-09-03 15:06:13 -03002310 v4l2->progressive = true;
Frank Schaefer58159172014-03-24 16:33:18 -03002311
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002312 /*
2313 * Default format, used for tvp5150 or saa711x output formats
2314 */
Frank Schaefer92972852014-03-24 16:33:15 -03002315 v4l2->vinmode = 0x10;
2316 v4l2->vinctl = EM28XX_VINCTRL_INTERLACED |
2317 EM28XX_VINCTRL_CCIR656_ENABLE;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002318
2319 /* request some modules */
2320
2321 if (dev->board.has_msp34xx)
Frank Schaefer95d26082014-03-24 16:33:09 -03002322 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2323 &dev->i2c_adap[dev->def_i2c_bus],
2324 "msp3400", 0, msp3400_addrs);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002325
2326 if (dev->board.decoder == EM28XX_SAA711X)
Frank Schaefer95d26082014-03-24 16:33:09 -03002327 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2328 &dev->i2c_adap[dev->def_i2c_bus],
2329 "saa7115_auto", 0, saa711x_addrs);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002330
2331 if (dev->board.decoder == EM28XX_TVP5150)
Frank Schaefer95d26082014-03-24 16:33:09 -03002332 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2333 &dev->i2c_adap[dev->def_i2c_bus],
2334 "tvp5150", 0, tvp5150_addrs);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002335
2336 if (dev->board.adecoder == EM28XX_TVAUDIO)
Frank Schaefer95d26082014-03-24 16:33:09 -03002337 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2338 &dev->i2c_adap[dev->def_i2c_bus],
2339 "tvaudio", dev->board.tvaudio_addr, NULL);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002340
2341 /* Initialize tuner and camera */
2342
2343 if (dev->board.tuner_type != TUNER_ABSENT) {
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002344 unsigned short tuner_addr = dev->board.tuner_addr;
Frank Schaefer6867bd5a2014-03-24 16:33:23 -03002345 int has_demod = (dev->board.tda9887_conf & TDA9887_PRESENT);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002346
2347 if (dev->board.radio.type)
Frank Schaefer95d26082014-03-24 16:33:09 -03002348 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002349 &dev->i2c_adap[dev->def_i2c_bus],
2350 "tuner", dev->board.radio_addr,
2351 NULL);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002352
2353 if (has_demod)
Frank Schaefer95d26082014-03-24 16:33:09 -03002354 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002355 &dev->i2c_adap[dev->def_i2c_bus],
2356 "tuner", 0,
2357 v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002358 if (tuner_addr == 0) {
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002359 enum v4l2_i2c_tuner_type type =
2360 has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV;
2361 struct v4l2_subdev *sd;
2362
Frank Schaefer95d26082014-03-24 16:33:09 -03002363 sd = v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002364 &dev->i2c_adap[dev->def_i2c_bus],
2365 "tuner", 0,
2366 v4l2_i2c_tuner_addrs(type));
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002367
2368 if (sd)
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002369 tuner_addr = v4l2_i2c_subdev_addr(sd);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002370 } else {
Frank Schaefer95d26082014-03-24 16:33:09 -03002371 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2372 &dev->i2c_adap[dev->def_i2c_bus],
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002373 "tuner", tuner_addr, NULL);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002374 }
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002375
2376 em28xx_tuner_setup(dev, tuner_addr);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002377 }
2378
Frank Schaeferd86bc652014-01-17 14:45:32 -03002379 if (dev->em28xx_sensor != EM28XX_NOSENSOR)
2380 em28xx_init_camera(dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002381
2382 /* Configure audio */
2383 ret = em28xx_audio_setup(dev);
2384 if (ret < 0) {
2385 em28xx_errdev("%s: Error while setting audio - error [%d]!\n",
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002386 __func__, ret);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002387 goto unregister_dev;
2388 }
2389 if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
2390 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002391 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002392 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002393 V4L2_CID_AUDIO_VOLUME, 0, 0x1f, 1, 0x1f);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002394 } else {
2395 /* install the em28xx notify callback */
2396 v4l2_ctrl_notify(v4l2_ctrl_find(hdl, V4L2_CID_AUDIO_MUTE),
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002397 em28xx_ctrl_notify, dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002398 v4l2_ctrl_notify(v4l2_ctrl_find(hdl, V4L2_CID_AUDIO_VOLUME),
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002399 em28xx_ctrl_notify, dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002400 }
2401
2402 /* wake i2c devices */
2403 em28xx_wake_i2c(dev);
2404
2405 /* init video dma queues */
2406 INIT_LIST_HEAD(&dev->vidq.active);
2407 INIT_LIST_HEAD(&dev->vbiq.active);
2408
2409 if (dev->board.has_msp34xx) {
2410 /* Send a reset to other chips via gpio */
2411 ret = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xf7);
2412 if (ret < 0) {
2413 em28xx_errdev("%s: em28xx_write_reg - msp34xx(1) failed! error [%d]\n",
2414 __func__, ret);
2415 goto unregister_dev;
2416 }
2417 msleep(3);
2418
2419 ret = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xff);
2420 if (ret < 0) {
2421 em28xx_errdev("%s: em28xx_write_reg - msp34xx(2) failed! error [%d]\n",
2422 __func__, ret);
2423 goto unregister_dev;
2424 }
2425 msleep(3);
2426 }
2427
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002428 /* set default norm */
Frank Schaefer52faaf72014-03-24 16:33:16 -03002429 v4l2->norm = V4L2_STD_PAL;
Laurent Pinchart8774bed2014-04-28 16:53:01 -03002430 v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_std, v4l2->norm);
Frank Schaefer58159172014-03-24 16:33:18 -03002431 v4l2->interlaced_fieldmode = EM28XX_INTERLACED_DEFAULT;
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002432
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002433 /* Analog specific initialization */
Frank Schaefer06e20672014-03-24 16:33:17 -03002434 v4l2->format = &format[0];
Sascha Sommer1020d132012-01-08 16:54:28 -03002435
2436 maxw = norm_maxw(dev);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002437 /* MaxPacketSize for em2800 is too small to capture at full resolution
2438 * use half of maxw as the scaler can only scale to 50% */
2439 if (dev->board.is_em2800)
2440 maxw /= 2;
Sascha Sommer1020d132012-01-08 16:54:28 -03002441
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03002442 em28xx_set_video_format(dev, format[0].fourcc,
Sascha Sommer1020d132012-01-08 16:54:28 -03002443 maxw, norm_maxh(dev));
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03002444
Ezequiel García96371fc2012-03-23 18:09:34 -03002445 video_mux(dev, 0);
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002446
2447 /* Audio defaults */
2448 dev->mute = 1;
2449 dev->volume = 0x1f;
2450
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002451/* em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -03002452 val = (u8)em28xx_read_reg(dev, EM28XX_R0F_XCLK);
2453 em28xx_write_reg(dev, EM28XX_R0F_XCLK,
2454 (EM28XX_XCLK_AUDIO_UNMUTE | val));
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002455
2456 em28xx_set_outfmt(dev);
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002457
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002458 /* Add image controls */
2459 /* NOTE: at this point, the subdevices are already registered, so bridge
2460 * controls are only added/enabled when no subdevice provides them */
Frank Schaeferad298052014-03-24 16:33:08 -03002461 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_CONTRAST))
2462 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002463 V4L2_CID_CONTRAST,
2464 0, 0x1f, 1, CONTRAST_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002465 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_BRIGHTNESS))
2466 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002467 V4L2_CID_BRIGHTNESS,
2468 -0x80, 0x7f, 1, BRIGHTNESS_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002469 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_SATURATION))
2470 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002471 V4L2_CID_SATURATION,
2472 0, 0x1f, 1, SATURATION_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002473 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_BLUE_BALANCE))
2474 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002475 V4L2_CID_BLUE_BALANCE,
2476 -0x30, 0x30, 1, BLUE_BALANCE_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002477 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_RED_BALANCE))
2478 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002479 V4L2_CID_RED_BALANCE,
2480 -0x30, 0x30, 1, RED_BALANCE_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002481 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_SHARPNESS))
2482 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002483 V4L2_CID_SHARPNESS,
2484 0, 0x0f, 1, SHARPNESS_DEFAULT);
2485
2486 /* Reset image controls */
2487 em28xx_colorlevels_set_default(dev);
Frank Schaeferad298052014-03-24 16:33:08 -03002488 v4l2_ctrl_handler_setup(hdl);
2489 ret = hdl->error;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002490 if (ret)
2491 goto unregister_dev;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002492
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002493 /* allocate and fill video video_device struct */
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002494 v4l2->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video");
2495 if (!v4l2->vdev) {
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002496 em28xx_errdev("cannot allocate video_device.\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002497 ret = -ENODEV;
2498 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002499 }
Frank Schaefer27a36df2014-03-24 16:33:13 -03002500 mutex_init(&v4l2->vb_queue_lock);
2501 mutex_init(&v4l2->vb_vbi_queue_lock);
2502 v4l2->vdev->queue = &v4l2->vb_vidq;
2503 v4l2->vdev->queue->lock = &v4l2->vb_queue_lock;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002504
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002505 /* disable inapplicable ioctls */
2506 if (dev->board.is_webcam) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002507 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_QUERYSTD);
2508 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_G_STD);
2509 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_STD);
Frank Schaefer3bc85cc2013-02-07 13:39:12 -03002510 } else {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002511 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_PARM);
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002512 }
Frank Schaefer66df67b2013-02-07 13:39:10 -03002513 if (dev->tuner_type == TUNER_ABSENT) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002514 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_G_TUNER);
2515 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_TUNER);
2516 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_G_FREQUENCY);
2517 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_FREQUENCY);
Frank Schaefer66df67b2013-02-07 13:39:10 -03002518 }
Frank Schaefer920f1e42014-09-13 05:52:21 -03002519 if (dev->int_audio_type == EM28XX_INT_AUDIO_NONE) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002520 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_G_AUDIO);
2521 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_AUDIO);
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002522 }
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002523
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002524 /* register v4l2 video video_device */
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002525 ret = video_register_device(v4l2->vdev, VFL_TYPE_GRABBER,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002526 video_nr[dev->devno]);
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002527 if (ret) {
2528 em28xx_errdev("unable to register video device (error=%i).\n",
2529 ret);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002530 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002531 }
2532
2533 /* Allocate and fill vbi video_device struct */
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002534 if (em28xx_vbi_supported(dev) == 1) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002535 v4l2->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template,
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002536 "vbi");
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002537
Frank Schaefer27a36df2014-03-24 16:33:13 -03002538 v4l2->vbi_dev->queue = &v4l2->vb_vbiq;
2539 v4l2->vbi_dev->queue->lock = &v4l2->vb_vbi_queue_lock;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002540
Frank Schaefer66df67b2013-02-07 13:39:10 -03002541 /* disable inapplicable ioctls */
Frank Schaefer3d3a4102014-07-25 15:08:30 -03002542 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_PARM);
Frank Schaefer66df67b2013-02-07 13:39:10 -03002543 if (dev->tuner_type == TUNER_ABSENT) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002544 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_G_TUNER);
2545 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_TUNER);
2546 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_G_FREQUENCY);
2547 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_FREQUENCY);
Frank Schaefer66df67b2013-02-07 13:39:10 -03002548 }
Frank Schaefer920f1e42014-09-13 05:52:21 -03002549 if (dev->int_audio_type == EM28XX_INT_AUDIO_NONE) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002550 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_G_AUDIO);
2551 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_AUDIO);
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002552 }
Frank Schaefer66df67b2013-02-07 13:39:10 -03002553
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002554 /* register v4l2 vbi video_device */
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002555 ret = video_register_device(v4l2->vbi_dev, VFL_TYPE_VBI,
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002556 vbi_nr[dev->devno]);
2557 if (ret < 0) {
2558 em28xx_errdev("unable to register vbi device\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002559 goto unregister_dev;
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002560 }
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002561 }
2562
2563 if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002564 v4l2->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template,
2565 "radio");
2566 if (!v4l2->radio_dev) {
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002567 em28xx_errdev("cannot allocate video_device.\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002568 ret = -ENODEV;
2569 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002570 }
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002571 ret = video_register_device(v4l2->radio_dev, VFL_TYPE_RADIO,
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002572 radio_nr[dev->devno]);
2573 if (ret < 0) {
2574 em28xx_errdev("can't register radio device\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002575 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002576 }
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002577 em28xx_info("Registered radio device as %s\n",
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002578 video_device_node_name(v4l2->radio_dev));
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002579 }
2580
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002581 em28xx_info("V4L2 video device registered as %s\n",
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002582 video_device_node_name(v4l2->vdev));
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002583
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002584 if (v4l2->vbi_dev)
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002585 em28xx_info("V4L2 VBI device registered as %s\n",
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002586 video_device_node_name(v4l2->vbi_dev));
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002587
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002588 /* Save some power by putting tuner to sleep */
Frank Schaefer95d26082014-03-24 16:33:09 -03002589 v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_power, 0);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002590
2591 /* initialize videobuf2 stuff */
2592 em28xx_vb2_setup(dev);
2593
Mauro Carvalho Chehab96346142013-12-26 12:41:03 -03002594 em28xx_info("V4L2 extension successfully initialized\n");
2595
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002596 kref_get(&dev->ref);
2597
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002598 mutex_unlock(&dev->lock);
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002599 return 0;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002600
2601unregister_dev:
Frank Schaeferabc13082014-03-24 16:33:10 -03002602 v4l2_ctrl_handler_free(&v4l2->ctrl_handler);
Frank Schaefer95d26082014-03-24 16:33:09 -03002603 v4l2_device_unregister(&v4l2->v4l2_dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002604err:
Frank Schaefer95d26082014-03-24 16:33:09 -03002605 dev->v4l2 = NULL;
2606 kref_put(&v4l2->ref, em28xx_free_v4l2);
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002607 mutex_unlock(&dev->lock);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002608 return ret;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002609}
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002610
2611static struct em28xx_ops v4l2_ops = {
2612 .id = EM28XX_V4L2,
2613 .name = "Em28xx v4l2 Extension",
2614 .init = em28xx_v4l2_init,
2615 .fini = em28xx_v4l2_fini,
Shuah Khana61f6812014-02-21 21:50:17 -03002616 .suspend = em28xx_v4l2_suspend,
2617 .resume = em28xx_v4l2_resume,
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002618};
2619
2620static int __init em28xx_video_register(void)
2621{
2622 return em28xx_register_extension(&v4l2_ops);
2623}
2624
2625static void __exit em28xx_video_unregister(void)
2626{
2627 em28xx_unregister_extension(&v4l2_ops);
2628}
2629
2630module_init(em28xx_video_register);
2631module_exit(em28xx_video_unregister);