blob: 5b9441889398cec4574e96175e0f31925204e982 [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
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001065 /* Make sure streaming is not already in progress for this type
1066 of filehandle (e.g. video, vbi) */
1067 rc = res_get(dev, vq->type);
1068 if (rc)
1069 return rc;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001070
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001071 if (v4l2->streaming_users == 0) {
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001072 /* First active streaming user, so allocate all the URBs */
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001073
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001074 /* Allocate the USB bandwidth */
1075 em28xx_set_alternate(dev);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001076
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001077 /* Needed, since GPIO might have disabled power of
1078 some i2c device
1079 */
1080 em28xx_wake_i2c(dev);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001081
Frank Schaeferf0e38232014-03-24 16:33:20 -03001082 v4l2->capture_type = -1;
Frank Schaefer960da932012-11-25 06:37:37 -03001083 rc = em28xx_init_usb_xfer(dev, EM28XX_ANALOG_MODE,
1084 dev->analog_xfer_bulk,
1085 EM28XX_NUM_BUFS,
1086 dev->max_pkt_size,
1087 dev->packet_multiplier,
1088 em28xx_urb_data_copy);
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -03001089 if (rc < 0)
Frank Schaefer032f1dd2013-10-10 15:31:53 -03001090 return rc;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001091
1092 /*
1093 * djh: it's not clear whether this code is still needed. I'm
1094 * leaving it in here for now entirely out of concern for
1095 * backward compatibility (the old code did it)
1096 */
1097
1098 /* Ask tuner to go to analog or radio mode */
1099 memset(&f, 0, sizeof(f));
Frank Schaefer3854b0d2014-03-24 16:33:22 -03001100 f.frequency = v4l2->frequency;
Junghak Sung2d700712015-09-22 10:30:30 -03001101 owner = (struct v4l2_fh *)vq->owner;
1102 if (owner && owner->vdev->vfl_type == VFL_TYPE_RADIO)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001103 f.type = V4L2_TUNER_RADIO;
1104 else
1105 f.type = V4L2_TUNER_ANALOG_TV;
Frank Schaeferf0e38232014-03-24 16:33:20 -03001106 v4l2_device_call_all(&v4l2->v4l2_dev,
Frank Schaefer95d26082014-03-24 16:33:09 -03001107 0, tuner, s_frequency, &f);
Mauro Carvalho Chehab13d52fe2016-01-26 06:59:39 -02001108
1109 /* Enable video stream at TV decoder */
1110 v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_stream, 1);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001111 }
1112
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001113 v4l2->streaming_users++;
Frank Schaefer032f1dd2013-10-10 15:31:53 -03001114
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001115 return rc;
1116}
1117
Hans Verkuile37559b2014-04-17 02:47:21 -03001118static void em28xx_stop_streaming(struct vb2_queue *vq)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001119{
1120 struct em28xx *dev = vb2_get_drv_priv(vq);
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001121 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001122 struct em28xx_dmaqueue *vidq = &dev->vidq;
1123 unsigned long flags = 0;
1124
1125 em28xx_videodbg("%s\n", __func__);
1126
1127 res_free(dev, vq->type);
1128
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001129 if (v4l2->streaming_users-- == 1) {
Mauro Carvalho Chehab13d52fe2016-01-26 06:59:39 -02001130 /* Disable video stream at TV decoder */
1131 v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_stream, 0);
1132
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001133 /* Last active user, so shutdown all the URBS */
1134 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
1135 }
1136
1137 spin_lock_irqsave(&dev->slock, flags);
Frank Schaefer627530c2014-08-09 06:37:20 -03001138 if (dev->usb_ctl.vid_buf != NULL) {
Junghak Sung2d700712015-09-22 10:30:30 -03001139 vb2_buffer_done(&dev->usb_ctl.vid_buf->vb.vb2_buf,
1140 VB2_BUF_STATE_ERROR);
Frank Schaefer627530c2014-08-09 06:37:20 -03001141 dev->usb_ctl.vid_buf = NULL;
1142 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001143 while (!list_empty(&vidq->active)) {
1144 struct em28xx_buffer *buf;
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001145
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001146 buf = list_entry(vidq->active.next, struct em28xx_buffer, list);
1147 list_del(&buf->list);
Junghak Sung2d700712015-09-22 10:30:30 -03001148 vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001149 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001150 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001151}
1152
Hans Verkuile37559b2014-04-17 02:47:21 -03001153void em28xx_stop_vbi_streaming(struct vb2_queue *vq)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001154{
1155 struct em28xx *dev = vb2_get_drv_priv(vq);
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001156 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001157 struct em28xx_dmaqueue *vbiq = &dev->vbiq;
1158 unsigned long flags = 0;
1159
1160 em28xx_videodbg("%s\n", __func__);
1161
1162 res_free(dev, vq->type);
1163
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001164 if (v4l2->streaming_users-- == 1) {
Mauro Carvalho Chehab13d52fe2016-01-26 06:59:39 -02001165 /* Disable video stream at TV decoder */
1166 v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_stream, 0);
1167
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001168 /* Last active user, so shutdown all the URBS */
1169 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
1170 }
1171
1172 spin_lock_irqsave(&dev->slock, flags);
Frank Schaefer627530c2014-08-09 06:37:20 -03001173 if (dev->usb_ctl.vbi_buf != NULL) {
Junghak Sung2d700712015-09-22 10:30:30 -03001174 vb2_buffer_done(&dev->usb_ctl.vbi_buf->vb.vb2_buf,
1175 VB2_BUF_STATE_ERROR);
Frank Schaefer627530c2014-08-09 06:37:20 -03001176 dev->usb_ctl.vbi_buf = NULL;
1177 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001178 while (!list_empty(&vbiq->active)) {
1179 struct em28xx_buffer *buf;
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001180
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001181 buf = list_entry(vbiq->active.next, struct em28xx_buffer, list);
1182 list_del(&buf->list);
Junghak Sung2d700712015-09-22 10:30:30 -03001183 vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001184 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001185 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001186}
1187
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001188static void
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001189buffer_queue(struct vb2_buffer *vb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001190{
Junghak Sung2d700712015-09-22 10:30:30 -03001191 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001192 struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue);
Junghak Sung2d700712015-09-22 10:30:30 -03001193 struct em28xx_buffer *buf =
1194 container_of(vbuf, struct em28xx_buffer, vb);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001195 struct em28xx_dmaqueue *vidq = &dev->vidq;
1196 unsigned long flags = 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001197
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001198 em28xx_videodbg("%s\n", __func__);
1199 buf->mem = vb2_plane_vaddr(vb, 0);
1200 buf->length = vb2_plane_size(vb, 0);
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001201
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001202 spin_lock_irqsave(&dev->slock, flags);
1203 list_add_tail(&buf->list, &vidq->active);
1204 spin_unlock_irqrestore(&dev->slock, flags);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001205}
1206
Julia Lawall1bc17712016-09-08 20:59:01 -03001207static const struct vb2_ops em28xx_video_qops = {
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001208 .queue_setup = queue_setup,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001209 .buf_prepare = buffer_prepare,
1210 .buf_queue = buffer_queue,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001211 .start_streaming = em28xx_start_analog_streaming,
1212 .stop_streaming = em28xx_stop_streaming,
1213 .wait_prepare = vb2_ops_wait_prepare,
1214 .wait_finish = vb2_ops_wait_finish,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001215};
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001216
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001217static int em28xx_vb2_setup(struct em28xx *dev)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001218{
1219 int rc;
1220 struct vb2_queue *q;
Frank Schaefer27a36df2014-03-24 16:33:13 -03001221 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001222
1223 /* Setup Videobuf2 for Video capture */
Frank Schaefer27a36df2014-03-24 16:33:13 -03001224 q = &v4l2->vb_vidq;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001225 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Mauro Carvalho Chehabef85cd92013-01-06 00:34:22 -02001226 q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
Sakari Ailusade48682014-02-25 19:12:19 -03001227 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001228 q->drv_priv = dev;
1229 q->buf_struct_size = sizeof(struct em28xx_buffer);
1230 q->ops = &em28xx_video_qops;
1231 q->mem_ops = &vb2_vmalloc_memops;
1232
1233 rc = vb2_queue_init(q);
1234 if (rc < 0)
1235 return rc;
1236
1237 /* Setup Videobuf2 for VBI capture */
Frank Schaefer27a36df2014-03-24 16:33:13 -03001238 q = &v4l2->vb_vbiq;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001239 q->type = V4L2_BUF_TYPE_VBI_CAPTURE;
1240 q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR;
Sakari Ailusade48682014-02-25 19:12:19 -03001241 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001242 q->drv_priv = dev;
1243 q->buf_struct_size = sizeof(struct em28xx_buffer);
1244 q->ops = &em28xx_vbi_qops;
1245 q->mem_ops = &vb2_vmalloc_memops;
1246
1247 rc = vb2_queue_init(q);
1248 if (rc < 0)
1249 return rc;
1250
1251 return 0;
1252}
1253
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001254/********************* v4l2 interface **************************************/
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001255
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001256static void video_mux(struct em28xx *dev, int index)
1257{
Frank Schaefer95d26082014-03-24 16:33:09 -03001258 struct v4l2_device *v4l2_dev = &dev->v4l2->v4l2_dev;
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001259
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001260 dev->ctl_input = index;
1261 dev->ctl_ainput = INPUT(index)->amux;
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001262 dev->ctl_aoutput = INPUT(index)->aout;
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001263
Mauro Carvalho Chehabe879b8e2008-11-20 13:39:39 -03001264 if (!dev->ctl_aoutput)
1265 dev->ctl_aoutput = EM28XX_AOUT_MASTER;
1266
Frank Schaefer95d26082014-03-24 16:33:09 -03001267 v4l2_device_call_all(v4l2_dev, 0, video, s_routing,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001268 INPUT(index)->vmux, 0, 0);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001269
Mauro Carvalho Chehab505b6d02008-11-25 09:39:50 -03001270 if (dev->board.has_msp34xx) {
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001271 if (dev->i2s_speed) {
Frank Schaefer95d26082014-03-24 16:33:09 -03001272 v4l2_device_call_all(v4l2_dev, 0, audio,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001273 s_i2s_clock_freq, dev->i2s_speed);
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001274 }
Hans Verkuil2474ed42006-03-19 12:35:57 -03001275 /* Note: this is msp3400 specific */
Frank Schaefer95d26082014-03-24 16:33:09 -03001276 v4l2_device_call_all(v4l2_dev, 0, audio, s_routing,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001277 dev->ctl_ainput,
1278 MSP_OUTPUT(MSP_SC_IN_DSP_SCART1), 0);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001279 }
Mauro Carvalho Chehab539c96d2008-01-05 09:53:54 -03001280
Vitaly Wool2bd1d9e2009-03-04 08:27:52 -03001281 if (dev->board.adecoder != EM28XX_NOADECODER) {
Frank Schaefer95d26082014-03-24 16:33:09 -03001282 v4l2_device_call_all(v4l2_dev, 0, audio, s_routing,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001283 dev->ctl_ainput, dev->ctl_aoutput, 0);
Vitaly Wool2bd1d9e2009-03-04 08:27:52 -03001284 }
1285
Mauro Carvalho Chehab00b87302008-02-06 18:34:13 -03001286 em28xx_audio_analog_set(dev);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001287}
1288
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001289static void em28xx_ctrl_notify(struct v4l2_ctrl *ctrl, void *priv)
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001290{
Hans Verkuil081b9452012-09-07 05:43:59 -03001291 struct em28xx *dev = priv;
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001292
Hans Verkuil081b9452012-09-07 05:43:59 -03001293 /*
1294 * In the case of non-AC97 volume controls, we still need
1295 * to do some setups at em28xx, in order to mute/unmute
1296 * and to adjust audio volume. However, the value ranges
1297 * should be checked by the corresponding V4L subdriver.
1298 */
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001299 switch (ctrl->id) {
1300 case V4L2_CID_AUDIO_MUTE:
Hans Verkuil081b9452012-09-07 05:43:59 -03001301 dev->mute = ctrl->val;
1302 em28xx_audio_analog_set(dev);
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001303 break;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001304 case V4L2_CID_AUDIO_VOLUME:
Hans Verkuil081b9452012-09-07 05:43:59 -03001305 dev->volume = ctrl->val;
1306 em28xx_audio_analog_set(dev);
1307 break;
1308 }
1309}
1310
1311static int em28xx_s_ctrl(struct v4l2_ctrl *ctrl)
1312{
Frank Schaeferabc13082014-03-24 16:33:10 -03001313 struct em28xx_v4l2 *v4l2 =
1314 container_of(ctrl->handler, struct em28xx_v4l2, ctrl_handler);
1315 struct em28xx *dev = v4l2->dev;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001316 int ret = -EINVAL;
Hans Verkuil081b9452012-09-07 05:43:59 -03001317
1318 switch (ctrl->id) {
1319 case V4L2_CID_AUDIO_MUTE:
1320 dev->mute = ctrl->val;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001321 ret = em28xx_audio_analog_set(dev);
Hans Verkuil081b9452012-09-07 05:43:59 -03001322 break;
1323 case V4L2_CID_AUDIO_VOLUME:
1324 dev->volume = ctrl->val;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001325 ret = em28xx_audio_analog_set(dev);
1326 break;
1327 case V4L2_CID_CONTRAST:
1328 ret = em28xx_write_reg(dev, EM28XX_R20_YGAIN, ctrl->val);
1329 break;
1330 case V4L2_CID_BRIGHTNESS:
1331 ret = em28xx_write_reg(dev, EM28XX_R21_YOFFSET, ctrl->val);
1332 break;
1333 case V4L2_CID_SATURATION:
1334 ret = em28xx_write_reg(dev, EM28XX_R22_UVGAIN, ctrl->val);
1335 break;
1336 case V4L2_CID_BLUE_BALANCE:
1337 ret = em28xx_write_reg(dev, EM28XX_R23_UOFFSET, ctrl->val);
1338 break;
1339 case V4L2_CID_RED_BALANCE:
1340 ret = em28xx_write_reg(dev, EM28XX_R24_VOFFSET, ctrl->val);
1341 break;
1342 case V4L2_CID_SHARPNESS:
1343 ret = em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, ctrl->val);
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001344 break;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001345 }
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001346
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001347 return (ret < 0) ? ret : 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001348}
1349
Fengguang Wu8068eb82014-01-07 12:50:47 -03001350static const struct v4l2_ctrl_ops em28xx_ctrl_ops = {
Hans Verkuil081b9452012-09-07 05:43:59 -03001351 .s_ctrl = em28xx_s_ctrl,
1352};
1353
Frank Schaefer6b09a212013-02-10 16:05:12 -03001354static void size_to_scale(struct em28xx *dev,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001355 unsigned int width, unsigned int height,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001356 unsigned int *hscale, unsigned int *vscale)
1357{
Mauro Carvalho Chehab55699962009-07-13 20:15:02 -03001358 unsigned int maxw = norm_maxw(dev);
1359 unsigned int maxh = norm_maxh(dev);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001360
1361 *hscale = (((unsigned long)maxw) << 12) / width - 4096L;
Frank Schaefer81685322013-02-10 16:05:11 -03001362 if (*hscale > EM28XX_HVSCALE_MAX)
1363 *hscale = EM28XX_HVSCALE_MAX;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001364
1365 *vscale = (((unsigned long)maxh) << 12) / height - 4096L;
Frank Schaefer81685322013-02-10 16:05:11 -03001366 if (*vscale > EM28XX_HVSCALE_MAX)
1367 *vscale = EM28XX_HVSCALE_MAX;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001368}
1369
Frank Schaeferb8374132013-02-10 16:05:13 -03001370static void scale_to_size(struct em28xx *dev,
1371 unsigned int hscale, unsigned int vscale,
1372 unsigned int *width, unsigned int *height)
1373{
1374 unsigned int maxw = norm_maxw(dev);
1375 unsigned int maxh = norm_maxh(dev);
1376
1377 *width = (((unsigned long)maxw) << 12) / (hscale + 4096L);
1378 *height = (((unsigned long)maxh) << 12) / (vscale + 4096L);
Mauro Carvalho Chehab0962a762016-01-29 14:05:11 -02001379
1380 /* Don't let width or height to be zero */
1381 if (*width < 1)
1382 *width = 1;
1383 if (*height < 1)
1384 *height = 1;
Frank Schaeferb8374132013-02-10 16:05:13 -03001385}
1386
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001387/* ------------------------------------------------------------------
1388 IOCTL vidioc handling
1389 ------------------------------------------------------------------*/
1390
Hans Verkuil78b526a2008-05-28 12:16:41 -03001391static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001392 struct v4l2_format *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001393{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001394 struct em28xx *dev = video_drvdata(file);
Frank Schaefer753aee72014-03-24 16:33:14 -03001395 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001396
Frank Schaefer753aee72014-03-24 16:33:14 -03001397 f->fmt.pix.width = v4l2->width;
1398 f->fmt.pix.height = v4l2->height;
Frank Schaefer06e20672014-03-24 16:33:17 -03001399 f->fmt.pix.pixelformat = v4l2->format->fourcc;
1400 f->fmt.pix.bytesperline = (v4l2->width * v4l2->format->depth + 7) >> 3;
Frank Schaefer753aee72014-03-24 16:33:14 -03001401 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * v4l2->height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001402 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
1403
1404 /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */
Frank Schaefer58159172014-03-24 16:33:18 -03001405 if (v4l2->progressive)
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -03001406 f->fmt.pix.field = V4L2_FIELD_NONE;
1407 else
Frank Schaefer58159172014-03-24 16:33:18 -03001408 f->fmt.pix.field = v4l2->interlaced_fieldmode ?
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001409 V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001410 return 0;
1411}
1412
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001413static struct em28xx_fmt *format_by_fourcc(unsigned int fourcc)
1414{
1415 unsigned int i;
1416
1417 for (i = 0; i < ARRAY_SIZE(format); i++)
1418 if (format[i].fourcc == fourcc)
1419 return &format[i];
1420
1421 return NULL;
1422}
1423
Hans Verkuil78b526a2008-05-28 12:16:41 -03001424static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001425 struct v4l2_format *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001426{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001427 struct em28xx *dev = video_drvdata(file);
Frank Schaefer58159172014-03-24 16:33:18 -03001428 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Trent Piephoccb83402009-05-30 21:45:46 -03001429 unsigned int width = f->fmt.pix.width;
1430 unsigned int height = f->fmt.pix.height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001431 unsigned int maxw = norm_maxw(dev);
1432 unsigned int maxh = norm_maxh(dev);
1433 unsigned int hscale, vscale;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001434 struct em28xx_fmt *fmt;
1435
1436 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
1437 if (!fmt) {
Mauro Carvalho Chehab8e7c0fc2018-09-13 23:22:40 -04001438 fmt = &format[0];
1439 em28xx_videodbg("Fourcc format (%08x) invalid. Using default (%08x).\n",
1440 f->fmt.pix.pixelformat, fmt->fourcc);
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001441 }
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001442
Mauro Carvalho Chehab55699962009-07-13 20:15:02 -03001443 if (dev->board.is_em2800) {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001444 /* the em2800 can only scale down to 50% */
Trent Piephoccb83402009-05-30 21:45:46 -03001445 height = height > (3 * maxh / 4) ? maxh : maxh / 2;
1446 width = width > (3 * maxw / 4) ? maxw : maxw / 2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001447 /*
1448 * MaxPacketSize for em2800 is too small to capture at full
1449 * resolution use half of maxw as the scaler can only scale
1450 * to 50%
1451 */
Sascha Sommer1020d132012-01-08 16:54:28 -03001452 if (width == maxw && height == maxh)
1453 width /= 2;
Trent Piephoccb83402009-05-30 21:45:46 -03001454 } else {
1455 /* width must even because of the YUYV format
1456 height must be even because of interlacing */
Devin Heitmuellere3ba4d32009-09-15 00:18:06 -03001457 v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh,
1458 1, 0);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001459 }
Mauro Carvalho Chehab0962a762016-01-29 14:05:11 -02001460 /* Avoid division by zero at size_to_scale */
1461 if (width < 1)
1462 width = 1;
1463 if (height < 1)
1464 height = 1;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001465
Frank Schaefer6b09a212013-02-10 16:05:12 -03001466 size_to_scale(dev, width, height, &hscale, &vscale);
Hans Verkuil46f85972013-03-30 05:31:42 -03001467 scale_to_size(dev, hscale, vscale, &width, &height);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001468
1469 f->fmt.pix.width = width;
1470 f->fmt.pix.height = height;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001471 f->fmt.pix.pixelformat = fmt->fourcc;
Hans Verkuile6066db2013-02-06 08:14:47 -03001472 f->fmt.pix.bytesperline = (width * fmt->depth + 7) >> 3;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001473 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001474 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
Frank Schaefer58159172014-03-24 16:33:18 -03001475 if (v4l2->progressive)
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -03001476 f->fmt.pix.field = V4L2_FIELD_NONE;
1477 else
Frank Schaefer58159172014-03-24 16:33:18 -03001478 f->fmt.pix.field = v4l2->interlaced_fieldmode ?
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -03001479 V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
Alban Browaeys51dd4d72013-07-16 19:06:46 -03001480 f->fmt.pix.priv = 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001481
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001482 return 0;
1483}
1484
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001485static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc,
1486 unsigned width, unsigned height)
1487{
1488 struct em28xx_fmt *fmt;
Frank Schaefer753aee72014-03-24 16:33:14 -03001489 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001490
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001491 fmt = format_by_fourcc(fourcc);
1492 if (!fmt)
1493 return -EINVAL;
1494
Frank Schaefer06e20672014-03-24 16:33:17 -03001495 v4l2->format = fmt;
Frank Schaefer753aee72014-03-24 16:33:14 -03001496 v4l2->width = width;
1497 v4l2->height = height;
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001498
1499 /* set new image size */
Frank Schaefer753aee72014-03-24 16:33:14 -03001500 size_to_scale(dev, v4l2->width, v4l2->height,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001501 &v4l2->hscale, &v4l2->vscale);
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001502
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001503 em28xx_resolution_set(dev);
1504
1505 return 0;
1506}
1507
Hans Verkuil78b526a2008-05-28 12:16:41 -03001508static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001509 struct v4l2_format *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001510{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001511 struct em28xx *dev = video_drvdata(file);
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001512 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001513
Mauro Carvalho Chehabc7854c22014-09-19 13:02:12 -03001514 if (vb2_is_busy(&v4l2->vb_vidq))
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001515 return -EBUSY;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001516
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001517 vidioc_try_fmt_vid_cap(file, priv, f);
1518
Hans Verkuil0499a5a2010-09-26 07:34:45 -03001519 return em28xx_set_video_format(dev, f->fmt.pix.pixelformat,
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001520 f->fmt.pix.width, f->fmt.pix.height);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001521}
1522
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001523static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
1524{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001525 struct em28xx *dev = video_drvdata(file);
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001526
Frank Schaefer52faaf72014-03-24 16:33:16 -03001527 *norm = dev->v4l2->norm;
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001528
1529 return 0;
1530}
1531
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001532static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm)
1533{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001534 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001535
Frank Schaefer95d26082014-03-24 16:33:09 -03001536 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, video, querystd, norm);
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001537
1538 return 0;
1539}
1540
Hans Verkuil314527a2013-03-15 06:10:40 -03001541static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001542{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001543 struct em28xx *dev = video_drvdata(file);
Frank Schaefer753aee72014-03-24 16:33:14 -03001544 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001545 struct v4l2_format f;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001546
Frank Schaefer52faaf72014-03-24 16:33:16 -03001547 if (norm == v4l2->norm)
Hans Verkuild8c95c02012-09-07 07:31:54 -03001548 return 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001549
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001550 if (v4l2->streaming_users > 0)
Hans Verkuild8c95c02012-09-07 07:31:54 -03001551 return -EBUSY;
Hans Verkuild8c95c02012-09-07 07:31:54 -03001552
Frank Schaefer52faaf72014-03-24 16:33:16 -03001553 v4l2->norm = norm;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001554
1555 /* Adjusts width/height, if needed */
Hans Verkuild8c95c02012-09-07 07:31:54 -03001556 f.fmt.pix.width = 720;
Hans Verkuil314527a2013-03-15 06:10:40 -03001557 f.fmt.pix.height = (norm & V4L2_STD_525_60) ? 480 : 576;
Hans Verkuil78b526a2008-05-28 12:16:41 -03001558 vidioc_try_fmt_vid_cap(file, priv, &f);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001559
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001560 /* set new image size */
Frank Schaefer753aee72014-03-24 16:33:14 -03001561 v4l2->width = f.fmt.pix.width;
1562 v4l2->height = f.fmt.pix.height;
1563 size_to_scale(dev, v4l2->width, v4l2->height,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001564 &v4l2->hscale, &v4l2->vscale);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001565
1566 em28xx_resolution_set(dev);
Laurent Pinchart8774bed2014-04-28 16:53:01 -03001567 v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_std, v4l2->norm);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001568
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001569 return 0;
1570}
1571
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001572static int vidioc_g_parm(struct file *file, void *priv,
1573 struct v4l2_streamparm *p)
1574{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001575 struct em28xx *dev = video_drvdata(file);
Frank Schaefer52faaf72014-03-24 16:33:16 -03001576 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001577 int rc = 0;
1578
Hans Verkuil86ff7f12012-09-07 06:16:03 -03001579 p->parm.capture.readbuffers = EM28XX_MIN_BUF;
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001580 if (dev->board.is_webcam)
Frank Schaefer52faaf72014-03-24 16:33:16 -03001581 rc = v4l2_device_call_until_err(&v4l2->v4l2_dev, 0,
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001582 video, g_parm, p);
1583 else
Frank Schaefer52faaf72014-03-24 16:33:16 -03001584 v4l2_video_std_frame_period(v4l2->norm,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001585 &p->parm.capture.timeperframe);
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001586
1587 return rc;
1588}
1589
1590static int vidioc_s_parm(struct file *file, void *priv,
1591 struct v4l2_streamparm *p)
1592{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001593 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001594
Hans Verkuil86ff7f12012-09-07 06:16:03 -03001595 p->parm.capture.readbuffers = EM28XX_MIN_BUF;
Frank Schaefer95d26082014-03-24 16:33:09 -03001596 return v4l2_device_call_until_err(&dev->v4l2->v4l2_dev,
1597 0, video, s_parm, p);
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001598}
1599
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001600static int vidioc_enum_input(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001601 struct v4l2_input *i)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001602{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001603 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001604 unsigned int n;
1605
1606 n = i->index;
1607 if (n >= MAX_EM28XX_INPUT)
1608 return -EINVAL;
1609 if (0 == INPUT(n)->type)
1610 return -EINVAL;
1611
1612 i->index = n;
1613 i->type = V4L2_INPUT_TYPE_CAMERA;
1614
1615 strcpy(i->name, iname[INPUT(n)->type]);
1616
Mauro Carvalho Chehabd83a96a2016-01-27 09:24:29 -02001617 if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type))
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001618 i->type = V4L2_INPUT_TYPE_TUNER;
1619
Hans Verkuild4352f32015-03-09 13:34:06 -03001620 i->std = dev->v4l2->vdev.tvnorms;
Hans Verkuild8c95c02012-09-07 07:31:54 -03001621 /* webcams do not have the STD API */
1622 if (dev->board.is_webcam)
1623 i->capabilities = 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001624
1625 return 0;
1626}
1627
1628static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1629{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001630 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001631
1632 *i = dev->ctl_input;
1633
1634 return 0;
1635}
1636
1637static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
1638{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001639 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001640
1641 if (i >= MAX_EM28XX_INPUT)
1642 return -EINVAL;
1643 if (0 == INPUT(i)->type)
1644 return -EINVAL;
1645
Ezequiel García96371fc2012-03-23 18:09:34 -03001646 video_mux(dev, i);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001647 return 0;
1648}
1649
1650static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
1651{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001652 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001653
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001654 switch (a->index) {
1655 case EM28XX_AMUX_VIDEO:
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001656 strcpy(a->name, "Television");
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001657 break;
1658 case EM28XX_AMUX_LINE_IN:
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001659 strcpy(a->name, "Line In");
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001660 break;
1661 case EM28XX_AMUX_VIDEO2:
1662 strcpy(a->name, "Television alt");
1663 break;
1664 case EM28XX_AMUX_PHONE:
1665 strcpy(a->name, "Phone");
1666 break;
1667 case EM28XX_AMUX_MIC:
1668 strcpy(a->name, "Mic");
1669 break;
1670 case EM28XX_AMUX_CD:
1671 strcpy(a->name, "CD");
1672 break;
1673 case EM28XX_AMUX_AUX:
1674 strcpy(a->name, "Aux");
1675 break;
1676 case EM28XX_AMUX_PCM_OUT:
1677 strcpy(a->name, "PCM");
1678 break;
1679 default:
1680 return -EINVAL;
1681 }
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001682
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001683 a->index = dev->ctl_ainput;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001684 a->capability = V4L2_AUDCAP_STEREO;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001685
1686 return 0;
1687}
1688
Hans Verkuil0e8025b92012-09-04 11:59:31 -03001689static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001690{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001691 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001692
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03001693 if (a->index >= MAX_EM28XX_INPUT)
1694 return -EINVAL;
1695 if (0 == INPUT(a->index)->type)
1696 return -EINVAL;
1697
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001698 dev->ctl_ainput = INPUT(a->index)->amux;
1699 dev->ctl_aoutput = INPUT(a->index)->aout;
Mauro Carvalho Chehabe879b8e2008-11-20 13:39:39 -03001700
1701 if (!dev->ctl_aoutput)
1702 dev->ctl_aoutput = EM28XX_AOUT_MASTER;
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001703
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001704 return 0;
1705}
1706
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001707static int vidioc_g_tuner(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001708 struct v4l2_tuner *t)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001709{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001710 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001711
1712 if (0 != t->index)
1713 return -EINVAL;
1714
1715 strcpy(t->name, "Tuner");
1716
Frank Schaefer95d26082014-03-24 16:33:09 -03001717 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, g_tuner, t);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001718 return 0;
1719}
1720
1721static int vidioc_s_tuner(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001722 const struct v4l2_tuner *t)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001723{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001724 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001725
1726 if (0 != t->index)
1727 return -EINVAL;
1728
Frank Schaefer95d26082014-03-24 16:33:09 -03001729 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, s_tuner, t);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001730 return 0;
1731}
1732
1733static int vidioc_g_frequency(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001734 struct v4l2_frequency *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001735{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001736 struct em28xx *dev = video_drvdata(file);
Frank Schaefer3854b0d2014-03-24 16:33:22 -03001737 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001738
Hans Verkuil20deebf2012-09-06 10:07:25 -03001739 if (0 != f->tuner)
1740 return -EINVAL;
1741
Frank Schaefer3854b0d2014-03-24 16:33:22 -03001742 f->frequency = v4l2->frequency;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001743 return 0;
1744}
1745
1746static int vidioc_s_frequency(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001747 const struct v4l2_frequency *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001748{
Frank Schaefer95d26082014-03-24 16:33:09 -03001749 struct v4l2_frequency new_freq = *f;
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001750 struct em28xx *dev = video_drvdata(file);
Frank Schaefer95d26082014-03-24 16:33:09 -03001751 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001752
1753 if (0 != f->tuner)
1754 return -EINVAL;
1755
Frank Schaefer95d26082014-03-24 16:33:09 -03001756 v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, s_frequency, f);
1757 v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, g_frequency, &new_freq);
Frank Schaefer3854b0d2014-03-24 16:33:22 -03001758 v4l2->frequency = new_freq.frequency;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001759
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001760 return 0;
1761}
1762
Hans Verkuilcd634f12013-03-27 08:04:23 -03001763#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuil96b03d22013-04-06 06:16:58 -03001764static int vidioc_g_chip_info(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001765 struct v4l2_dbg_chip_info *chip)
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001766{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001767 struct em28xx *dev = video_drvdata(file);
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001768
1769 if (chip->match.addr > 1)
1770 return -EINVAL;
1771 if (chip->match.addr == 1)
1772 strlcpy(chip->name, "ac97", sizeof(chip->name));
1773 else
Frank Schaefer95d26082014-03-24 16:33:09 -03001774 strlcpy(chip->name,
1775 dev->v4l2->v4l2_dev.name, sizeof(chip->name));
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001776 return 0;
1777}
1778
Frank Schaefer35deba32013-02-07 13:39:19 -03001779static int em28xx_reg_len(int reg)
1780{
1781 switch (reg) {
1782 case EM28XX_R40_AC97LSB:
1783 case EM28XX_R30_HSCALELOW:
1784 case EM28XX_R32_VSCALELOW:
1785 return 2;
1786 default:
1787 return 1;
1788 }
1789}
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001790
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001791static int vidioc_g_register(struct file *file, void *priv,
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001792 struct v4l2_dbg_register *reg)
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001793{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001794 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001795 int ret;
1796
Hans Verkuilabca2052013-05-29 06:59:35 -03001797 if (reg->match.addr > 1)
1798 return -EINVAL;
1799 if (reg->match.addr) {
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001800 ret = em28xx_read_ac97(dev, reg->reg);
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001801 if (ret < 0)
1802 return ret;
1803
1804 reg->val = ret;
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001805 reg->size = 1;
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001806 return 0;
1807 }
1808
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001809 /* Match host */
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001810 reg->size = em28xx_reg_len(reg->reg);
1811 if (reg->size == 1) {
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001812 ret = em28xx_read_reg(dev, reg->reg);
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001813
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001814 if (ret < 0)
1815 return ret;
1816
1817 reg->val = ret;
1818 } else {
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001819 __le16 val = 0;
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001820
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001821 ret = dev->em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001822 reg->reg, (char *)&val, 2);
1823 if (ret < 0)
1824 return ret;
1825
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001826 reg->val = le16_to_cpu(val);
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001827 }
1828
1829 return 0;
1830}
1831
1832static int vidioc_s_register(struct file *file, void *priv,
Hans Verkuil977ba3b2013-03-24 08:28:46 -03001833 const struct v4l2_dbg_register *reg)
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001834{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001835 struct em28xx *dev = video_drvdata(file);
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001836 __le16 buf;
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001837
Hans Verkuilabca2052013-05-29 06:59:35 -03001838 if (reg->match.addr > 1)
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001839 return -EINVAL;
Hans Verkuilabca2052013-05-29 06:59:35 -03001840 if (reg->match.addr)
1841 return em28xx_write_ac97(dev, reg->reg, reg->val);
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001842
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001843 /* Match host */
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001844 buf = cpu_to_le16(reg->val);
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001845
Hans Verkuil0499a5a2010-09-26 07:34:45 -03001846 return em28xx_write_regs(dev, reg->reg, (char *)&buf,
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001847 em28xx_reg_len(reg->reg));
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001848}
1849#endif
1850
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001851static int vidioc_querycap(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001852 struct v4l2_capability *cap)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001853{
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001854 struct video_device *vdev = video_devdata(file);
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001855 struct em28xx *dev = video_drvdata(file);
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001856 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001857
1858 strlcpy(cap->driver, "em28xx", sizeof(cap->driver));
1859 strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card));
Thierry MERLEcb977162009-01-20 18:01:33 -03001860 usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001861
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001862 if (vdev->vfl_type == VFL_TYPE_GRABBER)
1863 cap->device_caps = V4L2_CAP_READWRITE |
1864 V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1865 else if (vdev->vfl_type == VFL_TYPE_RADIO)
1866 cap->device_caps = V4L2_CAP_RADIO;
1867 else
Hans Verkuil1d179ee2012-09-07 08:45:10 -03001868 cap->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE;
Devin Heitmueller04146142009-09-11 00:08:44 -03001869
Frank Schaefer920f1e42014-09-13 05:52:21 -03001870 if (dev->int_audio_type != EM28XX_INT_AUDIO_NONE)
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001871 cap->device_caps |= V4L2_CAP_AUDIO;
Mauro Carvalho Chehab6c428b52009-08-04 19:52:37 -03001872
Mauro Carvalho Chehabed086312008-01-24 06:59:20 -03001873 if (dev->tuner_type != TUNER_ABSENT)
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001874 cap->device_caps |= V4L2_CAP_TUNER;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001875
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001876 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS |
1877 V4L2_CAP_READWRITE | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
Hans Verkuild4352f32015-03-09 13:34:06 -03001878 if (video_is_registered(&v4l2->vbi_dev))
Hans Verkuil1d179ee2012-09-07 08:45:10 -03001879 cap->capabilities |= V4L2_CAP_VBI_CAPTURE;
Hans Verkuild4352f32015-03-09 13:34:06 -03001880 if (video_is_registered(&v4l2->radio_dev))
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001881 cap->capabilities |= V4L2_CAP_RADIO;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001882 return 0;
1883}
1884
Hans Verkuil78b526a2008-05-28 12:16:41 -03001885static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001886 struct v4l2_fmtdesc *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001887{
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001888 if (unlikely(f->index >= ARRAY_SIZE(format)))
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001889 return -EINVAL;
1890
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001891 strlcpy(f->description, format[f->index].name, sizeof(f->description));
1892 f->pixelformat = format[f->index].fourcc;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001893
1894 return 0;
1895}
1896
Mauro Carvalho Chehab1c5c5062011-10-16 13:52:43 -02001897static int vidioc_enum_framesizes(struct file *file, void *priv,
1898 struct v4l2_frmsizeenum *fsize)
1899{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001900 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab1c5c5062011-10-16 13:52:43 -02001901 struct em28xx_fmt *fmt;
1902 unsigned int maxw = norm_maxw(dev);
1903 unsigned int maxh = norm_maxh(dev);
1904
1905 fmt = format_by_fourcc(fsize->pixel_format);
1906 if (!fmt) {
1907 em28xx_videodbg("Fourcc format (%08x) invalid.\n",
1908 fsize->pixel_format);
1909 return -EINVAL;
1910 }
1911
1912 if (dev->board.is_em2800) {
1913 if (fsize->index > 1)
1914 return -EINVAL;
1915 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
1916 fsize->discrete.width = maxw / (1 + fsize->index);
1917 fsize->discrete.height = maxh / (1 + fsize->index);
1918 return 0;
1919 }
1920
1921 if (fsize->index != 0)
1922 return -EINVAL;
1923
1924 /* Report a continuous range */
1925 fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
Frank Schaefer6c3598e2013-02-10 16:05:14 -03001926 scale_to_size(dev, EM28XX_HVSCALE_MAX, EM28XX_HVSCALE_MAX,
1927 &fsize->stepwise.min_width, &fsize->stepwise.min_height);
1928 if (fsize->stepwise.min_width < 48)
1929 fsize->stepwise.min_width = 48;
1930 if (fsize->stepwise.min_height < 38)
1931 fsize->stepwise.min_height = 38;
Mauro Carvalho Chehab1c5c5062011-10-16 13:52:43 -02001932 fsize->stepwise.max_width = maxw;
1933 fsize->stepwise.max_height = maxh;
1934 fsize->stepwise.step_width = 1;
1935 fsize->stepwise.step_height = 1;
1936 return 0;
1937}
1938
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001939/* RAW VBI ioctls */
1940
1941static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
1942 struct v4l2_format *format)
1943{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001944 struct em28xx *dev = video_drvdata(file);
Frank Schaefer753aee72014-03-24 16:33:14 -03001945 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001946
Frank Schaefer753aee72014-03-24 16:33:14 -03001947 format->fmt.vbi.samples_per_line = v4l2->vbi_width;
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001948 format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
1949 format->fmt.vbi.offset = 0;
1950 format->fmt.vbi.flags = 0;
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001951 format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
Frank Schaefer753aee72014-03-24 16:33:14 -03001952 format->fmt.vbi.count[0] = v4l2->vbi_height;
1953 format->fmt.vbi.count[1] = v4l2->vbi_height;
Hans Verkuil2a221d32012-09-07 08:51:32 -03001954 memset(format->fmt.vbi.reserved, 0, sizeof(format->fmt.vbi.reserved));
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001955
1956 /* Varies by video standard (NTSC, PAL, etc.) */
Frank Schaefer52faaf72014-03-24 16:33:16 -03001957 if (v4l2->norm & V4L2_STD_525_60) {
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001958 /* NTSC */
1959 format->fmt.vbi.start[0] = 10;
1960 format->fmt.vbi.start[1] = 273;
Frank Schaefer52faaf72014-03-24 16:33:16 -03001961 } else if (v4l2->norm & V4L2_STD_625_50) {
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001962 /* PAL */
1963 format->fmt.vbi.start[0] = 6;
1964 format->fmt.vbi.start[1] = 318;
1965 }
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001966
1967 return 0;
1968}
1969
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001970/* ----------------------------------------------------------- */
1971/* RADIO ESPECIFIC IOCTLS */
1972/* ----------------------------------------------------------- */
1973
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001974static int radio_g_tuner(struct file *file, void *priv,
1975 struct v4l2_tuner *t)
1976{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001977 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001978
1979 if (unlikely(t->index > 0))
1980 return -EINVAL;
1981
1982 strcpy(t->name, "Radio");
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001983
Frank Schaefer95d26082014-03-24 16:33:09 -03001984 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, g_tuner, t);
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001985
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001986 return 0;
1987}
1988
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001989static int radio_s_tuner(struct file *file, void *priv,
Hans Verkuil2f73c7c2013-03-15 06:10:06 -03001990 const struct v4l2_tuner *t)
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001991{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001992 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001993
1994 if (0 != t->index)
1995 return -EINVAL;
1996
Frank Schaefer95d26082014-03-24 16:33:09 -03001997 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, s_tuner, t);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001998
1999 return 0;
2000}
2001
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002002/*
Frank Schaefer95d26082014-03-24 16:33:09 -03002003 * em28xx_free_v4l2() - Free struct em28xx_v4l2
2004 *
2005 * @ref: struct kref for struct em28xx_v4l2
2006 *
2007 * Called when all users of struct em28xx_v4l2 are gone
2008 */
Mauro Carvalho Chehabf472c0b2014-05-23 14:29:44 -03002009static void em28xx_free_v4l2(struct kref *ref)
Frank Schaefer95d26082014-03-24 16:33:09 -03002010{
2011 struct em28xx_v4l2 *v4l2 = container_of(ref, struct em28xx_v4l2, ref);
2012
Frank Schaeferabc13082014-03-24 16:33:10 -03002013 v4l2->dev->v4l2 = NULL;
Frank Schaefer95d26082014-03-24 16:33:09 -03002014 kfree(v4l2);
2015}
2016
2017/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002018 * em28xx_v4l2_open()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002019 * inits the device and starts isoc transfer
2020 */
Hans Verkuilbec43662008-12-30 06:58:20 -03002021static int em28xx_v4l2_open(struct file *filp)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002022{
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02002023 struct video_device *vdev = video_devdata(filp);
2024 struct em28xx *dev = video_drvdata(filp);
Frank Schaefer95d26082014-03-24 16:33:09 -03002025 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02002026 enum v4l2_buf_type fh_type = 0;
Frank Schaefer3c0f90e2014-07-25 14:48:57 -03002027 int ret;
Markus Rechberger9c755412005-11-08 21:37:52 -08002028
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02002029 switch (vdev->vfl_type) {
2030 case VFL_TYPE_GRABBER:
2031 fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2032 break;
2033 case VFL_TYPE_VBI:
2034 fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
2035 break;
Frank Schaefer4e170242014-01-12 13:24:18 -03002036 case VFL_TYPE_RADIO:
2037 break;
2038 default:
2039 return -EINVAL;
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02002040 }
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002041
Frank Schaefer8e2c8712014-09-18 17:55:45 -03002042 em28xx_videodbg("open dev=%s type=%s users=%d\n",
2043 video_device_node_name(vdev), v4l2_type_names[fh_type],
2044 v4l2->users);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002045
Hans Verkuil876cb142012-06-23 08:12:47 -03002046 if (mutex_lock_interruptible(&dev->lock))
2047 return -ERESTARTSYS;
Frank Schaefer3c0f90e2014-07-25 14:48:57 -03002048
2049 ret = v4l2_fh_open(filp);
2050 if (ret) {
2051 em28xx_errdev("%s: v4l2_fh_open() returned error %d\n",
2052 __func__, ret);
Hans Verkuil876cb142012-06-23 08:12:47 -03002053 mutex_unlock(&dev->lock);
Frank Schaefer3c0f90e2014-07-25 14:48:57 -03002054 return ret;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002055 }
2056
Frank Schaefer8e2c8712014-09-18 17:55:45 -03002057 if (v4l2->users == 0) {
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03002058 em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002059
Frank Schaefer4e170242014-01-12 13:24:18 -03002060 if (vdev->vfl_type != VFL_TYPE_RADIO)
2061 em28xx_resolution_set(dev);
2062
2063 /*
2064 * Needed, since GPIO might have disabled power
2065 * of some i2c devices
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03002066 */
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002067 em28xx_wake_i2c(dev);
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02002068 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002069
2070 if (vdev->vfl_type == VFL_TYPE_RADIO) {
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002071 em28xx_videodbg("video_open: setting radio device\n");
Frank Schaefer95d26082014-03-24 16:33:09 -03002072 v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, s_radio);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002073 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002074
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002075 kref_get(&dev->ref);
Frank Schaefer95d26082014-03-24 16:33:09 -03002076 kref_get(&v4l2->ref);
Frank Schaefer8e2c8712014-09-18 17:55:45 -03002077 v4l2->users++;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002078
Hans Verkuil876cb142012-06-23 08:12:47 -03002079 mutex_unlock(&dev->lock);
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03002080
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002081 return 0;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002082}
2083
2084/*
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002085 * em28xx_v4l2_fini()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002086 * unregisters the v4l2,i2c and usb devices
2087 * called when the device gets disconected or at module unload
2088*/
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002089static int em28xx_v4l2_fini(struct em28xx *dev)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002090{
Frank Schaefer95d26082014-03-24 16:33:09 -03002091 struct em28xx_v4l2 *v4l2 = dev->v4l2;
2092
Mauro Carvalho Chehab822b8de2014-01-06 05:27:47 -03002093 if (dev->is_audio_only) {
2094 /* Shouldn't initialize IR for this interface */
2095 return 0;
2096 }
2097
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002098 if (!dev->has_video) {
2099 /* This device does not support the v4l2 extension */
2100 return 0;
2101 }
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02002102
Frank Schaefer95d26082014-03-24 16:33:09 -03002103 if (v4l2 == NULL)
2104 return 0;
2105
Russell King0418ca62014-12-20 09:45:20 -03002106 em28xx_info("Closing video extension\n");
Mauro Carvalho Chehabaa929ad2014-01-12 19:22:07 -03002107
Mauro Carvalho Chehabebbfbc22014-01-13 02:53:44 -03002108 mutex_lock(&dev->lock);
2109
Frank Schaefer95d26082014-03-24 16:33:09 -03002110 v4l2_device_disconnect(&v4l2->v4l2_dev);
Frank Schaefer5ad10de2014-01-12 13:24:21 -03002111
Frank Schaefer23e86422014-01-12 13:24:20 -03002112 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
2113
Mauro Carvalho Chehab37ecc7b2016-01-27 07:07:24 -02002114 em28xx_v4l2_media_release(dev);
2115
Hans Verkuild4352f32015-03-09 13:34:06 -03002116 if (video_is_registered(&v4l2->radio_dev)) {
Frank Schaefere8470222014-01-12 13:24:25 -03002117 em28xx_info("V4L2 device %s deregistered\n",
Hans Verkuild4352f32015-03-09 13:34:06 -03002118 video_device_node_name(&v4l2->radio_dev));
2119 video_unregister_device(&v4l2->radio_dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002120 }
Hans Verkuild4352f32015-03-09 13:34:06 -03002121 if (video_is_registered(&v4l2->vbi_dev)) {
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002122 em28xx_info("V4L2 device %s deregistered\n",
Hans Verkuild4352f32015-03-09 13:34:06 -03002123 video_device_node_name(&v4l2->vbi_dev));
2124 video_unregister_device(&v4l2->vbi_dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002125 }
Hans Verkuild4352f32015-03-09 13:34:06 -03002126 if (video_is_registered(&v4l2->vdev)) {
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002127 em28xx_info("V4L2 device %s deregistered\n",
Hans Verkuild4352f32015-03-09 13:34:06 -03002128 video_device_node_name(&v4l2->vdev));
2129 video_unregister_device(&v4l2->vdev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002130 }
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002131
Frank Schaeferabc13082014-03-24 16:33:10 -03002132 v4l2_ctrl_handler_free(&v4l2->ctrl_handler);
Frank Schaefer95d26082014-03-24 16:33:09 -03002133 v4l2_device_unregister(&v4l2->v4l2_dev);
Frank Schaefer103f18a2014-01-17 14:45:30 -03002134
Frank Schaefer2c52a2f2014-03-24 16:33:11 -03002135 if (v4l2->clk) {
2136 v4l2_clk_unregister_fixed(v4l2->clk);
2137 v4l2->clk = NULL;
Frank Schaefer25dd1652014-01-12 13:24:23 -03002138 }
2139
Frank Schaefer95d26082014-03-24 16:33:09 -03002140 kref_put(&v4l2->ref, em28xx_free_v4l2);
2141
Mauro Carvalho Chehabebbfbc22014-01-13 02:53:44 -03002142 mutex_unlock(&dev->lock);
Frank Schaefer95d26082014-03-24 16:33:09 -03002143
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002144 kref_put(&dev->ref, em28xx_free_device);
Frank Schaefer5ad10de2014-01-12 13:24:21 -03002145
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002146 return 0;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002147}
2148
Shuah Khana61f6812014-02-21 21:50:17 -03002149static int em28xx_v4l2_suspend(struct em28xx *dev)
2150{
2151 if (dev->is_audio_only)
2152 return 0;
2153
2154 if (!dev->has_video)
2155 return 0;
2156
Russell King32e63f02014-12-20 09:45:51 -03002157 em28xx_info("Suspending video extension\n");
Shuah Khana61f6812014-02-21 21:50:17 -03002158 em28xx_stop_urbs(dev);
2159 return 0;
2160}
2161
2162static int em28xx_v4l2_resume(struct em28xx *dev)
2163{
2164 if (dev->is_audio_only)
2165 return 0;
2166
2167 if (!dev->has_video)
2168 return 0;
2169
Russell King32e63f02014-12-20 09:45:51 -03002170 em28xx_info("Resuming video extension\n");
Shuah Khana61f6812014-02-21 21:50:17 -03002171 /* what do we do here */
2172 return 0;
2173}
2174
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002175/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002176 * em28xx_v4l2_close()
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03002177 * stops streaming and deallocates all resources allocated by the v4l2
2178 * calls and ioctls
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002179 */
Hans Verkuilbec43662008-12-30 06:58:20 -03002180static int em28xx_v4l2_close(struct file *filp)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002181{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03002182 struct em28xx *dev = video_drvdata(filp);
Frank Schaefer95d26082014-03-24 16:33:09 -03002183 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03002184 int errCode;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002185
Frank Schaefer8e2c8712014-09-18 17:55:45 -03002186 em28xx_videodbg("users=%d\n", v4l2->users);
2187
2188 vb2_fop_release(filp);
Ricardo Ribalda98c24dcd2013-11-06 05:39:35 -03002189 mutex_lock(&dev->lock);
Devin Heitmueller8c873d32009-09-03 00:23:27 -03002190
Frank Schaefer8e2c8712014-09-18 17:55:45 -03002191 if (v4l2->users == 1) {
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002192 /* No sense to try to write to the device */
2193 if (dev->disconnected)
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002194 goto exit;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03002195
Mauro Carvalho Chehabeb6c9632008-12-05 10:39:12 -03002196 /* Save some power by putting tuner to sleep */
Frank Schaefer95d26082014-03-24 16:33:09 -03002197 v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_power, 0);
Mauro Carvalho Chehabeb6c9632008-12-05 10:39:12 -03002198
Aidan Thorntond7aa8022008-04-13 14:38:47 -03002199 /* do this before setting alternate! */
Mauro Carvalho Chehab2fe3e2e2008-11-27 09:10:40 -03002200 em28xx_set_mode(dev, EM28XX_SUSPEND);
Aidan Thorntond7aa8022008-04-13 14:38:47 -03002201
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03002202 /* set alternate 0 */
2203 dev->alt = 0;
2204 em28xx_videodbg("setting alternate 0\n");
2205 errCode = usb_set_interface(dev->udev, 0, 0);
2206 if (errCode < 0) {
2207 em28xx_errdev("cannot change alternate number to "
2208 "0 (error=%i)\n", errCode);
2209 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002210 }
Devin Heitmueller28abf0832009-09-01 01:54:54 -03002211
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002212exit:
Frank Schaefer8e2c8712014-09-18 17:55:45 -03002213 v4l2->users--;
Frank Schaefer95d26082014-03-24 16:33:09 -03002214 kref_put(&v4l2->ref, em28xx_free_v4l2);
Hans Verkuil876cb142012-06-23 08:12:47 -03002215 mutex_unlock(&dev->lock);
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002216 kref_put(&dev->ref, em28xx_free_device);
2217
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002218 return 0;
2219}
2220
Hans Verkuilbec43662008-12-30 06:58:20 -03002221static const struct v4l2_file_operations em28xx_v4l_fops = {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002222 .owner = THIS_MODULE,
2223 .open = em28xx_v4l2_open,
2224 .release = em28xx_v4l2_close,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002225 .read = vb2_fop_read,
2226 .poll = vb2_fop_poll,
2227 .mmap = vb2_fop_mmap,
Hans Verkuil0499a5a2010-09-26 07:34:45 -03002228 .unlocked_ioctl = video_ioctl2,
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002229};
2230
Hans Verkuila3998102008-07-21 02:57:38 -03002231static const struct v4l2_ioctl_ops video_ioctl_ops = {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002232 .vidioc_querycap = vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03002233 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
2234 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
2235 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
2236 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Devin Heitmueller28abf0832009-09-01 01:54:54 -03002237 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Hans Verkuil2a221d32012-09-07 08:51:32 -03002238 .vidioc_try_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Frank Schaeferaab34612013-02-07 13:39:16 -03002239 .vidioc_s_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Mauro Carvalho Chehab1c5c5062011-10-16 13:52:43 -02002240 .vidioc_enum_framesizes = vidioc_enum_framesizes,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002241 .vidioc_g_audio = vidioc_g_audio,
2242 .vidioc_s_audio = vidioc_s_audio,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002243
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002244 .vidioc_reqbufs = vb2_ioctl_reqbufs,
2245 .vidioc_create_bufs = vb2_ioctl_create_bufs,
2246 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
2247 .vidioc_querybuf = vb2_ioctl_querybuf,
2248 .vidioc_qbuf = vb2_ioctl_qbuf,
2249 .vidioc_dqbuf = vb2_ioctl_dqbuf,
2250
Devin Heitmueller19bf0032009-09-11 00:40:18 -03002251 .vidioc_g_std = vidioc_g_std,
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03002252 .vidioc_querystd = vidioc_querystd,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002253 .vidioc_s_std = vidioc_s_std,
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03002254 .vidioc_g_parm = vidioc_g_parm,
2255 .vidioc_s_parm = vidioc_s_parm,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002256 .vidioc_enum_input = vidioc_enum_input,
2257 .vidioc_g_input = vidioc_g_input,
2258 .vidioc_s_input = vidioc_s_input,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002259 .vidioc_streamon = vb2_ioctl_streamon,
2260 .vidioc_streamoff = vb2_ioctl_streamoff,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002261 .vidioc_g_tuner = vidioc_g_tuner,
2262 .vidioc_s_tuner = vidioc_s_tuner,
2263 .vidioc_g_frequency = vidioc_g_frequency,
2264 .vidioc_s_frequency = vidioc_s_frequency,
Hans Verkuil50fdf402012-09-07 06:10:12 -03002265 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
2266 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002267#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuil96b03d22013-04-06 06:16:58 -03002268 .vidioc_g_chip_info = vidioc_g_chip_info,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002269 .vidioc_g_register = vidioc_g_register,
2270 .vidioc_s_register = vidioc_s_register,
2271#endif
Hans Verkuila3998102008-07-21 02:57:38 -03002272};
2273
2274static const struct video_device em28xx_video_template = {
Frank Schaefere8470222014-01-12 13:24:25 -03002275 .fops = &em28xx_v4l_fops,
2276 .ioctl_ops = &video_ioctl_ops,
Hans Verkuild4352f32015-03-09 13:34:06 -03002277 .release = video_device_release_empty,
Frank Schaefere8470222014-01-12 13:24:25 -03002278 .tvnorms = V4L2_STD_ALL,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002279};
2280
Hans Verkuilbec43662008-12-30 06:58:20 -03002281static const struct v4l2_file_operations radio_fops = {
Hans Verkuila3998102008-07-21 02:57:38 -03002282 .owner = THIS_MODULE,
2283 .open = em28xx_v4l2_open,
2284 .release = em28xx_v4l2_close,
Hans Verkuil8fd0bda2010-12-18 09:59:51 -03002285 .unlocked_ioctl = video_ioctl2,
Hans Verkuila3998102008-07-21 02:57:38 -03002286};
2287
2288static const struct v4l2_ioctl_ops radio_ioctl_ops = {
Hans Verkuila9d79fe2012-09-06 07:31:04 -03002289 .vidioc_querycap = vidioc_querycap,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002290 .vidioc_g_tuner = radio_g_tuner,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002291 .vidioc_s_tuner = radio_s_tuner,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002292 .vidioc_g_frequency = vidioc_g_frequency,
2293 .vidioc_s_frequency = vidioc_s_frequency,
Hans Verkuil50fdf402012-09-07 06:10:12 -03002294 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
2295 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002296#ifdef CONFIG_VIDEO_ADV_DEBUG
Michal Marek430c73f2013-04-16 08:06:30 -03002297 .vidioc_g_chip_info = vidioc_g_chip_info,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002298 .vidioc_g_register = vidioc_g_register,
2299 .vidioc_s_register = vidioc_s_register,
2300#endif
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002301};
2302
Hans Verkuila3998102008-07-21 02:57:38 -03002303static struct video_device em28xx_radio_template = {
Frank Schaefere8470222014-01-12 13:24:25 -03002304 .fops = &radio_fops,
2305 .ioctl_ops = &radio_ioctl_ops,
Hans Verkuild4352f32015-03-09 13:34:06 -03002306 .release = video_device_release_empty,
Hans Verkuila3998102008-07-21 02:57:38 -03002307};
2308
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002309/* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */
2310static unsigned short saa711x_addrs[] = {
2311 0x4a >> 1, 0x48 >> 1, /* SAA7111, SAA7111A and SAA7113 */
2312 0x42 >> 1, 0x40 >> 1, /* SAA7114, SAA7115 and SAA7118 */
2313 I2C_CLIENT_END };
2314
2315static unsigned short tvp5150_addrs[] = {
2316 0xb8 >> 1,
2317 0xba >> 1,
2318 I2C_CLIENT_END
2319};
2320
2321static unsigned short msp3400_addrs[] = {
2322 0x80 >> 1,
2323 0x88 >> 1,
2324 I2C_CLIENT_END
2325};
2326
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03002327/******************************** usb interface ******************************/
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002328
Hans Verkuild4352f32015-03-09 13:34:06 -03002329static void em28xx_vdev_init(struct em28xx *dev,
2330 struct video_device *vfd,
2331 const struct video_device *template,
2332 const char *type_name)
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002333{
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03002334 *vfd = *template;
Frank Schaefer95d26082014-03-24 16:33:09 -03002335 vfd->v4l2_dev = &dev->v4l2->v4l2_dev;
Hans Verkuil0499a5a2010-09-26 07:34:45 -03002336 vfd->lock = &dev->lock;
Hans Verkuild8c95c02012-09-07 07:31:54 -03002337 if (dev->board.is_webcam)
2338 vfd->tvnorms = 0;
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002339
2340 snprintf(vfd->name, sizeof(vfd->name), "%s %s",
2341 dev->name, type_name);
2342
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02002343 video_set_drvdata(vfd, dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002344}
2345
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002346static void em28xx_tuner_setup(struct em28xx *dev, unsigned short tuner_addr)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002347{
Frank Schaefer3854b0d2014-03-24 16:33:22 -03002348 struct em28xx_v4l2 *v4l2 = dev->v4l2;
2349 struct v4l2_device *v4l2_dev = &v4l2->v4l2_dev;
2350 struct tuner_setup tun_setup;
2351 struct v4l2_frequency f;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002352
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002353 memset(&tun_setup, 0, sizeof(tun_setup));
2354
2355 tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
2356 tun_setup.tuner_callback = em28xx_tuner_callback;
2357
2358 if (dev->board.radio.type) {
2359 tun_setup.type = dev->board.radio.type;
2360 tun_setup.addr = dev->board.radio_addr;
2361
Frank Schaefer95d26082014-03-24 16:33:09 -03002362 v4l2_device_call_all(v4l2_dev,
2363 0, tuner, s_type_addr, &tun_setup);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002364 }
2365
2366 if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type)) {
2367 tun_setup.type = dev->tuner_type;
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002368 tun_setup.addr = tuner_addr;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002369
Frank Schaefer95d26082014-03-24 16:33:09 -03002370 v4l2_device_call_all(v4l2_dev,
2371 0, tuner, s_type_addr, &tun_setup);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002372 }
2373
Frank Schaefer6867bd5a2014-03-24 16:33:23 -03002374 if (dev->board.tda9887_conf) {
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002375 struct v4l2_priv_tun_config tda9887_cfg;
2376
2377 tda9887_cfg.tuner = TUNER_TDA9887;
Frank Schaefer6867bd5a2014-03-24 16:33:23 -03002378 tda9887_cfg.priv = &dev->board.tda9887_conf;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002379
Frank Schaefer95d26082014-03-24 16:33:09 -03002380 v4l2_device_call_all(v4l2_dev,
2381 0, tuner, s_config, &tda9887_cfg);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002382 }
2383
2384 if (dev->tuner_type == TUNER_XC2028) {
2385 struct v4l2_priv_tun_config xc2028_cfg;
2386 struct xc2028_ctrl ctl;
2387
2388 memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
2389 memset(&ctl, 0, sizeof(ctl));
2390
2391 em28xx_setup_xc3028(dev, &ctl);
2392
2393 xc2028_cfg.tuner = TUNER_XC2028;
2394 xc2028_cfg.priv = &ctl;
2395
Frank Schaefer95d26082014-03-24 16:33:09 -03002396 v4l2_device_call_all(v4l2_dev, 0, tuner, s_config, &xc2028_cfg);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002397 }
2398
2399 /* configure tuner */
2400 f.tuner = 0;
2401 f.type = V4L2_TUNER_ANALOG_TV;
2402 f.frequency = 9076; /* just a magic number */
Frank Schaefer3854b0d2014-03-24 16:33:22 -03002403 v4l2->frequency = f.frequency;
Frank Schaefer95d26082014-03-24 16:33:09 -03002404 v4l2_device_call_all(v4l2_dev, 0, tuner, s_frequency, &f);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002405}
2406
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002407static int em28xx_v4l2_init(struct em28xx *dev)
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002408{
Hans Verkuil081b9452012-09-07 05:43:59 -03002409 u8 val;
Mauro Carvalho Chehab2e5ef2d2008-12-28 22:26:36 -03002410 int ret;
Sascha Sommer1020d132012-01-08 16:54:28 -03002411 unsigned int maxw;
Frank Schaeferabc13082014-03-24 16:33:10 -03002412 struct v4l2_ctrl_handler *hdl;
Frank Schaefer95d26082014-03-24 16:33:09 -03002413 struct em28xx_v4l2 *v4l2;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002414
Mauro Carvalho Chehab822b8de2014-01-06 05:27:47 -03002415 if (dev->is_audio_only) {
2416 /* Shouldn't initialize IR for this interface */
2417 return 0;
2418 }
2419
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002420 if (!dev->has_video) {
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002421 /* This device does not support the v4l2 extension */
2422 return 0;
2423 }
Mauro Carvalho Chehab2e5ef2d2008-12-28 22:26:36 -03002424
Mauro Carvalho Chehab96346142013-12-26 12:41:03 -03002425 em28xx_info("Registering V4L2 extension\n");
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002426
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002427 mutex_lock(&dev->lock);
2428
Frank Schaefer95d26082014-03-24 16:33:09 -03002429 v4l2 = kzalloc(sizeof(struct em28xx_v4l2), GFP_KERNEL);
2430 if (v4l2 == NULL) {
2431 em28xx_info("em28xx_v4l: memory allocation failed\n");
2432 mutex_unlock(&dev->lock);
2433 return -ENOMEM;
2434 }
2435 kref_init(&v4l2->ref);
Frank Schaeferabc13082014-03-24 16:33:10 -03002436 v4l2->dev = dev;
Frank Schaefer95d26082014-03-24 16:33:09 -03002437 dev->v4l2 = v4l2;
2438
Mauro Carvalho Chehab37ecc7b2016-01-27 07:07:24 -02002439#ifdef CONFIG_MEDIA_CONTROLLER
2440 v4l2->v4l2_dev.mdev = dev->media_dev;
2441#endif
Frank Schaefer95d26082014-03-24 16:33:09 -03002442 ret = v4l2_device_register(&dev->udev->dev, &v4l2->v4l2_dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002443 if (ret < 0) {
2444 em28xx_errdev("Call to v4l2_device_register() failed!\n");
2445 goto err;
2446 }
2447
Frank Schaeferabc13082014-03-24 16:33:10 -03002448 hdl = &v4l2->ctrl_handler;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002449 v4l2_ctrl_handler_init(hdl, 8);
Frank Schaefer95d26082014-03-24 16:33:09 -03002450 v4l2->v4l2_dev.ctrl_handler = hdl;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002451
Frank Schaefer58159172014-03-24 16:33:18 -03002452 if (dev->board.is_webcam)
Mauro Carvalho Chehab7e6c8c12014-09-03 15:06:13 -03002453 v4l2->progressive = true;
Frank Schaefer58159172014-03-24 16:33:18 -03002454
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002455 /*
2456 * Default format, used for tvp5150 or saa711x output formats
2457 */
Frank Schaefer92972852014-03-24 16:33:15 -03002458 v4l2->vinmode = 0x10;
2459 v4l2->vinctl = EM28XX_VINCTRL_INTERLACED |
2460 EM28XX_VINCTRL_CCIR656_ENABLE;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002461
2462 /* request some modules */
2463
2464 if (dev->board.has_msp34xx)
Frank Schaefer95d26082014-03-24 16:33:09 -03002465 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2466 &dev->i2c_adap[dev->def_i2c_bus],
2467 "msp3400", 0, msp3400_addrs);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002468
2469 if (dev->board.decoder == EM28XX_SAA711X)
Frank Schaefer95d26082014-03-24 16:33:09 -03002470 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2471 &dev->i2c_adap[dev->def_i2c_bus],
2472 "saa7115_auto", 0, saa711x_addrs);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002473
2474 if (dev->board.decoder == EM28XX_TVP5150)
Frank Schaefer95d26082014-03-24 16:33:09 -03002475 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2476 &dev->i2c_adap[dev->def_i2c_bus],
2477 "tvp5150", 0, tvp5150_addrs);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002478
2479 if (dev->board.adecoder == EM28XX_TVAUDIO)
Frank Schaefer95d26082014-03-24 16:33:09 -03002480 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2481 &dev->i2c_adap[dev->def_i2c_bus],
2482 "tvaudio", dev->board.tvaudio_addr, NULL);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002483
2484 /* Initialize tuner and camera */
2485
2486 if (dev->board.tuner_type != TUNER_ABSENT) {
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002487 unsigned short tuner_addr = dev->board.tuner_addr;
Frank Schaefer6867bd5a2014-03-24 16:33:23 -03002488 int has_demod = (dev->board.tda9887_conf & TDA9887_PRESENT);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002489
2490 if (dev->board.radio.type)
Frank Schaefer95d26082014-03-24 16:33:09 -03002491 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002492 &dev->i2c_adap[dev->def_i2c_bus],
2493 "tuner", dev->board.radio_addr,
2494 NULL);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002495
2496 if (has_demod)
Frank Schaefer95d26082014-03-24 16:33:09 -03002497 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002498 &dev->i2c_adap[dev->def_i2c_bus],
2499 "tuner", 0,
2500 v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002501 if (tuner_addr == 0) {
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002502 enum v4l2_i2c_tuner_type type =
2503 has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV;
2504 struct v4l2_subdev *sd;
2505
Frank Schaefer95d26082014-03-24 16:33:09 -03002506 sd = v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002507 &dev->i2c_adap[dev->def_i2c_bus],
2508 "tuner", 0,
2509 v4l2_i2c_tuner_addrs(type));
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002510
2511 if (sd)
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002512 tuner_addr = v4l2_i2c_subdev_addr(sd);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002513 } else {
Frank Schaefer95d26082014-03-24 16:33:09 -03002514 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2515 &dev->i2c_adap[dev->def_i2c_bus],
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002516 "tuner", tuner_addr, NULL);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002517 }
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002518
2519 em28xx_tuner_setup(dev, tuner_addr);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002520 }
2521
Frank Schaeferd86bc652014-01-17 14:45:32 -03002522 if (dev->em28xx_sensor != EM28XX_NOSENSOR)
2523 em28xx_init_camera(dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002524
2525 /* Configure audio */
2526 ret = em28xx_audio_setup(dev);
2527 if (ret < 0) {
2528 em28xx_errdev("%s: Error while setting audio - error [%d]!\n",
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002529 __func__, ret);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002530 goto unregister_dev;
2531 }
2532 if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
2533 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002534 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002535 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002536 V4L2_CID_AUDIO_VOLUME, 0, 0x1f, 1, 0x1f);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002537 } else {
2538 /* install the em28xx notify callback */
2539 v4l2_ctrl_notify(v4l2_ctrl_find(hdl, V4L2_CID_AUDIO_MUTE),
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002540 em28xx_ctrl_notify, dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002541 v4l2_ctrl_notify(v4l2_ctrl_find(hdl, V4L2_CID_AUDIO_VOLUME),
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002542 em28xx_ctrl_notify, dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002543 }
2544
2545 /* wake i2c devices */
2546 em28xx_wake_i2c(dev);
2547
2548 /* init video dma queues */
2549 INIT_LIST_HEAD(&dev->vidq.active);
2550 INIT_LIST_HEAD(&dev->vbiq.active);
2551
2552 if (dev->board.has_msp34xx) {
2553 /* Send a reset to other chips via gpio */
2554 ret = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xf7);
2555 if (ret < 0) {
2556 em28xx_errdev("%s: em28xx_write_reg - msp34xx(1) failed! error [%d]\n",
2557 __func__, ret);
2558 goto unregister_dev;
2559 }
2560 msleep(3);
2561
2562 ret = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xff);
2563 if (ret < 0) {
2564 em28xx_errdev("%s: em28xx_write_reg - msp34xx(2) failed! error [%d]\n",
2565 __func__, ret);
2566 goto unregister_dev;
2567 }
2568 msleep(3);
2569 }
2570
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002571 /* set default norm */
Frank Schaefer52faaf72014-03-24 16:33:16 -03002572 v4l2->norm = V4L2_STD_PAL;
Laurent Pinchart8774bed2014-04-28 16:53:01 -03002573 v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_std, v4l2->norm);
Frank Schaefer58159172014-03-24 16:33:18 -03002574 v4l2->interlaced_fieldmode = EM28XX_INTERLACED_DEFAULT;
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002575
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002576 /* Analog specific initialization */
Frank Schaefer06e20672014-03-24 16:33:17 -03002577 v4l2->format = &format[0];
Sascha Sommer1020d132012-01-08 16:54:28 -03002578
2579 maxw = norm_maxw(dev);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002580 /* MaxPacketSize for em2800 is too small to capture at full resolution
2581 * use half of maxw as the scaler can only scale to 50% */
2582 if (dev->board.is_em2800)
2583 maxw /= 2;
Sascha Sommer1020d132012-01-08 16:54:28 -03002584
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03002585 em28xx_set_video_format(dev, format[0].fourcc,
Sascha Sommer1020d132012-01-08 16:54:28 -03002586 maxw, norm_maxh(dev));
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03002587
Ezequiel García96371fc2012-03-23 18:09:34 -03002588 video_mux(dev, 0);
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002589
2590 /* Audio defaults */
2591 dev->mute = 1;
2592 dev->volume = 0x1f;
2593
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002594/* em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -03002595 val = (u8)em28xx_read_reg(dev, EM28XX_R0F_XCLK);
2596 em28xx_write_reg(dev, EM28XX_R0F_XCLK,
2597 (EM28XX_XCLK_AUDIO_UNMUTE | val));
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002598
2599 em28xx_set_outfmt(dev);
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002600
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002601 /* Add image controls */
2602 /* NOTE: at this point, the subdevices are already registered, so bridge
2603 * controls are only added/enabled when no subdevice provides them */
Frank Schaeferad298052014-03-24 16:33:08 -03002604 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_CONTRAST))
2605 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002606 V4L2_CID_CONTRAST,
2607 0, 0x1f, 1, CONTRAST_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002608 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_BRIGHTNESS))
2609 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002610 V4L2_CID_BRIGHTNESS,
2611 -0x80, 0x7f, 1, BRIGHTNESS_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002612 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_SATURATION))
2613 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002614 V4L2_CID_SATURATION,
2615 0, 0x1f, 1, SATURATION_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002616 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_BLUE_BALANCE))
2617 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002618 V4L2_CID_BLUE_BALANCE,
2619 -0x30, 0x30, 1, BLUE_BALANCE_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002620 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_RED_BALANCE))
2621 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002622 V4L2_CID_RED_BALANCE,
2623 -0x30, 0x30, 1, RED_BALANCE_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002624 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_SHARPNESS))
2625 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002626 V4L2_CID_SHARPNESS,
2627 0, 0x0f, 1, SHARPNESS_DEFAULT);
2628
2629 /* Reset image controls */
2630 em28xx_colorlevels_set_default(dev);
Frank Schaeferad298052014-03-24 16:33:08 -03002631 v4l2_ctrl_handler_setup(hdl);
2632 ret = hdl->error;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002633 if (ret)
2634 goto unregister_dev;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002635
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002636 /* allocate and fill video video_device struct */
Hans Verkuild4352f32015-03-09 13:34:06 -03002637 em28xx_vdev_init(dev, &v4l2->vdev, &em28xx_video_template, "video");
Frank Schaefer27a36df2014-03-24 16:33:13 -03002638 mutex_init(&v4l2->vb_queue_lock);
2639 mutex_init(&v4l2->vb_vbi_queue_lock);
Hans Verkuild4352f32015-03-09 13:34:06 -03002640 v4l2->vdev.queue = &v4l2->vb_vidq;
2641 v4l2->vdev.queue->lock = &v4l2->vb_queue_lock;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002642
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002643 /* disable inapplicable ioctls */
2644 if (dev->board.is_webcam) {
Hans Verkuild4352f32015-03-09 13:34:06 -03002645 v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_QUERYSTD);
2646 v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_G_STD);
2647 v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_S_STD);
Frank Schaefer3bc85cc2013-02-07 13:39:12 -03002648 } else {
Hans Verkuild4352f32015-03-09 13:34:06 -03002649 v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_S_PARM);
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002650 }
Frank Schaefer66df67b2013-02-07 13:39:10 -03002651 if (dev->tuner_type == TUNER_ABSENT) {
Hans Verkuild4352f32015-03-09 13:34:06 -03002652 v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_G_TUNER);
2653 v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_S_TUNER);
2654 v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_G_FREQUENCY);
2655 v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_S_FREQUENCY);
Frank Schaefer66df67b2013-02-07 13:39:10 -03002656 }
Frank Schaefer920f1e42014-09-13 05:52:21 -03002657 if (dev->int_audio_type == EM28XX_INT_AUDIO_NONE) {
Hans Verkuild4352f32015-03-09 13:34:06 -03002658 v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_G_AUDIO);
2659 v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_S_AUDIO);
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002660 }
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002661
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002662 /* register v4l2 video video_device */
Hans Verkuild4352f32015-03-09 13:34:06 -03002663 ret = video_register_device(&v4l2->vdev, VFL_TYPE_GRABBER,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002664 video_nr[dev->devno]);
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002665 if (ret) {
2666 em28xx_errdev("unable to register video device (error=%i).\n",
2667 ret);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002668 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002669 }
2670
2671 /* Allocate and fill vbi video_device struct */
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002672 if (em28xx_vbi_supported(dev) == 1) {
Hans Verkuild4352f32015-03-09 13:34:06 -03002673 em28xx_vdev_init(dev, &v4l2->vbi_dev, &em28xx_video_template,
2674 "vbi");
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002675
Hans Verkuild4352f32015-03-09 13:34:06 -03002676 v4l2->vbi_dev.queue = &v4l2->vb_vbiq;
2677 v4l2->vbi_dev.queue->lock = &v4l2->vb_vbi_queue_lock;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002678
Frank Schaefer66df67b2013-02-07 13:39:10 -03002679 /* disable inapplicable ioctls */
Hans Verkuild4352f32015-03-09 13:34:06 -03002680 v4l2_disable_ioctl(&v4l2->vbi_dev, VIDIOC_S_PARM);
Frank Schaefer66df67b2013-02-07 13:39:10 -03002681 if (dev->tuner_type == TUNER_ABSENT) {
Hans Verkuild4352f32015-03-09 13:34:06 -03002682 v4l2_disable_ioctl(&v4l2->vbi_dev, VIDIOC_G_TUNER);
2683 v4l2_disable_ioctl(&v4l2->vbi_dev, VIDIOC_S_TUNER);
2684 v4l2_disable_ioctl(&v4l2->vbi_dev, VIDIOC_G_FREQUENCY);
2685 v4l2_disable_ioctl(&v4l2->vbi_dev, VIDIOC_S_FREQUENCY);
Frank Schaefer66df67b2013-02-07 13:39:10 -03002686 }
Frank Schaefer920f1e42014-09-13 05:52:21 -03002687 if (dev->int_audio_type == EM28XX_INT_AUDIO_NONE) {
Hans Verkuild4352f32015-03-09 13:34:06 -03002688 v4l2_disable_ioctl(&v4l2->vbi_dev, VIDIOC_G_AUDIO);
2689 v4l2_disable_ioctl(&v4l2->vbi_dev, VIDIOC_S_AUDIO);
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002690 }
Frank Schaefer66df67b2013-02-07 13:39:10 -03002691
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002692 /* register v4l2 vbi video_device */
Hans Verkuild4352f32015-03-09 13:34:06 -03002693 ret = video_register_device(&v4l2->vbi_dev, VFL_TYPE_VBI,
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002694 vbi_nr[dev->devno]);
2695 if (ret < 0) {
2696 em28xx_errdev("unable to register vbi device\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002697 goto unregister_dev;
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002698 }
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002699 }
2700
2701 if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) {
Hans Verkuild4352f32015-03-09 13:34:06 -03002702 em28xx_vdev_init(dev, &v4l2->radio_dev, &em28xx_radio_template,
2703 "radio");
2704 ret = video_register_device(&v4l2->radio_dev, VFL_TYPE_RADIO,
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002705 radio_nr[dev->devno]);
2706 if (ret < 0) {
2707 em28xx_errdev("can't register radio device\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002708 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002709 }
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002710 em28xx_info("Registered radio device as %s\n",
Hans Verkuild4352f32015-03-09 13:34:06 -03002711 video_device_node_name(&v4l2->radio_dev));
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002712 }
2713
Mauro Carvalho Chehab37ecc7b2016-01-27 07:07:24 -02002714 /* Init entities at the Media Controller */
2715 em28xx_v4l2_create_entities(dev);
2716
Arnd Bergmann0d37ba62016-02-26 08:53:22 -03002717#ifdef CONFIG_MEDIA_CONTROLLER
Mauro Carvalho Chehabde390782016-02-05 07:08:25 -02002718 ret = v4l2_mc_create_media_graph(dev->media_dev);
Mauro Carvalho Chehab37ecc7b2016-01-27 07:07:24 -02002719 if (ret) {
2720 em28xx_errdev("failed to create media graph\n");
2721 em28xx_v4l2_media_release(dev);
2722 goto unregister_dev;
2723 }
Arnd Bergmann0d37ba62016-02-26 08:53:22 -03002724#endif
Mauro Carvalho Chehab37ecc7b2016-01-27 07:07:24 -02002725
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002726 em28xx_info("V4L2 video device registered as %s\n",
Hans Verkuild4352f32015-03-09 13:34:06 -03002727 video_device_node_name(&v4l2->vdev));
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002728
Hans Verkuild4352f32015-03-09 13:34:06 -03002729 if (video_is_registered(&v4l2->vbi_dev))
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002730 em28xx_info("V4L2 VBI device registered as %s\n",
Hans Verkuild4352f32015-03-09 13:34:06 -03002731 video_device_node_name(&v4l2->vbi_dev));
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002732
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002733 /* Save some power by putting tuner to sleep */
Frank Schaefer95d26082014-03-24 16:33:09 -03002734 v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_power, 0);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002735
2736 /* initialize videobuf2 stuff */
2737 em28xx_vb2_setup(dev);
2738
Mauro Carvalho Chehab96346142013-12-26 12:41:03 -03002739 em28xx_info("V4L2 extension successfully initialized\n");
2740
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002741 kref_get(&dev->ref);
2742
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002743 mutex_unlock(&dev->lock);
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002744 return 0;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002745
2746unregister_dev:
Mauro Carvalho Chehab56a7f512016-01-29 13:08:19 -02002747 if (video_is_registered(&v4l2->radio_dev)) {
2748 em28xx_info("V4L2 device %s deregistered\n",
2749 video_device_node_name(&v4l2->radio_dev));
2750 video_unregister_device(&v4l2->radio_dev);
2751 }
2752 if (video_is_registered(&v4l2->vbi_dev)) {
2753 em28xx_info("V4L2 device %s deregistered\n",
2754 video_device_node_name(&v4l2->vbi_dev));
2755 video_unregister_device(&v4l2->vbi_dev);
2756 }
2757 if (video_is_registered(&v4l2->vdev)) {
2758 em28xx_info("V4L2 device %s deregistered\n",
2759 video_device_node_name(&v4l2->vdev));
2760 video_unregister_device(&v4l2->vdev);
2761 }
2762
Frank Schaeferabc13082014-03-24 16:33:10 -03002763 v4l2_ctrl_handler_free(&v4l2->ctrl_handler);
Frank Schaefer95d26082014-03-24 16:33:09 -03002764 v4l2_device_unregister(&v4l2->v4l2_dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002765err:
Frank Schaefer95d26082014-03-24 16:33:09 -03002766 dev->v4l2 = NULL;
2767 kref_put(&v4l2->ref, em28xx_free_v4l2);
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002768 mutex_unlock(&dev->lock);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002769 return ret;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002770}
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002771
2772static struct em28xx_ops v4l2_ops = {
2773 .id = EM28XX_V4L2,
2774 .name = "Em28xx v4l2 Extension",
2775 .init = em28xx_v4l2_init,
2776 .fini = em28xx_v4l2_fini,
Shuah Khana61f6812014-02-21 21:50:17 -03002777 .suspend = em28xx_v4l2_suspend,
2778 .resume = em28xx_v4l2_resume,
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002779};
2780
2781static int __init em28xx_video_register(void)
2782{
2783 return em28xx_register_extension(&v4l2_ops);
2784}
2785
2786static void __exit em28xx_video_unregister(void)
2787{
2788 em28xx_unregister_extension(&v4l2_ops);
2789}
2790
2791module_init(em28xx_video_register);
2792module_exit(em28xx_video_unregister);