blob: a8ddc4cada95979a9157697978e7954b75fb9357 [file] [log] [blame]
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001/*
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03002 em28xx-video.c - driver for Empia EM2800/EM2820/2840 USB
3 video capture devices
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08004
Mauro Carvalho Chehabf7abcd32005-11-08 21:38:25 -08005 Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
6 Markus Rechberger <mrechberger@gmail.com>
Mauro Carvalho Chehab2e7c6dc2006-04-03 07:53:40 -03007 Mauro Carvalho Chehab <mchehab@infradead.org>
Mauro Carvalho Chehabf7abcd32005-11-08 21:38:25 -08008 Sascha Sommer <saschasommer@freenet.de>
Frank Schaefer0fa4a402012-11-08 14:11:45 -03009 Copyright (C) 2012 Frank Schäfer <fschaefer.oss@googlemail.com>
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080010
Mauro Carvalho Chehab439090d2006-01-23 17:10:54 -020011 Some parts based on SN9C10x PC Camera Controllers GPL driver made
12 by Luca Risolia <luca.risolia@studio.unibo.it>
13
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080014 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 */
28
29#include <linux/init.h>
30#include <linux/list.h>
31#include <linux/module.h>
32#include <linux/kernel.h>
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -020033#include <linux/bitmap.h>
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080034#include <linux/usb.h>
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080035#include <linux/i2c.h>
Trent Piepho6d35c8f2007-11-01 01:16:09 -030036#include <linux/mm.h>
Ingo Molnar1e4baed2006-01-15 07:52:23 -020037#include <linux/mutex.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090038#include <linux/slab.h>
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080039
Mauro Carvalho Chehabf7abcd32005-11-08 21:38:25 -080040#include "em28xx.h"
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -030041#include "em28xx-v4l.h"
Mauro Carvalho Chehabc0477ad2006-01-09 15:25:14 -020042#include <media/v4l2-common.h>
Hans Verkuil35ea11f2008-07-20 08:12:02 -030043#include <media/v4l2-ioctl.h>
Hans Verkuil50fdf402012-09-07 06:10:12 -030044#include <media/v4l2-event.h>
Frank Schaefer25dd1652014-01-12 13:24:23 -030045#include <media/v4l2-clk.h>
Hans Verkuil2474ed42006-03-19 12:35:57 -030046#include <media/msp3400.h>
Mauro Carvalho Chehabed086312008-01-24 06:59:20 -030047#include <media/tuner.h>
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080048
Mauro Carvalho Chehabf7abcd32005-11-08 21:38:25 -080049#define DRIVER_AUTHOR "Ludovico Cavedon <cavedon@sssup.it>, " \
50 "Markus Rechberger <mrechberger@gmail.com>, " \
Mauro Carvalho Chehab2e7c6dc2006-04-03 07:53:40 -030051 "Mauro Carvalho Chehab <mchehab@infradead.org>, " \
Mauro Carvalho Chehabf7abcd32005-11-08 21:38:25 -080052 "Sascha Sommer <saschasommer@freenet.de>"
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080053
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -030054static unsigned int isoc_debug;
55module_param(isoc_debug, int, 0644);
56MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");
57
58static unsigned int disable_vbi;
59module_param(disable_vbi, int, 0644);
60MODULE_PARM_DESC(disable_vbi, "disable vbi support");
61
62static int alt;
63module_param(alt, int, 0644);
64MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint");
65
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -080066#define em28xx_videodbg(fmt, arg...) do {\
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -080067 if (video_debug) \
68 printk(KERN_INFO "%s %s :"fmt, \
Harvey Harrisond80e1342008-04-08 23:20:00 -030069 dev->name, __func__ , ##arg); } while (0)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080070
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -030071#define em28xx_isocdbg(fmt, arg...) \
72do {\
73 if (isoc_debug) { \
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -030074 printk(KERN_INFO "%s %s :"fmt, \
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -030075 dev->name, __func__ , ##arg); \
76 } \
77 } while (0)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -030078
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080079MODULE_AUTHOR(DRIVER_AUTHOR);
Mauro Carvalho Chehabd8992b02013-12-27 11:14:59 -030080MODULE_DESCRIPTION(DRIVER_DESC " - v4l2 interface");
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080081MODULE_LICENSE("GPL");
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -030082MODULE_VERSION(EM28XX_VERSION);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080083
Frank Schaefere507e0e2013-03-26 13:38:38 -030084
85#define EM25XX_FRMDATAHDR_BYTE1 0x02
86#define EM25XX_FRMDATAHDR_BYTE2_STILL_IMAGE 0x20
87#define EM25XX_FRMDATAHDR_BYTE2_FRAME_END 0x02
88#define EM25XX_FRMDATAHDR_BYTE2_FRAME_ID 0x01
89#define EM25XX_FRMDATAHDR_BYTE2_MASK (EM25XX_FRMDATAHDR_BYTE2_STILL_IMAGE | \
90 EM25XX_FRMDATAHDR_BYTE2_FRAME_END | \
91 EM25XX_FRMDATAHDR_BYTE2_FRAME_ID)
92
93
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -030094static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
95static unsigned int vbi_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
96static unsigned int radio_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -030097
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -020098module_param_array(video_nr, int, NULL, 0444);
99module_param_array(vbi_nr, int, NULL, 0444);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -0300100module_param_array(radio_nr, int, NULL, 0444);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -0300101MODULE_PARM_DESC(video_nr, "video device numbers");
102MODULE_PARM_DESC(vbi_nr, "vbi device numbers");
103MODULE_PARM_DESC(radio_nr, "radio device numbers");
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -0800104
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -0300105static unsigned int video_debug;
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -0300106module_param(video_debug, int, 0644);
107MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800108
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -0300109/* supported video standards */
110static struct em28xx_fmt format[] = {
111 {
Mauro Carvalho Chehab58fc1ce2009-07-03 02:54:18 -0300112 .name = "16 bpp YUY2, 4:2:2, packed",
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -0300113 .fourcc = V4L2_PIX_FMT_YUYV,
114 .depth = 16,
Devin Heitmueller3fbf9302008-12-29 23:34:37 -0300115 .reg = EM28XX_OUTFMT_YUV422_Y0UY1V,
Mauro Carvalho Chehab43cb9fe2009-06-30 08:36:17 -0300116 }, {
Mauro Carvalho Chehab58fc1ce2009-07-03 02:54:18 -0300117 .name = "16 bpp RGB 565, LE",
Mauro Carvalho Chehab43cb9fe2009-06-30 08:36:17 -0300118 .fourcc = V4L2_PIX_FMT_RGB565,
119 .depth = 16,
Mauro Carvalho Chehab58fc1ce2009-07-03 02:54:18 -0300120 .reg = EM28XX_OUTFMT_RGB_16_656,
121 }, {
122 .name = "8 bpp Bayer BGBG..GRGR",
123 .fourcc = V4L2_PIX_FMT_SBGGR8,
124 .depth = 8,
125 .reg = EM28XX_OUTFMT_RGB_8_BGBG,
126 }, {
127 .name = "8 bpp Bayer GRGR..BGBG",
128 .fourcc = V4L2_PIX_FMT_SGRBG8,
129 .depth = 8,
130 .reg = EM28XX_OUTFMT_RGB_8_GRGR,
131 }, {
132 .name = "8 bpp Bayer GBGB..RGRG",
133 .fourcc = V4L2_PIX_FMT_SGBRG8,
134 .depth = 8,
135 .reg = EM28XX_OUTFMT_RGB_8_GBGB,
136 }, {
137 .name = "12 bpp YUV411",
138 .fourcc = V4L2_PIX_FMT_YUV411P,
139 .depth = 12,
140 .reg = EM28XX_OUTFMT_YUV411,
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -0300141 },
142};
143
Frank Schaefer25c61e42014-03-22 10:01:03 -0300144/*FIXME: maxw should be dependent of alt mode */
145static inline unsigned int norm_maxw(struct em28xx *dev)
146{
147 if (dev->board.is_webcam)
148 return dev->sensor_xres;
149
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{
158 if (dev->board.is_webcam)
159 return dev->sensor_yres;
160
161 if (dev->board.max_range_640_480)
162 return 480;
163
164 return (dev->norm & V4L2_STD_625_50) ? 576 : 480;
165}
166
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300167static int em28xx_vbi_supported(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300168{
169 /* Modprobe option to manually disable */
170 if (disable_vbi == 1)
171 return 0;
172
173 if (dev->board.is_webcam)
174 return 0;
175
176 /* FIXME: check subdevices for VBI support */
177
178 if (dev->chip_id == CHIP_ID_EM2860 ||
179 dev->chip_id == CHIP_ID_EM2883)
180 return 1;
181
182 /* Version of em28xx that does not support VBI */
183 return 0;
184}
185
186/*
187 * em28xx_wake_i2c()
188 * configure i2c attached devices
189 */
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300190static void em28xx_wake_i2c(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300191{
Frank Schaefer95d26082014-03-24 16:33:09 -0300192 struct v4l2_device *v4l2_dev = &dev->v4l2->v4l2_dev;
193 v4l2_device_call_all(v4l2_dev, 0, core, reset, 0);
194 v4l2_device_call_all(v4l2_dev, 0, video, s_routing,
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300195 INPUT(dev->ctl_input)->vmux, 0, 0);
Frank Schaefer95d26082014-03-24 16:33:09 -0300196 v4l2_device_call_all(v4l2_dev, 0, video, s_stream, 0);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300197}
198
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300199static int em28xx_colorlevels_set_default(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300200{
201 em28xx_write_reg(dev, EM28XX_R20_YGAIN, CONTRAST_DEFAULT);
202 em28xx_write_reg(dev, EM28XX_R21_YOFFSET, BRIGHTNESS_DEFAULT);
203 em28xx_write_reg(dev, EM28XX_R22_UVGAIN, SATURATION_DEFAULT);
204 em28xx_write_reg(dev, EM28XX_R23_UOFFSET, BLUE_BALANCE_DEFAULT);
205 em28xx_write_reg(dev, EM28XX_R24_VOFFSET, RED_BALANCE_DEFAULT);
206 em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, SHARPNESS_DEFAULT);
207
208 em28xx_write_reg(dev, EM28XX_R14_GAMMA, 0x20);
209 em28xx_write_reg(dev, EM28XX_R15_RGAIN, 0x20);
210 em28xx_write_reg(dev, EM28XX_R16_GGAIN, 0x20);
211 em28xx_write_reg(dev, EM28XX_R17_BGAIN, 0x20);
212 em28xx_write_reg(dev, EM28XX_R18_ROFFSET, 0x00);
213 em28xx_write_reg(dev, EM28XX_R19_GOFFSET, 0x00);
214 return em28xx_write_reg(dev, EM28XX_R1A_BOFFSET, 0x00);
215}
216
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300217static int em28xx_set_outfmt(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300218{
219 int ret;
220 u8 fmt, vinctrl;
221
222 fmt = dev->format->reg;
223 if (!dev->is_em25xx)
224 fmt |= 0x20;
225 /*
226 * NOTE: it's not clear if this is really needed !
227 * The datasheets say bit 5 is a reserved bit and devices seem to work
228 * fine without it. But the Windows driver sets it for em2710/50+em28xx
229 * devices and we've always been setting it, too.
230 *
231 * em2765 (em25xx, em276x/7x/8x) devices do NOT work with this bit set,
232 * it's likely used for an additional (compressed ?) format there.
233 */
234 ret = em28xx_write_reg(dev, EM28XX_R27_OUTFMT, fmt);
235 if (ret < 0)
236 return ret;
237
238 ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, dev->vinmode);
239 if (ret < 0)
240 return ret;
241
242 vinctrl = dev->vinctl;
243 if (em28xx_vbi_supported(dev) == 1) {
244 vinctrl |= EM28XX_VINCTRL_VBI_RAW;
245 em28xx_write_reg(dev, EM28XX_R34_VBI_START_H, 0x00);
246 em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH, dev->vbi_width/4);
247 em28xx_write_reg(dev, EM28XX_R37_VBI_HEIGHT, dev->vbi_height);
248 if (dev->norm & V4L2_STD_525_60) {
249 /* NTSC */
250 em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x09);
251 } else if (dev->norm & V4L2_STD_625_50) {
252 /* PAL */
253 em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x07);
254 }
255 }
256
257 return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctrl);
258}
259
260static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax,
261 u8 ymin, u8 ymax)
262{
263 em28xx_videodbg("em28xx Scale: (%d,%d)-(%d,%d)\n",
264 xmin, ymin, xmax, ymax);
265
266 em28xx_write_regs(dev, EM28XX_R28_XMIN, &xmin, 1);
267 em28xx_write_regs(dev, EM28XX_R29_XMAX, &xmax, 1);
268 em28xx_write_regs(dev, EM28XX_R2A_YMIN, &ymin, 1);
269 return em28xx_write_regs(dev, EM28XX_R2B_YMAX, &ymax, 1);
270}
271
272static void em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
273 u16 width, u16 height)
274{
275 u8 cwidth = width >> 2;
276 u8 cheight = height >> 2;
277 u8 overflow = (height >> 9 & 0x02) | (width >> 10 & 0x01);
278 /* NOTE: size limit: 2047x1023 = 2MPix */
279
280 em28xx_videodbg("capture area set to (%d,%d): %dx%d\n",
281 hstart, vstart,
282 ((overflow & 2) << 9 | cwidth << 2),
283 ((overflow & 1) << 10 | cheight << 2));
284
285 em28xx_write_regs(dev, EM28XX_R1C_HSTART, &hstart, 1);
286 em28xx_write_regs(dev, EM28XX_R1D_VSTART, &vstart, 1);
287 em28xx_write_regs(dev, EM28XX_R1E_CWIDTH, &cwidth, 1);
288 em28xx_write_regs(dev, EM28XX_R1F_CHEIGHT, &cheight, 1);
289 em28xx_write_regs(dev, EM28XX_R1B_OFLOW, &overflow, 1);
290
291 /* FIXME: function/meaning of these registers ? */
292 /* FIXME: align width+height to multiples of 4 ?! */
293 if (dev->is_em25xx) {
294 em28xx_write_reg(dev, 0x34, width >> 4);
295 em28xx_write_reg(dev, 0x35, height >> 4);
296 }
297}
298
299static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v)
300{
Frank Schaefercba8e9b2014-03-24 16:28:36 -0300301 u8 mode = 0x00;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300302 /* the em2800 scaler only supports scaling down to 50% */
303
304 if (dev->board.is_em2800) {
305 mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00);
306 } else {
307 u8 buf[2];
308
309 buf[0] = h;
310 buf[1] = h >> 8;
311 em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2);
312
313 buf[0] = v;
314 buf[1] = v >> 8;
315 em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2);
316 /* it seems that both H and V scalers must be active
317 to work correctly */
318 mode = (h || v) ? 0x30 : 0x00;
319 }
Frank Schaefercba8e9b2014-03-24 16:28:36 -0300320 return em28xx_write_reg(dev, EM28XX_R26_COMPR, mode);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300321}
322
323/* FIXME: this only function read values from dev */
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300324static int em28xx_resolution_set(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300325{
326 int width, height;
327 width = norm_maxw(dev);
328 height = norm_maxh(dev);
329
330 /* Properly setup VBI */
331 dev->vbi_width = 720;
332 if (dev->norm & V4L2_STD_525_60)
333 dev->vbi_height = 12;
334 else
335 dev->vbi_height = 18;
336
337 em28xx_set_outfmt(dev);
338
339 em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2);
340
341 /* If we don't set the start position to 2 in VBI mode, we end up
342 with line 20/21 being YUYV encoded instead of being in 8-bit
343 greyscale. The core of the issue is that line 21 (and line 23 for
344 PAL WSS) are inside of active video region, and as a result they
345 get the pixelformatting associated with that area. So by cropping
346 it out, we end up with the same format as the rest of the VBI
347 region */
348 if (em28xx_vbi_supported(dev) == 1)
349 em28xx_capture_area_set(dev, 0, 2, width, height);
350 else
351 em28xx_capture_area_set(dev, 0, 0, width, height);
352
353 return em28xx_scaler_set(dev, dev->hscale, dev->vscale);
354}
355
356/* Set USB alternate setting for analog video */
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300357static int em28xx_set_alternate(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300358{
359 int errCode;
360 int i;
361 unsigned int min_pkt_size = dev->width * 2 + 4;
362
363 /* NOTE: for isoc transfers, only alt settings > 0 are allowed
364 bulk transfers seem to work only with alt=0 ! */
365 dev->alt = 0;
366 if ((alt > 0) && (alt < dev->num_alt)) {
367 em28xx_videodbg("alternate forced to %d\n", dev->alt);
368 dev->alt = alt;
369 goto set_alt;
370 }
371 if (dev->analog_xfer_bulk)
372 goto set_alt;
373
374 /* When image size is bigger than a certain value,
375 the frame size should be increased, otherwise, only
376 green screen will be received.
377 */
378 if (dev->width * 2 * dev->height > 720 * 240 * 2)
379 min_pkt_size *= 2;
380
381 for (i = 0; i < dev->num_alt; i++) {
382 /* stop when the selected alt setting offers enough bandwidth */
383 if (dev->alt_max_pkt_size_isoc[i] >= min_pkt_size) {
384 dev->alt = i;
385 break;
386 /* otherwise make sure that we end up with the maximum bandwidth
387 because the min_pkt_size equation might be wrong...
388 */
389 } else if (dev->alt_max_pkt_size_isoc[i] >
390 dev->alt_max_pkt_size_isoc[dev->alt])
391 dev->alt = i;
392 }
393
394set_alt:
395 /* NOTE: for bulk transfers, we need to call usb_set_interface()
396 * even if the previous settings were the same. Otherwise streaming
397 * fails with all urbs having status = -EOVERFLOW ! */
398 if (dev->analog_xfer_bulk) {
399 dev->max_pkt_size = 512; /* USB 2.0 spec */
400 dev->packet_multiplier = EM28XX_BULK_PACKET_MULTIPLIER;
401 } else { /* isoc */
402 em28xx_videodbg("minimum isoc packet size: %u (alt=%d)\n",
403 min_pkt_size, dev->alt);
404 dev->max_pkt_size =
405 dev->alt_max_pkt_size_isoc[dev->alt];
406 dev->packet_multiplier = EM28XX_NUM_ISOC_PACKETS;
407 }
408 em28xx_videodbg("setting alternate %d with wMaxPacketSize=%u\n",
409 dev->alt, dev->max_pkt_size);
Frank Schaefer961717b2014-01-13 19:02:06 -0300410 errCode = usb_set_interface(dev->udev, dev->ifnum, dev->alt);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300411 if (errCode < 0) {
412 em28xx_errdev("cannot change alternate number to %d (error=%i)\n",
413 dev->alt, errCode);
414 return errCode;
415 }
416 return 0;
417}
418
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300419/* ------------------------------------------------------------------
420 DMA and thread functions
421 ------------------------------------------------------------------*/
422
423/*
Frank Schaefer948a49a2012-12-08 11:31:25 -0300424 * Finish the current buffer
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300425 */
Frank Schaefer948a49a2012-12-08 11:31:25 -0300426static inline void finish_buffer(struct em28xx *dev,
427 struct em28xx_buffer *buf)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300428{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300429 em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->top_field);
430
431 buf->vb.v4l2_buf.sequence = dev->field_count++;
432 buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
433 v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
434
435 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300436}
437
438/*
Frank Schaefer36016a32012-12-08 11:31:32 -0300439 * Copy picture data from USB buffer to videobuf buffer
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300440 */
441static void em28xx_copy_video(struct em28xx *dev,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300442 struct em28xx_buffer *buf,
Frank Schaefer36016a32012-12-08 11:31:32 -0300443 unsigned char *usb_buf,
Frank Schaefer4078d622012-12-08 11:31:29 -0300444 unsigned long len)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300445{
446 void *fieldstart, *startwrite, *startread;
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300447 int linesdone, currlinedone, offset, lencopy, remain;
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300448 int bytesperline = dev->width << 1;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300449
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300450 if (buf->pos + len > buf->length)
451 len = buf->length - buf->pos;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300452
Frank Schaefer36016a32012-12-08 11:31:32 -0300453 startread = usb_buf;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300454 remain = len;
455
Frank Schaeferc02ec712012-11-08 14:11:33 -0300456 if (dev->progressive || buf->top_field)
Frank Schaefer36016a32012-12-08 11:31:32 -0300457 fieldstart = buf->vb_buf;
Frank Schaeferc02ec712012-11-08 14:11:33 -0300458 else /* interlaced mode, even nr. of lines */
Frank Schaefer36016a32012-12-08 11:31:32 -0300459 fieldstart = buf->vb_buf + bytesperline;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300460
Frank Schaefer87325332012-12-08 11:31:27 -0300461 linesdone = buf->pos / bytesperline;
462 currlinedone = buf->pos % bytesperline;
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -0300463
464 if (dev->progressive)
465 offset = linesdone * bytesperline + currlinedone;
466 else
467 offset = linesdone * bytesperline * 2 + currlinedone;
468
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300469 startwrite = fieldstart + offset;
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300470 lencopy = bytesperline - currlinedone;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300471 lencopy = lencopy > remain ? remain : lencopy;
472
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300473 if ((char *)startwrite + lencopy > (char *)buf->vb_buf + buf->length) {
Mauro Carvalho Chehabea8df7e2008-04-13 14:39:29 -0300474 em28xx_isocdbg("Overflow of %zi bytes past buffer end (1)\n",
Frank Schaefer36016a32012-12-08 11:31:32 -0300475 ((char *)startwrite + lencopy) -
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300476 ((char *)buf->vb_buf + buf->length));
477 remain = (char *)buf->vb_buf + buf->length -
Frank Schaefer36016a32012-12-08 11:31:32 -0300478 (char *)startwrite;
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -0300479 lencopy = remain;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300480 }
Aidan Thorntone0fadfd342008-04-13 14:56:02 -0300481 if (lencopy <= 0)
482 return;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300483 memcpy(startwrite, startread, lencopy);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300484
485 remain -= lencopy;
486
487 while (remain > 0) {
Frank Schaeferc02ec712012-11-08 14:11:33 -0300488 if (dev->progressive)
489 startwrite += lencopy;
490 else
491 startwrite += lencopy + bytesperline;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300492 startread += lencopy;
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300493 if (bytesperline > remain)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300494 lencopy = remain;
495 else
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300496 lencopy = bytesperline;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300497
Frank Schaefer36016a32012-12-08 11:31:32 -0300498 if ((char *)startwrite + lencopy > (char *)buf->vb_buf +
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300499 buf->length) {
Devin Heitmuellere3ba4d32009-09-15 00:18:06 -0300500 em28xx_isocdbg("Overflow of %zi bytes past buffer end"
501 "(2)\n",
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300502 ((char *)startwrite + lencopy) -
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300503 ((char *)buf->vb_buf + buf->length));
504 lencopy = remain = (char *)buf->vb_buf + buf->length -
505 (char *)startwrite;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300506 }
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300507 if (lencopy <= 0)
508 break;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300509
510 memcpy(startwrite, startread, lencopy);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300511
512 remain -= lencopy;
513 }
514
Frank Schaefer87325332012-12-08 11:31:27 -0300515 buf->pos += len;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300516}
517
Frank Schaefer36016a32012-12-08 11:31:32 -0300518/*
519 * Copy VBI data from USB buffer to videobuf buffer
520 */
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300521static void em28xx_copy_vbi(struct em28xx *dev,
Frank Schaefer87325332012-12-08 11:31:27 -0300522 struct em28xx_buffer *buf,
Frank Schaefer36016a32012-12-08 11:31:32 -0300523 unsigned char *usb_buf,
Frank Schaefer4078d622012-12-08 11:31:29 -0300524 unsigned long len)
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300525{
Frank Schaefer36016a32012-12-08 11:31:32 -0300526 unsigned int offset;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300527
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300528 if (buf->pos + len > buf->length)
529 len = buf->length - buf->pos;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300530
Frank Schaefer87325332012-12-08 11:31:27 -0300531 offset = buf->pos;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300532 /* Make sure the bottom field populates the second half of the frame */
Frank Schaefer36016a32012-12-08 11:31:32 -0300533 if (buf->top_field == 0)
534 offset += dev->vbi_width * dev->vbi_height;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300535
Frank Schaefer36016a32012-12-08 11:31:32 -0300536 memcpy(buf->vb_buf + offset, usb_buf, len);
Frank Schaefer87325332012-12-08 11:31:27 -0300537 buf->pos += len;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300538}
539
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300540static inline void print_err_status(struct em28xx *dev,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300541 int packet, int status)
542{
543 char *errmsg = "Unknown";
544
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300545 switch (status) {
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300546 case -ENOENT:
547 errmsg = "unlinked synchronuously";
548 break;
549 case -ECONNRESET:
550 errmsg = "unlinked asynchronuously";
551 break;
552 case -ENOSR:
553 errmsg = "Buffer error (overrun)";
554 break;
555 case -EPIPE:
556 errmsg = "Stalled (device not responding)";
557 break;
558 case -EOVERFLOW:
559 errmsg = "Babble (bad cable?)";
560 break;
561 case -EPROTO:
562 errmsg = "Bit-stuff error (bad cable?)";
563 break;
564 case -EILSEQ:
565 errmsg = "CRC/Timeout (could be anything)";
566 break;
567 case -ETIME:
568 errmsg = "Device does not respond";
569 break;
570 }
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300571 if (packet < 0) {
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300572 em28xx_isocdbg("URB status %d [%s].\n", status, errmsg);
573 } else {
574 em28xx_isocdbg("URB packet %d, status %d [%s].\n",
575 packet, status, errmsg);
576 }
577}
578
579/*
Frank Schaefer24a6d842012-12-08 11:31:24 -0300580 * get the next available buffer from dma queue
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300581 */
Frank Schaefer24a6d842012-12-08 11:31:24 -0300582static inline struct em28xx_buffer *get_next_buf(struct em28xx *dev,
583 struct em28xx_dmaqueue *dma_q)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300584{
Frank Schaefer24a6d842012-12-08 11:31:24 -0300585 struct em28xx_buffer *buf;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300586
Mauro Carvalho Chehabdbecb442008-04-13 15:08:55 -0300587 if (list_empty(&dma_q->active)) {
588 em28xx_isocdbg("No active queue to serve\n");
Frank Schaefer24a6d842012-12-08 11:31:24 -0300589 return NULL;
Mauro Carvalho Chehabdbecb442008-04-13 15:08:55 -0300590 }
591
Mauro Carvalho Chehabdbecb442008-04-13 15:08:55 -0300592 /* Get the next buffer */
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300593 buf = list_entry(dma_q->active.next, struct em28xx_buffer, list);
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300594 /* Cleans up buffer - Useful for testing for frame/URB loss */
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300595 list_del(&buf->list);
Frank Schaefer87325332012-12-08 11:31:27 -0300596 buf->pos = 0;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300597 buf->vb_buf = buf->mem;
Mauro Carvalho Chehabcb784722008-04-13 15:06:52 -0300598
Frank Schaefer24a6d842012-12-08 11:31:24 -0300599 return buf;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300600}
601
Frank Schaefere04c00d2012-12-08 11:31:30 -0300602/*
603 * Finish the current buffer if completed and prepare for the next field
604 */
605static struct em28xx_buffer *
606finish_field_prepare_next(struct em28xx *dev,
607 struct em28xx_buffer *buf,
608 struct em28xx_dmaqueue *dma_q)
609{
610 if (dev->progressive || dev->top_field) { /* Brand new frame */
611 if (buf != NULL)
612 finish_buffer(dev, buf);
613 buf = get_next_buf(dev, dma_q);
614 }
615 if (buf != NULL) {
616 buf->top_field = dev->top_field;
617 buf->pos = 0;
618 }
619
620 return buf;
621}
622
Frank Schaefer227b7c92012-12-08 11:31:31 -0300623/*
624 * Process data packet according to the em2710/em2750/em28xx frame data format
625 */
626static inline void process_frame_data_em28xx(struct em28xx *dev,
627 unsigned char *data_pkt,
628 unsigned int data_len)
629{
630 struct em28xx_buffer *buf = dev->usb_ctl.vid_buf;
631 struct em28xx_buffer *vbi_buf = dev->usb_ctl.vbi_buf;
632 struct em28xx_dmaqueue *dma_q = &dev->vidq;
633 struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq;
634
635 /* capture type 0 = vbi start
636 capture type 1 = vbi in progress
637 capture type 2 = video start
638 capture type 3 = video in progress */
639 if (data_len >= 4) {
640 /* NOTE: Headers are always 4 bytes and
641 * never split across packets */
642 if (data_pkt[0] == 0x88 && data_pkt[1] == 0x88 &&
643 data_pkt[2] == 0x88 && data_pkt[3] == 0x88) {
644 /* Continuation */
645 data_pkt += 4;
646 data_len -= 4;
647 } else if (data_pkt[0] == 0x33 && data_pkt[1] == 0x95) {
648 /* Field start (VBI mode) */
649 dev->capture_type = 0;
650 dev->vbi_read = 0;
651 em28xx_isocdbg("VBI START HEADER !!!\n");
652 dev->top_field = !(data_pkt[2] & 1);
653 data_pkt += 4;
654 data_len -= 4;
655 } else if (data_pkt[0] == 0x22 && data_pkt[1] == 0x5a) {
656 /* Field start (VBI disabled) */
657 dev->capture_type = 2;
658 em28xx_isocdbg("VIDEO START HEADER !!!\n");
659 dev->top_field = !(data_pkt[2] & 1);
660 data_pkt += 4;
661 data_len -= 4;
662 }
663 }
664 /* NOTE: With bulk transfers, intermediate data packets
665 * have no continuation header */
666
667 if (dev->capture_type == 0) {
668 vbi_buf = finish_field_prepare_next(dev, vbi_buf, vbi_dma_q);
669 dev->usb_ctl.vbi_buf = vbi_buf;
670 dev->capture_type = 1;
671 }
672
673 if (dev->capture_type == 1) {
674 int vbi_size = dev->vbi_width * dev->vbi_height;
675 int vbi_data_len = ((dev->vbi_read + data_len) > vbi_size) ?
676 (vbi_size - dev->vbi_read) : data_len;
677
678 /* Copy VBI data */
679 if (vbi_buf != NULL)
680 em28xx_copy_vbi(dev, vbi_buf, data_pkt, vbi_data_len);
681 dev->vbi_read += vbi_data_len;
682
683 if (vbi_data_len < data_len) {
684 /* Continue with copying video data */
685 dev->capture_type = 2;
686 data_pkt += vbi_data_len;
687 data_len -= vbi_data_len;
688 }
689 }
690
691 if (dev->capture_type == 2) {
692 buf = finish_field_prepare_next(dev, buf, dma_q);
693 dev->usb_ctl.vid_buf = buf;
694 dev->capture_type = 3;
695 }
696
697 if (dev->capture_type == 3 && buf != NULL && data_len > 0)
698 em28xx_copy_video(dev, buf, data_pkt, data_len);
699}
700
Frank Schaefere507e0e2013-03-26 13:38:38 -0300701/*
702 * Process data packet according to the em25xx/em276x/7x/8x frame data format
703 */
704static inline void process_frame_data_em25xx(struct em28xx *dev,
705 unsigned char *data_pkt,
706 unsigned int data_len)
707{
708 struct em28xx_buffer *buf = dev->usb_ctl.vid_buf;
709 struct em28xx_dmaqueue *dmaq = &dev->vidq;
710 bool frame_end = 0;
711
712 /* Check for header */
713 /* NOTE: at least with bulk transfers, only the first packet
714 * has a header and has always set the FRAME_END bit */
715 if (data_len >= 2) { /* em25xx header is only 2 bytes long */
716 if ((data_pkt[0] == EM25XX_FRMDATAHDR_BYTE1) &&
717 ((data_pkt[1] & ~EM25XX_FRMDATAHDR_BYTE2_MASK) == 0x00)) {
718 dev->top_field = !(data_pkt[1] &
719 EM25XX_FRMDATAHDR_BYTE2_FRAME_ID);
720 frame_end = data_pkt[1] &
721 EM25XX_FRMDATAHDR_BYTE2_FRAME_END;
722 data_pkt += 2;
723 data_len -= 2;
724 }
725
726 /* Finish field and prepare next (BULK only) */
727 if (dev->analog_xfer_bulk && frame_end) {
728 buf = finish_field_prepare_next(dev, buf, dmaq);
729 dev->usb_ctl.vid_buf = buf;
730 }
731 /* NOTE: in ISOC mode when a new frame starts and buf==NULL,
732 * we COULD already prepare a buffer here to avoid skipping the
733 * first frame.
734 */
735 }
736
737 /* Copy data */
738 if (buf != NULL && data_len > 0)
739 em28xx_copy_video(dev, buf, data_pkt, data_len);
740
741 /* Finish frame (ISOC only) => avoids lag of 1 frame */
742 if (!dev->analog_xfer_bulk && frame_end) {
743 buf = finish_field_prepare_next(dev, buf, dmaq);
744 dev->usb_ctl.vid_buf = buf;
745 }
746
747 /* NOTE: Tested with USB bulk transfers only !
748 * The wording in the datasheet suggests that isoc might work different.
749 * The current code assumes that with isoc transfers each packet has a
750 * header like with the other em28xx devices.
751 */
752 /* NOTE: Support for interlaced mode is pure theory. It has not been
753 * tested and it is unknown if these devices actually support it. */
754 /* NOTE: No VBI support yet (these chips likely do not support VBI). */
755}
756
Frank Schaefer960da932012-11-25 06:37:37 -0300757/* Processes and copies the URB data content (video and VBI data) */
Frank Schaefer0fa4a402012-11-08 14:11:45 -0300758static inline int em28xx_urb_data_copy(struct em28xx *dev, struct urb *urb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300759{
Frank Schaefer227b7c92012-12-08 11:31:31 -0300760 int xfer_bulk, num_packets, i;
761 unsigned char *usb_data_pkt;
762 unsigned int usb_data_len;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300763
764 if (!dev)
765 return 0;
766
Frank Schaefer2665c292012-12-27 19:02:43 -0300767 if (dev->disconnected)
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300768 return 0;
769
Frank Schaefer1653cb0c2012-11-08 14:11:44 -0300770 if (urb->status < 0)
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300771 print_err_status(dev, -1, urb->status);
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300772
Frank Schaefer4601cc32012-11-08 14:11:46 -0300773 xfer_bulk = usb_pipebulk(urb->pipe);
774
Frank Schaefer4601cc32012-11-08 14:11:46 -0300775 if (xfer_bulk) /* bulk */
776 num_packets = 1;
777 else /* isoc */
778 num_packets = urb->number_of_packets;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300779
Frank Schaefer4601cc32012-11-08 14:11:46 -0300780 for (i = 0; i < num_packets; i++) {
781 if (xfer_bulk) { /* bulk */
Frank Schaefer227b7c92012-12-08 11:31:31 -0300782 usb_data_len = urb->actual_length;
Frank Schaefer4601cc32012-11-08 14:11:46 -0300783
Frank Schaefer227b7c92012-12-08 11:31:31 -0300784 usb_data_pkt = urb->transfer_buffer;
Frank Schaefer4601cc32012-11-08 14:11:46 -0300785 } else { /* isoc */
786 if (urb->iso_frame_desc[i].status < 0) {
787 print_err_status(dev, i,
788 urb->iso_frame_desc[i].status);
789 if (urb->iso_frame_desc[i].status != -EPROTO)
790 continue;
791 }
792
Frank Schaefer227b7c92012-12-08 11:31:31 -0300793 usb_data_len = urb->iso_frame_desc[i].actual_length;
794 if (usb_data_len > dev->max_pkt_size) {
Frank Schaefer4601cc32012-11-08 14:11:46 -0300795 em28xx_isocdbg("packet bigger than packet size");
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300796 continue;
Frank Schaefer4601cc32012-11-08 14:11:46 -0300797 }
798
Frank Schaefer227b7c92012-12-08 11:31:31 -0300799 usb_data_pkt = urb->transfer_buffer +
800 urb->iso_frame_desc[i].offset;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300801 }
802
Frank Schaefer227b7c92012-12-08 11:31:31 -0300803 if (usb_data_len == 0) {
Frank Schaefer4601cc32012-11-08 14:11:46 -0300804 /* NOTE: happens very often with isoc transfers */
805 /* em28xx_usbdbg("packet %d is empty",i); - spammy */
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300806 continue;
807 }
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300808
Frank Schaefere507e0e2013-03-26 13:38:38 -0300809 if (dev->is_em25xx)
810 process_frame_data_em25xx(dev,
811 usb_data_pkt, usb_data_len);
812 else
813 process_frame_data_em28xx(dev,
814 usb_data_pkt, usb_data_len);
815
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300816 }
Frank Schaefer227b7c92012-12-08 11:31:31 -0300817 return 1;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300818}
819
820
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300821static int get_ressource(enum v4l2_buf_type f_type)
822{
823 switch (f_type) {
824 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
825 return EM28XX_RESOURCE_VIDEO;
826 case V4L2_BUF_TYPE_VBI_CAPTURE:
827 return EM28XX_RESOURCE_VBI;
828 default:
829 BUG();
830 return 0;
831 }
832}
833
834/* Usage lock check functions */
835static int res_get(struct em28xx *dev, enum v4l2_buf_type f_type)
836{
837 int res_type = get_ressource(f_type);
838
839 /* is it free? */
840 if (dev->resources & res_type) {
841 /* no, someone else uses it */
842 return -EBUSY;
843 }
844
845 /* it's free, grab it */
846 dev->resources |= res_type;
847 em28xx_videodbg("res: get %d\n", res_type);
848 return 0;
849}
850
851static void res_free(struct em28xx *dev, enum v4l2_buf_type f_type)
852{
853 int res_type = get_ressource(f_type);
854
855 dev->resources &= ~res_type;
856 em28xx_videodbg("res: put %d\n", res_type);
857}
858
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300859/* ------------------------------------------------------------------
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300860 Videobuf2 operations
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300861 ------------------------------------------------------------------*/
862
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300863static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
864 unsigned int *nbuffers, unsigned int *nplanes,
865 unsigned int sizes[], void *alloc_ctxs[])
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300866{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300867 struct em28xx *dev = vb2_get_drv_priv(vq);
868 unsigned long size;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300869
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300870 if (fmt)
871 size = fmt->fmt.pix.sizeimage;
872 else
873 size = (dev->width * dev->height * dev->format->depth + 7) >> 3;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -0300874
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300875 if (size == 0)
876 return -EINVAL;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300877
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300878 if (0 == *nbuffers)
879 *nbuffers = 32;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300880
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300881 *nplanes = 1;
882 sizes[0] = size;
Mauro Carvalho Chehabd2d9fbf2008-04-17 21:38:53 -0300883
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300884 return 0;
885}
886
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300887static int
888buffer_prepare(struct vb2_buffer *vb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300889{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300890 struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue);
891 struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
892 unsigned long size;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300893
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300894 em28xx_videodbg("%s, field=%d\n", __func__, vb->v4l2_buf.field);
Aidan Thornton3b5fa922008-04-13 15:09:36 -0300895
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300896 size = (dev->width * dev->height * dev->format->depth + 7) >> 3;
Aidan Thornton3b5fa922008-04-13 15:09:36 -0300897
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300898 if (vb2_plane_size(vb, 0) < size) {
899 em28xx_videodbg("%s data will not fit into plane (%lu < %lu)\n",
900 __func__, vb2_plane_size(vb, 0), size);
901 return -EINVAL;
902 }
903 vb2_set_plane_payload(&buf->vb, 0, size);
904
905 return 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300906}
907
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300908int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300909{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300910 struct em28xx *dev = vb2_get_drv_priv(vq);
911 struct v4l2_frequency f;
912 int rc = 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300913
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300914 em28xx_videodbg("%s\n", __func__);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300915
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300916 /* Make sure streaming is not already in progress for this type
917 of filehandle (e.g. video, vbi) */
918 rc = res_get(dev, vq->type);
919 if (rc)
920 return rc;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300921
Frank Schaefer032f1dd2013-10-10 15:31:53 -0300922 if (dev->streaming_users == 0) {
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300923 /* First active streaming user, so allocate all the URBs */
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300924
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300925 /* Allocate the USB bandwidth */
926 em28xx_set_alternate(dev);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300927
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300928 /* Needed, since GPIO might have disabled power of
929 some i2c device
930 */
931 em28xx_wake_i2c(dev);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300932
Frank Schaefer0455eeb2012-11-25 06:37:34 -0300933 dev->capture_type = -1;
Frank Schaefer960da932012-11-25 06:37:37 -0300934 rc = em28xx_init_usb_xfer(dev, EM28XX_ANALOG_MODE,
935 dev->analog_xfer_bulk,
936 EM28XX_NUM_BUFS,
937 dev->max_pkt_size,
938 dev->packet_multiplier,
939 em28xx_urb_data_copy);
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300940 if (rc < 0)
Frank Schaefer032f1dd2013-10-10 15:31:53 -0300941 return rc;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300942
943 /*
944 * djh: it's not clear whether this code is still needed. I'm
945 * leaving it in here for now entirely out of concern for
946 * backward compatibility (the old code did it)
947 */
948
949 /* Ask tuner to go to analog or radio mode */
950 memset(&f, 0, sizeof(f));
951 f.frequency = dev->ctl_freq;
952 if (vq->owner && vq->owner->vdev->vfl_type == VFL_TYPE_RADIO)
953 f.type = V4L2_TUNER_RADIO;
954 else
955 f.type = V4L2_TUNER_ANALOG_TV;
Frank Schaefer95d26082014-03-24 16:33:09 -0300956 v4l2_device_call_all(&dev->v4l2->v4l2_dev,
957 0, tuner, s_frequency, &f);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300958 }
959
Frank Schaefer032f1dd2013-10-10 15:31:53 -0300960 dev->streaming_users++;
961
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300962 return rc;
963}
964
Hans Verkuile37559b2014-04-17 02:47:21 -0300965static void em28xx_stop_streaming(struct vb2_queue *vq)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300966{
967 struct em28xx *dev = vb2_get_drv_priv(vq);
968 struct em28xx_dmaqueue *vidq = &dev->vidq;
969 unsigned long flags = 0;
970
971 em28xx_videodbg("%s\n", __func__);
972
973 res_free(dev, vq->type);
974
975 if (dev->streaming_users-- == 1) {
976 /* Last active user, so shutdown all the URBS */
977 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
978 }
979
980 spin_lock_irqsave(&dev->slock, flags);
981 while (!list_empty(&vidq->active)) {
982 struct em28xx_buffer *buf;
983 buf = list_entry(vidq->active.next, struct em28xx_buffer, list);
984 list_del(&buf->list);
985 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
986 }
987 dev->usb_ctl.vid_buf = NULL;
988 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300989}
990
Hans Verkuile37559b2014-04-17 02:47:21 -0300991void em28xx_stop_vbi_streaming(struct vb2_queue *vq)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300992{
993 struct em28xx *dev = vb2_get_drv_priv(vq);
994 struct em28xx_dmaqueue *vbiq = &dev->vbiq;
995 unsigned long flags = 0;
996
997 em28xx_videodbg("%s\n", __func__);
998
999 res_free(dev, vq->type);
1000
1001 if (dev->streaming_users-- == 1) {
1002 /* Last active user, so shutdown all the URBS */
1003 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
1004 }
1005
1006 spin_lock_irqsave(&dev->slock, flags);
1007 while (!list_empty(&vbiq->active)) {
1008 struct em28xx_buffer *buf;
1009 buf = list_entry(vbiq->active.next, struct em28xx_buffer, list);
1010 list_del(&buf->list);
1011 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
1012 }
1013 dev->usb_ctl.vbi_buf = NULL;
1014 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001015}
1016
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001017static void
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001018buffer_queue(struct vb2_buffer *vb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001019{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001020 struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue);
1021 struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
1022 struct em28xx_dmaqueue *vidq = &dev->vidq;
1023 unsigned long flags = 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001024
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001025 em28xx_videodbg("%s\n", __func__);
1026 buf->mem = vb2_plane_vaddr(vb, 0);
1027 buf->length = vb2_plane_size(vb, 0);
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001028
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001029 spin_lock_irqsave(&dev->slock, flags);
1030 list_add_tail(&buf->list, &vidq->active);
1031 spin_unlock_irqrestore(&dev->slock, flags);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001032}
1033
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001034static struct vb2_ops em28xx_video_qops = {
1035 .queue_setup = queue_setup,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001036 .buf_prepare = buffer_prepare,
1037 .buf_queue = buffer_queue,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001038 .start_streaming = em28xx_start_analog_streaming,
1039 .stop_streaming = em28xx_stop_streaming,
1040 .wait_prepare = vb2_ops_wait_prepare,
1041 .wait_finish = vb2_ops_wait_finish,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001042};
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001043
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001044static int em28xx_vb2_setup(struct em28xx *dev)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001045{
1046 int rc;
1047 struct vb2_queue *q;
1048
1049 /* Setup Videobuf2 for Video capture */
1050 q = &dev->vb_vidq;
1051 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Mauro Carvalho Chehabef85cd92013-01-06 00:34:22 -02001052 q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
Sakari Ailusade48682014-02-25 19:12:19 -03001053 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001054 q->drv_priv = dev;
1055 q->buf_struct_size = sizeof(struct em28xx_buffer);
1056 q->ops = &em28xx_video_qops;
1057 q->mem_ops = &vb2_vmalloc_memops;
1058
1059 rc = vb2_queue_init(q);
1060 if (rc < 0)
1061 return rc;
1062
1063 /* Setup Videobuf2 for VBI capture */
1064 q = &dev->vb_vbiq;
1065 q->type = V4L2_BUF_TYPE_VBI_CAPTURE;
1066 q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR;
Sakari Ailusade48682014-02-25 19:12:19 -03001067 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001068 q->drv_priv = dev;
1069 q->buf_struct_size = sizeof(struct em28xx_buffer);
1070 q->ops = &em28xx_vbi_qops;
1071 q->mem_ops = &vb2_vmalloc_memops;
1072
1073 rc = vb2_queue_init(q);
1074 if (rc < 0)
1075 return rc;
1076
1077 return 0;
1078}
1079
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001080/********************* v4l2 interface **************************************/
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001081
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001082static void video_mux(struct em28xx *dev, int index)
1083{
Frank Schaefer95d26082014-03-24 16:33:09 -03001084 struct v4l2_device *v4l2_dev = &dev->v4l2->v4l2_dev;
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001085 dev->ctl_input = index;
1086 dev->ctl_ainput = INPUT(index)->amux;
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001087 dev->ctl_aoutput = INPUT(index)->aout;
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001088
Mauro Carvalho Chehabe879b8e2008-11-20 13:39:39 -03001089 if (!dev->ctl_aoutput)
1090 dev->ctl_aoutput = EM28XX_AOUT_MASTER;
1091
Frank Schaefer95d26082014-03-24 16:33:09 -03001092 v4l2_device_call_all(v4l2_dev, 0, video, s_routing,
Hans Verkuil5325b422009-04-02 11:26:22 -03001093 INPUT(index)->vmux, 0, 0);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001094
Mauro Carvalho Chehab505b6d02008-11-25 09:39:50 -03001095 if (dev->board.has_msp34xx) {
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001096 if (dev->i2s_speed) {
Frank Schaefer95d26082014-03-24 16:33:09 -03001097 v4l2_device_call_all(v4l2_dev, 0, audio,
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03001098 s_i2s_clock_freq, dev->i2s_speed);
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001099 }
Hans Verkuil2474ed42006-03-19 12:35:57 -03001100 /* Note: this is msp3400 specific */
Frank Schaefer95d26082014-03-24 16:33:09 -03001101 v4l2_device_call_all(v4l2_dev, 0, audio, s_routing,
Hans Verkuil5325b422009-04-02 11:26:22 -03001102 dev->ctl_ainput, MSP_OUTPUT(MSP_SC_IN_DSP_SCART1), 0);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001103 }
Mauro Carvalho Chehab539c96d2008-01-05 09:53:54 -03001104
Vitaly Wool2bd1d9e2009-03-04 08:27:52 -03001105 if (dev->board.adecoder != EM28XX_NOADECODER) {
Frank Schaefer95d26082014-03-24 16:33:09 -03001106 v4l2_device_call_all(v4l2_dev, 0, audio, s_routing,
Hans Verkuil5325b422009-04-02 11:26:22 -03001107 dev->ctl_ainput, dev->ctl_aoutput, 0);
Vitaly Wool2bd1d9e2009-03-04 08:27:52 -03001108 }
1109
Mauro Carvalho Chehab00b87302008-02-06 18:34:13 -03001110 em28xx_audio_analog_set(dev);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001111}
1112
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001113static void em28xx_ctrl_notify(struct v4l2_ctrl *ctrl, void *priv)
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001114{
Hans Verkuil081b9452012-09-07 05:43:59 -03001115 struct em28xx *dev = priv;
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001116
Hans Verkuil081b9452012-09-07 05:43:59 -03001117 /*
1118 * In the case of non-AC97 volume controls, we still need
1119 * to do some setups at em28xx, in order to mute/unmute
1120 * and to adjust audio volume. However, the value ranges
1121 * should be checked by the corresponding V4L subdriver.
1122 */
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001123 switch (ctrl->id) {
1124 case V4L2_CID_AUDIO_MUTE:
Hans Verkuil081b9452012-09-07 05:43:59 -03001125 dev->mute = ctrl->val;
1126 em28xx_audio_analog_set(dev);
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001127 break;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001128 case V4L2_CID_AUDIO_VOLUME:
Hans Verkuil081b9452012-09-07 05:43:59 -03001129 dev->volume = ctrl->val;
1130 em28xx_audio_analog_set(dev);
1131 break;
1132 }
1133}
1134
1135static int em28xx_s_ctrl(struct v4l2_ctrl *ctrl)
1136{
Frank Schaeferabc13082014-03-24 16:33:10 -03001137 struct em28xx_v4l2 *v4l2 =
1138 container_of(ctrl->handler, struct em28xx_v4l2, ctrl_handler);
1139 struct em28xx *dev = v4l2->dev;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001140 int ret = -EINVAL;
Hans Verkuil081b9452012-09-07 05:43:59 -03001141
1142 switch (ctrl->id) {
1143 case V4L2_CID_AUDIO_MUTE:
1144 dev->mute = ctrl->val;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001145 ret = em28xx_audio_analog_set(dev);
Hans Verkuil081b9452012-09-07 05:43:59 -03001146 break;
1147 case V4L2_CID_AUDIO_VOLUME:
1148 dev->volume = ctrl->val;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001149 ret = em28xx_audio_analog_set(dev);
1150 break;
1151 case V4L2_CID_CONTRAST:
1152 ret = em28xx_write_reg(dev, EM28XX_R20_YGAIN, ctrl->val);
1153 break;
1154 case V4L2_CID_BRIGHTNESS:
1155 ret = em28xx_write_reg(dev, EM28XX_R21_YOFFSET, ctrl->val);
1156 break;
1157 case V4L2_CID_SATURATION:
1158 ret = em28xx_write_reg(dev, EM28XX_R22_UVGAIN, ctrl->val);
1159 break;
1160 case V4L2_CID_BLUE_BALANCE:
1161 ret = em28xx_write_reg(dev, EM28XX_R23_UOFFSET, ctrl->val);
1162 break;
1163 case V4L2_CID_RED_BALANCE:
1164 ret = em28xx_write_reg(dev, EM28XX_R24_VOFFSET, ctrl->val);
1165 break;
1166 case V4L2_CID_SHARPNESS:
1167 ret = em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, ctrl->val);
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001168 break;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001169 }
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001170
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001171 return (ret < 0) ? ret : 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001172}
1173
Fengguang Wu8068eb82014-01-07 12:50:47 -03001174static const struct v4l2_ctrl_ops em28xx_ctrl_ops = {
Hans Verkuil081b9452012-09-07 05:43:59 -03001175 .s_ctrl = em28xx_s_ctrl,
1176};
1177
Frank Schaefer6b09a212013-02-10 16:05:12 -03001178static void size_to_scale(struct em28xx *dev,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001179 unsigned int width, unsigned int height,
1180 unsigned int *hscale, unsigned int *vscale)
1181{
Mauro Carvalho Chehab55699962009-07-13 20:15:02 -03001182 unsigned int maxw = norm_maxw(dev);
1183 unsigned int maxh = norm_maxh(dev);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001184
1185 *hscale = (((unsigned long)maxw) << 12) / width - 4096L;
Frank Schaefer81685322013-02-10 16:05:11 -03001186 if (*hscale > EM28XX_HVSCALE_MAX)
1187 *hscale = EM28XX_HVSCALE_MAX;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001188
1189 *vscale = (((unsigned long)maxh) << 12) / height - 4096L;
Frank Schaefer81685322013-02-10 16:05:11 -03001190 if (*vscale > EM28XX_HVSCALE_MAX)
1191 *vscale = EM28XX_HVSCALE_MAX;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001192}
1193
Frank Schaeferb8374132013-02-10 16:05:13 -03001194static void scale_to_size(struct em28xx *dev,
1195 unsigned int hscale, unsigned int vscale,
1196 unsigned int *width, unsigned int *height)
1197{
1198 unsigned int maxw = norm_maxw(dev);
1199 unsigned int maxh = norm_maxh(dev);
1200
1201 *width = (((unsigned long)maxw) << 12) / (hscale + 4096L);
1202 *height = (((unsigned long)maxh) << 12) / (vscale + 4096L);
1203}
1204
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001205/* ------------------------------------------------------------------
1206 IOCTL vidioc handling
1207 ------------------------------------------------------------------*/
1208
Hans Verkuil78b526a2008-05-28 12:16:41 -03001209static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001210 struct v4l2_format *f)
1211{
1212 struct em28xx_fh *fh = priv;
1213 struct em28xx *dev = fh->dev;
1214
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001215 f->fmt.pix.width = dev->width;
1216 f->fmt.pix.height = dev->height;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001217 f->fmt.pix.pixelformat = dev->format->fourcc;
1218 f->fmt.pix.bytesperline = (dev->width * dev->format->depth + 7) >> 3;
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -03001219 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * dev->height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001220 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
1221
1222 /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -03001223 if (dev->progressive)
1224 f->fmt.pix.field = V4L2_FIELD_NONE;
1225 else
1226 f->fmt.pix.field = dev->interlaced ?
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001227 V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001228 return 0;
1229}
1230
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001231static struct em28xx_fmt *format_by_fourcc(unsigned int fourcc)
1232{
1233 unsigned int i;
1234
1235 for (i = 0; i < ARRAY_SIZE(format); i++)
1236 if (format[i].fourcc == fourcc)
1237 return &format[i];
1238
1239 return NULL;
1240}
1241
Hans Verkuil78b526a2008-05-28 12:16:41 -03001242static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001243 struct v4l2_format *f)
1244{
1245 struct em28xx_fh *fh = priv;
1246 struct em28xx *dev = fh->dev;
Trent Piephoccb83402009-05-30 21:45:46 -03001247 unsigned int width = f->fmt.pix.width;
1248 unsigned int height = f->fmt.pix.height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001249 unsigned int maxw = norm_maxw(dev);
1250 unsigned int maxh = norm_maxh(dev);
1251 unsigned int hscale, vscale;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001252 struct em28xx_fmt *fmt;
1253
1254 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
1255 if (!fmt) {
1256 em28xx_videodbg("Fourcc format (%08x) invalid.\n",
1257 f->fmt.pix.pixelformat);
1258 return -EINVAL;
1259 }
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001260
Mauro Carvalho Chehab55699962009-07-13 20:15:02 -03001261 if (dev->board.is_em2800) {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001262 /* the em2800 can only scale down to 50% */
Trent Piephoccb83402009-05-30 21:45:46 -03001263 height = height > (3 * maxh / 4) ? maxh : maxh / 2;
1264 width = width > (3 * maxw / 4) ? maxw : maxw / 2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001265 /*
1266 * MaxPacketSize for em2800 is too small to capture at full
1267 * resolution use half of maxw as the scaler can only scale
1268 * to 50%
1269 */
Sascha Sommer1020d132012-01-08 16:54:28 -03001270 if (width == maxw && height == maxh)
1271 width /= 2;
Trent Piephoccb83402009-05-30 21:45:46 -03001272 } else {
1273 /* width must even because of the YUYV format
1274 height must be even because of interlacing */
Devin Heitmuellere3ba4d32009-09-15 00:18:06 -03001275 v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh,
1276 1, 0);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001277 }
1278
Frank Schaefer6b09a212013-02-10 16:05:12 -03001279 size_to_scale(dev, width, height, &hscale, &vscale);
Hans Verkuil46f85972013-03-30 05:31:42 -03001280 scale_to_size(dev, hscale, vscale, &width, &height);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001281
1282 f->fmt.pix.width = width;
1283 f->fmt.pix.height = height;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001284 f->fmt.pix.pixelformat = fmt->fourcc;
Hans Verkuile6066db2013-02-06 08:14:47 -03001285 f->fmt.pix.bytesperline = (width * fmt->depth + 7) >> 3;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001286 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001287 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -03001288 if (dev->progressive)
1289 f->fmt.pix.field = V4L2_FIELD_NONE;
1290 else
1291 f->fmt.pix.field = dev->interlaced ?
1292 V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
Alban Browaeys51dd4d72013-07-16 19:06:46 -03001293 f->fmt.pix.priv = 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001294
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001295 return 0;
1296}
1297
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001298static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc,
1299 unsigned width, unsigned height)
1300{
1301 struct em28xx_fmt *fmt;
1302
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001303 fmt = format_by_fourcc(fourcc);
1304 if (!fmt)
1305 return -EINVAL;
1306
1307 dev->format = fmt;
1308 dev->width = width;
1309 dev->height = height;
1310
1311 /* set new image size */
Frank Schaefer6b09a212013-02-10 16:05:12 -03001312 size_to_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001313
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001314 em28xx_resolution_set(dev);
1315
1316 return 0;
1317}
1318
Hans Verkuil78b526a2008-05-28 12:16:41 -03001319static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001320 struct v4l2_format *f)
1321{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001322 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001323
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001324 if (dev->streaming_users > 0)
1325 return -EBUSY;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001326
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001327 vidioc_try_fmt_vid_cap(file, priv, f);
1328
Hans Verkuil0499a5a2010-09-26 07:34:45 -03001329 return em28xx_set_video_format(dev, f->fmt.pix.pixelformat,
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001330 f->fmt.pix.width, f->fmt.pix.height);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001331}
1332
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001333static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
1334{
1335 struct em28xx_fh *fh = priv;
1336 struct em28xx *dev = fh->dev;
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001337
1338 *norm = dev->norm;
1339
1340 return 0;
1341}
1342
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001343static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm)
1344{
1345 struct em28xx_fh *fh = priv;
1346 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001347
Frank Schaefer95d26082014-03-24 16:33:09 -03001348 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, video, querystd, norm);
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001349
1350 return 0;
1351}
1352
Hans Verkuil314527a2013-03-15 06:10:40 -03001353static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001354{
1355 struct em28xx_fh *fh = priv;
1356 struct em28xx *dev = fh->dev;
1357 struct v4l2_format f;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001358
Hans Verkuil314527a2013-03-15 06:10:40 -03001359 if (norm == dev->norm)
Hans Verkuild8c95c02012-09-07 07:31:54 -03001360 return 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001361
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001362 if (dev->streaming_users > 0)
Hans Verkuild8c95c02012-09-07 07:31:54 -03001363 return -EBUSY;
Hans Verkuild8c95c02012-09-07 07:31:54 -03001364
Hans Verkuil314527a2013-03-15 06:10:40 -03001365 dev->norm = norm;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001366
1367 /* Adjusts width/height, if needed */
Hans Verkuild8c95c02012-09-07 07:31:54 -03001368 f.fmt.pix.width = 720;
Hans Verkuil314527a2013-03-15 06:10:40 -03001369 f.fmt.pix.height = (norm & V4L2_STD_525_60) ? 480 : 576;
Hans Verkuil78b526a2008-05-28 12:16:41 -03001370 vidioc_try_fmt_vid_cap(file, priv, &f);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001371
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001372 /* set new image size */
1373 dev->width = f.fmt.pix.width;
1374 dev->height = f.fmt.pix.height;
Frank Schaefer6b09a212013-02-10 16:05:12 -03001375 size_to_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001376
1377 em28xx_resolution_set(dev);
Frank Schaefer95d26082014-03-24 16:33:09 -03001378 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, core, s_std, dev->norm);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001379
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001380 return 0;
1381}
1382
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001383static int vidioc_g_parm(struct file *file, void *priv,
1384 struct v4l2_streamparm *p)
1385{
1386 struct em28xx_fh *fh = priv;
1387 struct em28xx *dev = fh->dev;
1388 int rc = 0;
1389
Hans Verkuil86ff7f12012-09-07 06:16:03 -03001390 p->parm.capture.readbuffers = EM28XX_MIN_BUF;
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001391 if (dev->board.is_webcam)
Frank Schaefer95d26082014-03-24 16:33:09 -03001392 rc = v4l2_device_call_until_err(&dev->v4l2->v4l2_dev, 0,
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001393 video, g_parm, p);
1394 else
1395 v4l2_video_std_frame_period(dev->norm,
1396 &p->parm.capture.timeperframe);
1397
1398 return rc;
1399}
1400
1401static int vidioc_s_parm(struct file *file, void *priv,
1402 struct v4l2_streamparm *p)
1403{
1404 struct em28xx_fh *fh = priv;
1405 struct em28xx *dev = fh->dev;
1406
Hans Verkuil86ff7f12012-09-07 06:16:03 -03001407 p->parm.capture.readbuffers = EM28XX_MIN_BUF;
Frank Schaefer95d26082014-03-24 16:33:09 -03001408 return v4l2_device_call_until_err(&dev->v4l2->v4l2_dev,
1409 0, video, s_parm, p);
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001410}
1411
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001412static const char *iname[] = {
1413 [EM28XX_VMUX_COMPOSITE1] = "Composite1",
1414 [EM28XX_VMUX_COMPOSITE2] = "Composite2",
1415 [EM28XX_VMUX_COMPOSITE3] = "Composite3",
1416 [EM28XX_VMUX_COMPOSITE4] = "Composite4",
1417 [EM28XX_VMUX_SVIDEO] = "S-Video",
1418 [EM28XX_VMUX_TELEVISION] = "Television",
1419 [EM28XX_VMUX_CABLE] = "Cable TV",
1420 [EM28XX_VMUX_DVB] = "DVB",
1421 [EM28XX_VMUX_DEBUG] = "for debug only",
1422};
1423
1424static int vidioc_enum_input(struct file *file, void *priv,
1425 struct v4l2_input *i)
1426{
1427 struct em28xx_fh *fh = priv;
1428 struct em28xx *dev = fh->dev;
1429 unsigned int n;
1430
1431 n = i->index;
1432 if (n >= MAX_EM28XX_INPUT)
1433 return -EINVAL;
1434 if (0 == INPUT(n)->type)
1435 return -EINVAL;
1436
1437 i->index = n;
1438 i->type = V4L2_INPUT_TYPE_CAMERA;
1439
1440 strcpy(i->name, iname[INPUT(n)->type]);
1441
1442 if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type) ||
1443 (EM28XX_VMUX_CABLE == INPUT(n)->type))
1444 i->type = V4L2_INPUT_TYPE_TUNER;
1445
Mauro Carvalho Chehab7d497f82007-11-11 14:15:34 -03001446 i->std = dev->vdev->tvnorms;
Hans Verkuild8c95c02012-09-07 07:31:54 -03001447 /* webcams do not have the STD API */
1448 if (dev->board.is_webcam)
1449 i->capabilities = 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001450
1451 return 0;
1452}
1453
1454static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1455{
1456 struct em28xx_fh *fh = priv;
1457 struct em28xx *dev = fh->dev;
1458
1459 *i = dev->ctl_input;
1460
1461 return 0;
1462}
1463
1464static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
1465{
1466 struct em28xx_fh *fh = priv;
1467 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001468
1469 if (i >= MAX_EM28XX_INPUT)
1470 return -EINVAL;
1471 if (0 == INPUT(i)->type)
1472 return -EINVAL;
1473
Ezequiel García96371fc2012-03-23 18:09:34 -03001474 video_mux(dev, i);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001475 return 0;
1476}
1477
1478static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
1479{
1480 struct em28xx_fh *fh = priv;
1481 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001482
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001483 switch (a->index) {
1484 case EM28XX_AMUX_VIDEO:
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001485 strcpy(a->name, "Television");
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001486 break;
1487 case EM28XX_AMUX_LINE_IN:
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001488 strcpy(a->name, "Line In");
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001489 break;
1490 case EM28XX_AMUX_VIDEO2:
1491 strcpy(a->name, "Television alt");
1492 break;
1493 case EM28XX_AMUX_PHONE:
1494 strcpy(a->name, "Phone");
1495 break;
1496 case EM28XX_AMUX_MIC:
1497 strcpy(a->name, "Mic");
1498 break;
1499 case EM28XX_AMUX_CD:
1500 strcpy(a->name, "CD");
1501 break;
1502 case EM28XX_AMUX_AUX:
1503 strcpy(a->name, "Aux");
1504 break;
1505 case EM28XX_AMUX_PCM_OUT:
1506 strcpy(a->name, "PCM");
1507 break;
1508 default:
1509 return -EINVAL;
1510 }
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001511
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001512 a->index = dev->ctl_ainput;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001513 a->capability = V4L2_AUDCAP_STEREO;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001514
1515 return 0;
1516}
1517
Hans Verkuil0e8025b92012-09-04 11:59:31 -03001518static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001519{
1520 struct em28xx_fh *fh = priv;
1521 struct em28xx *dev = fh->dev;
1522
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03001523 if (a->index >= MAX_EM28XX_INPUT)
1524 return -EINVAL;
1525 if (0 == INPUT(a->index)->type)
1526 return -EINVAL;
1527
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001528 dev->ctl_ainput = INPUT(a->index)->amux;
1529 dev->ctl_aoutput = INPUT(a->index)->aout;
Mauro Carvalho Chehabe879b8e2008-11-20 13:39:39 -03001530
1531 if (!dev->ctl_aoutput)
1532 dev->ctl_aoutput = EM28XX_AOUT_MASTER;
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001533
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001534 return 0;
1535}
1536
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001537static int vidioc_g_tuner(struct file *file, void *priv,
1538 struct v4l2_tuner *t)
1539{
1540 struct em28xx_fh *fh = priv;
1541 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001542
1543 if (0 != t->index)
1544 return -EINVAL;
1545
1546 strcpy(t->name, "Tuner");
1547
Frank Schaefer95d26082014-03-24 16:33:09 -03001548 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, g_tuner, t);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001549 return 0;
1550}
1551
1552static int vidioc_s_tuner(struct file *file, void *priv,
Hans Verkuil2f73c7c2013-03-15 06:10:06 -03001553 const struct v4l2_tuner *t)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001554{
1555 struct em28xx_fh *fh = priv;
1556 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001557
1558 if (0 != t->index)
1559 return -EINVAL;
1560
Frank Schaefer95d26082014-03-24 16:33:09 -03001561 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, s_tuner, t);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001562 return 0;
1563}
1564
1565static int vidioc_g_frequency(struct file *file, void *priv,
1566 struct v4l2_frequency *f)
1567{
1568 struct em28xx_fh *fh = priv;
1569 struct em28xx *dev = fh->dev;
1570
Hans Verkuil20deebf2012-09-06 10:07:25 -03001571 if (0 != f->tuner)
1572 return -EINVAL;
1573
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001574 f->frequency = dev->ctl_freq;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001575 return 0;
1576}
1577
1578static int vidioc_s_frequency(struct file *file, void *priv,
Hans Verkuilb530a442013-03-19 04:09:26 -03001579 const struct v4l2_frequency *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001580{
Frank Schaefer95d26082014-03-24 16:33:09 -03001581 struct v4l2_frequency new_freq = *f;
1582 struct em28xx_fh *fh = priv;
1583 struct em28xx *dev = fh->dev;
1584 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001585
1586 if (0 != f->tuner)
1587 return -EINVAL;
1588
Frank Schaefer95d26082014-03-24 16:33:09 -03001589 v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, s_frequency, f);
1590 v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, g_frequency, &new_freq);
Hans Verkuilb530a442013-03-19 04:09:26 -03001591 dev->ctl_freq = new_freq.frequency;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001592
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001593 return 0;
1594}
1595
Hans Verkuilcd634f12013-03-27 08:04:23 -03001596#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuil96b03d22013-04-06 06:16:58 -03001597static int vidioc_g_chip_info(struct file *file, void *priv,
1598 struct v4l2_dbg_chip_info *chip)
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001599{
1600 struct em28xx_fh *fh = priv;
1601 struct em28xx *dev = fh->dev;
1602
1603 if (chip->match.addr > 1)
1604 return -EINVAL;
1605 if (chip->match.addr == 1)
1606 strlcpy(chip->name, "ac97", sizeof(chip->name));
1607 else
Frank Schaefer95d26082014-03-24 16:33:09 -03001608 strlcpy(chip->name,
1609 dev->v4l2->v4l2_dev.name, sizeof(chip->name));
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001610 return 0;
1611}
1612
Frank Schaefer35deba32013-02-07 13:39:19 -03001613static int em28xx_reg_len(int reg)
1614{
1615 switch (reg) {
1616 case EM28XX_R40_AC97LSB:
1617 case EM28XX_R30_HSCALELOW:
1618 case EM28XX_R32_VSCALELOW:
1619 return 2;
1620 default:
1621 return 1;
1622 }
1623}
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001624
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001625static int vidioc_g_register(struct file *file, void *priv,
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001626 struct v4l2_dbg_register *reg)
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001627{
1628 struct em28xx_fh *fh = priv;
1629 struct em28xx *dev = fh->dev;
1630 int ret;
1631
Hans Verkuilabca2052013-05-29 06:59:35 -03001632 if (reg->match.addr > 1)
1633 return -EINVAL;
1634 if (reg->match.addr) {
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001635 ret = em28xx_read_ac97(dev, reg->reg);
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001636 if (ret < 0)
1637 return ret;
1638
1639 reg->val = ret;
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001640 reg->size = 1;
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001641 return 0;
1642 }
1643
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001644 /* Match host */
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001645 reg->size = em28xx_reg_len(reg->reg);
1646 if (reg->size == 1) {
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001647 ret = em28xx_read_reg(dev, reg->reg);
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001648
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001649 if (ret < 0)
1650 return ret;
1651
1652 reg->val = ret;
1653 } else {
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001654 __le16 val = 0;
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001655 ret = dev->em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001656 reg->reg, (char *)&val, 2);
1657 if (ret < 0)
1658 return ret;
1659
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001660 reg->val = le16_to_cpu(val);
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001661 }
1662
1663 return 0;
1664}
1665
1666static int vidioc_s_register(struct file *file, void *priv,
Hans Verkuil977ba3b2013-03-24 08:28:46 -03001667 const struct v4l2_dbg_register *reg)
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001668{
1669 struct em28xx_fh *fh = priv;
1670 struct em28xx *dev = fh->dev;
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001671 __le16 buf;
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001672
Hans Verkuilabca2052013-05-29 06:59:35 -03001673 if (reg->match.addr > 1)
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001674 return -EINVAL;
Hans Verkuilabca2052013-05-29 06:59:35 -03001675 if (reg->match.addr)
1676 return em28xx_write_ac97(dev, reg->reg, reg->val);
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001677
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001678 /* Match host */
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001679 buf = cpu_to_le16(reg->val);
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001680
Hans Verkuil0499a5a2010-09-26 07:34:45 -03001681 return em28xx_write_regs(dev, reg->reg, (char *)&buf,
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001682 em28xx_reg_len(reg->reg));
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001683}
1684#endif
1685
1686
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001687static int vidioc_querycap(struct file *file, void *priv,
1688 struct v4l2_capability *cap)
1689{
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001690 struct video_device *vdev = video_devdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001691 struct em28xx_fh *fh = priv;
1692 struct em28xx *dev = fh->dev;
1693
1694 strlcpy(cap->driver, "em28xx", sizeof(cap->driver));
1695 strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card));
Thierry MERLEcb977162009-01-20 18:01:33 -03001696 usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001697
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001698 if (vdev->vfl_type == VFL_TYPE_GRABBER)
1699 cap->device_caps = V4L2_CAP_READWRITE |
1700 V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1701 else if (vdev->vfl_type == VFL_TYPE_RADIO)
1702 cap->device_caps = V4L2_CAP_RADIO;
1703 else
Hans Verkuil1d179ee2012-09-07 08:45:10 -03001704 cap->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE;
Devin Heitmueller04146142009-09-11 00:08:44 -03001705
Mauro Carvalho Chehab6c428b52009-08-04 19:52:37 -03001706 if (dev->audio_mode.has_audio)
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001707 cap->device_caps |= V4L2_CAP_AUDIO;
Mauro Carvalho Chehab6c428b52009-08-04 19:52:37 -03001708
Mauro Carvalho Chehabed086312008-01-24 06:59:20 -03001709 if (dev->tuner_type != TUNER_ABSENT)
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001710 cap->device_caps |= V4L2_CAP_TUNER;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001711
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001712 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS |
1713 V4L2_CAP_READWRITE | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1714 if (dev->vbi_dev)
Hans Verkuil1d179ee2012-09-07 08:45:10 -03001715 cap->capabilities |= V4L2_CAP_VBI_CAPTURE;
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001716 if (dev->radio_dev)
1717 cap->capabilities |= V4L2_CAP_RADIO;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001718 return 0;
1719}
1720
Hans Verkuil78b526a2008-05-28 12:16:41 -03001721static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001722 struct v4l2_fmtdesc *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001723{
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001724 if (unlikely(f->index >= ARRAY_SIZE(format)))
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001725 return -EINVAL;
1726
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001727 strlcpy(f->description, format[f->index].name, sizeof(f->description));
1728 f->pixelformat = format[f->index].fourcc;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001729
1730 return 0;
1731}
1732
Mauro Carvalho Chehab1c5c50682011-10-16 13:52:43 -02001733static int vidioc_enum_framesizes(struct file *file, void *priv,
1734 struct v4l2_frmsizeenum *fsize)
1735{
1736 struct em28xx_fh *fh = priv;
1737 struct em28xx *dev = fh->dev;
1738 struct em28xx_fmt *fmt;
1739 unsigned int maxw = norm_maxw(dev);
1740 unsigned int maxh = norm_maxh(dev);
1741
1742 fmt = format_by_fourcc(fsize->pixel_format);
1743 if (!fmt) {
1744 em28xx_videodbg("Fourcc format (%08x) invalid.\n",
1745 fsize->pixel_format);
1746 return -EINVAL;
1747 }
1748
1749 if (dev->board.is_em2800) {
1750 if (fsize->index > 1)
1751 return -EINVAL;
1752 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
1753 fsize->discrete.width = maxw / (1 + fsize->index);
1754 fsize->discrete.height = maxh / (1 + fsize->index);
1755 return 0;
1756 }
1757
1758 if (fsize->index != 0)
1759 return -EINVAL;
1760
1761 /* Report a continuous range */
1762 fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
Frank Schaefer6c3598e2013-02-10 16:05:14 -03001763 scale_to_size(dev, EM28XX_HVSCALE_MAX, EM28XX_HVSCALE_MAX,
1764 &fsize->stepwise.min_width, &fsize->stepwise.min_height);
1765 if (fsize->stepwise.min_width < 48)
1766 fsize->stepwise.min_width = 48;
1767 if (fsize->stepwise.min_height < 38)
1768 fsize->stepwise.min_height = 38;
Mauro Carvalho Chehab1c5c50682011-10-16 13:52:43 -02001769 fsize->stepwise.max_width = maxw;
1770 fsize->stepwise.max_height = maxh;
1771 fsize->stepwise.step_width = 1;
1772 fsize->stepwise.step_height = 1;
1773 return 0;
1774}
1775
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001776/* RAW VBI ioctls */
1777
1778static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
1779 struct v4l2_format *format)
1780{
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001781 struct em28xx_fh *fh = priv;
1782 struct em28xx *dev = fh->dev;
1783
1784 format->fmt.vbi.samples_per_line = dev->vbi_width;
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001785 format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
1786 format->fmt.vbi.offset = 0;
1787 format->fmt.vbi.flags = 0;
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001788 format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
1789 format->fmt.vbi.count[0] = dev->vbi_height;
1790 format->fmt.vbi.count[1] = dev->vbi_height;
Hans Verkuil2a221d32012-09-07 08:51:32 -03001791 memset(format->fmt.vbi.reserved, 0, sizeof(format->fmt.vbi.reserved));
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001792
1793 /* Varies by video standard (NTSC, PAL, etc.) */
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001794 if (dev->norm & V4L2_STD_525_60) {
1795 /* NTSC */
1796 format->fmt.vbi.start[0] = 10;
1797 format->fmt.vbi.start[1] = 273;
1798 } else if (dev->norm & V4L2_STD_625_50) {
1799 /* PAL */
1800 format->fmt.vbi.start[0] = 6;
1801 format->fmt.vbi.start[1] = 318;
1802 }
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001803
1804 return 0;
1805}
1806
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001807/* ----------------------------------------------------------- */
1808/* RADIO ESPECIFIC IOCTLS */
1809/* ----------------------------------------------------------- */
1810
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001811static int radio_g_tuner(struct file *file, void *priv,
1812 struct v4l2_tuner *t)
1813{
1814 struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;
1815
1816 if (unlikely(t->index > 0))
1817 return -EINVAL;
1818
1819 strcpy(t->name, "Radio");
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001820
Frank Schaefer95d26082014-03-24 16:33:09 -03001821 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, g_tuner, t);
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001822
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001823 return 0;
1824}
1825
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001826static int radio_s_tuner(struct file *file, void *priv,
Hans Verkuil2f73c7c2013-03-15 06:10:06 -03001827 const struct v4l2_tuner *t)
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001828{
1829 struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;
1830
1831 if (0 != t->index)
1832 return -EINVAL;
1833
Frank Schaefer95d26082014-03-24 16:33:09 -03001834 v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, s_tuner, t);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001835
1836 return 0;
1837}
1838
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001839/*
Frank Schaefer95d26082014-03-24 16:33:09 -03001840 * em28xx_free_v4l2() - Free struct em28xx_v4l2
1841 *
1842 * @ref: struct kref for struct em28xx_v4l2
1843 *
1844 * Called when all users of struct em28xx_v4l2 are gone
1845 */
1846void em28xx_free_v4l2(struct kref *ref)
1847{
1848 struct em28xx_v4l2 *v4l2 = container_of(ref, struct em28xx_v4l2, ref);
1849
Frank Schaeferabc13082014-03-24 16:33:10 -03001850 v4l2->dev->v4l2 = NULL;
Frank Schaefer95d26082014-03-24 16:33:09 -03001851 kfree(v4l2);
1852}
1853
1854/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08001855 * em28xx_v4l2_open()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001856 * inits the device and starts isoc transfer
1857 */
Hans Verkuilbec43662008-12-30 06:58:20 -03001858static int em28xx_v4l2_open(struct file *filp)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001859{
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001860 struct video_device *vdev = video_devdata(filp);
1861 struct em28xx *dev = video_drvdata(filp);
Frank Schaefer95d26082014-03-24 16:33:09 -03001862 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001863 enum v4l2_buf_type fh_type = 0;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001864 struct em28xx_fh *fh;
Markus Rechberger9c755412005-11-08 21:37:52 -08001865
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001866 switch (vdev->vfl_type) {
1867 case VFL_TYPE_GRABBER:
1868 fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1869 break;
1870 case VFL_TYPE_VBI:
1871 fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
1872 break;
Frank Schaefer4e170242014-01-12 13:24:18 -03001873 case VFL_TYPE_RADIO:
1874 break;
1875 default:
1876 return -EINVAL;
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001877 }
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03001878
Laurent Pinchart50462eb2009-12-10 11:47:13 -02001879 em28xx_videodbg("open dev=%s type=%s users=%d\n",
1880 video_device_node_name(vdev), v4l2_type_names[fh_type],
1881 dev->users);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001882
Hans Verkuil876cb142012-06-23 08:12:47 -03001883 if (mutex_lock_interruptible(&dev->lock))
1884 return -ERESTARTSYS;
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001885 fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001886 if (!fh) {
1887 em28xx_errdev("em28xx-video.c: Out of memory?!\n");
Hans Verkuil876cb142012-06-23 08:12:47 -03001888 mutex_unlock(&dev->lock);
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001889 return -ENOMEM;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001890 }
Hans Verkuil69a61642012-09-07 05:52:40 -03001891 v4l2_fh_init(&fh->fh, vdev);
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001892 fh->dev = dev;
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001893 fh->type = fh_type;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001894 filp->private_data = fh;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001895
Frank Schaefer4e170242014-01-12 13:24:18 -03001896 if (dev->users == 0) {
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001897 em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001898
Frank Schaefer4e170242014-01-12 13:24:18 -03001899 if (vdev->vfl_type != VFL_TYPE_RADIO)
1900 em28xx_resolution_set(dev);
1901
1902 /*
1903 * Needed, since GPIO might have disabled power
1904 * of some i2c devices
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001905 */
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03001906 em28xx_wake_i2c(dev);
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02001907 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001908
1909 if (vdev->vfl_type == VFL_TYPE_RADIO) {
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001910 em28xx_videodbg("video_open: setting radio device\n");
Frank Schaefer95d26082014-03-24 16:33:09 -03001911 v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, s_radio);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001912 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001913
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03001914 kref_get(&dev->ref);
Frank Schaefer95d26082014-03-24 16:33:09 -03001915 kref_get(&v4l2->ref);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001916 dev->users++;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001917
Hans Verkuil876cb142012-06-23 08:12:47 -03001918 mutex_unlock(&dev->lock);
Hans Verkuil69a61642012-09-07 05:52:40 -03001919 v4l2_fh_add(&fh->fh);
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001920
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001921 return 0;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001922}
1923
1924/*
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001925 * em28xx_v4l2_fini()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001926 * unregisters the v4l2,i2c and usb devices
1927 * called when the device gets disconected or at module unload
1928*/
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001929static int em28xx_v4l2_fini(struct em28xx *dev)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001930{
Frank Schaefer95d26082014-03-24 16:33:09 -03001931 struct em28xx_v4l2 *v4l2 = dev->v4l2;
1932
Mauro Carvalho Chehab822b8de2014-01-06 05:27:47 -03001933 if (dev->is_audio_only) {
1934 /* Shouldn't initialize IR for this interface */
1935 return 0;
1936 }
1937
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001938 if (!dev->has_video) {
1939 /* This device does not support the v4l2 extension */
1940 return 0;
1941 }
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02001942
Frank Schaefer95d26082014-03-24 16:33:09 -03001943 if (v4l2 == NULL)
1944 return 0;
1945
Mauro Carvalho Chehabaa929ad2014-01-12 19:22:07 -03001946 em28xx_info("Closing video extension");
1947
Mauro Carvalho Chehabebbfbc22014-01-13 02:53:44 -03001948 mutex_lock(&dev->lock);
1949
Frank Schaefer95d26082014-03-24 16:33:09 -03001950 v4l2_device_disconnect(&v4l2->v4l2_dev);
Frank Schaefer5ad10de2014-01-12 13:24:21 -03001951
Frank Schaefer23e86422014-01-12 13:24:20 -03001952 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
1953
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001954 if (dev->radio_dev) {
Frank Schaefere8470222014-01-12 13:24:25 -03001955 em28xx_info("V4L2 device %s deregistered\n",
1956 video_device_node_name(dev->radio_dev));
1957 video_unregister_device(dev->radio_dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001958 }
1959 if (dev->vbi_dev) {
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001960 em28xx_info("V4L2 device %s deregistered\n",
1961 video_device_node_name(dev->vbi_dev));
Frank Schaefere8470222014-01-12 13:24:25 -03001962 video_unregister_device(dev->vbi_dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001963 }
1964 if (dev->vdev) {
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001965 em28xx_info("V4L2 device %s deregistered\n",
1966 video_device_node_name(dev->vdev));
Frank Schaefere8470222014-01-12 13:24:25 -03001967 video_unregister_device(dev->vdev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001968 }
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001969
Frank Schaeferabc13082014-03-24 16:33:10 -03001970 v4l2_ctrl_handler_free(&v4l2->ctrl_handler);
Frank Schaefer95d26082014-03-24 16:33:09 -03001971 v4l2_device_unregister(&v4l2->v4l2_dev);
Frank Schaefer103f18a2014-01-17 14:45:30 -03001972
Frank Schaefer25dd1652014-01-12 13:24:23 -03001973 if (dev->clk) {
1974 v4l2_clk_unregister_fixed(dev->clk);
1975 dev->clk = NULL;
1976 }
1977
Frank Schaefer95d26082014-03-24 16:33:09 -03001978 kref_put(&v4l2->ref, em28xx_free_v4l2);
1979
Mauro Carvalho Chehabebbfbc22014-01-13 02:53:44 -03001980 mutex_unlock(&dev->lock);
Frank Schaefer95d26082014-03-24 16:33:09 -03001981
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03001982 kref_put(&dev->ref, em28xx_free_device);
Frank Schaefer5ad10de2014-01-12 13:24:21 -03001983
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001984 return 0;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001985}
1986
Shuah Khana61f6812014-02-21 21:50:17 -03001987static int em28xx_v4l2_suspend(struct em28xx *dev)
1988{
1989 if (dev->is_audio_only)
1990 return 0;
1991
1992 if (!dev->has_video)
1993 return 0;
1994
1995 em28xx_info("Suspending video extension");
1996 em28xx_stop_urbs(dev);
1997 return 0;
1998}
1999
2000static int em28xx_v4l2_resume(struct em28xx *dev)
2001{
2002 if (dev->is_audio_only)
2003 return 0;
2004
2005 if (!dev->has_video)
2006 return 0;
2007
2008 em28xx_info("Resuming video extension");
2009 /* what do we do here */
2010 return 0;
2011}
2012
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002013/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002014 * em28xx_v4l2_close()
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03002015 * stops streaming and deallocates all resources allocated by the v4l2
2016 * calls and ioctls
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002017 */
Hans Verkuilbec43662008-12-30 06:58:20 -03002018static int em28xx_v4l2_close(struct file *filp)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002019{
Frank Schaefer95d26082014-03-24 16:33:09 -03002020 struct em28xx_fh *fh = filp->private_data;
2021 struct em28xx *dev = fh->dev;
2022 struct em28xx_v4l2 *v4l2 = dev->v4l2;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03002023 int errCode;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002024
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08002025 em28xx_videodbg("users=%d\n", dev->users);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002026
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002027 vb2_fop_release(filp);
Ricardo Ribalda98c24dcd2013-11-06 05:39:35 -03002028 mutex_lock(&dev->lock);
Devin Heitmueller8c873d32009-09-03 00:23:27 -03002029
Devin Heitmuellere3ba4d32009-09-15 00:18:06 -03002030 if (dev->users == 1) {
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002031 /* No sense to try to write to the device */
2032 if (dev->disconnected)
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002033 goto exit;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03002034
Mauro Carvalho Chehabeb6c9632008-12-05 10:39:12 -03002035 /* Save some power by putting tuner to sleep */
Frank Schaefer95d26082014-03-24 16:33:09 -03002036 v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_power, 0);
Mauro Carvalho Chehabeb6c9632008-12-05 10:39:12 -03002037
Aidan Thorntond7aa8022008-04-13 14:38:47 -03002038 /* do this before setting alternate! */
Mauro Carvalho Chehab2fe3e2e2008-11-27 09:10:40 -03002039 em28xx_set_mode(dev, EM28XX_SUSPEND);
Aidan Thorntond7aa8022008-04-13 14:38:47 -03002040
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03002041 /* set alternate 0 */
2042 dev->alt = 0;
2043 em28xx_videodbg("setting alternate 0\n");
2044 errCode = usb_set_interface(dev->udev, 0, 0);
2045 if (errCode < 0) {
2046 em28xx_errdev("cannot change alternate number to "
2047 "0 (error=%i)\n", errCode);
2048 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002049 }
Devin Heitmueller28abf0832009-09-01 01:54:54 -03002050
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002051exit:
Frank Schaefer95d26082014-03-24 16:33:09 -03002052 kref_put(&v4l2->ref, em28xx_free_v4l2);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002053 dev->users--;
Hans Verkuil876cb142012-06-23 08:12:47 -03002054 mutex_unlock(&dev->lock);
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002055 kref_put(&dev->ref, em28xx_free_device);
2056
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002057 return 0;
2058}
2059
Frank Schaefere8470222014-01-12 13:24:25 -03002060/*
2061 * em28xx_videodevice_release()
2062 * called when the last user of the video device exits and frees the memeory
2063 */
2064static void em28xx_videodevice_release(struct video_device *vdev)
2065{
2066 struct em28xx *dev = video_get_drvdata(vdev);
2067
2068 video_device_release(vdev);
2069 if (vdev == dev->vdev)
2070 dev->vdev = NULL;
2071 else if (vdev == dev->vbi_dev)
2072 dev->vbi_dev = NULL;
2073 else if (vdev == dev->radio_dev)
2074 dev->radio_dev = NULL;
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 Chehab1c5c50682011-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,
2133 .release = em28xx_videodevice_release,
2134 .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,
2162 .release = em28xx_videodevice_release,
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
Adrian Bunk532fe652008-01-28 22:10:48 -03002185static struct video_device *em28xx_vdev_init(struct em28xx *dev,
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -03002186 const struct video_device *template,
2187 const char *type_name)
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002188{
2189 struct video_device *vfd;
2190
2191 vfd = video_device_alloc();
2192 if (NULL == vfd)
2193 return NULL;
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03002194
2195 *vfd = *template;
Frank Schaefer95d26082014-03-24 16:33:09 -03002196 vfd->v4l2_dev = &dev->v4l2->v4l2_dev;
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03002197 vfd->debug = video_debug;
Hans Verkuil0499a5a2010-09-26 07:34:45 -03002198 vfd->lock = &dev->lock;
Hans Verkuil69a61642012-09-07 05:52:40 -03002199 set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
Hans Verkuild8c95c02012-09-07 07:31:54 -03002200 if (dev->board.is_webcam)
2201 vfd->tvnorms = 0;
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002202
2203 snprintf(vfd->name, sizeof(vfd->name), "%s %s",
2204 dev->name, type_name);
2205
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02002206 video_set_drvdata(vfd, dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002207 return vfd;
2208}
2209
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002210static void em28xx_tuner_setup(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002211{
Frank Schaefer95d26082014-03-24 16:33:09 -03002212 struct v4l2_device *v4l2_dev = &dev->v4l2->v4l2_dev;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002213 struct tuner_setup tun_setup;
2214 struct v4l2_frequency f;
2215
2216 if (dev->tuner_type == TUNER_ABSENT)
2217 return;
2218
2219 memset(&tun_setup, 0, sizeof(tun_setup));
2220
2221 tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
2222 tun_setup.tuner_callback = em28xx_tuner_callback;
2223
2224 if (dev->board.radio.type) {
2225 tun_setup.type = dev->board.radio.type;
2226 tun_setup.addr = dev->board.radio_addr;
2227
Frank Schaefer95d26082014-03-24 16:33:09 -03002228 v4l2_device_call_all(v4l2_dev,
2229 0, tuner, s_type_addr, &tun_setup);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002230 }
2231
2232 if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type)) {
2233 tun_setup.type = dev->tuner_type;
2234 tun_setup.addr = dev->tuner_addr;
2235
Frank Schaefer95d26082014-03-24 16:33:09 -03002236 v4l2_device_call_all(v4l2_dev,
2237 0, tuner, s_type_addr, &tun_setup);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002238 }
2239
2240 if (dev->tda9887_conf) {
2241 struct v4l2_priv_tun_config tda9887_cfg;
2242
2243 tda9887_cfg.tuner = TUNER_TDA9887;
2244 tda9887_cfg.priv = &dev->tda9887_conf;
2245
Frank Schaefer95d26082014-03-24 16:33:09 -03002246 v4l2_device_call_all(v4l2_dev,
2247 0, tuner, s_config, &tda9887_cfg);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002248 }
2249
2250 if (dev->tuner_type == TUNER_XC2028) {
2251 struct v4l2_priv_tun_config xc2028_cfg;
2252 struct xc2028_ctrl ctl;
2253
2254 memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
2255 memset(&ctl, 0, sizeof(ctl));
2256
2257 em28xx_setup_xc3028(dev, &ctl);
2258
2259 xc2028_cfg.tuner = TUNER_XC2028;
2260 xc2028_cfg.priv = &ctl;
2261
Frank Schaefer95d26082014-03-24 16:33:09 -03002262 v4l2_device_call_all(v4l2_dev, 0, tuner, s_config, &xc2028_cfg);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002263 }
2264
2265 /* configure tuner */
2266 f.tuner = 0;
2267 f.type = V4L2_TUNER_ANALOG_TV;
2268 f.frequency = 9076; /* just a magic number */
2269 dev->ctl_freq = f.frequency;
Frank Schaefer95d26082014-03-24 16:33:09 -03002270 v4l2_device_call_all(v4l2_dev, 0, tuner, s_frequency, &f);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002271}
2272
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002273static int em28xx_v4l2_init(struct em28xx *dev)
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002274{
Hans Verkuil081b9452012-09-07 05:43:59 -03002275 u8 val;
Mauro Carvalho Chehab2e5ef2d2008-12-28 22:26:36 -03002276 int ret;
Sascha Sommer1020d132012-01-08 16:54:28 -03002277 unsigned int maxw;
Frank Schaeferabc13082014-03-24 16:33:10 -03002278 struct v4l2_ctrl_handler *hdl;
Frank Schaefer95d26082014-03-24 16:33:09 -03002279 struct em28xx_v4l2 *v4l2;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002280
Mauro Carvalho Chehab822b8de2014-01-06 05:27:47 -03002281 if (dev->is_audio_only) {
2282 /* Shouldn't initialize IR for this interface */
2283 return 0;
2284 }
2285
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002286 if (!dev->has_video) {
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002287 /* This device does not support the v4l2 extension */
2288 return 0;
2289 }
Mauro Carvalho Chehab2e5ef2d2008-12-28 22:26:36 -03002290
Mauro Carvalho Chehab96346142013-12-26 12:41:03 -03002291 em28xx_info("Registering V4L2 extension\n");
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002292
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002293 mutex_lock(&dev->lock);
2294
Frank Schaefer95d26082014-03-24 16:33:09 -03002295 v4l2 = kzalloc(sizeof(struct em28xx_v4l2), GFP_KERNEL);
2296 if (v4l2 == NULL) {
2297 em28xx_info("em28xx_v4l: memory allocation failed\n");
2298 mutex_unlock(&dev->lock);
2299 return -ENOMEM;
2300 }
2301 kref_init(&v4l2->ref);
Frank Schaeferabc13082014-03-24 16:33:10 -03002302 v4l2->dev = dev;
Frank Schaefer95d26082014-03-24 16:33:09 -03002303 dev->v4l2 = v4l2;
2304
2305 ret = v4l2_device_register(&dev->udev->dev, &v4l2->v4l2_dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002306 if (ret < 0) {
2307 em28xx_errdev("Call to v4l2_device_register() failed!\n");
2308 goto err;
2309 }
2310
Frank Schaeferabc13082014-03-24 16:33:10 -03002311 hdl = &v4l2->ctrl_handler;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002312 v4l2_ctrl_handler_init(hdl, 8);
Frank Schaefer95d26082014-03-24 16:33:09 -03002313 v4l2->v4l2_dev.ctrl_handler = hdl;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002314
2315 /*
2316 * Default format, used for tvp5150 or saa711x output formats
2317 */
2318 dev->vinmode = 0x10;
2319 dev->vinctl = EM28XX_VINCTRL_INTERLACED |
2320 EM28XX_VINCTRL_CCIR656_ENABLE;
2321
2322 /* request some modules */
2323
2324 if (dev->board.has_msp34xx)
Frank Schaefer95d26082014-03-24 16:33:09 -03002325 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2326 &dev->i2c_adap[dev->def_i2c_bus],
2327 "msp3400", 0, msp3400_addrs);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002328
2329 if (dev->board.decoder == EM28XX_SAA711X)
Frank Schaefer95d26082014-03-24 16:33:09 -03002330 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2331 &dev->i2c_adap[dev->def_i2c_bus],
2332 "saa7115_auto", 0, saa711x_addrs);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002333
2334 if (dev->board.decoder == EM28XX_TVP5150)
Frank Schaefer95d26082014-03-24 16:33:09 -03002335 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2336 &dev->i2c_adap[dev->def_i2c_bus],
2337 "tvp5150", 0, tvp5150_addrs);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002338
2339 if (dev->board.adecoder == EM28XX_TVAUDIO)
Frank Schaefer95d26082014-03-24 16:33:09 -03002340 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2341 &dev->i2c_adap[dev->def_i2c_bus],
2342 "tvaudio", dev->board.tvaudio_addr, NULL);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002343
2344 /* Initialize tuner and camera */
2345
2346 if (dev->board.tuner_type != TUNER_ABSENT) {
2347 int has_demod = (dev->tda9887_conf & TDA9887_PRESENT);
2348
2349 if (dev->board.radio.type)
Frank Schaefer95d26082014-03-24 16:33:09 -03002350 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2351 &dev->i2c_adap[dev->def_i2c_bus],
2352 "tuner", dev->board.radio_addr, NULL);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002353
2354 if (has_demod)
Frank Schaefer95d26082014-03-24 16:33:09 -03002355 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002356 &dev->i2c_adap[dev->def_i2c_bus], "tuner",
2357 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
2358 if (dev->tuner_addr == 0) {
2359 enum v4l2_i2c_tuner_type type =
2360 has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV;
2361 struct v4l2_subdev *sd;
2362
Frank Schaefer95d26082014-03-24 16:33:09 -03002363 sd = v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002364 &dev->i2c_adap[dev->def_i2c_bus], "tuner",
2365 0, v4l2_i2c_tuner_addrs(type));
2366
2367 if (sd)
2368 dev->tuner_addr = v4l2_i2c_subdev_addr(sd);
2369 } else {
Frank Schaefer95d26082014-03-24 16:33:09 -03002370 v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
2371 &dev->i2c_adap[dev->def_i2c_bus],
2372 "tuner", dev->tuner_addr, NULL);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002373 }
2374 }
2375
2376 em28xx_tuner_setup(dev);
Frank Schaeferd86bc652014-01-17 14:45:32 -03002377 if (dev->em28xx_sensor != EM28XX_NOSENSOR)
2378 em28xx_init_camera(dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002379
2380 /* Configure audio */
2381 ret = em28xx_audio_setup(dev);
2382 if (ret < 0) {
2383 em28xx_errdev("%s: Error while setting audio - error [%d]!\n",
2384 __func__, ret);
2385 goto unregister_dev;
2386 }
2387 if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
2388 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
2389 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
2390 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
2391 V4L2_CID_AUDIO_VOLUME, 0, 0x1f, 1, 0x1f);
2392 } else {
2393 /* install the em28xx notify callback */
2394 v4l2_ctrl_notify(v4l2_ctrl_find(hdl, V4L2_CID_AUDIO_MUTE),
2395 em28xx_ctrl_notify, dev);
2396 v4l2_ctrl_notify(v4l2_ctrl_find(hdl, V4L2_CID_AUDIO_VOLUME),
2397 em28xx_ctrl_notify, dev);
2398 }
2399
2400 /* wake i2c devices */
2401 em28xx_wake_i2c(dev);
2402
2403 /* init video dma queues */
2404 INIT_LIST_HEAD(&dev->vidq.active);
2405 INIT_LIST_HEAD(&dev->vbiq.active);
2406
2407 if (dev->board.has_msp34xx) {
2408 /* Send a reset to other chips via gpio */
2409 ret = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xf7);
2410 if (ret < 0) {
2411 em28xx_errdev("%s: em28xx_write_reg - msp34xx(1) failed! error [%d]\n",
2412 __func__, ret);
2413 goto unregister_dev;
2414 }
2415 msleep(3);
2416
2417 ret = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xff);
2418 if (ret < 0) {
2419 em28xx_errdev("%s: em28xx_write_reg - msp34xx(2) failed! error [%d]\n",
2420 __func__, ret);
2421 goto unregister_dev;
2422 }
2423 msleep(3);
2424 }
2425
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002426 /* set default norm */
Hans Verkuild8c95c02012-09-07 07:31:54 -03002427 dev->norm = V4L2_STD_PAL;
Frank Schaefer95d26082014-03-24 16:33:09 -03002428 v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_std, dev->norm);
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002429 dev->interlaced = EM28XX_INTERLACED_DEFAULT;
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002430
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002431 /* Analog specific initialization */
2432 dev->format = &format[0];
Sascha Sommer1020d132012-01-08 16:54:28 -03002433
2434 maxw = norm_maxw(dev);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002435 /* MaxPacketSize for em2800 is too small to capture at full resolution
2436 * use half of maxw as the scaler can only scale to 50% */
2437 if (dev->board.is_em2800)
2438 maxw /= 2;
Sascha Sommer1020d132012-01-08 16:54:28 -03002439
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03002440 em28xx_set_video_format(dev, format[0].fourcc,
Sascha Sommer1020d132012-01-08 16:54:28 -03002441 maxw, norm_maxh(dev));
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03002442
Ezequiel García96371fc2012-03-23 18:09:34 -03002443 video_mux(dev, 0);
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002444
2445 /* Audio defaults */
2446 dev->mute = 1;
2447 dev->volume = 0x1f;
2448
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002449/* em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -03002450 val = (u8)em28xx_read_reg(dev, EM28XX_R0F_XCLK);
2451 em28xx_write_reg(dev, EM28XX_R0F_XCLK,
2452 (EM28XX_XCLK_AUDIO_UNMUTE | val));
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002453
2454 em28xx_set_outfmt(dev);
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002455
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002456 /* Add image controls */
2457 /* NOTE: at this point, the subdevices are already registered, so bridge
2458 * controls are only added/enabled when no subdevice provides them */
Frank Schaeferad298052014-03-24 16:33:08 -03002459 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_CONTRAST))
2460 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002461 V4L2_CID_CONTRAST,
2462 0, 0x1f, 1, CONTRAST_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002463 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_BRIGHTNESS))
2464 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002465 V4L2_CID_BRIGHTNESS,
2466 -0x80, 0x7f, 1, BRIGHTNESS_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002467 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_SATURATION))
2468 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002469 V4L2_CID_SATURATION,
2470 0, 0x1f, 1, SATURATION_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002471 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_BLUE_BALANCE))
2472 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002473 V4L2_CID_BLUE_BALANCE,
2474 -0x30, 0x30, 1, BLUE_BALANCE_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002475 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_RED_BALANCE))
2476 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002477 V4L2_CID_RED_BALANCE,
2478 -0x30, 0x30, 1, RED_BALANCE_DEFAULT);
Frank Schaeferad298052014-03-24 16:33:08 -03002479 if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_SHARPNESS))
2480 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002481 V4L2_CID_SHARPNESS,
2482 0, 0x0f, 1, SHARPNESS_DEFAULT);
2483
2484 /* Reset image controls */
2485 em28xx_colorlevels_set_default(dev);
Frank Schaeferad298052014-03-24 16:33:08 -03002486 v4l2_ctrl_handler_setup(hdl);
2487 ret = hdl->error;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002488 if (ret)
2489 goto unregister_dev;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002490
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002491 /* allocate and fill video video_device struct */
2492 dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video");
2493 if (!dev->vdev) {
2494 em28xx_errdev("cannot allocate video_device.\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002495 ret = -ENODEV;
2496 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002497 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002498 dev->vdev->queue = &dev->vb_vidq;
2499 dev->vdev->queue->lock = &dev->vb_queue_lock;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002500
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002501 /* disable inapplicable ioctls */
2502 if (dev->board.is_webcam) {
2503 v4l2_disable_ioctl(dev->vdev, VIDIOC_QUERYSTD);
2504 v4l2_disable_ioctl(dev->vdev, VIDIOC_G_STD);
2505 v4l2_disable_ioctl(dev->vdev, VIDIOC_S_STD);
Frank Schaefer3bc85cc2013-02-07 13:39:12 -03002506 } else {
2507 v4l2_disable_ioctl(dev->vdev, VIDIOC_S_PARM);
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002508 }
Frank Schaefer66df67b2013-02-07 13:39:10 -03002509 if (dev->tuner_type == TUNER_ABSENT) {
2510 v4l2_disable_ioctl(dev->vdev, VIDIOC_G_TUNER);
2511 v4l2_disable_ioctl(dev->vdev, VIDIOC_S_TUNER);
2512 v4l2_disable_ioctl(dev->vdev, VIDIOC_G_FREQUENCY);
2513 v4l2_disable_ioctl(dev->vdev, VIDIOC_S_FREQUENCY);
2514 }
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002515 if (!dev->audio_mode.has_audio) {
2516 v4l2_disable_ioctl(dev->vdev, VIDIOC_G_AUDIO);
2517 v4l2_disable_ioctl(dev->vdev, VIDIOC_S_AUDIO);
2518 }
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002519
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002520 /* register v4l2 video video_device */
2521 ret = video_register_device(dev->vdev, VFL_TYPE_GRABBER,
2522 video_nr[dev->devno]);
2523 if (ret) {
2524 em28xx_errdev("unable to register video device (error=%i).\n",
2525 ret);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002526 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002527 }
2528
2529 /* Allocate and fill vbi video_device struct */
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002530 if (em28xx_vbi_supported(dev) == 1) {
2531 dev->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template,
2532 "vbi");
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002533
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002534 dev->vbi_dev->queue = &dev->vb_vbiq;
2535 dev->vbi_dev->queue->lock = &dev->vb_vbi_queue_lock;
2536
Frank Schaefer66df67b2013-02-07 13:39:10 -03002537 /* disable inapplicable ioctls */
Frank Schaefer83c8bcc2013-02-07 13:39:13 -03002538 v4l2_disable_ioctl(dev->vdev, VIDIOC_S_PARM);
Frank Schaefer66df67b2013-02-07 13:39:10 -03002539 if (dev->tuner_type == TUNER_ABSENT) {
2540 v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_G_TUNER);
2541 v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_S_TUNER);
2542 v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_G_FREQUENCY);
2543 v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_S_FREQUENCY);
2544 }
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002545 if (!dev->audio_mode.has_audio) {
2546 v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_G_AUDIO);
2547 v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_S_AUDIO);
2548 }
Frank Schaefer66df67b2013-02-07 13:39:10 -03002549
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002550 /* register v4l2 vbi video_device */
2551 ret = video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
2552 vbi_nr[dev->devno]);
2553 if (ret < 0) {
2554 em28xx_errdev("unable to register vbi device\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002555 goto unregister_dev;
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002556 }
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002557 }
2558
2559 if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) {
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -03002560 dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template,
2561 "radio");
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002562 if (!dev->radio_dev) {
2563 em28xx_errdev("cannot allocate video_device.\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002564 ret = -ENODEV;
2565 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002566 }
2567 ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO,
2568 radio_nr[dev->devno]);
2569 if (ret < 0) {
2570 em28xx_errdev("can't register radio device\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002571 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002572 }
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002573 em28xx_info("Registered radio device as %s\n",
2574 video_device_node_name(dev->radio_dev));
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002575 }
2576
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002577 em28xx_info("V4L2 video device registered as %s\n",
2578 video_device_node_name(dev->vdev));
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002579
2580 if (dev->vbi_dev)
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002581 em28xx_info("V4L2 VBI device registered as %s\n",
2582 video_device_node_name(dev->vbi_dev));
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002583
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002584 /* Save some power by putting tuner to sleep */
Frank Schaefer95d26082014-03-24 16:33:09 -03002585 v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_power, 0);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002586
2587 /* initialize videobuf2 stuff */
2588 em28xx_vb2_setup(dev);
2589
Mauro Carvalho Chehab96346142013-12-26 12:41:03 -03002590 em28xx_info("V4L2 extension successfully initialized\n");
2591
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002592 kref_get(&dev->ref);
2593
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002594 mutex_unlock(&dev->lock);
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002595 return 0;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002596
2597unregister_dev:
Frank Schaeferabc13082014-03-24 16:33:10 -03002598 v4l2_ctrl_handler_free(&v4l2->ctrl_handler);
Frank Schaefer95d26082014-03-24 16:33:09 -03002599 v4l2_device_unregister(&v4l2->v4l2_dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002600err:
Frank Schaefer95d26082014-03-24 16:33:09 -03002601 dev->v4l2 = NULL;
2602 kref_put(&v4l2->ref, em28xx_free_v4l2);
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002603 mutex_unlock(&dev->lock);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002604 return ret;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002605}
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002606
2607static struct em28xx_ops v4l2_ops = {
2608 .id = EM28XX_V4L2,
2609 .name = "Em28xx v4l2 Extension",
2610 .init = em28xx_v4l2_init,
2611 .fini = em28xx_v4l2_fini,
Shuah Khana61f6812014-02-21 21:50:17 -03002612 .suspend = em28xx_v4l2_suspend,
2613 .resume = em28xx_v4l2_resume,
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002614};
2615
2616static int __init em28xx_video_register(void)
2617{
2618 return em28xx_register_extension(&v4l2_ops);
2619}
2620
2621static void __exit em28xx_video_unregister(void)
2622{
2623 em28xx_unregister_extension(&v4l2_ops);
2624}
2625
2626module_init(em28xx_video_register);
2627module_exit(em28xx_video_unregister);