blob: ae959e01042a6666a275102a9fd902b2f844d2ee [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>
Mauro Carvalho Chehabd647f0b2015-11-13 19:40:07 -020046#include <media/drv-intf/msp3400.h>
Mauro Carvalho Chehabed086312008-01-24 06:59:20 -030047#include <media/tuner.h>
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080048
Mauro Carvalho Chehabf7abcd32005-11-08 21:38:25 -080049#define DRIVER_AUTHOR "Ludovico Cavedon <cavedon@sssup.it>, " \
50 "Markus Rechberger <mrechberger@gmail.com>, " \
Mauro Carvalho Chehab2e7c6dc2006-04-03 07:53:40 -030051 "Mauro Carvalho Chehab <mchehab@infradead.org>, " \
Mauro Carvalho Chehabf7abcd32005-11-08 21:38:25 -080052 "Sascha Sommer <saschasommer@freenet.de>"
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080053
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -030054static unsigned int isoc_debug;
55module_param(isoc_debug, int, 0644);
56MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");
57
58static unsigned int disable_vbi;
59module_param(disable_vbi, int, 0644);
60MODULE_PARM_DESC(disable_vbi, "disable vbi support");
61
62static int alt;
63module_param(alt, int, 0644);
64MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint");
65
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -080066#define em28xx_videodbg(fmt, arg...) do {\
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -080067 if (video_debug) \
68 printk(KERN_INFO "%s %s :"fmt, \
Harvey Harrisond80e1342008-04-08 23:20:00 -030069 dev->name, __func__ , ##arg); } while (0)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080070
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -030071#define em28xx_isocdbg(fmt, arg...) \
72do {\
73 if (isoc_debug) { \
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -030074 printk(KERN_INFO "%s %s :"fmt, \
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -030075 dev->name, __func__ , ##arg); \
76 } \
77 } while (0)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -030078
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080079MODULE_AUTHOR(DRIVER_AUTHOR);
Mauro Carvalho Chehabd8992b02013-12-27 11:14:59 -030080MODULE_DESCRIPTION(DRIVER_DESC " - v4l2 interface");
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080081MODULE_LICENSE("GPL");
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -030082MODULE_VERSION(EM28XX_VERSION);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080083
Frank Schaefere507e0e2013-03-26 13:38:38 -030084#define EM25XX_FRMDATAHDR_BYTE1 0x02
85#define EM25XX_FRMDATAHDR_BYTE2_STILL_IMAGE 0x20
86#define EM25XX_FRMDATAHDR_BYTE2_FRAME_END 0x02
87#define EM25XX_FRMDATAHDR_BYTE2_FRAME_ID 0x01
88#define EM25XX_FRMDATAHDR_BYTE2_MASK (EM25XX_FRMDATAHDR_BYTE2_STILL_IMAGE | \
89 EM25XX_FRMDATAHDR_BYTE2_FRAME_END | \
90 EM25XX_FRMDATAHDR_BYTE2_FRAME_ID)
91
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -030092static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
93static unsigned int vbi_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
94static unsigned int radio_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -030095
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -020096module_param_array(video_nr, int, NULL, 0444);
97module_param_array(vbi_nr, int, NULL, 0444);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -030098module_param_array(radio_nr, int, NULL, 0444);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -030099MODULE_PARM_DESC(video_nr, "video device numbers");
100MODULE_PARM_DESC(vbi_nr, "vbi device numbers");
101MODULE_PARM_DESC(radio_nr, "radio device numbers");
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800102
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -0300103static unsigned int video_debug;
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -0300104module_param(video_debug, int, 0644);
105MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800106
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -0300107/* supported video standards */
108static struct em28xx_fmt format[] = {
109 {
Mauro Carvalho Chehab58fc1ce2009-07-03 02:54:18 -0300110 .name = "16 bpp YUY2, 4:2:2, packed",
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -0300111 .fourcc = V4L2_PIX_FMT_YUYV,
112 .depth = 16,
Devin Heitmueller3fbf9302008-12-29 23:34:37 -0300113 .reg = EM28XX_OUTFMT_YUV422_Y0UY1V,
Mauro Carvalho Chehab43cb9fe2009-06-30 08:36:17 -0300114 }, {
Mauro Carvalho Chehab58fc1ce2009-07-03 02:54:18 -0300115 .name = "16 bpp RGB 565, LE",
Mauro Carvalho Chehab43cb9fe2009-06-30 08:36:17 -0300116 .fourcc = V4L2_PIX_FMT_RGB565,
117 .depth = 16,
Mauro Carvalho Chehab58fc1ce2009-07-03 02:54:18 -0300118 .reg = EM28XX_OUTFMT_RGB_16_656,
119 }, {
120 .name = "8 bpp Bayer BGBG..GRGR",
121 .fourcc = V4L2_PIX_FMT_SBGGR8,
122 .depth = 8,
123 .reg = EM28XX_OUTFMT_RGB_8_BGBG,
124 }, {
125 .name = "8 bpp Bayer GRGR..BGBG",
126 .fourcc = V4L2_PIX_FMT_SGRBG8,
127 .depth = 8,
128 .reg = EM28XX_OUTFMT_RGB_8_GRGR,
129 }, {
130 .name = "8 bpp Bayer GBGB..RGRG",
131 .fourcc = V4L2_PIX_FMT_SGBRG8,
132 .depth = 8,
133 .reg = EM28XX_OUTFMT_RGB_8_GBGB,
134 }, {
135 .name = "12 bpp YUV411",
136 .fourcc = V4L2_PIX_FMT_YUV411P,
137 .depth = 12,
138 .reg = EM28XX_OUTFMT_YUV411,
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -0300139 },
140};
141
Frank Schaefer25c61e42014-03-22 10:01:03 -0300142/*FIXME: maxw should be dependent of alt mode */
143static inline unsigned int norm_maxw(struct em28xx *dev)
144{
Frank Schaeferd7dc18d2014-03-24 16:33:19 -0300145 struct em28xx_v4l2 *v4l2 = dev->v4l2;
146
Frank Schaefer25c61e42014-03-22 10:01:03 -0300147 if (dev->board.is_webcam)
Frank Schaeferd7dc18d2014-03-24 16:33:19 -0300148 return v4l2->sensor_xres;
Frank Schaefer25c61e42014-03-22 10:01:03 -0300149
150 if (dev->board.max_range_640_480)
151 return 640;
152
153 return 720;
154}
155
156static inline unsigned int norm_maxh(struct em28xx *dev)
157{
Frank Schaefer52faaf72014-03-24 16:33:16 -0300158 struct em28xx_v4l2 *v4l2 = dev->v4l2;
159
Frank Schaefer25c61e42014-03-22 10:01:03 -0300160 if (dev->board.is_webcam)
Frank Schaeferd7dc18d2014-03-24 16:33:19 -0300161 return v4l2->sensor_yres;
Frank Schaefer25c61e42014-03-22 10:01:03 -0300162
163 if (dev->board.max_range_640_480)
164 return 480;
165
Frank Schaefer52faaf72014-03-24 16:33:16 -0300166 return (v4l2->norm & V4L2_STD_625_50) ? 576 : 480;
Frank Schaefer25c61e42014-03-22 10:01:03 -0300167}
168
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300169static int em28xx_vbi_supported(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300170{
171 /* Modprobe option to manually disable */
172 if (disable_vbi == 1)
173 return 0;
174
175 if (dev->board.is_webcam)
176 return 0;
177
178 /* FIXME: check subdevices for VBI support */
179
180 if (dev->chip_id == CHIP_ID_EM2860 ||
181 dev->chip_id == CHIP_ID_EM2883)
182 return 1;
183
184 /* Version of em28xx that does not support VBI */
185 return 0;
186}
187
188/*
189 * em28xx_wake_i2c()
190 * configure i2c attached devices
191 */
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300192static void em28xx_wake_i2c(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300193{
Frank Schaefer95d26082014-03-24 16:33:09 -0300194 struct v4l2_device *v4l2_dev = &dev->v4l2->v4l2_dev;
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -0300195
Frank Schaefer95d26082014-03-24 16:33:09 -0300196 v4l2_device_call_all(v4l2_dev, 0, core, reset, 0);
197 v4l2_device_call_all(v4l2_dev, 0, video, s_routing,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -0300198 INPUT(dev->ctl_input)->vmux, 0, 0);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300199}
200
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300201static int em28xx_colorlevels_set_default(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300202{
203 em28xx_write_reg(dev, EM28XX_R20_YGAIN, CONTRAST_DEFAULT);
204 em28xx_write_reg(dev, EM28XX_R21_YOFFSET, BRIGHTNESS_DEFAULT);
205 em28xx_write_reg(dev, EM28XX_R22_UVGAIN, SATURATION_DEFAULT);
206 em28xx_write_reg(dev, EM28XX_R23_UOFFSET, BLUE_BALANCE_DEFAULT);
207 em28xx_write_reg(dev, EM28XX_R24_VOFFSET, RED_BALANCE_DEFAULT);
208 em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, SHARPNESS_DEFAULT);
209
210 em28xx_write_reg(dev, EM28XX_R14_GAMMA, 0x20);
211 em28xx_write_reg(dev, EM28XX_R15_RGAIN, 0x20);
212 em28xx_write_reg(dev, EM28XX_R16_GGAIN, 0x20);
213 em28xx_write_reg(dev, EM28XX_R17_BGAIN, 0x20);
214 em28xx_write_reg(dev, EM28XX_R18_ROFFSET, 0x00);
215 em28xx_write_reg(dev, EM28XX_R19_GOFFSET, 0x00);
216 return em28xx_write_reg(dev, EM28XX_R1A_BOFFSET, 0x00);
217}
218
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300219static int em28xx_set_outfmt(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300220{
221 int ret;
222 u8 fmt, vinctrl;
Frank Schaefer753aee72014-03-24 16:33:14 -0300223 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300224
Frank Schaefer06e20672014-03-24 16:33:17 -0300225 fmt = v4l2->format->reg;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300226 if (!dev->is_em25xx)
227 fmt |= 0x20;
228 /*
229 * NOTE: it's not clear if this is really needed !
230 * The datasheets say bit 5 is a reserved bit and devices seem to work
231 * fine without it. But the Windows driver sets it for em2710/50+em28xx
232 * devices and we've always been setting it, too.
233 *
234 * em2765 (em25xx, em276x/7x/8x) devices do NOT work with this bit set,
235 * it's likely used for an additional (compressed ?) format there.
236 */
237 ret = em28xx_write_reg(dev, EM28XX_R27_OUTFMT, fmt);
238 if (ret < 0)
239 return ret;
240
Frank Schaefer92972852014-03-24 16:33:15 -0300241 ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, v4l2->vinmode);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300242 if (ret < 0)
243 return ret;
244
Frank Schaefer92972852014-03-24 16:33:15 -0300245 vinctrl = v4l2->vinctl;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300246 if (em28xx_vbi_supported(dev) == 1) {
247 vinctrl |= EM28XX_VINCTRL_VBI_RAW;
248 em28xx_write_reg(dev, EM28XX_R34_VBI_START_H, 0x00);
Frank Schaefer753aee72014-03-24 16:33:14 -0300249 em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH, v4l2->vbi_width/4);
250 em28xx_write_reg(dev, EM28XX_R37_VBI_HEIGHT, v4l2->vbi_height);
Frank Schaefer52faaf72014-03-24 16:33:16 -0300251 if (v4l2->norm & V4L2_STD_525_60) {
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300252 /* NTSC */
253 em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x09);
Frank Schaefer52faaf72014-03-24 16:33:16 -0300254 } else if (v4l2->norm & V4L2_STD_625_50) {
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300255 /* PAL */
256 em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x07);
257 }
258 }
259
260 return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctrl);
261}
262
263static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax,
264 u8 ymin, u8 ymax)
265{
266 em28xx_videodbg("em28xx Scale: (%d,%d)-(%d,%d)\n",
267 xmin, ymin, xmax, ymax);
268
269 em28xx_write_regs(dev, EM28XX_R28_XMIN, &xmin, 1);
270 em28xx_write_regs(dev, EM28XX_R29_XMAX, &xmax, 1);
271 em28xx_write_regs(dev, EM28XX_R2A_YMIN, &ymin, 1);
272 return em28xx_write_regs(dev, EM28XX_R2B_YMAX, &ymax, 1);
273}
274
275static void em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -0300276 u16 width, u16 height)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300277{
278 u8 cwidth = width >> 2;
279 u8 cheight = height >> 2;
280 u8 overflow = (height >> 9 & 0x02) | (width >> 10 & 0x01);
281 /* NOTE: size limit: 2047x1023 = 2MPix */
282
283 em28xx_videodbg("capture area set to (%d,%d): %dx%d\n",
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -0300284 hstart, vstart,
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300285 ((overflow & 2) << 9 | cwidth << 2),
286 ((overflow & 1) << 10 | cheight << 2));
287
288 em28xx_write_regs(dev, EM28XX_R1C_HSTART, &hstart, 1);
289 em28xx_write_regs(dev, EM28XX_R1D_VSTART, &vstart, 1);
290 em28xx_write_regs(dev, EM28XX_R1E_CWIDTH, &cwidth, 1);
291 em28xx_write_regs(dev, EM28XX_R1F_CHEIGHT, &cheight, 1);
292 em28xx_write_regs(dev, EM28XX_R1B_OFLOW, &overflow, 1);
293
294 /* FIXME: function/meaning of these registers ? */
295 /* FIXME: align width+height to multiples of 4 ?! */
296 if (dev->is_em25xx) {
297 em28xx_write_reg(dev, 0x34, width >> 4);
298 em28xx_write_reg(dev, 0x35, height >> 4);
299 }
300}
301
302static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v)
303{
Frank Schaefercba8e9b2014-03-24 16:28:36 -0300304 u8 mode = 0x00;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300305 /* the em2800 scaler only supports scaling down to 50% */
306
307 if (dev->board.is_em2800) {
308 mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00);
309 } else {
310 u8 buf[2];
311
312 buf[0] = h;
313 buf[1] = h >> 8;
314 em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2);
315
316 buf[0] = v;
317 buf[1] = v >> 8;
318 em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2);
319 /* it seems that both H and V scalers must be active
320 to work correctly */
321 mode = (h || v) ? 0x30 : 0x00;
322 }
Frank Schaefercba8e9b2014-03-24 16:28:36 -0300323 return em28xx_write_reg(dev, EM28XX_R26_COMPR, mode);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300324}
325
326/* FIXME: this only function read values from dev */
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300327static int em28xx_resolution_set(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300328{
Frank Schaefer753aee72014-03-24 16:33:14 -0300329 struct em28xx_v4l2 *v4l2 = dev->v4l2;
330 int width = norm_maxw(dev);
331 int height = norm_maxh(dev);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300332
333 /* Properly setup VBI */
Frank Schaefer753aee72014-03-24 16:33:14 -0300334 v4l2->vbi_width = 720;
Frank Schaefer52faaf72014-03-24 16:33:16 -0300335 if (v4l2->norm & V4L2_STD_525_60)
Frank Schaefer753aee72014-03-24 16:33:14 -0300336 v4l2->vbi_height = 12;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300337 else
Frank Schaefer753aee72014-03-24 16:33:14 -0300338 v4l2->vbi_height = 18;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300339
340 em28xx_set_outfmt(dev);
341
342 em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2);
343
344 /* If we don't set the start position to 2 in VBI mode, we end up
345 with line 20/21 being YUYV encoded instead of being in 8-bit
346 greyscale. The core of the issue is that line 21 (and line 23 for
347 PAL WSS) are inside of active video region, and as a result they
348 get the pixelformatting associated with that area. So by cropping
349 it out, we end up with the same format as the rest of the VBI
350 region */
351 if (em28xx_vbi_supported(dev) == 1)
352 em28xx_capture_area_set(dev, 0, 2, width, height);
353 else
354 em28xx_capture_area_set(dev, 0, 0, width, height);
355
Frank Schaefer753aee72014-03-24 16:33:14 -0300356 return em28xx_scaler_set(dev, v4l2->hscale, v4l2->vscale);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300357}
358
359/* Set USB alternate setting for analog video */
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300360static int em28xx_set_alternate(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300361{
Frank Schaefer753aee72014-03-24 16:33:14 -0300362 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300363 int errCode;
364 int i;
Frank Schaefer753aee72014-03-24 16:33:14 -0300365 unsigned int min_pkt_size = v4l2->width * 2 + 4;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300366
367 /* NOTE: for isoc transfers, only alt settings > 0 are allowed
368 bulk transfers seem to work only with alt=0 ! */
369 dev->alt = 0;
370 if ((alt > 0) && (alt < dev->num_alt)) {
371 em28xx_videodbg("alternate forced to %d\n", dev->alt);
372 dev->alt = alt;
373 goto set_alt;
374 }
375 if (dev->analog_xfer_bulk)
376 goto set_alt;
377
378 /* When image size is bigger than a certain value,
379 the frame size should be increased, otherwise, only
380 green screen will be received.
381 */
Frank Schaefer753aee72014-03-24 16:33:14 -0300382 if (v4l2->width * 2 * v4l2->height > 720 * 240 * 2)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300383 min_pkt_size *= 2;
384
385 for (i = 0; i < dev->num_alt; i++) {
386 /* stop when the selected alt setting offers enough bandwidth */
387 if (dev->alt_max_pkt_size_isoc[i] >= min_pkt_size) {
388 dev->alt = i;
389 break;
390 /* otherwise make sure that we end up with the maximum bandwidth
391 because the min_pkt_size equation might be wrong...
392 */
393 } else if (dev->alt_max_pkt_size_isoc[i] >
394 dev->alt_max_pkt_size_isoc[dev->alt])
395 dev->alt = i;
396 }
397
398set_alt:
399 /* NOTE: for bulk transfers, we need to call usb_set_interface()
400 * even if the previous settings were the same. Otherwise streaming
401 * fails with all urbs having status = -EOVERFLOW ! */
402 if (dev->analog_xfer_bulk) {
403 dev->max_pkt_size = 512; /* USB 2.0 spec */
404 dev->packet_multiplier = EM28XX_BULK_PACKET_MULTIPLIER;
405 } else { /* isoc */
406 em28xx_videodbg("minimum isoc packet size: %u (alt=%d)\n",
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -0300407 min_pkt_size, dev->alt);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300408 dev->max_pkt_size =
409 dev->alt_max_pkt_size_isoc[dev->alt];
410 dev->packet_multiplier = EM28XX_NUM_ISOC_PACKETS;
411 }
412 em28xx_videodbg("setting alternate %d with wMaxPacketSize=%u\n",
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -0300413 dev->alt, dev->max_pkt_size);
Frank Schaefer961717b2014-01-13 19:02:06 -0300414 errCode = usb_set_interface(dev->udev, dev->ifnum, dev->alt);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300415 if (errCode < 0) {
416 em28xx_errdev("cannot change alternate number to %d (error=%i)\n",
417 dev->alt, errCode);
418 return errCode;
419 }
420 return 0;
421}
422
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300423/* ------------------------------------------------------------------
424 DMA and thread functions
425 ------------------------------------------------------------------*/
426
427/*
Frank Schaefer948a49a2012-12-08 11:31:25 -0300428 * Finish the current buffer
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300429 */
Frank Schaefer948a49a2012-12-08 11:31:25 -0300430static inline void finish_buffer(struct em28xx *dev,
431 struct em28xx_buffer *buf)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300432{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300433 em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->top_field);
434
Junghak Sung2d700712015-09-22 10:30:30 -0300435 buf->vb.sequence = dev->v4l2->field_count++;
Frank Schaefer662c97c2014-08-09 06:37:21 -0300436 if (dev->v4l2->progressive)
Junghak Sung2d700712015-09-22 10:30:30 -0300437 buf->vb.field = V4L2_FIELD_NONE;
Frank Schaefer662c97c2014-08-09 06:37:21 -0300438 else
Junghak Sung2d700712015-09-22 10:30:30 -0300439 buf->vb.field = V4L2_FIELD_INTERLACED;
Junghak Sungd6dd6452015-11-03 08:16:37 -0200440 buf->vb.vb2_buf.timestamp = ktime_get_ns();
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300441
Junghak Sung2d700712015-09-22 10:30:30 -0300442 vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300443}
444
445/*
Frank Schaefer36016a32012-12-08 11:31:32 -0300446 * Copy picture data from USB buffer to videobuf buffer
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300447 */
448static void em28xx_copy_video(struct em28xx *dev,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300449 struct em28xx_buffer *buf,
Frank Schaefer36016a32012-12-08 11:31:32 -0300450 unsigned char *usb_buf,
Frank Schaefer4078d622012-12-08 11:31:29 -0300451 unsigned long len)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300452{
Frank Schaefer58159172014-03-24 16:33:18 -0300453 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300454 void *fieldstart, *startwrite, *startread;
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300455 int linesdone, currlinedone, offset, lencopy, remain;
Frank Schaefer58159172014-03-24 16:33:18 -0300456 int bytesperline = v4l2->width << 1;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300457
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300458 if (buf->pos + len > buf->length)
459 len = buf->length - buf->pos;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300460
Frank Schaefer36016a32012-12-08 11:31:32 -0300461 startread = usb_buf;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300462 remain = len;
463
Frank Schaefer58159172014-03-24 16:33:18 -0300464 if (v4l2->progressive || buf->top_field)
Frank Schaefer36016a32012-12-08 11:31:32 -0300465 fieldstart = buf->vb_buf;
Frank Schaeferc02ec712012-11-08 14:11:33 -0300466 else /* interlaced mode, even nr. of lines */
Frank Schaefer36016a32012-12-08 11:31:32 -0300467 fieldstart = buf->vb_buf + bytesperline;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300468
Frank Schaefer87325332012-12-08 11:31:27 -0300469 linesdone = buf->pos / bytesperline;
470 currlinedone = buf->pos % bytesperline;
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -0300471
Frank Schaefer58159172014-03-24 16:33:18 -0300472 if (v4l2->progressive)
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -0300473 offset = linesdone * bytesperline + currlinedone;
474 else
475 offset = linesdone * bytesperline * 2 + currlinedone;
476
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300477 startwrite = fieldstart + offset;
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300478 lencopy = bytesperline - currlinedone;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300479 lencopy = lencopy > remain ? remain : lencopy;
480
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300481 if ((char *)startwrite + lencopy > (char *)buf->vb_buf + buf->length) {
Mauro Carvalho Chehab7983b772014-09-24 20:36:07 -0300482 em28xx_isocdbg("Overflow of %zu bytes past buffer end (1)\n",
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -0300483 ((char *)startwrite + lencopy) -
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300484 ((char *)buf->vb_buf + buf->length));
485 remain = (char *)buf->vb_buf + buf->length -
Frank Schaefer36016a32012-12-08 11:31:32 -0300486 (char *)startwrite;
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -0300487 lencopy = remain;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300488 }
Aidan Thorntone0fadfd342008-04-13 14:56:02 -0300489 if (lencopy <= 0)
490 return;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300491 memcpy(startwrite, startread, lencopy);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300492
493 remain -= lencopy;
494
495 while (remain > 0) {
Frank Schaefer58159172014-03-24 16:33:18 -0300496 if (v4l2->progressive)
Frank Schaeferc02ec712012-11-08 14:11:33 -0300497 startwrite += lencopy;
498 else
499 startwrite += lencopy + bytesperline;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300500 startread += lencopy;
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300501 if (bytesperline > remain)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300502 lencopy = remain;
503 else
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300504 lencopy = bytesperline;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300505
Frank Schaefer36016a32012-12-08 11:31:32 -0300506 if ((char *)startwrite + lencopy > (char *)buf->vb_buf +
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300507 buf->length) {
Mauro Carvalho Chehab7983b772014-09-24 20:36:07 -0300508 em28xx_isocdbg("Overflow of %zu bytes past buffer end"
Devin Heitmuellere3ba4d32009-09-15 00:18:06 -0300509 "(2)\n",
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300510 ((char *)startwrite + lencopy) -
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300511 ((char *)buf->vb_buf + buf->length));
512 lencopy = remain = (char *)buf->vb_buf + buf->length -
513 (char *)startwrite;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300514 }
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300515 if (lencopy <= 0)
516 break;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300517
518 memcpy(startwrite, startread, lencopy);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300519
520 remain -= lencopy;
521 }
522
Frank Schaefer87325332012-12-08 11:31:27 -0300523 buf->pos += len;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300524}
525
Frank Schaefer36016a32012-12-08 11:31:32 -0300526/*
527 * Copy VBI data from USB buffer to videobuf buffer
528 */
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300529static void em28xx_copy_vbi(struct em28xx *dev,
Frank Schaefer87325332012-12-08 11:31:27 -0300530 struct em28xx_buffer *buf,
Frank Schaefer36016a32012-12-08 11:31:32 -0300531 unsigned char *usb_buf,
Frank Schaefer4078d622012-12-08 11:31:29 -0300532 unsigned long len)
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300533{
Frank Schaefer36016a32012-12-08 11:31:32 -0300534 unsigned int offset;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300535
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300536 if (buf->pos + len > buf->length)
537 len = buf->length - buf->pos;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300538
Frank Schaefer87325332012-12-08 11:31:27 -0300539 offset = buf->pos;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300540 /* Make sure the bottom field populates the second half of the frame */
Frank Schaefer36016a32012-12-08 11:31:32 -0300541 if (buf->top_field == 0)
Frank Schaefer753aee72014-03-24 16:33:14 -0300542 offset += dev->v4l2->vbi_width * dev->v4l2->vbi_height;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300543
Frank Schaefer36016a32012-12-08 11:31:32 -0300544 memcpy(buf->vb_buf + offset, usb_buf, len);
Frank Schaefer87325332012-12-08 11:31:27 -0300545 buf->pos += len;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300546}
547
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300548static inline void print_err_status(struct em28xx *dev,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -0300549 int packet, int status)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300550{
551 char *errmsg = "Unknown";
552
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300553 switch (status) {
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300554 case -ENOENT:
555 errmsg = "unlinked synchronuously";
556 break;
557 case -ECONNRESET:
558 errmsg = "unlinked asynchronuously";
559 break;
560 case -ENOSR:
561 errmsg = "Buffer error (overrun)";
562 break;
563 case -EPIPE:
564 errmsg = "Stalled (device not responding)";
565 break;
566 case -EOVERFLOW:
567 errmsg = "Babble (bad cable?)";
568 break;
569 case -EPROTO:
570 errmsg = "Bit-stuff error (bad cable?)";
571 break;
572 case -EILSEQ:
573 errmsg = "CRC/Timeout (could be anything)";
574 break;
575 case -ETIME:
576 errmsg = "Device does not respond";
577 break;
578 }
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300579 if (packet < 0) {
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300580 em28xx_isocdbg("URB status %d [%s].\n", status, errmsg);
581 } else {
582 em28xx_isocdbg("URB packet %d, status %d [%s].\n",
583 packet, status, errmsg);
584 }
585}
586
587/*
Frank Schaefer24a6d842012-12-08 11:31:24 -0300588 * get the next available buffer from dma queue
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300589 */
Frank Schaefer24a6d842012-12-08 11:31:24 -0300590static inline struct em28xx_buffer *get_next_buf(struct em28xx *dev,
591 struct em28xx_dmaqueue *dma_q)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300592{
Frank Schaefer24a6d842012-12-08 11:31:24 -0300593 struct em28xx_buffer *buf;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300594
Mauro Carvalho Chehabdbecb442008-04-13 15:08:55 -0300595 if (list_empty(&dma_q->active)) {
596 em28xx_isocdbg("No active queue to serve\n");
Frank Schaefer24a6d842012-12-08 11:31:24 -0300597 return NULL;
Mauro Carvalho Chehabdbecb442008-04-13 15:08:55 -0300598 }
599
Mauro Carvalho Chehabdbecb442008-04-13 15:08:55 -0300600 /* Get the next buffer */
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300601 buf = list_entry(dma_q->active.next, struct em28xx_buffer, list);
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300602 /* Cleans up buffer - Useful for testing for frame/URB loss */
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300603 list_del(&buf->list);
Frank Schaefer87325332012-12-08 11:31:27 -0300604 buf->pos = 0;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300605 buf->vb_buf = buf->mem;
Mauro Carvalho Chehabcb784722008-04-13 15:06:52 -0300606
Frank Schaefer24a6d842012-12-08 11:31:24 -0300607 return buf;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300608}
609
Frank Schaefere04c00d2012-12-08 11:31:30 -0300610/*
611 * Finish the current buffer if completed and prepare for the next field
612 */
613static struct em28xx_buffer *
614finish_field_prepare_next(struct em28xx *dev,
615 struct em28xx_buffer *buf,
616 struct em28xx_dmaqueue *dma_q)
617{
Frank Schaefer58159172014-03-24 16:33:18 -0300618 struct em28xx_v4l2 *v4l2 = dev->v4l2;
619
Frank Schaeferf0e38232014-03-24 16:33:20 -0300620 if (v4l2->progressive || v4l2->top_field) { /* Brand new frame */
Frank Schaefere04c00d2012-12-08 11:31:30 -0300621 if (buf != NULL)
622 finish_buffer(dev, buf);
623 buf = get_next_buf(dev, dma_q);
624 }
625 if (buf != NULL) {
Frank Schaeferf0e38232014-03-24 16:33:20 -0300626 buf->top_field = v4l2->top_field;
Frank Schaefere04c00d2012-12-08 11:31:30 -0300627 buf->pos = 0;
628 }
629
630 return buf;
631}
632
Frank Schaefer227b7c92012-12-08 11:31:31 -0300633/*
634 * Process data packet according to the em2710/em2750/em28xx frame data format
635 */
636static inline void process_frame_data_em28xx(struct em28xx *dev,
637 unsigned char *data_pkt,
638 unsigned int data_len)
639{
Frank Schaefer753aee72014-03-24 16:33:14 -0300640 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300641 struct em28xx_buffer *buf = dev->usb_ctl.vid_buf;
642 struct em28xx_buffer *vbi_buf = dev->usb_ctl.vbi_buf;
643 struct em28xx_dmaqueue *dma_q = &dev->vidq;
644 struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq;
645
646 /* capture type 0 = vbi start
647 capture type 1 = vbi in progress
648 capture type 2 = video start
649 capture type 3 = video in progress */
650 if (data_len >= 4) {
651 /* NOTE: Headers are always 4 bytes and
652 * never split across packets */
653 if (data_pkt[0] == 0x88 && data_pkt[1] == 0x88 &&
654 data_pkt[2] == 0x88 && data_pkt[3] == 0x88) {
655 /* Continuation */
656 data_pkt += 4;
657 data_len -= 4;
658 } else if (data_pkt[0] == 0x33 && data_pkt[1] == 0x95) {
659 /* Field start (VBI mode) */
Frank Schaeferf0e38232014-03-24 16:33:20 -0300660 v4l2->capture_type = 0;
661 v4l2->vbi_read = 0;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300662 em28xx_isocdbg("VBI START HEADER !!!\n");
Frank Schaeferf0e38232014-03-24 16:33:20 -0300663 v4l2->top_field = !(data_pkt[2] & 1);
Frank Schaefer227b7c92012-12-08 11:31:31 -0300664 data_pkt += 4;
665 data_len -= 4;
666 } else if (data_pkt[0] == 0x22 && data_pkt[1] == 0x5a) {
667 /* Field start (VBI disabled) */
Frank Schaeferf0e38232014-03-24 16:33:20 -0300668 v4l2->capture_type = 2;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300669 em28xx_isocdbg("VIDEO START HEADER !!!\n");
Frank Schaeferf0e38232014-03-24 16:33:20 -0300670 v4l2->top_field = !(data_pkt[2] & 1);
Frank Schaefer227b7c92012-12-08 11:31:31 -0300671 data_pkt += 4;
672 data_len -= 4;
673 }
674 }
675 /* NOTE: With bulk transfers, intermediate data packets
676 * have no continuation header */
677
Frank Schaeferf0e38232014-03-24 16:33:20 -0300678 if (v4l2->capture_type == 0) {
Frank Schaefer227b7c92012-12-08 11:31:31 -0300679 vbi_buf = finish_field_prepare_next(dev, vbi_buf, vbi_dma_q);
680 dev->usb_ctl.vbi_buf = vbi_buf;
Frank Schaeferf0e38232014-03-24 16:33:20 -0300681 v4l2->capture_type = 1;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300682 }
683
Frank Schaeferf0e38232014-03-24 16:33:20 -0300684 if (v4l2->capture_type == 1) {
Frank Schaefer753aee72014-03-24 16:33:14 -0300685 int vbi_size = v4l2->vbi_width * v4l2->vbi_height;
Frank Schaeferf0e38232014-03-24 16:33:20 -0300686 int vbi_data_len = ((v4l2->vbi_read + data_len) > vbi_size) ?
687 (vbi_size - v4l2->vbi_read) : data_len;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300688
689 /* Copy VBI data */
690 if (vbi_buf != NULL)
691 em28xx_copy_vbi(dev, vbi_buf, data_pkt, vbi_data_len);
Frank Schaeferf0e38232014-03-24 16:33:20 -0300692 v4l2->vbi_read += vbi_data_len;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300693
694 if (vbi_data_len < data_len) {
695 /* Continue with copying video data */
Frank Schaeferf0e38232014-03-24 16:33:20 -0300696 v4l2->capture_type = 2;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300697 data_pkt += vbi_data_len;
698 data_len -= vbi_data_len;
699 }
700 }
701
Frank Schaeferf0e38232014-03-24 16:33:20 -0300702 if (v4l2->capture_type == 2) {
Frank Schaefer227b7c92012-12-08 11:31:31 -0300703 buf = finish_field_prepare_next(dev, buf, dma_q);
704 dev->usb_ctl.vid_buf = buf;
Frank Schaeferf0e38232014-03-24 16:33:20 -0300705 v4l2->capture_type = 3;
Frank Schaefer227b7c92012-12-08 11:31:31 -0300706 }
707
Frank Schaeferf0e38232014-03-24 16:33:20 -0300708 if (v4l2->capture_type == 3 && buf != NULL && data_len > 0)
Frank Schaefer227b7c92012-12-08 11:31:31 -0300709 em28xx_copy_video(dev, buf, data_pkt, data_len);
710}
711
Frank Schaefere507e0e2013-03-26 13:38:38 -0300712/*
713 * Process data packet according to the em25xx/em276x/7x/8x frame data format
714 */
715static inline void process_frame_data_em25xx(struct em28xx *dev,
716 unsigned char *data_pkt,
717 unsigned int data_len)
718{
719 struct em28xx_buffer *buf = dev->usb_ctl.vid_buf;
720 struct em28xx_dmaqueue *dmaq = &dev->vidq;
Frank Schaeferf0e38232014-03-24 16:33:20 -0300721 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab7e6c8c12014-09-03 15:06:13 -0300722 bool frame_end = false;
Frank Schaefere507e0e2013-03-26 13:38:38 -0300723
724 /* Check for header */
725 /* NOTE: at least with bulk transfers, only the first packet
726 * has a header and has always set the FRAME_END bit */
727 if (data_len >= 2) { /* em25xx header is only 2 bytes long */
728 if ((data_pkt[0] == EM25XX_FRMDATAHDR_BYTE1) &&
729 ((data_pkt[1] & ~EM25XX_FRMDATAHDR_BYTE2_MASK) == 0x00)) {
Frank Schaeferf0e38232014-03-24 16:33:20 -0300730 v4l2->top_field = !(data_pkt[1] &
Frank Schaefere507e0e2013-03-26 13:38:38 -0300731 EM25XX_FRMDATAHDR_BYTE2_FRAME_ID);
732 frame_end = data_pkt[1] &
733 EM25XX_FRMDATAHDR_BYTE2_FRAME_END;
734 data_pkt += 2;
735 data_len -= 2;
736 }
737
738 /* Finish field and prepare next (BULK only) */
739 if (dev->analog_xfer_bulk && frame_end) {
740 buf = finish_field_prepare_next(dev, buf, dmaq);
741 dev->usb_ctl.vid_buf = buf;
742 }
743 /* NOTE: in ISOC mode when a new frame starts and buf==NULL,
744 * we COULD already prepare a buffer here to avoid skipping the
745 * first frame.
746 */
747 }
748
749 /* Copy data */
750 if (buf != NULL && data_len > 0)
751 em28xx_copy_video(dev, buf, data_pkt, data_len);
752
753 /* Finish frame (ISOC only) => avoids lag of 1 frame */
754 if (!dev->analog_xfer_bulk && frame_end) {
755 buf = finish_field_prepare_next(dev, buf, dmaq);
756 dev->usb_ctl.vid_buf = buf;
757 }
758
759 /* NOTE: Tested with USB bulk transfers only !
760 * The wording in the datasheet suggests that isoc might work different.
761 * The current code assumes that with isoc transfers each packet has a
762 * header like with the other em28xx devices.
763 */
764 /* NOTE: Support for interlaced mode is pure theory. It has not been
765 * tested and it is unknown if these devices actually support it. */
766 /* NOTE: No VBI support yet (these chips likely do not support VBI). */
767}
768
Frank Schaefer960da932012-11-25 06:37:37 -0300769/* Processes and copies the URB data content (video and VBI data) */
Frank Schaefer0fa4a402012-11-08 14:11:45 -0300770static inline int em28xx_urb_data_copy(struct em28xx *dev, struct urb *urb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300771{
Frank Schaefer227b7c92012-12-08 11:31:31 -0300772 int xfer_bulk, num_packets, i;
773 unsigned char *usb_data_pkt;
774 unsigned int usb_data_len;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300775
776 if (!dev)
777 return 0;
778
Frank Schaefer2665c292012-12-27 19:02:43 -0300779 if (dev->disconnected)
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300780 return 0;
781
Frank Schaefer1653cb0c2012-11-08 14:11:44 -0300782 if (urb->status < 0)
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300783 print_err_status(dev, -1, urb->status);
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300784
Frank Schaefer4601cc32012-11-08 14:11:46 -0300785 xfer_bulk = usb_pipebulk(urb->pipe);
786
Frank Schaefer4601cc32012-11-08 14:11:46 -0300787 if (xfer_bulk) /* bulk */
788 num_packets = 1;
789 else /* isoc */
790 num_packets = urb->number_of_packets;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300791
Frank Schaefer4601cc32012-11-08 14:11:46 -0300792 for (i = 0; i < num_packets; i++) {
793 if (xfer_bulk) { /* bulk */
Frank Schaefer227b7c92012-12-08 11:31:31 -0300794 usb_data_len = urb->actual_length;
Frank Schaefer4601cc32012-11-08 14:11:46 -0300795
Frank Schaefer227b7c92012-12-08 11:31:31 -0300796 usb_data_pkt = urb->transfer_buffer;
Frank Schaefer4601cc32012-11-08 14:11:46 -0300797 } else { /* isoc */
798 if (urb->iso_frame_desc[i].status < 0) {
799 print_err_status(dev, i,
800 urb->iso_frame_desc[i].status);
801 if (urb->iso_frame_desc[i].status != -EPROTO)
802 continue;
803 }
804
Frank Schaefer227b7c92012-12-08 11:31:31 -0300805 usb_data_len = urb->iso_frame_desc[i].actual_length;
806 if (usb_data_len > dev->max_pkt_size) {
Frank Schaefer4601cc32012-11-08 14:11:46 -0300807 em28xx_isocdbg("packet bigger than packet size");
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300808 continue;
Frank Schaefer4601cc32012-11-08 14:11:46 -0300809 }
810
Frank Schaefer227b7c92012-12-08 11:31:31 -0300811 usb_data_pkt = urb->transfer_buffer +
812 urb->iso_frame_desc[i].offset;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300813 }
814
Frank Schaefer227b7c92012-12-08 11:31:31 -0300815 if (usb_data_len == 0) {
Frank Schaefer4601cc32012-11-08 14:11:46 -0300816 /* NOTE: happens very often with isoc transfers */
817 /* em28xx_usbdbg("packet %d is empty",i); - spammy */
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300818 continue;
819 }
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300820
Frank Schaefere507e0e2013-03-26 13:38:38 -0300821 if (dev->is_em25xx)
822 process_frame_data_em25xx(dev,
823 usb_data_pkt, usb_data_len);
824 else
825 process_frame_data_em28xx(dev,
826 usb_data_pkt, usb_data_len);
827
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300828 }
Frank Schaefer227b7c92012-12-08 11:31:31 -0300829 return 1;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300830}
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();
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300841 }
842}
843
844/* Usage lock check functions */
845static int res_get(struct em28xx *dev, enum v4l2_buf_type f_type)
846{
847 int res_type = get_ressource(f_type);
848
849 /* is it free? */
850 if (dev->resources & res_type) {
851 /* no, someone else uses it */
852 return -EBUSY;
853 }
854
855 /* it's free, grab it */
856 dev->resources |= res_type;
857 em28xx_videodbg("res: get %d\n", res_type);
858 return 0;
859}
860
861static void res_free(struct em28xx *dev, enum v4l2_buf_type f_type)
862{
863 int res_type = get_ressource(f_type);
864
865 dev->resources &= ~res_type;
866 em28xx_videodbg("res: put %d\n", res_type);
867}
868
Mauro Carvalho Chehab37ecc7b2016-01-27 07:07:24 -0200869static void em28xx_v4l2_media_release(struct em28xx *dev)
870{
871#ifdef CONFIG_MEDIA_CONTROLLER
872 int i;
873
874 for (i = 0; i < MAX_EM28XX_INPUT; i++) {
875 if (!INPUT(i)->type)
876 return;
877 media_device_unregister_entity(&dev->input_ent[i]);
878 }
879#endif
880}
881
882/*
883 * Media Controller helper functions
884 */
885
Mauro Carvalho Chehab37ecc7b2016-01-27 07:07:24 -0200886static int em28xx_enable_analog_tuner(struct em28xx *dev)
887{
888#ifdef CONFIG_MEDIA_CONTROLLER
889 struct media_device *mdev = dev->media_dev;
890 struct em28xx_v4l2 *v4l2 = dev->v4l2;
891 struct media_entity *source;
892 struct media_link *link, *found_link = NULL;
893 int ret, active_links = 0;
894
895 if (!mdev || !v4l2->decoder)
896 return 0;
897
898 /*
899 * This will find the tuner that is connected into the decoder.
900 * Technically, this is not 100% correct, as the device may be
901 * using an analog input instead of the tuner. However, as we can't
902 * do DVB streaming while the DMA engine is being used for V4L2,
903 * this should be enough for the actual needs.
904 */
905 list_for_each_entry(link, &v4l2->decoder->links, list) {
906 if (link->sink->entity == v4l2->decoder) {
907 found_link = link;
908 if (link->flags & MEDIA_LNK_FL_ENABLED)
909 active_links++;
910 break;
911 }
912 }
913
914 if (active_links == 1 || !found_link)
915 return 0;
916
917 source = found_link->source->entity;
918 list_for_each_entry(link, &source->links, list) {
919 struct media_entity *sink;
920 int flags = 0;
921
922 sink = link->sink->entity;
923
924 if (sink == v4l2->decoder)
925 flags = MEDIA_LNK_FL_ENABLED;
926
927 ret = media_entity_setup_link(link, flags);
928 if (ret) {
929 pr_err("Couldn't change link %s->%s to %s. Error %d\n",
930 source->name, sink->name,
931 flags ? "enabled" : "disabled",
932 ret);
933 return ret;
934 } else
935 em28xx_videodbg("link %s->%s was %s\n",
936 source->name, sink->name,
937 flags ? "ENABLED" : "disabled");
938 }
939#endif
940 return 0;
941}
942
943static const char * const iname[] = {
944 [EM28XX_VMUX_COMPOSITE] = "Composite",
945 [EM28XX_VMUX_SVIDEO] = "S-Video",
946 [EM28XX_VMUX_TELEVISION] = "Television",
947 [EM28XX_RADIO] = "Radio",
948};
949
950static void em28xx_v4l2_create_entities(struct em28xx *dev)
951{
952#if defined(CONFIG_MEDIA_CONTROLLER)
953 struct em28xx_v4l2 *v4l2 = dev->v4l2;
954 int ret, i;
955
956 /* Initialize Video, VBI and Radio pads */
957 v4l2->video_pad.flags = MEDIA_PAD_FL_SINK;
958 ret = media_entity_pads_init(&v4l2->vdev.entity, 1, &v4l2->video_pad);
959 if (ret < 0)
960 pr_err("failed to initialize video media entity!\n");
961
962 if (em28xx_vbi_supported(dev)) {
963 v4l2->vbi_pad.flags = MEDIA_PAD_FL_SINK;
964 ret = media_entity_pads_init(&v4l2->vbi_dev.entity, 1,
965 &v4l2->vbi_pad);
966 if (ret < 0)
967 pr_err("failed to initialize vbi media entity!\n");
968 }
969
970 /* Webcams don't have input connectors */
971 if (dev->board.is_webcam)
972 return;
973
974 /* Create entities for each input connector */
975 for (i = 0; i < MAX_EM28XX_INPUT; i++) {
976 struct media_entity *ent = &dev->input_ent[i];
977
978 if (!INPUT(i)->type)
979 break;
980
981 ent->name = iname[INPUT(i)->type];
982 ent->flags = MEDIA_ENT_FL_CONNECTOR;
983 dev->input_pad[i].flags = MEDIA_PAD_FL_SOURCE;
984
985 switch (INPUT(i)->type) {
986 case EM28XX_VMUX_COMPOSITE:
987 ent->function = MEDIA_ENT_F_CONN_COMPOSITE;
988 break;
989 case EM28XX_VMUX_SVIDEO:
990 ent->function = MEDIA_ENT_F_CONN_SVIDEO;
991 break;
992 default: /* EM28XX_VMUX_TELEVISION or EM28XX_RADIO */
Mauro Carvalho Chehabe9ef88b2016-02-11 17:17:30 -0200993 if (dev->tuner_type != TUNER_ABSENT)
994 ent->function = MEDIA_ENT_F_CONN_RF;
Mauro Carvalho Chehab37ecc7b2016-01-27 07:07:24 -0200995 break;
996 }
997
998 ret = media_entity_pads_init(ent, 1, &dev->input_pad[i]);
999 if (ret < 0)
1000 pr_err("failed to initialize input pad[%d]!\n", i);
1001
1002 ret = media_device_register_entity(dev->media_dev, ent);
1003 if (ret < 0)
1004 pr_err("failed to register input entity %d!\n", i);
1005 }
1006#endif
1007}
1008
1009
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001010/* ------------------------------------------------------------------
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001011 Videobuf2 operations
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001012 ------------------------------------------------------------------*/
1013
Hans Verkuildf9ecb02015-10-28 00:50:37 -02001014static int queue_setup(struct vb2_queue *vq,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001015 unsigned int *nbuffers, unsigned int *nplanes,
Hans Verkuil36c0f8b2016-04-15 09:15:05 -03001016 unsigned int sizes[], struct device *alloc_devs[])
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001017{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001018 struct em28xx *dev = vb2_get_drv_priv(vq);
Frank Schaefer753aee72014-03-24 16:33:14 -03001019 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Hans Verkuildf9ecb02015-10-28 00:50:37 -02001020 unsigned long size =
Frank Schaefer06e20672014-03-24 16:33:17 -03001021 (v4l2->width * v4l2->height * v4l2->format->depth + 7) >> 3;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001022
Hans Verkuildf9ecb02015-10-28 00:50:37 -02001023 if (*nplanes)
1024 return sizes[0] < size ? -EINVAL : 0;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001025 *nplanes = 1;
1026 sizes[0] = size;
Mauro Carvalho Chehab37ecc7b2016-01-27 07:07:24 -02001027
1028 em28xx_enable_analog_tuner(dev);
1029
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001030 return 0;
1031}
1032
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001033static int
1034buffer_prepare(struct vb2_buffer *vb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001035{
Junghak Sung2d700712015-09-22 10:30:30 -03001036 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001037 struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue);
Frank Schaefer753aee72014-03-24 16:33:14 -03001038 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001039 unsigned long size;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001040
Junghak Sung2d700712015-09-22 10:30:30 -03001041 em28xx_videodbg("%s, field=%d\n", __func__, vbuf->field);
Aidan Thornton3b5fa922008-04-13 15:09:36 -03001042
Frank Schaefer06e20672014-03-24 16:33:17 -03001043 size = (v4l2->width * v4l2->height * v4l2->format->depth + 7) >> 3;
Aidan Thornton3b5fa922008-04-13 15:09:36 -03001044
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001045 if (vb2_plane_size(vb, 0) < size) {
1046 em28xx_videodbg("%s data will not fit into plane (%lu < %lu)\n",
1047 __func__, vb2_plane_size(vb, 0), size);
1048 return -EINVAL;
1049 }
Junghak Sung2d700712015-09-22 10:30:30 -03001050 vb2_set_plane_payload(vb, 0, size);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001051
1052 return 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001053}
1054
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001055int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001056{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001057 struct em28xx *dev = vb2_get_drv_priv(vq);
Frank Schaeferf0e38232014-03-24 16:33:20 -03001058 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001059 struct v4l2_frequency f;
Junghak Sung2d700712015-09-22 10:30:30 -03001060 struct v4l2_fh *owner;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001061 int rc = 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001062
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001063 em28xx_videodbg("%s\n", __func__);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001064
Ben Hutchings52befa02019-01-17 00:22:48 +00001065 dev->v4l2->field_count = 0;
1066
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001067 /* Make sure streaming is not already in progress for this type
1068 of filehandle (e.g. video, vbi) */
1069 rc = res_get(dev, vq->type);
1070 if (rc)
1071 return rc;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001072
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001073 if (v4l2->streaming_users == 0) {
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001074 /* First active streaming user, so allocate all the URBs */
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001075
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001076 /* Allocate the USB bandwidth */
1077 em28xx_set_alternate(dev);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001078
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001079 /* Needed, since GPIO might have disabled power of
1080 some i2c device
1081 */
1082 em28xx_wake_i2c(dev);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001083
Frank Schaeferf0e38232014-03-24 16:33:20 -03001084 v4l2->capture_type = -1;
Frank Schaefer960da932012-11-25 06:37:37 -03001085 rc = em28xx_init_usb_xfer(dev, EM28XX_ANALOG_MODE,
1086 dev->analog_xfer_bulk,
1087 EM28XX_NUM_BUFS,
1088 dev->max_pkt_size,
1089 dev->packet_multiplier,
1090 em28xx_urb_data_copy);
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -03001091 if (rc < 0)
Frank Schaefer032f1dd2013-10-10 15:31:53 -03001092 return rc;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001093
1094 /*
1095 * djh: it's not clear whether this code is still needed. I'm
1096 * leaving it in here for now entirely out of concern for
1097 * backward compatibility (the old code did it)
1098 */
1099
1100 /* Ask tuner to go to analog or radio mode */
1101 memset(&f, 0, sizeof(f));
Frank Schaefer3854b0d2014-03-24 16:33:22 -03001102 f.frequency = v4l2->frequency;
Junghak Sung2d700712015-09-22 10:30:30 -03001103 owner = (struct v4l2_fh *)vq->owner;
1104 if (owner && owner->vdev->vfl_type == VFL_TYPE_RADIO)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001105 f.type = V4L2_TUNER_RADIO;
1106 else
1107 f.type = V4L2_TUNER_ANALOG_TV;
Frank Schaeferf0e38232014-03-24 16:33:20 -03001108 v4l2_device_call_all(&v4l2->v4l2_dev,
Frank Schaefer95d26082014-03-24 16:33:09 -03001109 0, tuner, s_frequency, &f);
Mauro Carvalho Chehab13d52fe2016-01-26 06:59:39 -02001110
1111 /* Enable video stream at TV decoder */
1112 v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_stream, 1);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001113 }
1114
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001115 v4l2->streaming_users++;
Frank Schaefer032f1dd2013-10-10 15:31:53 -03001116
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001117 return rc;
1118}
1119
Hans Verkuile37559b2014-04-17 02:47:21 -03001120static void em28xx_stop_streaming(struct vb2_queue *vq)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001121{
1122 struct em28xx *dev = vb2_get_drv_priv(vq);
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001123 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001124 struct em28xx_dmaqueue *vidq = &dev->vidq;
1125 unsigned long flags = 0;
1126
1127 em28xx_videodbg("%s\n", __func__);
1128
1129 res_free(dev, vq->type);
1130
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001131 if (v4l2->streaming_users-- == 1) {
Mauro Carvalho Chehab13d52fe2016-01-26 06:59:39 -02001132 /* Disable video stream at TV decoder */
1133 v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_stream, 0);
1134
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001135 /* Last active user, so shutdown all the URBS */
1136 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
1137 }
1138
1139 spin_lock_irqsave(&dev->slock, flags);
Frank Schaefer627530c2014-08-09 06:37:20 -03001140 if (dev->usb_ctl.vid_buf != NULL) {
Junghak Sung2d700712015-09-22 10:30:30 -03001141 vb2_buffer_done(&dev->usb_ctl.vid_buf->vb.vb2_buf,
1142 VB2_BUF_STATE_ERROR);
Frank Schaefer627530c2014-08-09 06:37:20 -03001143 dev->usb_ctl.vid_buf = NULL;
1144 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001145 while (!list_empty(&vidq->active)) {
1146 struct em28xx_buffer *buf;
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001147
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001148 buf = list_entry(vidq->active.next, struct em28xx_buffer, list);
1149 list_del(&buf->list);
Junghak Sung2d700712015-09-22 10:30:30 -03001150 vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001151 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001152 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001153}
1154
Hans Verkuile37559b2014-04-17 02:47:21 -03001155void em28xx_stop_vbi_streaming(struct vb2_queue *vq)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001156{
1157 struct em28xx *dev = vb2_get_drv_priv(vq);
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001158 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001159 struct em28xx_dmaqueue *vbiq = &dev->vbiq;
1160 unsigned long flags = 0;
1161
1162 em28xx_videodbg("%s\n", __func__);
1163
1164 res_free(dev, vq->type);
1165
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001166 if (v4l2->streaming_users-- == 1) {
Mauro Carvalho Chehab13d52fe2016-01-26 06:59:39 -02001167 /* Disable video stream at TV decoder */
1168 v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_stream, 0);
1169
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001170 /* Last active user, so shutdown all the URBS */
1171 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
1172 }
1173
1174 spin_lock_irqsave(&dev->slock, flags);
Frank Schaefer627530c2014-08-09 06:37:20 -03001175 if (dev->usb_ctl.vbi_buf != NULL) {
Junghak Sung2d700712015-09-22 10:30:30 -03001176 vb2_buffer_done(&dev->usb_ctl.vbi_buf->vb.vb2_buf,
1177 VB2_BUF_STATE_ERROR);
Frank Schaefer627530c2014-08-09 06:37:20 -03001178 dev->usb_ctl.vbi_buf = NULL;
1179 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001180 while (!list_empty(&vbiq->active)) {
1181 struct em28xx_buffer *buf;
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001182
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001183 buf = list_entry(vbiq->active.next, struct em28xx_buffer, list);
1184 list_del(&buf->list);
Junghak Sung2d700712015-09-22 10:30:30 -03001185 vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001186 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001187 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001188}
1189
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001190static void
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001191buffer_queue(struct vb2_buffer *vb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001192{
Junghak Sung2d700712015-09-22 10:30:30 -03001193 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001194 struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue);
Junghak Sung2d700712015-09-22 10:30:30 -03001195 struct em28xx_buffer *buf =
1196 container_of(vbuf, struct em28xx_buffer, vb);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001197 struct em28xx_dmaqueue *vidq = &dev->vidq;
1198 unsigned long flags = 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001199
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001200 em28xx_videodbg("%s\n", __func__);
1201 buf->mem = vb2_plane_vaddr(vb, 0);
1202 buf->length = vb2_plane_size(vb, 0);
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001203
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001204 spin_lock_irqsave(&dev->slock, flags);
1205 list_add_tail(&buf->list, &vidq->active);
1206 spin_unlock_irqrestore(&dev->slock, flags);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001207}
1208
Julia Lawall1bc17712016-09-08 20:59:01 -03001209static const struct vb2_ops em28xx_video_qops = {
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001210 .queue_setup = queue_setup,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001211 .buf_prepare = buffer_prepare,
1212 .buf_queue = buffer_queue,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001213 .start_streaming = em28xx_start_analog_streaming,
1214 .stop_streaming = em28xx_stop_streaming,
1215 .wait_prepare = vb2_ops_wait_prepare,
1216 .wait_finish = vb2_ops_wait_finish,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001217};
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001218
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001219static int em28xx_vb2_setup(struct em28xx *dev)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001220{
1221 int rc;
1222 struct vb2_queue *q;
Frank Schaefer27a36df2014-03-24 16:33:13 -03001223 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001224
1225 /* Setup Videobuf2 for Video capture */
Frank Schaefer27a36df2014-03-24 16:33:13 -03001226 q = &v4l2->vb_vidq;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001227 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Mauro Carvalho Chehabef85cd92013-01-06 00:34:22 -02001228 q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
Sakari Ailusade48682014-02-25 19:12:19 -03001229 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001230 q->drv_priv = dev;
1231 q->buf_struct_size = sizeof(struct em28xx_buffer);
1232 q->ops = &em28xx_video_qops;
1233 q->mem_ops = &vb2_vmalloc_memops;
1234
1235 rc = vb2_queue_init(q);
1236 if (rc < 0)
1237 return rc;
1238
1239 /* Setup Videobuf2 for VBI capture */
Frank Schaefer27a36df2014-03-24 16:33:13 -03001240 q = &v4l2->vb_vbiq;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001241 q->type = V4L2_BUF_TYPE_VBI_CAPTURE;
1242 q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR;
Sakari Ailusade48682014-02-25 19:12:19 -03001243 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001244 q->drv_priv = dev;
1245 q->buf_struct_size = sizeof(struct em28xx_buffer);
1246 q->ops = &em28xx_vbi_qops;
1247 q->mem_ops = &vb2_vmalloc_memops;
1248
1249 rc = vb2_queue_init(q);
1250 if (rc < 0)
1251 return rc;
1252
1253 return 0;
1254}
1255
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001256/********************* v4l2 interface **************************************/
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001257
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001258static void video_mux(struct em28xx *dev, int index)
1259{
Frank Schaefer95d26082014-03-24 16:33:09 -03001260 struct v4l2_device *v4l2_dev = &dev->v4l2->v4l2_dev;
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001261
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001262 dev->ctl_input = index;
1263 dev->ctl_ainput = INPUT(index)->amux;
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001264 dev->ctl_aoutput = INPUT(index)->aout;
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001265
Mauro Carvalho Chehabe879b8e2008-11-20 13:39:39 -03001266 if (!dev->ctl_aoutput)
1267 dev->ctl_aoutput = EM28XX_AOUT_MASTER;
1268
Frank Schaefer95d26082014-03-24 16:33:09 -03001269 v4l2_device_call_all(v4l2_dev, 0, video, s_routing,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001270 INPUT(index)->vmux, 0, 0);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001271
Mauro Carvalho Chehab505b6d02008-11-25 09:39:50 -03001272 if (dev->board.has_msp34xx) {
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001273 if (dev->i2s_speed) {
Frank Schaefer95d26082014-03-24 16:33:09 -03001274 v4l2_device_call_all(v4l2_dev, 0, audio,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001275 s_i2s_clock_freq, dev->i2s_speed);
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001276 }
Hans Verkuil2474ed42006-03-19 12:35:57 -03001277 /* Note: this is msp3400 specific */
Frank Schaefer95d26082014-03-24 16:33:09 -03001278 v4l2_device_call_all(v4l2_dev, 0, audio, s_routing,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001279 dev->ctl_ainput,
1280 MSP_OUTPUT(MSP_SC_IN_DSP_SCART1), 0);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001281 }
Mauro Carvalho Chehab539c96d2008-01-05 09:53:54 -03001282
Vitaly Wool2bd1d9e2009-03-04 08:27:52 -03001283 if (dev->board.adecoder != EM28XX_NOADECODER) {
Frank Schaefer95d26082014-03-24 16:33:09 -03001284 v4l2_device_call_all(v4l2_dev, 0, audio, s_routing,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001285 dev->ctl_ainput, dev->ctl_aoutput, 0);
Vitaly Wool2bd1d9e2009-03-04 08:27:52 -03001286 }
1287
Mauro Carvalho Chehab00b87302008-02-06 18:34:13 -03001288 em28xx_audio_analog_set(dev);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001289}
1290
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001291static void em28xx_ctrl_notify(struct v4l2_ctrl *ctrl, void *priv)
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001292{
Hans Verkuil081b9452012-09-07 05:43:59 -03001293 struct em28xx *dev = priv;
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001294
Hans Verkuil081b9452012-09-07 05:43:59 -03001295 /*
1296 * In the case of non-AC97 volume controls, we still need
1297 * to do some setups at em28xx, in order to mute/unmute
1298 * and to adjust audio volume. However, the value ranges
1299 * should be checked by the corresponding V4L subdriver.
1300 */
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001301 switch (ctrl->id) {
1302 case V4L2_CID_AUDIO_MUTE:
Hans Verkuil081b9452012-09-07 05:43:59 -03001303 dev->mute = ctrl->val;
1304 em28xx_audio_analog_set(dev);
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001305 break;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001306 case V4L2_CID_AUDIO_VOLUME:
Hans Verkuil081b9452012-09-07 05:43:59 -03001307 dev->volume = ctrl->val;
1308 em28xx_audio_analog_set(dev);
1309 break;
1310 }
1311}
1312
1313static int em28xx_s_ctrl(struct v4l2_ctrl *ctrl)
1314{
Frank Schaeferabc13082014-03-24 16:33:10 -03001315 struct em28xx_v4l2 *v4l2 =
1316 container_of(ctrl->handler, struct em28xx_v4l2, ctrl_handler);
1317 struct em28xx *dev = v4l2->dev;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001318 int ret = -EINVAL;
Hans Verkuil081b9452012-09-07 05:43:59 -03001319
1320 switch (ctrl->id) {
1321 case V4L2_CID_AUDIO_MUTE:
1322 dev->mute = ctrl->val;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001323 ret = em28xx_audio_analog_set(dev);
Hans Verkuil081b9452012-09-07 05:43:59 -03001324 break;
1325 case V4L2_CID_AUDIO_VOLUME:
1326 dev->volume = ctrl->val;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001327 ret = em28xx_audio_analog_set(dev);
1328 break;
1329 case V4L2_CID_CONTRAST:
1330 ret = em28xx_write_reg(dev, EM28XX_R20_YGAIN, ctrl->val);
1331 break;
1332 case V4L2_CID_BRIGHTNESS:
1333 ret = em28xx_write_reg(dev, EM28XX_R21_YOFFSET, ctrl->val);
1334 break;
1335 case V4L2_CID_SATURATION:
1336 ret = em28xx_write_reg(dev, EM28XX_R22_UVGAIN, ctrl->val);
1337 break;
1338 case V4L2_CID_BLUE_BALANCE:
1339 ret = em28xx_write_reg(dev, EM28XX_R23_UOFFSET, ctrl->val);
1340 break;
1341 case V4L2_CID_RED_BALANCE:
1342 ret = em28xx_write_reg(dev, EM28XX_R24_VOFFSET, ctrl->val);
1343 break;
1344 case V4L2_CID_SHARPNESS:
1345 ret = em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, ctrl->val);
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001346 break;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001347 }
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001348
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001349 return (ret < 0) ? ret : 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001350}
1351
Fengguang Wu8068eb82014-01-07 12:50:47 -03001352static const struct v4l2_ctrl_ops em28xx_ctrl_ops = {
Hans Verkuil081b9452012-09-07 05:43:59 -03001353 .s_ctrl = em28xx_s_ctrl,
1354};
1355
Frank Schaefer6b09a212013-02-10 16:05:12 -03001356static void size_to_scale(struct em28xx *dev,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001357 unsigned int width, unsigned int height,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001358 unsigned int *hscale, unsigned int *vscale)
1359{
Mauro Carvalho Chehab55699962009-07-13 20:15:02 -03001360 unsigned int maxw = norm_maxw(dev);
1361 unsigned int maxh = norm_maxh(dev);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001362
1363 *hscale = (((unsigned long)maxw) << 12) / width - 4096L;
Frank Schaefer81685322013-02-10 16:05:11 -03001364 if (*hscale > EM28XX_HVSCALE_MAX)
1365 *hscale = EM28XX_HVSCALE_MAX;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001366
1367 *vscale = (((unsigned long)maxh) << 12) / height - 4096L;
Frank Schaefer81685322013-02-10 16:05:11 -03001368 if (*vscale > EM28XX_HVSCALE_MAX)
1369 *vscale = EM28XX_HVSCALE_MAX;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001370}
1371
Frank Schaeferb8374132013-02-10 16:05:13 -03001372static void scale_to_size(struct em28xx *dev,
1373 unsigned int hscale, unsigned int vscale,
1374 unsigned int *width, unsigned int *height)
1375{
1376 unsigned int maxw = norm_maxw(dev);
1377 unsigned int maxh = norm_maxh(dev);
1378
1379 *width = (((unsigned long)maxw) << 12) / (hscale + 4096L);
1380 *height = (((unsigned long)maxh) << 12) / (vscale + 4096L);
Mauro Carvalho Chehab0962a762016-01-29 14:05:11 -02001381
1382 /* Don't let width or height to be zero */
1383 if (*width < 1)
1384 *width = 1;
1385 if (*height < 1)
1386 *height = 1;
Frank Schaeferb8374132013-02-10 16:05:13 -03001387}
1388
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001389/* ------------------------------------------------------------------
1390 IOCTL vidioc handling
1391 ------------------------------------------------------------------*/
1392
Hans Verkuil78b526a2008-05-28 12:16:41 -03001393static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001394 struct v4l2_format *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001395{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001396 struct em28xx *dev = video_drvdata(file);
Frank Schaefer753aee72014-03-24 16:33:14 -03001397 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001398
Frank Schaefer753aee72014-03-24 16:33:14 -03001399 f->fmt.pix.width = v4l2->width;
1400 f->fmt.pix.height = v4l2->height;
Frank Schaefer06e20672014-03-24 16:33:17 -03001401 f->fmt.pix.pixelformat = v4l2->format->fourcc;
1402 f->fmt.pix.bytesperline = (v4l2->width * v4l2->format->depth + 7) >> 3;
Frank Schaefer753aee72014-03-24 16:33:14 -03001403 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * v4l2->height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001404 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
1405
1406 /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */
Frank Schaefer58159172014-03-24 16:33:18 -03001407 if (v4l2->progressive)
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -03001408 f->fmt.pix.field = V4L2_FIELD_NONE;
1409 else
Frank Schaefer58159172014-03-24 16:33:18 -03001410 f->fmt.pix.field = v4l2->interlaced_fieldmode ?
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001411 V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001412 return 0;
1413}
1414
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001415static struct em28xx_fmt *format_by_fourcc(unsigned int fourcc)
1416{
1417 unsigned int i;
1418
1419 for (i = 0; i < ARRAY_SIZE(format); i++)
1420 if (format[i].fourcc == fourcc)
1421 return &format[i];
1422
1423 return NULL;
1424}
1425
Hans Verkuil78b526a2008-05-28 12:16:41 -03001426static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001427 struct v4l2_format *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001428{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001429 struct em28xx *dev = video_drvdata(file);
Frank Schaefer58159172014-03-24 16:33:18 -03001430 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Trent Piephoccb83402009-05-30 21:45:46 -03001431 unsigned int width = f->fmt.pix.width;
1432 unsigned int height = f->fmt.pix.height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001433 unsigned int maxw = norm_maxw(dev);
1434 unsigned int maxh = norm_maxh(dev);
1435 unsigned int hscale, vscale;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001436 struct em28xx_fmt *fmt;
1437
1438 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
1439 if (!fmt) {
Mauro Carvalho Chehab8e7c0fc2018-09-13 23:22:40 -04001440 fmt = &format[0];
1441 em28xx_videodbg("Fourcc format (%08x) invalid. Using default (%08x).\n",
1442 f->fmt.pix.pixelformat, fmt->fourcc);
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001443 }
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001444
Mauro Carvalho Chehab55699962009-07-13 20:15:02 -03001445 if (dev->board.is_em2800) {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001446 /* the em2800 can only scale down to 50% */
Trent Piephoccb83402009-05-30 21:45:46 -03001447 height = height > (3 * maxh / 4) ? maxh : maxh / 2;
1448 width = width > (3 * maxw / 4) ? maxw : maxw / 2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001449 /*
1450 * MaxPacketSize for em2800 is too small to capture at full
1451 * resolution use half of maxw as the scaler can only scale
1452 * to 50%
1453 */
Sascha Sommer1020d132012-01-08 16:54:28 -03001454 if (width == maxw && height == maxh)
1455 width /= 2;
Trent Piephoccb83402009-05-30 21:45:46 -03001456 } else {
1457 /* width must even because of the YUYV format
1458 height must be even because of interlacing */
Devin Heitmuellere3ba4d32009-09-15 00:18:06 -03001459 v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh,
1460 1, 0);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001461 }
Mauro Carvalho Chehab0962a762016-01-29 14:05:11 -02001462 /* Avoid division by zero at size_to_scale */
1463 if (width < 1)
1464 width = 1;
1465 if (height < 1)
1466 height = 1;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001467
Frank Schaefer6b09a212013-02-10 16:05:12 -03001468 size_to_scale(dev, width, height, &hscale, &vscale);
Hans Verkuil46f85972013-03-30 05:31:42 -03001469 scale_to_size(dev, hscale, vscale, &width, &height);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001470
1471 f->fmt.pix.width = width;
1472 f->fmt.pix.height = height;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001473 f->fmt.pix.pixelformat = fmt->fourcc;
Hans Verkuile6066db2013-02-06 08:14:47 -03001474 f->fmt.pix.bytesperline = (width * fmt->depth + 7) >> 3;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001475 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001476 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
Frank Schaefer58159172014-03-24 16:33:18 -03001477 if (v4l2->progressive)
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -03001478 f->fmt.pix.field = V4L2_FIELD_NONE;
1479 else
Frank Schaefer58159172014-03-24 16:33:18 -03001480 f->fmt.pix.field = v4l2->interlaced_fieldmode ?
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -03001481 V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
Alban Browaeys51dd4d72013-07-16 19:06:46 -03001482 f->fmt.pix.priv = 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001483
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001484 return 0;
1485}
1486
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001487static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc,
1488 unsigned width, unsigned height)
1489{
1490 struct em28xx_fmt *fmt;
Frank Schaefer753aee72014-03-24 16:33:14 -03001491 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001492
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001493 fmt = format_by_fourcc(fourcc);
1494 if (!fmt)
1495 return -EINVAL;
1496
Frank Schaefer06e20672014-03-24 16:33:17 -03001497 v4l2->format = fmt;
Frank Schaefer753aee72014-03-24 16:33:14 -03001498 v4l2->width = width;
1499 v4l2->height = height;
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001500
1501 /* set new image size */
Frank Schaefer753aee72014-03-24 16:33:14 -03001502 size_to_scale(dev, v4l2->width, v4l2->height,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001503 &v4l2->hscale, &v4l2->vscale);
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001504
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001505 em28xx_resolution_set(dev);
1506
1507 return 0;
1508}
1509
Hans Verkuil78b526a2008-05-28 12:16:41 -03001510static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001511 struct v4l2_format *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001512{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001513 struct em28xx *dev = video_drvdata(file);
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001514 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001515
Mauro Carvalho Chehabc7854c22014-09-19 13:02:12 -03001516 if (vb2_is_busy(&v4l2->vb_vidq))
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001517 return -EBUSY;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001518
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001519 vidioc_try_fmt_vid_cap(file, priv, f);
1520
Hans Verkuil0499a5a2010-09-26 07:34:45 -03001521 return em28xx_set_video_format(dev, f->fmt.pix.pixelformat,
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001522 f->fmt.pix.width, f->fmt.pix.height);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001523}
1524
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001525static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
1526{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001527 struct em28xx *dev = video_drvdata(file);
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001528
Frank Schaefer52faaf72014-03-24 16:33:16 -03001529 *norm = dev->v4l2->norm;
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001530
1531 return 0;
1532}
1533
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001534static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm)
1535{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001536 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001537
Frank Schaefer95d26082014-03-24 16:33:09 -03001538 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, video, querystd, norm);
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001539
1540 return 0;
1541}
1542
Hans Verkuil314527a2013-03-15 06:10:40 -03001543static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001544{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001545 struct em28xx *dev = video_drvdata(file);
Frank Schaefer753aee72014-03-24 16:33:14 -03001546 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001547 struct v4l2_format f;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001548
Frank Schaefer52faaf72014-03-24 16:33:16 -03001549 if (norm == v4l2->norm)
Hans Verkuild8c95c02012-09-07 07:31:54 -03001550 return 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001551
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001552 if (v4l2->streaming_users > 0)
Hans Verkuild8c95c02012-09-07 07:31:54 -03001553 return -EBUSY;
Hans Verkuild8c95c02012-09-07 07:31:54 -03001554
Frank Schaefer52faaf72014-03-24 16:33:16 -03001555 v4l2->norm = norm;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001556
1557 /* Adjusts width/height, if needed */
Hans Verkuild8c95c02012-09-07 07:31:54 -03001558 f.fmt.pix.width = 720;
Hans Verkuil314527a2013-03-15 06:10:40 -03001559 f.fmt.pix.height = (norm & V4L2_STD_525_60) ? 480 : 576;
Hans Verkuil78b526a2008-05-28 12:16:41 -03001560 vidioc_try_fmt_vid_cap(file, priv, &f);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001561
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001562 /* set new image size */
Frank Schaefer753aee72014-03-24 16:33:14 -03001563 v4l2->width = f.fmt.pix.width;
1564 v4l2->height = f.fmt.pix.height;
1565 size_to_scale(dev, v4l2->width, v4l2->height,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001566 &v4l2->hscale, &v4l2->vscale);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001567
1568 em28xx_resolution_set(dev);
Laurent Pinchart8774bed2014-04-28 16:53:01 -03001569 v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_std, v4l2->norm);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001570
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001571 return 0;
1572}
1573
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001574static int vidioc_g_parm(struct file *file, void *priv,
1575 struct v4l2_streamparm *p)
1576{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001577 struct em28xx *dev = video_drvdata(file);
Frank Schaefer52faaf72014-03-24 16:33:16 -03001578 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001579 int rc = 0;
1580
Hans Verkuil86ff7f12012-09-07 06:16:03 -03001581 p->parm.capture.readbuffers = EM28XX_MIN_BUF;
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001582 if (dev->board.is_webcam)
Frank Schaefer52faaf72014-03-24 16:33:16 -03001583 rc = v4l2_device_call_until_err(&v4l2->v4l2_dev, 0,
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001584 video, g_parm, p);
1585 else
Frank Schaefer52faaf72014-03-24 16:33:16 -03001586 v4l2_video_std_frame_period(v4l2->norm,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001587 &p->parm.capture.timeperframe);
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001588
1589 return rc;
1590}
1591
1592static int vidioc_s_parm(struct file *file, void *priv,
1593 struct v4l2_streamparm *p)
1594{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001595 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001596
Hans Verkuil86ff7f12012-09-07 06:16:03 -03001597 p->parm.capture.readbuffers = EM28XX_MIN_BUF;
Frank Schaefer95d26082014-03-24 16:33:09 -03001598 return v4l2_device_call_until_err(&dev->v4l2->v4l2_dev,
1599 0, video, s_parm, p);
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001600}
1601
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001602static int vidioc_enum_input(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001603 struct v4l2_input *i)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001604{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001605 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001606 unsigned int n;
1607
1608 n = i->index;
1609 if (n >= MAX_EM28XX_INPUT)
1610 return -EINVAL;
1611 if (0 == INPUT(n)->type)
1612 return -EINVAL;
1613
1614 i->index = n;
1615 i->type = V4L2_INPUT_TYPE_CAMERA;
1616
1617 strcpy(i->name, iname[INPUT(n)->type]);
1618
Mauro Carvalho Chehabd83a96a2016-01-27 09:24:29 -02001619 if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type))
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001620 i->type = V4L2_INPUT_TYPE_TUNER;
1621
Hans Verkuild4352f32015-03-09 13:34:06 -03001622 i->std = dev->v4l2->vdev.tvnorms;
Hans Verkuild8c95c02012-09-07 07:31:54 -03001623 /* webcams do not have the STD API */
1624 if (dev->board.is_webcam)
1625 i->capabilities = 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001626
1627 return 0;
1628}
1629
1630static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1631{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001632 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001633
1634 *i = dev->ctl_input;
1635
1636 return 0;
1637}
1638
1639static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
1640{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001641 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001642
1643 if (i >= MAX_EM28XX_INPUT)
1644 return -EINVAL;
1645 if (0 == INPUT(i)->type)
1646 return -EINVAL;
1647
Ezequiel García96371fc2012-03-23 18:09:34 -03001648 video_mux(dev, i);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001649 return 0;
1650}
1651
1652static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
1653{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001654 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001655
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001656 switch (a->index) {
1657 case EM28XX_AMUX_VIDEO:
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001658 strcpy(a->name, "Television");
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001659 break;
1660 case EM28XX_AMUX_LINE_IN:
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001661 strcpy(a->name, "Line In");
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001662 break;
1663 case EM28XX_AMUX_VIDEO2:
1664 strcpy(a->name, "Television alt");
1665 break;
1666 case EM28XX_AMUX_PHONE:
1667 strcpy(a->name, "Phone");
1668 break;
1669 case EM28XX_AMUX_MIC:
1670 strcpy(a->name, "Mic");
1671 break;
1672 case EM28XX_AMUX_CD:
1673 strcpy(a->name, "CD");
1674 break;
1675 case EM28XX_AMUX_AUX:
1676 strcpy(a->name, "Aux");
1677 break;
1678 case EM28XX_AMUX_PCM_OUT:
1679 strcpy(a->name, "PCM");
1680 break;
1681 default:
1682 return -EINVAL;
1683 }
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001684
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001685 a->index = dev->ctl_ainput;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001686 a->capability = V4L2_AUDCAP_STEREO;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001687
1688 return 0;
1689}
1690
Hans Verkuil0e8025b92012-09-04 11:59:31 -03001691static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001692{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001693 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001694
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03001695 if (a->index >= MAX_EM28XX_INPUT)
1696 return -EINVAL;
1697 if (0 == INPUT(a->index)->type)
1698 return -EINVAL;
1699
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001700 dev->ctl_ainput = INPUT(a->index)->amux;
1701 dev->ctl_aoutput = INPUT(a->index)->aout;
Mauro Carvalho Chehabe879b8e2008-11-20 13:39:39 -03001702
1703 if (!dev->ctl_aoutput)
1704 dev->ctl_aoutput = EM28XX_AOUT_MASTER;
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001705
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001706 return 0;
1707}
1708
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001709static int vidioc_g_tuner(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001710 struct v4l2_tuner *t)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001711{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001712 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001713
1714 if (0 != t->index)
1715 return -EINVAL;
1716
1717 strcpy(t->name, "Tuner");
1718
Frank Schaefer95d26082014-03-24 16:33:09 -03001719 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, g_tuner, t);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001720 return 0;
1721}
1722
1723static int vidioc_s_tuner(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001724 const struct v4l2_tuner *t)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001725{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001726 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001727
1728 if (0 != t->index)
1729 return -EINVAL;
1730
Frank Schaefer95d26082014-03-24 16:33:09 -03001731 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, s_tuner, t);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001732 return 0;
1733}
1734
1735static int vidioc_g_frequency(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001736 struct v4l2_frequency *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001737{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001738 struct em28xx *dev = video_drvdata(file);
Frank Schaefer3854b0d2014-03-24 16:33:22 -03001739 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001740
Hans Verkuil20deebf2012-09-06 10:07:25 -03001741 if (0 != f->tuner)
1742 return -EINVAL;
1743
Frank Schaefer3854b0d2014-03-24 16:33:22 -03001744 f->frequency = v4l2->frequency;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001745 return 0;
1746}
1747
1748static int vidioc_s_frequency(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001749 const struct v4l2_frequency *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001750{
Frank Schaefer95d26082014-03-24 16:33:09 -03001751 struct v4l2_frequency new_freq = *f;
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001752 struct em28xx *dev = video_drvdata(file);
Frank Schaefer95d26082014-03-24 16:33:09 -03001753 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001754
1755 if (0 != f->tuner)
1756 return -EINVAL;
1757
Frank Schaefer95d26082014-03-24 16:33:09 -03001758 v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, s_frequency, f);
1759 v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, g_frequency, &new_freq);
Frank Schaefer3854b0d2014-03-24 16:33:22 -03001760 v4l2->frequency = new_freq.frequency;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001761
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001762 return 0;
1763}
1764
Hans Verkuilcd634f12013-03-27 08:04:23 -03001765#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuil96b03d22013-04-06 06:16:58 -03001766static int vidioc_g_chip_info(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001767 struct v4l2_dbg_chip_info *chip)
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001768{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001769 struct em28xx *dev = video_drvdata(file);
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001770
1771 if (chip->match.addr > 1)
1772 return -EINVAL;
1773 if (chip->match.addr == 1)
1774 strlcpy(chip->name, "ac97", sizeof(chip->name));
1775 else
Frank Schaefer95d26082014-03-24 16:33:09 -03001776 strlcpy(chip->name,
1777 dev->v4l2->v4l2_dev.name, sizeof(chip->name));
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001778 return 0;
1779}
1780
Frank Schaefer35deba32013-02-07 13:39:19 -03001781static int em28xx_reg_len(int reg)
1782{
1783 switch (reg) {
1784 case EM28XX_R40_AC97LSB:
1785 case EM28XX_R30_HSCALELOW:
1786 case EM28XX_R32_VSCALELOW:
1787 return 2;
1788 default:
1789 return 1;
1790 }
1791}
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001792
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001793static int vidioc_g_register(struct file *file, void *priv,
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001794 struct v4l2_dbg_register *reg)
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001795{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001796 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001797 int ret;
1798
Hans Verkuilabca2052013-05-29 06:59:35 -03001799 if (reg->match.addr > 1)
1800 return -EINVAL;
1801 if (reg->match.addr) {
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001802 ret = em28xx_read_ac97(dev, reg->reg);
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001803 if (ret < 0)
1804 return ret;
1805
1806 reg->val = ret;
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001807 reg->size = 1;
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001808 return 0;
1809 }
1810
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001811 /* Match host */
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001812 reg->size = em28xx_reg_len(reg->reg);
1813 if (reg->size == 1) {
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001814 ret = em28xx_read_reg(dev, reg->reg);
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001815
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001816 if (ret < 0)
1817 return ret;
1818
1819 reg->val = ret;
1820 } else {
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001821 __le16 val = 0;
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001822
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001823 ret = dev->em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001824 reg->reg, (char *)&val, 2);
1825 if (ret < 0)
1826 return ret;
1827
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001828 reg->val = le16_to_cpu(val);
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001829 }
1830
1831 return 0;
1832}
1833
1834static int vidioc_s_register(struct file *file, void *priv,
Hans Verkuil977ba3b2013-03-24 08:28:46 -03001835 const struct v4l2_dbg_register *reg)
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001836{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001837 struct em28xx *dev = video_drvdata(file);
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001838 __le16 buf;
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001839
Hans Verkuilabca2052013-05-29 06:59:35 -03001840 if (reg->match.addr > 1)
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001841 return -EINVAL;
Hans Verkuilabca2052013-05-29 06:59:35 -03001842 if (reg->match.addr)
1843 return em28xx_write_ac97(dev, reg->reg, reg->val);
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001844
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001845 /* Match host */
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001846 buf = cpu_to_le16(reg->val);
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001847
Hans Verkuil0499a5a2010-09-26 07:34:45 -03001848 return em28xx_write_regs(dev, reg->reg, (char *)&buf,
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001849 em28xx_reg_len(reg->reg));
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001850}
1851#endif
1852
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001853static int vidioc_querycap(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001854 struct v4l2_capability *cap)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001855{
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001856 struct video_device *vdev = video_devdata(file);
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001857 struct em28xx *dev = video_drvdata(file);
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001858 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001859
1860 strlcpy(cap->driver, "em28xx", sizeof(cap->driver));
1861 strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card));
Thierry MERLEcb977162009-01-20 18:01:33 -03001862 usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001863
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001864 if (vdev->vfl_type == VFL_TYPE_GRABBER)
1865 cap->device_caps = V4L2_CAP_READWRITE |
1866 V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1867 else if (vdev->vfl_type == VFL_TYPE_RADIO)
1868 cap->device_caps = V4L2_CAP_RADIO;
1869 else
Hans Verkuil1d179ee2012-09-07 08:45:10 -03001870 cap->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE;
Devin Heitmueller04146142009-09-11 00:08:44 -03001871
Frank Schaefer920f1e42014-09-13 05:52:21 -03001872 if (dev->int_audio_type != EM28XX_INT_AUDIO_NONE)
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001873 cap->device_caps |= V4L2_CAP_AUDIO;
Mauro Carvalho Chehab6c428b52009-08-04 19:52:37 -03001874
Mauro Carvalho Chehabed086312008-01-24 06:59:20 -03001875 if (dev->tuner_type != TUNER_ABSENT)
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001876 cap->device_caps |= V4L2_CAP_TUNER;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001877
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001878 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS |
1879 V4L2_CAP_READWRITE | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
Hans Verkuild4352f32015-03-09 13:34:06 -03001880 if (video_is_registered(&v4l2->vbi_dev))
Hans Verkuil1d179ee2012-09-07 08:45:10 -03001881 cap->capabilities |= V4L2_CAP_VBI_CAPTURE;
Hans Verkuild4352f32015-03-09 13:34:06 -03001882 if (video_is_registered(&v4l2->radio_dev))
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001883 cap->capabilities |= V4L2_CAP_RADIO;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001884 return 0;
1885}
1886
Hans Verkuil78b526a2008-05-28 12:16:41 -03001887static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001888 struct v4l2_fmtdesc *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001889{
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001890 if (unlikely(f->index >= ARRAY_SIZE(format)))
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001891 return -EINVAL;
1892
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001893 strlcpy(f->description, format[f->index].name, sizeof(f->description));
1894 f->pixelformat = format[f->index].fourcc;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001895
1896 return 0;
1897}
1898
Mauro Carvalho Chehab1c5c5062011-10-16 13:52:43 -02001899static int vidioc_enum_framesizes(struct file *file, void *priv,
1900 struct v4l2_frmsizeenum *fsize)
1901{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001902 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab1c5c5062011-10-16 13:52:43 -02001903 struct em28xx_fmt *fmt;
1904 unsigned int maxw = norm_maxw(dev);
1905 unsigned int maxh = norm_maxh(dev);
1906
1907 fmt = format_by_fourcc(fsize->pixel_format);
1908 if (!fmt) {
1909 em28xx_videodbg("Fourcc format (%08x) invalid.\n",
1910 fsize->pixel_format);
1911 return -EINVAL;
1912 }
1913
1914 if (dev->board.is_em2800) {
1915 if (fsize->index > 1)
1916 return -EINVAL;
1917 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
1918 fsize->discrete.width = maxw / (1 + fsize->index);
1919 fsize->discrete.height = maxh / (1 + fsize->index);
1920 return 0;
1921 }
1922
1923 if (fsize->index != 0)
1924 return -EINVAL;
1925
1926 /* Report a continuous range */
1927 fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
Frank Schaefer6c3598e2013-02-10 16:05:14 -03001928 scale_to_size(dev, EM28XX_HVSCALE_MAX, EM28XX_HVSCALE_MAX,
1929 &fsize->stepwise.min_width, &fsize->stepwise.min_height);
1930 if (fsize->stepwise.min_width < 48)
1931 fsize->stepwise.min_width = 48;
1932 if (fsize->stepwise.min_height < 38)
1933 fsize->stepwise.min_height = 38;
Mauro Carvalho Chehab1c5c5062011-10-16 13:52:43 -02001934 fsize->stepwise.max_width = maxw;
1935 fsize->stepwise.max_height = maxh;
1936 fsize->stepwise.step_width = 1;
1937 fsize->stepwise.step_height = 1;
1938 return 0;
1939}
1940
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001941/* RAW VBI ioctls */
1942
1943static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
1944 struct v4l2_format *format)
1945{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001946 struct em28xx *dev = video_drvdata(file);
Frank Schaefer753aee72014-03-24 16:33:14 -03001947 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001948
Frank Schaefer753aee72014-03-24 16:33:14 -03001949 format->fmt.vbi.samples_per_line = v4l2->vbi_width;
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001950 format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
1951 format->fmt.vbi.offset = 0;
1952 format->fmt.vbi.flags = 0;
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001953 format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
Frank Schaefer753aee72014-03-24 16:33:14 -03001954 format->fmt.vbi.count[0] = v4l2->vbi_height;
1955 format->fmt.vbi.count[1] = v4l2->vbi_height;
Hans Verkuil2a221d32012-09-07 08:51:32 -03001956 memset(format->fmt.vbi.reserved, 0, sizeof(format->fmt.vbi.reserved));
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001957
1958 /* Varies by video standard (NTSC, PAL, etc.) */
Frank Schaefer52faaf72014-03-24 16:33:16 -03001959 if (v4l2->norm & V4L2_STD_525_60) {
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001960 /* NTSC */
1961 format->fmt.vbi.start[0] = 10;
1962 format->fmt.vbi.start[1] = 273;
Frank Schaefer52faaf72014-03-24 16:33:16 -03001963 } else if (v4l2->norm & V4L2_STD_625_50) {
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001964 /* PAL */
1965 format->fmt.vbi.start[0] = 6;
1966 format->fmt.vbi.start[1] = 318;
1967 }
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001968
1969 return 0;
1970}
1971
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001972/* ----------------------------------------------------------- */
1973/* RADIO ESPECIFIC IOCTLS */
1974/* ----------------------------------------------------------- */
1975
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001976static int radio_g_tuner(struct file *file, void *priv,
1977 struct v4l2_tuner *t)
1978{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001979 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001980
1981 if (unlikely(t->index > 0))
1982 return -EINVAL;
1983
1984 strcpy(t->name, "Radio");
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001985
Frank Schaefer95d26082014-03-24 16:33:09 -03001986 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, g_tuner, t);
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001987
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001988 return 0;
1989}
1990
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001991static int radio_s_tuner(struct file *file, void *priv,
Hans Verkuil2f73c7c2013-03-15 06:10:06 -03001992 const struct v4l2_tuner *t)
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001993{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001994 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001995
1996 if (0 != t->index)
1997 return -EINVAL;
1998
Frank Schaefer95d26082014-03-24 16:33:09 -03001999 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, s_tuner, t);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002000
2001 return 0;
2002}
2003
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002004/*
Frank Schaefer95d26082014-03-24 16:33:09 -03002005 * em28xx_free_v4l2() - Free struct em28xx_v4l2
2006 *
2007 * @ref: struct kref for struct em28xx_v4l2
2008 *
2009 * Called when all users of struct em28xx_v4l2 are gone
2010 */
Mauro Carvalho Chehabf472c0b2014-05-23 14:29:44 -03002011static void em28xx_free_v4l2(struct kref *ref)
Frank Schaefer95d26082014-03-24 16:33:09 -03002012{
2013 struct em28xx_v4l2 *v4l2 = container_of(ref, struct em28xx_v4l2, ref);
2014
Frank Schaeferabc13082014-03-24 16:33:10 -03002015 v4l2->dev->v4l2 = NULL;
Frank Schaefer95d26082014-03-24 16:33:09 -03002016 kfree(v4l2);
2017}
2018
2019/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002020 * em28xx_v4l2_open()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002021 * inits the device and starts isoc transfer
2022 */
Hans Verkuilbec43662008-12-30 06:58:20 -03002023static int em28xx_v4l2_open(struct file *filp)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002024{
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02002025 struct video_device *vdev = video_devdata(filp);
2026 struct em28xx *dev = video_drvdata(filp);
Frank Schaefer95d26082014-03-24 16:33:09 -03002027 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02002028 enum v4l2_buf_type fh_type = 0;
Frank Schaefer3c0f90e2014-07-25 14:48:57 -03002029 int ret;
Markus Rechberger9c755412005-11-08 21:37:52 -08002030
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02002031 switch (vdev->vfl_type) {
2032 case VFL_TYPE_GRABBER:
2033 fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2034 break;
2035 case VFL_TYPE_VBI:
2036 fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
2037 break;
Frank Schaefer4e170242014-01-12 13:24:18 -03002038 case VFL_TYPE_RADIO:
2039 break;
2040 default:
2041 return -EINVAL;
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02002042 }
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002043
Frank Schaefer8e2c8712014-09-18 17:55:45 -03002044 em28xx_videodbg("open dev=%s type=%s users=%d\n",
2045 video_device_node_name(vdev), v4l2_type_names[fh_type],
2046 v4l2->users);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002047
Hans Verkuil876cb142012-06-23 08:12:47 -03002048 if (mutex_lock_interruptible(&dev->lock))
2049 return -ERESTARTSYS;
Frank Schaefer3c0f90e2014-07-25 14:48:57 -03002050
2051 ret = v4l2_fh_open(filp);
2052 if (ret) {
2053 em28xx_errdev("%s: v4l2_fh_open() returned error %d\n",
2054 __func__, ret);
Hans Verkuil876cb142012-06-23 08:12:47 -03002055 mutex_unlock(&dev->lock);
Frank Schaefer3c0f90e2014-07-25 14:48:57 -03002056 return ret;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002057 }
2058
Frank Schaefer8e2c8712014-09-18 17:55:45 -03002059 if (v4l2->users == 0) {
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03002060 em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002061
Frank Schaefer4e170242014-01-12 13:24:18 -03002062 if (vdev->vfl_type != VFL_TYPE_RADIO)
2063 em28xx_resolution_set(dev);
2064
2065 /*
2066 * Needed, since GPIO might have disabled power
2067 * of some i2c devices
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03002068 */
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002069 em28xx_wake_i2c(dev);
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02002070 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002071
2072 if (vdev->vfl_type == VFL_TYPE_RADIO) {
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002073 em28xx_videodbg("video_open: setting radio device\n");
Frank Schaefer95d26082014-03-24 16:33:09 -03002074 v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, s_radio);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002075 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002076
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002077 kref_get(&dev->ref);
Frank Schaefer95d26082014-03-24 16:33:09 -03002078 kref_get(&v4l2->ref);
Frank Schaefer8e2c8712014-09-18 17:55:45 -03002079 v4l2->users++;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002080
Hans Verkuil876cb142012-06-23 08:12:47 -03002081 mutex_unlock(&dev->lock);
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03002082
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002083 return 0;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002084}
2085
2086/*
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002087 * em28xx_v4l2_fini()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002088 * unregisters the v4l2,i2c and usb devices
2089 * called when the device gets disconected or at module unload
2090*/
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002091static int em28xx_v4l2_fini(struct em28xx *dev)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002092{
Frank Schaefer95d26082014-03-24 16:33:09 -03002093 struct em28xx_v4l2 *v4l2 = dev->v4l2;
2094
Mauro Carvalho Chehab822b8de2014-01-06 05:27:47 -03002095 if (dev->is_audio_only) {
2096 /* Shouldn't initialize IR for this interface */
2097 return 0;
2098 }
2099
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002100 if (!dev->has_video) {
2101 /* This device does not support the v4l2 extension */
2102 return 0;
2103 }
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02002104
Frank Schaefer95d26082014-03-24 16:33:09 -03002105 if (v4l2 == NULL)
2106 return 0;
2107
Russell King0418ca62014-12-20 09:45:20 -03002108 em28xx_info("Closing video extension\n");
Mauro Carvalho Chehabaa929ad2014-01-12 19:22:07 -03002109
Mauro Carvalho Chehabebbfbc22014-01-13 02:53:44 -03002110 mutex_lock(&dev->lock);
2111
Frank Schaefer95d26082014-03-24 16:33:09 -03002112 v4l2_device_disconnect(&v4l2->v4l2_dev);
Frank Schaefer5ad10de2014-01-12 13:24:21 -03002113
Frank Schaefer23e86422014-01-12 13:24:20 -03002114 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
2115
Mauro Carvalho Chehab37ecc7b2016-01-27 07:07:24 -02002116 em28xx_v4l2_media_release(dev);
2117
Hans Verkuild4352f32015-03-09 13:34:06 -03002118 if (video_is_registered(&v4l2->radio_dev)) {
Frank Schaefere8470222014-01-12 13:24:25 -03002119 em28xx_info("V4L2 device %s deregistered\n",
Hans Verkuild4352f32015-03-09 13:34:06 -03002120 video_device_node_name(&v4l2->radio_dev));
2121 video_unregister_device(&v4l2->radio_dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002122 }
Hans Verkuild4352f32015-03-09 13:34:06 -03002123 if (video_is_registered(&v4l2->vbi_dev)) {
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002124 em28xx_info("V4L2 device %s deregistered\n",
Hans Verkuild4352f32015-03-09 13:34:06 -03002125 video_device_node_name(&v4l2->vbi_dev));
2126 video_unregister_device(&v4l2->vbi_dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002127 }
Hans Verkuild4352f32015-03-09 13:34:06 -03002128 if (video_is_registered(&v4l2->vdev)) {
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002129 em28xx_info("V4L2 device %s deregistered\n",
Hans Verkuild4352f32015-03-09 13:34:06 -03002130 video_device_node_name(&v4l2->vdev));
2131 video_unregister_device(&v4l2->vdev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002132 }
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002133
Frank Schaeferabc13082014-03-24 16:33:10 -03002134 v4l2_ctrl_handler_free(&v4l2->ctrl_handler);
Frank Schaefer95d26082014-03-24 16:33:09 -03002135 v4l2_device_unregister(&v4l2->v4l2_dev);
Frank Schaefer103f18a2014-01-17 14:45:30 -03002136
Frank Schaefer2c52a2f2014-03-24 16:33:11 -03002137 if (v4l2->clk) {
2138 v4l2_clk_unregister_fixed(v4l2->clk);
2139 v4l2->clk = NULL;
Frank Schaefer25dd1652014-01-12 13:24:23 -03002140 }
2141
Frank Schaefer95d26082014-03-24 16:33:09 -03002142 kref_put(&v4l2->ref, em28xx_free_v4l2);
2143
Mauro Carvalho Chehabebbfbc22014-01-13 02:53:44 -03002144 mutex_unlock(&dev->lock);
Frank Schaefer95d26082014-03-24 16:33:09 -03002145
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002146 kref_put(&dev->ref, em28xx_free_device);
Frank Schaefer5ad10de2014-01-12 13:24:21 -03002147
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002148 return 0;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002149}
2150
Shuah Khana61f6812014-02-21 21:50:17 -03002151static int em28xx_v4l2_suspend(struct em28xx *dev)
2152{
2153 if (dev->is_audio_only)
2154 return 0;
2155
2156 if (!dev->has_video)
2157 return 0;
2158
Russell King32e63f02014-12-20 09:45:51 -03002159 em28xx_info("Suspending video extension\n");
Shuah Khana61f6812014-02-21 21:50:17 -03002160 em28xx_stop_urbs(dev);
2161 return 0;
2162}
2163
2164static int em28xx_v4l2_resume(struct em28xx *dev)
2165{
2166 if (dev->is_audio_only)
2167 return 0;
2168
2169 if (!dev->has_video)
2170 return 0;
2171
Russell King32e63f02014-12-20 09:45:51 -03002172 em28xx_info("Resuming video extension\n");
Shuah Khana61f6812014-02-21 21:50:17 -03002173 /* what do we do here */
2174 return 0;
2175}
2176
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002177/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002178 * em28xx_v4l2_close()
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03002179 * stops streaming and deallocates all resources allocated by the v4l2
2180 * calls and ioctls
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002181 */
Hans Verkuilbec43662008-12-30 06:58:20 -03002182static int em28xx_v4l2_close(struct file *filp)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002183{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03002184 struct em28xx *dev = video_drvdata(filp);
Frank Schaefer95d26082014-03-24 16:33:09 -03002185 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03002186 int errCode;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002187
Frank Schaefer8e2c8712014-09-18 17:55:45 -03002188 em28xx_videodbg("users=%d\n", v4l2->users);
2189
2190 vb2_fop_release(filp);
Ricardo Ribalda98c24dcd2013-11-06 05:39:35 -03002191 mutex_lock(&dev->lock);
Devin Heitmueller8c873d32009-09-03 00:23:27 -03002192
Frank Schaefer8e2c8712014-09-18 17:55:45 -03002193 if (v4l2->users == 1) {
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002194 /* No sense to try to write to the device */
2195 if (dev->disconnected)
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002196 goto exit;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03002197
Mauro Carvalho Chehabeb6c9632008-12-05 10:39:12 -03002198 /* Save some power by putting tuner to sleep */
Frank Schaefer95d26082014-03-24 16:33:09 -03002199 v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_power, 0);
Mauro Carvalho Chehabeb6c9632008-12-05 10:39:12 -03002200
Aidan Thorntond7aa8022008-04-13 14:38:47 -03002201 /* do this before setting alternate! */
Mauro Carvalho Chehab2fe3e2e2008-11-27 09:10:40 -03002202 em28xx_set_mode(dev, EM28XX_SUSPEND);
Aidan Thorntond7aa8022008-04-13 14:38:47 -03002203
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03002204 /* set alternate 0 */
2205 dev->alt = 0;
2206 em28xx_videodbg("setting alternate 0\n");
2207 errCode = usb_set_interface(dev->udev, 0, 0);
2208 if (errCode < 0) {
2209 em28xx_errdev("cannot change alternate number to "
2210 "0 (error=%i)\n", errCode);
2211 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002212 }
Devin Heitmueller28abf0832009-09-01 01:54:54 -03002213
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002214exit:
Frank Schaefer8e2c8712014-09-18 17:55:45 -03002215 v4l2->users--;
Frank Schaefer95d26082014-03-24 16:33:09 -03002216 kref_put(&v4l2->ref, em28xx_free_v4l2);
Hans Verkuil876cb142012-06-23 08:12:47 -03002217 mutex_unlock(&dev->lock);
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002218 kref_put(&dev->ref, em28xx_free_device);
2219
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002220 return 0;
2221}
2222
Hans Verkuilbec43662008-12-30 06:58:20 -03002223static const struct v4l2_file_operations em28xx_v4l_fops = {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002224 .owner = THIS_MODULE,
2225 .open = em28xx_v4l2_open,
2226 .release = em28xx_v4l2_close,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002227 .read = vb2_fop_read,
2228 .poll = vb2_fop_poll,
2229 .mmap = vb2_fop_mmap,
Hans Verkuil0499a5a2010-09-26 07:34:45 -03002230 .unlocked_ioctl = video_ioctl2,
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002231};
2232
Hans Verkuila3998102008-07-21 02:57:38 -03002233static const struct v4l2_ioctl_ops video_ioctl_ops = {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002234 .vidioc_querycap = vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03002235 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
2236 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
2237 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
2238 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Devin Heitmueller28abf0832009-09-01 01:54:54 -03002239 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Hans Verkuil2a221d32012-09-07 08:51:32 -03002240 .vidioc_try_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Frank Schaeferaab34612013-02-07 13:39:16 -03002241 .vidioc_s_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Mauro Carvalho Chehab1c5c5062011-10-16 13:52:43 -02002242 .vidioc_enum_framesizes = vidioc_enum_framesizes,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002243 .vidioc_g_audio = vidioc_g_audio,
2244 .vidioc_s_audio = vidioc_s_audio,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002245
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002246 .vidioc_reqbufs = vb2_ioctl_reqbufs,
2247 .vidioc_create_bufs = vb2_ioctl_create_bufs,
2248 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
2249 .vidioc_querybuf = vb2_ioctl_querybuf,
2250 .vidioc_qbuf = vb2_ioctl_qbuf,
2251 .vidioc_dqbuf = vb2_ioctl_dqbuf,
2252
Devin Heitmueller19bf0032009-09-11 00:40:18 -03002253 .vidioc_g_std = vidioc_g_std,
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03002254 .vidioc_querystd = vidioc_querystd,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002255 .vidioc_s_std = vidioc_s_std,
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03002256 .vidioc_g_parm = vidioc_g_parm,
2257 .vidioc_s_parm = vidioc_s_parm,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002258 .vidioc_enum_input = vidioc_enum_input,
2259 .vidioc_g_input = vidioc_g_input,
2260 .vidioc_s_input = vidioc_s_input,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002261 .vidioc_streamon = vb2_ioctl_streamon,
2262 .vidioc_streamoff = vb2_ioctl_streamoff,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002263 .vidioc_g_tuner = vidioc_g_tuner,
2264 .vidioc_s_tuner = vidioc_s_tuner,
2265 .vidioc_g_frequency = vidioc_g_frequency,
2266 .vidioc_s_frequency = vidioc_s_frequency,
Hans Verkuil50fdf402012-09-07 06:10:12 -03002267 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
2268 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002269#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuil96b03d22013-04-06 06:16:58 -03002270 .vidioc_g_chip_info = vidioc_g_chip_info,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002271 .vidioc_g_register = vidioc_g_register,
2272 .vidioc_s_register = vidioc_s_register,
2273#endif
Hans Verkuila3998102008-07-21 02:57:38 -03002274};
2275
2276static const struct video_device em28xx_video_template = {
Frank Schaefere8470222014-01-12 13:24:25 -03002277 .fops = &em28xx_v4l_fops,
2278 .ioctl_ops = &video_ioctl_ops,
Hans Verkuild4352f32015-03-09 13:34:06 -03002279 .release = video_device_release_empty,
Frank Schaefere8470222014-01-12 13:24:25 -03002280 .tvnorms = V4L2_STD_ALL,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002281};
2282
Hans Verkuilbec43662008-12-30 06:58:20 -03002283static const struct v4l2_file_operations radio_fops = {
Hans Verkuila3998102008-07-21 02:57:38 -03002284 .owner = THIS_MODULE,
2285 .open = em28xx_v4l2_open,
2286 .release = em28xx_v4l2_close,
Hans Verkuil8fd0bda2010-12-18 09:59:51 -03002287 .unlocked_ioctl = video_ioctl2,
Hans Verkuila3998102008-07-21 02:57:38 -03002288};
2289
2290static const struct v4l2_ioctl_ops radio_ioctl_ops = {
Hans Verkuila9d79fe2012-09-06 07:31:04 -03002291 .vidioc_querycap = vidioc_querycap,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002292 .vidioc_g_tuner = radio_g_tuner,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002293 .vidioc_s_tuner = radio_s_tuner,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002294 .vidioc_g_frequency = vidioc_g_frequency,
2295 .vidioc_s_frequency = vidioc_s_frequency,
Hans Verkuil50fdf402012-09-07 06:10:12 -03002296 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
2297 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002298#ifdef CONFIG_VIDEO_ADV_DEBUG
Michal Marek430c73f2013-04-16 08:06:30 -03002299 .vidioc_g_chip_info = vidioc_g_chip_info,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002300 .vidioc_g_register = vidioc_g_register,
2301 .vidioc_s_register = vidioc_s_register,
2302#endif
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002303};
2304
Hans Verkuila3998102008-07-21 02:57:38 -03002305static struct video_device em28xx_radio_template = {
Frank Schaefere8470222014-01-12 13:24:25 -03002306 .fops = &radio_fops,
2307 .ioctl_ops = &radio_ioctl_ops,
Hans Verkuild4352f32015-03-09 13:34:06 -03002308 .release = video_device_release_empty,
Hans Verkuila3998102008-07-21 02:57:38 -03002309};
2310
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002311/* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */
2312static unsigned short saa711x_addrs[] = {
2313 0x4a >> 1, 0x48 >> 1, /* SAA7111, SAA7111A and SAA7113 */
2314 0x42 >> 1, 0x40 >> 1, /* SAA7114, SAA7115 and SAA7118 */
2315 I2C_CLIENT_END };
2316
2317static unsigned short tvp5150_addrs[] = {
2318 0xb8 >> 1,
2319 0xba >> 1,
2320 I2C_CLIENT_END
2321};
2322
2323static unsigned short msp3400_addrs[] = {
2324 0x80 >> 1,
2325 0x88 >> 1,
2326 I2C_CLIENT_END
2327};
2328
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03002329/******************************** usb interface ******************************/
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002330
Hans Verkuild4352f32015-03-09 13:34:06 -03002331static void em28xx_vdev_init(struct em28xx *dev,
2332 struct video_device *vfd,
2333 const struct video_device *template,
2334 const char *type_name)
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002335{
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03002336 *vfd = *template;
Frank Schaefer95d26082014-03-24 16:33:09 -03002337 vfd->v4l2_dev = &dev->v4l2->v4l2_dev;
Hans Verkuil0499a5a2010-09-26 07:34:45 -03002338 vfd->lock = &dev->lock;
Hans Verkuild8c95c02012-09-07 07:31:54 -03002339 if (dev->board.is_webcam)
2340 vfd->tvnorms = 0;
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002341
2342 snprintf(vfd->name, sizeof(vfd->name), "%s %s",
2343 dev->name, type_name);
2344
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02002345 video_set_drvdata(vfd, dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002346}
2347
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002348static void em28xx_tuner_setup(struct em28xx *dev, unsigned short tuner_addr)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002349{
Frank Schaefer3854b0d2014-03-24 16:33:22 -03002350 struct em28xx_v4l2 *v4l2 = dev->v4l2;
2351 struct v4l2_device *v4l2_dev = &v4l2->v4l2_dev;
2352 struct tuner_setup tun_setup;
2353 struct v4l2_frequency f;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002354
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002355 memset(&tun_setup, 0, sizeof(tun_setup));
2356
2357 tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
2358 tun_setup.tuner_callback = em28xx_tuner_callback;
2359
2360 if (dev->board.radio.type) {
2361 tun_setup.type = dev->board.radio.type;
2362 tun_setup.addr = dev->board.radio_addr;
2363
Frank Schaefer95d26082014-03-24 16:33:09 -03002364 v4l2_device_call_all(v4l2_dev,
2365 0, tuner, s_type_addr, &tun_setup);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002366 }
2367
2368 if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type)) {
2369 tun_setup.type = dev->tuner_type;
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002370 tun_setup.addr = tuner_addr;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002371
Frank Schaefer95d26082014-03-24 16:33:09 -03002372 v4l2_device_call_all(v4l2_dev,
2373 0, tuner, s_type_addr, &tun_setup);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002374 }
2375
Frank Schaefer6867bd5a2014-03-24 16:33:23 -03002376 if (dev->board.tda9887_conf) {
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002377 struct v4l2_priv_tun_config tda9887_cfg;
2378
2379 tda9887_cfg.tuner = TUNER_TDA9887;
Frank Schaefer6867bd5a2014-03-24 16:33:23 -03002380 tda9887_cfg.priv = &dev->board.tda9887_conf;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002381
Frank Schaefer95d26082014-03-24 16:33:09 -03002382 v4l2_device_call_all(v4l2_dev,
2383 0, tuner, s_config, &tda9887_cfg);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002384 }
2385
2386 if (dev->tuner_type == TUNER_XC2028) {
2387 struct v4l2_priv_tun_config xc2028_cfg;
2388 struct xc2028_ctrl ctl;
2389
2390 memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
2391 memset(&ctl, 0, sizeof(ctl));
2392
2393 em28xx_setup_xc3028(dev, &ctl);
2394
2395 xc2028_cfg.tuner = TUNER_XC2028;
2396 xc2028_cfg.priv = &ctl;
2397
Frank Schaefer95d26082014-03-24 16:33:09 -03002398 v4l2_device_call_all(v4l2_dev, 0, tuner, s_config, &xc2028_cfg);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002399 }
2400
2401 /* configure tuner */
2402 f.tuner = 0;
2403 f.type = V4L2_TUNER_ANALOG_TV;
2404 f.frequency = 9076; /* just a magic number */
Frank Schaefer3854b0d2014-03-24 16:33:22 -03002405 v4l2->frequency = f.frequency;
Frank Schaefer95d26082014-03-24 16:33:09 -03002406 v4l2_device_call_all(v4l2_dev, 0, tuner, s_frequency, &f);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002407}
2408
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002409static int em28xx_v4l2_init(struct em28xx *dev)
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002410{
Hans Verkuil081b9452012-09-07 05:43:59 -03002411 u8 val;
Mauro Carvalho Chehab2e5ef2d2008-12-28 22:26:36 -03002412 int ret;
Sascha Sommer1020d132012-01-08 16:54:28 -03002413 unsigned int maxw;
Frank Schaeferabc13082014-03-24 16:33:10 -03002414 struct v4l2_ctrl_handler *hdl;
Frank Schaefer95d26082014-03-24 16:33:09 -03002415 struct em28xx_v4l2 *v4l2;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002416
Mauro Carvalho Chehab822b8de2014-01-06 05:27:47 -03002417 if (dev->is_audio_only) {
2418 /* Shouldn't initialize IR for this interface */
2419 return 0;
2420 }
2421
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002422 if (!dev->has_video) {
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002423 /* This device does not support the v4l2 extension */
2424 return 0;
2425 }
Mauro Carvalho Chehab2e5ef2d2008-12-28 22:26:36 -03002426
Mauro Carvalho Chehab96346142013-12-26 12:41:03 -03002427 em28xx_info("Registering V4L2 extension\n");
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002428
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002429 mutex_lock(&dev->lock);
2430
Frank Schaefer95d26082014-03-24 16:33:09 -03002431 v4l2 = kzalloc(sizeof(struct em28xx_v4l2), GFP_KERNEL);
2432 if (v4l2 == NULL) {
2433 em28xx_info("em28xx_v4l: memory allocation failed\n");
2434 mutex_unlock(&dev->lock);
2435 return -ENOMEM;
2436 }
2437 kref_init(&v4l2->ref);
Frank Schaeferabc13082014-03-24 16:33:10 -03002438 v4l2->dev = dev;
Frank Schaefer95d26082014-03-24 16:33:09 -03002439 dev->v4l2 = v4l2;
2440
Mauro Carvalho Chehab37ecc7b2016-01-27 07:07:24 -02002441#ifdef CONFIG_MEDIA_CONTROLLER
2442 v4l2->v4l2_dev.mdev = dev->media_dev;
2443#endif
Frank Schaefer95d26082014-03-24 16:33:09 -03002444 ret = v4l2_device_register(&dev->udev->dev, &v4l2->v4l2_dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002445 if (ret < 0) {
2446 em28xx_errdev("Call to v4l2_device_register() failed!\n");
2447 goto err;
2448 }
2449
Frank Schaeferabc13082014-03-24 16:33:10 -03002450 hdl = &v4l2->ctrl_handler;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002451 v4l2_ctrl_handler_init(hdl, 8);
Frank Schaefer95d26082014-03-24 16:33:09 -03002452 v4l2->v4l2_dev.ctrl_handler = hdl;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002453
Frank Schaefer58159172014-03-24 16:33:18 -03002454 if (dev->board.is_webcam)
Mauro Carvalho Chehab7e6c8c12014-09-03 15:06:13 -03002455 v4l2->progressive = true;
Frank Schaefer58159172014-03-24 16:33:18 -03002456
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002457 /*
2458 * Default format, used for tvp5150 or saa711x output formats
2459 */
Frank Schaefer92972852014-03-24 16:33:15 -03002460 v4l2->vinmode = 0x10;
2461 v4l2->vinctl = EM28XX_VINCTRL_INTERLACED |
2462 EM28XX_VINCTRL_CCIR656_ENABLE;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002463
2464 /* request some modules */
2465
2466 if (dev->board.has_msp34xx)
Frank Schaefer95d26082014-03-24 16:33:09 -03002467 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2468 &dev->i2c_adap[dev->def_i2c_bus],
2469 "msp3400", 0, msp3400_addrs);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002470
2471 if (dev->board.decoder == EM28XX_SAA711X)
Frank Schaefer95d26082014-03-24 16:33:09 -03002472 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2473 &dev->i2c_adap[dev->def_i2c_bus],
2474 "saa7115_auto", 0, saa711x_addrs);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002475
2476 if (dev->board.decoder == EM28XX_TVP5150)
Frank Schaefer95d26082014-03-24 16:33:09 -03002477 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2478 &dev->i2c_adap[dev->def_i2c_bus],
2479 "tvp5150", 0, tvp5150_addrs);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002480
2481 if (dev->board.adecoder == EM28XX_TVAUDIO)
Frank Schaefer95d26082014-03-24 16:33:09 -03002482 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2483 &dev->i2c_adap[dev->def_i2c_bus],
2484 "tvaudio", dev->board.tvaudio_addr, NULL);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002485
2486 /* Initialize tuner and camera */
2487
2488 if (dev->board.tuner_type != TUNER_ABSENT) {
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002489 unsigned short tuner_addr = dev->board.tuner_addr;
Frank Schaefer6867bd5a2014-03-24 16:33:23 -03002490 int has_demod = (dev->board.tda9887_conf & TDA9887_PRESENT);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002491
2492 if (dev->board.radio.type)
Frank Schaefer95d26082014-03-24 16:33:09 -03002493 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002494 &dev->i2c_adap[dev->def_i2c_bus],
2495 "tuner", dev->board.radio_addr,
2496 NULL);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002497
2498 if (has_demod)
Frank Schaefer95d26082014-03-24 16:33:09 -03002499 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002500 &dev->i2c_adap[dev->def_i2c_bus],
2501 "tuner", 0,
2502 v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002503 if (tuner_addr == 0) {
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002504 enum v4l2_i2c_tuner_type type =
2505 has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV;
2506 struct v4l2_subdev *sd;
2507
Frank Schaefer95d26082014-03-24 16:33:09 -03002508 sd = v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002509 &dev->i2c_adap[dev->def_i2c_bus],
2510 "tuner", 0,
2511 v4l2_i2c_tuner_addrs(type));
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002512
2513 if (sd)
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002514 tuner_addr = v4l2_i2c_subdev_addr(sd);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002515 } else {
Frank Schaefer95d26082014-03-24 16:33:09 -03002516 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2517 &dev->i2c_adap[dev->def_i2c_bus],
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002518 "tuner", tuner_addr, NULL);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002519 }
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002520
2521 em28xx_tuner_setup(dev, tuner_addr);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002522 }
2523
Frank Schaeferd86bc652014-01-17 14:45:32 -03002524 if (dev->em28xx_sensor != EM28XX_NOSENSOR)
2525 em28xx_init_camera(dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002526
2527 /* Configure audio */
2528 ret = em28xx_audio_setup(dev);
2529 if (ret < 0) {
2530 em28xx_errdev("%s: Error while setting audio - error [%d]!\n",
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002531 __func__, ret);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002532 goto unregister_dev;
2533 }
2534 if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
2535 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002536 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002537 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002538 V4L2_CID_AUDIO_VOLUME, 0, 0x1f, 1, 0x1f);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002539 } else {
2540 /* install the em28xx notify callback */
2541 v4l2_ctrl_notify(v4l2_ctrl_find(hdl, V4L2_CID_AUDIO_MUTE),
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002542 em28xx_ctrl_notify, dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002543 v4l2_ctrl_notify(v4l2_ctrl_find(hdl, V4L2_CID_AUDIO_VOLUME),
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002544 em28xx_ctrl_notify, dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002545 }
2546
2547 /* wake i2c devices */
2548 em28xx_wake_i2c(dev);
2549
2550 /* init video dma queues */
2551 INIT_LIST_HEAD(&dev->vidq.active);
2552 INIT_LIST_HEAD(&dev->vbiq.active);
2553
2554 if (dev->board.has_msp34xx) {
2555 /* Send a reset to other chips via gpio */
2556 ret = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xf7);
2557 if (ret < 0) {
2558 em28xx_errdev("%s: em28xx_write_reg - msp34xx(1) failed! error [%d]\n",
2559 __func__, ret);
2560 goto unregister_dev;
2561 }
2562 msleep(3);
2563
2564 ret = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xff);
2565 if (ret < 0) {
2566 em28xx_errdev("%s: em28xx_write_reg - msp34xx(2) failed! error [%d]\n",
2567 __func__, ret);
2568 goto unregister_dev;
2569 }
2570 msleep(3);
2571 }
2572
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002573 /* set default norm */
Frank Schaefer52faaf72014-03-24 16:33:16 -03002574 v4l2->norm = V4L2_STD_PAL;
Laurent Pinchart8774bed2014-04-28 16:53:01 -03002575 v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_std, v4l2->norm);
Frank Schaefer58159172014-03-24 16:33:18 -03002576 v4l2->interlaced_fieldmode = EM28XX_INTERLACED_DEFAULT;
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002577
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002578 /* Analog specific initialization */
Frank Schaefer06e20672014-03-24 16:33:17 -03002579 v4l2->format = &format[0];
Sascha Sommer1020d132012-01-08 16:54:28 -03002580
2581 maxw = norm_maxw(dev);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002582 /* MaxPacketSize for em2800 is too small to capture at full resolution
2583 * use half of maxw as the scaler can only scale to 50% */
2584 if (dev->board.is_em2800)
2585 maxw /= 2;
Sascha Sommer1020d132012-01-08 16:54:28 -03002586
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03002587 em28xx_set_video_format(dev, format[0].fourcc,
Sascha Sommer1020d132012-01-08 16:54:28 -03002588 maxw, norm_maxh(dev));
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03002589
Ezequiel García96371fc2012-03-23 18:09:34 -03002590 video_mux(dev, 0);
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002591
2592 /* Audio defaults */
2593 dev->mute = 1;
2594 dev->volume = 0x1f;
2595
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002596/* em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -03002597 val = (u8)em28xx_read_reg(dev, EM28XX_R0F_XCLK);
2598 em28xx_write_reg(dev, EM28XX_R0F_XCLK,
2599 (EM28XX_XCLK_AUDIO_UNMUTE | val));
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002600
2601 em28xx_set_outfmt(dev);
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002602
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002603 /* Add image controls */
2604 /* NOTE: at this point, the subdevices are already registered, so bridge
2605 * controls are only added/enabled when no subdevice provides them */
Frank Schaeferad298052014-03-24 16:33:08 -03002606 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_CONTRAST))
2607 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002608 V4L2_CID_CONTRAST,
2609 0, 0x1f, 1, CONTRAST_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002610 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_BRIGHTNESS))
2611 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002612 V4L2_CID_BRIGHTNESS,
2613 -0x80, 0x7f, 1, BRIGHTNESS_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002614 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_SATURATION))
2615 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002616 V4L2_CID_SATURATION,
2617 0, 0x1f, 1, SATURATION_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002618 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_BLUE_BALANCE))
2619 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002620 V4L2_CID_BLUE_BALANCE,
2621 -0x30, 0x30, 1, BLUE_BALANCE_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002622 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_RED_BALANCE))
2623 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002624 V4L2_CID_RED_BALANCE,
2625 -0x30, 0x30, 1, RED_BALANCE_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002626 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_SHARPNESS))
2627 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002628 V4L2_CID_SHARPNESS,
2629 0, 0x0f, 1, SHARPNESS_DEFAULT);
2630
2631 /* Reset image controls */
2632 em28xx_colorlevels_set_default(dev);
Frank Schaeferad298052014-03-24 16:33:08 -03002633 v4l2_ctrl_handler_setup(hdl);
2634 ret = hdl->error;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002635 if (ret)
2636 goto unregister_dev;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002637
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002638 /* allocate and fill video video_device struct */
Hans Verkuild4352f32015-03-09 13:34:06 -03002639 em28xx_vdev_init(dev, &v4l2->vdev, &em28xx_video_template, "video");
Frank Schaefer27a36df2014-03-24 16:33:13 -03002640 mutex_init(&v4l2->vb_queue_lock);
2641 mutex_init(&v4l2->vb_vbi_queue_lock);
Hans Verkuild4352f32015-03-09 13:34:06 -03002642 v4l2->vdev.queue = &v4l2->vb_vidq;
2643 v4l2->vdev.queue->lock = &v4l2->vb_queue_lock;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002644
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002645 /* disable inapplicable ioctls */
2646 if (dev->board.is_webcam) {
Hans Verkuild4352f32015-03-09 13:34:06 -03002647 v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_QUERYSTD);
2648 v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_G_STD);
2649 v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_S_STD);
Frank Schaefer3bc85cc2013-02-07 13:39:12 -03002650 } else {
Hans Verkuild4352f32015-03-09 13:34:06 -03002651 v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_S_PARM);
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002652 }
Frank Schaefer66df67b2013-02-07 13:39:10 -03002653 if (dev->tuner_type == TUNER_ABSENT) {
Hans Verkuild4352f32015-03-09 13:34:06 -03002654 v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_G_TUNER);
2655 v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_S_TUNER);
2656 v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_G_FREQUENCY);
2657 v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_S_FREQUENCY);
Frank Schaefer66df67b2013-02-07 13:39:10 -03002658 }
Frank Schaefer920f1e42014-09-13 05:52:21 -03002659 if (dev->int_audio_type == EM28XX_INT_AUDIO_NONE) {
Hans Verkuild4352f32015-03-09 13:34:06 -03002660 v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_G_AUDIO);
2661 v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_S_AUDIO);
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002662 }
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002663
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002664 /* register v4l2 video video_device */
Hans Verkuild4352f32015-03-09 13:34:06 -03002665 ret = video_register_device(&v4l2->vdev, VFL_TYPE_GRABBER,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002666 video_nr[dev->devno]);
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002667 if (ret) {
2668 em28xx_errdev("unable to register video device (error=%i).\n",
2669 ret);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002670 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002671 }
2672
2673 /* Allocate and fill vbi video_device struct */
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002674 if (em28xx_vbi_supported(dev) == 1) {
Hans Verkuild4352f32015-03-09 13:34:06 -03002675 em28xx_vdev_init(dev, &v4l2->vbi_dev, &em28xx_video_template,
2676 "vbi");
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002677
Hans Verkuild4352f32015-03-09 13:34:06 -03002678 v4l2->vbi_dev.queue = &v4l2->vb_vbiq;
2679 v4l2->vbi_dev.queue->lock = &v4l2->vb_vbi_queue_lock;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002680
Frank Schaefer66df67b2013-02-07 13:39:10 -03002681 /* disable inapplicable ioctls */
Hans Verkuild4352f32015-03-09 13:34:06 -03002682 v4l2_disable_ioctl(&v4l2->vbi_dev, VIDIOC_S_PARM);
Frank Schaefer66df67b2013-02-07 13:39:10 -03002683 if (dev->tuner_type == TUNER_ABSENT) {
Hans Verkuild4352f32015-03-09 13:34:06 -03002684 v4l2_disable_ioctl(&v4l2->vbi_dev, VIDIOC_G_TUNER);
2685 v4l2_disable_ioctl(&v4l2->vbi_dev, VIDIOC_S_TUNER);
2686 v4l2_disable_ioctl(&v4l2->vbi_dev, VIDIOC_G_FREQUENCY);
2687 v4l2_disable_ioctl(&v4l2->vbi_dev, VIDIOC_S_FREQUENCY);
Frank Schaefer66df67b2013-02-07 13:39:10 -03002688 }
Frank Schaefer920f1e42014-09-13 05:52:21 -03002689 if (dev->int_audio_type == EM28XX_INT_AUDIO_NONE) {
Hans Verkuild4352f32015-03-09 13:34:06 -03002690 v4l2_disable_ioctl(&v4l2->vbi_dev, VIDIOC_G_AUDIO);
2691 v4l2_disable_ioctl(&v4l2->vbi_dev, VIDIOC_S_AUDIO);
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002692 }
Frank Schaefer66df67b2013-02-07 13:39:10 -03002693
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002694 /* register v4l2 vbi video_device */
Hans Verkuild4352f32015-03-09 13:34:06 -03002695 ret = video_register_device(&v4l2->vbi_dev, VFL_TYPE_VBI,
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002696 vbi_nr[dev->devno]);
2697 if (ret < 0) {
2698 em28xx_errdev("unable to register vbi device\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002699 goto unregister_dev;
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002700 }
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002701 }
2702
2703 if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) {
Hans Verkuild4352f32015-03-09 13:34:06 -03002704 em28xx_vdev_init(dev, &v4l2->radio_dev, &em28xx_radio_template,
2705 "radio");
2706 ret = video_register_device(&v4l2->radio_dev, VFL_TYPE_RADIO,
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002707 radio_nr[dev->devno]);
2708 if (ret < 0) {
2709 em28xx_errdev("can't register radio device\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002710 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002711 }
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002712 em28xx_info("Registered radio device as %s\n",
Hans Verkuild4352f32015-03-09 13:34:06 -03002713 video_device_node_name(&v4l2->radio_dev));
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002714 }
2715
Mauro Carvalho Chehab37ecc7b2016-01-27 07:07:24 -02002716 /* Init entities at the Media Controller */
2717 em28xx_v4l2_create_entities(dev);
2718
Arnd Bergmann0d37ba62016-02-26 08:53:22 -03002719#ifdef CONFIG_MEDIA_CONTROLLER
Mauro Carvalho Chehabde390782016-02-05 07:08:25 -02002720 ret = v4l2_mc_create_media_graph(dev->media_dev);
Mauro Carvalho Chehab37ecc7b2016-01-27 07:07:24 -02002721 if (ret) {
2722 em28xx_errdev("failed to create media graph\n");
2723 em28xx_v4l2_media_release(dev);
2724 goto unregister_dev;
2725 }
Arnd Bergmann0d37ba62016-02-26 08:53:22 -03002726#endif
Mauro Carvalho Chehab37ecc7b2016-01-27 07:07:24 -02002727
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002728 em28xx_info("V4L2 video device registered as %s\n",
Hans Verkuild4352f32015-03-09 13:34:06 -03002729 video_device_node_name(&v4l2->vdev));
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002730
Hans Verkuild4352f32015-03-09 13:34:06 -03002731 if (video_is_registered(&v4l2->vbi_dev))
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002732 em28xx_info("V4L2 VBI device registered as %s\n",
Hans Verkuild4352f32015-03-09 13:34:06 -03002733 video_device_node_name(&v4l2->vbi_dev));
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002734
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002735 /* Save some power by putting tuner to sleep */
Frank Schaefer95d26082014-03-24 16:33:09 -03002736 v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_power, 0);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002737
2738 /* initialize videobuf2 stuff */
2739 em28xx_vb2_setup(dev);
2740
Mauro Carvalho Chehab96346142013-12-26 12:41:03 -03002741 em28xx_info("V4L2 extension successfully initialized\n");
2742
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002743 kref_get(&dev->ref);
2744
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002745 mutex_unlock(&dev->lock);
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002746 return 0;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002747
2748unregister_dev:
Mauro Carvalho Chehab56a7f512016-01-29 13:08:19 -02002749 if (video_is_registered(&v4l2->radio_dev)) {
2750 em28xx_info("V4L2 device %s deregistered\n",
2751 video_device_node_name(&v4l2->radio_dev));
2752 video_unregister_device(&v4l2->radio_dev);
2753 }
2754 if (video_is_registered(&v4l2->vbi_dev)) {
2755 em28xx_info("V4L2 device %s deregistered\n",
2756 video_device_node_name(&v4l2->vbi_dev));
2757 video_unregister_device(&v4l2->vbi_dev);
2758 }
2759 if (video_is_registered(&v4l2->vdev)) {
2760 em28xx_info("V4L2 device %s deregistered\n",
2761 video_device_node_name(&v4l2->vdev));
2762 video_unregister_device(&v4l2->vdev);
2763 }
2764
Frank Schaeferabc13082014-03-24 16:33:10 -03002765 v4l2_ctrl_handler_free(&v4l2->ctrl_handler);
Frank Schaefer95d26082014-03-24 16:33:09 -03002766 v4l2_device_unregister(&v4l2->v4l2_dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002767err:
Frank Schaefer95d26082014-03-24 16:33:09 -03002768 dev->v4l2 = NULL;
2769 kref_put(&v4l2->ref, em28xx_free_v4l2);
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002770 mutex_unlock(&dev->lock);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002771 return ret;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002772}
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002773
2774static struct em28xx_ops v4l2_ops = {
2775 .id = EM28XX_V4L2,
2776 .name = "Em28xx v4l2 Extension",
2777 .init = em28xx_v4l2_init,
2778 .fini = em28xx_v4l2_fini,
Shuah Khana61f6812014-02-21 21:50:17 -03002779 .suspend = em28xx_v4l2_suspend,
2780 .resume = em28xx_v4l2_resume,
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002781};
2782
2783static int __init em28xx_video_register(void)
2784{
2785 return em28xx_register_extension(&v4l2_ops);
2786}
2787
2788static void __exit em28xx_video_unregister(void)
2789{
2790 em28xx_unregister_extension(&v4l2_ops);
2791}
2792
2793module_init(em28xx_video_register);
2794module_exit(em28xx_video_unregister);