blob: 6a015e8e865531480af43f269a14e02a88fd87d5 [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 Chehabad0ebb92008-04-13 14:37:52 -0300869/* ------------------------------------------------------------------
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300870 Videobuf2 operations
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300871 ------------------------------------------------------------------*/
872
Hans Verkuildf9ecb02015-10-28 00:50:37 -0200873static int queue_setup(struct vb2_queue *vq,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300874 unsigned int *nbuffers, unsigned int *nplanes,
875 unsigned int sizes[], void *alloc_ctxs[])
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300876{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300877 struct em28xx *dev = vb2_get_drv_priv(vq);
Frank Schaefer753aee72014-03-24 16:33:14 -0300878 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Hans Verkuildf9ecb02015-10-28 00:50:37 -0200879 unsigned long size =
Frank Schaefer06e20672014-03-24 16:33:17 -0300880 (v4l2->width * v4l2->height * v4l2->format->depth + 7) >> 3;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -0300881
Hans Verkuildf9ecb02015-10-28 00:50:37 -0200882 if (*nplanes)
883 return sizes[0] < size ? -EINVAL : 0;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300884 *nplanes = 1;
885 sizes[0] = size;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300886 return 0;
887}
888
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300889static int
890buffer_prepare(struct vb2_buffer *vb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300891{
Junghak Sung2d700712015-09-22 10:30:30 -0300892 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300893 struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue);
Frank Schaefer753aee72014-03-24 16:33:14 -0300894 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300895 unsigned long size;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300896
Junghak Sung2d700712015-09-22 10:30:30 -0300897 em28xx_videodbg("%s, field=%d\n", __func__, vbuf->field);
Aidan Thornton3b5fa922008-04-13 15:09:36 -0300898
Frank Schaefer06e20672014-03-24 16:33:17 -0300899 size = (v4l2->width * v4l2->height * v4l2->format->depth + 7) >> 3;
Aidan Thornton3b5fa922008-04-13 15:09:36 -0300900
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300901 if (vb2_plane_size(vb, 0) < size) {
902 em28xx_videodbg("%s data will not fit into plane (%lu < %lu)\n",
903 __func__, vb2_plane_size(vb, 0), size);
904 return -EINVAL;
905 }
Junghak Sung2d700712015-09-22 10:30:30 -0300906 vb2_set_plane_payload(vb, 0, size);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300907
908 return 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300909}
910
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300911int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300912{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300913 struct em28xx *dev = vb2_get_drv_priv(vq);
Frank Schaeferf0e38232014-03-24 16:33:20 -0300914 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300915 struct v4l2_frequency f;
Junghak Sung2d700712015-09-22 10:30:30 -0300916 struct v4l2_fh *owner;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300917 int rc = 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300918
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300919 em28xx_videodbg("%s\n", __func__);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300920
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300921 /* Make sure streaming is not already in progress for this type
922 of filehandle (e.g. video, vbi) */
923 rc = res_get(dev, vq->type);
924 if (rc)
925 return rc;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300926
Frank Schaefer8139a4d2014-05-11 17:59:04 -0300927 if (v4l2->streaming_users == 0) {
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300928 /* First active streaming user, so allocate all the URBs */
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300929
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300930 /* Allocate the USB bandwidth */
931 em28xx_set_alternate(dev);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300932
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300933 /* Needed, since GPIO might have disabled power of
934 some i2c device
935 */
936 em28xx_wake_i2c(dev);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300937
Frank Schaeferf0e38232014-03-24 16:33:20 -0300938 v4l2->capture_type = -1;
Frank Schaefer960da932012-11-25 06:37:37 -0300939 rc = em28xx_init_usb_xfer(dev, EM28XX_ANALOG_MODE,
940 dev->analog_xfer_bulk,
941 EM28XX_NUM_BUFS,
942 dev->max_pkt_size,
943 dev->packet_multiplier,
944 em28xx_urb_data_copy);
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300945 if (rc < 0)
Frank Schaefer032f1dd2013-10-10 15:31:53 -0300946 return rc;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300947
948 /*
949 * djh: it's not clear whether this code is still needed. I'm
950 * leaving it in here for now entirely out of concern for
951 * backward compatibility (the old code did it)
952 */
953
954 /* Ask tuner to go to analog or radio mode */
955 memset(&f, 0, sizeof(f));
Frank Schaefer3854b0d2014-03-24 16:33:22 -0300956 f.frequency = v4l2->frequency;
Junghak Sung2d700712015-09-22 10:30:30 -0300957 owner = (struct v4l2_fh *)vq->owner;
958 if (owner && owner->vdev->vfl_type == VFL_TYPE_RADIO)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300959 f.type = V4L2_TUNER_RADIO;
960 else
961 f.type = V4L2_TUNER_ANALOG_TV;
Frank Schaeferf0e38232014-03-24 16:33:20 -0300962 v4l2_device_call_all(&v4l2->v4l2_dev,
Frank Schaefer95d26082014-03-24 16:33:09 -0300963 0, tuner, s_frequency, &f);
Mauro Carvalho Chehab13d52fe2016-01-26 06:59:39 -0200964
965 /* Enable video stream at TV decoder */
966 v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_stream, 1);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300967 }
968
Frank Schaefer8139a4d2014-05-11 17:59:04 -0300969 v4l2->streaming_users++;
Frank Schaefer032f1dd2013-10-10 15:31:53 -0300970
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300971 return rc;
972}
973
Hans Verkuile37559b2014-04-17 02:47:21 -0300974static void em28xx_stop_streaming(struct vb2_queue *vq)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300975{
976 struct em28xx *dev = vb2_get_drv_priv(vq);
Frank Schaefer8139a4d2014-05-11 17:59:04 -0300977 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300978 struct em28xx_dmaqueue *vidq = &dev->vidq;
979 unsigned long flags = 0;
980
981 em28xx_videodbg("%s\n", __func__);
982
983 res_free(dev, vq->type);
984
Frank Schaefer8139a4d2014-05-11 17:59:04 -0300985 if (v4l2->streaming_users-- == 1) {
Mauro Carvalho Chehab13d52fe2016-01-26 06:59:39 -0200986 /* Disable video stream at TV decoder */
987 v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_stream, 0);
988
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300989 /* Last active user, so shutdown all the URBS */
990 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
991 }
992
993 spin_lock_irqsave(&dev->slock, flags);
Frank Schaefer627530c2014-08-09 06:37:20 -0300994 if (dev->usb_ctl.vid_buf != NULL) {
Junghak Sung2d700712015-09-22 10:30:30 -0300995 vb2_buffer_done(&dev->usb_ctl.vid_buf->vb.vb2_buf,
996 VB2_BUF_STATE_ERROR);
Frank Schaefer627530c2014-08-09 06:37:20 -0300997 dev->usb_ctl.vid_buf = NULL;
998 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300999 while (!list_empty(&vidq->active)) {
1000 struct em28xx_buffer *buf;
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001001
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001002 buf = list_entry(vidq->active.next, struct em28xx_buffer, list);
1003 list_del(&buf->list);
Junghak Sung2d700712015-09-22 10:30:30 -03001004 vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001005 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001006 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001007}
1008
Hans Verkuile37559b2014-04-17 02:47:21 -03001009void em28xx_stop_vbi_streaming(struct vb2_queue *vq)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001010{
1011 struct em28xx *dev = vb2_get_drv_priv(vq);
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001012 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001013 struct em28xx_dmaqueue *vbiq = &dev->vbiq;
1014 unsigned long flags = 0;
1015
1016 em28xx_videodbg("%s\n", __func__);
1017
1018 res_free(dev, vq->type);
1019
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001020 if (v4l2->streaming_users-- == 1) {
Mauro Carvalho Chehab13d52fe2016-01-26 06:59:39 -02001021 /* Disable video stream at TV decoder */
1022 v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_stream, 0);
1023
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001024 /* Last active user, so shutdown all the URBS */
1025 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
1026 }
1027
1028 spin_lock_irqsave(&dev->slock, flags);
Frank Schaefer627530c2014-08-09 06:37:20 -03001029 if (dev->usb_ctl.vbi_buf != NULL) {
Junghak Sung2d700712015-09-22 10:30:30 -03001030 vb2_buffer_done(&dev->usb_ctl.vbi_buf->vb.vb2_buf,
1031 VB2_BUF_STATE_ERROR);
Frank Schaefer627530c2014-08-09 06:37:20 -03001032 dev->usb_ctl.vbi_buf = NULL;
1033 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001034 while (!list_empty(&vbiq->active)) {
1035 struct em28xx_buffer *buf;
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001036
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001037 buf = list_entry(vbiq->active.next, struct em28xx_buffer, list);
1038 list_del(&buf->list);
Junghak Sung2d700712015-09-22 10:30:30 -03001039 vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001040 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001041 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001042}
1043
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001044static void
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001045buffer_queue(struct vb2_buffer *vb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001046{
Junghak Sung2d700712015-09-22 10:30:30 -03001047 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001048 struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue);
Junghak Sung2d700712015-09-22 10:30:30 -03001049 struct em28xx_buffer *buf =
1050 container_of(vbuf, struct em28xx_buffer, vb);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001051 struct em28xx_dmaqueue *vidq = &dev->vidq;
1052 unsigned long flags = 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001053
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001054 em28xx_videodbg("%s\n", __func__);
1055 buf->mem = vb2_plane_vaddr(vb, 0);
1056 buf->length = vb2_plane_size(vb, 0);
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001057
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001058 spin_lock_irqsave(&dev->slock, flags);
1059 list_add_tail(&buf->list, &vidq->active);
1060 spin_unlock_irqrestore(&dev->slock, flags);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001061}
1062
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001063static struct vb2_ops em28xx_video_qops = {
1064 .queue_setup = queue_setup,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001065 .buf_prepare = buffer_prepare,
1066 .buf_queue = buffer_queue,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001067 .start_streaming = em28xx_start_analog_streaming,
1068 .stop_streaming = em28xx_stop_streaming,
1069 .wait_prepare = vb2_ops_wait_prepare,
1070 .wait_finish = vb2_ops_wait_finish,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001071};
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001072
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001073static int em28xx_vb2_setup(struct em28xx *dev)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001074{
1075 int rc;
1076 struct vb2_queue *q;
Frank Schaefer27a36df2014-03-24 16:33:13 -03001077 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001078
1079 /* Setup Videobuf2 for Video capture */
Frank Schaefer27a36df2014-03-24 16:33:13 -03001080 q = &v4l2->vb_vidq;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001081 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Mauro Carvalho Chehabef85cd92013-01-06 00:34:22 -02001082 q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
Sakari Ailusade48682014-02-25 19:12:19 -03001083 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001084 q->drv_priv = dev;
1085 q->buf_struct_size = sizeof(struct em28xx_buffer);
1086 q->ops = &em28xx_video_qops;
1087 q->mem_ops = &vb2_vmalloc_memops;
1088
1089 rc = vb2_queue_init(q);
1090 if (rc < 0)
1091 return rc;
1092
1093 /* Setup Videobuf2 for VBI capture */
Frank Schaefer27a36df2014-03-24 16:33:13 -03001094 q = &v4l2->vb_vbiq;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001095 q->type = V4L2_BUF_TYPE_VBI_CAPTURE;
1096 q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR;
Sakari Ailusade48682014-02-25 19:12:19 -03001097 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001098 q->drv_priv = dev;
1099 q->buf_struct_size = sizeof(struct em28xx_buffer);
1100 q->ops = &em28xx_vbi_qops;
1101 q->mem_ops = &vb2_vmalloc_memops;
1102
1103 rc = vb2_queue_init(q);
1104 if (rc < 0)
1105 return rc;
1106
1107 return 0;
1108}
1109
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001110/********************* v4l2 interface **************************************/
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001111
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001112static void video_mux(struct em28xx *dev, int index)
1113{
Frank Schaefer95d26082014-03-24 16:33:09 -03001114 struct v4l2_device *v4l2_dev = &dev->v4l2->v4l2_dev;
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001115
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001116 dev->ctl_input = index;
1117 dev->ctl_ainput = INPUT(index)->amux;
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001118 dev->ctl_aoutput = INPUT(index)->aout;
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001119
Mauro Carvalho Chehabe879b8e2008-11-20 13:39:39 -03001120 if (!dev->ctl_aoutput)
1121 dev->ctl_aoutput = EM28XX_AOUT_MASTER;
1122
Frank Schaefer95d26082014-03-24 16:33:09 -03001123 v4l2_device_call_all(v4l2_dev, 0, video, s_routing,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001124 INPUT(index)->vmux, 0, 0);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001125
Mauro Carvalho Chehab505b6d02008-11-25 09:39:50 -03001126 if (dev->board.has_msp34xx) {
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001127 if (dev->i2s_speed) {
Frank Schaefer95d26082014-03-24 16:33:09 -03001128 v4l2_device_call_all(v4l2_dev, 0, audio,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001129 s_i2s_clock_freq, dev->i2s_speed);
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001130 }
Hans Verkuil2474ed42006-03-19 12:35:57 -03001131 /* Note: this is msp3400 specific */
Frank Schaefer95d26082014-03-24 16:33:09 -03001132 v4l2_device_call_all(v4l2_dev, 0, audio, s_routing,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001133 dev->ctl_ainput,
1134 MSP_OUTPUT(MSP_SC_IN_DSP_SCART1), 0);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001135 }
Mauro Carvalho Chehab539c96d2008-01-05 09:53:54 -03001136
Vitaly Wool2bd1d9e2009-03-04 08:27:52 -03001137 if (dev->board.adecoder != EM28XX_NOADECODER) {
Frank Schaefer95d26082014-03-24 16:33:09 -03001138 v4l2_device_call_all(v4l2_dev, 0, audio, s_routing,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001139 dev->ctl_ainput, dev->ctl_aoutput, 0);
Vitaly Wool2bd1d9e2009-03-04 08:27:52 -03001140 }
1141
Mauro Carvalho Chehab00b87302008-02-06 18:34:13 -03001142 em28xx_audio_analog_set(dev);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001143}
1144
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001145static void em28xx_ctrl_notify(struct v4l2_ctrl *ctrl, void *priv)
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001146{
Hans Verkuil081b9452012-09-07 05:43:59 -03001147 struct em28xx *dev = priv;
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001148
Hans Verkuil081b9452012-09-07 05:43:59 -03001149 /*
1150 * In the case of non-AC97 volume controls, we still need
1151 * to do some setups at em28xx, in order to mute/unmute
1152 * and to adjust audio volume. However, the value ranges
1153 * should be checked by the corresponding V4L subdriver.
1154 */
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001155 switch (ctrl->id) {
1156 case V4L2_CID_AUDIO_MUTE:
Hans Verkuil081b9452012-09-07 05:43:59 -03001157 dev->mute = ctrl->val;
1158 em28xx_audio_analog_set(dev);
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001159 break;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001160 case V4L2_CID_AUDIO_VOLUME:
Hans Verkuil081b9452012-09-07 05:43:59 -03001161 dev->volume = ctrl->val;
1162 em28xx_audio_analog_set(dev);
1163 break;
1164 }
1165}
1166
1167static int em28xx_s_ctrl(struct v4l2_ctrl *ctrl)
1168{
Frank Schaeferabc13082014-03-24 16:33:10 -03001169 struct em28xx_v4l2 *v4l2 =
1170 container_of(ctrl->handler, struct em28xx_v4l2, ctrl_handler);
1171 struct em28xx *dev = v4l2->dev;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001172 int ret = -EINVAL;
Hans Verkuil081b9452012-09-07 05:43:59 -03001173
1174 switch (ctrl->id) {
1175 case V4L2_CID_AUDIO_MUTE:
1176 dev->mute = ctrl->val;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001177 ret = em28xx_audio_analog_set(dev);
Hans Verkuil081b9452012-09-07 05:43:59 -03001178 break;
1179 case V4L2_CID_AUDIO_VOLUME:
1180 dev->volume = ctrl->val;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001181 ret = em28xx_audio_analog_set(dev);
1182 break;
1183 case V4L2_CID_CONTRAST:
1184 ret = em28xx_write_reg(dev, EM28XX_R20_YGAIN, ctrl->val);
1185 break;
1186 case V4L2_CID_BRIGHTNESS:
1187 ret = em28xx_write_reg(dev, EM28XX_R21_YOFFSET, ctrl->val);
1188 break;
1189 case V4L2_CID_SATURATION:
1190 ret = em28xx_write_reg(dev, EM28XX_R22_UVGAIN, ctrl->val);
1191 break;
1192 case V4L2_CID_BLUE_BALANCE:
1193 ret = em28xx_write_reg(dev, EM28XX_R23_UOFFSET, ctrl->val);
1194 break;
1195 case V4L2_CID_RED_BALANCE:
1196 ret = em28xx_write_reg(dev, EM28XX_R24_VOFFSET, ctrl->val);
1197 break;
1198 case V4L2_CID_SHARPNESS:
1199 ret = em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, ctrl->val);
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001200 break;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001201 }
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001202
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001203 return (ret < 0) ? ret : 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001204}
1205
Fengguang Wu8068eb82014-01-07 12:50:47 -03001206static const struct v4l2_ctrl_ops em28xx_ctrl_ops = {
Hans Verkuil081b9452012-09-07 05:43:59 -03001207 .s_ctrl = em28xx_s_ctrl,
1208};
1209
Frank Schaefer6b09a212013-02-10 16:05:12 -03001210static void size_to_scale(struct em28xx *dev,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001211 unsigned int width, unsigned int height,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001212 unsigned int *hscale, unsigned int *vscale)
1213{
Mauro Carvalho Chehab55699962009-07-13 20:15:02 -03001214 unsigned int maxw = norm_maxw(dev);
1215 unsigned int maxh = norm_maxh(dev);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001216
1217 *hscale = (((unsigned long)maxw) << 12) / width - 4096L;
Frank Schaefer81685322013-02-10 16:05:11 -03001218 if (*hscale > EM28XX_HVSCALE_MAX)
1219 *hscale = EM28XX_HVSCALE_MAX;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001220
1221 *vscale = (((unsigned long)maxh) << 12) / height - 4096L;
Frank Schaefer81685322013-02-10 16:05:11 -03001222 if (*vscale > EM28XX_HVSCALE_MAX)
1223 *vscale = EM28XX_HVSCALE_MAX;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001224}
1225
Frank Schaeferb8374132013-02-10 16:05:13 -03001226static void scale_to_size(struct em28xx *dev,
1227 unsigned int hscale, unsigned int vscale,
1228 unsigned int *width, unsigned int *height)
1229{
1230 unsigned int maxw = norm_maxw(dev);
1231 unsigned int maxh = norm_maxh(dev);
1232
1233 *width = (((unsigned long)maxw) << 12) / (hscale + 4096L);
1234 *height = (((unsigned long)maxh) << 12) / (vscale + 4096L);
1235}
1236
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001237/* ------------------------------------------------------------------
1238 IOCTL vidioc handling
1239 ------------------------------------------------------------------*/
1240
Hans Verkuil78b526a2008-05-28 12:16:41 -03001241static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001242 struct v4l2_format *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001243{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001244 struct em28xx *dev = video_drvdata(file);
Frank Schaefer753aee72014-03-24 16:33:14 -03001245 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001246
Frank Schaefer753aee72014-03-24 16:33:14 -03001247 f->fmt.pix.width = v4l2->width;
1248 f->fmt.pix.height = v4l2->height;
Frank Schaefer06e20672014-03-24 16:33:17 -03001249 f->fmt.pix.pixelformat = v4l2->format->fourcc;
1250 f->fmt.pix.bytesperline = (v4l2->width * v4l2->format->depth + 7) >> 3;
Frank Schaefer753aee72014-03-24 16:33:14 -03001251 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * v4l2->height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001252 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
1253
1254 /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */
Frank Schaefer58159172014-03-24 16:33:18 -03001255 if (v4l2->progressive)
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -03001256 f->fmt.pix.field = V4L2_FIELD_NONE;
1257 else
Frank Schaefer58159172014-03-24 16:33:18 -03001258 f->fmt.pix.field = v4l2->interlaced_fieldmode ?
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001259 V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001260 return 0;
1261}
1262
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001263static struct em28xx_fmt *format_by_fourcc(unsigned int fourcc)
1264{
1265 unsigned int i;
1266
1267 for (i = 0; i < ARRAY_SIZE(format); i++)
1268 if (format[i].fourcc == fourcc)
1269 return &format[i];
1270
1271 return NULL;
1272}
1273
Hans Verkuil78b526a2008-05-28 12:16:41 -03001274static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001275 struct v4l2_format *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001276{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001277 struct em28xx *dev = video_drvdata(file);
Frank Schaefer58159172014-03-24 16:33:18 -03001278 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Trent Piephoccb83402009-05-30 21:45:46 -03001279 unsigned int width = f->fmt.pix.width;
1280 unsigned int height = f->fmt.pix.height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001281 unsigned int maxw = norm_maxw(dev);
1282 unsigned int maxh = norm_maxh(dev);
1283 unsigned int hscale, vscale;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001284 struct em28xx_fmt *fmt;
1285
1286 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
1287 if (!fmt) {
1288 em28xx_videodbg("Fourcc format (%08x) invalid.\n",
1289 f->fmt.pix.pixelformat);
1290 return -EINVAL;
1291 }
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001292
Mauro Carvalho Chehab55699962009-07-13 20:15:02 -03001293 if (dev->board.is_em2800) {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001294 /* the em2800 can only scale down to 50% */
Trent Piephoccb83402009-05-30 21:45:46 -03001295 height = height > (3 * maxh / 4) ? maxh : maxh / 2;
1296 width = width > (3 * maxw / 4) ? maxw : maxw / 2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001297 /*
1298 * MaxPacketSize for em2800 is too small to capture at full
1299 * resolution use half of maxw as the scaler can only scale
1300 * to 50%
1301 */
Sascha Sommer1020d132012-01-08 16:54:28 -03001302 if (width == maxw && height == maxh)
1303 width /= 2;
Trent Piephoccb83402009-05-30 21:45:46 -03001304 } else {
1305 /* width must even because of the YUYV format
1306 height must be even because of interlacing */
Devin Heitmuellere3ba4d32009-09-15 00:18:06 -03001307 v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh,
1308 1, 0);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001309 }
1310
Frank Schaefer6b09a212013-02-10 16:05:12 -03001311 size_to_scale(dev, width, height, &hscale, &vscale);
Hans Verkuil46f85972013-03-30 05:31:42 -03001312 scale_to_size(dev, hscale, vscale, &width, &height);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001313
1314 f->fmt.pix.width = width;
1315 f->fmt.pix.height = height;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001316 f->fmt.pix.pixelformat = fmt->fourcc;
Hans Verkuile6066db2013-02-06 08:14:47 -03001317 f->fmt.pix.bytesperline = (width * fmt->depth + 7) >> 3;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001318 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001319 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
Frank Schaefer58159172014-03-24 16:33:18 -03001320 if (v4l2->progressive)
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -03001321 f->fmt.pix.field = V4L2_FIELD_NONE;
1322 else
Frank Schaefer58159172014-03-24 16:33:18 -03001323 f->fmt.pix.field = v4l2->interlaced_fieldmode ?
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -03001324 V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
Alban Browaeys51dd4d72013-07-16 19:06:46 -03001325 f->fmt.pix.priv = 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001326
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001327 return 0;
1328}
1329
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001330static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc,
1331 unsigned width, unsigned height)
1332{
1333 struct em28xx_fmt *fmt;
Frank Schaefer753aee72014-03-24 16:33:14 -03001334 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001335
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001336 fmt = format_by_fourcc(fourcc);
1337 if (!fmt)
1338 return -EINVAL;
1339
Frank Schaefer06e20672014-03-24 16:33:17 -03001340 v4l2->format = fmt;
Frank Schaefer753aee72014-03-24 16:33:14 -03001341 v4l2->width = width;
1342 v4l2->height = height;
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001343
1344 /* set new image size */
Frank Schaefer753aee72014-03-24 16:33:14 -03001345 size_to_scale(dev, v4l2->width, v4l2->height,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001346 &v4l2->hscale, &v4l2->vscale);
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001347
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001348 em28xx_resolution_set(dev);
1349
1350 return 0;
1351}
1352
Hans Verkuil78b526a2008-05-28 12:16:41 -03001353static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001354 struct v4l2_format *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001355{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001356 struct em28xx *dev = video_drvdata(file);
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001357 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001358
Mauro Carvalho Chehabc7854c22014-09-19 13:02:12 -03001359 if (vb2_is_busy(&v4l2->vb_vidq))
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001360 return -EBUSY;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001361
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001362 vidioc_try_fmt_vid_cap(file, priv, f);
1363
Hans Verkuil0499a5a2010-09-26 07:34:45 -03001364 return em28xx_set_video_format(dev, f->fmt.pix.pixelformat,
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001365 f->fmt.pix.width, f->fmt.pix.height);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001366}
1367
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001368static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
1369{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001370 struct em28xx *dev = video_drvdata(file);
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001371
Frank Schaefer52faaf72014-03-24 16:33:16 -03001372 *norm = dev->v4l2->norm;
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001373
1374 return 0;
1375}
1376
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001377static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm)
1378{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001379 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001380
Frank Schaefer95d26082014-03-24 16:33:09 -03001381 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, video, querystd, norm);
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001382
1383 return 0;
1384}
1385
Hans Verkuil314527a2013-03-15 06:10:40 -03001386static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001387{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001388 struct em28xx *dev = video_drvdata(file);
Frank Schaefer753aee72014-03-24 16:33:14 -03001389 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001390 struct v4l2_format f;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001391
Frank Schaefer52faaf72014-03-24 16:33:16 -03001392 if (norm == v4l2->norm)
Hans Verkuild8c95c02012-09-07 07:31:54 -03001393 return 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001394
Frank Schaefer8139a4d2014-05-11 17:59:04 -03001395 if (v4l2->streaming_users > 0)
Hans Verkuild8c95c02012-09-07 07:31:54 -03001396 return -EBUSY;
Hans Verkuild8c95c02012-09-07 07:31:54 -03001397
Frank Schaefer52faaf72014-03-24 16:33:16 -03001398 v4l2->norm = norm;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001399
1400 /* Adjusts width/height, if needed */
Hans Verkuild8c95c02012-09-07 07:31:54 -03001401 f.fmt.pix.width = 720;
Hans Verkuil314527a2013-03-15 06:10:40 -03001402 f.fmt.pix.height = (norm & V4L2_STD_525_60) ? 480 : 576;
Hans Verkuil78b526a2008-05-28 12:16:41 -03001403 vidioc_try_fmt_vid_cap(file, priv, &f);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001404
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001405 /* set new image size */
Frank Schaefer753aee72014-03-24 16:33:14 -03001406 v4l2->width = f.fmt.pix.width;
1407 v4l2->height = f.fmt.pix.height;
1408 size_to_scale(dev, v4l2->width, v4l2->height,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001409 &v4l2->hscale, &v4l2->vscale);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001410
1411 em28xx_resolution_set(dev);
Laurent Pinchart8774bed2014-04-28 16:53:01 -03001412 v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_std, v4l2->norm);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001413
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001414 return 0;
1415}
1416
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001417static int vidioc_g_parm(struct file *file, void *priv,
1418 struct v4l2_streamparm *p)
1419{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001420 struct em28xx *dev = video_drvdata(file);
Frank Schaefer52faaf72014-03-24 16:33:16 -03001421 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001422 int rc = 0;
1423
Hans Verkuil86ff7f12012-09-07 06:16:03 -03001424 p->parm.capture.readbuffers = EM28XX_MIN_BUF;
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001425 if (dev->board.is_webcam)
Frank Schaefer52faaf72014-03-24 16:33:16 -03001426 rc = v4l2_device_call_until_err(&v4l2->v4l2_dev, 0,
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001427 video, g_parm, p);
1428 else
Frank Schaefer52faaf72014-03-24 16:33:16 -03001429 v4l2_video_std_frame_period(v4l2->norm,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001430 &p->parm.capture.timeperframe);
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001431
1432 return rc;
1433}
1434
1435static int vidioc_s_parm(struct file *file, void *priv,
1436 struct v4l2_streamparm *p)
1437{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001438 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001439
Hans Verkuil86ff7f12012-09-07 06:16:03 -03001440 p->parm.capture.readbuffers = EM28XX_MIN_BUF;
Frank Schaefer95d26082014-03-24 16:33:09 -03001441 return v4l2_device_call_until_err(&dev->v4l2->v4l2_dev,
1442 0, video, s_parm, p);
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001443}
1444
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001445static const char *iname[] = {
1446 [EM28XX_VMUX_COMPOSITE1] = "Composite1",
1447 [EM28XX_VMUX_COMPOSITE2] = "Composite2",
1448 [EM28XX_VMUX_COMPOSITE3] = "Composite3",
1449 [EM28XX_VMUX_COMPOSITE4] = "Composite4",
1450 [EM28XX_VMUX_SVIDEO] = "S-Video",
1451 [EM28XX_VMUX_TELEVISION] = "Television",
1452 [EM28XX_VMUX_CABLE] = "Cable TV",
1453 [EM28XX_VMUX_DVB] = "DVB",
1454 [EM28XX_VMUX_DEBUG] = "for debug only",
1455};
1456
1457static int vidioc_enum_input(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001458 struct v4l2_input *i)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001459{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001460 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001461 unsigned int n;
1462
1463 n = i->index;
1464 if (n >= MAX_EM28XX_INPUT)
1465 return -EINVAL;
1466 if (0 == INPUT(n)->type)
1467 return -EINVAL;
1468
1469 i->index = n;
1470 i->type = V4L2_INPUT_TYPE_CAMERA;
1471
1472 strcpy(i->name, iname[INPUT(n)->type]);
1473
1474 if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type) ||
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001475 (EM28XX_VMUX_CABLE == INPUT(n)->type))
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001476 i->type = V4L2_INPUT_TYPE_TUNER;
1477
Hans Verkuild4352f32015-03-09 13:34:06 -03001478 i->std = dev->v4l2->vdev.tvnorms;
Hans Verkuild8c95c02012-09-07 07:31:54 -03001479 /* webcams do not have the STD API */
1480 if (dev->board.is_webcam)
1481 i->capabilities = 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001482
1483 return 0;
1484}
1485
1486static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1487{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001488 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001489
1490 *i = dev->ctl_input;
1491
1492 return 0;
1493}
1494
1495static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
1496{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001497 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001498
1499 if (i >= MAX_EM28XX_INPUT)
1500 return -EINVAL;
1501 if (0 == INPUT(i)->type)
1502 return -EINVAL;
1503
Ezequiel García96371fc2012-03-23 18:09:34 -03001504 video_mux(dev, i);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001505 return 0;
1506}
1507
1508static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
1509{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001510 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001511
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001512 switch (a->index) {
1513 case EM28XX_AMUX_VIDEO:
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001514 strcpy(a->name, "Television");
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001515 break;
1516 case EM28XX_AMUX_LINE_IN:
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001517 strcpy(a->name, "Line In");
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001518 break;
1519 case EM28XX_AMUX_VIDEO2:
1520 strcpy(a->name, "Television alt");
1521 break;
1522 case EM28XX_AMUX_PHONE:
1523 strcpy(a->name, "Phone");
1524 break;
1525 case EM28XX_AMUX_MIC:
1526 strcpy(a->name, "Mic");
1527 break;
1528 case EM28XX_AMUX_CD:
1529 strcpy(a->name, "CD");
1530 break;
1531 case EM28XX_AMUX_AUX:
1532 strcpy(a->name, "Aux");
1533 break;
1534 case EM28XX_AMUX_PCM_OUT:
1535 strcpy(a->name, "PCM");
1536 break;
1537 default:
1538 return -EINVAL;
1539 }
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001540
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001541 a->index = dev->ctl_ainput;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001542 a->capability = V4L2_AUDCAP_STEREO;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001543
1544 return 0;
1545}
1546
Hans Verkuil0e8025b92012-09-04 11:59:31 -03001547static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001548{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001549 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001550
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03001551 if (a->index >= MAX_EM28XX_INPUT)
1552 return -EINVAL;
1553 if (0 == INPUT(a->index)->type)
1554 return -EINVAL;
1555
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001556 dev->ctl_ainput = INPUT(a->index)->amux;
1557 dev->ctl_aoutput = INPUT(a->index)->aout;
Mauro Carvalho Chehabe879b8e2008-11-20 13:39:39 -03001558
1559 if (!dev->ctl_aoutput)
1560 dev->ctl_aoutput = EM28XX_AOUT_MASTER;
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001561
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001562 return 0;
1563}
1564
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001565static int vidioc_g_tuner(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001566 struct v4l2_tuner *t)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001567{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001568 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001569
1570 if (0 != t->index)
1571 return -EINVAL;
1572
1573 strcpy(t->name, "Tuner");
1574
Frank Schaefer95d26082014-03-24 16:33:09 -03001575 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, g_tuner, t);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001576 return 0;
1577}
1578
1579static int vidioc_s_tuner(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001580 const struct v4l2_tuner *t)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001581{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001582 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001583
1584 if (0 != t->index)
1585 return -EINVAL;
1586
Frank Schaefer95d26082014-03-24 16:33:09 -03001587 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, s_tuner, t);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001588 return 0;
1589}
1590
1591static int vidioc_g_frequency(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001592 struct v4l2_frequency *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001593{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001594 struct em28xx *dev = video_drvdata(file);
Frank Schaefer3854b0d2014-03-24 16:33:22 -03001595 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001596
Hans Verkuil20deebf2012-09-06 10:07:25 -03001597 if (0 != f->tuner)
1598 return -EINVAL;
1599
Frank Schaefer3854b0d2014-03-24 16:33:22 -03001600 f->frequency = v4l2->frequency;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001601 return 0;
1602}
1603
1604static int vidioc_s_frequency(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001605 const struct v4l2_frequency *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001606{
Frank Schaefer95d26082014-03-24 16:33:09 -03001607 struct v4l2_frequency new_freq = *f;
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001608 struct em28xx *dev = video_drvdata(file);
Frank Schaefer95d26082014-03-24 16:33:09 -03001609 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001610
1611 if (0 != f->tuner)
1612 return -EINVAL;
1613
Frank Schaefer95d26082014-03-24 16:33:09 -03001614 v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, s_frequency, f);
1615 v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, g_frequency, &new_freq);
Frank Schaefer3854b0d2014-03-24 16:33:22 -03001616 v4l2->frequency = new_freq.frequency;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001617
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001618 return 0;
1619}
1620
Hans Verkuilcd634f12013-03-27 08:04:23 -03001621#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuil96b03d22013-04-06 06:16:58 -03001622static int vidioc_g_chip_info(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001623 struct v4l2_dbg_chip_info *chip)
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001624{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001625 struct em28xx *dev = video_drvdata(file);
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001626
1627 if (chip->match.addr > 1)
1628 return -EINVAL;
1629 if (chip->match.addr == 1)
1630 strlcpy(chip->name, "ac97", sizeof(chip->name));
1631 else
Frank Schaefer95d26082014-03-24 16:33:09 -03001632 strlcpy(chip->name,
1633 dev->v4l2->v4l2_dev.name, sizeof(chip->name));
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001634 return 0;
1635}
1636
Frank Schaefer35deba32013-02-07 13:39:19 -03001637static int em28xx_reg_len(int reg)
1638{
1639 switch (reg) {
1640 case EM28XX_R40_AC97LSB:
1641 case EM28XX_R30_HSCALELOW:
1642 case EM28XX_R32_VSCALELOW:
1643 return 2;
1644 default:
1645 return 1;
1646 }
1647}
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001648
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001649static int vidioc_g_register(struct file *file, void *priv,
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001650 struct v4l2_dbg_register *reg)
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001651{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001652 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001653 int ret;
1654
Hans Verkuilabca2052013-05-29 06:59:35 -03001655 if (reg->match.addr > 1)
1656 return -EINVAL;
1657 if (reg->match.addr) {
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001658 ret = em28xx_read_ac97(dev, reg->reg);
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001659 if (ret < 0)
1660 return ret;
1661
1662 reg->val = ret;
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001663 reg->size = 1;
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001664 return 0;
1665 }
1666
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001667 /* Match host */
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001668 reg->size = em28xx_reg_len(reg->reg);
1669 if (reg->size == 1) {
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001670 ret = em28xx_read_reg(dev, reg->reg);
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001671
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001672 if (ret < 0)
1673 return ret;
1674
1675 reg->val = ret;
1676 } else {
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001677 __le16 val = 0;
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001678
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001679 ret = dev->em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001680 reg->reg, (char *)&val, 2);
1681 if (ret < 0)
1682 return ret;
1683
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001684 reg->val = le16_to_cpu(val);
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001685 }
1686
1687 return 0;
1688}
1689
1690static int vidioc_s_register(struct file *file, void *priv,
Hans Verkuil977ba3b2013-03-24 08:28:46 -03001691 const struct v4l2_dbg_register *reg)
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001692{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001693 struct em28xx *dev = video_drvdata(file);
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001694 __le16 buf;
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001695
Hans Verkuilabca2052013-05-29 06:59:35 -03001696 if (reg->match.addr > 1)
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001697 return -EINVAL;
Hans Verkuilabca2052013-05-29 06:59:35 -03001698 if (reg->match.addr)
1699 return em28xx_write_ac97(dev, reg->reg, reg->val);
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001700
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001701 /* Match host */
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001702 buf = cpu_to_le16(reg->val);
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001703
Hans Verkuil0499a5a2010-09-26 07:34:45 -03001704 return em28xx_write_regs(dev, reg->reg, (char *)&buf,
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001705 em28xx_reg_len(reg->reg));
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001706}
1707#endif
1708
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001709static int vidioc_querycap(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001710 struct v4l2_capability *cap)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001711{
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001712 struct video_device *vdev = video_devdata(file);
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001713 struct em28xx *dev = video_drvdata(file);
Frank Schaeferef74a0b2014-03-24 16:33:12 -03001714 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001715
1716 strlcpy(cap->driver, "em28xx", sizeof(cap->driver));
1717 strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card));
Thierry MERLEcb977162009-01-20 18:01:33 -03001718 usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001719
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001720 if (vdev->vfl_type == VFL_TYPE_GRABBER)
1721 cap->device_caps = V4L2_CAP_READWRITE |
1722 V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1723 else if (vdev->vfl_type == VFL_TYPE_RADIO)
1724 cap->device_caps = V4L2_CAP_RADIO;
1725 else
Hans Verkuil1d179ee2012-09-07 08:45:10 -03001726 cap->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE;
Devin Heitmueller04146142009-09-11 00:08:44 -03001727
Frank Schaefer920f1e42014-09-13 05:52:21 -03001728 if (dev->int_audio_type != EM28XX_INT_AUDIO_NONE)
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001729 cap->device_caps |= V4L2_CAP_AUDIO;
Mauro Carvalho Chehab6c428b52009-08-04 19:52:37 -03001730
Mauro Carvalho Chehabed086312008-01-24 06:59:20 -03001731 if (dev->tuner_type != TUNER_ABSENT)
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001732 cap->device_caps |= V4L2_CAP_TUNER;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001733
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001734 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS |
1735 V4L2_CAP_READWRITE | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
Hans Verkuild4352f32015-03-09 13:34:06 -03001736 if (video_is_registered(&v4l2->vbi_dev))
Hans Verkuil1d179ee2012-09-07 08:45:10 -03001737 cap->capabilities |= V4L2_CAP_VBI_CAPTURE;
Hans Verkuild4352f32015-03-09 13:34:06 -03001738 if (video_is_registered(&v4l2->radio_dev))
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001739 cap->capabilities |= V4L2_CAP_RADIO;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001740 return 0;
1741}
1742
Hans Verkuil78b526a2008-05-28 12:16:41 -03001743static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03001744 struct v4l2_fmtdesc *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001745{
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001746 if (unlikely(f->index >= ARRAY_SIZE(format)))
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001747 return -EINVAL;
1748
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001749 strlcpy(f->description, format[f->index].name, sizeof(f->description));
1750 f->pixelformat = format[f->index].fourcc;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001751
1752 return 0;
1753}
1754
Mauro Carvalho Chehab1c5c5062011-10-16 13:52:43 -02001755static int vidioc_enum_framesizes(struct file *file, void *priv,
1756 struct v4l2_frmsizeenum *fsize)
1757{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001758 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab1c5c5062011-10-16 13:52:43 -02001759 struct em28xx_fmt *fmt;
1760 unsigned int maxw = norm_maxw(dev);
1761 unsigned int maxh = norm_maxh(dev);
1762
1763 fmt = format_by_fourcc(fsize->pixel_format);
1764 if (!fmt) {
1765 em28xx_videodbg("Fourcc format (%08x) invalid.\n",
1766 fsize->pixel_format);
1767 return -EINVAL;
1768 }
1769
1770 if (dev->board.is_em2800) {
1771 if (fsize->index > 1)
1772 return -EINVAL;
1773 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
1774 fsize->discrete.width = maxw / (1 + fsize->index);
1775 fsize->discrete.height = maxh / (1 + fsize->index);
1776 return 0;
1777 }
1778
1779 if (fsize->index != 0)
1780 return -EINVAL;
1781
1782 /* Report a continuous range */
1783 fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
Frank Schaefer6c3598e2013-02-10 16:05:14 -03001784 scale_to_size(dev, EM28XX_HVSCALE_MAX, EM28XX_HVSCALE_MAX,
1785 &fsize->stepwise.min_width, &fsize->stepwise.min_height);
1786 if (fsize->stepwise.min_width < 48)
1787 fsize->stepwise.min_width = 48;
1788 if (fsize->stepwise.min_height < 38)
1789 fsize->stepwise.min_height = 38;
Mauro Carvalho Chehab1c5c5062011-10-16 13:52:43 -02001790 fsize->stepwise.max_width = maxw;
1791 fsize->stepwise.max_height = maxh;
1792 fsize->stepwise.step_width = 1;
1793 fsize->stepwise.step_height = 1;
1794 return 0;
1795}
1796
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001797/* RAW VBI ioctls */
1798
1799static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
1800 struct v4l2_format *format)
1801{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001802 struct em28xx *dev = video_drvdata(file);
Frank Schaefer753aee72014-03-24 16:33:14 -03001803 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001804
Frank Schaefer753aee72014-03-24 16:33:14 -03001805 format->fmt.vbi.samples_per_line = v4l2->vbi_width;
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001806 format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
1807 format->fmt.vbi.offset = 0;
1808 format->fmt.vbi.flags = 0;
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001809 format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
Frank Schaefer753aee72014-03-24 16:33:14 -03001810 format->fmt.vbi.count[0] = v4l2->vbi_height;
1811 format->fmt.vbi.count[1] = v4l2->vbi_height;
Hans Verkuil2a221d32012-09-07 08:51:32 -03001812 memset(format->fmt.vbi.reserved, 0, sizeof(format->fmt.vbi.reserved));
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001813
1814 /* Varies by video standard (NTSC, PAL, etc.) */
Frank Schaefer52faaf72014-03-24 16:33:16 -03001815 if (v4l2->norm & V4L2_STD_525_60) {
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001816 /* NTSC */
1817 format->fmt.vbi.start[0] = 10;
1818 format->fmt.vbi.start[1] = 273;
Frank Schaefer52faaf72014-03-24 16:33:16 -03001819 } else if (v4l2->norm & V4L2_STD_625_50) {
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001820 /* PAL */
1821 format->fmt.vbi.start[0] = 6;
1822 format->fmt.vbi.start[1] = 318;
1823 }
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001824
1825 return 0;
1826}
1827
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001828/* ----------------------------------------------------------- */
1829/* RADIO ESPECIFIC IOCTLS */
1830/* ----------------------------------------------------------- */
1831
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001832static int radio_g_tuner(struct file *file, void *priv,
1833 struct v4l2_tuner *t)
1834{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001835 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001836
1837 if (unlikely(t->index > 0))
1838 return -EINVAL;
1839
1840 strcpy(t->name, "Radio");
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001841
Frank Schaefer95d26082014-03-24 16:33:09 -03001842 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, g_tuner, t);
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001843
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001844 return 0;
1845}
1846
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001847static int radio_s_tuner(struct file *file, void *priv,
Hans Verkuil2f73c7c2013-03-15 06:10:06 -03001848 const struct v4l2_tuner *t)
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001849{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03001850 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001851
1852 if (0 != t->index)
1853 return -EINVAL;
1854
Frank Schaefer95d26082014-03-24 16:33:09 -03001855 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, s_tuner, t);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001856
1857 return 0;
1858}
1859
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001860/*
Frank Schaefer95d26082014-03-24 16:33:09 -03001861 * em28xx_free_v4l2() - Free struct em28xx_v4l2
1862 *
1863 * @ref: struct kref for struct em28xx_v4l2
1864 *
1865 * Called when all users of struct em28xx_v4l2 are gone
1866 */
Mauro Carvalho Chehabf472c0b2014-05-23 14:29:44 -03001867static void em28xx_free_v4l2(struct kref *ref)
Frank Schaefer95d26082014-03-24 16:33:09 -03001868{
1869 struct em28xx_v4l2 *v4l2 = container_of(ref, struct em28xx_v4l2, ref);
1870
Frank Schaeferabc13082014-03-24 16:33:10 -03001871 v4l2->dev->v4l2 = NULL;
Frank Schaefer95d26082014-03-24 16:33:09 -03001872 kfree(v4l2);
1873}
1874
1875/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08001876 * em28xx_v4l2_open()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001877 * inits the device and starts isoc transfer
1878 */
Hans Verkuilbec43662008-12-30 06:58:20 -03001879static int em28xx_v4l2_open(struct file *filp)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001880{
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001881 struct video_device *vdev = video_devdata(filp);
1882 struct em28xx *dev = video_drvdata(filp);
Frank Schaefer95d26082014-03-24 16:33:09 -03001883 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001884 enum v4l2_buf_type fh_type = 0;
Frank Schaefer3c0f90e2014-07-25 14:48:57 -03001885 int ret;
Markus Rechberger9c755412005-11-08 21:37:52 -08001886
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001887 switch (vdev->vfl_type) {
1888 case VFL_TYPE_GRABBER:
1889 fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1890 break;
1891 case VFL_TYPE_VBI:
1892 fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
1893 break;
Frank Schaefer4e170242014-01-12 13:24:18 -03001894 case VFL_TYPE_RADIO:
1895 break;
1896 default:
1897 return -EINVAL;
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001898 }
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03001899
Frank Schaefer8e2c8712014-09-18 17:55:45 -03001900 em28xx_videodbg("open dev=%s type=%s users=%d\n",
1901 video_device_node_name(vdev), v4l2_type_names[fh_type],
1902 v4l2->users);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001903
Hans Verkuil876cb142012-06-23 08:12:47 -03001904 if (mutex_lock_interruptible(&dev->lock))
1905 return -ERESTARTSYS;
Frank Schaefer3c0f90e2014-07-25 14:48:57 -03001906
1907 ret = v4l2_fh_open(filp);
1908 if (ret) {
1909 em28xx_errdev("%s: v4l2_fh_open() returned error %d\n",
1910 __func__, ret);
Hans Verkuil876cb142012-06-23 08:12:47 -03001911 mutex_unlock(&dev->lock);
Frank Schaefer3c0f90e2014-07-25 14:48:57 -03001912 return ret;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001913 }
1914
Frank Schaefer8e2c8712014-09-18 17:55:45 -03001915 if (v4l2->users == 0) {
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001916 em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001917
Frank Schaefer4e170242014-01-12 13:24:18 -03001918 if (vdev->vfl_type != VFL_TYPE_RADIO)
1919 em28xx_resolution_set(dev);
1920
1921 /*
1922 * Needed, since GPIO might have disabled power
1923 * of some i2c devices
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001924 */
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03001925 em28xx_wake_i2c(dev);
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02001926 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001927
1928 if (vdev->vfl_type == VFL_TYPE_RADIO) {
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001929 em28xx_videodbg("video_open: setting radio device\n");
Frank Schaefer95d26082014-03-24 16:33:09 -03001930 v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, s_radio);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001931 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001932
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03001933 kref_get(&dev->ref);
Frank Schaefer95d26082014-03-24 16:33:09 -03001934 kref_get(&v4l2->ref);
Frank Schaefer8e2c8712014-09-18 17:55:45 -03001935 v4l2->users++;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001936
Hans Verkuil876cb142012-06-23 08:12:47 -03001937 mutex_unlock(&dev->lock);
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001938
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001939 return 0;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001940}
1941
1942/*
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001943 * em28xx_v4l2_fini()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001944 * unregisters the v4l2,i2c and usb devices
1945 * called when the device gets disconected or at module unload
1946*/
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001947static int em28xx_v4l2_fini(struct em28xx *dev)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001948{
Frank Schaefer95d26082014-03-24 16:33:09 -03001949 struct em28xx_v4l2 *v4l2 = dev->v4l2;
1950
Mauro Carvalho Chehab822b8de2014-01-06 05:27:47 -03001951 if (dev->is_audio_only) {
1952 /* Shouldn't initialize IR for this interface */
1953 return 0;
1954 }
1955
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001956 if (!dev->has_video) {
1957 /* This device does not support the v4l2 extension */
1958 return 0;
1959 }
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02001960
Frank Schaefer95d26082014-03-24 16:33:09 -03001961 if (v4l2 == NULL)
1962 return 0;
1963
Russell King0418ca62014-12-20 09:45:20 -03001964 em28xx_info("Closing video extension\n");
Mauro Carvalho Chehabaa929ad2014-01-12 19:22:07 -03001965
Mauro Carvalho Chehabebbfbc22014-01-13 02:53:44 -03001966 mutex_lock(&dev->lock);
1967
Frank Schaefer95d26082014-03-24 16:33:09 -03001968 v4l2_device_disconnect(&v4l2->v4l2_dev);
Frank Schaefer5ad10de2014-01-12 13:24:21 -03001969
Frank Schaefer23e86422014-01-12 13:24:20 -03001970 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
1971
Hans Verkuild4352f32015-03-09 13:34:06 -03001972 if (video_is_registered(&v4l2->radio_dev)) {
Frank Schaefere8470222014-01-12 13:24:25 -03001973 em28xx_info("V4L2 device %s deregistered\n",
Hans Verkuild4352f32015-03-09 13:34:06 -03001974 video_device_node_name(&v4l2->radio_dev));
1975 video_unregister_device(&v4l2->radio_dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001976 }
Hans Verkuild4352f32015-03-09 13:34:06 -03001977 if (video_is_registered(&v4l2->vbi_dev)) {
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001978 em28xx_info("V4L2 device %s deregistered\n",
Hans Verkuild4352f32015-03-09 13:34:06 -03001979 video_device_node_name(&v4l2->vbi_dev));
1980 video_unregister_device(&v4l2->vbi_dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001981 }
Hans Verkuild4352f32015-03-09 13:34:06 -03001982 if (video_is_registered(&v4l2->vdev)) {
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001983 em28xx_info("V4L2 device %s deregistered\n",
Hans Verkuild4352f32015-03-09 13:34:06 -03001984 video_device_node_name(&v4l2->vdev));
1985 video_unregister_device(&v4l2->vdev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001986 }
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001987
Frank Schaeferabc13082014-03-24 16:33:10 -03001988 v4l2_ctrl_handler_free(&v4l2->ctrl_handler);
Frank Schaefer95d26082014-03-24 16:33:09 -03001989 v4l2_device_unregister(&v4l2->v4l2_dev);
Frank Schaefer103f18a2014-01-17 14:45:30 -03001990
Frank Schaefer2c52a2f2014-03-24 16:33:11 -03001991 if (v4l2->clk) {
1992 v4l2_clk_unregister_fixed(v4l2->clk);
1993 v4l2->clk = NULL;
Frank Schaefer25dd1652014-01-12 13:24:23 -03001994 }
1995
Frank Schaefer95d26082014-03-24 16:33:09 -03001996 kref_put(&v4l2->ref, em28xx_free_v4l2);
1997
Mauro Carvalho Chehabebbfbc22014-01-13 02:53:44 -03001998 mutex_unlock(&dev->lock);
Frank Schaefer95d26082014-03-24 16:33:09 -03001999
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002000 kref_put(&dev->ref, em28xx_free_device);
Frank Schaefer5ad10de2014-01-12 13:24:21 -03002001
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002002 return 0;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002003}
2004
Shuah Khana61f6812014-02-21 21:50:17 -03002005static int em28xx_v4l2_suspend(struct em28xx *dev)
2006{
2007 if (dev->is_audio_only)
2008 return 0;
2009
2010 if (!dev->has_video)
2011 return 0;
2012
Russell King32e63f02014-12-20 09:45:51 -03002013 em28xx_info("Suspending video extension\n");
Shuah Khana61f6812014-02-21 21:50:17 -03002014 em28xx_stop_urbs(dev);
2015 return 0;
2016}
2017
2018static int em28xx_v4l2_resume(struct em28xx *dev)
2019{
2020 if (dev->is_audio_only)
2021 return 0;
2022
2023 if (!dev->has_video)
2024 return 0;
2025
Russell King32e63f02014-12-20 09:45:51 -03002026 em28xx_info("Resuming video extension\n");
Shuah Khana61f6812014-02-21 21:50:17 -03002027 /* what do we do here */
2028 return 0;
2029}
2030
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002031/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002032 * em28xx_v4l2_close()
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03002033 * stops streaming and deallocates all resources allocated by the v4l2
2034 * calls and ioctls
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002035 */
Hans Verkuilbec43662008-12-30 06:58:20 -03002036static int em28xx_v4l2_close(struct file *filp)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002037{
Frank Schaefer917ba6b2014-07-25 14:48:56 -03002038 struct em28xx *dev = video_drvdata(filp);
Frank Schaefer95d26082014-03-24 16:33:09 -03002039 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03002040 int errCode;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002041
Frank Schaefer8e2c8712014-09-18 17:55:45 -03002042 em28xx_videodbg("users=%d\n", v4l2->users);
2043
2044 vb2_fop_release(filp);
Ricardo Ribalda98c24dcd2013-11-06 05:39:35 -03002045 mutex_lock(&dev->lock);
Devin Heitmueller8c873d32009-09-03 00:23:27 -03002046
Frank Schaefer8e2c8712014-09-18 17:55:45 -03002047 if (v4l2->users == 1) {
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002048 /* No sense to try to write to the device */
2049 if (dev->disconnected)
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002050 goto exit;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03002051
Mauro Carvalho Chehabeb6c9632008-12-05 10:39:12 -03002052 /* Save some power by putting tuner to sleep */
Frank Schaefer95d26082014-03-24 16:33:09 -03002053 v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_power, 0);
Mauro Carvalho Chehabeb6c9632008-12-05 10:39:12 -03002054
Aidan Thorntond7aa8022008-04-13 14:38:47 -03002055 /* do this before setting alternate! */
Mauro Carvalho Chehab2fe3e2e2008-11-27 09:10:40 -03002056 em28xx_set_mode(dev, EM28XX_SUSPEND);
Aidan Thorntond7aa8022008-04-13 14:38:47 -03002057
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03002058 /* set alternate 0 */
2059 dev->alt = 0;
2060 em28xx_videodbg("setting alternate 0\n");
2061 errCode = usb_set_interface(dev->udev, 0, 0);
2062 if (errCode < 0) {
2063 em28xx_errdev("cannot change alternate number to "
2064 "0 (error=%i)\n", errCode);
2065 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002066 }
Devin Heitmueller28abf0832009-09-01 01:54:54 -03002067
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002068exit:
Frank Schaefer8e2c8712014-09-18 17:55:45 -03002069 v4l2->users--;
Frank Schaefer95d26082014-03-24 16:33:09 -03002070 kref_put(&v4l2->ref, em28xx_free_v4l2);
Hans Verkuil876cb142012-06-23 08:12:47 -03002071 mutex_unlock(&dev->lock);
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002072 kref_put(&dev->ref, em28xx_free_device);
2073
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002074 return 0;
2075}
2076
Hans Verkuilbec43662008-12-30 06:58:20 -03002077static const struct v4l2_file_operations em28xx_v4l_fops = {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002078 .owner = THIS_MODULE,
2079 .open = em28xx_v4l2_open,
2080 .release = em28xx_v4l2_close,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002081 .read = vb2_fop_read,
2082 .poll = vb2_fop_poll,
2083 .mmap = vb2_fop_mmap,
Hans Verkuil0499a5a2010-09-26 07:34:45 -03002084 .unlocked_ioctl = video_ioctl2,
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002085};
2086
Hans Verkuila3998102008-07-21 02:57:38 -03002087static const struct v4l2_ioctl_ops video_ioctl_ops = {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002088 .vidioc_querycap = vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03002089 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
2090 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
2091 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
2092 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Devin Heitmueller28abf0832009-09-01 01:54:54 -03002093 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Hans Verkuil2a221d32012-09-07 08:51:32 -03002094 .vidioc_try_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Frank Schaeferaab34612013-02-07 13:39:16 -03002095 .vidioc_s_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Mauro Carvalho Chehab1c5c5062011-10-16 13:52:43 -02002096 .vidioc_enum_framesizes = vidioc_enum_framesizes,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002097 .vidioc_g_audio = vidioc_g_audio,
2098 .vidioc_s_audio = vidioc_s_audio,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002099
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002100 .vidioc_reqbufs = vb2_ioctl_reqbufs,
2101 .vidioc_create_bufs = vb2_ioctl_create_bufs,
2102 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
2103 .vidioc_querybuf = vb2_ioctl_querybuf,
2104 .vidioc_qbuf = vb2_ioctl_qbuf,
2105 .vidioc_dqbuf = vb2_ioctl_dqbuf,
2106
Devin Heitmueller19bf0032009-09-11 00:40:18 -03002107 .vidioc_g_std = vidioc_g_std,
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03002108 .vidioc_querystd = vidioc_querystd,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002109 .vidioc_s_std = vidioc_s_std,
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03002110 .vidioc_g_parm = vidioc_g_parm,
2111 .vidioc_s_parm = vidioc_s_parm,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002112 .vidioc_enum_input = vidioc_enum_input,
2113 .vidioc_g_input = vidioc_g_input,
2114 .vidioc_s_input = vidioc_s_input,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002115 .vidioc_streamon = vb2_ioctl_streamon,
2116 .vidioc_streamoff = vb2_ioctl_streamoff,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002117 .vidioc_g_tuner = vidioc_g_tuner,
2118 .vidioc_s_tuner = vidioc_s_tuner,
2119 .vidioc_g_frequency = vidioc_g_frequency,
2120 .vidioc_s_frequency = vidioc_s_frequency,
Hans Verkuil50fdf402012-09-07 06:10:12 -03002121 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
2122 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002123#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuil96b03d22013-04-06 06:16:58 -03002124 .vidioc_g_chip_info = vidioc_g_chip_info,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002125 .vidioc_g_register = vidioc_g_register,
2126 .vidioc_s_register = vidioc_s_register,
2127#endif
Hans Verkuila3998102008-07-21 02:57:38 -03002128};
2129
2130static const struct video_device em28xx_video_template = {
Frank Schaefere8470222014-01-12 13:24:25 -03002131 .fops = &em28xx_v4l_fops,
2132 .ioctl_ops = &video_ioctl_ops,
Hans Verkuild4352f32015-03-09 13:34:06 -03002133 .release = video_device_release_empty,
Frank Schaefere8470222014-01-12 13:24:25 -03002134 .tvnorms = V4L2_STD_ALL,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002135};
2136
Hans Verkuilbec43662008-12-30 06:58:20 -03002137static const struct v4l2_file_operations radio_fops = {
Hans Verkuila3998102008-07-21 02:57:38 -03002138 .owner = THIS_MODULE,
2139 .open = em28xx_v4l2_open,
2140 .release = em28xx_v4l2_close,
Hans Verkuil8fd0bda2010-12-18 09:59:51 -03002141 .unlocked_ioctl = video_ioctl2,
Hans Verkuila3998102008-07-21 02:57:38 -03002142};
2143
2144static const struct v4l2_ioctl_ops radio_ioctl_ops = {
Hans Verkuila9d79fe2012-09-06 07:31:04 -03002145 .vidioc_querycap = vidioc_querycap,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002146 .vidioc_g_tuner = radio_g_tuner,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002147 .vidioc_s_tuner = radio_s_tuner,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002148 .vidioc_g_frequency = vidioc_g_frequency,
2149 .vidioc_s_frequency = vidioc_s_frequency,
Hans Verkuil50fdf402012-09-07 06:10:12 -03002150 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
2151 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002152#ifdef CONFIG_VIDEO_ADV_DEBUG
Michal Marek430c73f2013-04-16 08:06:30 -03002153 .vidioc_g_chip_info = vidioc_g_chip_info,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002154 .vidioc_g_register = vidioc_g_register,
2155 .vidioc_s_register = vidioc_s_register,
2156#endif
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002157};
2158
Hans Verkuila3998102008-07-21 02:57:38 -03002159static struct video_device em28xx_radio_template = {
Frank Schaefere8470222014-01-12 13:24:25 -03002160 .fops = &radio_fops,
2161 .ioctl_ops = &radio_ioctl_ops,
Hans Verkuild4352f32015-03-09 13:34:06 -03002162 .release = video_device_release_empty,
Hans Verkuila3998102008-07-21 02:57:38 -03002163};
2164
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002165/* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */
2166static unsigned short saa711x_addrs[] = {
2167 0x4a >> 1, 0x48 >> 1, /* SAA7111, SAA7111A and SAA7113 */
2168 0x42 >> 1, 0x40 >> 1, /* SAA7114, SAA7115 and SAA7118 */
2169 I2C_CLIENT_END };
2170
2171static unsigned short tvp5150_addrs[] = {
2172 0xb8 >> 1,
2173 0xba >> 1,
2174 I2C_CLIENT_END
2175};
2176
2177static unsigned short msp3400_addrs[] = {
2178 0x80 >> 1,
2179 0x88 >> 1,
2180 I2C_CLIENT_END
2181};
2182
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03002183/******************************** usb interface ******************************/
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002184
Hans Verkuild4352f32015-03-09 13:34:06 -03002185static void em28xx_vdev_init(struct em28xx *dev,
2186 struct video_device *vfd,
2187 const struct video_device *template,
2188 const char *type_name)
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002189{
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03002190 *vfd = *template;
Frank Schaefer95d26082014-03-24 16:33:09 -03002191 vfd->v4l2_dev = &dev->v4l2->v4l2_dev;
Hans Verkuil0499a5a2010-09-26 07:34:45 -03002192 vfd->lock = &dev->lock;
Hans Verkuild8c95c02012-09-07 07:31:54 -03002193 if (dev->board.is_webcam)
2194 vfd->tvnorms = 0;
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002195
2196 snprintf(vfd->name, sizeof(vfd->name), "%s %s",
2197 dev->name, type_name);
2198
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02002199 video_set_drvdata(vfd, dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002200}
2201
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002202static void em28xx_tuner_setup(struct em28xx *dev, unsigned short tuner_addr)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002203{
Frank Schaefer3854b0d2014-03-24 16:33:22 -03002204 struct em28xx_v4l2 *v4l2 = dev->v4l2;
2205 struct v4l2_device *v4l2_dev = &v4l2->v4l2_dev;
2206 struct tuner_setup tun_setup;
2207 struct v4l2_frequency f;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002208
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002209 memset(&tun_setup, 0, sizeof(tun_setup));
2210
2211 tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
2212 tun_setup.tuner_callback = em28xx_tuner_callback;
2213
2214 if (dev->board.radio.type) {
2215 tun_setup.type = dev->board.radio.type;
2216 tun_setup.addr = dev->board.radio_addr;
2217
Frank Schaefer95d26082014-03-24 16:33:09 -03002218 v4l2_device_call_all(v4l2_dev,
2219 0, tuner, s_type_addr, &tun_setup);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002220 }
2221
2222 if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type)) {
2223 tun_setup.type = dev->tuner_type;
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002224 tun_setup.addr = tuner_addr;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002225
Frank Schaefer95d26082014-03-24 16:33:09 -03002226 v4l2_device_call_all(v4l2_dev,
2227 0, tuner, s_type_addr, &tun_setup);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002228 }
2229
Frank Schaefer6867bd5a2014-03-24 16:33:23 -03002230 if (dev->board.tda9887_conf) {
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002231 struct v4l2_priv_tun_config tda9887_cfg;
2232
2233 tda9887_cfg.tuner = TUNER_TDA9887;
Frank Schaefer6867bd5a2014-03-24 16:33:23 -03002234 tda9887_cfg.priv = &dev->board.tda9887_conf;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002235
Frank Schaefer95d26082014-03-24 16:33:09 -03002236 v4l2_device_call_all(v4l2_dev,
2237 0, tuner, s_config, &tda9887_cfg);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002238 }
2239
2240 if (dev->tuner_type == TUNER_XC2028) {
2241 struct v4l2_priv_tun_config xc2028_cfg;
2242 struct xc2028_ctrl ctl;
2243
2244 memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
2245 memset(&ctl, 0, sizeof(ctl));
2246
2247 em28xx_setup_xc3028(dev, &ctl);
2248
2249 xc2028_cfg.tuner = TUNER_XC2028;
2250 xc2028_cfg.priv = &ctl;
2251
Frank Schaefer95d26082014-03-24 16:33:09 -03002252 v4l2_device_call_all(v4l2_dev, 0, tuner, s_config, &xc2028_cfg);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002253 }
2254
2255 /* configure tuner */
2256 f.tuner = 0;
2257 f.type = V4L2_TUNER_ANALOG_TV;
2258 f.frequency = 9076; /* just a magic number */
Frank Schaefer3854b0d2014-03-24 16:33:22 -03002259 v4l2->frequency = f.frequency;
Frank Schaefer95d26082014-03-24 16:33:09 -03002260 v4l2_device_call_all(v4l2_dev, 0, tuner, s_frequency, &f);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002261}
2262
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002263static int em28xx_v4l2_init(struct em28xx *dev)
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002264{
Hans Verkuil081b9452012-09-07 05:43:59 -03002265 u8 val;
Mauro Carvalho Chehab2e5ef2d2008-12-28 22:26:36 -03002266 int ret;
Sascha Sommer1020d132012-01-08 16:54:28 -03002267 unsigned int maxw;
Frank Schaeferabc13082014-03-24 16:33:10 -03002268 struct v4l2_ctrl_handler *hdl;
Frank Schaefer95d26082014-03-24 16:33:09 -03002269 struct em28xx_v4l2 *v4l2;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002270
Mauro Carvalho Chehab822b8de2014-01-06 05:27:47 -03002271 if (dev->is_audio_only) {
2272 /* Shouldn't initialize IR for this interface */
2273 return 0;
2274 }
2275
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002276 if (!dev->has_video) {
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002277 /* This device does not support the v4l2 extension */
2278 return 0;
2279 }
Mauro Carvalho Chehab2e5ef2d2008-12-28 22:26:36 -03002280
Mauro Carvalho Chehab96346142013-12-26 12:41:03 -03002281 em28xx_info("Registering V4L2 extension\n");
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002282
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002283 mutex_lock(&dev->lock);
2284
Frank Schaefer95d26082014-03-24 16:33:09 -03002285 v4l2 = kzalloc(sizeof(struct em28xx_v4l2), GFP_KERNEL);
2286 if (v4l2 == NULL) {
2287 em28xx_info("em28xx_v4l: memory allocation failed\n");
2288 mutex_unlock(&dev->lock);
2289 return -ENOMEM;
2290 }
2291 kref_init(&v4l2->ref);
Frank Schaeferabc13082014-03-24 16:33:10 -03002292 v4l2->dev = dev;
Frank Schaefer95d26082014-03-24 16:33:09 -03002293 dev->v4l2 = v4l2;
2294
2295 ret = v4l2_device_register(&dev->udev->dev, &v4l2->v4l2_dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002296 if (ret < 0) {
2297 em28xx_errdev("Call to v4l2_device_register() failed!\n");
2298 goto err;
2299 }
2300
Frank Schaeferabc13082014-03-24 16:33:10 -03002301 hdl = &v4l2->ctrl_handler;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002302 v4l2_ctrl_handler_init(hdl, 8);
Frank Schaefer95d26082014-03-24 16:33:09 -03002303 v4l2->v4l2_dev.ctrl_handler = hdl;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002304
Frank Schaefer58159172014-03-24 16:33:18 -03002305 if (dev->board.is_webcam)
Mauro Carvalho Chehab7e6c8c12014-09-03 15:06:13 -03002306 v4l2->progressive = true;
Frank Schaefer58159172014-03-24 16:33:18 -03002307
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002308 /*
2309 * Default format, used for tvp5150 or saa711x output formats
2310 */
Frank Schaefer92972852014-03-24 16:33:15 -03002311 v4l2->vinmode = 0x10;
2312 v4l2->vinctl = EM28XX_VINCTRL_INTERLACED |
2313 EM28XX_VINCTRL_CCIR656_ENABLE;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002314
2315 /* request some modules */
2316
2317 if (dev->board.has_msp34xx)
Frank Schaefer95d26082014-03-24 16:33:09 -03002318 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2319 &dev->i2c_adap[dev->def_i2c_bus],
2320 "msp3400", 0, msp3400_addrs);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002321
2322 if (dev->board.decoder == EM28XX_SAA711X)
Frank Schaefer95d26082014-03-24 16:33:09 -03002323 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2324 &dev->i2c_adap[dev->def_i2c_bus],
2325 "saa7115_auto", 0, saa711x_addrs);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002326
2327 if (dev->board.decoder == EM28XX_TVP5150)
Frank Schaefer95d26082014-03-24 16:33:09 -03002328 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2329 &dev->i2c_adap[dev->def_i2c_bus],
2330 "tvp5150", 0, tvp5150_addrs);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002331
2332 if (dev->board.adecoder == EM28XX_TVAUDIO)
Frank Schaefer95d26082014-03-24 16:33:09 -03002333 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2334 &dev->i2c_adap[dev->def_i2c_bus],
2335 "tvaudio", dev->board.tvaudio_addr, NULL);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002336
2337 /* Initialize tuner and camera */
2338
2339 if (dev->board.tuner_type != TUNER_ABSENT) {
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002340 unsigned short tuner_addr = dev->board.tuner_addr;
Frank Schaefer6867bd5a2014-03-24 16:33:23 -03002341 int has_demod = (dev->board.tda9887_conf & TDA9887_PRESENT);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002342
2343 if (dev->board.radio.type)
Frank Schaefer95d26082014-03-24 16:33:09 -03002344 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002345 &dev->i2c_adap[dev->def_i2c_bus],
2346 "tuner", dev->board.radio_addr,
2347 NULL);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002348
2349 if (has_demod)
Frank Schaefer95d26082014-03-24 16:33:09 -03002350 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002351 &dev->i2c_adap[dev->def_i2c_bus],
2352 "tuner", 0,
2353 v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002354 if (tuner_addr == 0) {
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002355 enum v4l2_i2c_tuner_type type =
2356 has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV;
2357 struct v4l2_subdev *sd;
2358
Frank Schaefer95d26082014-03-24 16:33:09 -03002359 sd = v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002360 &dev->i2c_adap[dev->def_i2c_bus],
2361 "tuner", 0,
2362 v4l2_i2c_tuner_addrs(type));
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002363
2364 if (sd)
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002365 tuner_addr = v4l2_i2c_subdev_addr(sd);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002366 } else {
Frank Schaefer95d26082014-03-24 16:33:09 -03002367 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2368 &dev->i2c_adap[dev->def_i2c_bus],
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002369 "tuner", tuner_addr, NULL);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002370 }
Frank Schaefer3319e6f2014-03-24 16:33:24 -03002371
2372 em28xx_tuner_setup(dev, tuner_addr);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002373 }
2374
Frank Schaeferd86bc652014-01-17 14:45:32 -03002375 if (dev->em28xx_sensor != EM28XX_NOSENSOR)
2376 em28xx_init_camera(dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002377
2378 /* Configure audio */
2379 ret = em28xx_audio_setup(dev);
2380 if (ret < 0) {
2381 em28xx_errdev("%s: Error while setting audio - error [%d]!\n",
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002382 __func__, ret);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002383 goto unregister_dev;
2384 }
2385 if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
2386 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002387 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002388 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002389 V4L2_CID_AUDIO_VOLUME, 0, 0x1f, 1, 0x1f);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002390 } else {
2391 /* install the em28xx notify callback */
2392 v4l2_ctrl_notify(v4l2_ctrl_find(hdl, V4L2_CID_AUDIO_MUTE),
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002393 em28xx_ctrl_notify, dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002394 v4l2_ctrl_notify(v4l2_ctrl_find(hdl, V4L2_CID_AUDIO_VOLUME),
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002395 em28xx_ctrl_notify, dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002396 }
2397
2398 /* wake i2c devices */
2399 em28xx_wake_i2c(dev);
2400
2401 /* init video dma queues */
2402 INIT_LIST_HEAD(&dev->vidq.active);
2403 INIT_LIST_HEAD(&dev->vbiq.active);
2404
2405 if (dev->board.has_msp34xx) {
2406 /* Send a reset to other chips via gpio */
2407 ret = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xf7);
2408 if (ret < 0) {
2409 em28xx_errdev("%s: em28xx_write_reg - msp34xx(1) failed! error [%d]\n",
2410 __func__, ret);
2411 goto unregister_dev;
2412 }
2413 msleep(3);
2414
2415 ret = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xff);
2416 if (ret < 0) {
2417 em28xx_errdev("%s: em28xx_write_reg - msp34xx(2) failed! error [%d]\n",
2418 __func__, ret);
2419 goto unregister_dev;
2420 }
2421 msleep(3);
2422 }
2423
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002424 /* set default norm */
Frank Schaefer52faaf72014-03-24 16:33:16 -03002425 v4l2->norm = V4L2_STD_PAL;
Laurent Pinchart8774bed2014-04-28 16:53:01 -03002426 v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_std, v4l2->norm);
Frank Schaefer58159172014-03-24 16:33:18 -03002427 v4l2->interlaced_fieldmode = EM28XX_INTERLACED_DEFAULT;
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002428
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002429 /* Analog specific initialization */
Frank Schaefer06e20672014-03-24 16:33:17 -03002430 v4l2->format = &format[0];
Sascha Sommer1020d132012-01-08 16:54:28 -03002431
2432 maxw = norm_maxw(dev);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002433 /* MaxPacketSize for em2800 is too small to capture at full resolution
2434 * use half of maxw as the scaler can only scale to 50% */
2435 if (dev->board.is_em2800)
2436 maxw /= 2;
Sascha Sommer1020d132012-01-08 16:54:28 -03002437
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03002438 em28xx_set_video_format(dev, format[0].fourcc,
Sascha Sommer1020d132012-01-08 16:54:28 -03002439 maxw, norm_maxh(dev));
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03002440
Ezequiel García96371fc2012-03-23 18:09:34 -03002441 video_mux(dev, 0);
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002442
2443 /* Audio defaults */
2444 dev->mute = 1;
2445 dev->volume = 0x1f;
2446
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002447/* em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -03002448 val = (u8)em28xx_read_reg(dev, EM28XX_R0F_XCLK);
2449 em28xx_write_reg(dev, EM28XX_R0F_XCLK,
2450 (EM28XX_XCLK_AUDIO_UNMUTE | val));
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002451
2452 em28xx_set_outfmt(dev);
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002453
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002454 /* Add image controls */
2455 /* NOTE: at this point, the subdevices are already registered, so bridge
2456 * controls are only added/enabled when no subdevice provides them */
Frank Schaeferad298052014-03-24 16:33:08 -03002457 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_CONTRAST))
2458 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002459 V4L2_CID_CONTRAST,
2460 0, 0x1f, 1, CONTRAST_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002461 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_BRIGHTNESS))
2462 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002463 V4L2_CID_BRIGHTNESS,
2464 -0x80, 0x7f, 1, BRIGHTNESS_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002465 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_SATURATION))
2466 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002467 V4L2_CID_SATURATION,
2468 0, 0x1f, 1, SATURATION_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002469 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_BLUE_BALANCE))
2470 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002471 V4L2_CID_BLUE_BALANCE,
2472 -0x30, 0x30, 1, BLUE_BALANCE_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002473 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_RED_BALANCE))
2474 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002475 V4L2_CID_RED_BALANCE,
2476 -0x30, 0x30, 1, RED_BALANCE_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002477 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_SHARPNESS))
2478 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002479 V4L2_CID_SHARPNESS,
2480 0, 0x0f, 1, SHARPNESS_DEFAULT);
2481
2482 /* Reset image controls */
2483 em28xx_colorlevels_set_default(dev);
Frank Schaeferad298052014-03-24 16:33:08 -03002484 v4l2_ctrl_handler_setup(hdl);
2485 ret = hdl->error;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002486 if (ret)
2487 goto unregister_dev;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002488
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002489 /* allocate and fill video video_device struct */
Hans Verkuild4352f32015-03-09 13:34:06 -03002490 em28xx_vdev_init(dev, &v4l2->vdev, &em28xx_video_template, "video");
Frank Schaefer27a36df2014-03-24 16:33:13 -03002491 mutex_init(&v4l2->vb_queue_lock);
2492 mutex_init(&v4l2->vb_vbi_queue_lock);
Hans Verkuild4352f32015-03-09 13:34:06 -03002493 v4l2->vdev.queue = &v4l2->vb_vidq;
2494 v4l2->vdev.queue->lock = &v4l2->vb_queue_lock;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002495
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002496 /* disable inapplicable ioctls */
2497 if (dev->board.is_webcam) {
Hans Verkuild4352f32015-03-09 13:34:06 -03002498 v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_QUERYSTD);
2499 v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_G_STD);
2500 v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_S_STD);
Frank Schaefer3bc85cc2013-02-07 13:39:12 -03002501 } else {
Hans Verkuild4352f32015-03-09 13:34:06 -03002502 v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_S_PARM);
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002503 }
Frank Schaefer66df67b2013-02-07 13:39:10 -03002504 if (dev->tuner_type == TUNER_ABSENT) {
Hans Verkuild4352f32015-03-09 13:34:06 -03002505 v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_G_TUNER);
2506 v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_S_TUNER);
2507 v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_G_FREQUENCY);
2508 v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_S_FREQUENCY);
Frank Schaefer66df67b2013-02-07 13:39:10 -03002509 }
Frank Schaefer920f1e42014-09-13 05:52:21 -03002510 if (dev->int_audio_type == EM28XX_INT_AUDIO_NONE) {
Hans Verkuild4352f32015-03-09 13:34:06 -03002511 v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_G_AUDIO);
2512 v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_S_AUDIO);
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002513 }
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002514
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002515 /* register v4l2 video video_device */
Hans Verkuild4352f32015-03-09 13:34:06 -03002516 ret = video_register_device(&v4l2->vdev, VFL_TYPE_GRABBER,
Mauro Carvalho Chehabfdf1bc92014-11-28 08:34:15 -03002517 video_nr[dev->devno]);
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002518 if (ret) {
2519 em28xx_errdev("unable to register video device (error=%i).\n",
2520 ret);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002521 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002522 }
2523
2524 /* Allocate and fill vbi video_device struct */
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002525 if (em28xx_vbi_supported(dev) == 1) {
Hans Verkuild4352f32015-03-09 13:34:06 -03002526 em28xx_vdev_init(dev, &v4l2->vbi_dev, &em28xx_video_template,
2527 "vbi");
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002528
Hans Verkuild4352f32015-03-09 13:34:06 -03002529 v4l2->vbi_dev.queue = &v4l2->vb_vbiq;
2530 v4l2->vbi_dev.queue->lock = &v4l2->vb_vbi_queue_lock;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002531
Frank Schaefer66df67b2013-02-07 13:39:10 -03002532 /* disable inapplicable ioctls */
Hans Verkuild4352f32015-03-09 13:34:06 -03002533 v4l2_disable_ioctl(&v4l2->vbi_dev, VIDIOC_S_PARM);
Frank Schaefer66df67b2013-02-07 13:39:10 -03002534 if (dev->tuner_type == TUNER_ABSENT) {
Hans Verkuild4352f32015-03-09 13:34:06 -03002535 v4l2_disable_ioctl(&v4l2->vbi_dev, VIDIOC_G_TUNER);
2536 v4l2_disable_ioctl(&v4l2->vbi_dev, VIDIOC_S_TUNER);
2537 v4l2_disable_ioctl(&v4l2->vbi_dev, VIDIOC_G_FREQUENCY);
2538 v4l2_disable_ioctl(&v4l2->vbi_dev, VIDIOC_S_FREQUENCY);
Frank Schaefer66df67b2013-02-07 13:39:10 -03002539 }
Frank Schaefer920f1e42014-09-13 05:52:21 -03002540 if (dev->int_audio_type == EM28XX_INT_AUDIO_NONE) {
Hans Verkuild4352f32015-03-09 13:34:06 -03002541 v4l2_disable_ioctl(&v4l2->vbi_dev, VIDIOC_G_AUDIO);
2542 v4l2_disable_ioctl(&v4l2->vbi_dev, VIDIOC_S_AUDIO);
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002543 }
Frank Schaefer66df67b2013-02-07 13:39:10 -03002544
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002545 /* register v4l2 vbi video_device */
Hans Verkuild4352f32015-03-09 13:34:06 -03002546 ret = video_register_device(&v4l2->vbi_dev, VFL_TYPE_VBI,
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002547 vbi_nr[dev->devno]);
2548 if (ret < 0) {
2549 em28xx_errdev("unable to register vbi device\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002550 goto unregister_dev;
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002551 }
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002552 }
2553
2554 if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) {
Hans Verkuild4352f32015-03-09 13:34:06 -03002555 em28xx_vdev_init(dev, &v4l2->radio_dev, &em28xx_radio_template,
2556 "radio");
2557 ret = video_register_device(&v4l2->radio_dev, VFL_TYPE_RADIO,
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002558 radio_nr[dev->devno]);
2559 if (ret < 0) {
2560 em28xx_errdev("can't register radio device\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002561 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002562 }
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002563 em28xx_info("Registered radio device as %s\n",
Hans Verkuild4352f32015-03-09 13:34:06 -03002564 video_device_node_name(&v4l2->radio_dev));
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002565 }
2566
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002567 em28xx_info("V4L2 video device registered as %s\n",
Hans Verkuild4352f32015-03-09 13:34:06 -03002568 video_device_node_name(&v4l2->vdev));
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002569
Hans Verkuild4352f32015-03-09 13:34:06 -03002570 if (video_is_registered(&v4l2->vbi_dev))
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002571 em28xx_info("V4L2 VBI device registered as %s\n",
Hans Verkuild4352f32015-03-09 13:34:06 -03002572 video_device_node_name(&v4l2->vbi_dev));
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002573
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002574 /* Save some power by putting tuner to sleep */
Frank Schaefer95d26082014-03-24 16:33:09 -03002575 v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_power, 0);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002576
2577 /* initialize videobuf2 stuff */
2578 em28xx_vb2_setup(dev);
2579
Mauro Carvalho Chehab96346142013-12-26 12:41:03 -03002580 em28xx_info("V4L2 extension successfully initialized\n");
2581
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002582 kref_get(&dev->ref);
2583
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002584 mutex_unlock(&dev->lock);
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002585 return 0;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002586
2587unregister_dev:
Frank Schaeferabc13082014-03-24 16:33:10 -03002588 v4l2_ctrl_handler_free(&v4l2->ctrl_handler);
Frank Schaefer95d26082014-03-24 16:33:09 -03002589 v4l2_device_unregister(&v4l2->v4l2_dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002590err:
Frank Schaefer95d26082014-03-24 16:33:09 -03002591 dev->v4l2 = NULL;
2592 kref_put(&v4l2->ref, em28xx_free_v4l2);
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002593 mutex_unlock(&dev->lock);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002594 return ret;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002595}
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002596
2597static struct em28xx_ops v4l2_ops = {
2598 .id = EM28XX_V4L2,
2599 .name = "Em28xx v4l2 Extension",
2600 .init = em28xx_v4l2_init,
2601 .fini = em28xx_v4l2_fini,
Shuah Khana61f6812014-02-21 21:50:17 -03002602 .suspend = em28xx_v4l2_suspend,
2603 .resume = em28xx_v4l2_resume,
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002604};
2605
2606static int __init em28xx_video_register(void)
2607{
2608 return em28xx_register_extension(&v4l2_ops);
2609}
2610
2611static void __exit em28xx_video_unregister(void)
2612{
2613 em28xx_unregister_extension(&v4l2_ops);
2614}
2615
2616module_init(em28xx_video_register);
2617module_exit(em28xx_video_unregister);