blob: 46c42c6f34f604e13ba59638ce8939a3bfea714e [file] [log] [blame]
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001/*
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03002 em28xx-video.c - driver for Empia EM2800/EM2820/2840 USB
3 video capture devices
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08004
Mauro Carvalho Chehabf7abcd32005-11-08 21:38:25 -08005 Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
6 Markus Rechberger <mrechberger@gmail.com>
Mauro Carvalho Chehab2e7c6dc2006-04-03 07:53:40 -03007 Mauro Carvalho Chehab <mchehab@infradead.org>
Mauro Carvalho Chehabf7abcd32005-11-08 21:38:25 -08008 Sascha Sommer <saschasommer@freenet.de>
Frank Schaefer0fa4a402012-11-08 14:11:45 -03009 Copyright (C) 2012 Frank Schäfer <fschaefer.oss@googlemail.com>
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080010
Mauro Carvalho Chehab439090d2006-01-23 17:10:54 -020011 Some parts based on SN9C10x PC Camera Controllers GPL driver made
12 by Luca Risolia <luca.risolia@studio.unibo.it>
13
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080014 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 */
28
29#include <linux/init.h>
30#include <linux/list.h>
31#include <linux/module.h>
32#include <linux/kernel.h>
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -020033#include <linux/bitmap.h>
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080034#include <linux/usb.h>
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080035#include <linux/i2c.h>
Trent Piepho6d35c8f2007-11-01 01:16:09 -030036#include <linux/mm.h>
Ingo Molnar1e4baed2006-01-15 07:52:23 -020037#include <linux/mutex.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090038#include <linux/slab.h>
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080039
Mauro Carvalho Chehabf7abcd32005-11-08 21:38:25 -080040#include "em28xx.h"
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -030041#include "em28xx-v4l.h"
Mauro Carvalho Chehabc0477ad2006-01-09 15:25:14 -020042#include <media/v4l2-common.h>
Hans Verkuil35ea11f2008-07-20 08:12:02 -030043#include <media/v4l2-ioctl.h>
Hans Verkuil50fdf402012-09-07 06:10:12 -030044#include <media/v4l2-event.h>
Frank Schaefer25dd1652014-01-12 13:24:23 -030045#include <media/v4l2-clk.h>
Hans Verkuil2474ed42006-03-19 12:35:57 -030046#include <media/msp3400.h>
Mauro Carvalho Chehabed086312008-01-24 06:59:20 -030047#include <media/tuner.h>
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080048
Mauro Carvalho Chehabf7abcd32005-11-08 21:38:25 -080049#define DRIVER_AUTHOR "Ludovico Cavedon <cavedon@sssup.it>, " \
50 "Markus Rechberger <mrechberger@gmail.com>, " \
Mauro Carvalho Chehab2e7c6dc2006-04-03 07:53:40 -030051 "Mauro Carvalho Chehab <mchehab@infradead.org>, " \
Mauro Carvalho Chehabf7abcd32005-11-08 21:38:25 -080052 "Sascha Sommer <saschasommer@freenet.de>"
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080053
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -030054static unsigned int isoc_debug;
55module_param(isoc_debug, int, 0644);
56MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");
57
58static unsigned int disable_vbi;
59module_param(disable_vbi, int, 0644);
60MODULE_PARM_DESC(disable_vbi, "disable vbi support");
61
62static int alt;
63module_param(alt, int, 0644);
64MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint");
65
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -080066#define em28xx_videodbg(fmt, arg...) do {\
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -080067 if (video_debug) \
68 printk(KERN_INFO "%s %s :"fmt, \
Harvey Harrisond80e1342008-04-08 23:20:00 -030069 dev->name, __func__ , ##arg); } while (0)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080070
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -030071#define em28xx_isocdbg(fmt, arg...) \
72do {\
73 if (isoc_debug) { \
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -030074 printk(KERN_INFO "%s %s :"fmt, \
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -030075 dev->name, __func__ , ##arg); \
76 } \
77 } while (0)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -030078
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080079MODULE_AUTHOR(DRIVER_AUTHOR);
Mauro Carvalho Chehabd8992b02013-12-27 11:14:59 -030080MODULE_DESCRIPTION(DRIVER_DESC " - v4l2 interface");
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080081MODULE_LICENSE("GPL");
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -030082MODULE_VERSION(EM28XX_VERSION);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080083
Frank Schaefere507e0e2013-03-26 13:38:38 -030084
85#define EM25XX_FRMDATAHDR_BYTE1 0x02
86#define EM25XX_FRMDATAHDR_BYTE2_STILL_IMAGE 0x20
87#define EM25XX_FRMDATAHDR_BYTE2_FRAME_END 0x02
88#define EM25XX_FRMDATAHDR_BYTE2_FRAME_ID 0x01
89#define EM25XX_FRMDATAHDR_BYTE2_MASK (EM25XX_FRMDATAHDR_BYTE2_STILL_IMAGE | \
90 EM25XX_FRMDATAHDR_BYTE2_FRAME_END | \
91 EM25XX_FRMDATAHDR_BYTE2_FRAME_ID)
92
93
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -030094static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
95static unsigned int vbi_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
96static unsigned int radio_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -030097
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -020098module_param_array(video_nr, int, NULL, 0444);
99module_param_array(vbi_nr, int, NULL, 0444);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -0300100module_param_array(radio_nr, int, NULL, 0444);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -0300101MODULE_PARM_DESC(video_nr, "video device numbers");
102MODULE_PARM_DESC(vbi_nr, "vbi device numbers");
103MODULE_PARM_DESC(radio_nr, "radio device numbers");
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800104
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -0300105static unsigned int video_debug;
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -0300106module_param(video_debug, int, 0644);
107MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800108
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -0300109/* supported video standards */
110static struct em28xx_fmt format[] = {
111 {
Mauro Carvalho Chehab58fc1ce2009-07-03 02:54:18 -0300112 .name = "16 bpp YUY2, 4:2:2, packed",
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -0300113 .fourcc = V4L2_PIX_FMT_YUYV,
114 .depth = 16,
Devin Heitmueller3fbf9302008-12-29 23:34:37 -0300115 .reg = EM28XX_OUTFMT_YUV422_Y0UY1V,
Mauro Carvalho Chehab43cb9fe2009-06-30 08:36:17 -0300116 }, {
Mauro Carvalho Chehab58fc1ce2009-07-03 02:54:18 -0300117 .name = "16 bpp RGB 565, LE",
Mauro Carvalho Chehab43cb9fe2009-06-30 08:36:17 -0300118 .fourcc = V4L2_PIX_FMT_RGB565,
119 .depth = 16,
Mauro Carvalho Chehab58fc1ce2009-07-03 02:54:18 -0300120 .reg = EM28XX_OUTFMT_RGB_16_656,
121 }, {
122 .name = "8 bpp Bayer BGBG..GRGR",
123 .fourcc = V4L2_PIX_FMT_SBGGR8,
124 .depth = 8,
125 .reg = EM28XX_OUTFMT_RGB_8_BGBG,
126 }, {
127 .name = "8 bpp Bayer GRGR..BGBG",
128 .fourcc = V4L2_PIX_FMT_SGRBG8,
129 .depth = 8,
130 .reg = EM28XX_OUTFMT_RGB_8_GRGR,
131 }, {
132 .name = "8 bpp Bayer GBGB..RGRG",
133 .fourcc = V4L2_PIX_FMT_SGBRG8,
134 .depth = 8,
135 .reg = EM28XX_OUTFMT_RGB_8_GBGB,
136 }, {
137 .name = "12 bpp YUV411",
138 .fourcc = V4L2_PIX_FMT_YUV411P,
139 .depth = 12,
140 .reg = EM28XX_OUTFMT_YUV411,
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -0300141 },
142};
143
Frank Schaefer25c61e42014-03-22 10:01:03 -0300144/*FIXME: maxw should be dependent of alt mode */
145static inline unsigned int norm_maxw(struct em28xx *dev)
146{
Frank Schaeferd7dc18d2014-03-24 16:33:19 -0300147 struct em28xx_v4l2 *v4l2 = dev->v4l2;
148
Frank Schaefer25c61e42014-03-22 10:01:03 -0300149 if (dev->board.is_webcam)
Frank Schaeferd7dc18d2014-03-24 16:33:19 -0300150 return v4l2->sensor_xres;
Frank Schaefer25c61e42014-03-22 10:01:03 -0300151
152 if (dev->board.max_range_640_480)
153 return 640;
154
155 return 720;
156}
157
158static inline unsigned int norm_maxh(struct em28xx *dev)
159{
Frank Schaefer52faaf72014-03-24 16:33:16 -0300160 struct em28xx_v4l2 *v4l2 = dev->v4l2;
161
Frank Schaefer25c61e42014-03-22 10:01:03 -0300162 if (dev->board.is_webcam)
Frank Schaeferd7dc18d2014-03-24 16:33:19 -0300163 return v4l2->sensor_yres;
Frank Schaefer25c61e42014-03-22 10:01:03 -0300164
165 if (dev->board.max_range_640_480)
166 return 480;
167
Frank Schaefer52faaf72014-03-24 16:33:16 -0300168 return (v4l2->norm & V4L2_STD_625_50) ? 576 : 480;
Frank Schaefer25c61e42014-03-22 10:01:03 -0300169}
170
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300171static int em28xx_vbi_supported(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300172{
173 /* Modprobe option to manually disable */
174 if (disable_vbi == 1)
175 return 0;
176
177 if (dev->board.is_webcam)
178 return 0;
179
180 /* FIXME: check subdevices for VBI support */
181
182 if (dev->chip_id == CHIP_ID_EM2860 ||
183 dev->chip_id == CHIP_ID_EM2883)
184 return 1;
185
186 /* Version of em28xx that does not support VBI */
187 return 0;
188}
189
190/*
191 * em28xx_wake_i2c()
192 * configure i2c attached devices
193 */
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300194static void em28xx_wake_i2c(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300195{
Frank Schaefer95d26082014-03-24 16:33:09 -0300196 struct v4l2_device *v4l2_dev = &dev->v4l2->v4l2_dev;
197 v4l2_device_call_all(v4l2_dev, 0, core, reset, 0);
198 v4l2_device_call_all(v4l2_dev, 0, video, s_routing,
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300199 INPUT(dev->ctl_input)->vmux, 0, 0);
Frank Schaefer95d26082014-03-24 16:33:09 -0300200 v4l2_device_call_all(v4l2_dev, 0, video, s_stream, 0);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300201}
202
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300203static int em28xx_colorlevels_set_default(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300204{
205 em28xx_write_reg(dev, EM28XX_R20_YGAIN, CONTRAST_DEFAULT);
206 em28xx_write_reg(dev, EM28XX_R21_YOFFSET, BRIGHTNESS_DEFAULT);
207 em28xx_write_reg(dev, EM28XX_R22_UVGAIN, SATURATION_DEFAULT);
208 em28xx_write_reg(dev, EM28XX_R23_UOFFSET, BLUE_BALANCE_DEFAULT);
209 em28xx_write_reg(dev, EM28XX_R24_VOFFSET, RED_BALANCE_DEFAULT);
210 em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, SHARPNESS_DEFAULT);
211
212 em28xx_write_reg(dev, EM28XX_R14_GAMMA, 0x20);
213 em28xx_write_reg(dev, EM28XX_R15_RGAIN, 0x20);
214 em28xx_write_reg(dev, EM28XX_R16_GGAIN, 0x20);
215 em28xx_write_reg(dev, EM28XX_R17_BGAIN, 0x20);
216 em28xx_write_reg(dev, EM28XX_R18_ROFFSET, 0x00);
217 em28xx_write_reg(dev, EM28XX_R19_GOFFSET, 0x00);
218 return em28xx_write_reg(dev, EM28XX_R1A_BOFFSET, 0x00);
219}
220
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300221static int em28xx_set_outfmt(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300222{
223 int ret;
224 u8 fmt, vinctrl;
Frank Schaefer753aee72014-03-24 16:33:14 -0300225 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300226
Frank Schaefer06e20672014-03-24 16:33:17 -0300227 fmt = v4l2->format->reg;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300228 if (!dev->is_em25xx)
229 fmt |= 0x20;
230 /*
231 * NOTE: it's not clear if this is really needed !
232 * The datasheets say bit 5 is a reserved bit and devices seem to work
233 * fine without it. But the Windows driver sets it for em2710/50+em28xx
234 * devices and we've always been setting it, too.
235 *
236 * em2765 (em25xx, em276x/7x/8x) devices do NOT work with this bit set,
237 * it's likely used for an additional (compressed ?) format there.
238 */
239 ret = em28xx_write_reg(dev, EM28XX_R27_OUTFMT, fmt);
240 if (ret < 0)
241 return ret;
242
Frank Schaefer92972852014-03-24 16:33:15 -0300243 ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, v4l2->vinmode);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300244 if (ret < 0)
245 return ret;
246
Frank Schaefer92972852014-03-24 16:33:15 -0300247 vinctrl = v4l2->vinctl;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300248 if (em28xx_vbi_supported(dev) == 1) {
249 vinctrl |= EM28XX_VINCTRL_VBI_RAW;
250 em28xx_write_reg(dev, EM28XX_R34_VBI_START_H, 0x00);
Frank Schaefer753aee72014-03-24 16:33:14 -0300251 em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH, v4l2->vbi_width/4);
252 em28xx_write_reg(dev, EM28XX_R37_VBI_HEIGHT, v4l2->vbi_height);
Frank Schaefer52faaf72014-03-24 16:33:16 -0300253 if (v4l2->norm & V4L2_STD_525_60) {
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300254 /* NTSC */
255 em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x09);
Frank Schaefer52faaf72014-03-24 16:33:16 -0300256 } else if (v4l2->norm & V4L2_STD_625_50) {
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300257 /* PAL */
258 em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x07);
259 }
260 }
261
262 return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctrl);
263}
264
265static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax,
266 u8 ymin, u8 ymax)
267{
268 em28xx_videodbg("em28xx Scale: (%d,%d)-(%d,%d)\n",
269 xmin, ymin, xmax, ymax);
270
271 em28xx_write_regs(dev, EM28XX_R28_XMIN, &xmin, 1);
272 em28xx_write_regs(dev, EM28XX_R29_XMAX, &xmax, 1);
273 em28xx_write_regs(dev, EM28XX_R2A_YMIN, &ymin, 1);
274 return em28xx_write_regs(dev, EM28XX_R2B_YMAX, &ymax, 1);
275}
276
277static void em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
278 u16 width, u16 height)
279{
280 u8 cwidth = width >> 2;
281 u8 cheight = height >> 2;
282 u8 overflow = (height >> 9 & 0x02) | (width >> 10 & 0x01);
283 /* NOTE: size limit: 2047x1023 = 2MPix */
284
285 em28xx_videodbg("capture area set to (%d,%d): %dx%d\n",
286 hstart, vstart,
287 ((overflow & 2) << 9 | cwidth << 2),
288 ((overflow & 1) << 10 | cheight << 2));
289
290 em28xx_write_regs(dev, EM28XX_R1C_HSTART, &hstart, 1);
291 em28xx_write_regs(dev, EM28XX_R1D_VSTART, &vstart, 1);
292 em28xx_write_regs(dev, EM28XX_R1E_CWIDTH, &cwidth, 1);
293 em28xx_write_regs(dev, EM28XX_R1F_CHEIGHT, &cheight, 1);
294 em28xx_write_regs(dev, EM28XX_R1B_OFLOW, &overflow, 1);
295
296 /* FIXME: function/meaning of these registers ? */
297 /* FIXME: align width+height to multiples of 4 ?! */
298 if (dev->is_em25xx) {
299 em28xx_write_reg(dev, 0x34, width >> 4);
300 em28xx_write_reg(dev, 0x35, height >> 4);
301 }
302}
303
304static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v)
305{
Frank Schaefercba8e9b2014-03-24 16:28:36 -0300306 u8 mode = 0x00;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300307 /* the em2800 scaler only supports scaling down to 50% */
308
309 if (dev->board.is_em2800) {
310 mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00);
311 } else {
312 u8 buf[2];
313
314 buf[0] = h;
315 buf[1] = h >> 8;
316 em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2);
317
318 buf[0] = v;
319 buf[1] = v >> 8;
320 em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2);
321 /* it seems that both H and V scalers must be active
322 to work correctly */
323 mode = (h || v) ? 0x30 : 0x00;
324 }
Frank Schaefercba8e9b2014-03-24 16:28:36 -0300325 return em28xx_write_reg(dev, EM28XX_R26_COMPR, mode);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300326}
327
328/* FIXME: this only function read values from dev */
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300329static int em28xx_resolution_set(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300330{
Frank Schaefer753aee72014-03-24 16:33:14 -0300331 struct em28xx_v4l2 *v4l2 = dev->v4l2;
332 int width = norm_maxw(dev);
333 int height = norm_maxh(dev);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300334
335 /* Properly setup VBI */
Frank Schaefer753aee72014-03-24 16:33:14 -0300336 v4l2->vbi_width = 720;
Frank Schaefer52faaf72014-03-24 16:33:16 -0300337 if (v4l2->norm & V4L2_STD_525_60)
Frank Schaefer753aee72014-03-24 16:33:14 -0300338 v4l2->vbi_height = 12;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300339 else
Frank Schaefer753aee72014-03-24 16:33:14 -0300340 v4l2->vbi_height = 18;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300341
342 em28xx_set_outfmt(dev);
343
344 em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2);
345
346 /* If we don't set the start position to 2 in VBI mode, we end up
347 with line 20/21 being YUYV encoded instead of being in 8-bit
348 greyscale. The core of the issue is that line 21 (and line 23 for
349 PAL WSS) are inside of active video region, and as a result they
350 get the pixelformatting associated with that area. So by cropping
351 it out, we end up with the same format as the rest of the VBI
352 region */
353 if (em28xx_vbi_supported(dev) == 1)
354 em28xx_capture_area_set(dev, 0, 2, width, height);
355 else
356 em28xx_capture_area_set(dev, 0, 0, width, height);
357
Frank Schaefer753aee72014-03-24 16:33:14 -0300358 return em28xx_scaler_set(dev, v4l2->hscale, v4l2->vscale);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300359}
360
361/* Set USB alternate setting for analog video */
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300362static int em28xx_set_alternate(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300363{
Frank Schaefer753aee72014-03-24 16:33:14 -0300364 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300365 int errCode;
366 int i;
Frank Schaefer753aee72014-03-24 16:33:14 -0300367 unsigned int min_pkt_size = v4l2->width * 2 + 4;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300368
369 /* NOTE: for isoc transfers, only alt settings > 0 are allowed
370 bulk transfers seem to work only with alt=0 ! */
371 dev->alt = 0;
372 if ((alt > 0) && (alt < dev->num_alt)) {
373 em28xx_videodbg("alternate forced to %d\n", dev->alt);
374 dev->alt = alt;
375 goto set_alt;
376 }
377 if (dev->analog_xfer_bulk)
378 goto set_alt;
379
380 /* When image size is bigger than a certain value,
381 the frame size should be increased, otherwise, only
382 green screen will be received.
383 */
Frank Schaefer753aee72014-03-24 16:33:14 -0300384 if (v4l2->width * 2 * v4l2->height > 720 * 240 * 2)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300385 min_pkt_size *= 2;
386
387 for (i = 0; i < dev->num_alt; i++) {
388 /* stop when the selected alt setting offers enough bandwidth */
389 if (dev->alt_max_pkt_size_isoc[i] >= min_pkt_size) {
390 dev->alt = i;
391 break;
392 /* otherwise make sure that we end up with the maximum bandwidth
393 because the min_pkt_size equation might be wrong...
394 */
395 } else if (dev->alt_max_pkt_size_isoc[i] >
396 dev->alt_max_pkt_size_isoc[dev->alt])
397 dev->alt = i;
398 }
399
400set_alt:
401 /* NOTE: for bulk transfers, we need to call usb_set_interface()
402 * even if the previous settings were the same. Otherwise streaming
403 * fails with all urbs having status = -EOVERFLOW ! */
404 if (dev->analog_xfer_bulk) {
405 dev->max_pkt_size = 512; /* USB 2.0 spec */
406 dev->packet_multiplier = EM28XX_BULK_PACKET_MULTIPLIER;
407 } else { /* isoc */
408 em28xx_videodbg("minimum isoc packet size: %u (alt=%d)\n",
409 min_pkt_size, dev->alt);
410 dev->max_pkt_size =
411 dev->alt_max_pkt_size_isoc[dev->alt];
412 dev->packet_multiplier = EM28XX_NUM_ISOC_PACKETS;
413 }
414 em28xx_videodbg("setting alternate %d with wMaxPacketSize=%u\n",
415 dev->alt, dev->max_pkt_size);
Frank Schaefer961717b2014-01-13 19:02:06 -0300416 errCode = usb_set_interface(dev->udev, dev->ifnum, dev->alt);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300417 if (errCode < 0) {
418 em28xx_errdev("cannot change alternate number to %d (error=%i)\n",
419 dev->alt, errCode);
420 return errCode;
421 }
422 return 0;
423}
424
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300425/* ------------------------------------------------------------------
426 DMA and thread functions
427 ------------------------------------------------------------------*/
428
429/*
Frank Schaefer948a49a2012-12-08 11:31:25 -0300430 * Finish the current buffer
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300431 */
Frank Schaefer948a49a2012-12-08 11:31:25 -0300432static inline void finish_buffer(struct em28xx *dev,
433 struct em28xx_buffer *buf)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300434{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300435 em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->top_field);
436
Frank Schaeferf0e38232014-03-24 16:33:20 -0300437 buf->vb.v4l2_buf.sequence = dev->v4l2->field_count++;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300438 buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
439 v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
440
441 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300442}
443
444/*
Frank Schaefer36016a32012-12-08 11:31:32 -0300445 * Copy picture data from USB buffer to videobuf buffer
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300446 */
447static void em28xx_copy_video(struct em28xx *dev,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300448 struct em28xx_buffer *buf,
Frank Schaefer36016a32012-12-08 11:31:32 -0300449 unsigned char *usb_buf,
Frank Schaefer4078d622012-12-08 11:31:29 -0300450 unsigned long len)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300451{
Frank Schaefer58159172014-03-24 16:33:18 -0300452 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300453 void *fieldstart, *startwrite, *startread;
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300454 int linesdone, currlinedone, offset, lencopy, remain;
Frank Schaefer58159172014-03-24 16:33:18 -0300455 int bytesperline = v4l2->width << 1;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300456
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300457 if (buf->pos + len > buf->length)
458 len = buf->length - buf->pos;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300459
Frank Schaefer36016a32012-12-08 11:31:32 -0300460 startread = usb_buf;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300461 remain = len;
462
Frank Schaefer58159172014-03-24 16:33:18 -0300463 if (v4l2->progressive || buf->top_field)
Frank Schaefer36016a32012-12-08 11:31:32 -0300464 fieldstart = buf->vb_buf;
Frank Schaeferc02ec712012-11-08 14:11:33 -0300465 else /* interlaced mode, even nr. of lines */
Frank Schaefer36016a32012-12-08 11:31:32 -0300466 fieldstart = buf->vb_buf + bytesperline;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300467
Frank Schaefer87325332012-12-08 11:31:27 -0300468 linesdone = buf->pos / bytesperline;
469 currlinedone = buf->pos % bytesperline;
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -0300470
Frank Schaefer58159172014-03-24 16:33:18 -0300471 if (v4l2->progressive)
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -0300472 offset = linesdone * bytesperline + currlinedone;
473 else
474 offset = linesdone * bytesperline * 2 + currlinedone;
475
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300476 startwrite = fieldstart + offset;
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300477 lencopy = bytesperline - currlinedone;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300478 lencopy = lencopy > remain ? remain : lencopy;
479
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300480 if ((char *)startwrite + lencopy > (char *)buf->vb_buf + buf->length) {
Mauro Carvalho Chehabea8df7e2008-04-13 14:39:29 -0300481 em28xx_isocdbg("Overflow of %zi bytes past buffer end (1)\n",
Frank Schaefer36016a32012-12-08 11:31:32 -0300482 ((char *)startwrite + lencopy) -
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300483 ((char *)buf->vb_buf + buf->length));
484 remain = (char *)buf->vb_buf + buf->length -
Frank Schaefer36016a32012-12-08 11:31:32 -0300485 (char *)startwrite;
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -0300486 lencopy = remain;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300487 }
Aidan Thorntone0fadfd342008-04-13 14:56:02 -0300488 if (lencopy <= 0)
489 return;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300490 memcpy(startwrite, startread, lencopy);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300491
492 remain -= lencopy;
493
494 while (remain > 0) {
Frank Schaefer58159172014-03-24 16:33:18 -0300495 if (v4l2->progressive)
Frank Schaeferc02ec712012-11-08 14:11:33 -0300496 startwrite += lencopy;
497 else
498 startwrite += lencopy + bytesperline;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300499 startread += lencopy;
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300500 if (bytesperline > remain)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300501 lencopy = remain;
502 else
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300503 lencopy = bytesperline;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300504
Frank Schaefer36016a32012-12-08 11:31:32 -0300505 if ((char *)startwrite + lencopy > (char *)buf->vb_buf +
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300506 buf->length) {
Devin Heitmuellere3ba4d32009-09-15 00:18:06 -0300507 em28xx_isocdbg("Overflow of %zi bytes past buffer end"
508 "(2)\n",
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300509 ((char *)startwrite + lencopy) -
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300510 ((char *)buf->vb_buf + buf->length));
511 lencopy = remain = (char *)buf->vb_buf + buf->length -
512 (char *)startwrite;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300513 }
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300514 if (lencopy <= 0)
515 break;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300516
517 memcpy(startwrite, startread, lencopy);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300518
519 remain -= lencopy;
520 }
521
Frank Schaefer87325332012-12-08 11:31:27 -0300522 buf->pos += len;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300523}
524
Frank Schaefer36016a32012-12-08 11:31:32 -0300525/*
526 * Copy VBI data from USB buffer to videobuf buffer
527 */
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300528static void em28xx_copy_vbi(struct em28xx *dev,
Frank Schaefer87325332012-12-08 11:31:27 -0300529 struct em28xx_buffer *buf,
Frank Schaefer36016a32012-12-08 11:31:32 -0300530 unsigned char *usb_buf,
Frank Schaefer4078d622012-12-08 11:31:29 -0300531 unsigned long len)
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300532{
Frank Schaefer36016a32012-12-08 11:31:32 -0300533 unsigned int offset;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300534
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300535 if (buf->pos + len > buf->length)
536 len = buf->length - buf->pos;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300537
Frank Schaefer87325332012-12-08 11:31:27 -0300538 offset = buf->pos;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300539 /* Make sure the bottom field populates the second half of the frame */
Frank Schaefer36016a32012-12-08 11:31:32 -0300540 if (buf->top_field == 0)
Frank Schaefer753aee72014-03-24 16:33:14 -0300541 offset += dev->v4l2->vbi_width * dev->v4l2->vbi_height;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300542
Frank Schaefer36016a32012-12-08 11:31:32 -0300543 memcpy(buf->vb_buf + offset, usb_buf, len);
Frank Schaefer87325332012-12-08 11:31:27 -0300544 buf->pos += len;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300545}
546
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300547static inline void print_err_status(struct em28xx *dev,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300548 int packet, int status)
549{
550 char *errmsg = "Unknown";
551
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300552 switch (status) {
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300553 case -ENOENT:
554 errmsg = "unlinked synchronuously";
555 break;
556 case -ECONNRESET:
557 errmsg = "unlinked asynchronuously";
558 break;
559 case -ENOSR:
560 errmsg = "Buffer error (overrun)";
561 break;
562 case -EPIPE:
563 errmsg = "Stalled (device not responding)";
564 break;
565 case -EOVERFLOW:
566 errmsg = "Babble (bad cable?)";
567 break;
568 case -EPROTO:
569 errmsg = "Bit-stuff error (bad cable?)";
570 break;
571 case -EILSEQ:
572 errmsg = "CRC/Timeout (could be anything)";
573 break;
574 case -ETIME:
575 errmsg = "Device does not respond";
576 break;
577 }
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300578 if (packet < 0) {
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300579 em28xx_isocdbg("URB status %d [%s].\n", status, errmsg);
580 } else {
581 em28xx_isocdbg("URB packet %d, status %d [%s].\n",
582 packet, status, errmsg);
583 }
584}
585
586/*
Frank Schaefer24a6d842012-12-08 11:31:24 -0300587 * get the next available buffer from dma queue
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300588 */
Frank Schaefer24a6d842012-12-08 11:31:24 -0300589static inline struct em28xx_buffer *get_next_buf(struct em28xx *dev,
590 struct em28xx_dmaqueue *dma_q)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300591{
Frank Schaefer24a6d842012-12-08 11:31:24 -0300592 struct em28xx_buffer *buf;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300593
Mauro Carvalho Chehabdbecb442008-04-13 15:08:55 -0300594 if (list_empty(&dma_q->active)) {
595 em28xx_isocdbg("No active queue to serve\n");
Frank Schaefer24a6d842012-12-08 11:31:24 -0300596 return NULL;
Mauro Carvalho Chehabdbecb442008-04-13 15:08:55 -0300597 }
598
Mauro Carvalho Chehabdbecb442008-04-13 15:08:55 -0300599 /* Get the next buffer */
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300600 buf = list_entry(dma_q->active.next, struct em28xx_buffer, list);
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300601 /* Cleans up buffer - Useful for testing for frame/URB loss */
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300602 list_del(&buf->list);
Frank Schaefer87325332012-12-08 11:31:27 -0300603 buf->pos = 0;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300604 buf->vb_buf = buf->mem;
Mauro Carvalho Chehabcb784722008-04-13 15:06:52 -0300605
Frank Schaefer24a6d842012-12-08 11:31:24 -0300606 return buf;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300607}
608
Frank Schaefere04c00d2012-12-08 11:31:30 -0300609/*
610 * Finish the current buffer if completed and prepare for the next field
611 */
612static struct em28xx_buffer *
613finish_field_prepare_next(struct em28xx *dev,
614 struct em28xx_buffer *buf,
615 struct em28xx_dmaqueue *dma_q)
616{
Frank Schaefer58159172014-03-24 16:33:18 -0300617 struct em28xx_v4l2 *v4l2 = dev->v4l2;
618
Frank Schaeferf0e38232014-03-24 16:33:20 -0300619 if (v4l2->progressive || v4l2->top_field) { /* Brand new frame */
Frank Schaefere04c00d2012-12-08 11:31:30 -0300620 if (buf != NULL)
621 finish_buffer(dev, buf);
622 buf = get_next_buf(dev, dma_q);
623 }
624 if (buf != NULL) {
Frank Schaeferf0e38232014-03-24 16:33:20 -0300625 buf->top_field = v4l2->top_field;
Frank Schaefere04c00d2012-12-08 11:31:30 -0300626 buf->pos = 0;
627 }
628
629 return buf;
630}
631
Frank Schaefer227b7c92012-12-08 11:31:31 -0300632/*
633 * Process data packet according to the em2710/em2750/em28xx frame data format
634 */
635static inline void process_frame_data_em28xx(struct em28xx *dev,
636 unsigned char *data_pkt,
637 unsigned int data_len)
638{
Frank Schaefer753aee72014-03-24 16:33:14 -0300639 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300640 struct em28xx_buffer *buf = dev->usb_ctl.vid_buf;
641 struct em28xx_buffer *vbi_buf = dev->usb_ctl.vbi_buf;
642 struct em28xx_dmaqueue *dma_q = &dev->vidq;
643 struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq;
644
645 /* capture type 0 = vbi start
646 capture type 1 = vbi in progress
647 capture type 2 = video start
648 capture type 3 = video in progress */
649 if (data_len >= 4) {
650 /* NOTE: Headers are always 4 bytes and
651 * never split across packets */
652 if (data_pkt[0] == 0x88 && data_pkt[1] == 0x88 &&
653 data_pkt[2] == 0x88 && data_pkt[3] == 0x88) {
654 /* Continuation */
655 data_pkt += 4;
656 data_len -= 4;
657 } else if (data_pkt[0] == 0x33 && data_pkt[1] == 0x95) {
658 /* Field start (VBI mode) */
Frank Schaeferf0e38232014-03-24 16:33:20 -0300659 v4l2->capture_type = 0;
660 v4l2->vbi_read = 0;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300661 em28xx_isocdbg("VBI START HEADER !!!\n");
Frank Schaeferf0e38232014-03-24 16:33:20 -0300662 v4l2->top_field = !(data_pkt[2] & 1);
Frank Schaefer227b7c92012-12-08 11:31:31 -0300663 data_pkt += 4;
664 data_len -= 4;
665 } else if (data_pkt[0] == 0x22 && data_pkt[1] == 0x5a) {
666 /* Field start (VBI disabled) */
Frank Schaeferf0e38232014-03-24 16:33:20 -0300667 v4l2->capture_type = 2;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300668 em28xx_isocdbg("VIDEO START HEADER !!!\n");
Frank Schaeferf0e38232014-03-24 16:33:20 -0300669 v4l2->top_field = !(data_pkt[2] & 1);
Frank Schaefer227b7c92012-12-08 11:31:31 -0300670 data_pkt += 4;
671 data_len -= 4;
672 }
673 }
674 /* NOTE: With bulk transfers, intermediate data packets
675 * have no continuation header */
676
Frank Schaeferf0e38232014-03-24 16:33:20 -0300677 if (v4l2->capture_type == 0) {
Frank Schaefer227b7c92012-12-08 11:31:31 -0300678 vbi_buf = finish_field_prepare_next(dev, vbi_buf, vbi_dma_q);
679 dev->usb_ctl.vbi_buf = vbi_buf;
Frank Schaeferf0e38232014-03-24 16:33:20 -0300680 v4l2->capture_type = 1;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300681 }
682
Frank Schaeferf0e38232014-03-24 16:33:20 -0300683 if (v4l2->capture_type == 1) {
Frank Schaefer753aee72014-03-24 16:33:14 -0300684 int vbi_size = v4l2->vbi_width * v4l2->vbi_height;
Frank Schaeferf0e38232014-03-24 16:33:20 -0300685 int vbi_data_len = ((v4l2->vbi_read + data_len) > vbi_size) ?
686 (vbi_size - v4l2->vbi_read) : data_len;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300687
688 /* Copy VBI data */
689 if (vbi_buf != NULL)
690 em28xx_copy_vbi(dev, vbi_buf, data_pkt, vbi_data_len);
Frank Schaeferf0e38232014-03-24 16:33:20 -0300691 v4l2->vbi_read += vbi_data_len;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300692
693 if (vbi_data_len < data_len) {
694 /* Continue with copying video data */
Frank Schaeferf0e38232014-03-24 16:33:20 -0300695 v4l2->capture_type = 2;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300696 data_pkt += vbi_data_len;
697 data_len -= vbi_data_len;
698 }
699 }
700
Frank Schaeferf0e38232014-03-24 16:33:20 -0300701 if (v4l2->capture_type == 2) {
Frank Schaefer227b7c92012-12-08 11:31:31 -0300702 buf = finish_field_prepare_next(dev, buf, dma_q);
703 dev->usb_ctl.vid_buf = buf;
Frank Schaeferf0e38232014-03-24 16:33:20 -0300704 v4l2->capture_type = 3;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300705 }
706
Frank Schaeferf0e38232014-03-24 16:33:20 -0300707 if (v4l2->capture_type == 3 && buf != NULL && data_len > 0)
Frank Schaefer227b7c92012-12-08 11:31:31 -0300708 em28xx_copy_video(dev, buf, data_pkt, data_len);
709}
710
Frank Schaefere507e0e2013-03-26 13:38:38 -0300711/*
712 * Process data packet according to the em25xx/em276x/7x/8x frame data format
713 */
714static inline void process_frame_data_em25xx(struct em28xx *dev,
715 unsigned char *data_pkt,
716 unsigned int data_len)
717{
718 struct em28xx_buffer *buf = dev->usb_ctl.vid_buf;
719 struct em28xx_dmaqueue *dmaq = &dev->vidq;
Frank Schaeferf0e38232014-03-24 16:33:20 -0300720 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Frank Schaefere507e0e2013-03-26 13:38:38 -0300721 bool frame_end = 0;
722
723 /* Check for header */
724 /* NOTE: at least with bulk transfers, only the first packet
725 * has a header and has always set the FRAME_END bit */
726 if (data_len >= 2) { /* em25xx header is only 2 bytes long */
727 if ((data_pkt[0] == EM25XX_FRMDATAHDR_BYTE1) &&
728 ((data_pkt[1] & ~EM25XX_FRMDATAHDR_BYTE2_MASK) == 0x00)) {
Frank Schaeferf0e38232014-03-24 16:33:20 -0300729 v4l2->top_field = !(data_pkt[1] &
Frank Schaefere507e0e2013-03-26 13:38:38 -0300730 EM25XX_FRMDATAHDR_BYTE2_FRAME_ID);
731 frame_end = data_pkt[1] &
732 EM25XX_FRMDATAHDR_BYTE2_FRAME_END;
733 data_pkt += 2;
734 data_len -= 2;
735 }
736
737 /* Finish field and prepare next (BULK only) */
738 if (dev->analog_xfer_bulk && frame_end) {
739 buf = finish_field_prepare_next(dev, buf, dmaq);
740 dev->usb_ctl.vid_buf = buf;
741 }
742 /* NOTE: in ISOC mode when a new frame starts and buf==NULL,
743 * we COULD already prepare a buffer here to avoid skipping the
744 * first frame.
745 */
746 }
747
748 /* Copy data */
749 if (buf != NULL && data_len > 0)
750 em28xx_copy_video(dev, buf, data_pkt, data_len);
751
752 /* Finish frame (ISOC only) => avoids lag of 1 frame */
753 if (!dev->analog_xfer_bulk && frame_end) {
754 buf = finish_field_prepare_next(dev, buf, dmaq);
755 dev->usb_ctl.vid_buf = buf;
756 }
757
758 /* NOTE: Tested with USB bulk transfers only !
759 * The wording in the datasheet suggests that isoc might work different.
760 * The current code assumes that with isoc transfers each packet has a
761 * header like with the other em28xx devices.
762 */
763 /* NOTE: Support for interlaced mode is pure theory. It has not been
764 * tested and it is unknown if these devices actually support it. */
765 /* NOTE: No VBI support yet (these chips likely do not support VBI). */
766}
767
Frank Schaefer960da932012-11-25 06:37:37 -0300768/* Processes and copies the URB data content (video and VBI data) */
Frank Schaefer0fa4a402012-11-08 14:11:45 -0300769static inline int em28xx_urb_data_copy(struct em28xx *dev, struct urb *urb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300770{
Frank Schaefer227b7c92012-12-08 11:31:31 -0300771 int xfer_bulk, num_packets, i;
772 unsigned char *usb_data_pkt;
773 unsigned int usb_data_len;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300774
775 if (!dev)
776 return 0;
777
Frank Schaefer2665c292012-12-27 19:02:43 -0300778 if (dev->disconnected)
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300779 return 0;
780
Frank Schaefer1653cb0c2012-11-08 14:11:44 -0300781 if (urb->status < 0)
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300782 print_err_status(dev, -1, urb->status);
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300783
Frank Schaefer4601cc32012-11-08 14:11:46 -0300784 xfer_bulk = usb_pipebulk(urb->pipe);
785
Frank Schaefer4601cc32012-11-08 14:11:46 -0300786 if (xfer_bulk) /* bulk */
787 num_packets = 1;
788 else /* isoc */
789 num_packets = urb->number_of_packets;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300790
Frank Schaefer4601cc32012-11-08 14:11:46 -0300791 for (i = 0; i < num_packets; i++) {
792 if (xfer_bulk) { /* bulk */
Frank Schaefer227b7c92012-12-08 11:31:31 -0300793 usb_data_len = urb->actual_length;
Frank Schaefer4601cc32012-11-08 14:11:46 -0300794
Frank Schaefer227b7c92012-12-08 11:31:31 -0300795 usb_data_pkt = urb->transfer_buffer;
Frank Schaefer4601cc32012-11-08 14:11:46 -0300796 } else { /* isoc */
797 if (urb->iso_frame_desc[i].status < 0) {
798 print_err_status(dev, i,
799 urb->iso_frame_desc[i].status);
800 if (urb->iso_frame_desc[i].status != -EPROTO)
801 continue;
802 }
803
Frank Schaefer227b7c92012-12-08 11:31:31 -0300804 usb_data_len = urb->iso_frame_desc[i].actual_length;
805 if (usb_data_len > dev->max_pkt_size) {
Frank Schaefer4601cc32012-11-08 14:11:46 -0300806 em28xx_isocdbg("packet bigger than packet size");
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300807 continue;
Frank Schaefer4601cc32012-11-08 14:11:46 -0300808 }
809
Frank Schaefer227b7c92012-12-08 11:31:31 -0300810 usb_data_pkt = urb->transfer_buffer +
811 urb->iso_frame_desc[i].offset;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300812 }
813
Frank Schaefer227b7c92012-12-08 11:31:31 -0300814 if (usb_data_len == 0) {
Frank Schaefer4601cc32012-11-08 14:11:46 -0300815 /* NOTE: happens very often with isoc transfers */
816 /* em28xx_usbdbg("packet %d is empty",i); - spammy */
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300817 continue;
818 }
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300819
Frank Schaefere507e0e2013-03-26 13:38:38 -0300820 if (dev->is_em25xx)
821 process_frame_data_em25xx(dev,
822 usb_data_pkt, usb_data_len);
823 else
824 process_frame_data_em28xx(dev,
825 usb_data_pkt, usb_data_len);
826
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300827 }
Frank Schaefer227b7c92012-12-08 11:31:31 -0300828 return 1;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300829}
830
831
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300832static int get_ressource(enum v4l2_buf_type f_type)
833{
834 switch (f_type) {
835 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
836 return EM28XX_RESOURCE_VIDEO;
837 case V4L2_BUF_TYPE_VBI_CAPTURE:
838 return EM28XX_RESOURCE_VBI;
839 default:
840 BUG();
841 return 0;
842 }
843}
844
845/* Usage lock check functions */
846static int res_get(struct em28xx *dev, enum v4l2_buf_type f_type)
847{
848 int res_type = get_ressource(f_type);
849
850 /* is it free? */
851 if (dev->resources & res_type) {
852 /* no, someone else uses it */
853 return -EBUSY;
854 }
855
856 /* it's free, grab it */
857 dev->resources |= res_type;
858 em28xx_videodbg("res: get %d\n", res_type);
859 return 0;
860}
861
862static void res_free(struct em28xx *dev, enum v4l2_buf_type f_type)
863{
864 int res_type = get_ressource(f_type);
865
866 dev->resources &= ~res_type;
867 em28xx_videodbg("res: put %d\n", res_type);
868}
869
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300870/* ------------------------------------------------------------------
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300871 Videobuf2 operations
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300872 ------------------------------------------------------------------*/
873
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300874static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
875 unsigned int *nbuffers, unsigned int *nplanes,
876 unsigned int sizes[], void *alloc_ctxs[])
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300877{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300878 struct em28xx *dev = vb2_get_drv_priv(vq);
Frank Schaefer753aee72014-03-24 16:33:14 -0300879 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300880 unsigned long size;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300881
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300882 if (fmt)
883 size = fmt->fmt.pix.sizeimage;
884 else
Frank Schaefer753aee72014-03-24 16:33:14 -0300885 size =
Frank Schaefer06e20672014-03-24 16:33:17 -0300886 (v4l2->width * v4l2->height * v4l2->format->depth + 7) >> 3;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -0300887
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300888 if (size == 0)
889 return -EINVAL;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300890
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300891 if (0 == *nbuffers)
892 *nbuffers = 32;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300893
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300894 *nplanes = 1;
895 sizes[0] = size;
Mauro Carvalho Chehabd2d9fbf2008-04-17 21:38:53 -0300896
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300897 return 0;
898}
899
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300900static int
901buffer_prepare(struct vb2_buffer *vb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300902{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300903 struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue);
Frank Schaefer753aee72014-03-24 16:33:14 -0300904 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300905 struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
906 unsigned long size;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300907
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300908 em28xx_videodbg("%s, field=%d\n", __func__, vb->v4l2_buf.field);
Aidan Thornton3b5fa922008-04-13 15:09:36 -0300909
Frank Schaefer06e20672014-03-24 16:33:17 -0300910 size = (v4l2->width * v4l2->height * v4l2->format->depth + 7) >> 3;
Aidan Thornton3b5fa922008-04-13 15:09:36 -0300911
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300912 if (vb2_plane_size(vb, 0) < size) {
913 em28xx_videodbg("%s data will not fit into plane (%lu < %lu)\n",
914 __func__, vb2_plane_size(vb, 0), size);
915 return -EINVAL;
916 }
917 vb2_set_plane_payload(&buf->vb, 0, size);
918
919 return 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300920}
921
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300922int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300923{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300924 struct em28xx *dev = vb2_get_drv_priv(vq);
Frank Schaeferf0e38232014-03-24 16:33:20 -0300925 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300926 struct v4l2_frequency f;
927 int rc = 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300928
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300929 em28xx_videodbg("%s\n", __func__);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300930
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300931 /* Make sure streaming is not already in progress for this type
932 of filehandle (e.g. video, vbi) */
933 rc = res_get(dev, vq->type);
934 if (rc)
935 return rc;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300936
Frank Schaefer8139a4d2014-05-11 17:59:04 -0300937 if (v4l2->streaming_users == 0) {
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300938 /* First active streaming user, so allocate all the URBs */
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300939
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300940 /* Allocate the USB bandwidth */
941 em28xx_set_alternate(dev);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300942
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300943 /* Needed, since GPIO might have disabled power of
944 some i2c device
945 */
946 em28xx_wake_i2c(dev);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300947
Frank Schaeferf0e38232014-03-24 16:33:20 -0300948 v4l2->capture_type = -1;
Frank Schaefer960da932012-11-25 06:37:37 -0300949 rc = em28xx_init_usb_xfer(dev, EM28XX_ANALOG_MODE,
950 dev->analog_xfer_bulk,
951 EM28XX_NUM_BUFS,
952 dev->max_pkt_size,
953 dev->packet_multiplier,
954 em28xx_urb_data_copy);
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300955 if (rc < 0)
Frank Schaefer032f1dd2013-10-10 15:31:53 -0300956 return rc;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300957
958 /*
959 * djh: it's not clear whether this code is still needed. I'm
960 * leaving it in here for now entirely out of concern for
961 * backward compatibility (the old code did it)
962 */
963
964 /* Ask tuner to go to analog or radio mode */
965 memset(&f, 0, sizeof(f));
Frank Schaefer3854b0d2014-03-24 16:33:22 -0300966 f.frequency = v4l2->frequency;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300967 if (vq->owner && vq->owner->vdev->vfl_type == VFL_TYPE_RADIO)
968 f.type = V4L2_TUNER_RADIO;
969 else
970 f.type = V4L2_TUNER_ANALOG_TV;
Frank Schaeferf0e38232014-03-24 16:33:20 -0300971 v4l2_device_call_all(&v4l2->v4l2_dev,
Frank Schaefer95d26082014-03-24 16:33:09 -0300972 0, tuner, s_frequency, &f);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300973 }
974
Frank Schaefer8139a4d2014-05-11 17:59:04 -0300975 v4l2->streaming_users++;
Frank Schaefer032f1dd2013-10-10 15:31:53 -0300976
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300977 return rc;
978}
979
Hans Verkuile37559b2014-04-17 02:47:21 -0300980static void em28xx_stop_streaming(struct vb2_queue *vq)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300981{
982 struct em28xx *dev = vb2_get_drv_priv(vq);
Frank Schaefer8139a4d2014-05-11 17:59:04 -0300983 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300984 struct em28xx_dmaqueue *vidq = &dev->vidq;
985 unsigned long flags = 0;
986
987 em28xx_videodbg("%s\n", __func__);
988
989 res_free(dev, vq->type);
990
Frank Schaefer8139a4d2014-05-11 17:59:04 -0300991 if (v4l2->streaming_users-- == 1) {
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300992 /* Last active user, so shutdown all the URBS */
993 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
994 }
995
996 spin_lock_irqsave(&dev->slock, flags);
997 while (!list_empty(&vidq->active)) {
998 struct em28xx_buffer *buf;
999 buf = list_entry(vidq->active.next, struct em28xx_buffer, list);
1000 list_del(&buf->list);
1001 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
1002 }
1003 dev->usb_ctl.vid_buf = NULL;
1004 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001005}
1006
Hans Verkuile37559b2014-04-17 02:47:21 -03001007void em28xx_stop_vbi_streaming(struct vb2_queue *vq)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001008{
1009 struct em28xx *dev = vb2_get_drv_priv(vq);
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001010 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001011 struct em28xx_dmaqueue *vbiq = &dev->vbiq;
1012 unsigned long flags = 0;
1013
1014 em28xx_videodbg("%s\n", __func__);
1015
1016 res_free(dev, vq->type);
1017
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001018 if (v4l2->streaming_users-- == 1) {
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001019 /* Last active user, so shutdown all the URBS */
1020 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
1021 }
1022
1023 spin_lock_irqsave(&dev->slock, flags);
1024 while (!list_empty(&vbiq->active)) {
1025 struct em28xx_buffer *buf;
1026 buf = list_entry(vbiq->active.next, struct em28xx_buffer, list);
1027 list_del(&buf->list);
1028 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
1029 }
1030 dev->usb_ctl.vbi_buf = NULL;
1031 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001032}
1033
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001034static void
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001035buffer_queue(struct vb2_buffer *vb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001036{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001037 struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue);
1038 struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
1039 struct em28xx_dmaqueue *vidq = &dev->vidq;
1040 unsigned long flags = 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001041
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001042 em28xx_videodbg("%s\n", __func__);
1043 buf->mem = vb2_plane_vaddr(vb, 0);
1044 buf->length = vb2_plane_size(vb, 0);
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001045
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001046 spin_lock_irqsave(&dev->slock, flags);
1047 list_add_tail(&buf->list, &vidq->active);
1048 spin_unlock_irqrestore(&dev->slock, flags);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001049}
1050
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001051static struct vb2_ops em28xx_video_qops = {
1052 .queue_setup = queue_setup,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001053 .buf_prepare = buffer_prepare,
1054 .buf_queue = buffer_queue,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001055 .start_streaming = em28xx_start_analog_streaming,
1056 .stop_streaming = em28xx_stop_streaming,
1057 .wait_prepare = vb2_ops_wait_prepare,
1058 .wait_finish = vb2_ops_wait_finish,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001059};
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001060
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001061static int em28xx_vb2_setup(struct em28xx *dev)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001062{
1063 int rc;
1064 struct vb2_queue *q;
Frank Schaefer27a36df2014-03-24 16:33:13 -03001065 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001066
1067 /* Setup Videobuf2 for Video capture */
Frank Schaefer27a36df2014-03-24 16:33:13 -03001068 q = &v4l2->vb_vidq;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001069 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Mauro Carvalho Chehabef85cd92013-01-06 00:34:22 -02001070 q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
Sakari Ailusade48682014-02-25 19:12:19 -03001071 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001072 q->drv_priv = dev;
1073 q->buf_struct_size = sizeof(struct em28xx_buffer);
1074 q->ops = &em28xx_video_qops;
1075 q->mem_ops = &vb2_vmalloc_memops;
1076
1077 rc = vb2_queue_init(q);
1078 if (rc < 0)
1079 return rc;
1080
1081 /* Setup Videobuf2 for VBI capture */
Frank Schaefer27a36df2014-03-24 16:33:13 -03001082 q = &v4l2->vb_vbiq;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001083 q->type = V4L2_BUF_TYPE_VBI_CAPTURE;
1084 q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR;
Sakari Ailusade48682014-02-25 19:12:19 -03001085 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001086 q->drv_priv = dev;
1087 q->buf_struct_size = sizeof(struct em28xx_buffer);
1088 q->ops = &em28xx_vbi_qops;
1089 q->mem_ops = &vb2_vmalloc_memops;
1090
1091 rc = vb2_queue_init(q);
1092 if (rc < 0)
1093 return rc;
1094
1095 return 0;
1096}
1097
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001098/********************* v4l2 interface **************************************/
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001099
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001100static void video_mux(struct em28xx *dev, int index)
1101{
Frank Schaefer95d26082014-03-24 16:33:09 -03001102 struct v4l2_device *v4l2_dev = &dev->v4l2->v4l2_dev;
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001103 dev->ctl_input = index;
1104 dev->ctl_ainput = INPUT(index)->amux;
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001105 dev->ctl_aoutput = INPUT(index)->aout;
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001106
Mauro Carvalho Chehabe879b8e2008-11-20 13:39:39 -03001107 if (!dev->ctl_aoutput)
1108 dev->ctl_aoutput = EM28XX_AOUT_MASTER;
1109
Frank Schaefer95d26082014-03-24 16:33:09 -03001110 v4l2_device_call_all(v4l2_dev, 0, video, s_routing,
Hans Verkuil5325b422009-04-02 11:26:22 -03001111 INPUT(index)->vmux, 0, 0);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001112
Mauro Carvalho Chehab505b6d02008-11-25 09:39:50 -03001113 if (dev->board.has_msp34xx) {
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001114 if (dev->i2s_speed) {
Frank Schaefer95d26082014-03-24 16:33:09 -03001115 v4l2_device_call_all(v4l2_dev, 0, audio,
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03001116 s_i2s_clock_freq, dev->i2s_speed);
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001117 }
Hans Verkuil2474ed42006-03-19 12:35:57 -03001118 /* Note: this is msp3400 specific */
Frank Schaefer95d26082014-03-24 16:33:09 -03001119 v4l2_device_call_all(v4l2_dev, 0, audio, s_routing,
Hans Verkuil5325b422009-04-02 11:26:22 -03001120 dev->ctl_ainput, MSP_OUTPUT(MSP_SC_IN_DSP_SCART1), 0);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001121 }
Mauro Carvalho Chehab539c96d2008-01-05 09:53:54 -03001122
Vitaly Wool2bd1d9e2009-03-04 08:27:52 -03001123 if (dev->board.adecoder != EM28XX_NOADECODER) {
Frank Schaefer95d26082014-03-24 16:33:09 -03001124 v4l2_device_call_all(v4l2_dev, 0, audio, s_routing,
Hans Verkuil5325b422009-04-02 11:26:22 -03001125 dev->ctl_ainput, dev->ctl_aoutput, 0);
Vitaly Wool2bd1d9e2009-03-04 08:27:52 -03001126 }
1127
Mauro Carvalho Chehab00b87302008-02-06 18:34:13 -03001128 em28xx_audio_analog_set(dev);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001129}
1130
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001131static void em28xx_ctrl_notify(struct v4l2_ctrl *ctrl, void *priv)
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001132{
Hans Verkuil081b9452012-09-07 05:43:59 -03001133 struct em28xx *dev = priv;
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001134
Hans Verkuil081b9452012-09-07 05:43:59 -03001135 /*
1136 * In the case of non-AC97 volume controls, we still need
1137 * to do some setups at em28xx, in order to mute/unmute
1138 * and to adjust audio volume. However, the value ranges
1139 * should be checked by the corresponding V4L subdriver.
1140 */
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001141 switch (ctrl->id) {
1142 case V4L2_CID_AUDIO_MUTE:
Hans Verkuil081b9452012-09-07 05:43:59 -03001143 dev->mute = ctrl->val;
1144 em28xx_audio_analog_set(dev);
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001145 break;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001146 case V4L2_CID_AUDIO_VOLUME:
Hans Verkuil081b9452012-09-07 05:43:59 -03001147 dev->volume = ctrl->val;
1148 em28xx_audio_analog_set(dev);
1149 break;
1150 }
1151}
1152
1153static int em28xx_s_ctrl(struct v4l2_ctrl *ctrl)
1154{
Frank Schaeferabc13082014-03-24 16:33:10 -03001155 struct em28xx_v4l2 *v4l2 =
1156 container_of(ctrl->handler, struct em28xx_v4l2, ctrl_handler);
1157 struct em28xx *dev = v4l2->dev;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001158 int ret = -EINVAL;
Hans Verkuil081b9452012-09-07 05:43:59 -03001159
1160 switch (ctrl->id) {
1161 case V4L2_CID_AUDIO_MUTE:
1162 dev->mute = ctrl->val;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001163 ret = em28xx_audio_analog_set(dev);
Hans Verkuil081b9452012-09-07 05:43:59 -03001164 break;
1165 case V4L2_CID_AUDIO_VOLUME:
1166 dev->volume = ctrl->val;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001167 ret = em28xx_audio_analog_set(dev);
1168 break;
1169 case V4L2_CID_CONTRAST:
1170 ret = em28xx_write_reg(dev, EM28XX_R20_YGAIN, ctrl->val);
1171 break;
1172 case V4L2_CID_BRIGHTNESS:
1173 ret = em28xx_write_reg(dev, EM28XX_R21_YOFFSET, ctrl->val);
1174 break;
1175 case V4L2_CID_SATURATION:
1176 ret = em28xx_write_reg(dev, EM28XX_R22_UVGAIN, ctrl->val);
1177 break;
1178 case V4L2_CID_BLUE_BALANCE:
1179 ret = em28xx_write_reg(dev, EM28XX_R23_UOFFSET, ctrl->val);
1180 break;
1181 case V4L2_CID_RED_BALANCE:
1182 ret = em28xx_write_reg(dev, EM28XX_R24_VOFFSET, ctrl->val);
1183 break;
1184 case V4L2_CID_SHARPNESS:
1185 ret = em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, ctrl->val);
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001186 break;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001187 }
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001188
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001189 return (ret < 0) ? ret : 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001190}
1191
Fengguang Wu8068eb82014-01-07 12:50:47 -03001192static const struct v4l2_ctrl_ops em28xx_ctrl_ops = {
Hans Verkuil081b9452012-09-07 05:43:59 -03001193 .s_ctrl = em28xx_s_ctrl,
1194};
1195
Frank Schaefer6b09a212013-02-10 16:05:12 -03001196static void size_to_scale(struct em28xx *dev,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001197 unsigned int width, unsigned int height,
1198 unsigned int *hscale, unsigned int *vscale)
1199{
Mauro Carvalho Chehab55699962009-07-13 20:15:02 -03001200 unsigned int maxw = norm_maxw(dev);
1201 unsigned int maxh = norm_maxh(dev);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001202
1203 *hscale = (((unsigned long)maxw) << 12) / width - 4096L;
Frank Schaefer81685322013-02-10 16:05:11 -03001204 if (*hscale > EM28XX_HVSCALE_MAX)
1205 *hscale = EM28XX_HVSCALE_MAX;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001206
1207 *vscale = (((unsigned long)maxh) << 12) / height - 4096L;
Frank Schaefer81685322013-02-10 16:05:11 -03001208 if (*vscale > EM28XX_HVSCALE_MAX)
1209 *vscale = EM28XX_HVSCALE_MAX;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001210}
1211
Frank Schaeferb8374132013-02-10 16:05:13 -03001212static void scale_to_size(struct em28xx *dev,
1213 unsigned int hscale, unsigned int vscale,
1214 unsigned int *width, unsigned int *height)
1215{
1216 unsigned int maxw = norm_maxw(dev);
1217 unsigned int maxh = norm_maxh(dev);
1218
1219 *width = (((unsigned long)maxw) << 12) / (hscale + 4096L);
1220 *height = (((unsigned long)maxh) << 12) / (vscale + 4096L);
1221}
1222
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001223/* ------------------------------------------------------------------
1224 IOCTL vidioc handling
1225 ------------------------------------------------------------------*/
1226
Hans Verkuil78b526a2008-05-28 12:16:41 -03001227static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001228 struct v4l2_format *f)
1229{
1230 struct em28xx_fh *fh = priv;
1231 struct em28xx *dev = fh->dev;
Frank Schaefer753aee72014-03-24 16:33:14 -03001232 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001233
Frank Schaefer753aee72014-03-24 16:33:14 -03001234 f->fmt.pix.width = v4l2->width;
1235 f->fmt.pix.height = v4l2->height;
Frank Schaefer06e20672014-03-24 16:33:17 -03001236 f->fmt.pix.pixelformat = v4l2->format->fourcc;
1237 f->fmt.pix.bytesperline = (v4l2->width * v4l2->format->depth + 7) >> 3;
Frank Schaefer753aee72014-03-24 16:33:14 -03001238 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * v4l2->height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001239 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
1240
1241 /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */
Frank Schaefer58159172014-03-24 16:33:18 -03001242 if (v4l2->progressive)
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -03001243 f->fmt.pix.field = V4L2_FIELD_NONE;
1244 else
Frank Schaefer58159172014-03-24 16:33:18 -03001245 f->fmt.pix.field = v4l2->interlaced_fieldmode ?
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001246 V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001247 return 0;
1248}
1249
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001250static struct em28xx_fmt *format_by_fourcc(unsigned int fourcc)
1251{
1252 unsigned int i;
1253
1254 for (i = 0; i < ARRAY_SIZE(format); i++)
1255 if (format[i].fourcc == fourcc)
1256 return &format[i];
1257
1258 return NULL;
1259}
1260
Hans Verkuil78b526a2008-05-28 12:16:41 -03001261static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001262 struct v4l2_format *f)
1263{
1264 struct em28xx_fh *fh = priv;
1265 struct em28xx *dev = fh->dev;
Frank Schaefer58159172014-03-24 16:33:18 -03001266 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Trent Piephoccb83402009-05-30 21:45:46 -03001267 unsigned int width = f->fmt.pix.width;
1268 unsigned int height = f->fmt.pix.height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001269 unsigned int maxw = norm_maxw(dev);
1270 unsigned int maxh = norm_maxh(dev);
1271 unsigned int hscale, vscale;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001272 struct em28xx_fmt *fmt;
1273
1274 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
1275 if (!fmt) {
1276 em28xx_videodbg("Fourcc format (%08x) invalid.\n",
1277 f->fmt.pix.pixelformat);
1278 return -EINVAL;
1279 }
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001280
Mauro Carvalho Chehab55699962009-07-13 20:15:02 -03001281 if (dev->board.is_em2800) {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001282 /* the em2800 can only scale down to 50% */
Trent Piephoccb83402009-05-30 21:45:46 -03001283 height = height > (3 * maxh / 4) ? maxh : maxh / 2;
1284 width = width > (3 * maxw / 4) ? maxw : maxw / 2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001285 /*
1286 * MaxPacketSize for em2800 is too small to capture at full
1287 * resolution use half of maxw as the scaler can only scale
1288 * to 50%
1289 */
Sascha Sommer1020d132012-01-08 16:54:28 -03001290 if (width == maxw && height == maxh)
1291 width /= 2;
Trent Piephoccb83402009-05-30 21:45:46 -03001292 } else {
1293 /* width must even because of the YUYV format
1294 height must be even because of interlacing */
Devin Heitmuellere3ba4d32009-09-15 00:18:06 -03001295 v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh,
1296 1, 0);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001297 }
1298
Frank Schaefer6b09a212013-02-10 16:05:12 -03001299 size_to_scale(dev, width, height, &hscale, &vscale);
Hans Verkuil46f85972013-03-30 05:31:42 -03001300 scale_to_size(dev, hscale, vscale, &width, &height);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001301
1302 f->fmt.pix.width = width;
1303 f->fmt.pix.height = height;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001304 f->fmt.pix.pixelformat = fmt->fourcc;
Hans Verkuile6066db2013-02-06 08:14:47 -03001305 f->fmt.pix.bytesperline = (width * fmt->depth + 7) >> 3;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001306 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001307 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
Frank Schaefer58159172014-03-24 16:33:18 -03001308 if (v4l2->progressive)
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -03001309 f->fmt.pix.field = V4L2_FIELD_NONE;
1310 else
Frank Schaefer58159172014-03-24 16:33:18 -03001311 f->fmt.pix.field = v4l2->interlaced_fieldmode ?
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -03001312 V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
Alban Browaeys51dd4d72013-07-16 19:06:46 -03001313 f->fmt.pix.priv = 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001314
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001315 return 0;
1316}
1317
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001318static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc,
1319 unsigned width, unsigned height)
1320{
1321 struct em28xx_fmt *fmt;
Frank Schaefer753aee72014-03-24 16:33:14 -03001322 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001323
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001324 fmt = format_by_fourcc(fourcc);
1325 if (!fmt)
1326 return -EINVAL;
1327
Frank Schaefer06e20672014-03-24 16:33:17 -03001328 v4l2->format = fmt;
Frank Schaefer753aee72014-03-24 16:33:14 -03001329 v4l2->width = width;
1330 v4l2->height = height;
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001331
1332 /* set new image size */
Frank Schaefer753aee72014-03-24 16:33:14 -03001333 size_to_scale(dev, v4l2->width, v4l2->height,
1334 &v4l2->hscale, &v4l2->vscale);
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001335
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001336 em28xx_resolution_set(dev);
1337
1338 return 0;
1339}
1340
Hans Verkuil78b526a2008-05-28 12:16:41 -03001341static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001342 struct v4l2_format *f)
1343{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001344 struct em28xx *dev = video_drvdata(file);
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001345 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001346
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001347 if (v4l2->streaming_users > 0)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001348 return -EBUSY;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001349
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001350 vidioc_try_fmt_vid_cap(file, priv, f);
1351
Hans Verkuil0499a5a2010-09-26 07:34:45 -03001352 return em28xx_set_video_format(dev, f->fmt.pix.pixelformat,
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001353 f->fmt.pix.width, f->fmt.pix.height);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001354}
1355
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001356static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
1357{
1358 struct em28xx_fh *fh = priv;
1359 struct em28xx *dev = fh->dev;
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001360
Frank Schaefer52faaf72014-03-24 16:33:16 -03001361 *norm = dev->v4l2->norm;
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001362
1363 return 0;
1364}
1365
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001366static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm)
1367{
1368 struct em28xx_fh *fh = priv;
1369 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001370
Frank Schaefer95d26082014-03-24 16:33:09 -03001371 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, video, querystd, norm);
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001372
1373 return 0;
1374}
1375
Hans Verkuil314527a2013-03-15 06:10:40 -03001376static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001377{
Frank Schaefer753aee72014-03-24 16:33:14 -03001378 struct em28xx_fh *fh = priv;
1379 struct em28xx *dev = fh->dev;
1380 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001381 struct v4l2_format f;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001382
Frank Schaefer52faaf72014-03-24 16:33:16 -03001383 if (norm == v4l2->norm)
Hans Verkuild8c95c02012-09-07 07:31:54 -03001384 return 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001385
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001386 if (v4l2->streaming_users > 0)
Hans Verkuild8c95c02012-09-07 07:31:54 -03001387 return -EBUSY;
Hans Verkuild8c95c02012-09-07 07:31:54 -03001388
Frank Schaefer52faaf72014-03-24 16:33:16 -03001389 v4l2->norm = norm;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001390
1391 /* Adjusts width/height, if needed */
Hans Verkuild8c95c02012-09-07 07:31:54 -03001392 f.fmt.pix.width = 720;
Hans Verkuil314527a2013-03-15 06:10:40 -03001393 f.fmt.pix.height = (norm & V4L2_STD_525_60) ? 480 : 576;
Hans Verkuil78b526a2008-05-28 12:16:41 -03001394 vidioc_try_fmt_vid_cap(file, priv, &f);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001395
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001396 /* set new image size */
Frank Schaefer753aee72014-03-24 16:33:14 -03001397 v4l2->width = f.fmt.pix.width;
1398 v4l2->height = f.fmt.pix.height;
1399 size_to_scale(dev, v4l2->width, v4l2->height,
1400 &v4l2->hscale, &v4l2->vscale);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001401
1402 em28xx_resolution_set(dev);
Frank Schaefer52faaf72014-03-24 16:33:16 -03001403 v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_std, v4l2->norm);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001404
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001405 return 0;
1406}
1407
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001408static int vidioc_g_parm(struct file *file, void *priv,
1409 struct v4l2_streamparm *p)
1410{
Frank Schaefer52faaf72014-03-24 16:33:16 -03001411 struct em28xx_fh *fh = priv;
1412 struct em28xx *dev = fh->dev;
1413 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001414 int rc = 0;
1415
Hans Verkuil86ff7f12012-09-07 06:16:03 -03001416 p->parm.capture.readbuffers = EM28XX_MIN_BUF;
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001417 if (dev->board.is_webcam)
Frank Schaefer52faaf72014-03-24 16:33:16 -03001418 rc = v4l2_device_call_until_err(&v4l2->v4l2_dev, 0,
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001419 video, g_parm, p);
1420 else
Frank Schaefer52faaf72014-03-24 16:33:16 -03001421 v4l2_video_std_frame_period(v4l2->norm,
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001422 &p->parm.capture.timeperframe);
1423
1424 return rc;
1425}
1426
1427static int vidioc_s_parm(struct file *file, void *priv,
1428 struct v4l2_streamparm *p)
1429{
1430 struct em28xx_fh *fh = priv;
1431 struct em28xx *dev = fh->dev;
1432
Hans Verkuil86ff7f12012-09-07 06:16:03 -03001433 p->parm.capture.readbuffers = EM28XX_MIN_BUF;
Frank Schaefer95d26082014-03-24 16:33:09 -03001434 return v4l2_device_call_until_err(&dev->v4l2->v4l2_dev,
1435 0, video, s_parm, p);
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001436}
1437
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001438static const char *iname[] = {
1439 [EM28XX_VMUX_COMPOSITE1] = "Composite1",
1440 [EM28XX_VMUX_COMPOSITE2] = "Composite2",
1441 [EM28XX_VMUX_COMPOSITE3] = "Composite3",
1442 [EM28XX_VMUX_COMPOSITE4] = "Composite4",
1443 [EM28XX_VMUX_SVIDEO] = "S-Video",
1444 [EM28XX_VMUX_TELEVISION] = "Television",
1445 [EM28XX_VMUX_CABLE] = "Cable TV",
1446 [EM28XX_VMUX_DVB] = "DVB",
1447 [EM28XX_VMUX_DEBUG] = "for debug only",
1448};
1449
1450static int vidioc_enum_input(struct file *file, void *priv,
1451 struct v4l2_input *i)
1452{
1453 struct em28xx_fh *fh = priv;
1454 struct em28xx *dev = fh->dev;
1455 unsigned int n;
1456
1457 n = i->index;
1458 if (n >= MAX_EM28XX_INPUT)
1459 return -EINVAL;
1460 if (0 == INPUT(n)->type)
1461 return -EINVAL;
1462
1463 i->index = n;
1464 i->type = V4L2_INPUT_TYPE_CAMERA;
1465
1466 strcpy(i->name, iname[INPUT(n)->type]);
1467
1468 if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type) ||
1469 (EM28XX_VMUX_CABLE == INPUT(n)->type))
1470 i->type = V4L2_INPUT_TYPE_TUNER;
1471
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001472 i->std = dev->v4l2->vdev->tvnorms;
Hans Verkuild8c95c02012-09-07 07:31:54 -03001473 /* webcams do not have the STD API */
1474 if (dev->board.is_webcam)
1475 i->capabilities = 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001476
1477 return 0;
1478}
1479
1480static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1481{
1482 struct em28xx_fh *fh = priv;
1483 struct em28xx *dev = fh->dev;
1484
1485 *i = dev->ctl_input;
1486
1487 return 0;
1488}
1489
1490static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
1491{
1492 struct em28xx_fh *fh = priv;
1493 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001494
1495 if (i >= MAX_EM28XX_INPUT)
1496 return -EINVAL;
1497 if (0 == INPUT(i)->type)
1498 return -EINVAL;
1499
Ezequiel García96371fc2012-03-23 18:09:34 -03001500 video_mux(dev, i);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001501 return 0;
1502}
1503
1504static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
1505{
1506 struct em28xx_fh *fh = priv;
1507 struct em28xx *dev = fh->dev;
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{
1546 struct em28xx_fh *fh = priv;
1547 struct em28xx *dev = fh->dev;
1548
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03001549 if (a->index >= MAX_EM28XX_INPUT)
1550 return -EINVAL;
1551 if (0 == INPUT(a->index)->type)
1552 return -EINVAL;
1553
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001554 dev->ctl_ainput = INPUT(a->index)->amux;
1555 dev->ctl_aoutput = INPUT(a->index)->aout;
Mauro Carvalho Chehabe879b8e2008-11-20 13:39:39 -03001556
1557 if (!dev->ctl_aoutput)
1558 dev->ctl_aoutput = EM28XX_AOUT_MASTER;
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001559
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001560 return 0;
1561}
1562
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001563static int vidioc_g_tuner(struct file *file, void *priv,
1564 struct v4l2_tuner *t)
1565{
1566 struct em28xx_fh *fh = priv;
1567 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001568
1569 if (0 != t->index)
1570 return -EINVAL;
1571
1572 strcpy(t->name, "Tuner");
1573
Frank Schaefer95d26082014-03-24 16:33:09 -03001574 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, g_tuner, t);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001575 return 0;
1576}
1577
1578static int vidioc_s_tuner(struct file *file, void *priv,
Hans Verkuil2f73c7c2013-03-15 06:10:06 -03001579 const struct v4l2_tuner *t)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001580{
1581 struct em28xx_fh *fh = priv;
1582 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001583
1584 if (0 != t->index)
1585 return -EINVAL;
1586
Frank Schaefer95d26082014-03-24 16:33:09 -03001587 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, s_tuner, t);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001588 return 0;
1589}
1590
1591static int vidioc_g_frequency(struct file *file, void *priv,
1592 struct v4l2_frequency *f)
1593{
1594 struct em28xx_fh *fh = priv;
1595 struct em28xx *dev = fh->dev;
Frank Schaefer3854b0d2014-03-24 16:33:22 -03001596 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001597
Hans Verkuil20deebf2012-09-06 10:07:25 -03001598 if (0 != f->tuner)
1599 return -EINVAL;
1600
Frank Schaefer3854b0d2014-03-24 16:33:22 -03001601 f->frequency = v4l2->frequency;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001602 return 0;
1603}
1604
1605static int vidioc_s_frequency(struct file *file, void *priv,
Hans Verkuilb530a442013-03-19 04:09:26 -03001606 const struct v4l2_frequency *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001607{
Frank Schaefer95d26082014-03-24 16:33:09 -03001608 struct v4l2_frequency new_freq = *f;
1609 struct em28xx_fh *fh = priv;
1610 struct em28xx *dev = fh->dev;
1611 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001612
1613 if (0 != f->tuner)
1614 return -EINVAL;
1615
Frank Schaefer95d26082014-03-24 16:33:09 -03001616 v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, s_frequency, f);
1617 v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, g_frequency, &new_freq);
Frank Schaefer3854b0d2014-03-24 16:33:22 -03001618 v4l2->frequency = new_freq.frequency;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001619
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001620 return 0;
1621}
1622
Hans Verkuilcd634f12013-03-27 08:04:23 -03001623#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuil96b03d22013-04-06 06:16:58 -03001624static int vidioc_g_chip_info(struct file *file, void *priv,
1625 struct v4l2_dbg_chip_info *chip)
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001626{
1627 struct em28xx_fh *fh = priv;
1628 struct em28xx *dev = fh->dev;
1629
1630 if (chip->match.addr > 1)
1631 return -EINVAL;
1632 if (chip->match.addr == 1)
1633 strlcpy(chip->name, "ac97", sizeof(chip->name));
1634 else
Frank Schaefer95d26082014-03-24 16:33:09 -03001635 strlcpy(chip->name,
1636 dev->v4l2->v4l2_dev.name, sizeof(chip->name));
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001637 return 0;
1638}
1639
Frank Schaefer35deba32013-02-07 13:39:19 -03001640static int em28xx_reg_len(int reg)
1641{
1642 switch (reg) {
1643 case EM28XX_R40_AC97LSB:
1644 case EM28XX_R30_HSCALELOW:
1645 case EM28XX_R32_VSCALELOW:
1646 return 2;
1647 default:
1648 return 1;
1649 }
1650}
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001651
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001652static int vidioc_g_register(struct file *file, void *priv,
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001653 struct v4l2_dbg_register *reg)
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001654{
1655 struct em28xx_fh *fh = priv;
1656 struct em28xx *dev = fh->dev;
1657 int ret;
1658
Hans Verkuilabca2052013-05-29 06:59:35 -03001659 if (reg->match.addr > 1)
1660 return -EINVAL;
1661 if (reg->match.addr) {
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001662 ret = em28xx_read_ac97(dev, reg->reg);
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001663 if (ret < 0)
1664 return ret;
1665
1666 reg->val = ret;
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001667 reg->size = 1;
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001668 return 0;
1669 }
1670
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001671 /* Match host */
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001672 reg->size = em28xx_reg_len(reg->reg);
1673 if (reg->size == 1) {
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001674 ret = em28xx_read_reg(dev, reg->reg);
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001675
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001676 if (ret < 0)
1677 return ret;
1678
1679 reg->val = ret;
1680 } else {
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001681 __le16 val = 0;
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001682 ret = dev->em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001683 reg->reg, (char *)&val, 2);
1684 if (ret < 0)
1685 return ret;
1686
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001687 reg->val = le16_to_cpu(val);
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001688 }
1689
1690 return 0;
1691}
1692
1693static int vidioc_s_register(struct file *file, void *priv,
Hans Verkuil977ba3b2013-03-24 08:28:46 -03001694 const struct v4l2_dbg_register *reg)
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001695{
1696 struct em28xx_fh *fh = priv;
1697 struct em28xx *dev = fh->dev;
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001698 __le16 buf;
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001699
Hans Verkuilabca2052013-05-29 06:59:35 -03001700 if (reg->match.addr > 1)
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001701 return -EINVAL;
Hans Verkuilabca2052013-05-29 06:59:35 -03001702 if (reg->match.addr)
1703 return em28xx_write_ac97(dev, reg->reg, reg->val);
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001704
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001705 /* Match host */
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001706 buf = cpu_to_le16(reg->val);
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001707
Hans Verkuil0499a5a2010-09-26 07:34:45 -03001708 return em28xx_write_regs(dev, reg->reg, (char *)&buf,
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001709 em28xx_reg_len(reg->reg));
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001710}
1711#endif
1712
1713
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001714static int vidioc_querycap(struct file *file, void *priv,
1715 struct v4l2_capability *cap)
1716{
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001717 struct video_device *vdev = video_devdata(file);
1718 struct em28xx_fh *fh = priv;
1719 struct em28xx *dev = fh->dev;
1720 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001721
1722 strlcpy(cap->driver, "em28xx", sizeof(cap->driver));
1723 strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card));
Thierry MERLEcb977162009-01-20 18:01:33 -03001724 usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001725
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001726 if (vdev->vfl_type == VFL_TYPE_GRABBER)
1727 cap->device_caps = V4L2_CAP_READWRITE |
1728 V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1729 else if (vdev->vfl_type == VFL_TYPE_RADIO)
1730 cap->device_caps = V4L2_CAP_RADIO;
1731 else
Hans Verkuil1d179ee2012-09-07 08:45:10 -03001732 cap->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE;
Devin Heitmueller04146142009-09-11 00:08:44 -03001733
Mauro Carvalho Chehab6c428b52009-08-04 19:52:37 -03001734 if (dev->audio_mode.has_audio)
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001735 cap->device_caps |= V4L2_CAP_AUDIO;
Mauro Carvalho Chehab6c428b52009-08-04 19:52:37 -03001736
Mauro Carvalho Chehabed086312008-01-24 06:59:20 -03001737 if (dev->tuner_type != TUNER_ABSENT)
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001738 cap->device_caps |= V4L2_CAP_TUNER;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001739
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001740 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS |
1741 V4L2_CAP_READWRITE | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001742 if (v4l2->vbi_dev)
Hans Verkuil1d179ee2012-09-07 08:45:10 -03001743 cap->capabilities |= V4L2_CAP_VBI_CAPTURE;
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001744 if (v4l2->radio_dev)
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001745 cap->capabilities |= V4L2_CAP_RADIO;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001746 return 0;
1747}
1748
Hans Verkuil78b526a2008-05-28 12:16:41 -03001749static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001750 struct v4l2_fmtdesc *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001751{
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001752 if (unlikely(f->index >= ARRAY_SIZE(format)))
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001753 return -EINVAL;
1754
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001755 strlcpy(f->description, format[f->index].name, sizeof(f->description));
1756 f->pixelformat = format[f->index].fourcc;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001757
1758 return 0;
1759}
1760
Mauro Carvalho Chehab1c5c5062011-10-16 13:52:43 -02001761static int vidioc_enum_framesizes(struct file *file, void *priv,
1762 struct v4l2_frmsizeenum *fsize)
1763{
1764 struct em28xx_fh *fh = priv;
1765 struct em28xx *dev = fh->dev;
1766 struct em28xx_fmt *fmt;
1767 unsigned int maxw = norm_maxw(dev);
1768 unsigned int maxh = norm_maxh(dev);
1769
1770 fmt = format_by_fourcc(fsize->pixel_format);
1771 if (!fmt) {
1772 em28xx_videodbg("Fourcc format (%08x) invalid.\n",
1773 fsize->pixel_format);
1774 return -EINVAL;
1775 }
1776
1777 if (dev->board.is_em2800) {
1778 if (fsize->index > 1)
1779 return -EINVAL;
1780 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
1781 fsize->discrete.width = maxw / (1 + fsize->index);
1782 fsize->discrete.height = maxh / (1 + fsize->index);
1783 return 0;
1784 }
1785
1786 if (fsize->index != 0)
1787 return -EINVAL;
1788
1789 /* Report a continuous range */
1790 fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
Frank Schaefer6c3598e2013-02-10 16:05:14 -03001791 scale_to_size(dev, EM28XX_HVSCALE_MAX, EM28XX_HVSCALE_MAX,
1792 &fsize->stepwise.min_width, &fsize->stepwise.min_height);
1793 if (fsize->stepwise.min_width < 48)
1794 fsize->stepwise.min_width = 48;
1795 if (fsize->stepwise.min_height < 38)
1796 fsize->stepwise.min_height = 38;
Mauro Carvalho Chehab1c5c5062011-10-16 13:52:43 -02001797 fsize->stepwise.max_width = maxw;
1798 fsize->stepwise.max_height = maxh;
1799 fsize->stepwise.step_width = 1;
1800 fsize->stepwise.step_height = 1;
1801 return 0;
1802}
1803
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001804/* RAW VBI ioctls */
1805
1806static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
1807 struct v4l2_format *format)
1808{
Frank Schaefer753aee72014-03-24 16:33:14 -03001809 struct em28xx_fh *fh = priv;
1810 struct em28xx *dev = fh->dev;
1811 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001812
Frank Schaefer753aee72014-03-24 16:33:14 -03001813 format->fmt.vbi.samples_per_line = v4l2->vbi_width;
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001814 format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
1815 format->fmt.vbi.offset = 0;
1816 format->fmt.vbi.flags = 0;
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001817 format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
Frank Schaefer753aee72014-03-24 16:33:14 -03001818 format->fmt.vbi.count[0] = v4l2->vbi_height;
1819 format->fmt.vbi.count[1] = v4l2->vbi_height;
Hans Verkuil2a221d32012-09-07 08:51:32 -03001820 memset(format->fmt.vbi.reserved, 0, sizeof(format->fmt.vbi.reserved));
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001821
1822 /* Varies by video standard (NTSC, PAL, etc.) */
Frank Schaefer52faaf72014-03-24 16:33:16 -03001823 if (v4l2->norm & V4L2_STD_525_60) {
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001824 /* NTSC */
1825 format->fmt.vbi.start[0] = 10;
1826 format->fmt.vbi.start[1] = 273;
Frank Schaefer52faaf72014-03-24 16:33:16 -03001827 } else if (v4l2->norm & V4L2_STD_625_50) {
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001828 /* PAL */
1829 format->fmt.vbi.start[0] = 6;
1830 format->fmt.vbi.start[1] = 318;
1831 }
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001832
1833 return 0;
1834}
1835
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001836/* ----------------------------------------------------------- */
1837/* RADIO ESPECIFIC IOCTLS */
1838/* ----------------------------------------------------------- */
1839
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001840static int radio_g_tuner(struct file *file, void *priv,
1841 struct v4l2_tuner *t)
1842{
1843 struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;
1844
1845 if (unlikely(t->index > 0))
1846 return -EINVAL;
1847
1848 strcpy(t->name, "Radio");
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001849
Frank Schaefer95d26082014-03-24 16:33:09 -03001850 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, g_tuner, t);
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001851
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001852 return 0;
1853}
1854
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001855static int radio_s_tuner(struct file *file, void *priv,
Hans Verkuil2f73c7c2013-03-15 06:10:06 -03001856 const struct v4l2_tuner *t)
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001857{
1858 struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;
1859
1860 if (0 != t->index)
1861 return -EINVAL;
1862
Frank Schaefer95d26082014-03-24 16:33:09 -03001863 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, s_tuner, t);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001864
1865 return 0;
1866}
1867
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001868/*
Frank Schaefer95d26082014-03-24 16:33:09 -03001869 * em28xx_free_v4l2() - Free struct em28xx_v4l2
1870 *
1871 * @ref: struct kref for struct em28xx_v4l2
1872 *
1873 * Called when all users of struct em28xx_v4l2 are gone
1874 */
1875void em28xx_free_v4l2(struct kref *ref)
1876{
1877 struct em28xx_v4l2 *v4l2 = container_of(ref, struct em28xx_v4l2, ref);
1878
Frank Schaeferabc13082014-03-24 16:33:10 -03001879 v4l2->dev->v4l2 = NULL;
Frank Schaefer95d26082014-03-24 16:33:09 -03001880 kfree(v4l2);
1881}
1882
1883/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08001884 * em28xx_v4l2_open()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001885 * inits the device and starts isoc transfer
1886 */
Hans Verkuilbec43662008-12-30 06:58:20 -03001887static int em28xx_v4l2_open(struct file *filp)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001888{
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001889 struct video_device *vdev = video_devdata(filp);
1890 struct em28xx *dev = video_drvdata(filp);
Frank Schaefer95d26082014-03-24 16:33:09 -03001891 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001892 enum v4l2_buf_type fh_type = 0;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001893 struct em28xx_fh *fh;
Markus Rechberger9c755412005-11-08 21:37:52 -08001894
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001895 switch (vdev->vfl_type) {
1896 case VFL_TYPE_GRABBER:
1897 fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1898 break;
1899 case VFL_TYPE_VBI:
1900 fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
1901 break;
Frank Schaefer4e170242014-01-12 13:24:18 -03001902 case VFL_TYPE_RADIO:
1903 break;
1904 default:
1905 return -EINVAL;
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001906 }
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03001907
Laurent Pinchart50462eb2009-12-10 11:47:13 -02001908 em28xx_videodbg("open dev=%s type=%s users=%d\n",
1909 video_device_node_name(vdev), v4l2_type_names[fh_type],
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001910 v4l2->users);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001911
Hans Verkuil876cb142012-06-23 08:12:47 -03001912 if (mutex_lock_interruptible(&dev->lock))
1913 return -ERESTARTSYS;
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001914 fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001915 if (!fh) {
1916 em28xx_errdev("em28xx-video.c: Out of memory?!\n");
Hans Verkuil876cb142012-06-23 08:12:47 -03001917 mutex_unlock(&dev->lock);
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001918 return -ENOMEM;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001919 }
Hans Verkuil69a61642012-09-07 05:52:40 -03001920 v4l2_fh_init(&fh->fh, vdev);
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001921 fh->dev = dev;
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001922 fh->type = fh_type;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001923 filp->private_data = fh;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001924
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001925 if (v4l2->users == 0) {
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001926 em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001927
Frank Schaefer4e170242014-01-12 13:24:18 -03001928 if (vdev->vfl_type != VFL_TYPE_RADIO)
1929 em28xx_resolution_set(dev);
1930
1931 /*
1932 * Needed, since GPIO might have disabled power
1933 * of some i2c devices
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001934 */
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03001935 em28xx_wake_i2c(dev);
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02001936 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001937
1938 if (vdev->vfl_type == VFL_TYPE_RADIO) {
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001939 em28xx_videodbg("video_open: setting radio device\n");
Frank Schaefer95d26082014-03-24 16:33:09 -03001940 v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, s_radio);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001941 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001942
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03001943 kref_get(&dev->ref);
Frank Schaefer95d26082014-03-24 16:33:09 -03001944 kref_get(&v4l2->ref);
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001945 v4l2->users++;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001946
Hans Verkuil876cb142012-06-23 08:12:47 -03001947 mutex_unlock(&dev->lock);
Hans Verkuil69a61642012-09-07 05:52:40 -03001948 v4l2_fh_add(&fh->fh);
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001949
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001950 return 0;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001951}
1952
1953/*
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001954 * em28xx_v4l2_fini()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001955 * unregisters the v4l2,i2c and usb devices
1956 * called when the device gets disconected or at module unload
1957*/
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001958static int em28xx_v4l2_fini(struct em28xx *dev)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001959{
Frank Schaefer95d26082014-03-24 16:33:09 -03001960 struct em28xx_v4l2 *v4l2 = dev->v4l2;
1961
Mauro Carvalho Chehab822b8de2014-01-06 05:27:47 -03001962 if (dev->is_audio_only) {
1963 /* Shouldn't initialize IR for this interface */
1964 return 0;
1965 }
1966
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001967 if (!dev->has_video) {
1968 /* This device does not support the v4l2 extension */
1969 return 0;
1970 }
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02001971
Frank Schaefer95d26082014-03-24 16:33:09 -03001972 if (v4l2 == NULL)
1973 return 0;
1974
Mauro Carvalho Chehabaa929ad2014-01-12 19:22:07 -03001975 em28xx_info("Closing video extension");
1976
Mauro Carvalho Chehabebbfbc22014-01-13 02:53:44 -03001977 mutex_lock(&dev->lock);
1978
Frank Schaefer95d26082014-03-24 16:33:09 -03001979 v4l2_device_disconnect(&v4l2->v4l2_dev);
Frank Schaefer5ad10de2014-01-12 13:24:21 -03001980
Frank Schaefer23e86422014-01-12 13:24:20 -03001981 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
1982
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001983 if (v4l2->radio_dev) {
Frank Schaefere8470222014-01-12 13:24:25 -03001984 em28xx_info("V4L2 device %s deregistered\n",
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001985 video_device_node_name(v4l2->radio_dev));
1986 video_unregister_device(v4l2->radio_dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001987 }
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001988 if (v4l2->vbi_dev) {
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001989 em28xx_info("V4L2 device %s deregistered\n",
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001990 video_device_node_name(v4l2->vbi_dev));
1991 video_unregister_device(v4l2->vbi_dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001992 }
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001993 if (v4l2->vdev) {
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001994 em28xx_info("V4L2 device %s deregistered\n",
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001995 video_device_node_name(v4l2->vdev));
1996 video_unregister_device(v4l2->vdev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001997 }
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001998
Frank Schaeferabc13082014-03-24 16:33:10 -03001999 v4l2_ctrl_handler_free(&v4l2->ctrl_handler);
Frank Schaefer95d26082014-03-24 16:33:09 -03002000 v4l2_device_unregister(&v4l2->v4l2_dev);
Frank Schaefer103f18a2014-01-17 14:45:30 -03002001
Frank Schaefer2c52a2f2014-03-24 16:33:11 -03002002 if (v4l2->clk) {
2003 v4l2_clk_unregister_fixed(v4l2->clk);
2004 v4l2->clk = NULL;
Frank Schaefer25dd1652014-01-12 13:24:23 -03002005 }
2006
Frank Schaefer95d26082014-03-24 16:33:09 -03002007 kref_put(&v4l2->ref, em28xx_free_v4l2);
2008
Mauro Carvalho Chehabebbfbc22014-01-13 02:53:44 -03002009 mutex_unlock(&dev->lock);
Frank Schaefer95d26082014-03-24 16:33:09 -03002010
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002011 kref_put(&dev->ref, em28xx_free_device);
Frank Schaefer5ad10de2014-01-12 13:24:21 -03002012
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002013 return 0;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002014}
2015
Shuah Khana61f6812014-02-21 21:50:17 -03002016static int em28xx_v4l2_suspend(struct em28xx *dev)
2017{
2018 if (dev->is_audio_only)
2019 return 0;
2020
2021 if (!dev->has_video)
2022 return 0;
2023
2024 em28xx_info("Suspending video extension");
2025 em28xx_stop_urbs(dev);
2026 return 0;
2027}
2028
2029static int em28xx_v4l2_resume(struct em28xx *dev)
2030{
2031 if (dev->is_audio_only)
2032 return 0;
2033
2034 if (!dev->has_video)
2035 return 0;
2036
2037 em28xx_info("Resuming video extension");
2038 /* what do we do here */
2039 return 0;
2040}
2041
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002042/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002043 * em28xx_v4l2_close()
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03002044 * stops streaming and deallocates all resources allocated by the v4l2
2045 * calls and ioctls
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002046 */
Hans Verkuilbec43662008-12-30 06:58:20 -03002047static int em28xx_v4l2_close(struct file *filp)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002048{
Frank Schaefer95d26082014-03-24 16:33:09 -03002049 struct em28xx_fh *fh = filp->private_data;
2050 struct em28xx *dev = fh->dev;
2051 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03002052 int errCode;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002053
Frank Schaefer8139a4d2014-05-11 17:59:04 -03002054 em28xx_videodbg("users=%d\n", v4l2->users);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002055
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002056 vb2_fop_release(filp);
Ricardo Ribalda98c24dcd2013-11-06 05:39:35 -03002057 mutex_lock(&dev->lock);
Devin Heitmueller8c873d32009-09-03 00:23:27 -03002058
Frank Schaefer8139a4d2014-05-11 17:59:04 -03002059 if (v4l2->users == 1) {
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002060 /* No sense to try to write to the device */
2061 if (dev->disconnected)
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002062 goto exit;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03002063
Mauro Carvalho Chehabeb6c9632008-12-05 10:39:12 -03002064 /* Save some power by putting tuner to sleep */
Frank Schaefer95d26082014-03-24 16:33:09 -03002065 v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_power, 0);
Mauro Carvalho Chehabeb6c9632008-12-05 10:39:12 -03002066
Aidan Thorntond7aa8022008-04-13 14:38:47 -03002067 /* do this before setting alternate! */
Mauro Carvalho Chehab2fe3e2e2008-11-27 09:10:40 -03002068 em28xx_set_mode(dev, EM28XX_SUSPEND);
Aidan Thorntond7aa8022008-04-13 14:38:47 -03002069
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03002070 /* set alternate 0 */
2071 dev->alt = 0;
2072 em28xx_videodbg("setting alternate 0\n");
2073 errCode = usb_set_interface(dev->udev, 0, 0);
2074 if (errCode < 0) {
2075 em28xx_errdev("cannot change alternate number to "
2076 "0 (error=%i)\n", errCode);
2077 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002078 }
Devin Heitmueller28abf0832009-09-01 01:54:54 -03002079
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002080exit:
Frank Schaefer8139a4d2014-05-11 17:59:04 -03002081 v4l2->users--;
Frank Schaefer95d26082014-03-24 16:33:09 -03002082 kref_put(&v4l2->ref, em28xx_free_v4l2);
Hans Verkuil876cb142012-06-23 08:12:47 -03002083 mutex_unlock(&dev->lock);
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002084 kref_put(&dev->ref, em28xx_free_device);
2085
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002086 return 0;
2087}
2088
Hans Verkuilbec43662008-12-30 06:58:20 -03002089static const struct v4l2_file_operations em28xx_v4l_fops = {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002090 .owner = THIS_MODULE,
2091 .open = em28xx_v4l2_open,
2092 .release = em28xx_v4l2_close,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002093 .read = vb2_fop_read,
2094 .poll = vb2_fop_poll,
2095 .mmap = vb2_fop_mmap,
Hans Verkuil0499a5a2010-09-26 07:34:45 -03002096 .unlocked_ioctl = video_ioctl2,
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002097};
2098
Hans Verkuila3998102008-07-21 02:57:38 -03002099static const struct v4l2_ioctl_ops video_ioctl_ops = {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002100 .vidioc_querycap = vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03002101 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
2102 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
2103 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
2104 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Devin Heitmueller28abf0832009-09-01 01:54:54 -03002105 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Hans Verkuil2a221d32012-09-07 08:51:32 -03002106 .vidioc_try_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Frank Schaeferaab34612013-02-07 13:39:16 -03002107 .vidioc_s_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Mauro Carvalho Chehab1c5c5062011-10-16 13:52:43 -02002108 .vidioc_enum_framesizes = vidioc_enum_framesizes,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002109 .vidioc_g_audio = vidioc_g_audio,
2110 .vidioc_s_audio = vidioc_s_audio,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002111
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002112 .vidioc_reqbufs = vb2_ioctl_reqbufs,
2113 .vidioc_create_bufs = vb2_ioctl_create_bufs,
2114 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
2115 .vidioc_querybuf = vb2_ioctl_querybuf,
2116 .vidioc_qbuf = vb2_ioctl_qbuf,
2117 .vidioc_dqbuf = vb2_ioctl_dqbuf,
2118
Devin Heitmueller19bf0032009-09-11 00:40:18 -03002119 .vidioc_g_std = vidioc_g_std,
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03002120 .vidioc_querystd = vidioc_querystd,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002121 .vidioc_s_std = vidioc_s_std,
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03002122 .vidioc_g_parm = vidioc_g_parm,
2123 .vidioc_s_parm = vidioc_s_parm,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002124 .vidioc_enum_input = vidioc_enum_input,
2125 .vidioc_g_input = vidioc_g_input,
2126 .vidioc_s_input = vidioc_s_input,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002127 .vidioc_streamon = vb2_ioctl_streamon,
2128 .vidioc_streamoff = vb2_ioctl_streamoff,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002129 .vidioc_g_tuner = vidioc_g_tuner,
2130 .vidioc_s_tuner = vidioc_s_tuner,
2131 .vidioc_g_frequency = vidioc_g_frequency,
2132 .vidioc_s_frequency = vidioc_s_frequency,
Hans Verkuil50fdf402012-09-07 06:10:12 -03002133 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
2134 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002135#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuil96b03d22013-04-06 06:16:58 -03002136 .vidioc_g_chip_info = vidioc_g_chip_info,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002137 .vidioc_g_register = vidioc_g_register,
2138 .vidioc_s_register = vidioc_s_register,
2139#endif
Hans Verkuila3998102008-07-21 02:57:38 -03002140};
2141
2142static const struct video_device em28xx_video_template = {
Frank Schaefere8470222014-01-12 13:24:25 -03002143 .fops = &em28xx_v4l_fops,
2144 .ioctl_ops = &video_ioctl_ops,
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002145 .release = video_device_release,
Frank Schaefere8470222014-01-12 13:24:25 -03002146 .tvnorms = V4L2_STD_ALL,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002147};
2148
Hans Verkuilbec43662008-12-30 06:58:20 -03002149static const struct v4l2_file_operations radio_fops = {
Hans Verkuila3998102008-07-21 02:57:38 -03002150 .owner = THIS_MODULE,
2151 .open = em28xx_v4l2_open,
2152 .release = em28xx_v4l2_close,
Hans Verkuil8fd0bda2010-12-18 09:59:51 -03002153 .unlocked_ioctl = video_ioctl2,
Hans Verkuila3998102008-07-21 02:57:38 -03002154};
2155
2156static const struct v4l2_ioctl_ops radio_ioctl_ops = {
Hans Verkuila9d79fe2012-09-06 07:31:04 -03002157 .vidioc_querycap = vidioc_querycap,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002158 .vidioc_g_tuner = radio_g_tuner,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002159 .vidioc_s_tuner = radio_s_tuner,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002160 .vidioc_g_frequency = vidioc_g_frequency,
2161 .vidioc_s_frequency = vidioc_s_frequency,
Hans Verkuil50fdf402012-09-07 06:10:12 -03002162 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
2163 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002164#ifdef CONFIG_VIDEO_ADV_DEBUG
Michal Marek430c73f2013-04-16 08:06:30 -03002165 .vidioc_g_chip_info = vidioc_g_chip_info,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002166 .vidioc_g_register = vidioc_g_register,
2167 .vidioc_s_register = vidioc_s_register,
2168#endif
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002169};
2170
Hans Verkuila3998102008-07-21 02:57:38 -03002171static struct video_device em28xx_radio_template = {
Frank Schaefere8470222014-01-12 13:24:25 -03002172 .fops = &radio_fops,
2173 .ioctl_ops = &radio_ioctl_ops,
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002174 .release = video_device_release,
Hans Verkuila3998102008-07-21 02:57:38 -03002175};
2176
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002177/* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */
2178static unsigned short saa711x_addrs[] = {
2179 0x4a >> 1, 0x48 >> 1, /* SAA7111, SAA7111A and SAA7113 */
2180 0x42 >> 1, 0x40 >> 1, /* SAA7114, SAA7115 and SAA7118 */
2181 I2C_CLIENT_END };
2182
2183static unsigned short tvp5150_addrs[] = {
2184 0xb8 >> 1,
2185 0xba >> 1,
2186 I2C_CLIENT_END
2187};
2188
2189static unsigned short msp3400_addrs[] = {
2190 0x80 >> 1,
2191 0x88 >> 1,
2192 I2C_CLIENT_END
2193};
2194
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03002195/******************************** usb interface ******************************/
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002196
Adrian Bunk532fe652008-01-28 22:10:48 -03002197static struct video_device *em28xx_vdev_init(struct em28xx *dev,
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -03002198 const struct video_device *template,
2199 const char *type_name)
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002200{
2201 struct video_device *vfd;
2202
2203 vfd = video_device_alloc();
2204 if (NULL == vfd)
2205 return NULL;
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03002206
2207 *vfd = *template;
Frank Schaefer95d26082014-03-24 16:33:09 -03002208 vfd->v4l2_dev = &dev->v4l2->v4l2_dev;
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03002209 vfd->debug = video_debug;
Hans Verkuil0499a5a2010-09-26 07:34:45 -03002210 vfd->lock = &dev->lock;
Hans Verkuil69a61642012-09-07 05:52:40 -03002211 set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
Hans Verkuild8c95c02012-09-07 07:31:54 -03002212 if (dev->board.is_webcam)
2213 vfd->tvnorms = 0;
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002214
2215 snprintf(vfd->name, sizeof(vfd->name), "%s %s",
2216 dev->name, type_name);
2217
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02002218 video_set_drvdata(vfd, dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002219 return vfd;
2220}
2221
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002222static void em28xx_tuner_setup(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002223{
Frank Schaefer3854b0d2014-03-24 16:33:22 -03002224 struct em28xx_v4l2 *v4l2 = dev->v4l2;
2225 struct v4l2_device *v4l2_dev = &v4l2->v4l2_dev;
2226 struct tuner_setup tun_setup;
2227 struct v4l2_frequency f;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002228
2229 if (dev->tuner_type == TUNER_ABSENT)
2230 return;
2231
2232 memset(&tun_setup, 0, sizeof(tun_setup));
2233
2234 tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
2235 tun_setup.tuner_callback = em28xx_tuner_callback;
2236
2237 if (dev->board.radio.type) {
2238 tun_setup.type = dev->board.radio.type;
2239 tun_setup.addr = dev->board.radio_addr;
2240
Frank Schaefer95d26082014-03-24 16:33:09 -03002241 v4l2_device_call_all(v4l2_dev,
2242 0, tuner, s_type_addr, &tun_setup);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002243 }
2244
2245 if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type)) {
2246 tun_setup.type = dev->tuner_type;
2247 tun_setup.addr = dev->tuner_addr;
2248
Frank Schaefer95d26082014-03-24 16:33:09 -03002249 v4l2_device_call_all(v4l2_dev,
2250 0, tuner, s_type_addr, &tun_setup);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002251 }
2252
2253 if (dev->tda9887_conf) {
2254 struct v4l2_priv_tun_config tda9887_cfg;
2255
2256 tda9887_cfg.tuner = TUNER_TDA9887;
2257 tda9887_cfg.priv = &dev->tda9887_conf;
2258
Frank Schaefer95d26082014-03-24 16:33:09 -03002259 v4l2_device_call_all(v4l2_dev,
2260 0, tuner, s_config, &tda9887_cfg);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002261 }
2262
2263 if (dev->tuner_type == TUNER_XC2028) {
2264 struct v4l2_priv_tun_config xc2028_cfg;
2265 struct xc2028_ctrl ctl;
2266
2267 memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
2268 memset(&ctl, 0, sizeof(ctl));
2269
2270 em28xx_setup_xc3028(dev, &ctl);
2271
2272 xc2028_cfg.tuner = TUNER_XC2028;
2273 xc2028_cfg.priv = &ctl;
2274
Frank Schaefer95d26082014-03-24 16:33:09 -03002275 v4l2_device_call_all(v4l2_dev, 0, tuner, s_config, &xc2028_cfg);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002276 }
2277
2278 /* configure tuner */
2279 f.tuner = 0;
2280 f.type = V4L2_TUNER_ANALOG_TV;
2281 f.frequency = 9076; /* just a magic number */
Frank Schaefer3854b0d2014-03-24 16:33:22 -03002282 v4l2->frequency = f.frequency;
Frank Schaefer95d26082014-03-24 16:33:09 -03002283 v4l2_device_call_all(v4l2_dev, 0, tuner, s_frequency, &f);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002284}
2285
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002286static int em28xx_v4l2_init(struct em28xx *dev)
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002287{
Hans Verkuil081b9452012-09-07 05:43:59 -03002288 u8 val;
Mauro Carvalho Chehab2e5ef2d2008-12-28 22:26:36 -03002289 int ret;
Sascha Sommer1020d132012-01-08 16:54:28 -03002290 unsigned int maxw;
Frank Schaeferabc13082014-03-24 16:33:10 -03002291 struct v4l2_ctrl_handler *hdl;
Frank Schaefer95d26082014-03-24 16:33:09 -03002292 struct em28xx_v4l2 *v4l2;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002293
Mauro Carvalho Chehab822b8de2014-01-06 05:27:47 -03002294 if (dev->is_audio_only) {
2295 /* Shouldn't initialize IR for this interface */
2296 return 0;
2297 }
2298
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002299 if (!dev->has_video) {
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002300 /* This device does not support the v4l2 extension */
2301 return 0;
2302 }
Mauro Carvalho Chehab2e5ef2d2008-12-28 22:26:36 -03002303
Mauro Carvalho Chehab96346142013-12-26 12:41:03 -03002304 em28xx_info("Registering V4L2 extension\n");
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002305
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002306 mutex_lock(&dev->lock);
2307
Frank Schaefer95d26082014-03-24 16:33:09 -03002308 v4l2 = kzalloc(sizeof(struct em28xx_v4l2), GFP_KERNEL);
2309 if (v4l2 == NULL) {
2310 em28xx_info("em28xx_v4l: memory allocation failed\n");
2311 mutex_unlock(&dev->lock);
2312 return -ENOMEM;
2313 }
2314 kref_init(&v4l2->ref);
Frank Schaeferabc13082014-03-24 16:33:10 -03002315 v4l2->dev = dev;
Frank Schaefer95d26082014-03-24 16:33:09 -03002316 dev->v4l2 = v4l2;
2317
2318 ret = v4l2_device_register(&dev->udev->dev, &v4l2->v4l2_dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002319 if (ret < 0) {
2320 em28xx_errdev("Call to v4l2_device_register() failed!\n");
2321 goto err;
2322 }
2323
Frank Schaeferabc13082014-03-24 16:33:10 -03002324 hdl = &v4l2->ctrl_handler;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002325 v4l2_ctrl_handler_init(hdl, 8);
Frank Schaefer95d26082014-03-24 16:33:09 -03002326 v4l2->v4l2_dev.ctrl_handler = hdl;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002327
Frank Schaefer58159172014-03-24 16:33:18 -03002328 if (dev->board.is_webcam)
2329 v4l2->progressive = 1;
2330
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002331 /*
2332 * Default format, used for tvp5150 or saa711x output formats
2333 */
Frank Schaefer92972852014-03-24 16:33:15 -03002334 v4l2->vinmode = 0x10;
2335 v4l2->vinctl = EM28XX_VINCTRL_INTERLACED |
2336 EM28XX_VINCTRL_CCIR656_ENABLE;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002337
2338 /* request some modules */
2339
2340 if (dev->board.has_msp34xx)
Frank Schaefer95d26082014-03-24 16:33:09 -03002341 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2342 &dev->i2c_adap[dev->def_i2c_bus],
2343 "msp3400", 0, msp3400_addrs);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002344
2345 if (dev->board.decoder == EM28XX_SAA711X)
Frank Schaefer95d26082014-03-24 16:33:09 -03002346 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2347 &dev->i2c_adap[dev->def_i2c_bus],
2348 "saa7115_auto", 0, saa711x_addrs);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002349
2350 if (dev->board.decoder == EM28XX_TVP5150)
Frank Schaefer95d26082014-03-24 16:33:09 -03002351 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2352 &dev->i2c_adap[dev->def_i2c_bus],
2353 "tvp5150", 0, tvp5150_addrs);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002354
2355 if (dev->board.adecoder == EM28XX_TVAUDIO)
Frank Schaefer95d26082014-03-24 16:33:09 -03002356 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2357 &dev->i2c_adap[dev->def_i2c_bus],
2358 "tvaudio", dev->board.tvaudio_addr, NULL);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002359
2360 /* Initialize tuner and camera */
2361
2362 if (dev->board.tuner_type != TUNER_ABSENT) {
2363 int has_demod = (dev->tda9887_conf & TDA9887_PRESENT);
2364
2365 if (dev->board.radio.type)
Frank Schaefer95d26082014-03-24 16:33:09 -03002366 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2367 &dev->i2c_adap[dev->def_i2c_bus],
2368 "tuner", dev->board.radio_addr, NULL);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002369
2370 if (has_demod)
Frank Schaefer95d26082014-03-24 16:33:09 -03002371 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002372 &dev->i2c_adap[dev->def_i2c_bus], "tuner",
2373 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
2374 if (dev->tuner_addr == 0) {
2375 enum v4l2_i2c_tuner_type type =
2376 has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV;
2377 struct v4l2_subdev *sd;
2378
Frank Schaefer95d26082014-03-24 16:33:09 -03002379 sd = v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002380 &dev->i2c_adap[dev->def_i2c_bus], "tuner",
2381 0, v4l2_i2c_tuner_addrs(type));
2382
2383 if (sd)
2384 dev->tuner_addr = v4l2_i2c_subdev_addr(sd);
2385 } else {
Frank Schaefer95d26082014-03-24 16:33:09 -03002386 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2387 &dev->i2c_adap[dev->def_i2c_bus],
2388 "tuner", dev->tuner_addr, NULL);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002389 }
2390 }
2391
2392 em28xx_tuner_setup(dev);
Frank Schaeferd86bc652014-01-17 14:45:32 -03002393 if (dev->em28xx_sensor != EM28XX_NOSENSOR)
2394 em28xx_init_camera(dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002395
2396 /* Configure audio */
2397 ret = em28xx_audio_setup(dev);
2398 if (ret < 0) {
2399 em28xx_errdev("%s: Error while setting audio - error [%d]!\n",
2400 __func__, ret);
2401 goto unregister_dev;
2402 }
2403 if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
2404 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
2405 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
2406 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
2407 V4L2_CID_AUDIO_VOLUME, 0, 0x1f, 1, 0x1f);
2408 } else {
2409 /* install the em28xx notify callback */
2410 v4l2_ctrl_notify(v4l2_ctrl_find(hdl, V4L2_CID_AUDIO_MUTE),
2411 em28xx_ctrl_notify, dev);
2412 v4l2_ctrl_notify(v4l2_ctrl_find(hdl, V4L2_CID_AUDIO_VOLUME),
2413 em28xx_ctrl_notify, dev);
2414 }
2415
2416 /* wake i2c devices */
2417 em28xx_wake_i2c(dev);
2418
2419 /* init video dma queues */
2420 INIT_LIST_HEAD(&dev->vidq.active);
2421 INIT_LIST_HEAD(&dev->vbiq.active);
2422
2423 if (dev->board.has_msp34xx) {
2424 /* Send a reset to other chips via gpio */
2425 ret = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xf7);
2426 if (ret < 0) {
2427 em28xx_errdev("%s: em28xx_write_reg - msp34xx(1) failed! error [%d]\n",
2428 __func__, ret);
2429 goto unregister_dev;
2430 }
2431 msleep(3);
2432
2433 ret = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xff);
2434 if (ret < 0) {
2435 em28xx_errdev("%s: em28xx_write_reg - msp34xx(2) failed! error [%d]\n",
2436 __func__, ret);
2437 goto unregister_dev;
2438 }
2439 msleep(3);
2440 }
2441
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002442 /* set default norm */
Frank Schaefer52faaf72014-03-24 16:33:16 -03002443 v4l2->norm = V4L2_STD_PAL;
2444 v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_std, v4l2->norm);
Frank Schaefer58159172014-03-24 16:33:18 -03002445 v4l2->interlaced_fieldmode = EM28XX_INTERLACED_DEFAULT;
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002446
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002447 /* Analog specific initialization */
Frank Schaefer06e20672014-03-24 16:33:17 -03002448 v4l2->format = &format[0];
Sascha Sommer1020d132012-01-08 16:54:28 -03002449
2450 maxw = norm_maxw(dev);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002451 /* MaxPacketSize for em2800 is too small to capture at full resolution
2452 * use half of maxw as the scaler can only scale to 50% */
2453 if (dev->board.is_em2800)
2454 maxw /= 2;
Sascha Sommer1020d132012-01-08 16:54:28 -03002455
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03002456 em28xx_set_video_format(dev, format[0].fourcc,
Sascha Sommer1020d132012-01-08 16:54:28 -03002457 maxw, norm_maxh(dev));
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03002458
Ezequiel García96371fc2012-03-23 18:09:34 -03002459 video_mux(dev, 0);
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002460
2461 /* Audio defaults */
2462 dev->mute = 1;
2463 dev->volume = 0x1f;
2464
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002465/* em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -03002466 val = (u8)em28xx_read_reg(dev, EM28XX_R0F_XCLK);
2467 em28xx_write_reg(dev, EM28XX_R0F_XCLK,
2468 (EM28XX_XCLK_AUDIO_UNMUTE | val));
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002469
2470 em28xx_set_outfmt(dev);
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002471
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002472 /* Add image controls */
2473 /* NOTE: at this point, the subdevices are already registered, so bridge
2474 * controls are only added/enabled when no subdevice provides them */
Frank Schaeferad298052014-03-24 16:33:08 -03002475 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_CONTRAST))
2476 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002477 V4L2_CID_CONTRAST,
2478 0, 0x1f, 1, CONTRAST_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002479 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_BRIGHTNESS))
2480 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002481 V4L2_CID_BRIGHTNESS,
2482 -0x80, 0x7f, 1, BRIGHTNESS_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002483 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_SATURATION))
2484 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002485 V4L2_CID_SATURATION,
2486 0, 0x1f, 1, SATURATION_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002487 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_BLUE_BALANCE))
2488 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002489 V4L2_CID_BLUE_BALANCE,
2490 -0x30, 0x30, 1, BLUE_BALANCE_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002491 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_RED_BALANCE))
2492 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002493 V4L2_CID_RED_BALANCE,
2494 -0x30, 0x30, 1, RED_BALANCE_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002495 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_SHARPNESS))
2496 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002497 V4L2_CID_SHARPNESS,
2498 0, 0x0f, 1, SHARPNESS_DEFAULT);
2499
2500 /* Reset image controls */
2501 em28xx_colorlevels_set_default(dev);
Frank Schaeferad298052014-03-24 16:33:08 -03002502 v4l2_ctrl_handler_setup(hdl);
2503 ret = hdl->error;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002504 if (ret)
2505 goto unregister_dev;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002506
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002507 /* allocate and fill video video_device struct */
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002508 v4l2->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video");
2509 if (!v4l2->vdev) {
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002510 em28xx_errdev("cannot allocate video_device.\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002511 ret = -ENODEV;
2512 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002513 }
Frank Schaefer27a36df2014-03-24 16:33:13 -03002514 mutex_init(&v4l2->vb_queue_lock);
2515 mutex_init(&v4l2->vb_vbi_queue_lock);
2516 v4l2->vdev->queue = &v4l2->vb_vidq;
2517 v4l2->vdev->queue->lock = &v4l2->vb_queue_lock;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002518
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002519 /* disable inapplicable ioctls */
2520 if (dev->board.is_webcam) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002521 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_QUERYSTD);
2522 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_G_STD);
2523 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_STD);
Frank Schaefer3bc85cc2013-02-07 13:39:12 -03002524 } else {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002525 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_PARM);
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002526 }
Frank Schaefer66df67b2013-02-07 13:39:10 -03002527 if (dev->tuner_type == TUNER_ABSENT) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002528 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_G_TUNER);
2529 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_TUNER);
2530 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_G_FREQUENCY);
2531 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_FREQUENCY);
Frank Schaefer66df67b2013-02-07 13:39:10 -03002532 }
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002533 if (!dev->audio_mode.has_audio) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002534 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_G_AUDIO);
2535 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_AUDIO);
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002536 }
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002537
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002538 /* register v4l2 video video_device */
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002539 ret = video_register_device(v4l2->vdev, VFL_TYPE_GRABBER,
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002540 video_nr[dev->devno]);
2541 if (ret) {
2542 em28xx_errdev("unable to register video device (error=%i).\n",
2543 ret);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002544 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002545 }
2546
2547 /* Allocate and fill vbi video_device struct */
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002548 if (em28xx_vbi_supported(dev) == 1) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002549 v4l2->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template,
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002550 "vbi");
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002551
Frank Schaefer27a36df2014-03-24 16:33:13 -03002552 v4l2->vbi_dev->queue = &v4l2->vb_vbiq;
2553 v4l2->vbi_dev->queue->lock = &v4l2->vb_vbi_queue_lock;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002554
Frank Schaefer66df67b2013-02-07 13:39:10 -03002555 /* disable inapplicable ioctls */
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002556 v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_PARM);
Frank Schaefer66df67b2013-02-07 13:39:10 -03002557 if (dev->tuner_type == TUNER_ABSENT) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002558 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_G_TUNER);
2559 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_TUNER);
2560 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_G_FREQUENCY);
2561 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_FREQUENCY);
Frank Schaefer66df67b2013-02-07 13:39:10 -03002562 }
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002563 if (!dev->audio_mode.has_audio) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002564 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_G_AUDIO);
2565 v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_AUDIO);
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002566 }
Frank Schaefer66df67b2013-02-07 13:39:10 -03002567
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002568 /* register v4l2 vbi video_device */
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002569 ret = video_register_device(v4l2->vbi_dev, VFL_TYPE_VBI,
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002570 vbi_nr[dev->devno]);
2571 if (ret < 0) {
2572 em28xx_errdev("unable to register vbi device\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002573 goto unregister_dev;
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002574 }
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002575 }
2576
2577 if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) {
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002578 v4l2->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template,
2579 "radio");
2580 if (!v4l2->radio_dev) {
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002581 em28xx_errdev("cannot allocate video_device.\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002582 ret = -ENODEV;
2583 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002584 }
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002585 ret = video_register_device(v4l2->radio_dev, VFL_TYPE_RADIO,
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002586 radio_nr[dev->devno]);
2587 if (ret < 0) {
2588 em28xx_errdev("can't register radio device\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002589 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002590 }
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002591 em28xx_info("Registered radio device as %s\n",
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002592 video_device_node_name(v4l2->radio_dev));
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002593 }
2594
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002595 em28xx_info("V4L2 video device registered as %s\n",
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002596 video_device_node_name(v4l2->vdev));
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002597
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002598 if (v4l2->vbi_dev)
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002599 em28xx_info("V4L2 VBI device registered as %s\n",
Frank Schaeferef74a0b2014-03-24 16:33:12 -03002600 video_device_node_name(v4l2->vbi_dev));
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002601
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002602 /* Save some power by putting tuner to sleep */
Frank Schaefer95d26082014-03-24 16:33:09 -03002603 v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_power, 0);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002604
2605 /* initialize videobuf2 stuff */
2606 em28xx_vb2_setup(dev);
2607
Mauro Carvalho Chehab96346142013-12-26 12:41:03 -03002608 em28xx_info("V4L2 extension successfully initialized\n");
2609
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002610 kref_get(&dev->ref);
2611
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002612 mutex_unlock(&dev->lock);
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002613 return 0;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002614
2615unregister_dev:
Frank Schaeferabc13082014-03-24 16:33:10 -03002616 v4l2_ctrl_handler_free(&v4l2->ctrl_handler);
Frank Schaefer95d26082014-03-24 16:33:09 -03002617 v4l2_device_unregister(&v4l2->v4l2_dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002618err:
Frank Schaefer95d26082014-03-24 16:33:09 -03002619 dev->v4l2 = NULL;
2620 kref_put(&v4l2->ref, em28xx_free_v4l2);
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002621 mutex_unlock(&dev->lock);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002622 return ret;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002623}
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002624
2625static struct em28xx_ops v4l2_ops = {
2626 .id = EM28XX_V4L2,
2627 .name = "Em28xx v4l2 Extension",
2628 .init = em28xx_v4l2_init,
2629 .fini = em28xx_v4l2_fini,
Shuah Khana61f6812014-02-21 21:50:17 -03002630 .suspend = em28xx_v4l2_suspend,
2631 .resume = em28xx_v4l2_resume,
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002632};
2633
2634static int __init em28xx_video_register(void)
2635{
2636 return em28xx_register_extension(&v4l2_ops);
2637}
2638
2639static void __exit em28xx_video_unregister(void)
2640{
2641 em28xx_unregister_extension(&v4l2_ops);
2642}
2643
2644module_init(em28xx_video_register);
2645module_exit(em28xx_video_unregister);