blob: 8e0a44d03fc483e6a9611a3f2fdc7a2b490cdff1 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002
3 bttv - Bt848 frame grabber driver
4
5 Copyright (C) 1996,97,98 Ralph Metzler <rjkm@thp.uni-koeln.de>
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08006 & Marcus Metzler <mocm@thp.uni-koeln.de>
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 (c) 1999-2002 Gerd Knorr <kraxel@bytesex.org>
8
9 some v4l2 code lines are taken from Justin's bttv2 driver which is
10 (c) 2000 Justin Schoeman <justin@suntiger.ee.up.ac.za>
11
Nickolay V. Shmyreve84619b2007-10-26 11:01:08 -030012 V4L1 removal from:
13 (c) 2005-2006 Nickolay V. Shmyrev <nshmyrev@yandex.ru>
14
Mauro Carvalho Chehabc96dd072007-10-26 16:51:47 -030015 Fixes to be fully V4L2 compliant by
16 (c) 2006 Mauro Carvalho Chehab <mchehab@infradead.org>
17
Michael Schimeke5bd0262007-01-18 16:17:39 -030018 Cropping and overscan support
19 Copyright (C) 2005, 2006 Michael H. Schimek <mschimek@gmx.at>
20 Sponsored by OPQ Systems AB
21
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 This program is free software; you can redistribute it and/or modify
23 it under the terms of the GNU General Public License as published by
24 the Free Software Foundation; either version 2 of the License, or
25 (at your option) any later version.
26
27 This program is distributed in the hope that it will be useful,
28 but WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 GNU General Public License for more details.
31
32 You should have received a copy of the GNU General Public License
33 along with this program; if not, write to the Free Software
34 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35*/
36
Joe Perches8af443e2011-08-21 19:56:48 -030037#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
38
Linus Torvalds1da177e2005-04-16 15:20:36 -070039#include <linux/init.h>
40#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <linux/delay.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090042#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/errno.h>
44#include <linux/fs.h>
45#include <linux/kernel.h>
46#include <linux/sched.h>
47#include <linux/interrupt.h>
48#include <linux/kdev_t.h>
Mauro Carvalho Chehabb5b8ab82006-01-09 15:25:20 -020049#include "bttvp.h"
Michael Krufky5e453dc2006-01-09 15:32:31 -020050#include <media/v4l2-common.h>
Hans Verkuil35ea11f2008-07-20 08:12:02 -030051#include <media/v4l2-ioctl.h>
Hans Verkuil1b9e94d2012-09-09 09:23:31 -030052#include <media/v4l2-chip-ident.h>
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -030053#include <media/tvaudio.h>
Hans Verkuil2474ed42006-03-19 12:35:57 -030054#include <media/msp3400.h>
Mauro Carvalho Chehabb5b8ab82006-01-09 15:25:20 -020055
Mauro Carvalho Chehabfa9846a2005-07-12 13:58:42 -070056#include <linux/dma-mapping.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070057
58#include <asm/io.h>
59#include <asm/byteorder.h>
60
Hans Verkuilb9218f22010-12-27 12:22:46 -030061#include <media/saa6588.h>
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -070062
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -030063#define BTTV_VERSION "0.9.19"
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -070064
Linus Torvalds1da177e2005-04-16 15:20:36 -070065unsigned int bttv_num; /* number of Bt848s in use */
Trent Piepho4b10d3b2009-01-28 21:32:59 -030066struct bttv *bttvs[BTTV_MAX];
Linus Torvalds1da177e2005-04-16 15:20:36 -070067
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020068unsigned int bttv_debug;
Linus Torvalds1da177e2005-04-16 15:20:36 -070069unsigned int bttv_verbose = 1;
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020070unsigned int bttv_gpio;
Linus Torvalds1da177e2005-04-16 15:20:36 -070071
72/* config variables */
73#ifdef __BIG_ENDIAN
74static unsigned int bigendian=1;
75#else
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020076static unsigned int bigendian;
Linus Torvalds1da177e2005-04-16 15:20:36 -070077#endif
78static unsigned int radio[BTTV_MAX];
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020079static unsigned int irq_debug;
Linus Torvalds1da177e2005-04-16 15:20:36 -070080static unsigned int gbuffers = 8;
81static unsigned int gbufsize = 0x208000;
Michael Schimeke5bd0262007-01-18 16:17:39 -030082static unsigned int reset_crop = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -070083
Jean Delvare176c2f32008-09-07 12:49:59 -030084static int video_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
85static int radio_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
86static int vbi_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020087static int debug_latency;
Jean Delvared90a4ae2010-02-16 14:22:37 -030088static int disable_ir;
Linus Torvalds1da177e2005-04-16 15:20:36 -070089
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020090static unsigned int fdsr;
Linus Torvalds1da177e2005-04-16 15:20:36 -070091
92/* options */
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020093static unsigned int combfilter;
94static unsigned int lumafilter;
Linus Torvalds1da177e2005-04-16 15:20:36 -070095static unsigned int automute = 1;
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020096static unsigned int chroma_agc;
Hans Verkuil01df5302013-02-06 12:40:28 -030097static unsigned int agc_crush = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -070098static unsigned int whitecrush_upper = 0xCF;
99static unsigned int whitecrush_lower = 0x7F;
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -0200100static unsigned int vcr_hack;
101static unsigned int irq_iswitch;
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700102static unsigned int uv_ratio = 50;
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -0200103static unsigned int full_luma_range;
104static unsigned int coring;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105
106/* API features (turn on/off stuff for testing) */
107static unsigned int v4l2 = 1;
108
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109/* insmod args */
110module_param(bttv_verbose, int, 0644);
111module_param(bttv_gpio, int, 0644);
112module_param(bttv_debug, int, 0644);
113module_param(irq_debug, int, 0644);
114module_param(debug_latency, int, 0644);
Jean Delvared90a4ae2010-02-16 14:22:37 -0300115module_param(disable_ir, int, 0444);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116
117module_param(fdsr, int, 0444);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118module_param(gbuffers, int, 0444);
119module_param(gbufsize, int, 0444);
Michael Schimeke5bd0262007-01-18 16:17:39 -0300120module_param(reset_crop, int, 0444);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121
122module_param(v4l2, int, 0644);
123module_param(bigendian, int, 0644);
124module_param(irq_iswitch, int, 0644);
125module_param(combfilter, int, 0444);
126module_param(lumafilter, int, 0444);
127module_param(automute, int, 0444);
128module_param(chroma_agc, int, 0444);
Hans Verkuil01df5302013-02-06 12:40:28 -0300129module_param(agc_crush, int, 0444);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130module_param(whitecrush_upper, int, 0444);
131module_param(whitecrush_lower, int, 0444);
132module_param(vcr_hack, int, 0444);
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700133module_param(uv_ratio, int, 0444);
134module_param(full_luma_range, int, 0444);
135module_param(coring, int, 0444);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136
Jean Delvare176c2f32008-09-07 12:49:59 -0300137module_param_array(radio, int, NULL, 0444);
138module_param_array(video_nr, int, NULL, 0444);
139module_param_array(radio_nr, int, NULL, 0444);
140module_param_array(vbi_nr, int, NULL, 0444);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141
Hans Verkuil01df5302013-02-06 12:40:28 -0300142MODULE_PARM_DESC(radio, "The TV card supports radio, default is 0 (no)");
143MODULE_PARM_DESC(bigendian, "byte order of the framebuffer, default is native endian");
144MODULE_PARM_DESC(bttv_verbose, "verbose startup messages, default is 1 (yes)");
145MODULE_PARM_DESC(bttv_gpio, "log gpio changes, default is 0 (no)");
146MODULE_PARM_DESC(bttv_debug, "debug messages, default is 0 (no)");
147MODULE_PARM_DESC(irq_debug, "irq handler debug messages, default is 0 (no)");
Jean Delvared90a4ae2010-02-16 14:22:37 -0300148MODULE_PARM_DESC(disable_ir, "disable infrared remote support");
Hans Verkuil01df5302013-02-06 12:40:28 -0300149MODULE_PARM_DESC(gbuffers, "number of capture buffers. range 2-32, default 8");
150MODULE_PARM_DESC(gbufsize, "size of the capture buffers, default is 0x208000");
151MODULE_PARM_DESC(reset_crop, "reset cropping parameters at open(), default "
Michael Schimeke5bd0262007-01-18 16:17:39 -0300152 "is 1 (yes) for compatibility with older applications");
Hans Verkuil01df5302013-02-06 12:40:28 -0300153MODULE_PARM_DESC(automute, "mute audio on bad/missing video signal, default is 1 (yes)");
154MODULE_PARM_DESC(chroma_agc, "enables the AGC of chroma signal, default is 0 (no)");
155MODULE_PARM_DESC(agc_crush, "enables the luminance AGC crush, default is 1 (yes)");
156MODULE_PARM_DESC(whitecrush_upper, "sets the white crush upper value, default is 207");
157MODULE_PARM_DESC(whitecrush_lower, "sets the white crush lower value, default is 127");
158MODULE_PARM_DESC(vcr_hack, "enables the VCR hack (improves synch on poor VCR tapes), default is 0 (no)");
159MODULE_PARM_DESC(irq_iswitch, "switch inputs in irq handler");
160MODULE_PARM_DESC(uv_ratio, "ratio between u and v gains, default is 50");
161MODULE_PARM_DESC(full_luma_range, "use the full luma range, default is 0 (no)");
162MODULE_PARM_DESC(coring, "set the luma coring level, default is 0 (no)");
Jean Delvare176c2f32008-09-07 12:49:59 -0300163MODULE_PARM_DESC(video_nr, "video device numbers");
164MODULE_PARM_DESC(vbi_nr, "vbi device numbers");
165MODULE_PARM_DESC(radio_nr, "radio device numbers");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166
167MODULE_DESCRIPTION("bttv - v4l/v4l2 driver module for bt848/878 based cards");
168MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr");
169MODULE_LICENSE("GPL");
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -0300170MODULE_VERSION(BTTV_VERSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171
Hans Verkuil01df5302013-02-06 12:40:28 -0300172#define V4L2_CID_PRIVATE_COMBFILTER (V4L2_CID_USER_BTTV_BASE + 0)
173#define V4L2_CID_PRIVATE_AUTOMUTE (V4L2_CID_USER_BTTV_BASE + 1)
174#define V4L2_CID_PRIVATE_LUMAFILTER (V4L2_CID_USER_BTTV_BASE + 2)
175#define V4L2_CID_PRIVATE_AGC_CRUSH (V4L2_CID_USER_BTTV_BASE + 3)
176#define V4L2_CID_PRIVATE_VCR_HACK (V4L2_CID_USER_BTTV_BASE + 4)
177#define V4L2_CID_PRIVATE_WHITECRUSH_LOWER (V4L2_CID_USER_BTTV_BASE + 5)
178#define V4L2_CID_PRIVATE_WHITECRUSH_UPPER (V4L2_CID_USER_BTTV_BASE + 6)
179#define V4L2_CID_PRIVATE_UV_RATIO (V4L2_CID_USER_BTTV_BASE + 7)
180#define V4L2_CID_PRIVATE_FULL_LUMA_RANGE (V4L2_CID_USER_BTTV_BASE + 8)
181#define V4L2_CID_PRIVATE_CORING (V4L2_CID_USER_BTTV_BASE + 9)
182
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183/* ----------------------------------------------------------------------- */
184/* sysfs */
185
Kay Sievers54bd5b62007-10-08 16:26:13 -0300186static ssize_t show_card(struct device *cd,
187 struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188{
Hans Verkuil22a04f12008-07-20 06:35:02 -0300189 struct video_device *vfd = container_of(cd, struct video_device, dev);
Hans Verkuil74fc7bd2009-03-14 12:36:54 -0300190 struct bttv *btv = video_get_drvdata(vfd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 return sprintf(buf, "%d\n", btv ? btv->c.type : UNSET);
192}
Kay Sievers54bd5b62007-10-08 16:26:13 -0300193static DEVICE_ATTR(card, S_IRUGO, show_card, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194
195/* ----------------------------------------------------------------------- */
Jarod Wilsonf992a492007-03-24 15:23:50 -0300196/* dvb auto-load setup */
197#if defined(CONFIG_MODULES) && defined(MODULE)
198static void request_module_async(struct work_struct *work)
199{
200 request_module("dvb-bt8xx");
201}
202
203static void request_modules(struct bttv *dev)
204{
205 INIT_WORK(&dev->request_module_wk, request_module_async);
206 schedule_work(&dev->request_module_wk);
207}
Tejun Heo707bcf32010-12-24 16:14:20 +0100208
209static void flush_request_modules(struct bttv *dev)
210{
Linus Torvalds0b8e74c2012-10-07 17:49:05 +0900211 flush_work(&dev->request_module_wk);
Tejun Heo707bcf32010-12-24 16:14:20 +0100212}
Jarod Wilsonf992a492007-03-24 15:23:50 -0300213#else
214#define request_modules(dev)
Mauro Carvalho Chehaba1fd2872012-10-27 16:33:41 -0300215#define flush_request_modules(dev) do {} while(0)
Jarod Wilsonf992a492007-03-24 15:23:50 -0300216#endif /* CONFIG_MODULES */
217
218
219/* ----------------------------------------------------------------------- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220/* static data */
221
222/* special timing tables from conexant... */
223static u8 SRAM_Table[][60] =
224{
225 /* PAL digital input over GPIO[7:0] */
226 {
227 45, // 45 bytes following
228 0x36,0x11,0x01,0x00,0x90,0x02,0x05,0x10,0x04,0x16,
229 0x12,0x05,0x11,0x00,0x04,0x12,0xC0,0x00,0x31,0x00,
230 0x06,0x51,0x08,0x03,0x89,0x08,0x07,0xC0,0x44,0x00,
231 0x81,0x01,0x01,0xA9,0x0D,0x02,0x02,0x50,0x03,0x37,
232 0x37,0x00,0xAF,0x21,0x00
233 },
234 /* NTSC digital input over GPIO[7:0] */
235 {
236 51, // 51 bytes following
237 0x0C,0xC0,0x00,0x00,0x90,0x02,0x03,0x10,0x03,0x06,
238 0x10,0x04,0x12,0x12,0x05,0x02,0x13,0x04,0x19,0x00,
239 0x04,0x39,0x00,0x06,0x59,0x08,0x03,0x83,0x08,0x07,
240 0x03,0x50,0x00,0xC0,0x40,0x00,0x86,0x01,0x01,0xA6,
241 0x0D,0x02,0x03,0x11,0x01,0x05,0x37,0x00,0xAC,0x21,
242 0x00,
243 },
244 // TGB_NTSC392 // quartzsight
245 // This table has been modified to be used for Fusion Rev D
246 {
247 0x2A, // size of table = 42
248 0x06, 0x08, 0x04, 0x0a, 0xc0, 0x00, 0x18, 0x08, 0x03, 0x24,
249 0x08, 0x07, 0x02, 0x90, 0x02, 0x08, 0x10, 0x04, 0x0c, 0x10,
250 0x05, 0x2c, 0x11, 0x04, 0x55, 0x48, 0x00, 0x05, 0x50, 0x00,
251 0xbf, 0x0c, 0x02, 0x2f, 0x3d, 0x00, 0x2f, 0x3f, 0x00, 0xc3,
252 0x20, 0x00
253 }
254};
255
Michael Schimeke5bd0262007-01-18 16:17:39 -0300256/* minhdelayx1 first video pixel we can capture on a line and
257 hdelayx1 start of active video, both relative to rising edge of
258 /HRESET pulse (0H) in 1 / fCLKx1.
259 swidth width of active video and
260 totalwidth total line width, both in 1 / fCLKx1.
261 sqwidth total line width in square pixels.
262 vdelay start of active video in 2 * field lines relative to
263 trailing edge of /VRESET pulse (VDELAY register).
264 sheight height of active video in 2 * field lines.
265 videostart0 ITU-R frame line number of the line corresponding
266 to vdelay in the first field. */
267#define CROPCAP(minhdelayx1, hdelayx1, swidth, totalwidth, sqwidth, \
268 vdelay, sheight, videostart0) \
269 .cropcap.bounds.left = minhdelayx1, \
270 /* * 2 because vertically we count field lines times two, */ \
271 /* e.g. 23 * 2 to 23 * 2 + 576 in PAL-BGHI defrect. */ \
272 .cropcap.bounds.top = (videostart0) * 2 - (vdelay) + MIN_VDELAY, \
273 /* 4 is a safety margin at the end of the line. */ \
274 .cropcap.bounds.width = (totalwidth) - (minhdelayx1) - 4, \
275 .cropcap.bounds.height = (sheight) + (vdelay) - MIN_VDELAY, \
276 .cropcap.defrect.left = hdelayx1, \
277 .cropcap.defrect.top = (videostart0) * 2, \
278 .cropcap.defrect.width = swidth, \
279 .cropcap.defrect.height = sheight, \
280 .cropcap.pixelaspect.numerator = totalwidth, \
281 .cropcap.pixelaspect.denominator = sqwidth,
282
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283const struct bttv_tvnorm bttv_tvnorms[] = {
284 /* PAL-BDGHI */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800285 /* max. active video is actually 922, but 924 is divisible by 4 and 3! */
286 /* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 {
288 .v4l2_id = V4L2_STD_PAL,
289 .name = "PAL",
290 .Fsc = 35468950,
291 .swidth = 924,
292 .sheight = 576,
293 .totalwidth = 1135,
294 .adelay = 0x7f,
295 .bdelay = 0x72,
296 .iform = (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
297 .scaledtwidth = 1135,
298 .hdelayx1 = 186,
299 .hactivex1 = 924,
300 .vdelay = 0x20,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300301 .vbipack = 255, /* min (2048 / 4, 0x1ff) & 0xff */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302 .sram = 0,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200303 /* ITU-R frame line number of the first VBI line
Michael Schimeke5bd0262007-01-18 16:17:39 -0300304 we can capture, of the first and second field.
305 The last line is determined by cropcap.bounds. */
306 .vbistart = { 7, 320 },
307 CROPCAP(/* minhdelayx1 */ 68,
308 /* hdelayx1 */ 186,
309 /* Should be (768 * 1135 + 944 / 2) / 944.
310 cropcap.defrect is used for image width
311 checks, so we keep the old value 924. */
312 /* swidth */ 924,
313 /* totalwidth */ 1135,
314 /* sqwidth */ 944,
315 /* vdelay */ 0x20,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300316 /* bt878 (and bt848?) can capture another
317 line below active video. */
Mauro Carvalho Chehaba1fd2872012-10-27 16:33:41 -0300318 /* sheight */ (576 + 2) + 0x20 - 2,
319 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 },{
Hans Verkuild97a11e2006-02-07 06:48:40 -0200321 .v4l2_id = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 .name = "NTSC",
323 .Fsc = 28636363,
324 .swidth = 768,
325 .sheight = 480,
326 .totalwidth = 910,
327 .adelay = 0x68,
328 .bdelay = 0x5d,
329 .iform = (BT848_IFORM_NTSC|BT848_IFORM_XT0),
330 .scaledtwidth = 910,
331 .hdelayx1 = 128,
332 .hactivex1 = 910,
333 .vdelay = 0x1a,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300334 .vbipack = 144, /* min (1600 / 4, 0x1ff) & 0xff */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335 .sram = 1,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200336 .vbistart = { 10, 273 },
Michael Schimeke5bd0262007-01-18 16:17:39 -0300337 CROPCAP(/* minhdelayx1 */ 68,
338 /* hdelayx1 */ 128,
339 /* Should be (640 * 910 + 780 / 2) / 780? */
340 /* swidth */ 768,
341 /* totalwidth */ 910,
342 /* sqwidth */ 780,
343 /* vdelay */ 0x1a,
344 /* sheight */ 480,
345 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346 },{
347 .v4l2_id = V4L2_STD_SECAM,
348 .name = "SECAM",
349 .Fsc = 35468950,
350 .swidth = 924,
351 .sheight = 576,
352 .totalwidth = 1135,
353 .adelay = 0x7f,
354 .bdelay = 0xb0,
355 .iform = (BT848_IFORM_SECAM|BT848_IFORM_XT1),
356 .scaledtwidth = 1135,
357 .hdelayx1 = 186,
358 .hactivex1 = 922,
359 .vdelay = 0x20,
360 .vbipack = 255,
361 .sram = 0, /* like PAL, correct? */
Michael H. Schimek67f15702006-01-09 15:25:27 -0200362 .vbistart = { 7, 320 },
Michael Schimeke5bd0262007-01-18 16:17:39 -0300363 CROPCAP(/* minhdelayx1 */ 68,
364 /* hdelayx1 */ 186,
365 /* swidth */ 924,
366 /* totalwidth */ 1135,
367 /* sqwidth */ 944,
368 /* vdelay */ 0x20,
369 /* sheight */ 576,
370 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 },{
372 .v4l2_id = V4L2_STD_PAL_Nc,
373 .name = "PAL-Nc",
374 .Fsc = 28636363,
375 .swidth = 640,
376 .sheight = 576,
377 .totalwidth = 910,
378 .adelay = 0x68,
379 .bdelay = 0x5d,
380 .iform = (BT848_IFORM_PAL_NC|BT848_IFORM_XT0),
381 .scaledtwidth = 780,
382 .hdelayx1 = 130,
383 .hactivex1 = 734,
384 .vdelay = 0x1a,
385 .vbipack = 144,
386 .sram = -1,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200387 .vbistart = { 7, 320 },
Michael Schimeke5bd0262007-01-18 16:17:39 -0300388 CROPCAP(/* minhdelayx1 */ 68,
389 /* hdelayx1 */ 130,
390 /* swidth */ (640 * 910 + 780 / 2) / 780,
391 /* totalwidth */ 910,
392 /* sqwidth */ 780,
393 /* vdelay */ 0x1a,
394 /* sheight */ 576,
395 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 },{
397 .v4l2_id = V4L2_STD_PAL_M,
398 .name = "PAL-M",
399 .Fsc = 28636363,
400 .swidth = 640,
401 .sheight = 480,
402 .totalwidth = 910,
403 .adelay = 0x68,
404 .bdelay = 0x5d,
405 .iform = (BT848_IFORM_PAL_M|BT848_IFORM_XT0),
406 .scaledtwidth = 780,
407 .hdelayx1 = 135,
408 .hactivex1 = 754,
409 .vdelay = 0x1a,
410 .vbipack = 144,
411 .sram = -1,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200412 .vbistart = { 10, 273 },
Michael Schimeke5bd0262007-01-18 16:17:39 -0300413 CROPCAP(/* minhdelayx1 */ 68,
414 /* hdelayx1 */ 135,
415 /* swidth */ (640 * 910 + 780 / 2) / 780,
416 /* totalwidth */ 910,
417 /* sqwidth */ 780,
418 /* vdelay */ 0x1a,
419 /* sheight */ 480,
420 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 },{
422 .v4l2_id = V4L2_STD_PAL_N,
423 .name = "PAL-N",
424 .Fsc = 35468950,
425 .swidth = 768,
426 .sheight = 576,
427 .totalwidth = 1135,
428 .adelay = 0x7f,
429 .bdelay = 0x72,
430 .iform = (BT848_IFORM_PAL_N|BT848_IFORM_XT1),
431 .scaledtwidth = 944,
432 .hdelayx1 = 186,
433 .hactivex1 = 922,
434 .vdelay = 0x20,
435 .vbipack = 144,
436 .sram = -1,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300437 .vbistart = { 7, 320 },
438 CROPCAP(/* minhdelayx1 */ 68,
439 /* hdelayx1 */ 186,
440 /* swidth */ (768 * 1135 + 944 / 2) / 944,
441 /* totalwidth */ 1135,
442 /* sqwidth */ 944,
443 /* vdelay */ 0x20,
444 /* sheight */ 576,
445 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446 },{
447 .v4l2_id = V4L2_STD_NTSC_M_JP,
448 .name = "NTSC-JP",
449 .Fsc = 28636363,
450 .swidth = 640,
451 .sheight = 480,
452 .totalwidth = 910,
453 .adelay = 0x68,
454 .bdelay = 0x5d,
455 .iform = (BT848_IFORM_NTSC_J|BT848_IFORM_XT0),
456 .scaledtwidth = 780,
457 .hdelayx1 = 135,
458 .hactivex1 = 754,
459 .vdelay = 0x16,
460 .vbipack = 144,
461 .sram = -1,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300462 .vbistart = { 10, 273 },
463 CROPCAP(/* minhdelayx1 */ 68,
464 /* hdelayx1 */ 135,
465 /* swidth */ (640 * 910 + 780 / 2) / 780,
466 /* totalwidth */ 910,
467 /* sqwidth */ 780,
468 /* vdelay */ 0x16,
469 /* sheight */ 480,
470 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 },{
472 /* that one hopefully works with the strange timing
473 * which video recorders produce when playing a NTSC
474 * tape on a PAL TV ... */
475 .v4l2_id = V4L2_STD_PAL_60,
476 .name = "PAL-60",
477 .Fsc = 35468950,
478 .swidth = 924,
479 .sheight = 480,
480 .totalwidth = 1135,
481 .adelay = 0x7f,
482 .bdelay = 0x72,
483 .iform = (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
484 .scaledtwidth = 1135,
485 .hdelayx1 = 186,
486 .hactivex1 = 924,
487 .vdelay = 0x1a,
488 .vbipack = 255,
489 .vtotal = 524,
490 .sram = -1,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200491 .vbistart = { 10, 273 },
Michael Schimeke5bd0262007-01-18 16:17:39 -0300492 CROPCAP(/* minhdelayx1 */ 68,
493 /* hdelayx1 */ 186,
494 /* swidth */ 924,
495 /* totalwidth */ 1135,
496 /* sqwidth */ 944,
497 /* vdelay */ 0x1a,
498 /* sheight */ 480,
499 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 }
501};
502static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms);
503
504/* ----------------------------------------------------------------------- */
505/* bttv format list
506 packed pixel formats must come first */
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -0300507static const struct bttv_format formats[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 {
509 .name = "8 bpp, gray",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 .fourcc = V4L2_PIX_FMT_GREY,
511 .btformat = BT848_COLOR_FMT_Y8,
512 .depth = 8,
513 .flags = FORMAT_FLAGS_PACKED,
514 },{
515 .name = "8 bpp, dithered color",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 .fourcc = V4L2_PIX_FMT_HI240,
517 .btformat = BT848_COLOR_FMT_RGB8,
518 .depth = 8,
519 .flags = FORMAT_FLAGS_PACKED | FORMAT_FLAGS_DITHER,
520 },{
521 .name = "15 bpp RGB, le",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 .fourcc = V4L2_PIX_FMT_RGB555,
523 .btformat = BT848_COLOR_FMT_RGB15,
524 .depth = 16,
525 .flags = FORMAT_FLAGS_PACKED,
526 },{
527 .name = "15 bpp RGB, be",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 .fourcc = V4L2_PIX_FMT_RGB555X,
529 .btformat = BT848_COLOR_FMT_RGB15,
530 .btswap = 0x03, /* byteswap */
531 .depth = 16,
532 .flags = FORMAT_FLAGS_PACKED,
533 },{
534 .name = "16 bpp RGB, le",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 .fourcc = V4L2_PIX_FMT_RGB565,
536 .btformat = BT848_COLOR_FMT_RGB16,
537 .depth = 16,
538 .flags = FORMAT_FLAGS_PACKED,
539 },{
540 .name = "16 bpp RGB, be",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 .fourcc = V4L2_PIX_FMT_RGB565X,
542 .btformat = BT848_COLOR_FMT_RGB16,
543 .btswap = 0x03, /* byteswap */
544 .depth = 16,
545 .flags = FORMAT_FLAGS_PACKED,
546 },{
547 .name = "24 bpp RGB, le",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 .fourcc = V4L2_PIX_FMT_BGR24,
549 .btformat = BT848_COLOR_FMT_RGB24,
550 .depth = 24,
551 .flags = FORMAT_FLAGS_PACKED,
552 },{
553 .name = "32 bpp RGB, le",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 .fourcc = V4L2_PIX_FMT_BGR32,
555 .btformat = BT848_COLOR_FMT_RGB32,
556 .depth = 32,
557 .flags = FORMAT_FLAGS_PACKED,
558 },{
559 .name = "32 bpp RGB, be",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 .fourcc = V4L2_PIX_FMT_RGB32,
561 .btformat = BT848_COLOR_FMT_RGB32,
562 .btswap = 0x0f, /* byte+word swap */
563 .depth = 32,
564 .flags = FORMAT_FLAGS_PACKED,
565 },{
566 .name = "4:2:2, packed, YUYV",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567 .fourcc = V4L2_PIX_FMT_YUYV,
568 .btformat = BT848_COLOR_FMT_YUY2,
569 .depth = 16,
570 .flags = FORMAT_FLAGS_PACKED,
571 },{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572 .name = "4:2:2, packed, UYVY",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 .fourcc = V4L2_PIX_FMT_UYVY,
574 .btformat = BT848_COLOR_FMT_YUY2,
575 .btswap = 0x03, /* byteswap */
576 .depth = 16,
577 .flags = FORMAT_FLAGS_PACKED,
578 },{
579 .name = "4:2:2, planar, Y-Cb-Cr",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 .fourcc = V4L2_PIX_FMT_YUV422P,
581 .btformat = BT848_COLOR_FMT_YCrCb422,
582 .depth = 16,
583 .flags = FORMAT_FLAGS_PLANAR,
584 .hshift = 1,
585 .vshift = 0,
586 },{
587 .name = "4:2:0, planar, Y-Cb-Cr",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 .fourcc = V4L2_PIX_FMT_YUV420,
589 .btformat = BT848_COLOR_FMT_YCrCb422,
590 .depth = 12,
591 .flags = FORMAT_FLAGS_PLANAR,
592 .hshift = 1,
593 .vshift = 1,
594 },{
595 .name = "4:2:0, planar, Y-Cr-Cb",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596 .fourcc = V4L2_PIX_FMT_YVU420,
597 .btformat = BT848_COLOR_FMT_YCrCb422,
598 .depth = 12,
599 .flags = FORMAT_FLAGS_PLANAR | FORMAT_FLAGS_CrCb,
600 .hshift = 1,
601 .vshift = 1,
602 },{
603 .name = "4:1:1, planar, Y-Cb-Cr",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 .fourcc = V4L2_PIX_FMT_YUV411P,
605 .btformat = BT848_COLOR_FMT_YCrCb411,
606 .depth = 12,
607 .flags = FORMAT_FLAGS_PLANAR,
608 .hshift = 2,
609 .vshift = 0,
610 },{
611 .name = "4:1:0, planar, Y-Cb-Cr",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612 .fourcc = V4L2_PIX_FMT_YUV410,
613 .btformat = BT848_COLOR_FMT_YCrCb411,
614 .depth = 9,
615 .flags = FORMAT_FLAGS_PLANAR,
616 .hshift = 2,
617 .vshift = 2,
618 },{
619 .name = "4:1:0, planar, Y-Cr-Cb",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 .fourcc = V4L2_PIX_FMT_YVU410,
621 .btformat = BT848_COLOR_FMT_YCrCb411,
622 .depth = 9,
623 .flags = FORMAT_FLAGS_PLANAR | FORMAT_FLAGS_CrCb,
624 .hshift = 2,
625 .vshift = 2,
626 },{
627 .name = "raw scanlines",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 .fourcc = -1,
629 .btformat = BT848_COLOR_FMT_RAW,
630 .depth = 8,
631 .flags = FORMAT_FLAGS_RAW,
632 }
633};
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -0300634static const unsigned int FORMATS = ARRAY_SIZE(formats);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635
636/* ----------------------------------------------------------------------- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637/* resource management */
638
Michael Schimeke5bd0262007-01-18 16:17:39 -0300639/*
640 RESOURCE_ allocated by freed by
641
642 VIDEO_READ bttv_read 1) bttv_read 2)
643
644 VIDEO_STREAM VIDIOC_STREAMON VIDIOC_STREAMOFF
645 VIDIOC_QBUF 1) bttv_release
646 VIDIOCMCAPTURE 1)
647
648 OVERLAY VIDIOCCAPTURE on VIDIOCCAPTURE off
649 VIDIOC_OVERLAY on VIDIOC_OVERLAY off
650 3) bttv_release
651
652 VBI VIDIOC_STREAMON VIDIOC_STREAMOFF
653 VIDIOC_QBUF 1) bttv_release
654 bttv_read, bttv_poll 1) 4)
655
656 1) The resource must be allocated when we enter buffer prepare functions
657 and remain allocated while buffers are in the DMA queue.
658 2) This is a single frame read.
659 3) VIDIOC_S_FBUF and VIDIOC_S_FMT (OVERLAY) still work when
660 RESOURCE_OVERLAY is allocated.
661 4) This is a continuous read, implies VIDIOC_STREAMON.
662
663 Note this driver permits video input and standard changes regardless if
664 resources are allocated.
665*/
666
667#define VBI_RESOURCES (RESOURCE_VBI)
668#define VIDEO_RESOURCES (RESOURCE_VIDEO_READ | \
669 RESOURCE_VIDEO_STREAM | \
670 RESOURCE_OVERLAY)
671
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672static
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -0300673int check_alloc_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674{
Michael Schimeke5bd0262007-01-18 16:17:39 -0300675 int xbits; /* mutual exclusive resources */
676
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 if (fh->resources & bit)
678 /* have it already allocated */
679 return 1;
680
Michael Schimeke5bd0262007-01-18 16:17:39 -0300681 xbits = bit;
682 if (bit & (RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM))
683 xbits |= RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM;
684
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 /* is it free? */
Michael Schimeke5bd0262007-01-18 16:17:39 -0300686 if (btv->resources & xbits) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 /* no, someone else uses it */
Michael Schimeke5bd0262007-01-18 16:17:39 -0300688 goto fail;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689 }
Michael Schimeke5bd0262007-01-18 16:17:39 -0300690
691 if ((bit & VIDEO_RESOURCES)
692 && 0 == (btv->resources & VIDEO_RESOURCES)) {
693 /* Do crop - use current, don't - use default parameters. */
694 __s32 top = btv->crop[!!fh->do_crop].rect.top;
695
696 if (btv->vbi_end > top)
697 goto fail;
698
699 /* We cannot capture the same line as video and VBI data.
700 Claim scan lines crop[].rect.top to bottom. */
701 btv->crop_start = top;
702 } else if (bit & VBI_RESOURCES) {
703 __s32 end = fh->vbi_fmt.end;
704
705 if (end > btv->crop_start)
706 goto fail;
707
708 /* Claim scan lines above fh->vbi_fmt.end. */
709 btv->vbi_end = end;
710 }
711
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712 /* it's free, grab it */
713 fh->resources |= bit;
714 btv->resources |= bit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715 return 1;
Michael Schimeke5bd0262007-01-18 16:17:39 -0300716
717 fail:
Michael Schimeke5bd0262007-01-18 16:17:39 -0300718 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719}
720
721static
722int check_btres(struct bttv_fh *fh, int bit)
723{
724 return (fh->resources & bit);
725}
726
727static
728int locked_btres(struct bttv *btv, int bit)
729{
730 return (btv->resources & bit);
731}
732
Michael Schimeke5bd0262007-01-18 16:17:39 -0300733/* Call with btv->lock down. */
734static void
735disclaim_vbi_lines(struct bttv *btv)
736{
737 btv->vbi_end = 0;
738}
739
740/* Call with btv->lock down. */
741static void
742disclaim_video_lines(struct bttv *btv)
743{
744 const struct bttv_tvnorm *tvnorm;
745 u8 crop;
746
747 tvnorm = &bttv_tvnorms[btv->tvnorm];
748 btv->crop_start = tvnorm->cropcap.bounds.top
749 + tvnorm->cropcap.bounds.height;
750
751 /* VBI capturing ends at VDELAY, start of video capturing, no
752 matter how many lines the VBI RISC program expects. When video
753 capturing is off, it shall no longer "preempt" VBI capturing,
754 so we set VDELAY to maximum. */
755 crop = btread(BT848_E_CROP) | 0xc0;
756 btwrite(crop, BT848_E_CROP);
757 btwrite(0xfe, BT848_E_VDELAY_LO);
758 btwrite(crop, BT848_O_CROP);
759 btwrite(0xfe, BT848_O_VDELAY_LO);
760}
761
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762static
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -0300763void free_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bits)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 if ((fh->resources & bits) != bits) {
Joe Perches8af443e2011-08-21 19:56:48 -0300766 /* trying to free resources not allocated by us ... */
767 pr_err("BUG! (btres)\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769 fh->resources &= ~bits;
770 btv->resources &= ~bits;
Michael Schimeke5bd0262007-01-18 16:17:39 -0300771
772 bits = btv->resources;
773
774 if (0 == (bits & VIDEO_RESOURCES))
775 disclaim_video_lines(btv);
776
777 if (0 == (bits & VBI_RESOURCES))
778 disclaim_vbi_lines(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779}
780
781/* ----------------------------------------------------------------------- */
782/* If Bt848a or Bt849, use PLL for PAL/SECAM and crystal for NTSC */
783
784/* Frequency = (F_input / PLL_X) * PLL_I.PLL_F/PLL_C
785 PLL_X = Reference pre-divider (0=1, 1=2)
786 PLL_C = Post divider (0=6, 1=4)
787 PLL_I = Integer input
788 PLL_F = Fractional input
789
790 F_input = 28.636363 MHz:
791 PAL (CLKx2 = 35.46895 MHz): PLL_X = 1, PLL_I = 0x0E, PLL_F = 0xDCF9, PLL_C = 0
792*/
793
794static void set_pll_freq(struct bttv *btv, unsigned int fin, unsigned int fout)
795{
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800796 unsigned char fl, fh, fi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800798 /* prevent overflows */
799 fin/=4;
800 fout/=4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800802 fout*=12;
803 fi=fout/fin;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800805 fout=(fout%fin)*256;
806 fh=fout/fin;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800808 fout=(fout%fin)*256;
809 fl=fout/fin;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800811 btwrite(fl, BT848_PLL_F_LO);
812 btwrite(fh, BT848_PLL_F_HI);
813 btwrite(fi|BT848_PLL_X, BT848_PLL_XCI);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814}
815
816static void set_pll(struct bttv *btv)
817{
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800818 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800820 if (!btv->pll.pll_crystal)
821 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822
823 if (btv->pll.pll_ofreq == btv->pll.pll_current) {
Joe Perches8af443e2011-08-21 19:56:48 -0300824 dprintk("%d: PLL: no change required\n", btv->c.nr);
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800825 return;
826 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800828 if (btv->pll.pll_ifreq == btv->pll.pll_ofreq) {
829 /* no PLL needed */
830 if (btv->pll.pll_current == 0)
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -0800831 return;
Joe Perches8af443e2011-08-21 19:56:48 -0300832 if (bttv_verbose)
833 pr_info("%d: PLL can sleep, using XTAL (%d)\n",
834 btv->c.nr, btv->pll.pll_ifreq);
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800835 btwrite(0x00,BT848_TGCTRL);
836 btwrite(0x00,BT848_PLL_XCI);
837 btv->pll.pll_current = 0;
838 return;
839 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840
Joe Perches8af443e2011-08-21 19:56:48 -0300841 if (bttv_verbose)
842 pr_info("%d: Setting PLL: %d => %d (needs up to 100ms)\n",
843 btv->c.nr,
844 btv->pll.pll_ifreq, btv->pll.pll_ofreq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 set_pll_freq(btv, btv->pll.pll_ifreq, btv->pll.pll_ofreq);
846
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800847 for (i=0; i<10; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 /* Let other people run while the PLL stabilizes */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 msleep(10);
850
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800851 if (btread(BT848_DSTATUS) & BT848_DSTATUS_PLOCK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 btwrite(0,BT848_DSTATUS);
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800853 } else {
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -0800854 btwrite(0x08,BT848_TGCTRL);
855 btv->pll.pll_current = btv->pll.pll_ofreq;
Joe Perches8af443e2011-08-21 19:56:48 -0300856 if (bttv_verbose)
857 pr_info("PLL set ok\n");
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -0800858 return;
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800859 }
860 }
861 btv->pll.pll_current = -1;
Joe Perches8af443e2011-08-21 19:56:48 -0300862 if (bttv_verbose)
863 pr_info("Setting PLL failed\n");
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800864 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865}
866
867/* used to switch between the bt848's analog/digital video capture modes */
868static void bt848A_set_timing(struct bttv *btv)
869{
870 int i, len;
871 int table_idx = bttv_tvnorms[btv->tvnorm].sram;
872 int fsc = bttv_tvnorms[btv->tvnorm].Fsc;
873
Trent Piepho5221e212009-01-28 21:32:59 -0300874 if (btv->input == btv->dig) {
Joe Perches8af443e2011-08-21 19:56:48 -0300875 dprintk("%d: load digital timing table (table_idx=%d)\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 btv->c.nr,table_idx);
877
878 /* timing change...reset timing generator address */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800879 btwrite(0x00, BT848_TGCTRL);
880 btwrite(0x02, BT848_TGCTRL);
881 btwrite(0x00, BT848_TGCTRL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882
883 len=SRAM_Table[table_idx][0];
884 for(i = 1; i <= len; i++)
885 btwrite(SRAM_Table[table_idx][i],BT848_TGLB);
886 btv->pll.pll_ofreq = 27000000;
887
888 set_pll(btv);
889 btwrite(0x11, BT848_TGCTRL);
890 btwrite(0x41, BT848_DVSIF);
891 } else {
892 btv->pll.pll_ofreq = fsc;
893 set_pll(btv);
894 btwrite(0x0, BT848_DVSIF);
895 }
896}
897
898/* ----------------------------------------------------------------------- */
899
900static void bt848_bright(struct bttv *btv, int bright)
901{
902 int value;
903
Joe Perches8af443e2011-08-21 19:56:48 -0300904 // printk("set bright: %d\n", bright); // DEBUG
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 btv->bright = bright;
906
907 /* We want -128 to 127 we get 0-65535 */
908 value = (bright >> 8) - 128;
909 btwrite(value & 0xff, BT848_BRIGHT);
910}
911
912static void bt848_hue(struct bttv *btv, int hue)
913{
914 int value;
915
916 btv->hue = hue;
917
918 /* -128 to 127 */
919 value = (hue >> 8) - 128;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800920 btwrite(value & 0xff, BT848_HUE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921}
922
923static void bt848_contrast(struct bttv *btv, int cont)
924{
925 int value,hibit;
926
927 btv->contrast = cont;
928
929 /* 0-511 */
930 value = (cont >> 7);
931 hibit = (value >> 6) & 4;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800932 btwrite(value & 0xff, BT848_CONTRAST_LO);
933 btaor(hibit, ~4, BT848_E_CONTROL);
934 btaor(hibit, ~4, BT848_O_CONTROL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935}
936
937static void bt848_sat(struct bttv *btv, int color)
938{
939 int val_u,val_v,hibits;
940
941 btv->saturation = color;
942
943 /* 0-511 for the color */
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700944 val_u = ((color * btv->opt_uv_ratio) / 50) >> 7;
945 val_v = (((color * (100 - btv->opt_uv_ratio) / 50) >>7)*180L)/254;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800946 hibits = (val_u >> 7) & 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947 hibits |= (val_v >> 8) & 1;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800948 btwrite(val_u & 0xff, BT848_SAT_U_LO);
949 btwrite(val_v & 0xff, BT848_SAT_V_LO);
950 btaor(hibits, ~3, BT848_E_CONTROL);
951 btaor(hibits, ~3, BT848_O_CONTROL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952}
953
954/* ----------------------------------------------------------------------- */
955
956static int
957video_mux(struct bttv *btv, unsigned int input)
958{
959 int mux,mask2;
960
961 if (input >= bttv_tvcards[btv->c.type].video_inputs)
962 return -EINVAL;
963
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800964 /* needed by RemoteVideo MX */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 mask2 = bttv_tvcards[btv->c.type].gpiomask2;
966 if (mask2)
967 gpio_inout(mask2,mask2);
968
969 if (input == btv->svhs) {
970 btor(BT848_CONTROL_COMP, BT848_E_CONTROL);
971 btor(BT848_CONTROL_COMP, BT848_O_CONTROL);
972 } else {
973 btand(~BT848_CONTROL_COMP, BT848_E_CONTROL);
974 btand(~BT848_CONTROL_COMP, BT848_O_CONTROL);
975 }
Trent Piepho6f987002009-01-28 21:32:59 -0300976 mux = bttv_muxsel(btv, input);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 btaor(mux<<5, ~(3<<5), BT848_IFORM);
Joe Perches8af443e2011-08-21 19:56:48 -0300978 dprintk("%d: video mux: input=%d mux=%d\n", btv->c.nr, input, mux);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979
980 /* card specific hook */
981 if(bttv_tvcards[btv->c.type].muxsel_hook)
982 bttv_tvcards[btv->c.type].muxsel_hook (btv, input);
983 return 0;
984}
985
986static char *audio_modes[] = {
987 "audio: tuner", "audio: radio", "audio: extern",
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -0300988 "audio: intern", "audio: mute"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989};
990
991static int
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -0300992audio_mux(struct bttv *btv, int input, int mute)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993{
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -0300994 int gpio_val, signal;
Hans Verkuil01df5302013-02-06 12:40:28 -0300995 struct v4l2_ctrl *ctrl;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996
997 gpio_inout(bttv_tvcards[btv->c.type].gpiomask,
998 bttv_tvcards[btv->c.type].gpiomask);
999 signal = btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC;
1000
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001001 btv->mute = mute;
1002 btv->audio = input;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001004 /* automute */
Hans Verkuil01df5302013-02-06 12:40:28 -03001005 mute = mute || (btv->opt_automute && (!signal || !btv->users)
1006 && !btv->radio_user);
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001007
1008 if (mute)
1009 gpio_val = bttv_tvcards[btv->c.type].gpiomute;
1010 else
1011 gpio_val = bttv_tvcards[btv->c.type].gpiomux[input];
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001012
Trent Piepho72134a62009-01-28 21:32:59 -03001013 switch (btv->c.type) {
1014 case BTTV_BOARD_VOODOOTV_FM:
1015 case BTTV_BOARD_VOODOOTV_200:
1016 gpio_val = bttv_tda9880_setnorm(btv, gpio_val);
1017 break;
1018
1019 default:
1020 gpio_bits(bttv_tvcards[btv->c.type].gpiomask, gpio_val);
1021 }
1022
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 if (bttv_gpio)
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001024 bttv_gpio_tracking(btv, audio_modes[mute ? 4 : input]);
1025 if (in_interrupt())
1026 return 0;
1027
Hans Verkuil859f0272009-03-28 08:29:00 -03001028 if (btv->sd_msp34xx) {
Hans Verkuil5325b422009-04-02 11:26:22 -03001029 u32 in;
Hans Verkuil2474ed42006-03-19 12:35:57 -03001030
Hans Verkuil01df5302013-02-06 12:40:28 -03001031 ctrl = v4l2_ctrl_find(btv->sd_msp34xx->ctrl_handler, V4L2_CID_AUDIO_MUTE);
1032 if (ctrl)
1033 v4l2_ctrl_s_ctrl(ctrl, btv->mute);
1034
Hans Verkuil2474ed42006-03-19 12:35:57 -03001035 /* Note: the inputs tuner/radio/extern/intern are translated
1036 to msp routings. This assumes common behavior for all msp3400
1037 based TV cards. When this assumption fails, then the
1038 specific MSP routing must be added to the card table.
1039 For now this is sufficient. */
1040 switch (input) {
1041 case TVAUDIO_INPUT_RADIO:
Hans de Goede7025e522012-05-21 07:46:22 -03001042 /* Some boards need the msp do to the radio demod */
1043 if (btv->radio_uses_msp_demodulator) {
1044 in = MSP_INPUT_DEFAULT;
1045 break;
1046 }
Hans Verkuil5325b422009-04-02 11:26:22 -03001047 in = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1,
Hans Verkuil07151722006-04-01 18:03:23 -03001048 MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001049 break;
1050 case TVAUDIO_INPUT_EXTERN:
Hans Verkuil5325b422009-04-02 11:26:22 -03001051 in = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1,
Hans Verkuil07151722006-04-01 18:03:23 -03001052 MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001053 break;
1054 case TVAUDIO_INPUT_INTERN:
1055 /* Yes, this is the same input as for RADIO. I doubt
1056 if this is ever used. The only board with an INTERN
1057 input is the BTTV_BOARD_AVERMEDIA98. I wonder how
1058 that was tested. My guess is that the whole INTERN
1059 input does not work. */
Hans Verkuil5325b422009-04-02 11:26:22 -03001060 in = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1,
Hans Verkuil07151722006-04-01 18:03:23 -03001061 MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001062 break;
1063 case TVAUDIO_INPUT_TUNER:
1064 default:
Wade Berrier434b2522007-06-25 13:02:16 -03001065 /* This is the only card that uses TUNER2, and afaik,
1066 is the only difference between the VOODOOTV_FM
1067 and VOODOOTV_200 */
1068 if (btv->c.type == BTTV_BOARD_VOODOOTV_200)
Hans Verkuil5325b422009-04-02 11:26:22 -03001069 in = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER2, \
Wade Berrier434b2522007-06-25 13:02:16 -03001070 MSP_DSP_IN_TUNER, MSP_DSP_IN_TUNER);
1071 else
Hans Verkuil5325b422009-04-02 11:26:22 -03001072 in = MSP_INPUT_DEFAULT;
Hans Verkuil2474ed42006-03-19 12:35:57 -03001073 break;
1074 }
Hans Verkuil5325b422009-04-02 11:26:22 -03001075 v4l2_subdev_call(btv->sd_msp34xx, audio, s_routing,
1076 in, MSP_OUTPUT_DEFAULT, 0);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001077 }
Hans Verkuil859f0272009-03-28 08:29:00 -03001078 if (btv->sd_tvaudio) {
Hans Verkuil01df5302013-02-06 12:40:28 -03001079 ctrl = v4l2_ctrl_find(btv->sd_tvaudio->ctrl_handler, V4L2_CID_AUDIO_MUTE);
1080
1081 if (ctrl)
1082 v4l2_ctrl_s_ctrl(ctrl, btv->mute);
Hans Verkuil5325b422009-04-02 11:26:22 -03001083 v4l2_subdev_call(btv->sd_tvaudio, audio, s_routing,
1084 input, 0, 0);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001085 }
Hans Verkuil01df5302013-02-06 12:40:28 -03001086 if (btv->sd_tda7432) {
1087 ctrl = v4l2_ctrl_find(btv->sd_tda7432->ctrl_handler, V4L2_CID_AUDIO_MUTE);
1088
1089 if (ctrl)
1090 v4l2_ctrl_s_ctrl(ctrl, btv->mute);
1091 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 return 0;
1093}
1094
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001095static inline int
1096audio_mute(struct bttv *btv, int mute)
1097{
1098 return audio_mux(btv, btv->audio, mute);
1099}
1100
1101static inline int
1102audio_input(struct bttv *btv, int input)
1103{
1104 return audio_mux(btv, input, btv->mute);
1105}
1106
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107static void
Michael Schimeke5bd0262007-01-18 16:17:39 -03001108bttv_crop_calc_limits(struct bttv_crop *c)
1109{
1110 /* Scale factor min. 1:1, max. 16:1. Min. image size
1111 48 x 32. Scaled width must be a multiple of 4. */
1112
1113 if (1) {
1114 /* For bug compatibility with VIDIOCGCAP and image
1115 size checks in earlier driver versions. */
1116 c->min_scaled_width = 48;
1117 c->min_scaled_height = 32;
1118 } else {
1119 c->min_scaled_width =
1120 (max(48, c->rect.width >> 4) + 3) & ~3;
1121 c->min_scaled_height =
1122 max(32, c->rect.height >> 4);
1123 }
1124
1125 c->max_scaled_width = c->rect.width & ~3;
1126 c->max_scaled_height = c->rect.height;
1127}
1128
1129static void
Trent Piepho4ef2ccc2009-01-28 21:32:58 -03001130bttv_crop_reset(struct bttv_crop *c, unsigned int norm)
Michael Schimeke5bd0262007-01-18 16:17:39 -03001131{
1132 c->rect = bttv_tvnorms[norm].cropcap.defrect;
1133 bttv_crop_calc_limits(c);
1134}
1135
1136/* Call with btv->lock down. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137static int
1138set_tvnorm(struct bttv *btv, unsigned int norm)
1139{
1140 const struct bttv_tvnorm *tvnorm;
Nickolay V. Shmyrev302f61a2007-10-26 10:53:21 -03001141 v4l2_std_id id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142
Trent Piepho4ef2ccc2009-01-28 21:32:58 -03001143 BUG_ON(norm >= BTTV_TVNORMS);
1144 BUG_ON(btv->tvnorm >= BTTV_TVNORMS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146 tvnorm = &bttv_tvnorms[norm];
1147
Mike Isely2de26c02009-09-21 12:42:22 -03001148 if (memcmp(&bttv_tvnorms[btv->tvnorm].cropcap, &tvnorm->cropcap,
Trent Piepho4ef2ccc2009-01-28 21:32:58 -03001149 sizeof (tvnorm->cropcap))) {
Michael Schimeke5bd0262007-01-18 16:17:39 -03001150 bttv_crop_reset(&btv->crop[0], norm);
1151 btv->crop[1] = btv->crop[0]; /* current = default */
1152
1153 if (0 == (btv->resources & VIDEO_RESOURCES)) {
1154 btv->crop_start = tvnorm->cropcap.bounds.top
1155 + tvnorm->cropcap.bounds.height;
1156 }
1157 }
1158
1159 btv->tvnorm = norm;
1160
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 btwrite(tvnorm->adelay, BT848_ADELAY);
1162 btwrite(tvnorm->bdelay, BT848_BDELAY);
1163 btaor(tvnorm->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH),
1164 BT848_IFORM);
1165 btwrite(tvnorm->vbipack, BT848_VBI_PACK_SIZE);
1166 btwrite(1, BT848_VBI_PACK_DEL);
1167 bt848A_set_timing(btv);
1168
1169 switch (btv->c.type) {
Mauro Carvalho Chehab5a25e842005-11-08 21:36:52 -08001170 case BTTV_BOARD_VOODOOTV_FM:
Wade Berrier434b2522007-06-25 13:02:16 -03001171 case BTTV_BOARD_VOODOOTV_200:
Trent Piepho72134a62009-01-28 21:32:59 -03001172 bttv_tda9880_setnorm(btv, gpio_read());
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 }
Nickolay V. Shmyrev302f61a2007-10-26 10:53:21 -03001175 id = tvnorm->v4l2_id;
Hans Verkuilf41737e2009-04-01 03:52:39 -03001176 bttv_call_all(btv, core, s_std, id);
Nickolay V. Shmyrev302f61a2007-10-26 10:53:21 -03001177
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 return 0;
1179}
1180
Michael Schimeke5bd0262007-01-18 16:17:39 -03001181/* Call with btv->lock down. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182static void
Trent Piepho333408f2007-07-03 15:08:10 -03001183set_input(struct bttv *btv, unsigned int input, unsigned int norm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184{
1185 unsigned long flags;
1186
1187 btv->input = input;
1188 if (irq_iswitch) {
1189 spin_lock_irqsave(&btv->s_lock,flags);
1190 if (btv->curr.frame_irq) {
1191 /* active capture -> delayed input switch */
1192 btv->new_input = input;
1193 } else {
1194 video_mux(btv,input);
1195 }
1196 spin_unlock_irqrestore(&btv->s_lock,flags);
1197 } else {
1198 video_mux(btv,input);
1199 }
Trent Piephoabb03622009-01-28 21:32:59 -03001200 audio_input(btv, (btv->tuner_type != TUNER_ABSENT && input == 0) ?
1201 TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN);
Trent Piepho333408f2007-07-03 15:08:10 -03001202 set_tvnorm(btv, norm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203}
1204
1205static void init_irqreg(struct bttv *btv)
1206{
1207 /* clear status */
1208 btwrite(0xfffffUL, BT848_INT_STAT);
1209
1210 if (bttv_tvcards[btv->c.type].no_video) {
1211 /* i2c only */
1212 btwrite(BT848_INT_I2CDONE,
1213 BT848_INT_MASK);
1214 } else {
1215 /* full video */
1216 btwrite((btv->triton1) |
1217 (btv->gpioirq ? BT848_INT_GPINT : 0) |
1218 BT848_INT_SCERR |
1219 (fdsr ? BT848_INT_FDSR : 0) |
Jean Delvareeb1b27b2008-08-30 10:18:21 -03001220 BT848_INT_RISCI | BT848_INT_OCERR |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 BT848_INT_FMTCHG|BT848_INT_HLOCK|
1222 BT848_INT_I2CDONE,
1223 BT848_INT_MASK);
1224 }
1225}
1226
1227static void init_bt848(struct bttv *btv)
1228{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 if (bttv_tvcards[btv->c.type].no_video) {
1230 /* very basic init only */
1231 init_irqreg(btv);
1232 return;
1233 }
1234
1235 btwrite(0x00, BT848_CAP_CTL);
1236 btwrite(BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL);
1237 btwrite(BT848_IFORM_XTAUTO | BT848_IFORM_AUTO, BT848_IFORM);
1238
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001239 /* set planar and packed mode trigger points and */
1240 /* set rising edge of inverted GPINTR pin as irq trigger */
1241 btwrite(BT848_GPIO_DMA_CTL_PKTP_32|
1242 BT848_GPIO_DMA_CTL_PLTP1_16|
1243 BT848_GPIO_DMA_CTL_PLTP23_16|
1244 BT848_GPIO_DMA_CTL_GPINTC|
1245 BT848_GPIO_DMA_CTL_GPINTI,
1246 BT848_GPIO_DMA_CTL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001248 btwrite(0x20, BT848_E_VSCALE_HI);
1249 btwrite(0x20, BT848_O_VSCALE_HI);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250
Hans Verkuil01df5302013-02-06 12:40:28 -03001251 v4l2_ctrl_handler_setup(&btv->ctrl_handler);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001253 /* interrupt */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254 init_irqreg(btv);
1255}
1256
1257static void bttv_reinit_bt848(struct bttv *btv)
1258{
1259 unsigned long flags;
1260
1261 if (bttv_verbose)
Joe Perches8af443e2011-08-21 19:56:48 -03001262 pr_info("%d: reset, reinitialize\n", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263 spin_lock_irqsave(&btv->s_lock,flags);
1264 btv->errors=0;
1265 bttv_set_dma(btv,0);
1266 spin_unlock_irqrestore(&btv->s_lock,flags);
1267
1268 init_bt848(btv);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001269 btv->pll.pll_current = -1;
Trent Piepho333408f2007-07-03 15:08:10 -03001270 set_input(btv, btv->input, btv->tvnorm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271}
1272
Hans Verkuil01df5302013-02-06 12:40:28 -03001273static int bttv_s_ctrl(struct v4l2_ctrl *c)
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001274{
Hans Verkuil01df5302013-02-06 12:40:28 -03001275 struct bttv *btv = container_of(c->handler, struct bttv, ctrl_handler);
1276 int val;
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001277
1278 switch (c->id) {
1279 case V4L2_CID_BRIGHTNESS:
Hans Verkuil01df5302013-02-06 12:40:28 -03001280 bt848_bright(btv, c->val);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001281 break;
1282 case V4L2_CID_HUE:
Hans Verkuil01df5302013-02-06 12:40:28 -03001283 bt848_hue(btv, c->val);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001284 break;
1285 case V4L2_CID_CONTRAST:
Hans Verkuil01df5302013-02-06 12:40:28 -03001286 bt848_contrast(btv, c->val);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001287 break;
1288 case V4L2_CID_SATURATION:
Hans Verkuil01df5302013-02-06 12:40:28 -03001289 bt848_sat(btv, c->val);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001290 break;
Guilherme Herrmann Destefani34e59a72012-09-25 18:10:52 -03001291 case V4L2_CID_COLOR_KILLER:
Hans Verkuil01df5302013-02-06 12:40:28 -03001292 if (c->val) {
Guilherme Herrmann Destefani34e59a72012-09-25 18:10:52 -03001293 btor(BT848_SCLOOP_CKILL, BT848_E_SCLOOP);
1294 btor(BT848_SCLOOP_CKILL, BT848_O_SCLOOP);
1295 } else {
1296 btand(~BT848_SCLOOP_CKILL, BT848_E_SCLOOP);
1297 btand(~BT848_SCLOOP_CKILL, BT848_O_SCLOOP);
1298 }
1299 break;
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001300 case V4L2_CID_AUDIO_MUTE:
Hans Verkuil01df5302013-02-06 12:40:28 -03001301 audio_mute(btv, c->val);
1302 break;
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001303 case V4L2_CID_AUDIO_VOLUME:
Hans Verkuil01df5302013-02-06 12:40:28 -03001304 btv->volume_gpio(btv, c->val);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001305 break;
1306
Hans Verkuil01df5302013-02-06 12:40:28 -03001307 case V4L2_CID_CHROMA_AGC:
1308 val = c->val ? BT848_SCLOOP_CAGC : 0;
1309 btwrite(val, BT848_E_SCLOOP);
1310 btwrite(val, BT848_O_SCLOOP);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001311 break;
1312 case V4L2_CID_PRIVATE_COMBFILTER:
Hans Verkuil01df5302013-02-06 12:40:28 -03001313 btv->opt_combfilter = c->val;
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001314 break;
1315 case V4L2_CID_PRIVATE_LUMAFILTER:
Hans Verkuil01df5302013-02-06 12:40:28 -03001316 if (c->val) {
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001317 btand(~BT848_CONTROL_LDEC, BT848_E_CONTROL);
1318 btand(~BT848_CONTROL_LDEC, BT848_O_CONTROL);
1319 } else {
1320 btor(BT848_CONTROL_LDEC, BT848_E_CONTROL);
1321 btor(BT848_CONTROL_LDEC, BT848_O_CONTROL);
1322 }
1323 break;
1324 case V4L2_CID_PRIVATE_AUTOMUTE:
Hans Verkuil01df5302013-02-06 12:40:28 -03001325 btv->opt_automute = c->val;
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001326 break;
1327 case V4L2_CID_PRIVATE_AGC_CRUSH:
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001328 btwrite(BT848_ADC_RESERVED |
Hans Verkuil01df5302013-02-06 12:40:28 -03001329 (c->val ? BT848_ADC_CRUSH : 0),
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001330 BT848_ADC);
1331 break;
1332 case V4L2_CID_PRIVATE_VCR_HACK:
Hans Verkuil01df5302013-02-06 12:40:28 -03001333 btv->opt_vcr_hack = c->val;
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001334 break;
1335 case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
Hans Verkuil01df5302013-02-06 12:40:28 -03001336 btwrite(c->val, BT848_WC_UP);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001337 break;
1338 case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
Hans Verkuil01df5302013-02-06 12:40:28 -03001339 btwrite(c->val, BT848_WC_DOWN);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001340 break;
1341 case V4L2_CID_PRIVATE_UV_RATIO:
Hans Verkuil01df5302013-02-06 12:40:28 -03001342 btv->opt_uv_ratio = c->val;
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001343 bt848_sat(btv, btv->saturation);
1344 break;
1345 case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
Hans Verkuil01df5302013-02-06 12:40:28 -03001346 btaor((c->val << 7), ~BT848_OFORM_RANGE, BT848_OFORM);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001347 break;
1348 case V4L2_CID_PRIVATE_CORING:
Hans Verkuil01df5302013-02-06 12:40:28 -03001349 btaor((c->val << 5), ~BT848_OFORM_CORE32, BT848_OFORM);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001350 break;
1351 default:
1352 return -EINVAL;
1353 }
1354 return 0;
1355}
1356
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357/* ----------------------------------------------------------------------- */
1358
Hans Verkuil01df5302013-02-06 12:40:28 -03001359static const struct v4l2_ctrl_ops bttv_ctrl_ops = {
1360 .s_ctrl = bttv_s_ctrl,
1361};
1362
1363static struct v4l2_ctrl_config bttv_ctrl_combfilter = {
1364 .ops = &bttv_ctrl_ops,
1365 .id = V4L2_CID_PRIVATE_COMBFILTER,
1366 .name = "Comb Filter",
1367 .type = V4L2_CTRL_TYPE_BOOLEAN,
1368 .min = 0,
1369 .max = 1,
1370 .step = 1,
1371 .def = 1,
1372};
1373
1374static struct v4l2_ctrl_config bttv_ctrl_automute = {
1375 .ops = &bttv_ctrl_ops,
1376 .id = V4L2_CID_PRIVATE_AUTOMUTE,
1377 .name = "Auto Mute",
1378 .type = V4L2_CTRL_TYPE_BOOLEAN,
1379 .min = 0,
1380 .max = 1,
1381 .step = 1,
1382 .def = 1,
1383};
1384
1385static struct v4l2_ctrl_config bttv_ctrl_lumafilter = {
1386 .ops = &bttv_ctrl_ops,
1387 .id = V4L2_CID_PRIVATE_LUMAFILTER,
1388 .name = "Luma Decimation Filter",
1389 .type = V4L2_CTRL_TYPE_BOOLEAN,
1390 .min = 0,
1391 .max = 1,
1392 .step = 1,
1393 .def = 1,
1394};
1395
1396static struct v4l2_ctrl_config bttv_ctrl_agc_crush = {
1397 .ops = &bttv_ctrl_ops,
1398 .id = V4L2_CID_PRIVATE_AGC_CRUSH,
1399 .name = "AGC Crush",
1400 .type = V4L2_CTRL_TYPE_BOOLEAN,
1401 .min = 0,
1402 .max = 1,
1403 .step = 1,
1404 .def = 1,
1405};
1406
1407static struct v4l2_ctrl_config bttv_ctrl_vcr_hack = {
1408 .ops = &bttv_ctrl_ops,
1409 .id = V4L2_CID_PRIVATE_VCR_HACK,
1410 .name = "VCR Hack",
1411 .type = V4L2_CTRL_TYPE_BOOLEAN,
1412 .min = 0,
1413 .max = 1,
1414 .step = 1,
1415 .def = 1,
1416};
1417
1418static struct v4l2_ctrl_config bttv_ctrl_whitecrush_lower = {
1419 .ops = &bttv_ctrl_ops,
1420 .id = V4L2_CID_PRIVATE_WHITECRUSH_LOWER,
1421 .name = "Whitecrush Lower",
1422 .type = V4L2_CTRL_TYPE_INTEGER,
1423 .min = 0,
1424 .max = 255,
1425 .step = 1,
1426 .def = 0x7f,
1427};
1428
1429static struct v4l2_ctrl_config bttv_ctrl_whitecrush_upper = {
1430 .ops = &bttv_ctrl_ops,
1431 .id = V4L2_CID_PRIVATE_WHITECRUSH_UPPER,
1432 .name = "Whitecrush Upper",
1433 .type = V4L2_CTRL_TYPE_INTEGER,
1434 .min = 0,
1435 .max = 255,
1436 .step = 1,
1437 .def = 0xcf,
1438};
1439
1440static struct v4l2_ctrl_config bttv_ctrl_uv_ratio = {
1441 .ops = &bttv_ctrl_ops,
1442 .id = V4L2_CID_PRIVATE_UV_RATIO,
1443 .name = "UV Ratio",
1444 .type = V4L2_CTRL_TYPE_INTEGER,
1445 .min = 0,
1446 .max = 100,
1447 .step = 1,
1448 .def = 50,
1449};
1450
1451static struct v4l2_ctrl_config bttv_ctrl_full_luma = {
1452 .ops = &bttv_ctrl_ops,
1453 .id = V4L2_CID_PRIVATE_FULL_LUMA_RANGE,
1454 .name = "Full Luma Range",
1455 .type = V4L2_CTRL_TYPE_BOOLEAN,
1456 .min = 0,
1457 .max = 1,
1458 .step = 1,
1459};
1460
1461static struct v4l2_ctrl_config bttv_ctrl_coring = {
1462 .ops = &bttv_ctrl_ops,
1463 .id = V4L2_CID_PRIVATE_CORING,
1464 .name = "Coring",
1465 .type = V4L2_CTRL_TYPE_INTEGER,
1466 .min = 0,
1467 .max = 3,
1468 .step = 1,
1469};
1470
1471
1472/* ----------------------------------------------------------------------- */
1473
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474void bttv_gpio_tracking(struct bttv *btv, char *comment)
1475{
1476 unsigned int outbits, data;
1477 outbits = btread(BT848_GPIO_OUT_EN);
1478 data = btread(BT848_GPIO_DATA);
Joe Perches8af443e2011-08-21 19:56:48 -03001479 pr_debug("%d: gpio: en=%08x, out=%08x in=%08x [%s]\n",
1480 btv->c.nr, outbits, data & outbits, data & ~outbits, comment);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481}
1482
1483static void bttv_field_count(struct bttv *btv)
1484{
1485 int need_count = 0;
1486
1487 if (btv->users)
1488 need_count++;
1489
1490 if (need_count) {
1491 /* start field counter */
1492 btor(BT848_INT_VSYNC,BT848_INT_MASK);
1493 } else {
1494 /* stop field counter */
1495 btand(~BT848_INT_VSYNC,BT848_INT_MASK);
1496 btv->field_count = 0;
1497 }
1498}
1499
1500static const struct bttv_format*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501format_by_fourcc(int fourcc)
1502{
1503 unsigned int i;
1504
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001505 for (i = 0; i < FORMATS; i++) {
1506 if (-1 == formats[i].fourcc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507 continue;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001508 if (formats[i].fourcc == fourcc)
1509 return formats+i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510 }
1511 return NULL;
1512}
1513
1514/* ----------------------------------------------------------------------- */
1515/* misc helpers */
1516
1517static int
1518bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh,
1519 struct bttv_buffer *new)
1520{
1521 struct bttv_buffer *old;
1522 unsigned long flags;
1523 int retval = 0;
1524
Joe Perches8af443e2011-08-21 19:56:48 -03001525 dprintk("switch_overlay: enter [new=%p]\n", new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526 if (new)
Brandon Philips0fc06862007-11-06 20:02:36 -03001527 new->vb.state = VIDEOBUF_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 spin_lock_irqsave(&btv->s_lock,flags);
1529 old = btv->screen;
1530 btv->screen = new;
1531 btv->loop_irq |= 1;
1532 bttv_set_dma(btv, 0x03);
1533 spin_unlock_irqrestore(&btv->s_lock,flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534 if (NULL != old) {
Joe Perches8af443e2011-08-21 19:56:48 -03001535 dprintk("switch_overlay: old=%p state is %d\n",
1536 old, old->vb.state);
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001537 bttv_dma_free(&fh->cap,btv, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538 kfree(old);
1539 }
Michael Schimeke5bd0262007-01-18 16:17:39 -03001540 if (NULL == new)
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03001541 free_btres_lock(btv,fh,RESOURCE_OVERLAY);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542 dprintk("switch_overlay: done\n");
1543 return retval;
1544}
1545
1546/* ----------------------------------------------------------------------- */
1547/* video4linux (1) interface */
1548
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001549static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv,
1550 struct bttv_buffer *buf,
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001551 const struct bttv_format *fmt,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552 unsigned int width, unsigned int height,
1553 enum v4l2_field field)
1554{
Michael Schimeke5bd0262007-01-18 16:17:39 -03001555 struct bttv_fh *fh = q->priv_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556 int redo_dma_risc = 0;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001557 struct bttv_crop c;
1558 int norm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559 int rc;
1560
1561 /* check settings */
1562 if (NULL == fmt)
1563 return -EINVAL;
1564 if (fmt->btformat == BT848_COLOR_FMT_RAW) {
1565 width = RAW_BPL;
1566 height = RAW_LINES*2;
1567 if (width*height > buf->vb.bsize)
1568 return -EINVAL;
1569 buf->vb.size = buf->vb.bsize;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001570
1571 /* Make sure tvnorm and vbi_end remain consistent
1572 until we're done. */
Michael Schimeke5bd0262007-01-18 16:17:39 -03001573
1574 norm = btv->tvnorm;
1575
1576 /* In this mode capturing always starts at defrect.top
1577 (default VDELAY), ignoring cropping parameters. */
1578 if (btv->vbi_end > bttv_tvnorms[norm].cropcap.defrect.top) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579 return -EINVAL;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001580 }
1581
Michael Schimeke5bd0262007-01-18 16:17:39 -03001582 c.rect = bttv_tvnorms[norm].cropcap.defrect;
1583 } else {
Michael Schimeke5bd0262007-01-18 16:17:39 -03001584 norm = btv->tvnorm;
1585 c = btv->crop[!!fh->do_crop];
1586
Michael Schimeke5bd0262007-01-18 16:17:39 -03001587 if (width < c.min_scaled_width ||
1588 width > c.max_scaled_width ||
1589 height < c.min_scaled_height)
1590 return -EINVAL;
1591
1592 switch (field) {
1593 case V4L2_FIELD_TOP:
1594 case V4L2_FIELD_BOTTOM:
1595 case V4L2_FIELD_ALTERNATE:
1596 /* btv->crop counts frame lines. Max. scale
1597 factor is 16:1 for frames, 8:1 for fields. */
1598 if (height * 2 > c.max_scaled_height)
1599 return -EINVAL;
1600 break;
1601
1602 default:
1603 if (height > c.max_scaled_height)
1604 return -EINVAL;
1605 break;
1606 }
1607
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608 buf->vb.size = (width * height * fmt->depth) >> 3;
1609 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
1610 return -EINVAL;
1611 }
1612
1613 /* alloc + fill struct bttv_buffer (if changed) */
1614 if (buf->vb.width != width || buf->vb.height != height ||
1615 buf->vb.field != field ||
Michael Schimeke5bd0262007-01-18 16:17:39 -03001616 buf->tvnorm != norm || buf->fmt != fmt ||
1617 buf->crop.top != c.rect.top ||
1618 buf->crop.left != c.rect.left ||
1619 buf->crop.width != c.rect.width ||
1620 buf->crop.height != c.rect.height) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001621 buf->vb.width = width;
1622 buf->vb.height = height;
1623 buf->vb.field = field;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001624 buf->tvnorm = norm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625 buf->fmt = fmt;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001626 buf->crop = c.rect;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627 redo_dma_risc = 1;
1628 }
1629
1630 /* alloc risc memory */
Brandon Philips0fc06862007-11-06 20:02:36 -03001631 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632 redo_dma_risc = 1;
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001633 if (0 != (rc = videobuf_iolock(q,&buf->vb,&btv->fbuf)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634 goto fail;
1635 }
1636
1637 if (redo_dma_risc)
1638 if (0 != (rc = bttv_buffer_risc(btv,buf)))
1639 goto fail;
1640
Brandon Philips0fc06862007-11-06 20:02:36 -03001641 buf->vb.state = VIDEOBUF_PREPARED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642 return 0;
1643
1644 fail:
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001645 bttv_dma_free(q,btv,buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646 return rc;
1647}
1648
1649static int
1650buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
1651{
1652 struct bttv_fh *fh = q->priv_data;
1653
1654 *size = fh->fmt->depth*fh->width*fh->height >> 3;
1655 if (0 == *count)
1656 *count = gbuffers;
Andreas Bombedab7e312010-03-21 16:02:45 -03001657 if (*size * *count > gbuffers * gbufsize)
1658 *count = (gbuffers * gbufsize) / *size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659 return 0;
1660}
1661
1662static int
1663buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
1664 enum v4l2_field field)
1665{
1666 struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
1667 struct bttv_fh *fh = q->priv_data;
1668
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001669 return bttv_prepare_buffer(q,fh->btv, buf, fh->fmt,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670 fh->width, fh->height, field);
1671}
1672
1673static void
1674buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
1675{
1676 struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
1677 struct bttv_fh *fh = q->priv_data;
1678 struct bttv *btv = fh->btv;
1679
Brandon Philips0fc06862007-11-06 20:02:36 -03001680 buf->vb.state = VIDEOBUF_QUEUED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681 list_add_tail(&buf->vb.queue,&btv->capture);
1682 if (!btv->curr.frame_irq) {
1683 btv->loop_irq |= 1;
1684 bttv_set_dma(btv, 0x03);
1685 }
1686}
1687
1688static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
1689{
1690 struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
1691 struct bttv_fh *fh = q->priv_data;
1692
Michael Schimekfeaba7a2007-01-26 08:30:05 -03001693 bttv_dma_free(q,fh->btv,buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694}
1695
1696static struct videobuf_queue_ops bttv_video_qops = {
1697 .buf_setup = buffer_setup,
1698 .buf_prepare = buffer_prepare,
1699 .buf_queue = buffer_queue,
1700 .buf_release = buffer_release,
1701};
1702
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001703static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001705 struct bttv_fh *fh = priv;
1706 struct bttv *btv = fh->btv;
1707 unsigned int i;
1708 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709
Hans Verkuilffb48772010-05-01 08:03:24 -03001710 err = v4l2_prio_check(&btv->prio, fh->prio);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001711 if (err)
1712 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001714 for (i = 0; i < BTTV_TVNORMS; i++)
1715 if (*id & bttv_tvnorms[i].v4l2_id)
1716 break;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001717 if (i == BTTV_TVNORMS) {
1718 err = -EINVAL;
1719 goto err;
1720 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001722 set_tvnorm(btv, i);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001723
1724err:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001726 return err;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001727}
1728
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001729static int bttv_querystd(struct file *file, void *f, v4l2_std_id *id)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001730{
1731 struct bttv_fh *fh = f;
1732 struct bttv *btv = fh->btv;
1733
1734 if (btread(BT848_DSTATUS) & BT848_DSTATUS_NUML)
1735 *id = V4L2_STD_625_50;
1736 else
1737 *id = V4L2_STD_525_60;
1738 return 0;
1739}
1740
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001741static int bttv_enum_input(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001742 struct v4l2_input *i)
1743{
1744 struct bttv_fh *fh = priv;
1745 struct bttv *btv = fh->btv;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001746 int rc = 0;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001747
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001748 if (i->index >= bttv_tvcards[btv->c.type].video_inputs) {
1749 rc = -EINVAL;
1750 goto err;
1751 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001752
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001753 i->type = V4L2_INPUT_TYPE_CAMERA;
Hans Verkuilf74f89cb2013-01-31 08:45:13 -03001754 i->audioset = 0;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001755
Trent Piephoabb03622009-01-28 21:32:59 -03001756 if (btv->tuner_type != TUNER_ABSENT && i->index == 0) {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001757 sprintf(i->name, "Television");
1758 i->type = V4L2_INPUT_TYPE_TUNER;
1759 i->tuner = 0;
1760 } else if (i->index == btv->svhs) {
1761 sprintf(i->name, "S-Video");
1762 } else {
1763 sprintf(i->name, "Composite%d", i->index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764 }
1765
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001766 if (i->index == btv->input) {
1767 __u32 dstatus = btread(BT848_DSTATUS);
1768 if (0 == (dstatus & BT848_DSTATUS_PRES))
1769 i->status |= V4L2_IN_ST_NO_SIGNAL;
1770 if (0 == (dstatus & BT848_DSTATUS_HLOC))
1771 i->status |= V4L2_IN_ST_NO_H_LOCK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772 }
1773
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001774 i->std = BTTV_NORMS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001776err:
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001777
1778 return rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001779}
Nickolay V. Shmyrev4b9b9362006-08-25 16:53:04 -03001780
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001781static int bttv_g_input(struct file *file, void *priv, unsigned int *i)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001782{
1783 struct bttv_fh *fh = priv;
1784 struct bttv *btv = fh->btv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001786 *i = btv->input;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001787
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001788 return 0;
1789}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001790
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001791static int bttv_s_input(struct file *file, void *priv, unsigned int i)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001792{
1793 struct bttv_fh *fh = priv;
1794 struct bttv *btv = fh->btv;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001795 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001797 err = v4l2_prio_check(&btv->prio, fh->prio);
Hans Verkuilf74f89cb2013-01-31 08:45:13 -03001798 if (err)
1799 return err;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001800
Hans Verkuilf74f89cb2013-01-31 08:45:13 -03001801 if (i >= bttv_tvcards[btv->c.type].video_inputs)
1802 return -EINVAL;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001803
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001804 set_input(btv, i, btv->tvnorm);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001805 return 0;
1806}
1807
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001808static int bttv_s_tuner(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001809 struct v4l2_tuner *t)
1810{
1811 struct bttv_fh *fh = priv;
1812 struct bttv *btv = fh->btv;
1813 int err;
1814
Hans Verkuild9b67072013-02-06 11:43:07 -03001815 if (t->index)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001816 return -EINVAL;
1817
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001818 err = v4l2_prio_check(&btv->prio, fh->prio);
Hans Verkuild9b67072013-02-06 11:43:07 -03001819 if (err)
1820 return err;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001821
Hans Verkuil859f0272009-03-28 08:29:00 -03001822 bttv_call_all(btv, tuner, s_tuner, t);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001823
1824 if (btv->audio_mode_gpio)
1825 btv->audio_mode_gpio(btv, t, 1);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001826 return 0;
1827}
1828
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001829static int bttv_g_frequency(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001830 struct v4l2_frequency *f)
1831{
1832 struct bttv_fh *fh = priv;
1833 struct bttv *btv = fh->btv;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001834
Hans Verkuild9b67072013-02-06 11:43:07 -03001835 if (f->tuner)
1836 return -EINVAL;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001837
Hans Verkuil76ea9922013-02-06 11:49:14 -03001838 f->frequency = f->type == V4L2_TUNER_RADIO ?
1839 btv->radio_freq : btv->tv_freq;
1840
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001841 return 0;
1842}
1843
Hans Verkuil76ea9922013-02-06 11:49:14 -03001844static void bttv_set_frequency(struct bttv *btv, struct v4l2_frequency *f)
1845{
1846 bttv_call_all(btv, tuner, s_frequency, f);
1847 /* s_frequency may clamp the frequency, so get the actual
1848 frequency before assigning radio/tv_freq. */
1849 bttv_call_all(btv, tuner, g_frequency, f);
1850 if (f->type == V4L2_TUNER_RADIO) {
1851 btv->radio_freq = f->frequency;
1852 if (btv->has_matchbox)
1853 tea5757_set_freq(btv, btv->radio_freq);
1854 } else {
1855 btv->tv_freq = f->frequency;
1856 }
1857}
1858
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001859static int bttv_s_frequency(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001860 struct v4l2_frequency *f)
1861{
1862 struct bttv_fh *fh = priv;
1863 struct bttv *btv = fh->btv;
1864 int err;
1865
Hans Verkuild9b67072013-02-06 11:43:07 -03001866 if (f->tuner)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001867 return -EINVAL;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001868
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001869 err = v4l2_prio_check(&btv->prio, fh->prio);
Hans Verkuild9b67072013-02-06 11:43:07 -03001870 if (err)
1871 return err;
Hans Verkuil76ea9922013-02-06 11:49:14 -03001872 bttv_set_frequency(btv, f);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001873 return 0;
1874}
1875
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001876static int bttv_log_status(struct file *file, void *f)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001877{
Hans Verkuil01df5302013-02-06 12:40:28 -03001878 struct video_device *vdev = video_devdata(file);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001879 struct bttv_fh *fh = f;
1880 struct bttv *btv = fh->btv;
1881
Hans Verkuil01df5302013-02-06 12:40:28 -03001882 v4l2_ctrl_handler_log_status(vdev->ctrl_handler, btv->c.v4l2_dev.name);
Hans Verkuil859f0272009-03-28 08:29:00 -03001883 bttv_call_all(btv, core, log_status);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001884 return 0;
1885}
1886
Hans Verkuil1b9e94d2012-09-09 09:23:31 -03001887static int bttv_g_chip_ident(struct file *file, void *f, struct v4l2_dbg_chip_ident *chip)
1888{
1889 struct bttv_fh *fh = f;
1890 struct bttv *btv = fh->btv;
1891
1892 chip->ident = V4L2_IDENT_NONE;
1893 chip->revision = 0;
1894 if (chip->match.type == V4L2_CHIP_MATCH_HOST) {
1895 if (v4l2_chip_match_host(&chip->match)) {
1896 chip->ident = btv->id;
1897 if (chip->ident == PCI_DEVICE_ID_FUSION879)
1898 chip->ident = V4L2_IDENT_BT879;
1899 }
1900 return 0;
1901 }
1902 if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER &&
1903 chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
1904 return -EINVAL;
1905 /* TODO: is this correct? */
1906 return bttv_call_all_err(btv, core, g_chip_ident, chip);
1907}
1908
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001909#ifdef CONFIG_VIDEO_ADV_DEBUG
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001910static int bttv_g_register(struct file *file, void *f,
Hans Verkuilaecde8b2008-12-30 07:14:19 -03001911 struct v4l2_dbg_register *reg)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001912{
1913 struct bttv_fh *fh = f;
1914 struct bttv *btv = fh->btv;
1915
1916 if (!capable(CAP_SYS_ADMIN))
1917 return -EPERM;
1918
Hans Verkuil1b9e94d2012-09-09 09:23:31 -03001919 if (!v4l2_chip_match_host(&reg->match)) {
1920 /* TODO: subdev errors should not be ignored, this should become a
1921 subdev helper function. */
1922 bttv_call_all(btv, core, g_register, reg);
1923 return 0;
1924 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001925
1926 /* bt848 has a 12-bit register space */
1927 reg->reg &= 0xfff;
1928 reg->val = btread(reg->reg);
Hans Verkuilaecde8b2008-12-30 07:14:19 -03001929 reg->size = 1;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001930
1931 return 0;
1932}
1933
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001934static int bttv_s_register(struct file *file, void *f,
Hans Verkuilaecde8b2008-12-30 07:14:19 -03001935 struct v4l2_dbg_register *reg)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001936{
1937 struct bttv_fh *fh = f;
1938 struct bttv *btv = fh->btv;
1939
1940 if (!capable(CAP_SYS_ADMIN))
1941 return -EPERM;
1942
Hans Verkuil1b9e94d2012-09-09 09:23:31 -03001943 if (!v4l2_chip_match_host(&reg->match)) {
1944 /* TODO: subdev errors should not be ignored, this should become a
1945 subdev helper function. */
1946 bttv_call_all(btv, core, s_register, reg);
1947 return 0;
1948 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001949
1950 /* bt848 has a 12-bit register space */
1951 reg->reg &= 0xfff;
1952 btwrite(reg->val, reg->reg);
1953
1954 return 0;
1955}
1956#endif
1957
Michael Schimeke5bd0262007-01-18 16:17:39 -03001958/* Given cropping boundaries b and the scaled width and height of a
1959 single field or frame, which must not exceed hardware limits, this
1960 function adjusts the cropping parameters c. */
1961static void
1962bttv_crop_adjust (struct bttv_crop * c,
1963 const struct v4l2_rect * b,
1964 __s32 width,
1965 __s32 height,
1966 enum v4l2_field field)
1967{
1968 __s32 frame_height = height << !V4L2_FIELD_HAS_BOTH(field);
1969 __s32 max_left;
1970 __s32 max_top;
1971
1972 if (width < c->min_scaled_width) {
1973 /* Max. hor. scale factor 16:1. */
1974 c->rect.width = width * 16;
1975 } else if (width > c->max_scaled_width) {
1976 /* Min. hor. scale factor 1:1. */
1977 c->rect.width = width;
1978
1979 max_left = b->left + b->width - width;
1980 max_left = min(max_left, (__s32) MAX_HDELAY);
1981 if (c->rect.left > max_left)
1982 c->rect.left = max_left;
1983 }
1984
1985 if (height < c->min_scaled_height) {
1986 /* Max. vert. scale factor 16:1, single fields 8:1. */
1987 c->rect.height = height * 16;
1988 } else if (frame_height > c->max_scaled_height) {
1989 /* Min. vert. scale factor 1:1.
1990 Top and height count field lines times two. */
1991 c->rect.height = (frame_height + 1) & ~1;
1992
1993 max_top = b->top + b->height - c->rect.height;
1994 if (c->rect.top > max_top)
1995 c->rect.top = max_top;
1996 }
1997
1998 bttv_crop_calc_limits(c);
1999}
2000
2001/* Returns an error if scaling to a frame or single field with the given
2002 width and height is not possible with the current cropping parameters
2003 and width aligned according to width_mask. If adjust_size is TRUE the
2004 function may adjust the width and/or height instead, rounding width
2005 to (width + width_bias) & width_mask. If adjust_crop is TRUE it may
2006 also adjust the current cropping parameters to get closer to the
2007 desired image size. */
2008static int
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002009limit_scaled_size_lock (struct bttv_fh * fh,
Michael Schimeke5bd0262007-01-18 16:17:39 -03002010 __s32 * width,
2011 __s32 * height,
2012 enum v4l2_field field,
2013 unsigned int width_mask,
2014 unsigned int width_bias,
2015 int adjust_size,
2016 int adjust_crop)
2017{
2018 struct bttv *btv = fh->btv;
2019 const struct v4l2_rect *b;
2020 struct bttv_crop *c;
2021 __s32 min_width;
2022 __s32 min_height;
2023 __s32 max_width;
2024 __s32 max_height;
2025 int rc;
2026
2027 BUG_ON((int) width_mask >= 0 ||
2028 width_bias >= (unsigned int) -width_mask);
2029
2030 /* Make sure tvnorm, vbi_end and the current cropping parameters
2031 remain consistent until we're done. */
Michael Schimeke5bd0262007-01-18 16:17:39 -03002032
2033 b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
2034
2035 /* Do crop - use current, don't - use default parameters. */
2036 c = &btv->crop[!!fh->do_crop];
2037
2038 if (fh->do_crop
2039 && adjust_size
2040 && adjust_crop
2041 && !locked_btres(btv, VIDEO_RESOURCES)) {
2042 min_width = 48;
2043 min_height = 32;
2044
2045 /* We cannot scale up. When the scaled image is larger
2046 than crop.rect we adjust the crop.rect as required
2047 by the V4L2 spec, hence cropcap.bounds are our limit. */
2048 max_width = min(b->width, (__s32) MAX_HACTIVE);
2049 max_height = b->height;
2050
2051 /* We cannot capture the same line as video and VBI data.
2052 Note btv->vbi_end is really a minimum, see
2053 bttv_vbi_try_fmt(). */
2054 if (btv->vbi_end > b->top) {
2055 max_height -= btv->vbi_end - b->top;
2056 rc = -EBUSY;
2057 if (min_height > max_height)
2058 goto fail;
2059 }
2060 } else {
2061 rc = -EBUSY;
2062 if (btv->vbi_end > c->rect.top)
2063 goto fail;
2064
2065 min_width = c->min_scaled_width;
2066 min_height = c->min_scaled_height;
2067 max_width = c->max_scaled_width;
2068 max_height = c->max_scaled_height;
2069
2070 adjust_crop = 0;
2071 }
2072
2073 min_width = (min_width - width_mask - 1) & width_mask;
2074 max_width = max_width & width_mask;
2075
2076 /* Max. scale factor is 16:1 for frames, 8:1 for fields. */
2077 min_height = min_height;
2078 /* Min. scale factor is 1:1. */
2079 max_height >>= !V4L2_FIELD_HAS_BOTH(field);
2080
2081 if (adjust_size) {
2082 *width = clamp(*width, min_width, max_width);
2083 *height = clamp(*height, min_height, max_height);
2084
2085 /* Round after clamping to avoid overflow. */
2086 *width = (*width + width_bias) & width_mask;
2087
2088 if (adjust_crop) {
2089 bttv_crop_adjust(c, b, *width, *height, field);
2090
2091 if (btv->vbi_end > c->rect.top) {
2092 /* Move the crop window out of the way. */
2093 c->rect.top = btv->vbi_end;
2094 }
2095 }
2096 } else {
2097 rc = -EINVAL;
2098 if (*width < min_width ||
2099 *height < min_height ||
2100 *width > max_width ||
2101 *height > max_height ||
2102 0 != (*width & ~width_mask))
2103 goto fail;
2104 }
2105
2106 rc = 0; /* success */
2107
2108 fail:
Michael Schimeke5bd0262007-01-18 16:17:39 -03002109
2110 return rc;
2111}
2112
2113/* Returns an error if the given overlay window dimensions are not
2114 possible with the current cropping parameters. If adjust_size is
2115 TRUE the function may adjust the window width and/or height
2116 instead, however it always rounds the horizontal position and
2117 width as btcx_align() does. If adjust_crop is TRUE the function
2118 may also adjust the current cropping parameters to get closer
2119 to the desired window size. */
2120static int
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002121verify_window_lock (struct bttv_fh * fh,
Michael Schimeke5bd0262007-01-18 16:17:39 -03002122 struct v4l2_window * win,
2123 int adjust_size,
2124 int adjust_crop)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125{
2126 enum v4l2_field field;
Michael Schimeke5bd0262007-01-18 16:17:39 -03002127 unsigned int width_mask;
2128 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129
2130 if (win->w.width < 48 || win->w.height < 32)
2131 return -EINVAL;
2132 if (win->clipcount > 2048)
2133 return -EINVAL;
2134
2135 field = win->field;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136
2137 if (V4L2_FIELD_ANY == field) {
Michael Schimeke5bd0262007-01-18 16:17:39 -03002138 __s32 height2;
2139
2140 height2 = fh->btv->crop[!!fh->do_crop].rect.height >> 1;
2141 field = (win->w.height > height2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142 ? V4L2_FIELD_INTERLACED
2143 : V4L2_FIELD_TOP;
2144 }
2145 switch (field) {
2146 case V4L2_FIELD_TOP:
2147 case V4L2_FIELD_BOTTOM:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002148 case V4L2_FIELD_INTERLACED:
2149 break;
2150 default:
2151 return -EINVAL;
2152 }
2153
Michael Schimeke5bd0262007-01-18 16:17:39 -03002154 /* 4-byte alignment. */
2155 if (NULL == fh->ovfmt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156 return -EINVAL;
Michael Schimeke5bd0262007-01-18 16:17:39 -03002157 width_mask = ~0;
2158 switch (fh->ovfmt->depth) {
2159 case 8:
2160 case 24:
2161 width_mask = ~3;
2162 break;
2163 case 16:
2164 width_mask = ~1;
2165 break;
2166 case 32:
2167 break;
2168 default:
2169 BUG();
2170 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171
Michael Schimeke5bd0262007-01-18 16:17:39 -03002172 win->w.width -= win->w.left & ~width_mask;
2173 win->w.left = (win->w.left - width_mask - 1) & width_mask;
2174
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002175 rc = limit_scaled_size_lock(fh, &win->w.width, &win->w.height,
Michael Schimeke5bd0262007-01-18 16:17:39 -03002176 field, width_mask,
2177 /* width_bias: round down */ 0,
2178 adjust_size, adjust_crop);
2179 if (0 != rc)
2180 return rc;
2181
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182 win->field = field;
2183 return 0;
2184}
2185
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002186static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187 struct v4l2_window *win, int fixup)
2188{
2189 struct v4l2_clip *clips = NULL;
2190 int n,size,retval = 0;
2191
2192 if (NULL == fh->ovfmt)
2193 return -EINVAL;
2194 if (!(fh->ovfmt->flags & FORMAT_FLAGS_PACKED))
2195 return -EINVAL;
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002196 retval = verify_window_lock(fh, win,
Michael Schimeke5bd0262007-01-18 16:17:39 -03002197 /* adjust_size */ fixup,
2198 /* adjust_crop */ fixup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199 if (0 != retval)
2200 return retval;
2201
2202 /* copy clips -- luckily v4l1 + v4l2 are binary
2203 compatible here ...*/
2204 n = win->clipcount;
2205 size = sizeof(*clips)*(n+4);
2206 clips = kmalloc(size,GFP_KERNEL);
2207 if (NULL == clips)
2208 return -ENOMEM;
2209 if (n > 0) {
2210 if (copy_from_user(clips,win->clips,sizeof(struct v4l2_clip)*n)) {
2211 kfree(clips);
2212 return -EFAULT;
2213 }
2214 }
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002215
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216 /* clip against screen */
2217 if (NULL != btv->fbuf.base)
2218 n = btcx_screen_clips(btv->fbuf.fmt.width, btv->fbuf.fmt.height,
2219 &win->w, clips, n);
2220 btcx_sort_clips(clips,n);
2221
2222 /* 4-byte alignments */
2223 switch (fh->ovfmt->depth) {
2224 case 8:
2225 case 24:
2226 btcx_align(&win->w, clips, n, 3);
2227 break;
2228 case 16:
2229 btcx_align(&win->w, clips, n, 1);
2230 break;
2231 case 32:
2232 /* no alignment fixups needed */
2233 break;
2234 default:
2235 BUG();
2236 }
2237
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03002238 kfree(fh->ov.clips);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239 fh->ov.clips = clips;
2240 fh->ov.nclips = n;
2241
2242 fh->ov.w = win->w;
2243 fh->ov.field = win->field;
2244 fh->ov.setup_ok = 1;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002245
Linus Torvalds1da177e2005-04-16 15:20:36 -07002246 btv->init.ov.w.width = win->w.width;
2247 btv->init.ov.w.height = win->w.height;
2248 btv->init.ov.field = win->field;
2249
2250 /* update overlay if needed */
2251 retval = 0;
2252 if (check_btres(fh, RESOURCE_OVERLAY)) {
2253 struct bttv_buffer *new;
2254
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03002255 new = videobuf_sg_alloc(sizeof(*new));
Michael Schimeke5bd0262007-01-18 16:17:39 -03002256 new->crop = btv->crop[!!fh->do_crop].rect;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257 bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
2258 retval = bttv_switch_overlay(btv,fh,new);
2259 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002260 return retval;
2261}
2262
2263/* ----------------------------------------------------------------------- */
2264
2265static struct videobuf_queue* bttv_queue(struct bttv_fh *fh)
2266{
2267 struct videobuf_queue* q = NULL;
2268
2269 switch (fh->type) {
2270 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2271 q = &fh->cap;
2272 break;
2273 case V4L2_BUF_TYPE_VBI_CAPTURE:
2274 q = &fh->vbi;
2275 break;
2276 default:
2277 BUG();
2278 }
2279 return q;
2280}
2281
2282static int bttv_resource(struct bttv_fh *fh)
2283{
2284 int res = 0;
2285
2286 switch (fh->type) {
2287 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Michael Schimeke5bd0262007-01-18 16:17:39 -03002288 res = RESOURCE_VIDEO_STREAM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289 break;
2290 case V4L2_BUF_TYPE_VBI_CAPTURE:
2291 res = RESOURCE_VBI;
2292 break;
2293 default:
2294 BUG();
2295 }
2296 return res;
2297}
2298
2299static int bttv_switch_type(struct bttv_fh *fh, enum v4l2_buf_type type)
2300{
2301 struct videobuf_queue *q = bttv_queue(fh);
2302 int res = bttv_resource(fh);
2303
2304 if (check_btres(fh,res))
2305 return -EBUSY;
2306 if (videobuf_queue_is_busy(q))
2307 return -EBUSY;
2308 fh->type = type;
2309 return 0;
2310}
2311
Michael H. Schimekc87c9482005-12-01 00:51:33 -08002312static void
2313pix_format_set_size (struct v4l2_pix_format * f,
2314 const struct bttv_format * fmt,
2315 unsigned int width,
2316 unsigned int height)
2317{
2318 f->width = width;
2319 f->height = height;
2320
2321 if (fmt->flags & FORMAT_FLAGS_PLANAR) {
2322 f->bytesperline = width; /* Y plane */
2323 f->sizeimage = (width * height * fmt->depth) >> 3;
2324 } else {
2325 f->bytesperline = (width * fmt->depth) >> 3;
2326 f->sizeimage = height * f->bytesperline;
2327 }
2328}
2329
Hans Verkuil78b526a2008-05-28 12:16:41 -03002330static int bttv_g_fmt_vid_cap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002331 struct v4l2_format *f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002333 struct bttv_fh *fh = priv;
2334
2335 pix_format_set_size(&f->fmt.pix, fh->fmt,
2336 fh->width, fh->height);
2337 f->fmt.pix.field = fh->cap.field;
2338 f->fmt.pix.pixelformat = fh->fmt->fourcc;
Hans Verkuilf5864892013-02-06 11:58:59 -03002339 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002340
2341 return 0;
2342}
2343
Hans Verkuil78b526a2008-05-28 12:16:41 -03002344static int bttv_g_fmt_vid_overlay(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002345 struct v4l2_format *f)
2346{
2347 struct bttv_fh *fh = priv;
2348
2349 f->fmt.win.w = fh->ov.w;
2350 f->fmt.win.field = fh->ov.field;
2351
2352 return 0;
2353}
2354
Hans Verkuil78b526a2008-05-28 12:16:41 -03002355static int bttv_try_fmt_vid_cap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002356 struct v4l2_format *f)
2357{
2358 const struct bttv_format *fmt;
2359 struct bttv_fh *fh = priv;
2360 struct bttv *btv = fh->btv;
2361 enum v4l2_field field;
2362 __s32 width, height;
Hans Verkuilee70e3d2013-02-06 12:03:30 -03002363 __s32 height2;
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002364 int rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002365
2366 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
2367 if (NULL == fmt)
2368 return -EINVAL;
2369
2370 field = f->fmt.pix.field;
2371
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002372 switch (field) {
2373 case V4L2_FIELD_TOP:
2374 case V4L2_FIELD_BOTTOM:
2375 case V4L2_FIELD_ALTERNATE:
2376 case V4L2_FIELD_INTERLACED:
2377 break;
Hans Verkuilee70e3d2013-02-06 12:03:30 -03002378 case V4L2_FIELD_SEQ_BT:
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002379 case V4L2_FIELD_SEQ_TB:
Hans Verkuilee70e3d2013-02-06 12:03:30 -03002380 if (!(fmt->flags & FORMAT_FLAGS_PLANAR)) {
2381 field = V4L2_FIELD_SEQ_TB;
2382 break;
2383 }
2384 /* fall through */
2385 default: /* FIELD_ANY case */
2386 height2 = btv->crop[!!fh->do_crop].rect.height >> 1;
2387 field = (f->fmt.pix.height > height2)
2388 ? V4L2_FIELD_INTERLACED
2389 : V4L2_FIELD_BOTTOM;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002390 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002392
2393 width = f->fmt.pix.width;
2394 height = f->fmt.pix.height;
2395
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002396 rc = limit_scaled_size_lock(fh, &width, &height, field,
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002397 /* width_mask: 4 pixels */ ~3,
2398 /* width_bias: nearest */ 2,
2399 /* adjust_size */ 1,
2400 /* adjust_crop */ 0);
2401 if (0 != rc)
2402 return rc;
2403
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002404 /* update data for the application */
2405 f->fmt.pix.field = field;
2406 pix_format_set_size(&f->fmt.pix, fmt, width, height);
Hans Verkuilf5864892013-02-06 11:58:59 -03002407 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002408
2409 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410}
2411
Hans Verkuil78b526a2008-05-28 12:16:41 -03002412static int bttv_try_fmt_vid_overlay(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002413 struct v4l2_format *f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002415 struct bttv_fh *fh = priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002416
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002417 return verify_window_lock(fh, &f->fmt.win,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002418 /* adjust_size */ 1,
2419 /* adjust_crop */ 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420}
2421
Hans Verkuil78b526a2008-05-28 12:16:41 -03002422static int bttv_s_fmt_vid_cap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002423 struct v4l2_format *f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424{
2425 int retval;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002426 const struct bttv_format *fmt;
2427 struct bttv_fh *fh = priv;
2428 struct bttv *btv = fh->btv;
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002429 __s32 width, height;
2430 enum v4l2_field field;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002432 retval = bttv_switch_type(fh, f->type);
2433 if (0 != retval)
2434 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435
Hans Verkuil78b526a2008-05-28 12:16:41 -03002436 retval = bttv_try_fmt_vid_cap(file, priv, f);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002437 if (0 != retval)
2438 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002439
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002440 width = f->fmt.pix.width;
2441 height = f->fmt.pix.height;
2442 field = f->fmt.pix.field;
2443
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002444 retval = limit_scaled_size_lock(fh, &width, &height, f->fmt.pix.field,
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002445 /* width_mask: 4 pixels */ ~3,
2446 /* width_bias: nearest */ 2,
2447 /* adjust_size */ 1,
2448 /* adjust_crop */ 1);
2449 if (0 != retval)
2450 return retval;
2451
2452 f->fmt.pix.field = field;
2453
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002454 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002456 /* update our state informations */
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002457 fh->fmt = fmt;
2458 fh->cap.field = f->fmt.pix.field;
2459 fh->cap.last = V4L2_FIELD_NONE;
2460 fh->width = f->fmt.pix.width;
2461 fh->height = f->fmt.pix.height;
2462 btv->init.fmt = fmt;
2463 btv->init.width = f->fmt.pix.width;
2464 btv->init.height = f->fmt.pix.height;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002465
2466 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002467}
2468
Hans Verkuil78b526a2008-05-28 12:16:41 -03002469static int bttv_s_fmt_vid_overlay(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002470 struct v4l2_format *f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002472 struct bttv_fh *fh = priv;
2473 struct bttv *btv = fh->btv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002475 if (no_overlay > 0) {
Joe Perches8af443e2011-08-21 19:56:48 -03002476 pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002477 return -EINVAL;
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002478 }
Michael Krufky5e453dc2006-01-09 15:32:31 -02002479
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002480 return setup_window_lock(fh, btv, &f->fmt.win, 1);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002481}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002483static int bttv_querycap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002484 struct v4l2_capability *cap)
2485{
Hans Verkuil78dea1a2012-09-09 09:03:29 -03002486 struct video_device *vdev = video_devdata(file);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002487 struct bttv_fh *fh = priv;
2488 struct bttv *btv = fh->btv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002489
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002490 if (0 == v4l2)
2491 return -EINVAL;
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07002492
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002493 strlcpy(cap->driver, "bttv", sizeof(cap->driver));
2494 strlcpy(cap->card, btv->video_dev->name, sizeof(cap->card));
2495 snprintf(cap->bus_info, sizeof(cap->bus_info),
2496 "PCI:%s", pci_name(btv->c.pci));
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002497 cap->capabilities =
2498 V4L2_CAP_VIDEO_CAPTURE |
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002499 V4L2_CAP_READWRITE |
Hans Verkuil78dea1a2012-09-09 09:03:29 -03002500 V4L2_CAP_STREAMING |
2501 V4L2_CAP_DEVICE_CAPS;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002502 if (no_overlay <= 0)
2503 cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
Hans Verkuil78dea1a2012-09-09 09:03:29 -03002504 if (btv->vbi_dev)
2505 cap->capabilities |= V4L2_CAP_VBI_CAPTURE;
2506 if (btv->radio_dev)
2507 cap->capabilities |= V4L2_CAP_RADIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002509 /*
2510 * No need to lock here: those vars are initialized during board
2511 * probe and remains untouched during the rest of the driver lifecycle
2512 */
2513 if (btv->has_saa6588)
2514 cap->capabilities |= V4L2_CAP_RDS_CAPTURE;
Trent Piephoabb03622009-01-28 21:32:59 -03002515 if (btv->tuner_type != TUNER_ABSENT)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002516 cap->capabilities |= V4L2_CAP_TUNER;
Hans Verkuil78dea1a2012-09-09 09:03:29 -03002517 if (vdev->vfl_type == VFL_TYPE_GRABBER)
2518 cap->device_caps = cap->capabilities &
2519 (V4L2_CAP_VIDEO_CAPTURE |
2520 V4L2_CAP_READWRITE |
2521 V4L2_CAP_STREAMING |
2522 V4L2_CAP_VIDEO_OVERLAY |
2523 V4L2_CAP_TUNER);
2524 else if (vdev->vfl_type == VFL_TYPE_VBI)
2525 cap->device_caps = cap->capabilities &
2526 (V4L2_CAP_VBI_CAPTURE |
2527 V4L2_CAP_READWRITE |
2528 V4L2_CAP_STREAMING |
2529 V4L2_CAP_TUNER);
2530 else {
2531 cap->device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER;
2532 if (btv->has_saa6588)
2533 cap->device_caps |= V4L2_CAP_READWRITE |
2534 V4L2_CAP_RDS_CAPTURE;
2535 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002536 return 0;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002537}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002538
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002539static int bttv_enum_fmt_cap_ovr(struct v4l2_fmtdesc *f)
2540{
2541 int index = -1, i;
2542
2543 for (i = 0; i < FORMATS; i++) {
2544 if (formats[i].fourcc != -1)
2545 index++;
2546 if ((unsigned int)index == f->index)
2547 break;
2548 }
2549 if (FORMATS == i)
2550 return -EINVAL;
2551
2552 f->pixelformat = formats[i].fourcc;
2553 strlcpy(f->description, formats[i].name, sizeof(f->description));
2554
2555 return i;
2556}
2557
Hans Verkuil78b526a2008-05-28 12:16:41 -03002558static int bttv_enum_fmt_vid_cap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002559 struct v4l2_fmtdesc *f)
2560{
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002561 int rc = bttv_enum_fmt_cap_ovr(f);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002562
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002563 if (rc < 0)
2564 return rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002565
2566 return 0;
2567}
2568
Hans Verkuil78b526a2008-05-28 12:16:41 -03002569static int bttv_enum_fmt_vid_overlay(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002570 struct v4l2_fmtdesc *f)
2571{
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002572 int rc;
2573
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002574 if (no_overlay > 0) {
Joe Perches8af443e2011-08-21 19:56:48 -03002575 pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002576 return -EINVAL;
2577 }
2578
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002579 rc = bttv_enum_fmt_cap_ovr(f);
2580
2581 if (rc < 0)
2582 return rc;
2583
2584 if (!(formats[rc].flags & FORMAT_FLAGS_PACKED))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002585 return -EINVAL;
2586
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002587 return 0;
2588}
2589
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002590static int bttv_g_fbuf(struct file *file, void *f,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002591 struct v4l2_framebuffer *fb)
2592{
2593 struct bttv_fh *fh = f;
2594 struct bttv *btv = fh->btv;
2595
2596 *fb = btv->fbuf;
2597 fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
Hans Verkuila12fd702013-02-06 12:00:03 -03002598 fb->flags = V4L2_FBUF_FLAG_PRIMARY;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002599 if (fh->ovfmt)
2600 fb->fmt.pixelformat = fh->ovfmt->fourcc;
2601 return 0;
2602}
2603
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002604static int bttv_overlay(struct file *file, void *f, unsigned int on)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002605{
2606 struct bttv_fh *fh = f;
2607 struct bttv *btv = fh->btv;
2608 struct bttv_buffer *new;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002609 int retval = 0;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002610
2611 if (on) {
2612 /* verify args */
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002613 if (unlikely(!btv->fbuf.base)) {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002614 return -EINVAL;
2615 }
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002616 if (unlikely(!fh->ov.setup_ok)) {
Joe Perches8af443e2011-08-21 19:56:48 -03002617 dprintk("%d: overlay: !setup_ok\n", btv->c.nr);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002618 retval = -EINVAL;
2619 }
2620 if (retval)
2621 return retval;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002622 }
2623
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002624 if (!check_alloc_btres_lock(btv, fh, RESOURCE_OVERLAY))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002625 return -EBUSY;
2626
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002627 if (on) {
2628 fh->ov.tvnorm = btv->tvnorm;
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03002629 new = videobuf_sg_alloc(sizeof(*new));
Robert Fitzsimons7c018802008-02-13 16:38:11 -03002630 new->crop = btv->crop[!!fh->do_crop].rect;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002631 bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
2632 } else {
2633 new = NULL;
2634 }
2635
2636 /* switch over */
2637 retval = bttv_switch_overlay(btv, fh, new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002638 return retval;
2639}
2640
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002641static int bttv_s_fbuf(struct file *file, void *f,
Hans Verkuile6eb28c2012-09-04 10:26:45 -03002642 const struct v4l2_framebuffer *fb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002644 struct bttv_fh *fh = f;
2645 struct bttv *btv = fh->btv;
2646 const struct bttv_format *fmt;
2647 int retval;
2648
2649 if (!capable(CAP_SYS_ADMIN) &&
2650 !capable(CAP_SYS_RAWIO))
2651 return -EPERM;
2652
2653 /* check args */
2654 fmt = format_by_fourcc(fb->fmt.pixelformat);
2655 if (NULL == fmt)
2656 return -EINVAL;
2657 if (0 == (fmt->flags & FORMAT_FLAGS_PACKED))
2658 return -EINVAL;
2659
2660 retval = -EINVAL;
2661 if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
2662 __s32 width = fb->fmt.width;
2663 __s32 height = fb->fmt.height;
2664
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002665 retval = limit_scaled_size_lock(fh, &width, &height,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002666 V4L2_FIELD_INTERLACED,
2667 /* width_mask */ ~3,
2668 /* width_bias */ 2,
2669 /* adjust_size */ 0,
2670 /* adjust_crop */ 0);
2671 if (0 != retval)
2672 return retval;
2673 }
2674
2675 /* ok, accept it */
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002676 btv->fbuf.base = fb->base;
2677 btv->fbuf.fmt.width = fb->fmt.width;
2678 btv->fbuf.fmt.height = fb->fmt.height;
2679 if (0 != fb->fmt.bytesperline)
2680 btv->fbuf.fmt.bytesperline = fb->fmt.bytesperline;
2681 else
2682 btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fmt->depth/8;
2683
2684 retval = 0;
2685 fh->ovfmt = fmt;
2686 btv->init.ovfmt = fmt;
2687 if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
2688 fh->ov.w.left = 0;
2689 fh->ov.w.top = 0;
2690 fh->ov.w.width = fb->fmt.width;
2691 fh->ov.w.height = fb->fmt.height;
2692 btv->init.ov.w.width = fb->fmt.width;
2693 btv->init.ov.w.height = fb->fmt.height;
2694 kfree(fh->ov.clips);
2695 fh->ov.clips = NULL;
2696 fh->ov.nclips = 0;
2697
2698 if (check_btres(fh, RESOURCE_OVERLAY)) {
2699 struct bttv_buffer *new;
2700
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03002701 new = videobuf_sg_alloc(sizeof(*new));
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002702 new->crop = btv->crop[!!fh->do_crop].rect;
2703 bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
2704 retval = bttv_switch_overlay(btv, fh, new);
2705 }
2706 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002707 return retval;
2708}
2709
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002710static int bttv_reqbufs(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002711 struct v4l2_requestbuffers *p)
2712{
2713 struct bttv_fh *fh = priv;
2714 return videobuf_reqbufs(bttv_queue(fh), p);
2715}
2716
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002717static int bttv_querybuf(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002718 struct v4l2_buffer *b)
2719{
2720 struct bttv_fh *fh = priv;
2721 return videobuf_querybuf(bttv_queue(fh), b);
2722}
2723
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002724static int bttv_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002725{
2726 struct bttv_fh *fh = priv;
2727 struct bttv *btv = fh->btv;
2728 int res = bttv_resource(fh);
2729
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002730 if (!check_alloc_btres_lock(btv, fh, res))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002731 return -EBUSY;
2732
2733 return videobuf_qbuf(bttv_queue(fh), b);
2734}
2735
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002736static int bttv_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002737{
2738 struct bttv_fh *fh = priv;
2739 return videobuf_dqbuf(bttv_queue(fh), b,
2740 file->f_flags & O_NONBLOCK);
2741}
2742
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002743static int bttv_streamon(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002744 enum v4l2_buf_type type)
2745{
2746 struct bttv_fh *fh = priv;
2747 struct bttv *btv = fh->btv;
2748 int res = bttv_resource(fh);
2749
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002750 if (!check_alloc_btres_lock(btv, fh, res))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002751 return -EBUSY;
2752 return videobuf_streamon(bttv_queue(fh));
2753}
2754
2755
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002756static int bttv_streamoff(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002757 enum v4l2_buf_type type)
2758{
2759 struct bttv_fh *fh = priv;
2760 struct bttv *btv = fh->btv;
2761 int retval;
2762 int res = bttv_resource(fh);
2763
2764
2765 retval = videobuf_streamoff(bttv_queue(fh));
2766 if (retval < 0)
2767 return retval;
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002768 free_btres_lock(btv, fh, res);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002769 return 0;
2770}
2771
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002772static int bttv_g_parm(struct file *file, void *f,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002773 struct v4l2_streamparm *parm)
2774{
2775 struct bttv_fh *fh = f;
2776 struct bttv *btv = fh->btv;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002777
Hans Verkuila652ef62012-09-09 10:27:57 -03002778 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
2779 return -EINVAL;
2780 parm->parm.capture.readbuffers = gbuffers;
Trent Piepho51f0b8d2009-03-04 01:21:02 -03002781 v4l2_video_std_frame_period(bttv_tvnorms[btv->tvnorm].v4l2_id,
2782 &parm->parm.capture.timeperframe);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002783
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002784 return 0;
2785}
2786
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002787static int bttv_g_tuner(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002788 struct v4l2_tuner *t)
2789{
2790 struct bttv_fh *fh = priv;
2791 struct bttv *btv = fh->btv;
2792
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002793 if (0 != t->index)
2794 return -EINVAL;
2795
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002796 t->rxsubchans = V4L2_TUNER_SUB_MONO;
Hans Verkuil859f0272009-03-28 08:29:00 -03002797 bttv_call_all(btv, tuner, g_tuner, t);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002798 strcpy(t->name, "Television");
2799 t->capability = V4L2_TUNER_CAP_NORM;
2800 t->type = V4L2_TUNER_ANALOG_TV;
2801 if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)
2802 t->signal = 0xffff;
2803
2804 if (btv->audio_mode_gpio)
2805 btv->audio_mode_gpio(btv, t, 0);
2806
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002807 return 0;
2808}
2809
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002810static int bttv_g_priority(struct file *file, void *f, enum v4l2_priority *p)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002811{
2812 struct bttv_fh *fh = f;
2813 struct bttv *btv = fh->btv;
2814
2815 *p = v4l2_prio_max(&btv->prio);
2816
2817 return 0;
2818}
2819
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002820static int bttv_s_priority(struct file *file, void *f,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002821 enum v4l2_priority prio)
2822{
2823 struct bttv_fh *fh = f;
2824 struct bttv *btv = fh->btv;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002825 int rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002826
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002827 rc = v4l2_prio_change(&btv->prio, &fh->prio, prio);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002828
2829 return rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002830}
2831
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002832static int bttv_cropcap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002833 struct v4l2_cropcap *cap)
2834{
2835 struct bttv_fh *fh = priv;
2836 struct bttv *btv = fh->btv;
2837
2838 if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
2839 cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
2840 return -EINVAL;
2841
2842 *cap = bttv_tvnorms[btv->tvnorm].cropcap;
2843
2844 return 0;
2845}
2846
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002847static int bttv_g_crop(struct file *file, void *f, struct v4l2_crop *crop)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002848{
2849 struct bttv_fh *fh = f;
2850 struct bttv *btv = fh->btv;
2851
2852 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
2853 crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
2854 return -EINVAL;
2855
2856 /* No fh->do_crop = 1; because btv->crop[1] may be
2857 inconsistent with fh->width or fh->height and apps
2858 do not expect a change here. */
2859
2860 crop->c = btv->crop[!!fh->do_crop].rect;
2861
2862 return 0;
2863}
2864
Hans Verkuil4f9965942012-09-05 05:10:48 -03002865static int bttv_s_crop(struct file *file, void *f, const struct v4l2_crop *crop)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002866{
2867 struct bttv_fh *fh = f;
2868 struct bttv *btv = fh->btv;
2869 const struct v4l2_rect *b;
2870 int retval;
2871 struct bttv_crop c;
2872 __s32 b_left;
2873 __s32 b_top;
2874 __s32 b_right;
2875 __s32 b_bottom;
2876
2877 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
2878 crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
2879 return -EINVAL;
2880
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002881 /* Make sure tvnorm, vbi_end and the current cropping
2882 parameters remain consistent until we're done. Note
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002883 read() may change vbi_end in check_alloc_btres_lock(). */
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002884 retval = v4l2_prio_check(&btv->prio, fh->prio);
2885 if (0 != retval) {
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002886 return retval;
2887 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002888
2889 retval = -EBUSY;
2890
2891 if (locked_btres(fh->btv, VIDEO_RESOURCES)) {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002892 return retval;
2893 }
2894
2895 b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
2896
2897 b_left = b->left;
2898 b_right = b_left + b->width;
2899 b_bottom = b->top + b->height;
2900
2901 b_top = max(b->top, btv->vbi_end);
2902 if (b_top + 32 >= b_bottom) {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002903 return retval;
2904 }
2905
2906 /* Min. scaled size 48 x 32. */
Hans Verkuil4f9965942012-09-05 05:10:48 -03002907 c.rect.left = clamp_t(s32, crop->c.left, b_left, b_right - 48);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002908 c.rect.left = min(c.rect.left, (__s32) MAX_HDELAY);
2909
Hans Verkuil4f9965942012-09-05 05:10:48 -03002910 c.rect.width = clamp_t(s32, crop->c.width,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002911 48, b_right - c.rect.left);
2912
Hans Verkuil4f9965942012-09-05 05:10:48 -03002913 c.rect.top = clamp_t(s32, crop->c.top, b_top, b_bottom - 32);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002914 /* Top and height must be a multiple of two. */
2915 c.rect.top = (c.rect.top + 1) & ~1;
2916
Hans Verkuil4f9965942012-09-05 05:10:48 -03002917 c.rect.height = clamp_t(s32, crop->c.height,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002918 32, b_bottom - c.rect.top);
2919 c.rect.height = (c.rect.height + 1) & ~1;
2920
2921 bttv_crop_calc_limits(&c);
2922
2923 btv->crop[1] = c;
2924
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002925 fh->do_crop = 1;
2926
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002927 if (fh->width < c.min_scaled_width) {
2928 fh->width = c.min_scaled_width;
2929 btv->init.width = c.min_scaled_width;
2930 } else if (fh->width > c.max_scaled_width) {
2931 fh->width = c.max_scaled_width;
2932 btv->init.width = c.max_scaled_width;
2933 }
2934
2935 if (fh->height < c.min_scaled_height) {
2936 fh->height = c.min_scaled_height;
2937 btv->init.height = c.min_scaled_height;
2938 } else if (fh->height > c.max_scaled_height) {
2939 fh->height = c.max_scaled_height;
2940 btv->init.height = c.max_scaled_height;
2941 }
2942
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002943 return 0;
2944}
2945
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002946static int bttv_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002947{
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03002948 if (unlikely(a->index))
2949 return -EINVAL;
2950
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002951 strcpy(a->name, "audio");
2952 return 0;
2953}
2954
Hans Verkuil0e8025b2012-09-04 11:59:31 -03002955static int bttv_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002956{
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03002957 if (unlikely(a->index))
2958 return -EINVAL;
2959
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002960 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002961}
2962
2963static ssize_t bttv_read(struct file *file, char __user *data,
2964 size_t count, loff_t *ppos)
2965{
2966 struct bttv_fh *fh = file->private_data;
2967 int retval = 0;
2968
2969 if (fh->btv->errors)
2970 bttv_reinit_bt848(fh->btv);
Joe Perches8af443e2011-08-21 19:56:48 -03002971 dprintk("%d: read count=%d type=%s\n",
2972 fh->btv->c.nr, (int)count, v4l2_type_names[fh->type]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002973
2974 switch (fh->type) {
2975 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002976 if (!check_alloc_btres_lock(fh->btv, fh, RESOURCE_VIDEO_READ)) {
Michael Schimeke5bd0262007-01-18 16:17:39 -03002977 /* VIDEO_READ in use by another fh,
2978 or VIDEO_STREAM by any fh. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002979 return -EBUSY;
Michael Schimeke5bd0262007-01-18 16:17:39 -03002980 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002981 retval = videobuf_read_one(&fh->cap, data, count, ppos,
2982 file->f_flags & O_NONBLOCK);
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002983 free_btres_lock(fh->btv, fh, RESOURCE_VIDEO_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002984 break;
2985 case V4L2_BUF_TYPE_VBI_CAPTURE:
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002986 if (!check_alloc_btres_lock(fh->btv,fh,RESOURCE_VBI))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002987 return -EBUSY;
2988 retval = videobuf_read_stream(&fh->vbi, data, count, ppos, 1,
2989 file->f_flags & O_NONBLOCK);
2990 break;
2991 default:
2992 BUG();
2993 }
2994 return retval;
2995}
2996
2997static unsigned int bttv_poll(struct file *file, poll_table *wait)
2998{
2999 struct bttv_fh *fh = file->private_data;
3000 struct bttv_buffer *buf;
3001 enum v4l2_field field;
Figo.zhang9fd64182009-06-16 13:31:29 -03003002 unsigned int rc = POLLERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003003
3004 if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003005 if (!check_alloc_btres_lock(fh->btv,fh,RESOURCE_VBI))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003006 return POLLERR;
3007 return videobuf_poll_stream(file, &fh->vbi, wait);
3008 }
3009
Michael Schimeke5bd0262007-01-18 16:17:39 -03003010 if (check_btres(fh,RESOURCE_VIDEO_STREAM)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003011 /* streaming capture */
3012 if (list_empty(&fh->cap.stream))
Figo.zhang9fd64182009-06-16 13:31:29 -03003013 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003014 buf = list_entry(fh->cap.stream.next,struct bttv_buffer,vb.stream);
3015 } else {
3016 /* read() capture */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017 if (NULL == fh->cap.read_buf) {
3018 /* need to capture a new frame */
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03003019 if (locked_btres(fh->btv,RESOURCE_VIDEO_STREAM))
3020 goto err;
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03003021 fh->cap.read_buf = videobuf_sg_alloc(fh->cap.msize);
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03003022 if (NULL == fh->cap.read_buf)
3023 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024 fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR;
3025 field = videobuf_next_field(&fh->cap);
3026 if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,field)) {
Nickolay V. Shmyrev50ab5ed2005-12-01 00:51:32 -08003027 kfree (fh->cap.read_buf);
3028 fh->cap.read_buf = NULL;
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03003029 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003030 }
3031 fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf);
3032 fh->cap.read_off = 0;
3033 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034 buf = (struct bttv_buffer*)fh->cap.read_buf;
3035 }
3036
3037 poll_wait(file, &buf->vb.done, wait);
Brandon Philips0fc06862007-11-06 20:02:36 -03003038 if (buf->vb.state == VIDEOBUF_DONE ||
3039 buf->vb.state == VIDEOBUF_ERROR)
Figo.zhang9fd64182009-06-16 13:31:29 -03003040 rc = POLLIN|POLLRDNORM;
3041 else
3042 rc = 0;
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03003043err:
Figo.zhang9fd64182009-06-16 13:31:29 -03003044 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003045}
3046
Hans Verkuilbec43662008-12-30 06:58:20 -03003047static int bttv_open(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003048{
Laurent Pinchart50462eb2009-12-10 11:47:13 -02003049 struct video_device *vdev = video_devdata(file);
Trent Piepho4b10d3b2009-01-28 21:32:59 -03003050 struct bttv *btv = video_drvdata(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003051 struct bttv_fh *fh;
3052 enum v4l2_buf_type type = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003053
Joe Perches8af443e2011-08-21 19:56:48 -03003054 dprintk("open dev=%s\n", video_device_node_name(vdev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003055
Laurent Pinchart327ae592009-11-27 13:57:55 -03003056 if (vdev->vfl_type == VFL_TYPE_GRABBER) {
Trent Piepho4b10d3b2009-01-28 21:32:59 -03003057 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Laurent Pinchart327ae592009-11-27 13:57:55 -03003058 } else if (vdev->vfl_type == VFL_TYPE_VBI) {
Trent Piepho4b10d3b2009-01-28 21:32:59 -03003059 type = V4L2_BUF_TYPE_VBI_CAPTURE;
3060 } else {
3061 WARN_ON(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003062 return -ENODEV;
Hans Verkuild56dc612008-07-30 08:43:36 -03003063 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003064
Joe Perches8af443e2011-08-21 19:56:48 -03003065 dprintk("%d: open called (type=%s)\n",
3066 btv->c.nr, v4l2_type_names[type]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003067
3068 /* allocate per filehandle data */
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003069 fh = kmalloc(sizeof(*fh), GFP_KERNEL);
3070 if (unlikely(!fh))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003071 return -ENOMEM;
Hans Verkuil01df5302013-02-06 12:40:28 -03003072 btv->users++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003073 file->private_data = fh;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003074
Linus Torvalds1da177e2005-04-16 15:20:36 -07003075 *fh = btv->init;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003076
Linus Torvalds1da177e2005-04-16 15:20:36 -07003077 fh->type = type;
3078 fh->ov.setup_ok = 0;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003079
Hans Verkuilffb48772010-05-01 08:03:24 -03003080 v4l2_prio_open(&btv->prio, &fh->prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003081
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03003082 videobuf_queue_sg_init(&fh->cap, &bttv_video_qops,
3083 &btv->c.pci->dev, &btv->s_lock,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003084 V4L2_BUF_TYPE_VIDEO_CAPTURE,
3085 V4L2_FIELD_INTERLACED,
3086 sizeof(struct bttv_buffer),
Mauro Carvalho Chehab587f0d52010-12-15 18:45:42 -03003087 fh, &btv->lock);
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03003088 videobuf_queue_sg_init(&fh->vbi, &bttv_vbi_qops,
3089 &btv->c.pci->dev, &btv->s_lock,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003090 V4L2_BUF_TYPE_VBI_CAPTURE,
3091 V4L2_FIELD_SEQ_TB,
3092 sizeof(struct bttv_buffer),
Mauro Carvalho Chehab587f0d52010-12-15 18:45:42 -03003093 fh, &btv->lock);
Nickolay V. Shmyrev302f61a2007-10-26 10:53:21 -03003094 set_tvnorm(btv,btv->tvnorm);
Mauro Carvalho Chehabb46a9c82008-08-05 10:12:35 -03003095 set_input(btv, btv->input, btv->tvnorm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003096
Michael Schimeke5bd0262007-01-18 16:17:39 -03003097
3098 /* The V4L2 spec requires one global set of cropping parameters
3099 which only change on request. These are stored in btv->crop[1].
3100 However for compatibility with V4L apps and cropping unaware
3101 V4L2 apps we now reset the cropping parameters as seen through
3102 this fh, which is to say VIDIOC_G_CROP and scaling limit checks
3103 will use btv->crop[0], the default cropping parameters for the
3104 current video standard, and VIDIOC_S_FMT will not implicitely
3105 change the cropping parameters until VIDIOC_S_CROP has been
3106 called. */
3107 fh->do_crop = !reset_crop; /* module parameter */
3108
3109 /* Likewise there should be one global set of VBI capture
3110 parameters, but for compatibility with V4L apps and earlier
3111 driver versions each fh has its own parameters. */
3112 bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm);
3113
Linus Torvalds1da177e2005-04-16 15:20:36 -07003114 bttv_field_count(btv);
3115 return 0;
3116}
3117
Hans Verkuilbec43662008-12-30 06:58:20 -03003118static int bttv_release(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003119{
3120 struct bttv_fh *fh = file->private_data;
3121 struct bttv *btv = fh->btv;
3122
3123 /* turn off overlay */
3124 if (check_btres(fh, RESOURCE_OVERLAY))
3125 bttv_switch_overlay(btv,fh,NULL);
3126
3127 /* stop video capture */
Michael Schimeke5bd0262007-01-18 16:17:39 -03003128 if (check_btres(fh, RESOURCE_VIDEO_STREAM)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003129 videobuf_streamoff(&fh->cap);
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003130 free_btres_lock(btv,fh,RESOURCE_VIDEO_STREAM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003131 }
3132 if (fh->cap.read_buf) {
3133 buffer_release(&fh->cap,fh->cap.read_buf);
3134 kfree(fh->cap.read_buf);
3135 }
Michael Schimeke5bd0262007-01-18 16:17:39 -03003136 if (check_btres(fh, RESOURCE_VIDEO_READ)) {
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003137 free_btres_lock(btv, fh, RESOURCE_VIDEO_READ);
Michael Schimeke5bd0262007-01-18 16:17:39 -03003138 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003139
3140 /* stop vbi capture */
3141 if (check_btres(fh, RESOURCE_VBI)) {
Brandon Philips053fcb62007-11-13 20:11:26 -03003142 videobuf_stop(&fh->vbi);
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003143 free_btres_lock(btv,fh,RESOURCE_VBI);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003144 }
3145
3146 /* free stuff */
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003147
Linus Torvalds1da177e2005-04-16 15:20:36 -07003148 videobuf_mmap_free(&fh->cap);
3149 videobuf_mmap_free(&fh->vbi);
Hans Verkuilffb48772010-05-01 08:03:24 -03003150 v4l2_prio_close(&btv->prio, fh->prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003151 file->private_data = NULL;
3152 kfree(fh);
3153
3154 btv->users--;
3155 bttv_field_count(btv);
Mauro Carvalho Chehabb46a9c82008-08-05 10:12:35 -03003156
3157 if (!btv->users)
Hans Verkuil01df5302013-02-06 12:40:28 -03003158 audio_mute(btv, btv->mute);
Mauro Carvalho Chehabb46a9c82008-08-05 10:12:35 -03003159
Linus Torvalds1da177e2005-04-16 15:20:36 -07003160 return 0;
3161}
3162
3163static int
3164bttv_mmap(struct file *file, struct vm_area_struct *vma)
3165{
3166 struct bttv_fh *fh = file->private_data;
3167
Joe Perches8af443e2011-08-21 19:56:48 -03003168 dprintk("%d: mmap type=%s 0x%lx+%ld\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003169 fh->btv->c.nr, v4l2_type_names[fh->type],
3170 vma->vm_start, vma->vm_end - vma->vm_start);
3171 return videobuf_mmap_mapper(bttv_queue(fh),vma);
3172}
3173
Hans Verkuilbec43662008-12-30 06:58:20 -03003174static const struct v4l2_file_operations bttv_fops =
Linus Torvalds1da177e2005-04-16 15:20:36 -07003175{
Mauro Carvalho Chehab8979e9d2010-09-15 08:22:09 -03003176 .owner = THIS_MODULE,
3177 .open = bttv_open,
3178 .release = bttv_release,
3179 .unlocked_ioctl = video_ioctl2,
3180 .read = bttv_read,
3181 .mmap = bttv_mmap,
3182 .poll = bttv_poll,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003183};
3184
Hans Verkuila3998102008-07-21 02:57:38 -03003185static const struct v4l2_ioctl_ops bttv_ioctl_ops = {
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003186 .vidioc_querycap = bttv_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03003187 .vidioc_enum_fmt_vid_cap = bttv_enum_fmt_vid_cap,
3188 .vidioc_g_fmt_vid_cap = bttv_g_fmt_vid_cap,
3189 .vidioc_try_fmt_vid_cap = bttv_try_fmt_vid_cap,
3190 .vidioc_s_fmt_vid_cap = bttv_s_fmt_vid_cap,
3191 .vidioc_enum_fmt_vid_overlay = bttv_enum_fmt_vid_overlay,
3192 .vidioc_g_fmt_vid_overlay = bttv_g_fmt_vid_overlay,
3193 .vidioc_try_fmt_vid_overlay = bttv_try_fmt_vid_overlay,
3194 .vidioc_s_fmt_vid_overlay = bttv_s_fmt_vid_overlay,
Hans Verkuil78b526a2008-05-28 12:16:41 -03003195 .vidioc_g_fmt_vbi_cap = bttv_g_fmt_vbi_cap,
3196 .vidioc_try_fmt_vbi_cap = bttv_try_fmt_vbi_cap,
3197 .vidioc_s_fmt_vbi_cap = bttv_s_fmt_vbi_cap,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003198 .vidioc_g_audio = bttv_g_audio,
3199 .vidioc_s_audio = bttv_s_audio,
3200 .vidioc_cropcap = bttv_cropcap,
3201 .vidioc_reqbufs = bttv_reqbufs,
3202 .vidioc_querybuf = bttv_querybuf,
3203 .vidioc_qbuf = bttv_qbuf,
3204 .vidioc_dqbuf = bttv_dqbuf,
3205 .vidioc_s_std = bttv_s_std,
3206 .vidioc_enum_input = bttv_enum_input,
3207 .vidioc_g_input = bttv_g_input,
3208 .vidioc_s_input = bttv_s_input,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003209 .vidioc_streamon = bttv_streamon,
3210 .vidioc_streamoff = bttv_streamoff,
3211 .vidioc_g_tuner = bttv_g_tuner,
3212 .vidioc_s_tuner = bttv_s_tuner,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003213 .vidioc_g_crop = bttv_g_crop,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003214 .vidioc_s_crop = bttv_s_crop,
3215 .vidioc_g_fbuf = bttv_g_fbuf,
3216 .vidioc_s_fbuf = bttv_s_fbuf,
3217 .vidioc_overlay = bttv_overlay,
3218 .vidioc_g_priority = bttv_g_priority,
3219 .vidioc_s_priority = bttv_s_priority,
3220 .vidioc_g_parm = bttv_g_parm,
3221 .vidioc_g_frequency = bttv_g_frequency,
3222 .vidioc_s_frequency = bttv_s_frequency,
3223 .vidioc_log_status = bttv_log_status,
3224 .vidioc_querystd = bttv_querystd,
Hans Verkuil1b9e94d2012-09-09 09:23:31 -03003225 .vidioc_g_chip_ident = bttv_g_chip_ident,
Zoltan Devai43846832008-01-14 13:24:38 -03003226#ifdef CONFIG_VIDEO_ADV_DEBUG
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003227 .vidioc_g_register = bttv_g_register,
3228 .vidioc_s_register = bttv_s_register,
Zoltan Devai43846832008-01-14 13:24:38 -03003229#endif
Hans Verkuila3998102008-07-21 02:57:38 -03003230};
3231
3232static struct video_device bttv_video_template = {
3233 .fops = &bttv_fops,
Hans Verkuila3998102008-07-21 02:57:38 -03003234 .ioctl_ops = &bttv_ioctl_ops,
3235 .tvnorms = BTTV_NORMS,
3236 .current_norm = V4L2_STD_PAL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003237};
3238
Linus Torvalds1da177e2005-04-16 15:20:36 -07003239/* ----------------------------------------------------------------------- */
3240/* radio interface */
3241
Hans Verkuilbec43662008-12-30 06:58:20 -03003242static int radio_open(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003243{
Laurent Pinchart50462eb2009-12-10 11:47:13 -02003244 struct video_device *vdev = video_devdata(file);
Trent Piepho4b10d3b2009-01-28 21:32:59 -03003245 struct bttv *btv = video_drvdata(file);
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003246 struct bttv_fh *fh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003247
Joe Perches8af443e2011-08-21 19:56:48 -03003248 dprintk("open dev=%s\n", video_device_node_name(vdev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003249
Joe Perches8af443e2011-08-21 19:56:48 -03003250 dprintk("%d: open called (radio)\n", btv->c.nr);
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003251
3252 /* allocate per filehandle data */
3253 fh = kmalloc(sizeof(*fh), GFP_KERNEL);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003254 if (unlikely(!fh))
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003255 return -ENOMEM;
3256 file->private_data = fh;
3257 *fh = btv->init;
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003258
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003259 v4l2_prio_open(&btv->prio, &fh->prio);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003260
Linus Torvalds1da177e2005-04-16 15:20:36 -07003261 btv->radio_user++;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003262
Hans Verkuil859f0272009-03-28 08:29:00 -03003263 bttv_call_all(btv, tuner, s_radio);
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03003264 audio_input(btv,TVAUDIO_INPUT_RADIO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003265
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003266 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003267}
3268
Hans Verkuilbec43662008-12-30 06:58:20 -03003269static int radio_release(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003270{
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003271 struct bttv_fh *fh = file->private_data;
3272 struct bttv *btv = fh->btv;
Hans Verkuilb9218f22010-12-27 12:22:46 -03003273 struct saa6588_command cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003274
Hans Verkuilffb48772010-05-01 08:03:24 -03003275 v4l2_prio_close(&btv->prio, fh->prio);
Robert Fitzsimonsb9bc07a2008-04-10 09:40:31 -03003276 file->private_data = NULL;
3277 kfree(fh);
3278
Linus Torvalds1da177e2005-04-16 15:20:36 -07003279 btv->radio_user--;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003280
Hans Verkuilb9218f22010-12-27 12:22:46 -03003281 bttv_call_all(btv, core, ioctl, SAA6588_CMD_CLOSE, &cmd);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003282
Linus Torvalds1da177e2005-04-16 15:20:36 -07003283 return 0;
3284}
3285
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003286static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003287{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003288 struct bttv_fh *fh = priv;
3289 struct bttv *btv = fh->btv;
3290
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003291 if (0 != t->index)
3292 return -EINVAL;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003293 strcpy(t->name, "Radio");
3294 t->type = V4L2_TUNER_RADIO;
3295
Hans Verkuil859f0272009-03-28 08:29:00 -03003296 bttv_call_all(btv, tuner, g_tuner, t);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003297
3298 if (btv->audio_mode_gpio)
3299 btv->audio_mode_gpio(btv, t, 0);
3300
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003301 return 0;
3302}
3303
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003304static int radio_s_tuner(struct file *file, void *priv,
3305 struct v4l2_tuner *t)
3306{
3307 struct bttv_fh *fh = priv;
3308 struct bttv *btv = fh->btv;
3309
3310 if (0 != t->index)
3311 return -EINVAL;
3312
Hans Verkuila024c1a2011-06-12 07:02:43 -03003313 bttv_call_all(btv, tuner, s_tuner, t);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003314 return 0;
3315}
3316
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003317static ssize_t radio_read(struct file *file, char __user *data,
3318 size_t count, loff_t *ppos)
3319{
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003320 struct bttv_fh *fh = file->private_data;
3321 struct bttv *btv = fh->btv;
Hans Verkuilb9218f22010-12-27 12:22:46 -03003322 struct saa6588_command cmd;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003323 cmd.block_count = count/3;
3324 cmd.buffer = data;
3325 cmd.instance = file;
3326 cmd.result = -ENODEV;
3327
Hans Verkuilb9218f22010-12-27 12:22:46 -03003328 bttv_call_all(btv, core, ioctl, SAA6588_CMD_READ, &cmd);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003329
3330 return cmd.result;
3331}
3332
3333static unsigned int radio_poll(struct file *file, poll_table *wait)
3334{
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003335 struct bttv_fh *fh = file->private_data;
3336 struct bttv *btv = fh->btv;
Hans Verkuilb9218f22010-12-27 12:22:46 -03003337 struct saa6588_command cmd;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003338 cmd.instance = file;
3339 cmd.event_list = wait;
3340 cmd.result = -ENODEV;
Hans Verkuilb9218f22010-12-27 12:22:46 -03003341 bttv_call_all(btv, core, ioctl, SAA6588_CMD_POLL, &cmd);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003342
3343 return cmd.result;
3344}
3345
Hans Verkuilbec43662008-12-30 06:58:20 -03003346static const struct v4l2_file_operations radio_fops =
Linus Torvalds1da177e2005-04-16 15:20:36 -07003347{
3348 .owner = THIS_MODULE,
3349 .open = radio_open,
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003350 .read = radio_read,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003351 .release = radio_release,
Mauro Carvalho Chehab587f0d52010-12-15 18:45:42 -03003352 .unlocked_ioctl = video_ioctl2,
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003353 .poll = radio_poll,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003354};
3355
Hans Verkuila3998102008-07-21 02:57:38 -03003356static const struct v4l2_ioctl_ops radio_ioctl_ops = {
Hans Verkuil78dea1a2012-09-09 09:03:29 -03003357 .vidioc_querycap = bttv_querycap,
Hans Verkuil01df5302013-02-06 12:40:28 -03003358 .vidioc_log_status = bttv_log_status,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003359 .vidioc_g_tuner = radio_g_tuner,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003360 .vidioc_s_tuner = radio_s_tuner,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003361 .vidioc_g_frequency = bttv_g_frequency,
3362 .vidioc_s_frequency = bttv_s_frequency,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003363};
3364
Hans Verkuila3998102008-07-21 02:57:38 -03003365static struct video_device radio_template = {
3366 .fops = &radio_fops,
Hans Verkuila3998102008-07-21 02:57:38 -03003367 .ioctl_ops = &radio_ioctl_ops,
3368};
3369
Linus Torvalds1da177e2005-04-16 15:20:36 -07003370/* ----------------------------------------------------------------------- */
3371/* some debug code */
3372
Adrian Bunk408b6642005-05-01 08:59:29 -07003373static int bttv_risc_decode(u32 risc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003374{
3375 static char *instr[16] = {
3376 [ BT848_RISC_WRITE >> 28 ] = "write",
3377 [ BT848_RISC_SKIP >> 28 ] = "skip",
3378 [ BT848_RISC_WRITEC >> 28 ] = "writec",
3379 [ BT848_RISC_JUMP >> 28 ] = "jump",
3380 [ BT848_RISC_SYNC >> 28 ] = "sync",
3381 [ BT848_RISC_WRITE123 >> 28 ] = "write123",
3382 [ BT848_RISC_SKIP123 >> 28 ] = "skip123",
3383 [ BT848_RISC_WRITE1S23 >> 28 ] = "write1s23",
3384 };
3385 static int incr[16] = {
3386 [ BT848_RISC_WRITE >> 28 ] = 2,
3387 [ BT848_RISC_JUMP >> 28 ] = 2,
3388 [ BT848_RISC_SYNC >> 28 ] = 2,
3389 [ BT848_RISC_WRITE123 >> 28 ] = 5,
3390 [ BT848_RISC_SKIP123 >> 28 ] = 2,
3391 [ BT848_RISC_WRITE1S23 >> 28 ] = 3,
3392 };
3393 static char *bits[] = {
3394 "be0", "be1", "be2", "be3/resync",
3395 "set0", "set1", "set2", "set3",
3396 "clr0", "clr1", "clr2", "clr3",
3397 "irq", "res", "eol", "sol",
3398 };
3399 int i;
3400
Joe Perches8af443e2011-08-21 19:56:48 -03003401 pr_cont("0x%08x [ %s", risc,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003402 instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
3403 for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
3404 if (risc & (1 << (i + 12)))
Joe Perches8af443e2011-08-21 19:56:48 -03003405 pr_cont(" %s", bits[i]);
3406 pr_cont(" count=%d ]\n", risc & 0xfff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003407 return incr[risc >> 28] ? incr[risc >> 28] : 1;
3408}
3409
Adrian Bunk408b6642005-05-01 08:59:29 -07003410static void bttv_risc_disasm(struct bttv *btv,
3411 struct btcx_riscmem *risc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003412{
3413 unsigned int i,j,n;
3414
Joe Perches8af443e2011-08-21 19:56:48 -03003415 pr_info("%s: risc disasm: %p [dma=0x%08lx]\n",
3416 btv->c.v4l2_dev.name, risc->cpu, (unsigned long)risc->dma);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003417 for (i = 0; i < (risc->size >> 2); i += n) {
Joe Perches8af443e2011-08-21 19:56:48 -03003418 pr_info("%s: 0x%lx: ",
3419 btv->c.v4l2_dev.name,
3420 (unsigned long)(risc->dma + (i<<2)));
Al Viro3aa71102008-06-22 14:20:09 -03003421 n = bttv_risc_decode(le32_to_cpu(risc->cpu[i]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003422 for (j = 1; j < n; j++)
Joe Perches8af443e2011-08-21 19:56:48 -03003423 pr_info("%s: 0x%lx: 0x%08x [ arg #%d ]\n",
3424 btv->c.v4l2_dev.name,
3425 (unsigned long)(risc->dma + ((i+j)<<2)),
3426 risc->cpu[i+j], j);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003427 if (0 == risc->cpu[i])
3428 break;
3429 }
3430}
3431
3432static void bttv_print_riscaddr(struct bttv *btv)
3433{
Joe Perches8af443e2011-08-21 19:56:48 -03003434 pr_info(" main: %08llx\n", (unsigned long long)btv->main.dma);
3435 pr_info(" vbi : o=%08llx e=%08llx\n",
3436 btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
3437 btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0);
3438 pr_info(" cap : o=%08llx e=%08llx\n",
3439 btv->curr.top
3440 ? (unsigned long long)btv->curr.top->top.dma : 0,
3441 btv->curr.bottom
3442 ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
3443 pr_info(" scr : o=%08llx e=%08llx\n",
3444 btv->screen ? (unsigned long long)btv->screen->top.dma : 0,
3445 btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003446 bttv_risc_disasm(btv, &btv->main);
3447}
3448
3449/* ----------------------------------------------------------------------- */
3450/* irq handler */
3451
3452static char *irq_name[] = {
3453 "FMTCHG", // format change detected (525 vs. 625)
3454 "VSYNC", // vertical sync (new field)
3455 "HSYNC", // horizontal sync
3456 "OFLOW", // chroma/luma AGC overflow
3457 "HLOCK", // horizontal lock changed
3458 "VPRES", // video presence changed
3459 "6", "7",
3460 "I2CDONE", // hw irc operation finished
3461 "GPINT", // gpio port triggered irq
3462 "10",
3463 "RISCI", // risc instruction triggered irq
3464 "FBUS", // pixel data fifo dropped data (high pci bus latencies)
3465 "FTRGT", // pixel data fifo overrun
3466 "FDSR", // fifo data stream resyncronisation
3467 "PPERR", // parity error (data transfer)
3468 "RIPERR", // parity error (read risc instructions)
3469 "PABORT", // pci abort
3470 "OCERR", // risc instruction error
3471 "SCERR", // syncronisation error
3472};
3473
3474static void bttv_print_irqbits(u32 print, u32 mark)
3475{
3476 unsigned int i;
3477
Joe Perches8af443e2011-08-21 19:56:48 -03003478 pr_cont("bits:");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003479 for (i = 0; i < ARRAY_SIZE(irq_name); i++) {
3480 if (print & (1 << i))
Joe Perches8af443e2011-08-21 19:56:48 -03003481 pr_cont(" %s", irq_name[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003482 if (mark & (1 << i))
Joe Perches8af443e2011-08-21 19:56:48 -03003483 pr_cont("*");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003484 }
3485}
3486
3487static void bttv_irq_debug_low_latency(struct bttv *btv, u32 rc)
3488{
Joe Perches8af443e2011-08-21 19:56:48 -03003489 pr_warn("%d: irq: skipped frame [main=%lx,o_vbi=%lx,o_field=%lx,rc=%lx]\n",
3490 btv->c.nr,
3491 (unsigned long)btv->main.dma,
3492 (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_VBI+1]),
3493 (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_FIELD+1]),
3494 (unsigned long)rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003495
3496 if (0 == (btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC)) {
Joe Perches8af443e2011-08-21 19:56:48 -03003497 pr_notice("%d: Oh, there (temporarily?) is no input signal. "
3498 "Ok, then this is harmless, don't worry ;)\n",
3499 btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003500 return;
3501 }
Joe Perches8af443e2011-08-21 19:56:48 -03003502 pr_notice("%d: Uhm. Looks like we have unusual high IRQ latencies\n",
3503 btv->c.nr);
3504 pr_notice("%d: Lets try to catch the culpit red-handed ...\n",
3505 btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506 dump_stack();
3507}
3508
3509static int
3510bttv_irq_next_video(struct bttv *btv, struct bttv_buffer_set *set)
3511{
3512 struct bttv_buffer *item;
3513
3514 memset(set,0,sizeof(*set));
3515
3516 /* capture request ? */
3517 if (!list_empty(&btv->capture)) {
3518 set->frame_irq = 1;
3519 item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
3520 if (V4L2_FIELD_HAS_TOP(item->vb.field))
3521 set->top = item;
3522 if (V4L2_FIELD_HAS_BOTTOM(item->vb.field))
3523 set->bottom = item;
3524
3525 /* capture request for other field ? */
3526 if (!V4L2_FIELD_HAS_BOTH(item->vb.field) &&
3527 (item->vb.queue.next != &btv->capture)) {
3528 item = list_entry(item->vb.queue.next, struct bttv_buffer, vb.queue);
Mike Isely66349b42009-09-21 12:09:08 -03003529 /* Mike Isely <isely@pobox.com> - Only check
3530 * and set up the bottom field in the logic
3531 * below. Don't ever do the top field. This
3532 * of course means that if we set up the
3533 * bottom field in the above code that we'll
3534 * actually skip a field. But that's OK.
3535 * Having processed only a single buffer this
3536 * time, then the next time around the first
3537 * available buffer should be for a top field.
3538 * That will then cause us here to set up a
3539 * top then a bottom field in the normal way.
3540 * The alternative to this understanding is
3541 * that we set up the second available buffer
3542 * as a top field, but that's out of order
3543 * since this driver always processes the top
3544 * field first - the effect will be the two
3545 * buffers being returned in the wrong order,
3546 * with the second buffer also being delayed
3547 * by one field time (owing to the fifo nature
3548 * of videobuf). Worse still, we'll be stuck
3549 * doing fields out of order now every time
3550 * until something else causes a field to be
3551 * dropped. By effectively forcing a field to
3552 * drop this way then we always get back into
3553 * sync within a single frame time. (Out of
3554 * order fields can screw up deinterlacing
3555 * algorithms.) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003556 if (!V4L2_FIELD_HAS_BOTH(item->vb.field)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003557 if (NULL == set->bottom &&
3558 V4L2_FIELD_BOTTOM == item->vb.field) {
3559 set->bottom = item;
3560 }
3561 if (NULL != set->top && NULL != set->bottom)
3562 set->top_irq = 2;
3563 }
3564 }
3565 }
3566
3567 /* screen overlay ? */
3568 if (NULL != btv->screen) {
3569 if (V4L2_FIELD_HAS_BOTH(btv->screen->vb.field)) {
3570 if (NULL == set->top && NULL == set->bottom) {
3571 set->top = btv->screen;
3572 set->bottom = btv->screen;
3573 }
3574 } else {
3575 if (V4L2_FIELD_TOP == btv->screen->vb.field &&
3576 NULL == set->top) {
3577 set->top = btv->screen;
3578 }
3579 if (V4L2_FIELD_BOTTOM == btv->screen->vb.field &&
3580 NULL == set->bottom) {
3581 set->bottom = btv->screen;
3582 }
3583 }
3584 }
3585
Joe Perches8af443e2011-08-21 19:56:48 -03003586 dprintk("%d: next set: top=%p bottom=%p [screen=%p,irq=%d,%d]\n",
3587 btv->c.nr, set->top, set->bottom,
3588 btv->screen, set->frame_irq, set->top_irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003589 return 0;
3590}
3591
3592static void
3593bttv_irq_wakeup_video(struct bttv *btv, struct bttv_buffer_set *wakeup,
3594 struct bttv_buffer_set *curr, unsigned int state)
3595{
3596 struct timeval ts;
3597
Sakari Ailus8e6057b2012-09-15 15:14:42 -03003598 v4l2_get_timestamp(&ts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003599
3600 if (wakeup->top == wakeup->bottom) {
3601 if (NULL != wakeup->top && curr->top != wakeup->top) {
3602 if (irq_debug > 1)
Joe Perches8af443e2011-08-21 19:56:48 -03003603 pr_debug("%d: wakeup: both=%p\n",
3604 btv->c.nr, wakeup->top);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003605 wakeup->top->vb.ts = ts;
3606 wakeup->top->vb.field_count = btv->field_count;
3607 wakeup->top->vb.state = state;
3608 wake_up(&wakeup->top->vb.done);
3609 }
3610 } else {
3611 if (NULL != wakeup->top && curr->top != wakeup->top) {
3612 if (irq_debug > 1)
Joe Perches8af443e2011-08-21 19:56:48 -03003613 pr_debug("%d: wakeup: top=%p\n",
3614 btv->c.nr, wakeup->top);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003615 wakeup->top->vb.ts = ts;
3616 wakeup->top->vb.field_count = btv->field_count;
3617 wakeup->top->vb.state = state;
3618 wake_up(&wakeup->top->vb.done);
3619 }
3620 if (NULL != wakeup->bottom && curr->bottom != wakeup->bottom) {
3621 if (irq_debug > 1)
Joe Perches8af443e2011-08-21 19:56:48 -03003622 pr_debug("%d: wakeup: bottom=%p\n",
3623 btv->c.nr, wakeup->bottom);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003624 wakeup->bottom->vb.ts = ts;
3625 wakeup->bottom->vb.field_count = btv->field_count;
3626 wakeup->bottom->vb.state = state;
3627 wake_up(&wakeup->bottom->vb.done);
3628 }
3629 }
3630}
3631
3632static void
3633bttv_irq_wakeup_vbi(struct bttv *btv, struct bttv_buffer *wakeup,
3634 unsigned int state)
3635{
3636 struct timeval ts;
3637
3638 if (NULL == wakeup)
3639 return;
3640
Sakari Ailus8e6057b2012-09-15 15:14:42 -03003641 v4l2_get_timestamp(&ts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003642 wakeup->vb.ts = ts;
3643 wakeup->vb.field_count = btv->field_count;
3644 wakeup->vb.state = state;
3645 wake_up(&wakeup->vb.done);
3646}
3647
3648static void bttv_irq_timeout(unsigned long data)
3649{
3650 struct bttv *btv = (struct bttv *)data;
3651 struct bttv_buffer_set old,new;
3652 struct bttv_buffer *ovbi;
3653 struct bttv_buffer *item;
3654 unsigned long flags;
3655
3656 if (bttv_verbose) {
Joe Perches8af443e2011-08-21 19:56:48 -03003657 pr_info("%d: timeout: drop=%d irq=%d/%d, risc=%08x, ",
3658 btv->c.nr, btv->framedrop, btv->irq_me, btv->irq_total,
3659 btread(BT848_RISC_COUNT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003660 bttv_print_irqbits(btread(BT848_INT_STAT),0);
Joe Perches8af443e2011-08-21 19:56:48 -03003661 pr_cont("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003662 }
3663
3664 spin_lock_irqsave(&btv->s_lock,flags);
3665
3666 /* deactivate stuff */
3667 memset(&new,0,sizeof(new));
3668 old = btv->curr;
3669 ovbi = btv->cvbi;
3670 btv->curr = new;
3671 btv->cvbi = NULL;
3672 btv->loop_irq = 0;
3673 bttv_buffer_activate_video(btv, &new);
3674 bttv_buffer_activate_vbi(btv, NULL);
3675 bttv_set_dma(btv, 0);
3676
3677 /* wake up */
Brandon Philips0fc06862007-11-06 20:02:36 -03003678 bttv_irq_wakeup_video(btv, &old, &new, VIDEOBUF_ERROR);
3679 bttv_irq_wakeup_vbi(btv, ovbi, VIDEOBUF_ERROR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003680
3681 /* cancel all outstanding capture / vbi requests */
3682 while (!list_empty(&btv->capture)) {
3683 item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
3684 list_del(&item->vb.queue);
Brandon Philips0fc06862007-11-06 20:02:36 -03003685 item->vb.state = VIDEOBUF_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003686 wake_up(&item->vb.done);
3687 }
3688 while (!list_empty(&btv->vcapture)) {
3689 item = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
3690 list_del(&item->vb.queue);
Brandon Philips0fc06862007-11-06 20:02:36 -03003691 item->vb.state = VIDEOBUF_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003692 wake_up(&item->vb.done);
3693 }
3694
3695 btv->errors++;
3696 spin_unlock_irqrestore(&btv->s_lock,flags);
3697}
3698
3699static void
3700bttv_irq_wakeup_top(struct bttv *btv)
3701{
3702 struct bttv_buffer *wakeup = btv->curr.top;
3703
3704 if (NULL == wakeup)
3705 return;
3706
3707 spin_lock(&btv->s_lock);
3708 btv->curr.top_irq = 0;
3709 btv->curr.top = NULL;
3710 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
3711
Sakari Ailus8e6057b2012-09-15 15:14:42 -03003712 v4l2_get_timestamp(&wakeup->vb.ts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003713 wakeup->vb.field_count = btv->field_count;
Brandon Philips0fc06862007-11-06 20:02:36 -03003714 wakeup->vb.state = VIDEOBUF_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003715 wake_up(&wakeup->vb.done);
3716 spin_unlock(&btv->s_lock);
3717}
3718
3719static inline int is_active(struct btcx_riscmem *risc, u32 rc)
3720{
3721 if (rc < risc->dma)
3722 return 0;
3723 if (rc > risc->dma + risc->size)
3724 return 0;
3725 return 1;
3726}
3727
3728static void
3729bttv_irq_switch_video(struct bttv *btv)
3730{
3731 struct bttv_buffer_set new;
3732 struct bttv_buffer_set old;
3733 dma_addr_t rc;
3734
3735 spin_lock(&btv->s_lock);
3736
3737 /* new buffer set */
3738 bttv_irq_next_video(btv, &new);
3739 rc = btread(BT848_RISC_COUNT);
3740 if ((btv->curr.top && is_active(&btv->curr.top->top, rc)) ||
3741 (btv->curr.bottom && is_active(&btv->curr.bottom->bottom, rc))) {
3742 btv->framedrop++;
3743 if (debug_latency)
3744 bttv_irq_debug_low_latency(btv, rc);
3745 spin_unlock(&btv->s_lock);
3746 return;
3747 }
3748
3749 /* switch over */
3750 old = btv->curr;
3751 btv->curr = new;
3752 btv->loop_irq &= ~1;
3753 bttv_buffer_activate_video(btv, &new);
3754 bttv_set_dma(btv, 0);
3755
3756 /* switch input */
3757 if (UNSET != btv->new_input) {
3758 video_mux(btv,btv->new_input);
3759 btv->new_input = UNSET;
3760 }
3761
3762 /* wake up finished buffers */
Brandon Philips0fc06862007-11-06 20:02:36 -03003763 bttv_irq_wakeup_video(btv, &old, &new, VIDEOBUF_DONE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003764 spin_unlock(&btv->s_lock);
3765}
3766
3767static void
3768bttv_irq_switch_vbi(struct bttv *btv)
3769{
3770 struct bttv_buffer *new = NULL;
3771 struct bttv_buffer *old;
3772 u32 rc;
3773
3774 spin_lock(&btv->s_lock);
3775
3776 if (!list_empty(&btv->vcapture))
3777 new = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
3778 old = btv->cvbi;
3779
3780 rc = btread(BT848_RISC_COUNT);
3781 if (NULL != old && (is_active(&old->top, rc) ||
3782 is_active(&old->bottom, rc))) {
3783 btv->framedrop++;
3784 if (debug_latency)
3785 bttv_irq_debug_low_latency(btv, rc);
3786 spin_unlock(&btv->s_lock);
3787 return;
3788 }
3789
3790 /* switch */
3791 btv->cvbi = new;
3792 btv->loop_irq &= ~4;
3793 bttv_buffer_activate_vbi(btv, new);
3794 bttv_set_dma(btv, 0);
3795
Brandon Philips0fc06862007-11-06 20:02:36 -03003796 bttv_irq_wakeup_vbi(btv, old, VIDEOBUF_DONE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003797 spin_unlock(&btv->s_lock);
3798}
3799
David Howells7d12e782006-10-05 14:55:46 +01003800static irqreturn_t bttv_irq(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003801{
3802 u32 stat,astat;
3803 u32 dstat;
3804 int count;
3805 struct bttv *btv;
3806 int handled = 0;
3807
3808 btv=(struct bttv *)dev_id;
Mark Weaver6c6c0b22005-11-13 16:07:52 -08003809
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810 count=0;
3811 while (1) {
3812 /* get/clear interrupt status bits */
3813 stat=btread(BT848_INT_STAT);
3814 astat=stat&btread(BT848_INT_MASK);
3815 if (!astat)
3816 break;
3817 handled = 1;
3818 btwrite(stat,BT848_INT_STAT);
3819
3820 /* get device status bits */
3821 dstat=btread(BT848_DSTATUS);
3822
3823 if (irq_debug) {
Joe Perches8af443e2011-08-21 19:56:48 -03003824 pr_debug("%d: irq loop=%d fc=%d riscs=%x, riscc=%08x, ",
3825 btv->c.nr, count, btv->field_count,
3826 stat>>28, btread(BT848_RISC_COUNT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003827 bttv_print_irqbits(stat,astat);
3828 if (stat & BT848_INT_HLOCK)
Joe Perches8af443e2011-08-21 19:56:48 -03003829 pr_cont(" HLOC => %s",
3830 dstat & BT848_DSTATUS_HLOC
3831 ? "yes" : "no");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003832 if (stat & BT848_INT_VPRES)
Joe Perches8af443e2011-08-21 19:56:48 -03003833 pr_cont(" PRES => %s",
3834 dstat & BT848_DSTATUS_PRES
3835 ? "yes" : "no");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003836 if (stat & BT848_INT_FMTCHG)
Joe Perches8af443e2011-08-21 19:56:48 -03003837 pr_cont(" NUML => %s",
3838 dstat & BT848_DSTATUS_NUML
3839 ? "625" : "525");
3840 pr_cont("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841 }
3842
3843 if (astat&BT848_INT_VSYNC)
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003844 btv->field_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003845
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02003846 if ((astat & BT848_INT_GPINT) && btv->remote) {
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02003847 bttv_input_irq(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003848 }
3849
3850 if (astat & BT848_INT_I2CDONE) {
3851 btv->i2c_done = stat;
3852 wake_up(&btv->i2c_queue);
3853 }
3854
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003855 if ((astat & BT848_INT_RISCI) && (stat & (4<<28)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003856 bttv_irq_switch_vbi(btv);
3857
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003858 if ((astat & BT848_INT_RISCI) && (stat & (2<<28)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003859 bttv_irq_wakeup_top(btv);
3860
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003861 if ((astat & BT848_INT_RISCI) && (stat & (1<<28)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862 bttv_irq_switch_video(btv);
3863
3864 if ((astat & BT848_INT_HLOCK) && btv->opt_automute)
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03003865 audio_mute(btv, btv->mute); /* trigger automute */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003866
3867 if (astat & (BT848_INT_SCERR|BT848_INT_OCERR)) {
Joe Perches8af443e2011-08-21 19:56:48 -03003868 pr_info("%d: %s%s @ %08x,",
3869 btv->c.nr,
3870 (astat & BT848_INT_SCERR) ? "SCERR" : "",
3871 (astat & BT848_INT_OCERR) ? "OCERR" : "",
3872 btread(BT848_RISC_COUNT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003873 bttv_print_irqbits(stat,astat);
Joe Perches8af443e2011-08-21 19:56:48 -03003874 pr_cont("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003875 if (bttv_debug)
3876 bttv_print_riscaddr(btv);
3877 }
3878 if (fdsr && astat & BT848_INT_FDSR) {
Joe Perches8af443e2011-08-21 19:56:48 -03003879 pr_info("%d: FDSR @ %08x\n",
3880 btv->c.nr, btread(BT848_RISC_COUNT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003881 if (bttv_debug)
3882 bttv_print_riscaddr(btv);
3883 }
3884
3885 count++;
3886 if (count > 4) {
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08003887
3888 if (count > 8 || !(astat & BT848_INT_GPINT)) {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003889 btwrite(0, BT848_INT_MASK);
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08003890
Joe Perches8af443e2011-08-21 19:56:48 -03003891 pr_err("%d: IRQ lockup, cleared int mask [",
3892 btv->c.nr);
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08003893 } else {
Joe Perches8af443e2011-08-21 19:56:48 -03003894 pr_err("%d: IRQ lockup, clearing GPINT from int mask [",
3895 btv->c.nr);
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08003896
3897 btwrite(btread(BT848_INT_MASK) & (-1 ^ BT848_INT_GPINT),
3898 BT848_INT_MASK);
3899 };
3900
Linus Torvalds1da177e2005-04-16 15:20:36 -07003901 bttv_print_irqbits(stat,astat);
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08003902
Joe Perches8af443e2011-08-21 19:56:48 -03003903 pr_cont("]\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003904 }
3905 }
3906 btv->irq_total++;
3907 if (handled)
3908 btv->irq_me++;
3909 return IRQ_RETVAL(handled);
3910}
3911
3912
3913/* ----------------------------------------------------------------------- */
Hans Verkuild9b67072013-02-06 11:43:07 -03003914/* initialization */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003915
3916static struct video_device *vdev_init(struct bttv *btv,
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03003917 const struct video_device *template,
Hans Verkuil0ea6bc82008-07-26 08:26:43 -03003918 const char *type_name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003919{
3920 struct video_device *vfd;
3921
3922 vfd = video_device_alloc();
3923 if (NULL == vfd)
3924 return NULL;
3925 *vfd = *template;
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03003926 vfd->v4l2_dev = &btv->c.v4l2_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003927 vfd->release = video_device_release;
Mauro Carvalho Chehab1d0a4362008-06-23 12:31:29 -03003928 vfd->debug = bttv_debug;
Trent Piepho4b10d3b2009-01-28 21:32:59 -03003929 video_set_drvdata(vfd, btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003930 snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
3931 btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "",
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03003932 type_name, bttv_tvcards[btv->c.type].name);
Hans Verkuild9b67072013-02-06 11:43:07 -03003933 if (btv->tuner_type == TUNER_ABSENT) {
3934 v4l2_disable_ioctl(vfd, VIDIOC_G_FREQUENCY);
3935 v4l2_disable_ioctl(vfd, VIDIOC_S_FREQUENCY);
3936 v4l2_disable_ioctl(vfd, VIDIOC_G_TUNER);
3937 v4l2_disable_ioctl(vfd, VIDIOC_S_TUNER);
3938 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003939 return vfd;
3940}
3941
3942static void bttv_unregister_video(struct bttv *btv)
3943{
3944 if (btv->video_dev) {
Laurent Pinchartf0813b42009-11-27 13:57:30 -03003945 if (video_is_registered(btv->video_dev))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946 video_unregister_device(btv->video_dev);
3947 else
3948 video_device_release(btv->video_dev);
3949 btv->video_dev = NULL;
3950 }
3951 if (btv->vbi_dev) {
Laurent Pinchartf0813b42009-11-27 13:57:30 -03003952 if (video_is_registered(btv->vbi_dev))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003953 video_unregister_device(btv->vbi_dev);
3954 else
3955 video_device_release(btv->vbi_dev);
3956 btv->vbi_dev = NULL;
3957 }
3958 if (btv->radio_dev) {
Laurent Pinchartf0813b42009-11-27 13:57:30 -03003959 if (video_is_registered(btv->radio_dev))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003960 video_unregister_device(btv->radio_dev);
3961 else
3962 video_device_release(btv->radio_dev);
3963 btv->radio_dev = NULL;
3964 }
3965}
3966
3967/* register video4linux devices */
Greg Kroah-Hartman4c62e972012-12-21 13:17:53 -08003968static int bttv_register_video(struct bttv *btv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003969{
Hans Verkuil0ea6bc82008-07-26 08:26:43 -03003970 if (no_overlay > 0)
Joe Perches8af443e2011-08-21 19:56:48 -03003971 pr_notice("Overlay support disabled\n");
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07003972
Linus Torvalds1da177e2005-04-16 15:20:36 -07003973 /* video */
Hans Verkuil0ea6bc82008-07-26 08:26:43 -03003974 btv->video_dev = vdev_init(btv, &bttv_video_template, "video");
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03003975
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003976 if (NULL == btv->video_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003977 goto err;
Jean Delvare176c2f32008-09-07 12:49:59 -03003978 if (video_register_device(btv->video_dev, VFL_TYPE_GRABBER,
3979 video_nr[btv->c.nr]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003980 goto err;
Joe Perches8af443e2011-08-21 19:56:48 -03003981 pr_info("%d: registered device %s\n",
3982 btv->c.nr, video_device_node_name(btv->video_dev));
Hans Verkuil22a04f12008-07-20 06:35:02 -03003983 if (device_create_file(&btv->video_dev->dev,
Kay Sievers54bd5b62007-10-08 16:26:13 -03003984 &dev_attr_card)<0) {
Joe Perches8af443e2011-08-21 19:56:48 -03003985 pr_err("%d: device_create_file 'card' failed\n", btv->c.nr);
Trent Piephod94fc9a2006-07-29 17:18:06 -03003986 goto err;
3987 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003988
3989 /* vbi */
Hans Verkuil0ea6bc82008-07-26 08:26:43 -03003990 btv->vbi_dev = vdev_init(btv, &bttv_video_template, "vbi");
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03003991
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003992 if (NULL == btv->vbi_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003993 goto err;
Jean Delvare176c2f32008-09-07 12:49:59 -03003994 if (video_register_device(btv->vbi_dev, VFL_TYPE_VBI,
3995 vbi_nr[btv->c.nr]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003996 goto err;
Joe Perches8af443e2011-08-21 19:56:48 -03003997 pr_info("%d: registered device %s\n",
3998 btv->c.nr, video_device_node_name(btv->vbi_dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003999
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004000 if (!btv->has_radio)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004001 return 0;
4002 /* radio */
Hans Verkuil0ea6bc82008-07-26 08:26:43 -03004003 btv->radio_dev = vdev_init(btv, &radio_template, "radio");
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004004 if (NULL == btv->radio_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004005 goto err;
Hans Verkuil01df5302013-02-06 12:40:28 -03004006 btv->radio_dev->ctrl_handler = &btv->radio_ctrl_handler;
Jean Delvare176c2f32008-09-07 12:49:59 -03004007 if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,
4008 radio_nr[btv->c.nr]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004009 goto err;
Joe Perches8af443e2011-08-21 19:56:48 -03004010 pr_info("%d: registered device %s\n",
4011 btv->c.nr, video_device_node_name(btv->radio_dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004012
4013 /* all done */
4014 return 0;
4015
4016 err:
4017 bttv_unregister_video(btv);
4018 return -1;
4019}
4020
4021
4022/* on OpenFirmware machines (PowerMac at least), PCI memory cycle */
4023/* response on cards with no firmware is not enabled by OF */
4024static void pci_set_command(struct pci_dev *dev)
4025{
4026#if defined(__powerpc__)
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004027 unsigned int cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004028
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004029 pci_read_config_dword(dev, PCI_COMMAND, &cmd);
4030 cmd = (cmd | PCI_COMMAND_MEMORY );
4031 pci_write_config_dword(dev, PCI_COMMAND, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004032#endif
4033}
4034
Greg Kroah-Hartman4c62e972012-12-21 13:17:53 -08004035static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004036{
Hans Verkuil76ea9922013-02-06 11:49:14 -03004037 struct v4l2_frequency init_freq = {
4038 .tuner = 0,
4039 .type = V4L2_TUNER_ANALOG_TV,
4040 .frequency = 980,
4041 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042 int result;
4043 unsigned char lat;
4044 struct bttv *btv;
Hans Verkuil01df5302013-02-06 12:40:28 -03004045 struct v4l2_ctrl_handler *hdl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046
4047 if (bttv_num == BTTV_MAX)
4048 return -ENOMEM;
Joe Perches8af443e2011-08-21 19:56:48 -03004049 pr_info("Bt8xx card found (%d)\n", bttv_num);
Trent Piepho4b10d3b2009-01-28 21:32:59 -03004050 bttvs[bttv_num] = btv = kzalloc(sizeof(*btv), GFP_KERNEL);
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004051 if (btv == NULL) {
Joe Perches8af443e2011-08-21 19:56:48 -03004052 pr_err("out of memory\n");
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004053 return -ENOMEM;
4054 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004055 btv->c.nr = bttv_num;
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004056 snprintf(btv->c.v4l2_dev.name, sizeof(btv->c.v4l2_dev.name),
4057 "bttv%d", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004058
4059 /* initialize structs / fill in defaults */
Ingo Molnarbd5f0ac2006-01-13 14:10:24 -02004060 mutex_init(&btv->lock);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004061 spin_lock_init(&btv->s_lock);
4062 spin_lock_init(&btv->gpio_lock);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004063 init_waitqueue_head(&btv->i2c_queue);
4064 INIT_LIST_HEAD(&btv->c.subs);
4065 INIT_LIST_HEAD(&btv->capture);
4066 INIT_LIST_HEAD(&btv->vcapture);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067 v4l2_prio_init(&btv->prio);
4068
4069 init_timer(&btv->timeout);
4070 btv->timeout.function = bttv_irq_timeout;
4071 btv->timeout.data = (unsigned long)btv;
4072
Michael Krufky7c08fb02005-11-08 21:36:21 -08004073 btv->i2c_rc = -1;
4074 btv->tuner_type = UNSET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075 btv->new_input = UNSET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004076 btv->has_radio=radio[btv->c.nr];
4077
4078 /* pci stuff (init, get irq/mmio, ... */
4079 btv->c.pci = dev;
Michael Krufky7c08fb02005-11-08 21:36:21 -08004080 btv->id = dev->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004081 if (pci_enable_device(dev)) {
Joe Perches8af443e2011-08-21 19:56:48 -03004082 pr_warn("%d: Can't enable device\n", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004083 return -EIO;
4084 }
Yang Hongyang284901a2009-04-06 19:01:15 -07004085 if (pci_set_dma_mask(dev, DMA_BIT_MASK(32))) {
Joe Perches8af443e2011-08-21 19:56:48 -03004086 pr_warn("%d: No suitable DMA available\n", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087 return -EIO;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004088 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004089 if (!request_mem_region(pci_resource_start(dev,0),
4090 pci_resource_len(dev,0),
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004091 btv->c.v4l2_dev.name)) {
Joe Perches8af443e2011-08-21 19:56:48 -03004092 pr_warn("%d: can't request iomem (0x%llx)\n",
4093 btv->c.nr,
4094 (unsigned long long)pci_resource_start(dev, 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004095 return -EBUSY;
4096 }
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004097 pci_set_master(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004098 pci_set_command(dev);
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004099
4100 result = v4l2_device_register(&dev->dev, &btv->c.v4l2_dev);
4101 if (result < 0) {
Joe Perches8af443e2011-08-21 19:56:48 -03004102 pr_warn("%d: v4l2_device_register() failed\n", btv->c.nr);
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004103 goto fail0;
4104 }
Hans Verkuil01df5302013-02-06 12:40:28 -03004105 hdl = &btv->ctrl_handler;
4106 v4l2_ctrl_handler_init(hdl, 20);
4107 btv->c.v4l2_dev.ctrl_handler = hdl;
4108 v4l2_ctrl_handler_init(&btv->radio_ctrl_handler, 6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004109
Bjørn Morkabd34d82011-03-21 11:35:56 -03004110 btv->revision = dev->revision;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004111 pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
Joe Perches8af443e2011-08-21 19:56:48 -03004112 pr_info("%d: Bt%d (rev %d) at %s, irq: %d, latency: %d, mmio: 0x%llx\n",
4113 bttv_num, btv->id, btv->revision, pci_name(dev),
4114 btv->c.pci->irq, lat,
4115 (unsigned long long)pci_resource_start(dev, 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004116 schedule();
4117
Akinobu Mita5f1693f2006-12-20 10:08:56 -03004118 btv->bt848_mmio = ioremap(pci_resource_start(dev, 0), 0x1000);
4119 if (NULL == btv->bt848_mmio) {
Joe Perches8af443e2011-08-21 19:56:48 -03004120 pr_err("%d: ioremap() failed\n", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004121 result = -EIO;
4122 goto fail1;
4123 }
4124
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004125 /* identify card */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004126 bttv_idcard(btv);
4127
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004128 /* disable irqs, register irq handler */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004129 btwrite(0, BT848_INT_MASK);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004130 result = request_irq(btv->c.pci->irq, bttv_irq,
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004131 IRQF_SHARED | IRQF_DISABLED, btv->c.v4l2_dev.name, (void *)btv);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004132 if (result < 0) {
Joe Perches8af443e2011-08-21 19:56:48 -03004133 pr_err("%d: can't get IRQ %d\n",
4134 bttv_num, btv->c.pci->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004135 goto fail1;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004136 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004137
4138 if (0 != bttv_handle_chipset(btv)) {
4139 result = -EIO;
4140 goto fail2;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004141 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004142
4143 /* init options from insmod args */
4144 btv->opt_combfilter = combfilter;
Hans Verkuil01df5302013-02-06 12:40:28 -03004145 bttv_ctrl_combfilter.def = combfilter;
4146 bttv_ctrl_lumafilter.def = lumafilter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004147 btv->opt_automute = automute;
Hans Verkuil01df5302013-02-06 12:40:28 -03004148 bttv_ctrl_automute.def = automute;
4149 bttv_ctrl_agc_crush.def = agc_crush;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004150 btv->opt_vcr_hack = vcr_hack;
Hans Verkuil01df5302013-02-06 12:40:28 -03004151 bttv_ctrl_vcr_hack.def = vcr_hack;
4152 bttv_ctrl_whitecrush_upper.def = whitecrush_upper;
4153 bttv_ctrl_whitecrush_lower.def = whitecrush_lower;
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -07004154 btv->opt_uv_ratio = uv_ratio;
Hans Verkuil01df5302013-02-06 12:40:28 -03004155 bttv_ctrl_uv_ratio.def = uv_ratio;
4156 bttv_ctrl_full_luma.def = full_luma_range;
4157 bttv_ctrl_coring.def = coring;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004158
4159 /* fill struct bttv with some useful defaults */
4160 btv->init.btv = btv;
4161 btv->init.ov.w.width = 320;
4162 btv->init.ov.w.height = 240;
Mauro Carvalho Chehabc96dd072007-10-26 16:51:47 -03004163 btv->init.fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004164 btv->init.width = 320;
4165 btv->init.height = 240;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004166 btv->input = 0;
4167
Hans Verkuil01df5302013-02-06 12:40:28 -03004168 v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
4169 V4L2_CID_BRIGHTNESS, 0, 0xff00, 0x100, 32768);
4170 v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
4171 V4L2_CID_CONTRAST, 0, 0xff80, 0x80, 0x6c00);
4172 v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
4173 V4L2_CID_SATURATION, 0, 0xff80, 0x80, 32768);
4174 v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
4175 V4L2_CID_COLOR_KILLER, 0, 1, 1, 0);
4176 v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
4177 V4L2_CID_HUE, 0, 0xff00, 0x100, 32768);
4178 v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
4179 V4L2_CID_CHROMA_AGC, 0, 1, 1, !!chroma_agc);
4180 v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
4181 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
4182 if (btv->volume_gpio)
4183 v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
4184 V4L2_CID_AUDIO_VOLUME, 0, 0xff00, 0x100, 0xff00);
4185 v4l2_ctrl_new_custom(hdl, &bttv_ctrl_combfilter, NULL);
4186 v4l2_ctrl_new_custom(hdl, &bttv_ctrl_automute, NULL);
4187 v4l2_ctrl_new_custom(hdl, &bttv_ctrl_lumafilter, NULL);
4188 v4l2_ctrl_new_custom(hdl, &bttv_ctrl_agc_crush, NULL);
4189 v4l2_ctrl_new_custom(hdl, &bttv_ctrl_vcr_hack, NULL);
4190 v4l2_ctrl_new_custom(hdl, &bttv_ctrl_whitecrush_lower, NULL);
4191 v4l2_ctrl_new_custom(hdl, &bttv_ctrl_whitecrush_upper, NULL);
4192 v4l2_ctrl_new_custom(hdl, &bttv_ctrl_uv_ratio, NULL);
4193 v4l2_ctrl_new_custom(hdl, &bttv_ctrl_full_luma, NULL);
4194 v4l2_ctrl_new_custom(hdl, &bttv_ctrl_coring, NULL);
4195
Linus Torvalds1da177e2005-04-16 15:20:36 -07004196 /* initialize hardware */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004197 if (bttv_gpio)
4198 bttv_gpio_tracking(btv,"pre-init");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004199
4200 bttv_risc_init_main(btv);
4201 init_bt848(btv);
4202
4203 /* gpio */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004204 btwrite(0x00, BT848_GPIO_REG_INP);
4205 btwrite(0x00, BT848_GPIO_OUT_EN);
4206 if (bttv_verbose)
4207 bttv_gpio_tracking(btv,"init");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004208
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004209 /* needs to be done before i2c is registered */
4210 bttv_init_card1(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004211
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004212 /* register i2c + gpio */
4213 init_bttv_i2c(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004214
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004215 /* some card-specific stuff (needs working i2c) */
4216 bttv_init_card2(btv);
Hans Verkuil2c905772009-07-20 08:14:17 -03004217 bttv_init_tuner(btv);
Hans Verkuil76ea9922013-02-06 11:49:14 -03004218 if (btv->tuner_type != TUNER_ABSENT) {
4219 bttv_set_frequency(btv, &init_freq);
4220 btv->radio_freq = 90500 * 16; /* 90.5Mhz default */
4221 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004222 init_irqreg(btv);
Hans Verkuil01df5302013-02-06 12:40:28 -03004223 v4l2_ctrl_handler_setup(hdl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004224
Hans Verkuil01df5302013-02-06 12:40:28 -03004225 if (hdl->error) {
4226 result = hdl->error;
4227 goto fail2;
4228 }
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004229 /* register video4linux + input */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004230 if (!bttv_tvcards[btv->c.type].no_video) {
Hans Verkuil01df5302013-02-06 12:40:28 -03004231 v4l2_ctrl_add_handler(&btv->radio_ctrl_handler, hdl,
4232 v4l2_ctrl_radio_filter);
4233 if (btv->radio_ctrl_handler.error) {
4234 result = btv->radio_ctrl_handler.error;
4235 goto fail2;
4236 }
Trent Piepho333408f2007-07-03 15:08:10 -03004237 set_input(btv, 0, btv->tvnorm);
Michael Schimeke5bd0262007-01-18 16:17:39 -03004238 bttv_crop_reset(&btv->crop[0], btv->tvnorm);
4239 btv->crop[1] = btv->crop[0]; /* current = default */
4240 disclaim_vbi_lines(btv);
4241 disclaim_video_lines(btv);
Hans Verkuil01df5302013-02-06 12:40:28 -03004242 bttv_register_video(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004243 }
4244
Jarod Wilsonf992a492007-03-24 15:23:50 -03004245 /* add subdevices and autoload dvb-bt8xx if needed */
4246 if (bttv_tvcards[btv->c.type].has_dvb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004247 bttv_sub_add_device(&btv->c, "dvb");
Jarod Wilsonf992a492007-03-24 15:23:50 -03004248 request_modules(btv);
4249 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004250
Jean Delvared90a4ae2010-02-16 14:22:37 -03004251 if (!disable_ir) {
4252 init_bttv_i2c_ir(btv);
4253 bttv_input_init(btv);
4254 }
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02004255
Linus Torvalds1da177e2005-04-16 15:20:36 -07004256 /* everything is fine */
4257 bttv_num++;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004258 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004259
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004260fail2:
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004261 free_irq(btv->c.pci->irq,btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004262
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004263fail1:
Hans Verkuil01df5302013-02-06 12:40:28 -03004264 v4l2_ctrl_handler_free(&btv->ctrl_handler);
4265 v4l2_ctrl_handler_free(&btv->radio_ctrl_handler);
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004266 v4l2_device_unregister(&btv->c.v4l2_dev);
4267
4268fail0:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004269 if (btv->bt848_mmio)
4270 iounmap(btv->bt848_mmio);
4271 release_mem_region(pci_resource_start(btv->c.pci,0),
4272 pci_resource_len(btv->c.pci,0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004273 return result;
4274}
4275
Greg Kroah-Hartman4c62e972012-12-21 13:17:53 -08004276static void bttv_remove(struct pci_dev *pci_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004277{
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004278 struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
4279 struct bttv *btv = to_bttv(v4l2_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004280
4281 if (bttv_verbose)
Joe Perches8af443e2011-08-21 19:56:48 -03004282 pr_info("%d: unloading\n", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004283
Tejun Heo707bcf32010-12-24 16:14:20 +01004284 if (bttv_tvcards[btv->c.type].has_dvb)
4285 flush_request_modules(btv);
4286
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004287 /* shutdown everything (DMA+IRQs) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004288 btand(~15, BT848_GPIO_DMA_CTL);
4289 btwrite(0, BT848_INT_MASK);
4290 btwrite(~0x0, BT848_INT_STAT);
4291 btwrite(0x0, BT848_GPIO_OUT_EN);
4292 if (bttv_gpio)
4293 bttv_gpio_tracking(btv,"cleanup");
4294
4295 /* tell gpio modules we are leaving ... */
4296 btv->shutdown=1;
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02004297 bttv_input_fini(btv);
Christopher Pascoe889aee82006-01-09 15:25:28 -02004298 bttv_sub_del_devices(&btv->c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004299
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004300 /* unregister i2c_bus + input */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004301 fini_bttv_i2c(btv);
4302
4303 /* unregister video4linux */
4304 bttv_unregister_video(btv);
4305
4306 /* free allocated memory */
Hans Verkuil01df5302013-02-06 12:40:28 -03004307 v4l2_ctrl_handler_free(&btv->ctrl_handler);
4308 v4l2_ctrl_handler_free(&btv->radio_ctrl_handler);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004309 btcx_riscmem_free(btv->c.pci,&btv->main);
4310
Hans Verkuil01df5302013-02-06 12:40:28 -03004311 /* free resources */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004312 free_irq(btv->c.pci->irq,btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004313 iounmap(btv->bt848_mmio);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004314 release_mem_region(pci_resource_start(btv->c.pci,0),
4315 pci_resource_len(btv->c.pci,0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004316
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004317 v4l2_device_unregister(&btv->c.v4l2_dev);
Trent Piepho4b10d3b2009-01-28 21:32:59 -03004318 bttvs[btv->c.nr] = NULL;
4319 kfree(btv);
4320
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004321 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004322}
4323
Alexey Dobriyan17bc98a2006-08-12 22:01:27 -03004324#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -07004325static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state)
4326{
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004327 struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
4328 struct bttv *btv = to_bttv(v4l2_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004329 struct bttv_buffer_set idle;
4330 unsigned long flags;
4331
Joe Perches8af443e2011-08-21 19:56:48 -03004332 dprintk("%d: suspend %d\n", btv->c.nr, state.event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004333
4334 /* stop dma + irqs */
4335 spin_lock_irqsave(&btv->s_lock,flags);
4336 memset(&idle, 0, sizeof(idle));
4337 btv->state.video = btv->curr;
4338 btv->state.vbi = btv->cvbi;
4339 btv->state.loop_irq = btv->loop_irq;
4340 btv->curr = idle;
4341 btv->loop_irq = 0;
4342 bttv_buffer_activate_video(btv, &idle);
4343 bttv_buffer_activate_vbi(btv, NULL);
4344 bttv_set_dma(btv, 0);
4345 btwrite(0, BT848_INT_MASK);
4346 spin_unlock_irqrestore(&btv->s_lock,flags);
4347
4348 /* save bt878 state */
4349 btv->state.gpio_enable = btread(BT848_GPIO_OUT_EN);
4350 btv->state.gpio_data = gpio_read();
4351
4352 /* save pci state */
4353 pci_save_state(pci_dev);
4354 if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
4355 pci_disable_device(pci_dev);
4356 btv->state.disabled = 1;
4357 }
4358 return 0;
4359}
4360
4361static int bttv_resume(struct pci_dev *pci_dev)
4362{
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004363 struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
4364 struct bttv *btv = to_bttv(v4l2_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004365 unsigned long flags;
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004366 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004367
Joe Perches8af443e2011-08-21 19:56:48 -03004368 dprintk("%d: resume\n", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004369
4370 /* restore pci state */
4371 if (btv->state.disabled) {
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004372 err=pci_enable_device(pci_dev);
4373 if (err) {
Joe Perches8af443e2011-08-21 19:56:48 -03004374 pr_warn("%d: Can't enable device\n", btv->c.nr);
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004375 return err;
4376 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004377 btv->state.disabled = 0;
4378 }
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004379 err=pci_set_power_state(pci_dev, PCI_D0);
4380 if (err) {
4381 pci_disable_device(pci_dev);
Joe Perches8af443e2011-08-21 19:56:48 -03004382 pr_warn("%d: Can't enable device\n", btv->c.nr);
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004383 btv->state.disabled = 1;
4384 return err;
4385 }
4386
Linus Torvalds1da177e2005-04-16 15:20:36 -07004387 pci_restore_state(pci_dev);
4388
4389 /* restore bt878 state */
4390 bttv_reinit_bt848(btv);
4391 gpio_inout(0xffffff, btv->state.gpio_enable);
4392 gpio_write(btv->state.gpio_data);
4393
4394 /* restart dma */
4395 spin_lock_irqsave(&btv->s_lock,flags);
4396 btv->curr = btv->state.video;
4397 btv->cvbi = btv->state.vbi;
4398 btv->loop_irq = btv->state.loop_irq;
4399 bttv_buffer_activate_video(btv, &btv->curr);
4400 bttv_buffer_activate_vbi(btv, btv->cvbi);
4401 bttv_set_dma(btv, 0);
4402 spin_unlock_irqrestore(&btv->s_lock,flags);
4403 return 0;
4404}
Alexey Dobriyan17bc98a2006-08-12 22:01:27 -03004405#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07004406
4407static struct pci_device_id bttv_pci_tbl[] = {
Joe Perches76e97412009-07-05 15:59:21 -03004408 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT848), 0},
4409 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT849), 0},
4410 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT878), 0},
4411 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT879), 0},
Peter De Schrijverc540d9f2011-11-06 10:47:58 -03004412 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_FUSION879), 0},
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004413 {0,}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004414};
4415
4416MODULE_DEVICE_TABLE(pci, bttv_pci_tbl);
4417
4418static struct pci_driver bttv_pci_driver = {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004419 .name = "bttv",
4420 .id_table = bttv_pci_tbl,
4421 .probe = bttv_probe,
Greg Kroah-Hartman4c62e972012-12-21 13:17:53 -08004422 .remove = bttv_remove,
Alexey Dobriyan17bc98a2006-08-12 22:01:27 -03004423#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -07004424 .suspend = bttv_suspend,
4425 .resume = bttv_resume,
Alexey Dobriyan17bc98a2006-08-12 22:01:27 -03004426#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07004427};
4428
Adrian Bunk7d44e892007-12-11 19:23:43 -03004429static int __init bttv_init_module(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004430{
Randy Dunlapc526e222006-07-15 09:08:26 -03004431 int ret;
4432
Linus Torvalds1da177e2005-04-16 15:20:36 -07004433 bttv_num = 0;
4434
Joe Perches8af443e2011-08-21 19:56:48 -03004435 pr_info("driver version %s loaded\n", BTTV_VERSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004436 if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME)
4437 gbuffers = 2;
Filipe Rossetf41b6962009-05-28 11:11:53 -03004438 if (gbufsize > BTTV_MAX_FBUF)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004439 gbufsize = BTTV_MAX_FBUF;
4440 gbufsize = (gbufsize + PAGE_SIZE - 1) & PAGE_MASK;
4441 if (bttv_verbose)
Joe Perches8af443e2011-08-21 19:56:48 -03004442 pr_info("using %d buffers with %dk (%d pages) each for capture\n",
4443 gbuffers, gbufsize >> 10, gbufsize >> PAGE_SHIFT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004444
4445 bttv_check_chipset();
4446
Randy Dunlapc526e222006-07-15 09:08:26 -03004447 ret = bus_register(&bttv_sub_bus_type);
4448 if (ret < 0) {
Joe Perches8af443e2011-08-21 19:56:48 -03004449 pr_warn("bus_register error: %d\n", ret);
Randy Dunlapc526e222006-07-15 09:08:26 -03004450 return ret;
4451 }
Akinobu Mita9e7e85e2007-12-17 14:26:29 -03004452 ret = pci_register_driver(&bttv_pci_driver);
4453 if (ret < 0)
4454 bus_unregister(&bttv_sub_bus_type);
4455
4456 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004457}
4458
Adrian Bunk7d44e892007-12-11 19:23:43 -03004459static void __exit bttv_cleanup_module(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004460{
4461 pci_unregister_driver(&bttv_pci_driver);
4462 bus_unregister(&bttv_sub_bus_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004463}
4464
4465module_init(bttv_init_module);
4466module_exit(bttv_cleanup_module);
4467
4468/*
4469 * Local variables:
4470 * c-basic-offset: 8
4471 * End:
4472 */