blob: 9090a460f51d21c5e13c79e47e80098639aad565 [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{
192 v4l2_device_call_all(&dev->v4l2_dev, 0, core, reset, 0);
193 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
194 INPUT(dev->ctl_input)->vmux, 0, 0);
195 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
196}
197
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300198static int em28xx_colorlevels_set_default(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300199{
200 em28xx_write_reg(dev, EM28XX_R20_YGAIN, CONTRAST_DEFAULT);
201 em28xx_write_reg(dev, EM28XX_R21_YOFFSET, BRIGHTNESS_DEFAULT);
202 em28xx_write_reg(dev, EM28XX_R22_UVGAIN, SATURATION_DEFAULT);
203 em28xx_write_reg(dev, EM28XX_R23_UOFFSET, BLUE_BALANCE_DEFAULT);
204 em28xx_write_reg(dev, EM28XX_R24_VOFFSET, RED_BALANCE_DEFAULT);
205 em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, SHARPNESS_DEFAULT);
206
207 em28xx_write_reg(dev, EM28XX_R14_GAMMA, 0x20);
208 em28xx_write_reg(dev, EM28XX_R15_RGAIN, 0x20);
209 em28xx_write_reg(dev, EM28XX_R16_GGAIN, 0x20);
210 em28xx_write_reg(dev, EM28XX_R17_BGAIN, 0x20);
211 em28xx_write_reg(dev, EM28XX_R18_ROFFSET, 0x00);
212 em28xx_write_reg(dev, EM28XX_R19_GOFFSET, 0x00);
213 return em28xx_write_reg(dev, EM28XX_R1A_BOFFSET, 0x00);
214}
215
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300216static int em28xx_set_outfmt(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300217{
218 int ret;
219 u8 fmt, vinctrl;
220
221 fmt = dev->format->reg;
222 if (!dev->is_em25xx)
223 fmt |= 0x20;
224 /*
225 * NOTE: it's not clear if this is really needed !
226 * The datasheets say bit 5 is a reserved bit and devices seem to work
227 * fine without it. But the Windows driver sets it for em2710/50+em28xx
228 * devices and we've always been setting it, too.
229 *
230 * em2765 (em25xx, em276x/7x/8x) devices do NOT work with this bit set,
231 * it's likely used for an additional (compressed ?) format there.
232 */
233 ret = em28xx_write_reg(dev, EM28XX_R27_OUTFMT, fmt);
234 if (ret < 0)
235 return ret;
236
237 ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, dev->vinmode);
238 if (ret < 0)
239 return ret;
240
241 vinctrl = dev->vinctl;
242 if (em28xx_vbi_supported(dev) == 1) {
243 vinctrl |= EM28XX_VINCTRL_VBI_RAW;
244 em28xx_write_reg(dev, EM28XX_R34_VBI_START_H, 0x00);
245 em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH, dev->vbi_width/4);
246 em28xx_write_reg(dev, EM28XX_R37_VBI_HEIGHT, dev->vbi_height);
247 if (dev->norm & V4L2_STD_525_60) {
248 /* NTSC */
249 em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x09);
250 } else if (dev->norm & V4L2_STD_625_50) {
251 /* PAL */
252 em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x07);
253 }
254 }
255
256 return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctrl);
257}
258
259static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax,
260 u8 ymin, u8 ymax)
261{
262 em28xx_videodbg("em28xx Scale: (%d,%d)-(%d,%d)\n",
263 xmin, ymin, xmax, ymax);
264
265 em28xx_write_regs(dev, EM28XX_R28_XMIN, &xmin, 1);
266 em28xx_write_regs(dev, EM28XX_R29_XMAX, &xmax, 1);
267 em28xx_write_regs(dev, EM28XX_R2A_YMIN, &ymin, 1);
268 return em28xx_write_regs(dev, EM28XX_R2B_YMAX, &ymax, 1);
269}
270
271static void em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
272 u16 width, u16 height)
273{
274 u8 cwidth = width >> 2;
275 u8 cheight = height >> 2;
276 u8 overflow = (height >> 9 & 0x02) | (width >> 10 & 0x01);
277 /* NOTE: size limit: 2047x1023 = 2MPix */
278
279 em28xx_videodbg("capture area set to (%d,%d): %dx%d\n",
280 hstart, vstart,
281 ((overflow & 2) << 9 | cwidth << 2),
282 ((overflow & 1) << 10 | cheight << 2));
283
284 em28xx_write_regs(dev, EM28XX_R1C_HSTART, &hstart, 1);
285 em28xx_write_regs(dev, EM28XX_R1D_VSTART, &vstart, 1);
286 em28xx_write_regs(dev, EM28XX_R1E_CWIDTH, &cwidth, 1);
287 em28xx_write_regs(dev, EM28XX_R1F_CHEIGHT, &cheight, 1);
288 em28xx_write_regs(dev, EM28XX_R1B_OFLOW, &overflow, 1);
289
290 /* FIXME: function/meaning of these registers ? */
291 /* FIXME: align width+height to multiples of 4 ?! */
292 if (dev->is_em25xx) {
293 em28xx_write_reg(dev, 0x34, width >> 4);
294 em28xx_write_reg(dev, 0x35, height >> 4);
295 }
296}
297
298static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v)
299{
Frank Schaefercba8e9b2014-03-24 16:28:36 -0300300 u8 mode = 0x00;
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300301 /* the em2800 scaler only supports scaling down to 50% */
302
303 if (dev->board.is_em2800) {
304 mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00);
305 } else {
306 u8 buf[2];
307
308 buf[0] = h;
309 buf[1] = h >> 8;
310 em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2);
311
312 buf[0] = v;
313 buf[1] = v >> 8;
314 em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2);
315 /* it seems that both H and V scalers must be active
316 to work correctly */
317 mode = (h || v) ? 0x30 : 0x00;
318 }
Frank Schaefercba8e9b2014-03-24 16:28:36 -0300319 return em28xx_write_reg(dev, EM28XX_R26_COMPR, mode);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300320}
321
322/* FIXME: this only function read values from dev */
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300323static int em28xx_resolution_set(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300324{
325 int width, height;
326 width = norm_maxw(dev);
327 height = norm_maxh(dev);
328
329 /* Properly setup VBI */
330 dev->vbi_width = 720;
331 if (dev->norm & V4L2_STD_525_60)
332 dev->vbi_height = 12;
333 else
334 dev->vbi_height = 18;
335
336 em28xx_set_outfmt(dev);
337
338 em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2);
339
340 /* If we don't set the start position to 2 in VBI mode, we end up
341 with line 20/21 being YUYV encoded instead of being in 8-bit
342 greyscale. The core of the issue is that line 21 (and line 23 for
343 PAL WSS) are inside of active video region, and as a result they
344 get the pixelformatting associated with that area. So by cropping
345 it out, we end up with the same format as the rest of the VBI
346 region */
347 if (em28xx_vbi_supported(dev) == 1)
348 em28xx_capture_area_set(dev, 0, 2, width, height);
349 else
350 em28xx_capture_area_set(dev, 0, 0, width, height);
351
352 return em28xx_scaler_set(dev, dev->hscale, dev->vscale);
353}
354
355/* Set USB alternate setting for analog video */
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -0300356static int em28xx_set_alternate(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300357{
358 int errCode;
359 int i;
360 unsigned int min_pkt_size = dev->width * 2 + 4;
361
362 /* NOTE: for isoc transfers, only alt settings > 0 are allowed
363 bulk transfers seem to work only with alt=0 ! */
364 dev->alt = 0;
365 if ((alt > 0) && (alt < dev->num_alt)) {
366 em28xx_videodbg("alternate forced to %d\n", dev->alt);
367 dev->alt = alt;
368 goto set_alt;
369 }
370 if (dev->analog_xfer_bulk)
371 goto set_alt;
372
373 /* When image size is bigger than a certain value,
374 the frame size should be increased, otherwise, only
375 green screen will be received.
376 */
377 if (dev->width * 2 * dev->height > 720 * 240 * 2)
378 min_pkt_size *= 2;
379
380 for (i = 0; i < dev->num_alt; i++) {
381 /* stop when the selected alt setting offers enough bandwidth */
382 if (dev->alt_max_pkt_size_isoc[i] >= min_pkt_size) {
383 dev->alt = i;
384 break;
385 /* otherwise make sure that we end up with the maximum bandwidth
386 because the min_pkt_size equation might be wrong...
387 */
388 } else if (dev->alt_max_pkt_size_isoc[i] >
389 dev->alt_max_pkt_size_isoc[dev->alt])
390 dev->alt = i;
391 }
392
393set_alt:
394 /* NOTE: for bulk transfers, we need to call usb_set_interface()
395 * even if the previous settings were the same. Otherwise streaming
396 * fails with all urbs having status = -EOVERFLOW ! */
397 if (dev->analog_xfer_bulk) {
398 dev->max_pkt_size = 512; /* USB 2.0 spec */
399 dev->packet_multiplier = EM28XX_BULK_PACKET_MULTIPLIER;
400 } else { /* isoc */
401 em28xx_videodbg("minimum isoc packet size: %u (alt=%d)\n",
402 min_pkt_size, dev->alt);
403 dev->max_pkt_size =
404 dev->alt_max_pkt_size_isoc[dev->alt];
405 dev->packet_multiplier = EM28XX_NUM_ISOC_PACKETS;
406 }
407 em28xx_videodbg("setting alternate %d with wMaxPacketSize=%u\n",
408 dev->alt, dev->max_pkt_size);
Frank Schaefer961717b2014-01-13 19:02:06 -0300409 errCode = usb_set_interface(dev->udev, dev->ifnum, dev->alt);
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -0300410 if (errCode < 0) {
411 em28xx_errdev("cannot change alternate number to %d (error=%i)\n",
412 dev->alt, errCode);
413 return errCode;
414 }
415 return 0;
416}
417
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300418/* ------------------------------------------------------------------
419 DMA and thread functions
420 ------------------------------------------------------------------*/
421
422/*
Frank Schaefer948a49a2012-12-08 11:31:25 -0300423 * Finish the current buffer
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300424 */
Frank Schaefer948a49a2012-12-08 11:31:25 -0300425static inline void finish_buffer(struct em28xx *dev,
426 struct em28xx_buffer *buf)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300427{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300428 em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->top_field);
429
430 buf->vb.v4l2_buf.sequence = dev->field_count++;
431 buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
432 v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
433
434 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300435}
436
437/*
Frank Schaefer36016a32012-12-08 11:31:32 -0300438 * Copy picture data from USB buffer to videobuf buffer
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300439 */
440static void em28xx_copy_video(struct em28xx *dev,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300441 struct em28xx_buffer *buf,
Frank Schaefer36016a32012-12-08 11:31:32 -0300442 unsigned char *usb_buf,
Frank Schaefer4078d622012-12-08 11:31:29 -0300443 unsigned long len)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300444{
445 void *fieldstart, *startwrite, *startread;
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300446 int linesdone, currlinedone, offset, lencopy, remain;
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300447 int bytesperline = dev->width << 1;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300448
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300449 if (buf->pos + len > buf->length)
450 len = buf->length - buf->pos;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300451
Frank Schaefer36016a32012-12-08 11:31:32 -0300452 startread = usb_buf;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300453 remain = len;
454
Frank Schaeferc02ec712012-11-08 14:11:33 -0300455 if (dev->progressive || buf->top_field)
Frank Schaefer36016a32012-12-08 11:31:32 -0300456 fieldstart = buf->vb_buf;
Frank Schaeferc02ec712012-11-08 14:11:33 -0300457 else /* interlaced mode, even nr. of lines */
Frank Schaefer36016a32012-12-08 11:31:32 -0300458 fieldstart = buf->vb_buf + bytesperline;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300459
Frank Schaefer87325332012-12-08 11:31:27 -0300460 linesdone = buf->pos / bytesperline;
461 currlinedone = buf->pos % bytesperline;
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -0300462
463 if (dev->progressive)
464 offset = linesdone * bytesperline + currlinedone;
465 else
466 offset = linesdone * bytesperline * 2 + currlinedone;
467
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300468 startwrite = fieldstart + offset;
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300469 lencopy = bytesperline - currlinedone;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300470 lencopy = lencopy > remain ? remain : lencopy;
471
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300472 if ((char *)startwrite + lencopy > (char *)buf->vb_buf + buf->length) {
Mauro Carvalho Chehabea8df7e2008-04-13 14:39:29 -0300473 em28xx_isocdbg("Overflow of %zi bytes past buffer end (1)\n",
Frank Schaefer36016a32012-12-08 11:31:32 -0300474 ((char *)startwrite + lencopy) -
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300475 ((char *)buf->vb_buf + buf->length));
476 remain = (char *)buf->vb_buf + buf->length -
Frank Schaefer36016a32012-12-08 11:31:32 -0300477 (char *)startwrite;
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -0300478 lencopy = remain;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300479 }
Aidan Thorntone0fadfd342008-04-13 14:56:02 -0300480 if (lencopy <= 0)
481 return;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300482 memcpy(startwrite, startread, lencopy);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300483
484 remain -= lencopy;
485
486 while (remain > 0) {
Frank Schaeferc02ec712012-11-08 14:11:33 -0300487 if (dev->progressive)
488 startwrite += lencopy;
489 else
490 startwrite += lencopy + bytesperline;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300491 startread += lencopy;
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300492 if (bytesperline > remain)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300493 lencopy = remain;
494 else
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -0300495 lencopy = bytesperline;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300496
Frank Schaefer36016a32012-12-08 11:31:32 -0300497 if ((char *)startwrite + lencopy > (char *)buf->vb_buf +
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300498 buf->length) {
Devin Heitmuellere3ba4d32009-09-15 00:18:06 -0300499 em28xx_isocdbg("Overflow of %zi bytes past buffer end"
500 "(2)\n",
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300501 ((char *)startwrite + lencopy) -
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300502 ((char *)buf->vb_buf + buf->length));
503 lencopy = remain = (char *)buf->vb_buf + buf->length -
504 (char *)startwrite;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300505 }
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300506 if (lencopy <= 0)
507 break;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300508
509 memcpy(startwrite, startread, lencopy);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300510
511 remain -= lencopy;
512 }
513
Frank Schaefer87325332012-12-08 11:31:27 -0300514 buf->pos += len;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300515}
516
Frank Schaefer36016a32012-12-08 11:31:32 -0300517/*
518 * Copy VBI data from USB buffer to videobuf buffer
519 */
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300520static void em28xx_copy_vbi(struct em28xx *dev,
Frank Schaefer87325332012-12-08 11:31:27 -0300521 struct em28xx_buffer *buf,
Frank Schaefer36016a32012-12-08 11:31:32 -0300522 unsigned char *usb_buf,
Frank Schaefer4078d622012-12-08 11:31:29 -0300523 unsigned long len)
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300524{
Frank Schaefer36016a32012-12-08 11:31:32 -0300525 unsigned int offset;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300526
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300527 if (buf->pos + len > buf->length)
528 len = buf->length - buf->pos;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300529
Frank Schaefer87325332012-12-08 11:31:27 -0300530 offset = buf->pos;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300531 /* Make sure the bottom field populates the second half of the frame */
Frank Schaefer36016a32012-12-08 11:31:32 -0300532 if (buf->top_field == 0)
533 offset += dev->vbi_width * dev->vbi_height;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300534
Frank Schaefer36016a32012-12-08 11:31:32 -0300535 memcpy(buf->vb_buf + offset, usb_buf, len);
Frank Schaefer87325332012-12-08 11:31:27 -0300536 buf->pos += len;
Devin Heitmueller28abf0832009-09-01 01:54:54 -0300537}
538
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300539static inline void print_err_status(struct em28xx *dev,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300540 int packet, int status)
541{
542 char *errmsg = "Unknown";
543
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300544 switch (status) {
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300545 case -ENOENT:
546 errmsg = "unlinked synchronuously";
547 break;
548 case -ECONNRESET:
549 errmsg = "unlinked asynchronuously";
550 break;
551 case -ENOSR:
552 errmsg = "Buffer error (overrun)";
553 break;
554 case -EPIPE:
555 errmsg = "Stalled (device not responding)";
556 break;
557 case -EOVERFLOW:
558 errmsg = "Babble (bad cable?)";
559 break;
560 case -EPROTO:
561 errmsg = "Bit-stuff error (bad cable?)";
562 break;
563 case -EILSEQ:
564 errmsg = "CRC/Timeout (could be anything)";
565 break;
566 case -ETIME:
567 errmsg = "Device does not respond";
568 break;
569 }
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300570 if (packet < 0) {
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300571 em28xx_isocdbg("URB status %d [%s].\n", status, errmsg);
572 } else {
573 em28xx_isocdbg("URB packet %d, status %d [%s].\n",
574 packet, status, errmsg);
575 }
576}
577
578/*
Frank Schaefer24a6d842012-12-08 11:31:24 -0300579 * get the next available buffer from dma queue
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300580 */
Frank Schaefer24a6d842012-12-08 11:31:24 -0300581static inline struct em28xx_buffer *get_next_buf(struct em28xx *dev,
582 struct em28xx_dmaqueue *dma_q)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300583{
Frank Schaefer24a6d842012-12-08 11:31:24 -0300584 struct em28xx_buffer *buf;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300585
Mauro Carvalho Chehabdbecb442008-04-13 15:08:55 -0300586 if (list_empty(&dma_q->active)) {
587 em28xx_isocdbg("No active queue to serve\n");
Frank Schaefer24a6d842012-12-08 11:31:24 -0300588 return NULL;
Mauro Carvalho Chehabdbecb442008-04-13 15:08:55 -0300589 }
590
Mauro Carvalho Chehabdbecb442008-04-13 15:08:55 -0300591 /* Get the next buffer */
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300592 buf = list_entry(dma_q->active.next, struct em28xx_buffer, list);
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300593 /* Cleans up buffer - Useful for testing for frame/URB loss */
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300594 list_del(&buf->list);
Frank Schaefer87325332012-12-08 11:31:27 -0300595 buf->pos = 0;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300596 buf->vb_buf = buf->mem;
Mauro Carvalho Chehabcb784722008-04-13 15:06:52 -0300597
Frank Schaefer24a6d842012-12-08 11:31:24 -0300598 return buf;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300599}
600
Frank Schaefere04c00d2012-12-08 11:31:30 -0300601/*
602 * Finish the current buffer if completed and prepare for the next field
603 */
604static struct em28xx_buffer *
605finish_field_prepare_next(struct em28xx *dev,
606 struct em28xx_buffer *buf,
607 struct em28xx_dmaqueue *dma_q)
608{
609 if (dev->progressive || dev->top_field) { /* Brand new frame */
610 if (buf != NULL)
611 finish_buffer(dev, buf);
612 buf = get_next_buf(dev, dma_q);
613 }
614 if (buf != NULL) {
615 buf->top_field = dev->top_field;
616 buf->pos = 0;
617 }
618
619 return buf;
620}
621
Frank Schaefer227b7c92012-12-08 11:31:31 -0300622/*
623 * Process data packet according to the em2710/em2750/em28xx frame data format
624 */
625static inline void process_frame_data_em28xx(struct em28xx *dev,
626 unsigned char *data_pkt,
627 unsigned int data_len)
628{
629 struct em28xx_buffer *buf = dev->usb_ctl.vid_buf;
630 struct em28xx_buffer *vbi_buf = dev->usb_ctl.vbi_buf;
631 struct em28xx_dmaqueue *dma_q = &dev->vidq;
632 struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq;
633
634 /* capture type 0 = vbi start
635 capture type 1 = vbi in progress
636 capture type 2 = video start
637 capture type 3 = video in progress */
638 if (data_len >= 4) {
639 /* NOTE: Headers are always 4 bytes and
640 * never split across packets */
641 if (data_pkt[0] == 0x88 && data_pkt[1] == 0x88 &&
642 data_pkt[2] == 0x88 && data_pkt[3] == 0x88) {
643 /* Continuation */
644 data_pkt += 4;
645 data_len -= 4;
646 } else if (data_pkt[0] == 0x33 && data_pkt[1] == 0x95) {
647 /* Field start (VBI mode) */
648 dev->capture_type = 0;
649 dev->vbi_read = 0;
650 em28xx_isocdbg("VBI START HEADER !!!\n");
651 dev->top_field = !(data_pkt[2] & 1);
652 data_pkt += 4;
653 data_len -= 4;
654 } else if (data_pkt[0] == 0x22 && data_pkt[1] == 0x5a) {
655 /* Field start (VBI disabled) */
656 dev->capture_type = 2;
657 em28xx_isocdbg("VIDEO START HEADER !!!\n");
658 dev->top_field = !(data_pkt[2] & 1);
659 data_pkt += 4;
660 data_len -= 4;
661 }
662 }
663 /* NOTE: With bulk transfers, intermediate data packets
664 * have no continuation header */
665
666 if (dev->capture_type == 0) {
667 vbi_buf = finish_field_prepare_next(dev, vbi_buf, vbi_dma_q);
668 dev->usb_ctl.vbi_buf = vbi_buf;
669 dev->capture_type = 1;
670 }
671
672 if (dev->capture_type == 1) {
673 int vbi_size = dev->vbi_width * dev->vbi_height;
674 int vbi_data_len = ((dev->vbi_read + data_len) > vbi_size) ?
675 (vbi_size - dev->vbi_read) : data_len;
676
677 /* Copy VBI data */
678 if (vbi_buf != NULL)
679 em28xx_copy_vbi(dev, vbi_buf, data_pkt, vbi_data_len);
680 dev->vbi_read += vbi_data_len;
681
682 if (vbi_data_len < data_len) {
683 /* Continue with copying video data */
684 dev->capture_type = 2;
685 data_pkt += vbi_data_len;
686 data_len -= vbi_data_len;
687 }
688 }
689
690 if (dev->capture_type == 2) {
691 buf = finish_field_prepare_next(dev, buf, dma_q);
692 dev->usb_ctl.vid_buf = buf;
693 dev->capture_type = 3;
694 }
695
696 if (dev->capture_type == 3 && buf != NULL && data_len > 0)
697 em28xx_copy_video(dev, buf, data_pkt, data_len);
698}
699
Frank Schaefere507e0e2013-03-26 13:38:38 -0300700/*
701 * Process data packet according to the em25xx/em276x/7x/8x frame data format
702 */
703static inline void process_frame_data_em25xx(struct em28xx *dev,
704 unsigned char *data_pkt,
705 unsigned int data_len)
706{
707 struct em28xx_buffer *buf = dev->usb_ctl.vid_buf;
708 struct em28xx_dmaqueue *dmaq = &dev->vidq;
709 bool frame_end = 0;
710
711 /* Check for header */
712 /* NOTE: at least with bulk transfers, only the first packet
713 * has a header and has always set the FRAME_END bit */
714 if (data_len >= 2) { /* em25xx header is only 2 bytes long */
715 if ((data_pkt[0] == EM25XX_FRMDATAHDR_BYTE1) &&
716 ((data_pkt[1] & ~EM25XX_FRMDATAHDR_BYTE2_MASK) == 0x00)) {
717 dev->top_field = !(data_pkt[1] &
718 EM25XX_FRMDATAHDR_BYTE2_FRAME_ID);
719 frame_end = data_pkt[1] &
720 EM25XX_FRMDATAHDR_BYTE2_FRAME_END;
721 data_pkt += 2;
722 data_len -= 2;
723 }
724
725 /* Finish field and prepare next (BULK only) */
726 if (dev->analog_xfer_bulk && frame_end) {
727 buf = finish_field_prepare_next(dev, buf, dmaq);
728 dev->usb_ctl.vid_buf = buf;
729 }
730 /* NOTE: in ISOC mode when a new frame starts and buf==NULL,
731 * we COULD already prepare a buffer here to avoid skipping the
732 * first frame.
733 */
734 }
735
736 /* Copy data */
737 if (buf != NULL && data_len > 0)
738 em28xx_copy_video(dev, buf, data_pkt, data_len);
739
740 /* Finish frame (ISOC only) => avoids lag of 1 frame */
741 if (!dev->analog_xfer_bulk && frame_end) {
742 buf = finish_field_prepare_next(dev, buf, dmaq);
743 dev->usb_ctl.vid_buf = buf;
744 }
745
746 /* NOTE: Tested with USB bulk transfers only !
747 * The wording in the datasheet suggests that isoc might work different.
748 * The current code assumes that with isoc transfers each packet has a
749 * header like with the other em28xx devices.
750 */
751 /* NOTE: Support for interlaced mode is pure theory. It has not been
752 * tested and it is unknown if these devices actually support it. */
753 /* NOTE: No VBI support yet (these chips likely do not support VBI). */
754}
755
Frank Schaefer960da932012-11-25 06:37:37 -0300756/* Processes and copies the URB data content (video and VBI data) */
Frank Schaefer0fa4a402012-11-08 14:11:45 -0300757static inline int em28xx_urb_data_copy(struct em28xx *dev, struct urb *urb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300758{
Frank Schaefer227b7c92012-12-08 11:31:31 -0300759 int xfer_bulk, num_packets, i;
760 unsigned char *usb_data_pkt;
761 unsigned int usb_data_len;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300762
763 if (!dev)
764 return 0;
765
Frank Schaefer2665c292012-12-27 19:02:43 -0300766 if (dev->disconnected)
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300767 return 0;
768
Frank Schaefer1653cb0c2012-11-08 14:11:44 -0300769 if (urb->status < 0)
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300770 print_err_status(dev, -1, urb->status);
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300771
Frank Schaefer4601cc32012-11-08 14:11:46 -0300772 xfer_bulk = usb_pipebulk(urb->pipe);
773
Frank Schaefer4601cc32012-11-08 14:11:46 -0300774 if (xfer_bulk) /* bulk */
775 num_packets = 1;
776 else /* isoc */
777 num_packets = urb->number_of_packets;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300778
Frank Schaefer4601cc32012-11-08 14:11:46 -0300779 for (i = 0; i < num_packets; i++) {
780 if (xfer_bulk) { /* bulk */
Frank Schaefer227b7c92012-12-08 11:31:31 -0300781 usb_data_len = urb->actual_length;
Frank Schaefer4601cc32012-11-08 14:11:46 -0300782
Frank Schaefer227b7c92012-12-08 11:31:31 -0300783 usb_data_pkt = urb->transfer_buffer;
Frank Schaefer4601cc32012-11-08 14:11:46 -0300784 } else { /* isoc */
785 if (urb->iso_frame_desc[i].status < 0) {
786 print_err_status(dev, i,
787 urb->iso_frame_desc[i].status);
788 if (urb->iso_frame_desc[i].status != -EPROTO)
789 continue;
790 }
791
Frank Schaefer227b7c92012-12-08 11:31:31 -0300792 usb_data_len = urb->iso_frame_desc[i].actual_length;
793 if (usb_data_len > dev->max_pkt_size) {
Frank Schaefer4601cc32012-11-08 14:11:46 -0300794 em28xx_isocdbg("packet bigger than packet size");
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300795 continue;
Frank Schaefer4601cc32012-11-08 14:11:46 -0300796 }
797
Frank Schaefer227b7c92012-12-08 11:31:31 -0300798 usb_data_pkt = urb->transfer_buffer +
799 urb->iso_frame_desc[i].offset;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300800 }
801
Frank Schaefer227b7c92012-12-08 11:31:31 -0300802 if (usb_data_len == 0) {
Frank Schaefer4601cc32012-11-08 14:11:46 -0300803 /* NOTE: happens very often with isoc transfers */
804 /* em28xx_usbdbg("packet %d is empty",i); - spammy */
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300805 continue;
806 }
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300807
Frank Schaefere507e0e2013-03-26 13:38:38 -0300808 if (dev->is_em25xx)
809 process_frame_data_em25xx(dev,
810 usb_data_pkt, usb_data_len);
811 else
812 process_frame_data_em28xx(dev,
813 usb_data_pkt, usb_data_len);
814
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300815 }
Frank Schaefer227b7c92012-12-08 11:31:31 -0300816 return 1;
Devin Heitmuellerda52a552009-09-01 01:19:46 -0300817}
818
819
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300820static int get_ressource(enum v4l2_buf_type f_type)
821{
822 switch (f_type) {
823 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
824 return EM28XX_RESOURCE_VIDEO;
825 case V4L2_BUF_TYPE_VBI_CAPTURE:
826 return EM28XX_RESOURCE_VBI;
827 default:
828 BUG();
829 return 0;
830 }
831}
832
833/* Usage lock check functions */
834static int res_get(struct em28xx *dev, enum v4l2_buf_type f_type)
835{
836 int res_type = get_ressource(f_type);
837
838 /* is it free? */
839 if (dev->resources & res_type) {
840 /* no, someone else uses it */
841 return -EBUSY;
842 }
843
844 /* it's free, grab it */
845 dev->resources |= res_type;
846 em28xx_videodbg("res: get %d\n", res_type);
847 return 0;
848}
849
850static void res_free(struct em28xx *dev, enum v4l2_buf_type f_type)
851{
852 int res_type = get_ressource(f_type);
853
854 dev->resources &= ~res_type;
855 em28xx_videodbg("res: put %d\n", res_type);
856}
857
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300858/* ------------------------------------------------------------------
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300859 Videobuf2 operations
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300860 ------------------------------------------------------------------*/
861
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300862static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
863 unsigned int *nbuffers, unsigned int *nplanes,
864 unsigned int sizes[], void *alloc_ctxs[])
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300865{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300866 struct em28xx *dev = vb2_get_drv_priv(vq);
867 unsigned long size;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300868
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300869 if (fmt)
870 size = fmt->fmt.pix.sizeimage;
871 else
872 size = (dev->width * dev->height * dev->format->depth + 7) >> 3;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -0300873
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300874 if (size == 0)
875 return -EINVAL;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300876
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300877 if (0 == *nbuffers)
878 *nbuffers = 32;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300879
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300880 *nplanes = 1;
881 sizes[0] = size;
Mauro Carvalho Chehabd2d9fbf2008-04-17 21:38:53 -0300882
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300883 return 0;
884}
885
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300886static int
887buffer_prepare(struct vb2_buffer *vb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300888{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300889 struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue);
890 struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
891 unsigned long size;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300892
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300893 em28xx_videodbg("%s, field=%d\n", __func__, vb->v4l2_buf.field);
Aidan Thornton3b5fa922008-04-13 15:09:36 -0300894
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300895 size = (dev->width * dev->height * dev->format->depth + 7) >> 3;
Aidan Thornton3b5fa922008-04-13 15:09:36 -0300896
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300897 if (vb2_plane_size(vb, 0) < size) {
898 em28xx_videodbg("%s data will not fit into plane (%lu < %lu)\n",
899 __func__, vb2_plane_size(vb, 0), size);
900 return -EINVAL;
901 }
902 vb2_set_plane_payload(&buf->vb, 0, size);
903
904 return 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300905}
906
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300907int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300908{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300909 struct em28xx *dev = vb2_get_drv_priv(vq);
910 struct v4l2_frequency f;
911 int rc = 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300912
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300913 em28xx_videodbg("%s\n", __func__);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300914
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300915 /* Make sure streaming is not already in progress for this type
916 of filehandle (e.g. video, vbi) */
917 rc = res_get(dev, vq->type);
918 if (rc)
919 return rc;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300920
Frank Schaefer032f1dd2013-10-10 15:31:53 -0300921 if (dev->streaming_users == 0) {
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300922 /* First active streaming user, so allocate all the URBs */
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300923
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300924 /* Allocate the USB bandwidth */
925 em28xx_set_alternate(dev);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300926
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300927 /* Needed, since GPIO might have disabled power of
928 some i2c device
929 */
930 em28xx_wake_i2c(dev);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300931
Frank Schaefer0455eeb2012-11-25 06:37:34 -0300932 dev->capture_type = -1;
Frank Schaefer960da932012-11-25 06:37:37 -0300933 rc = em28xx_init_usb_xfer(dev, EM28XX_ANALOG_MODE,
934 dev->analog_xfer_bulk,
935 EM28XX_NUM_BUFS,
936 dev->max_pkt_size,
937 dev->packet_multiplier,
938 em28xx_urb_data_copy);
Mauro Carvalho Chehabf245e542008-04-13 14:41:23 -0300939 if (rc < 0)
Frank Schaefer032f1dd2013-10-10 15:31:53 -0300940 return rc;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300941
942 /*
943 * djh: it's not clear whether this code is still needed. I'm
944 * leaving it in here for now entirely out of concern for
945 * backward compatibility (the old code did it)
946 */
947
948 /* Ask tuner to go to analog or radio mode */
949 memset(&f, 0, sizeof(f));
950 f.frequency = dev->ctl_freq;
951 if (vq->owner && vq->owner->vdev->vfl_type == VFL_TYPE_RADIO)
952 f.type = V4L2_TUNER_RADIO;
953 else
954 f.type = V4L2_TUNER_ANALOG_TV;
955 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300956 }
957
Frank Schaefer032f1dd2013-10-10 15:31:53 -0300958 dev->streaming_users++;
959
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300960 return rc;
961}
962
Hans Verkuile37559b2014-04-17 02:47:21 -0300963static void em28xx_stop_streaming(struct vb2_queue *vq)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300964{
965 struct em28xx *dev = vb2_get_drv_priv(vq);
966 struct em28xx_dmaqueue *vidq = &dev->vidq;
967 unsigned long flags = 0;
968
969 em28xx_videodbg("%s\n", __func__);
970
971 res_free(dev, vq->type);
972
973 if (dev->streaming_users-- == 1) {
974 /* Last active user, so shutdown all the URBS */
975 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
976 }
977
978 spin_lock_irqsave(&dev->slock, flags);
979 while (!list_empty(&vidq->active)) {
980 struct em28xx_buffer *buf;
981 buf = list_entry(vidq->active.next, struct em28xx_buffer, list);
982 list_del(&buf->list);
983 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
984 }
985 dev->usb_ctl.vid_buf = NULL;
986 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300987}
988
Hans Verkuile37559b2014-04-17 02:47:21 -0300989void em28xx_stop_vbi_streaming(struct vb2_queue *vq)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -0300990{
991 struct em28xx *dev = vb2_get_drv_priv(vq);
992 struct em28xx_dmaqueue *vbiq = &dev->vbiq;
993 unsigned long flags = 0;
994
995 em28xx_videodbg("%s\n", __func__);
996
997 res_free(dev, vq->type);
998
999 if (dev->streaming_users-- == 1) {
1000 /* Last active user, so shutdown all the URBS */
1001 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
1002 }
1003
1004 spin_lock_irqsave(&dev->slock, flags);
1005 while (!list_empty(&vbiq->active)) {
1006 struct em28xx_buffer *buf;
1007 buf = list_entry(vbiq->active.next, struct em28xx_buffer, list);
1008 list_del(&buf->list);
1009 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
1010 }
1011 dev->usb_ctl.vbi_buf = NULL;
1012 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001013}
1014
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001015static void
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001016buffer_queue(struct vb2_buffer *vb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001017{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001018 struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue);
1019 struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
1020 struct em28xx_dmaqueue *vidq = &dev->vidq;
1021 unsigned long flags = 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001022
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001023 em28xx_videodbg("%s\n", __func__);
1024 buf->mem = vb2_plane_vaddr(vb, 0);
1025 buf->length = vb2_plane_size(vb, 0);
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001026
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001027 spin_lock_irqsave(&dev->slock, flags);
1028 list_add_tail(&buf->list, &vidq->active);
1029 spin_unlock_irqrestore(&dev->slock, flags);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001030}
1031
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001032static struct vb2_ops em28xx_video_qops = {
1033 .queue_setup = queue_setup,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001034 .buf_prepare = buffer_prepare,
1035 .buf_queue = buffer_queue,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001036 .start_streaming = em28xx_start_analog_streaming,
1037 .stop_streaming = em28xx_stop_streaming,
1038 .wait_prepare = vb2_ops_wait_prepare,
1039 .wait_finish = vb2_ops_wait_finish,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001040};
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001041
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001042static int em28xx_vb2_setup(struct em28xx *dev)
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001043{
1044 int rc;
1045 struct vb2_queue *q;
1046
1047 /* Setup Videobuf2 for Video capture */
1048 q = &dev->vb_vidq;
1049 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Mauro Carvalho Chehabef85cd92013-01-06 00:34:22 -02001050 q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
Sakari Ailusade48682014-02-25 19:12:19 -03001051 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001052 q->drv_priv = dev;
1053 q->buf_struct_size = sizeof(struct em28xx_buffer);
1054 q->ops = &em28xx_video_qops;
1055 q->mem_ops = &vb2_vmalloc_memops;
1056
1057 rc = vb2_queue_init(q);
1058 if (rc < 0)
1059 return rc;
1060
1061 /* Setup Videobuf2 for VBI capture */
1062 q = &dev->vb_vbiq;
1063 q->type = V4L2_BUF_TYPE_VBI_CAPTURE;
1064 q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR;
Sakari Ailusade48682014-02-25 19:12:19 -03001065 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001066 q->drv_priv = dev;
1067 q->buf_struct_size = sizeof(struct em28xx_buffer);
1068 q->ops = &em28xx_vbi_qops;
1069 q->mem_ops = &vb2_vmalloc_memops;
1070
1071 rc = vb2_queue_init(q);
1072 if (rc < 0)
1073 return rc;
1074
1075 return 0;
1076}
1077
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001078/********************* v4l2 interface **************************************/
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001079
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001080static void video_mux(struct em28xx *dev, int index)
1081{
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001082 dev->ctl_input = index;
1083 dev->ctl_ainput = INPUT(index)->amux;
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001084 dev->ctl_aoutput = INPUT(index)->aout;
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001085
Mauro Carvalho Chehabe879b8e2008-11-20 13:39:39 -03001086 if (!dev->ctl_aoutput)
1087 dev->ctl_aoutput = EM28XX_AOUT_MASTER;
1088
Hans Verkuil5325b422009-04-02 11:26:22 -03001089 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
1090 INPUT(index)->vmux, 0, 0);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001091
Mauro Carvalho Chehab505b6d02008-11-25 09:39:50 -03001092 if (dev->board.has_msp34xx) {
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001093 if (dev->i2s_speed) {
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03001094 v4l2_device_call_all(&dev->v4l2_dev, 0, audio,
1095 s_i2s_clock_freq, dev->i2s_speed);
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001096 }
Hans Verkuil2474ed42006-03-19 12:35:57 -03001097 /* Note: this is msp3400 specific */
Hans Verkuil5325b422009-04-02 11:26:22 -03001098 v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing,
1099 dev->ctl_ainput, MSP_OUTPUT(MSP_SC_IN_DSP_SCART1), 0);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001100 }
Mauro Carvalho Chehab539c96d2008-01-05 09:53:54 -03001101
Vitaly Wool2bd1d9e2009-03-04 08:27:52 -03001102 if (dev->board.adecoder != EM28XX_NOADECODER) {
Hans Verkuil5325b422009-04-02 11:26:22 -03001103 v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing,
1104 dev->ctl_ainput, dev->ctl_aoutput, 0);
Vitaly Wool2bd1d9e2009-03-04 08:27:52 -03001105 }
1106
Mauro Carvalho Chehab00b87302008-02-06 18:34:13 -03001107 em28xx_audio_analog_set(dev);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001108}
1109
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001110static void em28xx_ctrl_notify(struct v4l2_ctrl *ctrl, void *priv)
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001111{
Hans Verkuil081b9452012-09-07 05:43:59 -03001112 struct em28xx *dev = priv;
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001113
Hans Verkuil081b9452012-09-07 05:43:59 -03001114 /*
1115 * In the case of non-AC97 volume controls, we still need
1116 * to do some setups at em28xx, in order to mute/unmute
1117 * and to adjust audio volume. However, the value ranges
1118 * should be checked by the corresponding V4L subdriver.
1119 */
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001120 switch (ctrl->id) {
1121 case V4L2_CID_AUDIO_MUTE:
Hans Verkuil081b9452012-09-07 05:43:59 -03001122 dev->mute = ctrl->val;
1123 em28xx_audio_analog_set(dev);
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001124 break;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001125 case V4L2_CID_AUDIO_VOLUME:
Hans Verkuil081b9452012-09-07 05:43:59 -03001126 dev->volume = ctrl->val;
1127 em28xx_audio_analog_set(dev);
1128 break;
1129 }
1130}
1131
1132static int em28xx_s_ctrl(struct v4l2_ctrl *ctrl)
1133{
1134 struct em28xx *dev = container_of(ctrl->handler, struct em28xx, ctrl_handler);
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001135 int ret = -EINVAL;
Hans Verkuil081b9452012-09-07 05:43:59 -03001136
1137 switch (ctrl->id) {
1138 case V4L2_CID_AUDIO_MUTE:
1139 dev->mute = ctrl->val;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001140 ret = em28xx_audio_analog_set(dev);
Hans Verkuil081b9452012-09-07 05:43:59 -03001141 break;
1142 case V4L2_CID_AUDIO_VOLUME:
1143 dev->volume = ctrl->val;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001144 ret = em28xx_audio_analog_set(dev);
1145 break;
1146 case V4L2_CID_CONTRAST:
1147 ret = em28xx_write_reg(dev, EM28XX_R20_YGAIN, ctrl->val);
1148 break;
1149 case V4L2_CID_BRIGHTNESS:
1150 ret = em28xx_write_reg(dev, EM28XX_R21_YOFFSET, ctrl->val);
1151 break;
1152 case V4L2_CID_SATURATION:
1153 ret = em28xx_write_reg(dev, EM28XX_R22_UVGAIN, ctrl->val);
1154 break;
1155 case V4L2_CID_BLUE_BALANCE:
1156 ret = em28xx_write_reg(dev, EM28XX_R23_UOFFSET, ctrl->val);
1157 break;
1158 case V4L2_CID_RED_BALANCE:
1159 ret = em28xx_write_reg(dev, EM28XX_R24_VOFFSET, ctrl->val);
1160 break;
1161 case V4L2_CID_SHARPNESS:
1162 ret = em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, ctrl->val);
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001163 break;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001164 }
Mauro Carvalho Chehaba98f6af2009-07-19 10:45:49 -03001165
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03001166 return (ret < 0) ? ret : 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001167}
1168
Fengguang Wu8068eb82014-01-07 12:50:47 -03001169static const struct v4l2_ctrl_ops em28xx_ctrl_ops = {
Hans Verkuil081b9452012-09-07 05:43:59 -03001170 .s_ctrl = em28xx_s_ctrl,
1171};
1172
Frank Schaefer6b09a212013-02-10 16:05:12 -03001173static void size_to_scale(struct em28xx *dev,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001174 unsigned int width, unsigned int height,
1175 unsigned int *hscale, unsigned int *vscale)
1176{
Mauro Carvalho Chehab55699962009-07-13 20:15:02 -03001177 unsigned int maxw = norm_maxw(dev);
1178 unsigned int maxh = norm_maxh(dev);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001179
1180 *hscale = (((unsigned long)maxw) << 12) / width - 4096L;
Frank Schaefer81685322013-02-10 16:05:11 -03001181 if (*hscale > EM28XX_HVSCALE_MAX)
1182 *hscale = EM28XX_HVSCALE_MAX;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001183
1184 *vscale = (((unsigned long)maxh) << 12) / height - 4096L;
Frank Schaefer81685322013-02-10 16:05:11 -03001185 if (*vscale > EM28XX_HVSCALE_MAX)
1186 *vscale = EM28XX_HVSCALE_MAX;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001187}
1188
Frank Schaeferb8374132013-02-10 16:05:13 -03001189static void scale_to_size(struct em28xx *dev,
1190 unsigned int hscale, unsigned int vscale,
1191 unsigned int *width, unsigned int *height)
1192{
1193 unsigned int maxw = norm_maxw(dev);
1194 unsigned int maxh = norm_maxh(dev);
1195
1196 *width = (((unsigned long)maxw) << 12) / (hscale + 4096L);
1197 *height = (((unsigned long)maxh) << 12) / (vscale + 4096L);
1198}
1199
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001200/* ------------------------------------------------------------------
1201 IOCTL vidioc handling
1202 ------------------------------------------------------------------*/
1203
Hans Verkuil78b526a2008-05-28 12:16:41 -03001204static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001205 struct v4l2_format *f)
1206{
1207 struct em28xx_fh *fh = priv;
1208 struct em28xx *dev = fh->dev;
1209
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001210 f->fmt.pix.width = dev->width;
1211 f->fmt.pix.height = dev->height;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001212 f->fmt.pix.pixelformat = dev->format->fourcc;
1213 f->fmt.pix.bytesperline = (dev->width * dev->format->depth + 7) >> 3;
Mauro Carvalho Chehab44dc7332008-04-13 15:11:08 -03001214 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * dev->height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001215 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
1216
1217 /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -03001218 if (dev->progressive)
1219 f->fmt.pix.field = V4L2_FIELD_NONE;
1220 else
1221 f->fmt.pix.field = dev->interlaced ?
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001222 V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001223 return 0;
1224}
1225
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001226static struct em28xx_fmt *format_by_fourcc(unsigned int fourcc)
1227{
1228 unsigned int i;
1229
1230 for (i = 0; i < ARRAY_SIZE(format); i++)
1231 if (format[i].fourcc == fourcc)
1232 return &format[i];
1233
1234 return NULL;
1235}
1236
Hans Verkuil78b526a2008-05-28 12:16:41 -03001237static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001238 struct v4l2_format *f)
1239{
1240 struct em28xx_fh *fh = priv;
1241 struct em28xx *dev = fh->dev;
Trent Piephoccb83402009-05-30 21:45:46 -03001242 unsigned int width = f->fmt.pix.width;
1243 unsigned int height = f->fmt.pix.height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001244 unsigned int maxw = norm_maxw(dev);
1245 unsigned int maxh = norm_maxh(dev);
1246 unsigned int hscale, vscale;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001247 struct em28xx_fmt *fmt;
1248
1249 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
1250 if (!fmt) {
1251 em28xx_videodbg("Fourcc format (%08x) invalid.\n",
1252 f->fmt.pix.pixelformat);
1253 return -EINVAL;
1254 }
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001255
Mauro Carvalho Chehab55699962009-07-13 20:15:02 -03001256 if (dev->board.is_em2800) {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001257 /* the em2800 can only scale down to 50% */
Trent Piephoccb83402009-05-30 21:45:46 -03001258 height = height > (3 * maxh / 4) ? maxh : maxh / 2;
1259 width = width > (3 * maxw / 4) ? maxw : maxw / 2;
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001260 /*
1261 * MaxPacketSize for em2800 is too small to capture at full
1262 * resolution use half of maxw as the scaler can only scale
1263 * to 50%
1264 */
Sascha Sommer1020d132012-01-08 16:54:28 -03001265 if (width == maxw && height == maxh)
1266 width /= 2;
Trent Piephoccb83402009-05-30 21:45:46 -03001267 } else {
1268 /* width must even because of the YUYV format
1269 height must be even because of interlacing */
Devin Heitmuellere3ba4d32009-09-15 00:18:06 -03001270 v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh,
1271 1, 0);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001272 }
1273
Frank Schaefer6b09a212013-02-10 16:05:12 -03001274 size_to_scale(dev, width, height, &hscale, &vscale);
Hans Verkuil46f85972013-03-30 05:31:42 -03001275 scale_to_size(dev, hscale, vscale, &width, &height);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001276
1277 f->fmt.pix.width = width;
1278 f->fmt.pix.height = height;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001279 f->fmt.pix.pixelformat = fmt->fourcc;
Hans Verkuile6066db2013-02-06 08:14:47 -03001280 f->fmt.pix.bytesperline = (width * fmt->depth + 7) >> 3;
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001281 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001282 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
Mauro Carvalho Chehabc2a6b542009-08-08 03:14:55 -03001283 if (dev->progressive)
1284 f->fmt.pix.field = V4L2_FIELD_NONE;
1285 else
1286 f->fmt.pix.field = dev->interlaced ?
1287 V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
Alban Browaeys51dd4d72013-07-16 19:06:46 -03001288 f->fmt.pix.priv = 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001289
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001290 return 0;
1291}
1292
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001293static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc,
1294 unsigned width, unsigned height)
1295{
1296 struct em28xx_fmt *fmt;
1297
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001298 fmt = format_by_fourcc(fourcc);
1299 if (!fmt)
1300 return -EINVAL;
1301
1302 dev->format = fmt;
1303 dev->width = width;
1304 dev->height = height;
1305
1306 /* set new image size */
Frank Schaefer6b09a212013-02-10 16:05:12 -03001307 size_to_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001308
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001309 em28xx_resolution_set(dev);
1310
1311 return 0;
1312}
1313
Hans Verkuil78b526a2008-05-28 12:16:41 -03001314static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001315 struct v4l2_format *f)
1316{
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001317 struct em28xx *dev = video_drvdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001318
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001319 if (dev->streaming_users > 0)
1320 return -EBUSY;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001321
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001322 vidioc_try_fmt_vid_cap(file, priv, f);
1323
Hans Verkuil0499a5a2010-09-26 07:34:45 -03001324 return em28xx_set_video_format(dev, f->fmt.pix.pixelformat,
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03001325 f->fmt.pix.width, f->fmt.pix.height);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001326}
1327
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001328static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
1329{
1330 struct em28xx_fh *fh = priv;
1331 struct em28xx *dev = fh->dev;
Devin Heitmueller19bf0032009-09-11 00:40:18 -03001332
1333 *norm = dev->norm;
1334
1335 return 0;
1336}
1337
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001338static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm)
1339{
1340 struct em28xx_fh *fh = priv;
1341 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03001342
1343 v4l2_device_call_all(&dev->v4l2_dev, 0, video, querystd, norm);
1344
1345 return 0;
1346}
1347
Hans Verkuil314527a2013-03-15 06:10:40 -03001348static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001349{
1350 struct em28xx_fh *fh = priv;
1351 struct em28xx *dev = fh->dev;
1352 struct v4l2_format f;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001353
Hans Verkuil314527a2013-03-15 06:10:40 -03001354 if (norm == dev->norm)
Hans Verkuild8c95c02012-09-07 07:31:54 -03001355 return 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001356
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001357 if (dev->streaming_users > 0)
Hans Verkuild8c95c02012-09-07 07:31:54 -03001358 return -EBUSY;
Hans Verkuild8c95c02012-09-07 07:31:54 -03001359
Hans Verkuil314527a2013-03-15 06:10:40 -03001360 dev->norm = norm;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001361
1362 /* Adjusts width/height, if needed */
Hans Verkuild8c95c02012-09-07 07:31:54 -03001363 f.fmt.pix.width = 720;
Hans Verkuil314527a2013-03-15 06:10:40 -03001364 f.fmt.pix.height = (norm & V4L2_STD_525_60) ? 480 : 576;
Hans Verkuil78b526a2008-05-28 12:16:41 -03001365 vidioc_try_fmt_vid_cap(file, priv, &f);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001366
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001367 /* set new image size */
1368 dev->width = f.fmt.pix.width;
1369 dev->height = f.fmt.pix.height;
Frank Schaefer6b09a212013-02-10 16:05:12 -03001370 size_to_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001371
1372 em28xx_resolution_set(dev);
Hans Verkuilf41737e2009-04-01 03:52:39 -03001373 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001374
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001375 return 0;
1376}
1377
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001378static int vidioc_g_parm(struct file *file, void *priv,
1379 struct v4l2_streamparm *p)
1380{
1381 struct em28xx_fh *fh = priv;
1382 struct em28xx *dev = fh->dev;
1383 int rc = 0;
1384
Hans Verkuil86ff7f12012-09-07 06:16:03 -03001385 p->parm.capture.readbuffers = EM28XX_MIN_BUF;
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001386 if (dev->board.is_webcam)
1387 rc = v4l2_device_call_until_err(&dev->v4l2_dev, 0,
1388 video, g_parm, p);
1389 else
1390 v4l2_video_std_frame_period(dev->norm,
1391 &p->parm.capture.timeperframe);
1392
1393 return rc;
1394}
1395
1396static int vidioc_s_parm(struct file *file, void *priv,
1397 struct v4l2_streamparm *p)
1398{
1399 struct em28xx_fh *fh = priv;
1400 struct em28xx *dev = fh->dev;
1401
Hans Verkuil86ff7f12012-09-07 06:16:03 -03001402 p->parm.capture.readbuffers = EM28XX_MIN_BUF;
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03001403 return v4l2_device_call_until_err(&dev->v4l2_dev, 0, video, s_parm, p);
1404}
1405
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001406static const char *iname[] = {
1407 [EM28XX_VMUX_COMPOSITE1] = "Composite1",
1408 [EM28XX_VMUX_COMPOSITE2] = "Composite2",
1409 [EM28XX_VMUX_COMPOSITE3] = "Composite3",
1410 [EM28XX_VMUX_COMPOSITE4] = "Composite4",
1411 [EM28XX_VMUX_SVIDEO] = "S-Video",
1412 [EM28XX_VMUX_TELEVISION] = "Television",
1413 [EM28XX_VMUX_CABLE] = "Cable TV",
1414 [EM28XX_VMUX_DVB] = "DVB",
1415 [EM28XX_VMUX_DEBUG] = "for debug only",
1416};
1417
1418static int vidioc_enum_input(struct file *file, void *priv,
1419 struct v4l2_input *i)
1420{
1421 struct em28xx_fh *fh = priv;
1422 struct em28xx *dev = fh->dev;
1423 unsigned int n;
1424
1425 n = i->index;
1426 if (n >= MAX_EM28XX_INPUT)
1427 return -EINVAL;
1428 if (0 == INPUT(n)->type)
1429 return -EINVAL;
1430
1431 i->index = n;
1432 i->type = V4L2_INPUT_TYPE_CAMERA;
1433
1434 strcpy(i->name, iname[INPUT(n)->type]);
1435
1436 if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type) ||
1437 (EM28XX_VMUX_CABLE == INPUT(n)->type))
1438 i->type = V4L2_INPUT_TYPE_TUNER;
1439
Mauro Carvalho Chehab7d497f82007-11-11 14:15:34 -03001440 i->std = dev->vdev->tvnorms;
Hans Verkuild8c95c02012-09-07 07:31:54 -03001441 /* webcams do not have the STD API */
1442 if (dev->board.is_webcam)
1443 i->capabilities = 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001444
1445 return 0;
1446}
1447
1448static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1449{
1450 struct em28xx_fh *fh = priv;
1451 struct em28xx *dev = fh->dev;
1452
1453 *i = dev->ctl_input;
1454
1455 return 0;
1456}
1457
1458static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
1459{
1460 struct em28xx_fh *fh = priv;
1461 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001462
1463 if (i >= MAX_EM28XX_INPUT)
1464 return -EINVAL;
1465 if (0 == INPUT(i)->type)
1466 return -EINVAL;
1467
Ezequiel García96371fc2012-03-23 18:09:34 -03001468 video_mux(dev, i);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001469 return 0;
1470}
1471
1472static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
1473{
1474 struct em28xx_fh *fh = priv;
1475 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001476
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001477 switch (a->index) {
1478 case EM28XX_AMUX_VIDEO:
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001479 strcpy(a->name, "Television");
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001480 break;
1481 case EM28XX_AMUX_LINE_IN:
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001482 strcpy(a->name, "Line In");
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001483 break;
1484 case EM28XX_AMUX_VIDEO2:
1485 strcpy(a->name, "Television alt");
1486 break;
1487 case EM28XX_AMUX_PHONE:
1488 strcpy(a->name, "Phone");
1489 break;
1490 case EM28XX_AMUX_MIC:
1491 strcpy(a->name, "Mic");
1492 break;
1493 case EM28XX_AMUX_CD:
1494 strcpy(a->name, "CD");
1495 break;
1496 case EM28XX_AMUX_AUX:
1497 strcpy(a->name, "Aux");
1498 break;
1499 case EM28XX_AMUX_PCM_OUT:
1500 strcpy(a->name, "PCM");
1501 break;
1502 default:
1503 return -EINVAL;
1504 }
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001505
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001506 a->index = dev->ctl_ainput;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001507 a->capability = V4L2_AUDCAP_STEREO;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001508
1509 return 0;
1510}
1511
Hans Verkuil0e8025b92012-09-04 11:59:31 -03001512static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001513{
1514 struct em28xx_fh *fh = priv;
1515 struct em28xx *dev = fh->dev;
1516
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03001517 if (a->index >= MAX_EM28XX_INPUT)
1518 return -EINVAL;
1519 if (0 == INPUT(a->index)->type)
1520 return -EINVAL;
1521
Mauro Carvalho Chehab35ae6f02008-11-20 12:40:51 -03001522 dev->ctl_ainput = INPUT(a->index)->amux;
1523 dev->ctl_aoutput = INPUT(a->index)->aout;
Mauro Carvalho Chehabe879b8e2008-11-20 13:39:39 -03001524
1525 if (!dev->ctl_aoutput)
1526 dev->ctl_aoutput = EM28XX_AOUT_MASTER;
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001527
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001528 return 0;
1529}
1530
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001531static int vidioc_g_tuner(struct file *file, void *priv,
1532 struct v4l2_tuner *t)
1533{
1534 struct em28xx_fh *fh = priv;
1535 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001536
1537 if (0 != t->index)
1538 return -EINVAL;
1539
1540 strcpy(t->name, "Tuner");
1541
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03001542 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001543 return 0;
1544}
1545
1546static int vidioc_s_tuner(struct file *file, void *priv,
Hans Verkuil2f73c7c2013-03-15 06:10:06 -03001547 const struct v4l2_tuner *t)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001548{
1549 struct em28xx_fh *fh = priv;
1550 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001551
1552 if (0 != t->index)
1553 return -EINVAL;
1554
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03001555 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001556 return 0;
1557}
1558
1559static int vidioc_g_frequency(struct file *file, void *priv,
1560 struct v4l2_frequency *f)
1561{
1562 struct em28xx_fh *fh = priv;
1563 struct em28xx *dev = fh->dev;
1564
Hans Verkuil20deebf2012-09-06 10:07:25 -03001565 if (0 != f->tuner)
1566 return -EINVAL;
1567
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001568 f->frequency = dev->ctl_freq;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001569 return 0;
1570}
1571
1572static int vidioc_s_frequency(struct file *file, void *priv,
Hans Verkuilb530a442013-03-19 04:09:26 -03001573 const struct v4l2_frequency *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001574{
Hans Verkuilb530a442013-03-19 04:09:26 -03001575 struct v4l2_frequency new_freq = *f;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001576 struct em28xx_fh *fh = priv;
1577 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001578
1579 if (0 != f->tuner)
1580 return -EINVAL;
1581
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03001582 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, f);
Hans Verkuilb530a442013-03-19 04:09:26 -03001583 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_frequency, &new_freq);
1584 dev->ctl_freq = new_freq.frequency;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001585
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001586 return 0;
1587}
1588
Hans Verkuilcd634f12013-03-27 08:04:23 -03001589#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuil96b03d22013-04-06 06:16:58 -03001590static int vidioc_g_chip_info(struct file *file, void *priv,
1591 struct v4l2_dbg_chip_info *chip)
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001592{
1593 struct em28xx_fh *fh = priv;
1594 struct em28xx *dev = fh->dev;
1595
1596 if (chip->match.addr > 1)
1597 return -EINVAL;
1598 if (chip->match.addr == 1)
1599 strlcpy(chip->name, "ac97", sizeof(chip->name));
1600 else
1601 strlcpy(chip->name, dev->v4l2_dev.name, sizeof(chip->name));
1602 return 0;
1603}
1604
Frank Schaefer35deba32013-02-07 13:39:19 -03001605static int em28xx_reg_len(int reg)
1606{
1607 switch (reg) {
1608 case EM28XX_R40_AC97LSB:
1609 case EM28XX_R30_HSCALELOW:
1610 case EM28XX_R32_VSCALELOW:
1611 return 2;
1612 default:
1613 return 1;
1614 }
1615}
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001616
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001617static int vidioc_g_register(struct file *file, void *priv,
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001618 struct v4l2_dbg_register *reg)
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001619{
1620 struct em28xx_fh *fh = priv;
1621 struct em28xx *dev = fh->dev;
1622 int ret;
1623
Hans Verkuilabca2052013-05-29 06:59:35 -03001624 if (reg->match.addr > 1)
1625 return -EINVAL;
1626 if (reg->match.addr) {
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001627 ret = em28xx_read_ac97(dev, reg->reg);
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001628 if (ret < 0)
1629 return ret;
1630
1631 reg->val = ret;
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001632 reg->size = 1;
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001633 return 0;
1634 }
1635
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001636 /* Match host */
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001637 reg->size = em28xx_reg_len(reg->reg);
1638 if (reg->size == 1) {
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001639 ret = em28xx_read_reg(dev, reg->reg);
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001640
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001641 if (ret < 0)
1642 return ret;
1643
1644 reg->val = ret;
1645 } else {
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001646 __le16 val = 0;
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001647 ret = dev->em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001648 reg->reg, (char *)&val, 2);
1649 if (ret < 0)
1650 return ret;
1651
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001652 reg->val = le16_to_cpu(val);
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001653 }
1654
1655 return 0;
1656}
1657
1658static int vidioc_s_register(struct file *file, void *priv,
Hans Verkuil977ba3b2013-03-24 08:28:46 -03001659 const struct v4l2_dbg_register *reg)
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001660{
1661 struct em28xx_fh *fh = priv;
1662 struct em28xx *dev = fh->dev;
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001663 __le16 buf;
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001664
Hans Verkuilabca2052013-05-29 06:59:35 -03001665 if (reg->match.addr > 1)
Hans Verkuil3b2d17b2013-03-18 12:21:53 -03001666 return -EINVAL;
Hans Verkuilabca2052013-05-29 06:59:35 -03001667 if (reg->match.addr)
1668 return em28xx_write_ac97(dev, reg->reg, reg->val);
Mauro Carvalho Chehab531c98e2008-12-22 13:18:27 -03001669
Mauro Carvalho Chehab14983d82008-12-22 20:58:41 -03001670 /* Match host */
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001671 buf = cpu_to_le16(reg->val);
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001672
Hans Verkuil0499a5a2010-09-26 07:34:45 -03001673 return em28xx_write_regs(dev, reg->reg, (char *)&buf,
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001674 em28xx_reg_len(reg->reg));
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001675}
1676#endif
1677
1678
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001679static int vidioc_querycap(struct file *file, void *priv,
1680 struct v4l2_capability *cap)
1681{
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001682 struct video_device *vdev = video_devdata(file);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001683 struct em28xx_fh *fh = priv;
1684 struct em28xx *dev = fh->dev;
1685
1686 strlcpy(cap->driver, "em28xx", sizeof(cap->driver));
1687 strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card));
Thierry MERLEcb977162009-01-20 18:01:33 -03001688 usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001689
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001690 if (vdev->vfl_type == VFL_TYPE_GRABBER)
1691 cap->device_caps = V4L2_CAP_READWRITE |
1692 V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1693 else if (vdev->vfl_type == VFL_TYPE_RADIO)
1694 cap->device_caps = V4L2_CAP_RADIO;
1695 else
Hans Verkuil1d179ee2012-09-07 08:45:10 -03001696 cap->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE;
Devin Heitmueller04146142009-09-11 00:08:44 -03001697
Mauro Carvalho Chehab6c428b52009-08-04 19:52:37 -03001698 if (dev->audio_mode.has_audio)
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001699 cap->device_caps |= V4L2_CAP_AUDIO;
Mauro Carvalho Chehab6c428b52009-08-04 19:52:37 -03001700
Mauro Carvalho Chehabed086312008-01-24 06:59:20 -03001701 if (dev->tuner_type != TUNER_ABSENT)
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001702 cap->device_caps |= V4L2_CAP_TUNER;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001703
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001704 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS |
1705 V4L2_CAP_READWRITE | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1706 if (dev->vbi_dev)
Hans Verkuil1d179ee2012-09-07 08:45:10 -03001707 cap->capabilities |= V4L2_CAP_VBI_CAPTURE;
Hans Verkuila9d79fe2012-09-06 07:31:04 -03001708 if (dev->radio_dev)
1709 cap->capabilities |= V4L2_CAP_RADIO;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001710 return 0;
1711}
1712
Hans Verkuil78b526a2008-05-28 12:16:41 -03001713static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001714 struct v4l2_fmtdesc *f)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001715{
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001716 if (unlikely(f->index >= ARRAY_SIZE(format)))
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001717 return -EINVAL;
1718
Mauro Carvalho Chehabbddcf632008-12-20 09:06:37 -03001719 strlcpy(f->description, format[f->index].name, sizeof(f->description));
1720 f->pixelformat = format[f->index].fourcc;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001721
1722 return 0;
1723}
1724
Mauro Carvalho Chehab1c5c50682011-10-16 13:52:43 -02001725static int vidioc_enum_framesizes(struct file *file, void *priv,
1726 struct v4l2_frmsizeenum *fsize)
1727{
1728 struct em28xx_fh *fh = priv;
1729 struct em28xx *dev = fh->dev;
1730 struct em28xx_fmt *fmt;
1731 unsigned int maxw = norm_maxw(dev);
1732 unsigned int maxh = norm_maxh(dev);
1733
1734 fmt = format_by_fourcc(fsize->pixel_format);
1735 if (!fmt) {
1736 em28xx_videodbg("Fourcc format (%08x) invalid.\n",
1737 fsize->pixel_format);
1738 return -EINVAL;
1739 }
1740
1741 if (dev->board.is_em2800) {
1742 if (fsize->index > 1)
1743 return -EINVAL;
1744 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
1745 fsize->discrete.width = maxw / (1 + fsize->index);
1746 fsize->discrete.height = maxh / (1 + fsize->index);
1747 return 0;
1748 }
1749
1750 if (fsize->index != 0)
1751 return -EINVAL;
1752
1753 /* Report a continuous range */
1754 fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
Frank Schaefer6c3598e2013-02-10 16:05:14 -03001755 scale_to_size(dev, EM28XX_HVSCALE_MAX, EM28XX_HVSCALE_MAX,
1756 &fsize->stepwise.min_width, &fsize->stepwise.min_height);
1757 if (fsize->stepwise.min_width < 48)
1758 fsize->stepwise.min_width = 48;
1759 if (fsize->stepwise.min_height < 38)
1760 fsize->stepwise.min_height = 38;
Mauro Carvalho Chehab1c5c50682011-10-16 13:52:43 -02001761 fsize->stepwise.max_width = maxw;
1762 fsize->stepwise.max_height = maxh;
1763 fsize->stepwise.step_width = 1;
1764 fsize->stepwise.step_height = 1;
1765 return 0;
1766}
1767
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001768/* RAW VBI ioctls */
1769
1770static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
1771 struct v4l2_format *format)
1772{
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001773 struct em28xx_fh *fh = priv;
1774 struct em28xx *dev = fh->dev;
1775
1776 format->fmt.vbi.samples_per_line = dev->vbi_width;
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001777 format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
1778 format->fmt.vbi.offset = 0;
1779 format->fmt.vbi.flags = 0;
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001780 format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
1781 format->fmt.vbi.count[0] = dev->vbi_height;
1782 format->fmt.vbi.count[1] = dev->vbi_height;
Hans Verkuil2a221d32012-09-07 08:51:32 -03001783 memset(format->fmt.vbi.reserved, 0, sizeof(format->fmt.vbi.reserved));
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001784
1785 /* Varies by video standard (NTSC, PAL, etc.) */
Devin Heitmueller66d9cba2009-11-24 23:17:25 -03001786 if (dev->norm & V4L2_STD_525_60) {
1787 /* NTSC */
1788 format->fmt.vbi.start[0] = 10;
1789 format->fmt.vbi.start[1] = 273;
1790 } else if (dev->norm & V4L2_STD_625_50) {
1791 /* PAL */
1792 format->fmt.vbi.start[0] = 6;
1793 format->fmt.vbi.start[1] = 318;
1794 }
Devin Heitmueller28abf0832009-09-01 01:54:54 -03001795
1796 return 0;
1797}
1798
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001799/* ----------------------------------------------------------- */
1800/* RADIO ESPECIFIC IOCTLS */
1801/* ----------------------------------------------------------- */
1802
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001803static int radio_g_tuner(struct file *file, void *priv,
1804 struct v4l2_tuner *t)
1805{
1806 struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;
1807
1808 if (unlikely(t->index > 0))
1809 return -EINVAL;
1810
1811 strcpy(t->name, "Radio");
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001812
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03001813 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
Mauro Carvalho Chehabefc52a92008-12-16 22:04:56 -03001814
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001815 return 0;
1816}
1817
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001818static int radio_s_tuner(struct file *file, void *priv,
Hans Verkuil2f73c7c2013-03-15 06:10:06 -03001819 const struct v4l2_tuner *t)
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001820{
1821 struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;
1822
1823 if (0 != t->index)
1824 return -EINVAL;
1825
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03001826 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001827
1828 return 0;
1829}
1830
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001831/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08001832 * em28xx_v4l2_open()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001833 * inits the device and starts isoc transfer
1834 */
Hans Verkuilbec43662008-12-30 06:58:20 -03001835static int em28xx_v4l2_open(struct file *filp)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001836{
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001837 struct video_device *vdev = video_devdata(filp);
1838 struct em28xx *dev = video_drvdata(filp);
1839 enum v4l2_buf_type fh_type = 0;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001840 struct em28xx_fh *fh;
Markus Rechberger9c755412005-11-08 21:37:52 -08001841
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001842 switch (vdev->vfl_type) {
1843 case VFL_TYPE_GRABBER:
1844 fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1845 break;
1846 case VFL_TYPE_VBI:
1847 fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
1848 break;
Frank Schaefer4e170242014-01-12 13:24:18 -03001849 case VFL_TYPE_RADIO:
1850 break;
1851 default:
1852 return -EINVAL;
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001853 }
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03001854
Laurent Pinchart50462eb2009-12-10 11:47:13 -02001855 em28xx_videodbg("open dev=%s type=%s users=%d\n",
1856 video_device_node_name(vdev), v4l2_type_names[fh_type],
1857 dev->users);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001858
Hans Verkuil876cb142012-06-23 08:12:47 -03001859 if (mutex_lock_interruptible(&dev->lock))
1860 return -ERESTARTSYS;
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001861 fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001862 if (!fh) {
1863 em28xx_errdev("em28xx-video.c: Out of memory?!\n");
Hans Verkuil876cb142012-06-23 08:12:47 -03001864 mutex_unlock(&dev->lock);
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001865 return -ENOMEM;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001866 }
Hans Verkuil69a61642012-09-07 05:52:40 -03001867 v4l2_fh_init(&fh->fh, vdev);
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001868 fh->dev = dev;
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001869 fh->type = fh_type;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001870 filp->private_data = fh;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001871
Frank Schaefer4e170242014-01-12 13:24:18 -03001872 if (dev->users == 0) {
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001873 em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001874
Frank Schaefer4e170242014-01-12 13:24:18 -03001875 if (vdev->vfl_type != VFL_TYPE_RADIO)
1876 em28xx_resolution_set(dev);
1877
1878 /*
1879 * Needed, since GPIO might have disabled power
1880 * of some i2c devices
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001881 */
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03001882 em28xx_wake_i2c(dev);
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02001883 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001884
1885 if (vdev->vfl_type == VFL_TYPE_RADIO) {
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001886 em28xx_videodbg("video_open: setting radio device\n");
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03001887 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_radio);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001888 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001889
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03001890 kref_get(&dev->ref);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001891 dev->users++;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001892
Hans Verkuil876cb142012-06-23 08:12:47 -03001893 mutex_unlock(&dev->lock);
Hans Verkuil69a61642012-09-07 05:52:40 -03001894 v4l2_fh_add(&fh->fh);
Mauro Carvalho Chehabc67ec532008-04-17 21:48:00 -03001895
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001896 return 0;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001897}
1898
1899/*
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001900 * em28xx_v4l2_fini()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001901 * unregisters the v4l2,i2c and usb devices
1902 * called when the device gets disconected or at module unload
1903*/
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001904static int em28xx_v4l2_fini(struct em28xx *dev)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001905{
Mauro Carvalho Chehab822b8de2014-01-06 05:27:47 -03001906 if (dev->is_audio_only) {
1907 /* Shouldn't initialize IR for this interface */
1908 return 0;
1909 }
1910
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001911 if (!dev->has_video) {
1912 /* This device does not support the v4l2 extension */
1913 return 0;
1914 }
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02001915
Mauro Carvalho Chehabaa929ad2014-01-12 19:22:07 -03001916 em28xx_info("Closing video extension");
1917
Mauro Carvalho Chehabebbfbc22014-01-13 02:53:44 -03001918 mutex_lock(&dev->lock);
1919
Frank Schaefer5ad10de2014-01-12 13:24:21 -03001920 v4l2_device_disconnect(&dev->v4l2_dev);
1921
Frank Schaefer23e86422014-01-12 13:24:20 -03001922 em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
1923
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001924 if (dev->radio_dev) {
Frank Schaefere8470222014-01-12 13:24:25 -03001925 em28xx_info("V4L2 device %s deregistered\n",
1926 video_device_node_name(dev->radio_dev));
1927 video_unregister_device(dev->radio_dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001928 }
1929 if (dev->vbi_dev) {
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001930 em28xx_info("V4L2 device %s deregistered\n",
1931 video_device_node_name(dev->vbi_dev));
Frank Schaefere8470222014-01-12 13:24:25 -03001932 video_unregister_device(dev->vbi_dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001933 }
1934 if (dev->vdev) {
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001935 em28xx_info("V4L2 device %s deregistered\n",
1936 video_device_node_name(dev->vdev));
Frank Schaefere8470222014-01-12 13:24:25 -03001937 video_unregister_device(dev->vdev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001938 }
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001939
Frank Schaefer103f18a2014-01-17 14:45:30 -03001940 v4l2_ctrl_handler_free(&dev->ctrl_handler);
1941 v4l2_device_unregister(&dev->v4l2_dev);
1942
Frank Schaefer25dd1652014-01-12 13:24:23 -03001943 if (dev->clk) {
1944 v4l2_clk_unregister_fixed(dev->clk);
1945 dev->clk = NULL;
1946 }
1947
Mauro Carvalho Chehabebbfbc22014-01-13 02:53:44 -03001948 mutex_unlock(&dev->lock);
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03001949 kref_put(&dev->ref, em28xx_free_device);
Frank Schaefer5ad10de2014-01-12 13:24:21 -03001950
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001951 return 0;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001952}
1953
Shuah Khana61f6812014-02-21 21:50:17 -03001954static int em28xx_v4l2_suspend(struct em28xx *dev)
1955{
1956 if (dev->is_audio_only)
1957 return 0;
1958
1959 if (!dev->has_video)
1960 return 0;
1961
1962 em28xx_info("Suspending video extension");
1963 em28xx_stop_urbs(dev);
1964 return 0;
1965}
1966
1967static int em28xx_v4l2_resume(struct em28xx *dev)
1968{
1969 if (dev->is_audio_only)
1970 return 0;
1971
1972 if (!dev->has_video)
1973 return 0;
1974
1975 em28xx_info("Resuming video extension");
1976 /* what do we do here */
1977 return 0;
1978}
1979
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001980/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08001981 * em28xx_v4l2_close()
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03001982 * stops streaming and deallocates all resources allocated by the v4l2
1983 * calls and ioctls
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001984 */
Hans Verkuilbec43662008-12-30 06:58:20 -03001985static int em28xx_v4l2_close(struct file *filp)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001986{
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001987 struct em28xx_fh *fh = filp->private_data;
1988 struct em28xx *dev = fh->dev;
1989 int errCode;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001990
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001991 em28xx_videodbg("users=%d\n", dev->users);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001992
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03001993 vb2_fop_release(filp);
Ricardo Ribalda98c24dcd2013-11-06 05:39:35 -03001994 mutex_lock(&dev->lock);
Devin Heitmueller8c873d32009-09-03 00:23:27 -03001995
Devin Heitmuellere3ba4d32009-09-15 00:18:06 -03001996 if (dev->users == 1) {
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03001997 /* No sense to try to write to the device */
1998 if (dev->disconnected)
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03001999 goto exit;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03002000
Mauro Carvalho Chehabeb6c9632008-12-05 10:39:12 -03002001 /* Save some power by putting tuner to sleep */
Laurent Pinchart622b8282009-10-05 10:48:17 -03002002 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
Mauro Carvalho Chehabeb6c9632008-12-05 10:39:12 -03002003
Aidan Thorntond7aa8022008-04-13 14:38:47 -03002004 /* do this before setting alternate! */
Mauro Carvalho Chehab2fe3e2e2008-11-27 09:10:40 -03002005 em28xx_set_mode(dev, EM28XX_SUSPEND);
Aidan Thorntond7aa8022008-04-13 14:38:47 -03002006
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03002007 /* set alternate 0 */
2008 dev->alt = 0;
2009 em28xx_videodbg("setting alternate 0\n");
2010 errCode = usb_set_interface(dev->udev, 0, 0);
2011 if (errCode < 0) {
2012 em28xx_errdev("cannot change alternate number to "
2013 "0 (error=%i)\n", errCode);
2014 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002015 }
Devin Heitmueller28abf0832009-09-01 01:54:54 -03002016
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002017exit:
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002018 dev->users--;
Hans Verkuil876cb142012-06-23 08:12:47 -03002019 mutex_unlock(&dev->lock);
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002020 kref_put(&dev->ref, em28xx_free_device);
2021
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002022 return 0;
2023}
2024
Frank Schaefere8470222014-01-12 13:24:25 -03002025/*
2026 * em28xx_videodevice_release()
2027 * called when the last user of the video device exits and frees the memeory
2028 */
2029static void em28xx_videodevice_release(struct video_device *vdev)
2030{
2031 struct em28xx *dev = video_get_drvdata(vdev);
2032
2033 video_device_release(vdev);
2034 if (vdev == dev->vdev)
2035 dev->vdev = NULL;
2036 else if (vdev == dev->vbi_dev)
2037 dev->vbi_dev = NULL;
2038 else if (vdev == dev->radio_dev)
2039 dev->radio_dev = NULL;
2040}
2041
Hans Verkuilbec43662008-12-30 06:58:20 -03002042static const struct v4l2_file_operations em28xx_v4l_fops = {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002043 .owner = THIS_MODULE,
2044 .open = em28xx_v4l2_open,
2045 .release = em28xx_v4l2_close,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002046 .read = vb2_fop_read,
2047 .poll = vb2_fop_poll,
2048 .mmap = vb2_fop_mmap,
Hans Verkuil0499a5a2010-09-26 07:34:45 -03002049 .unlocked_ioctl = video_ioctl2,
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002050};
2051
Hans Verkuila3998102008-07-21 02:57:38 -03002052static const struct v4l2_ioctl_ops video_ioctl_ops = {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002053 .vidioc_querycap = vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03002054 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
2055 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
2056 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
2057 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Devin Heitmueller28abf0832009-09-01 01:54:54 -03002058 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Hans Verkuil2a221d32012-09-07 08:51:32 -03002059 .vidioc_try_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Frank Schaeferaab34612013-02-07 13:39:16 -03002060 .vidioc_s_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Mauro Carvalho Chehab1c5c50682011-10-16 13:52:43 -02002061 .vidioc_enum_framesizes = vidioc_enum_framesizes,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002062 .vidioc_g_audio = vidioc_g_audio,
2063 .vidioc_s_audio = vidioc_s_audio,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002064
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002065 .vidioc_reqbufs = vb2_ioctl_reqbufs,
2066 .vidioc_create_bufs = vb2_ioctl_create_bufs,
2067 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
2068 .vidioc_querybuf = vb2_ioctl_querybuf,
2069 .vidioc_qbuf = vb2_ioctl_qbuf,
2070 .vidioc_dqbuf = vb2_ioctl_dqbuf,
2071
Devin Heitmueller19bf0032009-09-11 00:40:18 -03002072 .vidioc_g_std = vidioc_g_std,
Mauro Carvalho Chehabd56ae6f2011-10-04 09:53:00 -03002073 .vidioc_querystd = vidioc_querystd,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002074 .vidioc_s_std = vidioc_s_std,
Mauro Carvalho Chehabd96ecda2009-08-06 21:53:59 -03002075 .vidioc_g_parm = vidioc_g_parm,
2076 .vidioc_s_parm = vidioc_s_parm,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002077 .vidioc_enum_input = vidioc_enum_input,
2078 .vidioc_g_input = vidioc_g_input,
2079 .vidioc_s_input = vidioc_s_input,
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002080 .vidioc_streamon = vb2_ioctl_streamon,
2081 .vidioc_streamoff = vb2_ioctl_streamoff,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002082 .vidioc_g_tuner = vidioc_g_tuner,
2083 .vidioc_s_tuner = vidioc_s_tuner,
2084 .vidioc_g_frequency = vidioc_g_frequency,
2085 .vidioc_s_frequency = vidioc_s_frequency,
Hans Verkuil50fdf402012-09-07 06:10:12 -03002086 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
2087 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002088#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuil96b03d22013-04-06 06:16:58 -03002089 .vidioc_g_chip_info = vidioc_g_chip_info,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002090 .vidioc_g_register = vidioc_g_register,
2091 .vidioc_s_register = vidioc_s_register,
2092#endif
Hans Verkuila3998102008-07-21 02:57:38 -03002093};
2094
2095static const struct video_device em28xx_video_template = {
Frank Schaefere8470222014-01-12 13:24:25 -03002096 .fops = &em28xx_v4l_fops,
2097 .ioctl_ops = &video_ioctl_ops,
2098 .release = em28xx_videodevice_release,
2099 .tvnorms = V4L2_STD_ALL,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002100};
2101
Hans Verkuilbec43662008-12-30 06:58:20 -03002102static const struct v4l2_file_operations radio_fops = {
Hans Verkuila3998102008-07-21 02:57:38 -03002103 .owner = THIS_MODULE,
2104 .open = em28xx_v4l2_open,
2105 .release = em28xx_v4l2_close,
Hans Verkuil8fd0bda2010-12-18 09:59:51 -03002106 .unlocked_ioctl = video_ioctl2,
Hans Verkuila3998102008-07-21 02:57:38 -03002107};
2108
2109static const struct v4l2_ioctl_ops radio_ioctl_ops = {
Hans Verkuila9d79fe2012-09-06 07:31:04 -03002110 .vidioc_querycap = vidioc_querycap,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002111 .vidioc_g_tuner = radio_g_tuner,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002112 .vidioc_s_tuner = radio_s_tuner,
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002113 .vidioc_g_frequency = vidioc_g_frequency,
2114 .vidioc_s_frequency = vidioc_s_frequency,
Hans Verkuil50fdf402012-09-07 06:10:12 -03002115 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
2116 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002117#ifdef CONFIG_VIDEO_ADV_DEBUG
Michal Marek430c73f2013-04-16 08:06:30 -03002118 .vidioc_g_chip_info = vidioc_g_chip_info,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002119 .vidioc_g_register = vidioc_g_register,
2120 .vidioc_s_register = vidioc_s_register,
2121#endif
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002122};
2123
Hans Verkuila3998102008-07-21 02:57:38 -03002124static struct video_device em28xx_radio_template = {
Frank Schaefere8470222014-01-12 13:24:25 -03002125 .fops = &radio_fops,
2126 .ioctl_ops = &radio_ioctl_ops,
2127 .release = em28xx_videodevice_release,
Hans Verkuila3998102008-07-21 02:57:38 -03002128};
2129
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002130/* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */
2131static unsigned short saa711x_addrs[] = {
2132 0x4a >> 1, 0x48 >> 1, /* SAA7111, SAA7111A and SAA7113 */
2133 0x42 >> 1, 0x40 >> 1, /* SAA7114, SAA7115 and SAA7118 */
2134 I2C_CLIENT_END };
2135
2136static unsigned short tvp5150_addrs[] = {
2137 0xb8 >> 1,
2138 0xba >> 1,
2139 I2C_CLIENT_END
2140};
2141
2142static unsigned short msp3400_addrs[] = {
2143 0x80 >> 1,
2144 0x88 >> 1,
2145 I2C_CLIENT_END
2146};
2147
Douglas Schilling Landgraf6ea54d92008-04-17 21:41:10 -03002148/******************************** usb interface ******************************/
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002149
Adrian Bunk532fe652008-01-28 22:10:48 -03002150static struct video_device *em28xx_vdev_init(struct em28xx *dev,
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -03002151 const struct video_device *template,
2152 const char *type_name)
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002153{
2154 struct video_device *vfd;
2155
2156 vfd = video_device_alloc();
2157 if (NULL == vfd)
2158 return NULL;
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03002159
2160 *vfd = *template;
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03002161 vfd->v4l2_dev = &dev->v4l2_dev;
Douglas Schilling Landgraff2cf2502009-03-31 17:10:58 -03002162 vfd->debug = video_debug;
Hans Verkuil0499a5a2010-09-26 07:34:45 -03002163 vfd->lock = &dev->lock;
Hans Verkuil69a61642012-09-07 05:52:40 -03002164 set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
Hans Verkuild8c95c02012-09-07 07:31:54 -03002165 if (dev->board.is_webcam)
2166 vfd->tvnorms = 0;
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002167
2168 snprintf(vfd->name, sizeof(vfd->name), "%s %s",
2169 dev->name, type_name);
2170
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02002171 video_set_drvdata(vfd, dev);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002172 return vfd;
2173}
2174
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002175static void em28xx_tuner_setup(struct em28xx *dev)
Mauro Carvalho Chehab0560f332013-12-22 15:28:26 -03002176{
2177 struct tuner_setup tun_setup;
2178 struct v4l2_frequency f;
2179
2180 if (dev->tuner_type == TUNER_ABSENT)
2181 return;
2182
2183 memset(&tun_setup, 0, sizeof(tun_setup));
2184
2185 tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
2186 tun_setup.tuner_callback = em28xx_tuner_callback;
2187
2188 if (dev->board.radio.type) {
2189 tun_setup.type = dev->board.radio.type;
2190 tun_setup.addr = dev->board.radio_addr;
2191
2192 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup);
2193 }
2194
2195 if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type)) {
2196 tun_setup.type = dev->tuner_type;
2197 tun_setup.addr = dev->tuner_addr;
2198
2199 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup);
2200 }
2201
2202 if (dev->tda9887_conf) {
2203 struct v4l2_priv_tun_config tda9887_cfg;
2204
2205 tda9887_cfg.tuner = TUNER_TDA9887;
2206 tda9887_cfg.priv = &dev->tda9887_conf;
2207
2208 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, &tda9887_cfg);
2209 }
2210
2211 if (dev->tuner_type == TUNER_XC2028) {
2212 struct v4l2_priv_tun_config xc2028_cfg;
2213 struct xc2028_ctrl ctl;
2214
2215 memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
2216 memset(&ctl, 0, sizeof(ctl));
2217
2218 em28xx_setup_xc3028(dev, &ctl);
2219
2220 xc2028_cfg.tuner = TUNER_XC2028;
2221 xc2028_cfg.priv = &ctl;
2222
2223 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, &xc2028_cfg);
2224 }
2225
2226 /* configure tuner */
2227 f.tuner = 0;
2228 f.type = V4L2_TUNER_ANALOG_TV;
2229 f.frequency = 9076; /* just a magic number */
2230 dev->ctl_freq = f.frequency;
2231 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
2232}
2233
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002234static int em28xx_v4l2_init(struct em28xx *dev)
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002235{
Hans Verkuil081b9452012-09-07 05:43:59 -03002236 u8 val;
Mauro Carvalho Chehab2e5ef2d2008-12-28 22:26:36 -03002237 int ret;
Sascha Sommer1020d132012-01-08 16:54:28 -03002238 unsigned int maxw;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002239 struct v4l2_ctrl_handler *hdl = &dev->ctrl_handler;
2240
Mauro Carvalho Chehab822b8de2014-01-06 05:27:47 -03002241 if (dev->is_audio_only) {
2242 /* Shouldn't initialize IR for this interface */
2243 return 0;
2244 }
2245
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002246 if (!dev->has_video) {
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002247 /* This device does not support the v4l2 extension */
2248 return 0;
2249 }
Mauro Carvalho Chehab2e5ef2d2008-12-28 22:26:36 -03002250
Mauro Carvalho Chehab96346142013-12-26 12:41:03 -03002251 em28xx_info("Registering V4L2 extension\n");
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002252
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002253 mutex_lock(&dev->lock);
2254
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002255 ret = v4l2_device_register(&dev->udev->dev, &dev->v4l2_dev);
2256 if (ret < 0) {
2257 em28xx_errdev("Call to v4l2_device_register() failed!\n");
2258 goto err;
2259 }
2260
2261 v4l2_ctrl_handler_init(hdl, 8);
2262 dev->v4l2_dev.ctrl_handler = hdl;
2263
2264 /*
2265 * Default format, used for tvp5150 or saa711x output formats
2266 */
2267 dev->vinmode = 0x10;
2268 dev->vinctl = EM28XX_VINCTRL_INTERLACED |
2269 EM28XX_VINCTRL_CCIR656_ENABLE;
2270
2271 /* request some modules */
2272
2273 if (dev->board.has_msp34xx)
2274 v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap[dev->def_i2c_bus],
2275 "msp3400", 0, msp3400_addrs);
2276
2277 if (dev->board.decoder == EM28XX_SAA711X)
2278 v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap[dev->def_i2c_bus],
2279 "saa7115_auto", 0, saa711x_addrs);
2280
2281 if (dev->board.decoder == EM28XX_TVP5150)
2282 v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap[dev->def_i2c_bus],
2283 "tvp5150", 0, tvp5150_addrs);
2284
2285 if (dev->board.adecoder == EM28XX_TVAUDIO)
2286 v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap[dev->def_i2c_bus],
2287 "tvaudio", dev->board.tvaudio_addr, NULL);
2288
2289 /* Initialize tuner and camera */
2290
2291 if (dev->board.tuner_type != TUNER_ABSENT) {
2292 int has_demod = (dev->tda9887_conf & TDA9887_PRESENT);
2293
2294 if (dev->board.radio.type)
2295 v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap[dev->def_i2c_bus],
2296 "tuner", dev->board.radio_addr, NULL);
2297
2298 if (has_demod)
2299 v4l2_i2c_new_subdev(&dev->v4l2_dev,
2300 &dev->i2c_adap[dev->def_i2c_bus], "tuner",
2301 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
2302 if (dev->tuner_addr == 0) {
2303 enum v4l2_i2c_tuner_type type =
2304 has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV;
2305 struct v4l2_subdev *sd;
2306
2307 sd = v4l2_i2c_new_subdev(&dev->v4l2_dev,
2308 &dev->i2c_adap[dev->def_i2c_bus], "tuner",
2309 0, v4l2_i2c_tuner_addrs(type));
2310
2311 if (sd)
2312 dev->tuner_addr = v4l2_i2c_subdev_addr(sd);
2313 } else {
2314 v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap[dev->def_i2c_bus],
2315 "tuner", dev->tuner_addr, NULL);
2316 }
2317 }
2318
2319 em28xx_tuner_setup(dev);
Frank Schaeferd86bc652014-01-17 14:45:32 -03002320 if (dev->em28xx_sensor != EM28XX_NOSENSOR)
2321 em28xx_init_camera(dev);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002322
2323 /* Configure audio */
2324 ret = em28xx_audio_setup(dev);
2325 if (ret < 0) {
2326 em28xx_errdev("%s: Error while setting audio - error [%d]!\n",
2327 __func__, ret);
2328 goto unregister_dev;
2329 }
2330 if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
2331 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
2332 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
2333 v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
2334 V4L2_CID_AUDIO_VOLUME, 0, 0x1f, 1, 0x1f);
2335 } else {
2336 /* install the em28xx notify callback */
2337 v4l2_ctrl_notify(v4l2_ctrl_find(hdl, V4L2_CID_AUDIO_MUTE),
2338 em28xx_ctrl_notify, dev);
2339 v4l2_ctrl_notify(v4l2_ctrl_find(hdl, V4L2_CID_AUDIO_VOLUME),
2340 em28xx_ctrl_notify, dev);
2341 }
2342
2343 /* wake i2c devices */
2344 em28xx_wake_i2c(dev);
2345
2346 /* init video dma queues */
2347 INIT_LIST_HEAD(&dev->vidq.active);
2348 INIT_LIST_HEAD(&dev->vbiq.active);
2349
2350 if (dev->board.has_msp34xx) {
2351 /* Send a reset to other chips via gpio */
2352 ret = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xf7);
2353 if (ret < 0) {
2354 em28xx_errdev("%s: em28xx_write_reg - msp34xx(1) failed! error [%d]\n",
2355 __func__, ret);
2356 goto unregister_dev;
2357 }
2358 msleep(3);
2359
2360 ret = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xff);
2361 if (ret < 0) {
2362 em28xx_errdev("%s: em28xx_write_reg - msp34xx(2) failed! error [%d]\n",
2363 __func__, ret);
2364 goto unregister_dev;
2365 }
2366 msleep(3);
2367 }
2368
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002369 /* set default norm */
Hans Verkuild8c95c02012-09-07 07:31:54 -03002370 dev->norm = V4L2_STD_PAL;
Hans Verkuild5906dd2010-09-26 07:45:15 -03002371 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm);
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002372 dev->interlaced = EM28XX_INTERLACED_DEFAULT;
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002373
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002374 /* Analog specific initialization */
2375 dev->format = &format[0];
Sascha Sommer1020d132012-01-08 16:54:28 -03002376
2377 maxw = norm_maxw(dev);
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002378 /* MaxPacketSize for em2800 is too small to capture at full resolution
2379 * use half of maxw as the scaler can only scale to 50% */
2380 if (dev->board.is_em2800)
2381 maxw /= 2;
Sascha Sommer1020d132012-01-08 16:54:28 -03002382
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03002383 em28xx_set_video_format(dev, format[0].fourcc,
Sascha Sommer1020d132012-01-08 16:54:28 -03002384 maxw, norm_maxh(dev));
Mauro Carvalho Chehabed5f1432009-07-02 17:34:04 -03002385
Ezequiel García96371fc2012-03-23 18:09:34 -03002386 video_mux(dev, 0);
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002387
2388 /* Audio defaults */
2389 dev->mute = 1;
2390 dev->volume = 0x1f;
2391
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002392/* em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -03002393 val = (u8)em28xx_read_reg(dev, EM28XX_R0F_XCLK);
2394 em28xx_write_reg(dev, EM28XX_R0F_XCLK,
2395 (EM28XX_XCLK_AUDIO_UNMUTE | val));
Mauro Carvalho Chehab24c3c412009-01-07 22:49:25 -03002396
2397 em28xx_set_outfmt(dev);
Mauro Carvalho Chehab1a23f812008-12-28 22:18:14 -03002398
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002399 /* Add image controls */
2400 /* NOTE: at this point, the subdevices are already registered, so bridge
2401 * controls are only added/enabled when no subdevice provides them */
2402 if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_CONTRAST))
2403 v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops,
2404 V4L2_CID_CONTRAST,
2405 0, 0x1f, 1, CONTRAST_DEFAULT);
2406 if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_BRIGHTNESS))
2407 v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops,
2408 V4L2_CID_BRIGHTNESS,
2409 -0x80, 0x7f, 1, BRIGHTNESS_DEFAULT);
2410 if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_SATURATION))
2411 v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops,
2412 V4L2_CID_SATURATION,
2413 0, 0x1f, 1, SATURATION_DEFAULT);
2414 if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_BLUE_BALANCE))
2415 v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops,
2416 V4L2_CID_BLUE_BALANCE,
2417 -0x30, 0x30, 1, BLUE_BALANCE_DEFAULT);
2418 if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_RED_BALANCE))
2419 v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops,
2420 V4L2_CID_RED_BALANCE,
2421 -0x30, 0x30, 1, RED_BALANCE_DEFAULT);
2422 if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_SHARPNESS))
2423 v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops,
2424 V4L2_CID_SHARPNESS,
2425 0, 0x0f, 1, SHARPNESS_DEFAULT);
2426
2427 /* Reset image controls */
2428 em28xx_colorlevels_set_default(dev);
2429 v4l2_ctrl_handler_setup(&dev->ctrl_handler);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002430 ret = dev->ctrl_handler.error;
2431 if (ret)
2432 goto unregister_dev;
Frank Schaefer8f8b113a2013-02-15 14:38:32 -03002433
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002434 /* allocate and fill video video_device struct */
2435 dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video");
2436 if (!dev->vdev) {
2437 em28xx_errdev("cannot allocate video_device.\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002438 ret = -ENODEV;
2439 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002440 }
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002441 dev->vdev->queue = &dev->vb_vidq;
2442 dev->vdev->queue->lock = &dev->vb_queue_lock;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002443
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002444 /* disable inapplicable ioctls */
2445 if (dev->board.is_webcam) {
2446 v4l2_disable_ioctl(dev->vdev, VIDIOC_QUERYSTD);
2447 v4l2_disable_ioctl(dev->vdev, VIDIOC_G_STD);
2448 v4l2_disable_ioctl(dev->vdev, VIDIOC_S_STD);
Frank Schaefer3bc85cc2013-02-07 13:39:12 -03002449 } else {
2450 v4l2_disable_ioctl(dev->vdev, VIDIOC_S_PARM);
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002451 }
Frank Schaefer66df67b2013-02-07 13:39:10 -03002452 if (dev->tuner_type == TUNER_ABSENT) {
2453 v4l2_disable_ioctl(dev->vdev, VIDIOC_G_TUNER);
2454 v4l2_disable_ioctl(dev->vdev, VIDIOC_S_TUNER);
2455 v4l2_disable_ioctl(dev->vdev, VIDIOC_G_FREQUENCY);
2456 v4l2_disable_ioctl(dev->vdev, VIDIOC_S_FREQUENCY);
2457 }
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002458 if (!dev->audio_mode.has_audio) {
2459 v4l2_disable_ioctl(dev->vdev, VIDIOC_G_AUDIO);
2460 v4l2_disable_ioctl(dev->vdev, VIDIOC_S_AUDIO);
2461 }
Frank Schaefer6e46dab2013-02-07 13:39:09 -03002462
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002463 /* register v4l2 video video_device */
2464 ret = video_register_device(dev->vdev, VFL_TYPE_GRABBER,
2465 video_nr[dev->devno]);
2466 if (ret) {
2467 em28xx_errdev("unable to register video device (error=%i).\n",
2468 ret);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002469 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002470 }
2471
2472 /* Allocate and fill vbi video_device struct */
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002473 if (em28xx_vbi_supported(dev) == 1) {
2474 dev->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template,
2475 "vbi");
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002476
Devin Heitmuellerd3829fa2013-01-04 16:16:24 -03002477 dev->vbi_dev->queue = &dev->vb_vbiq;
2478 dev->vbi_dev->queue->lock = &dev->vb_vbi_queue_lock;
2479
Frank Schaefer66df67b2013-02-07 13:39:10 -03002480 /* disable inapplicable ioctls */
Frank Schaefer83c8bcc2013-02-07 13:39:13 -03002481 v4l2_disable_ioctl(dev->vdev, VIDIOC_S_PARM);
Frank Schaefer66df67b2013-02-07 13:39:10 -03002482 if (dev->tuner_type == TUNER_ABSENT) {
2483 v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_G_TUNER);
2484 v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_S_TUNER);
2485 v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_G_FREQUENCY);
2486 v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_S_FREQUENCY);
2487 }
Frank Schaeferc2dcef82013-02-07 13:39:11 -03002488 if (!dev->audio_mode.has_audio) {
2489 v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_G_AUDIO);
2490 v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_S_AUDIO);
2491 }
Frank Schaefer66df67b2013-02-07 13:39:10 -03002492
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002493 /* register v4l2 vbi video_device */
2494 ret = video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
2495 vbi_nr[dev->devno]);
2496 if (ret < 0) {
2497 em28xx_errdev("unable to register vbi device\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002498 goto unregister_dev;
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002499 }
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002500 }
2501
2502 if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) {
Nicola Soranzoa1a6ee72009-02-10 23:28:24 -03002503 dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template,
2504 "radio");
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002505 if (!dev->radio_dev) {
2506 em28xx_errdev("cannot allocate video_device.\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002507 ret = -ENODEV;
2508 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002509 }
2510 ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO,
2511 radio_nr[dev->devno]);
2512 if (ret < 0) {
2513 em28xx_errdev("can't register radio device\n");
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002514 goto unregister_dev;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002515 }
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002516 em28xx_info("Registered radio device as %s\n",
2517 video_device_node_name(dev->radio_dev));
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002518 }
2519
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002520 em28xx_info("V4L2 video device registered as %s\n",
2521 video_device_node_name(dev->vdev));
Devin Heitmueller290c0cf2009-09-11 00:01:06 -03002522
2523 if (dev->vbi_dev)
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002524 em28xx_info("V4L2 VBI device registered as %s\n",
2525 video_device_node_name(dev->vbi_dev));
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002526
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002527 /* Save some power by putting tuner to sleep */
2528 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
2529
2530 /* initialize videobuf2 stuff */
2531 em28xx_vb2_setup(dev);
2532
Mauro Carvalho Chehab96346142013-12-26 12:41:03 -03002533 em28xx_info("V4L2 extension successfully initialized\n");
2534
Mauro Carvalho Chehab47677e52014-03-05 11:21:07 -03002535 kref_get(&dev->ref);
2536
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002537 mutex_unlock(&dev->lock);
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002538 return 0;
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002539
2540unregister_dev:
2541 v4l2_ctrl_handler_free(&dev->ctrl_handler);
2542 v4l2_device_unregister(&dev->v4l2_dev);
2543err:
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002544 mutex_unlock(&dev->lock);
Mauro Carvalho Chehabb64f8e92013-12-22 13:16:49 -03002545 return ret;
Mauro Carvalho Chehab818a5572008-11-20 10:30:26 -03002546}
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002547
2548static struct em28xx_ops v4l2_ops = {
2549 .id = EM28XX_V4L2,
2550 .name = "Em28xx v4l2 Extension",
2551 .init = em28xx_v4l2_init,
2552 .fini = em28xx_v4l2_fini,
Shuah Khana61f6812014-02-21 21:50:17 -03002553 .suspend = em28xx_v4l2_suspend,
2554 .resume = em28xx_v4l2_resume,
Mauro Carvalho Chehab01c28192013-12-22 13:27:02 -03002555};
2556
2557static int __init em28xx_video_register(void)
2558{
2559 return em28xx_register_extension(&v4l2_ops);
2560}
2561
2562static void __exit em28xx_video_unregister(void)
2563{
2564 em28xx_unregister_extension(&v4l2_ops);
2565}
2566
2567module_init(em28xx_video_register);
2568module_exit(em28xx_video_unregister);