blob: 9400e996087b6a5eb5076cd7e0ab399f2bed0e9e [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 Verkuilae50f0f2013-02-06 12:42:13 -030052#include <media/v4l2-event.h>
Mauro Carvalho Chehabb5dcee22015-11-10 12:01:44 -020053#include <media/i2c/tvaudio.h>
Mauro Carvalho Chehabd647f0b2015-11-13 19:40:07 -020054#include <media/drv-intf/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
Mauro Carvalho Chehabb5dcee22015-11-10 12:01:44 -020061#include <media/i2c/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.
Hans de Goede35ccece2013-03-25 14:45:54 -0300265 extraheight Added to sheight for cropcap.bounds.height only
Michael Schimeke5bd0262007-01-18 16:17:39 -0300266 videostart0 ITU-R frame line number of the line corresponding
267 to vdelay in the first field. */
268#define CROPCAP(minhdelayx1, hdelayx1, swidth, totalwidth, sqwidth, \
Hans de Goede35ccece2013-03-25 14:45:54 -0300269 vdelay, sheight, extraheight, videostart0) \
Michael Schimeke5bd0262007-01-18 16:17:39 -0300270 .cropcap.bounds.left = minhdelayx1, \
271 /* * 2 because vertically we count field lines times two, */ \
272 /* e.g. 23 * 2 to 23 * 2 + 576 in PAL-BGHI defrect. */ \
273 .cropcap.bounds.top = (videostart0) * 2 - (vdelay) + MIN_VDELAY, \
274 /* 4 is a safety margin at the end of the line. */ \
275 .cropcap.bounds.width = (totalwidth) - (minhdelayx1) - 4, \
Hans de Goede35ccece2013-03-25 14:45:54 -0300276 .cropcap.bounds.height = (sheight) + (extraheight) + (vdelay) - \
277 MIN_VDELAY, \
Michael Schimeke5bd0262007-01-18 16:17:39 -0300278 .cropcap.defrect.left = hdelayx1, \
279 .cropcap.defrect.top = (videostart0) * 2, \
280 .cropcap.defrect.width = swidth, \
281 .cropcap.defrect.height = sheight, \
282 .cropcap.pixelaspect.numerator = totalwidth, \
283 .cropcap.pixelaspect.denominator = sqwidth,
284
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285const struct bttv_tvnorm bttv_tvnorms[] = {
286 /* PAL-BDGHI */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800287 /* max. active video is actually 922, but 924 is divisible by 4 and 3! */
288 /* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289 {
290 .v4l2_id = V4L2_STD_PAL,
291 .name = "PAL",
292 .Fsc = 35468950,
293 .swidth = 924,
294 .sheight = 576,
295 .totalwidth = 1135,
296 .adelay = 0x7f,
297 .bdelay = 0x72,
298 .iform = (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
299 .scaledtwidth = 1135,
300 .hdelayx1 = 186,
301 .hactivex1 = 924,
302 .vdelay = 0x20,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300303 .vbipack = 255, /* min (2048 / 4, 0x1ff) & 0xff */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 .sram = 0,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200305 /* ITU-R frame line number of the first VBI line
Michael Schimeke5bd0262007-01-18 16:17:39 -0300306 we can capture, of the first and second field.
307 The last line is determined by cropcap.bounds. */
308 .vbistart = { 7, 320 },
309 CROPCAP(/* minhdelayx1 */ 68,
310 /* hdelayx1 */ 186,
311 /* Should be (768 * 1135 + 944 / 2) / 944.
312 cropcap.defrect is used for image width
313 checks, so we keep the old value 924. */
314 /* swidth */ 924,
315 /* totalwidth */ 1135,
316 /* sqwidth */ 944,
317 /* vdelay */ 0x20,
Hans de Goede35ccece2013-03-25 14:45:54 -0300318 /* sheight */ 576,
319 /* bt878 (and bt848?) can capture another
320 line below active video. */
321 /* extraheight */ 2,
Mauro Carvalho Chehaba1fd2872012-10-27 16:33:41 -0300322 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 },{
Hans Verkuild97a11e2006-02-07 06:48:40 -0200324 .v4l2_id = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 .name = "NTSC",
326 .Fsc = 28636363,
327 .swidth = 768,
328 .sheight = 480,
329 .totalwidth = 910,
330 .adelay = 0x68,
331 .bdelay = 0x5d,
332 .iform = (BT848_IFORM_NTSC|BT848_IFORM_XT0),
333 .scaledtwidth = 910,
334 .hdelayx1 = 128,
335 .hactivex1 = 910,
336 .vdelay = 0x1a,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300337 .vbipack = 144, /* min (1600 / 4, 0x1ff) & 0xff */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 .sram = 1,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200339 .vbistart = { 10, 273 },
Michael Schimeke5bd0262007-01-18 16:17:39 -0300340 CROPCAP(/* minhdelayx1 */ 68,
341 /* hdelayx1 */ 128,
342 /* Should be (640 * 910 + 780 / 2) / 780? */
343 /* swidth */ 768,
344 /* totalwidth */ 910,
345 /* sqwidth */ 780,
346 /* vdelay */ 0x1a,
347 /* sheight */ 480,
Hans de Goede35ccece2013-03-25 14:45:54 -0300348 /* extraheight */ 0,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300349 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 },{
351 .v4l2_id = V4L2_STD_SECAM,
352 .name = "SECAM",
353 .Fsc = 35468950,
354 .swidth = 924,
355 .sheight = 576,
356 .totalwidth = 1135,
357 .adelay = 0x7f,
358 .bdelay = 0xb0,
359 .iform = (BT848_IFORM_SECAM|BT848_IFORM_XT1),
360 .scaledtwidth = 1135,
361 .hdelayx1 = 186,
362 .hactivex1 = 922,
363 .vdelay = 0x20,
364 .vbipack = 255,
365 .sram = 0, /* like PAL, correct? */
Michael H. Schimek67f15702006-01-09 15:25:27 -0200366 .vbistart = { 7, 320 },
Michael Schimeke5bd0262007-01-18 16:17:39 -0300367 CROPCAP(/* minhdelayx1 */ 68,
368 /* hdelayx1 */ 186,
369 /* swidth */ 924,
370 /* totalwidth */ 1135,
371 /* sqwidth */ 944,
372 /* vdelay */ 0x20,
373 /* sheight */ 576,
Hans de Goede35ccece2013-03-25 14:45:54 -0300374 /* extraheight */ 0,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300375 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 },{
377 .v4l2_id = V4L2_STD_PAL_Nc,
378 .name = "PAL-Nc",
379 .Fsc = 28636363,
380 .swidth = 640,
381 .sheight = 576,
382 .totalwidth = 910,
383 .adelay = 0x68,
384 .bdelay = 0x5d,
385 .iform = (BT848_IFORM_PAL_NC|BT848_IFORM_XT0),
386 .scaledtwidth = 780,
387 .hdelayx1 = 130,
388 .hactivex1 = 734,
389 .vdelay = 0x1a,
390 .vbipack = 144,
391 .sram = -1,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200392 .vbistart = { 7, 320 },
Michael Schimeke5bd0262007-01-18 16:17:39 -0300393 CROPCAP(/* minhdelayx1 */ 68,
394 /* hdelayx1 */ 130,
395 /* swidth */ (640 * 910 + 780 / 2) / 780,
396 /* totalwidth */ 910,
397 /* sqwidth */ 780,
398 /* vdelay */ 0x1a,
399 /* sheight */ 576,
Hans de Goede35ccece2013-03-25 14:45:54 -0300400 /* extraheight */ 0,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300401 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 },{
403 .v4l2_id = V4L2_STD_PAL_M,
404 .name = "PAL-M",
405 .Fsc = 28636363,
406 .swidth = 640,
407 .sheight = 480,
408 .totalwidth = 910,
409 .adelay = 0x68,
410 .bdelay = 0x5d,
411 .iform = (BT848_IFORM_PAL_M|BT848_IFORM_XT0),
412 .scaledtwidth = 780,
413 .hdelayx1 = 135,
414 .hactivex1 = 754,
415 .vdelay = 0x1a,
416 .vbipack = 144,
417 .sram = -1,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200418 .vbistart = { 10, 273 },
Michael Schimeke5bd0262007-01-18 16:17:39 -0300419 CROPCAP(/* minhdelayx1 */ 68,
420 /* hdelayx1 */ 135,
421 /* swidth */ (640 * 910 + 780 / 2) / 780,
422 /* totalwidth */ 910,
423 /* sqwidth */ 780,
424 /* vdelay */ 0x1a,
425 /* sheight */ 480,
Hans de Goede35ccece2013-03-25 14:45:54 -0300426 /* extraheight */ 0,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300427 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 },{
429 .v4l2_id = V4L2_STD_PAL_N,
430 .name = "PAL-N",
431 .Fsc = 35468950,
432 .swidth = 768,
433 .sheight = 576,
434 .totalwidth = 1135,
435 .adelay = 0x7f,
436 .bdelay = 0x72,
437 .iform = (BT848_IFORM_PAL_N|BT848_IFORM_XT1),
438 .scaledtwidth = 944,
439 .hdelayx1 = 186,
440 .hactivex1 = 922,
441 .vdelay = 0x20,
442 .vbipack = 144,
443 .sram = -1,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300444 .vbistart = { 7, 320 },
445 CROPCAP(/* minhdelayx1 */ 68,
446 /* hdelayx1 */ 186,
447 /* swidth */ (768 * 1135 + 944 / 2) / 944,
448 /* totalwidth */ 1135,
449 /* sqwidth */ 944,
450 /* vdelay */ 0x20,
451 /* sheight */ 576,
Hans de Goede35ccece2013-03-25 14:45:54 -0300452 /* extraheight */ 0,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300453 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 },{
455 .v4l2_id = V4L2_STD_NTSC_M_JP,
456 .name = "NTSC-JP",
457 .Fsc = 28636363,
458 .swidth = 640,
459 .sheight = 480,
460 .totalwidth = 910,
461 .adelay = 0x68,
462 .bdelay = 0x5d,
463 .iform = (BT848_IFORM_NTSC_J|BT848_IFORM_XT0),
464 .scaledtwidth = 780,
465 .hdelayx1 = 135,
466 .hactivex1 = 754,
467 .vdelay = 0x16,
468 .vbipack = 144,
469 .sram = -1,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300470 .vbistart = { 10, 273 },
471 CROPCAP(/* minhdelayx1 */ 68,
472 /* hdelayx1 */ 135,
473 /* swidth */ (640 * 910 + 780 / 2) / 780,
474 /* totalwidth */ 910,
475 /* sqwidth */ 780,
476 /* vdelay */ 0x16,
477 /* sheight */ 480,
Hans de Goede35ccece2013-03-25 14:45:54 -0300478 /* extraheight */ 0,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300479 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480 },{
481 /* that one hopefully works with the strange timing
482 * which video recorders produce when playing a NTSC
483 * tape on a PAL TV ... */
484 .v4l2_id = V4L2_STD_PAL_60,
485 .name = "PAL-60",
486 .Fsc = 35468950,
487 .swidth = 924,
488 .sheight = 480,
489 .totalwidth = 1135,
490 .adelay = 0x7f,
491 .bdelay = 0x72,
492 .iform = (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
493 .scaledtwidth = 1135,
494 .hdelayx1 = 186,
495 .hactivex1 = 924,
496 .vdelay = 0x1a,
497 .vbipack = 255,
498 .vtotal = 524,
499 .sram = -1,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200500 .vbistart = { 10, 273 },
Michael Schimeke5bd0262007-01-18 16:17:39 -0300501 CROPCAP(/* minhdelayx1 */ 68,
502 /* hdelayx1 */ 186,
503 /* swidth */ 924,
504 /* totalwidth */ 1135,
505 /* sqwidth */ 944,
506 /* vdelay */ 0x1a,
507 /* sheight */ 480,
Hans de Goede35ccece2013-03-25 14:45:54 -0300508 /* extraheight */ 0,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300509 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 }
511};
512static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms);
513
514/* ----------------------------------------------------------------------- */
515/* bttv format list
516 packed pixel formats must come first */
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -0300517static const struct bttv_format formats[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 {
519 .name = "8 bpp, gray",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 .fourcc = V4L2_PIX_FMT_GREY,
521 .btformat = BT848_COLOR_FMT_Y8,
522 .depth = 8,
523 .flags = FORMAT_FLAGS_PACKED,
524 },{
525 .name = "8 bpp, dithered color",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 .fourcc = V4L2_PIX_FMT_HI240,
527 .btformat = BT848_COLOR_FMT_RGB8,
528 .depth = 8,
529 .flags = FORMAT_FLAGS_PACKED | FORMAT_FLAGS_DITHER,
530 },{
531 .name = "15 bpp RGB, le",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 .fourcc = V4L2_PIX_FMT_RGB555,
533 .btformat = BT848_COLOR_FMT_RGB15,
534 .depth = 16,
535 .flags = FORMAT_FLAGS_PACKED,
536 },{
537 .name = "15 bpp RGB, be",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 .fourcc = V4L2_PIX_FMT_RGB555X,
539 .btformat = BT848_COLOR_FMT_RGB15,
540 .btswap = 0x03, /* byteswap */
541 .depth = 16,
542 .flags = FORMAT_FLAGS_PACKED,
543 },{
544 .name = "16 bpp RGB, le",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 .fourcc = V4L2_PIX_FMT_RGB565,
546 .btformat = BT848_COLOR_FMT_RGB16,
547 .depth = 16,
548 .flags = FORMAT_FLAGS_PACKED,
549 },{
550 .name = "16 bpp RGB, be",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 .fourcc = V4L2_PIX_FMT_RGB565X,
552 .btformat = BT848_COLOR_FMT_RGB16,
553 .btswap = 0x03, /* byteswap */
554 .depth = 16,
555 .flags = FORMAT_FLAGS_PACKED,
556 },{
557 .name = "24 bpp RGB, le",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 .fourcc = V4L2_PIX_FMT_BGR24,
559 .btformat = BT848_COLOR_FMT_RGB24,
560 .depth = 24,
561 .flags = FORMAT_FLAGS_PACKED,
562 },{
563 .name = "32 bpp RGB, le",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 .fourcc = V4L2_PIX_FMT_BGR32,
565 .btformat = BT848_COLOR_FMT_RGB32,
566 .depth = 32,
567 .flags = FORMAT_FLAGS_PACKED,
568 },{
569 .name = "32 bpp RGB, be",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 .fourcc = V4L2_PIX_FMT_RGB32,
571 .btformat = BT848_COLOR_FMT_RGB32,
572 .btswap = 0x0f, /* byte+word swap */
573 .depth = 32,
574 .flags = FORMAT_FLAGS_PACKED,
575 },{
576 .name = "4:2:2, packed, YUYV",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 .fourcc = V4L2_PIX_FMT_YUYV,
578 .btformat = BT848_COLOR_FMT_YUY2,
579 .depth = 16,
580 .flags = FORMAT_FLAGS_PACKED,
581 },{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582 .name = "4:2:2, packed, UYVY",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 .fourcc = V4L2_PIX_FMT_UYVY,
584 .btformat = BT848_COLOR_FMT_YUY2,
585 .btswap = 0x03, /* byteswap */
586 .depth = 16,
587 .flags = FORMAT_FLAGS_PACKED,
588 },{
589 .name = "4:2:2, planar, Y-Cb-Cr",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 .fourcc = V4L2_PIX_FMT_YUV422P,
591 .btformat = BT848_COLOR_FMT_YCrCb422,
592 .depth = 16,
593 .flags = FORMAT_FLAGS_PLANAR,
594 .hshift = 1,
595 .vshift = 0,
596 },{
597 .name = "4:2:0, planar, Y-Cb-Cr",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598 .fourcc = V4L2_PIX_FMT_YUV420,
599 .btformat = BT848_COLOR_FMT_YCrCb422,
600 .depth = 12,
601 .flags = FORMAT_FLAGS_PLANAR,
602 .hshift = 1,
603 .vshift = 1,
604 },{
605 .name = "4:2:0, planar, Y-Cr-Cb",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 .fourcc = V4L2_PIX_FMT_YVU420,
607 .btformat = BT848_COLOR_FMT_YCrCb422,
608 .depth = 12,
609 .flags = FORMAT_FLAGS_PLANAR | FORMAT_FLAGS_CrCb,
610 .hshift = 1,
611 .vshift = 1,
612 },{
613 .name = "4:1:1, planar, Y-Cb-Cr",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 .fourcc = V4L2_PIX_FMT_YUV411P,
615 .btformat = BT848_COLOR_FMT_YCrCb411,
616 .depth = 12,
617 .flags = FORMAT_FLAGS_PLANAR,
618 .hshift = 2,
619 .vshift = 0,
620 },{
621 .name = "4:1:0, planar, Y-Cb-Cr",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622 .fourcc = V4L2_PIX_FMT_YUV410,
623 .btformat = BT848_COLOR_FMT_YCrCb411,
624 .depth = 9,
625 .flags = FORMAT_FLAGS_PLANAR,
626 .hshift = 2,
627 .vshift = 2,
628 },{
629 .name = "4:1:0, planar, Y-Cr-Cb",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 .fourcc = V4L2_PIX_FMT_YVU410,
631 .btformat = BT848_COLOR_FMT_YCrCb411,
632 .depth = 9,
633 .flags = FORMAT_FLAGS_PLANAR | FORMAT_FLAGS_CrCb,
634 .hshift = 2,
635 .vshift = 2,
636 },{
637 .name = "raw scanlines",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 .fourcc = -1,
639 .btformat = BT848_COLOR_FMT_RAW,
640 .depth = 8,
641 .flags = FORMAT_FLAGS_RAW,
642 }
643};
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -0300644static const unsigned int FORMATS = ARRAY_SIZE(formats);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645
646/* ----------------------------------------------------------------------- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647/* resource management */
648
Michael Schimeke5bd0262007-01-18 16:17:39 -0300649/*
650 RESOURCE_ allocated by freed by
651
652 VIDEO_READ bttv_read 1) bttv_read 2)
653
654 VIDEO_STREAM VIDIOC_STREAMON VIDIOC_STREAMOFF
655 VIDIOC_QBUF 1) bttv_release
656 VIDIOCMCAPTURE 1)
657
658 OVERLAY VIDIOCCAPTURE on VIDIOCCAPTURE off
659 VIDIOC_OVERLAY on VIDIOC_OVERLAY off
660 3) bttv_release
661
662 VBI VIDIOC_STREAMON VIDIOC_STREAMOFF
663 VIDIOC_QBUF 1) bttv_release
664 bttv_read, bttv_poll 1) 4)
665
666 1) The resource must be allocated when we enter buffer prepare functions
667 and remain allocated while buffers are in the DMA queue.
668 2) This is a single frame read.
669 3) VIDIOC_S_FBUF and VIDIOC_S_FMT (OVERLAY) still work when
670 RESOURCE_OVERLAY is allocated.
671 4) This is a continuous read, implies VIDIOC_STREAMON.
672
673 Note this driver permits video input and standard changes regardless if
674 resources are allocated.
675*/
676
677#define VBI_RESOURCES (RESOURCE_VBI)
678#define VIDEO_RESOURCES (RESOURCE_VIDEO_READ | \
679 RESOURCE_VIDEO_STREAM | \
680 RESOURCE_OVERLAY)
681
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682static
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -0300683int check_alloc_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684{
Michael Schimeke5bd0262007-01-18 16:17:39 -0300685 int xbits; /* mutual exclusive resources */
686
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 if (fh->resources & bit)
688 /* have it already allocated */
689 return 1;
690
Michael Schimeke5bd0262007-01-18 16:17:39 -0300691 xbits = bit;
692 if (bit & (RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM))
693 xbits |= RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM;
694
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695 /* is it free? */
Michael Schimeke5bd0262007-01-18 16:17:39 -0300696 if (btv->resources & xbits) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 /* no, someone else uses it */
Michael Schimeke5bd0262007-01-18 16:17:39 -0300698 goto fail;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699 }
Michael Schimeke5bd0262007-01-18 16:17:39 -0300700
701 if ((bit & VIDEO_RESOURCES)
702 && 0 == (btv->resources & VIDEO_RESOURCES)) {
703 /* Do crop - use current, don't - use default parameters. */
704 __s32 top = btv->crop[!!fh->do_crop].rect.top;
705
706 if (btv->vbi_end > top)
707 goto fail;
708
709 /* We cannot capture the same line as video and VBI data.
710 Claim scan lines crop[].rect.top to bottom. */
711 btv->crop_start = top;
712 } else if (bit & VBI_RESOURCES) {
713 __s32 end = fh->vbi_fmt.end;
714
715 if (end > btv->crop_start)
716 goto fail;
717
718 /* Claim scan lines above fh->vbi_fmt.end. */
719 btv->vbi_end = end;
720 }
721
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 /* it's free, grab it */
723 fh->resources |= bit;
724 btv->resources |= bit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 return 1;
Michael Schimeke5bd0262007-01-18 16:17:39 -0300726
727 fail:
Michael Schimeke5bd0262007-01-18 16:17:39 -0300728 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729}
730
731static
732int check_btres(struct bttv_fh *fh, int bit)
733{
734 return (fh->resources & bit);
735}
736
737static
738int locked_btres(struct bttv *btv, int bit)
739{
740 return (btv->resources & bit);
741}
742
Michael Schimeke5bd0262007-01-18 16:17:39 -0300743/* Call with btv->lock down. */
744static void
745disclaim_vbi_lines(struct bttv *btv)
746{
747 btv->vbi_end = 0;
748}
749
750/* Call with btv->lock down. */
751static void
752disclaim_video_lines(struct bttv *btv)
753{
754 const struct bttv_tvnorm *tvnorm;
755 u8 crop;
756
757 tvnorm = &bttv_tvnorms[btv->tvnorm];
758 btv->crop_start = tvnorm->cropcap.bounds.top
759 + tvnorm->cropcap.bounds.height;
760
761 /* VBI capturing ends at VDELAY, start of video capturing, no
762 matter how many lines the VBI RISC program expects. When video
763 capturing is off, it shall no longer "preempt" VBI capturing,
764 so we set VDELAY to maximum. */
765 crop = btread(BT848_E_CROP) | 0xc0;
766 btwrite(crop, BT848_E_CROP);
767 btwrite(0xfe, BT848_E_VDELAY_LO);
768 btwrite(crop, BT848_O_CROP);
769 btwrite(0xfe, BT848_O_VDELAY_LO);
770}
771
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772static
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -0300773void free_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bits)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775 if ((fh->resources & bits) != bits) {
Joe Perches8af443e2011-08-21 19:56:48 -0300776 /* trying to free resources not allocated by us ... */
777 pr_err("BUG! (btres)\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 fh->resources &= ~bits;
780 btv->resources &= ~bits;
Michael Schimeke5bd0262007-01-18 16:17:39 -0300781
782 bits = btv->resources;
783
784 if (0 == (bits & VIDEO_RESOURCES))
785 disclaim_video_lines(btv);
786
787 if (0 == (bits & VBI_RESOURCES))
788 disclaim_vbi_lines(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789}
790
791/* ----------------------------------------------------------------------- */
792/* If Bt848a or Bt849, use PLL for PAL/SECAM and crystal for NTSC */
793
794/* Frequency = (F_input / PLL_X) * PLL_I.PLL_F/PLL_C
795 PLL_X = Reference pre-divider (0=1, 1=2)
796 PLL_C = Post divider (0=6, 1=4)
797 PLL_I = Integer input
798 PLL_F = Fractional input
799
800 F_input = 28.636363 MHz:
801 PAL (CLKx2 = 35.46895 MHz): PLL_X = 1, PLL_I = 0x0E, PLL_F = 0xDCF9, PLL_C = 0
802*/
803
804static void set_pll_freq(struct bttv *btv, unsigned int fin, unsigned int fout)
805{
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800806 unsigned char fl, fh, fi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800808 /* prevent overflows */
809 fin/=4;
810 fout/=4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800812 fout*=12;
813 fi=fout/fin;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800815 fout=(fout%fin)*256;
816 fh=fout/fin;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800818 fout=(fout%fin)*256;
819 fl=fout/fin;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800821 btwrite(fl, BT848_PLL_F_LO);
822 btwrite(fh, BT848_PLL_F_HI);
823 btwrite(fi|BT848_PLL_X, BT848_PLL_XCI);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824}
825
826static void set_pll(struct bttv *btv)
827{
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800828 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800830 if (!btv->pll.pll_crystal)
831 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832
833 if (btv->pll.pll_ofreq == btv->pll.pll_current) {
Joe Perches8af443e2011-08-21 19:56:48 -0300834 dprintk("%d: PLL: no change required\n", btv->c.nr);
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800835 return;
836 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800838 if (btv->pll.pll_ifreq == btv->pll.pll_ofreq) {
839 /* no PLL needed */
840 if (btv->pll.pll_current == 0)
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -0800841 return;
Joe Perches8af443e2011-08-21 19:56:48 -0300842 if (bttv_verbose)
843 pr_info("%d: PLL can sleep, using XTAL (%d)\n",
844 btv->c.nr, btv->pll.pll_ifreq);
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800845 btwrite(0x00,BT848_TGCTRL);
846 btwrite(0x00,BT848_PLL_XCI);
847 btv->pll.pll_current = 0;
848 return;
849 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850
Joe Perches8af443e2011-08-21 19:56:48 -0300851 if (bttv_verbose)
852 pr_info("%d: Setting PLL: %d => %d (needs up to 100ms)\n",
853 btv->c.nr,
854 btv->pll.pll_ifreq, btv->pll.pll_ofreq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 set_pll_freq(btv, btv->pll.pll_ifreq, btv->pll.pll_ofreq);
856
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800857 for (i=0; i<10; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 /* Let other people run while the PLL stabilizes */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859 msleep(10);
860
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800861 if (btread(BT848_DSTATUS) & BT848_DSTATUS_PLOCK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 btwrite(0,BT848_DSTATUS);
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800863 } else {
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -0800864 btwrite(0x08,BT848_TGCTRL);
865 btv->pll.pll_current = btv->pll.pll_ofreq;
Joe Perches8af443e2011-08-21 19:56:48 -0300866 if (bttv_verbose)
867 pr_info("PLL set ok\n");
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -0800868 return;
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800869 }
870 }
871 btv->pll.pll_current = -1;
Joe Perches8af443e2011-08-21 19:56:48 -0300872 if (bttv_verbose)
873 pr_info("Setting PLL failed\n");
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800874 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875}
876
877/* used to switch between the bt848's analog/digital video capture modes */
878static void bt848A_set_timing(struct bttv *btv)
879{
880 int i, len;
881 int table_idx = bttv_tvnorms[btv->tvnorm].sram;
882 int fsc = bttv_tvnorms[btv->tvnorm].Fsc;
883
Trent Piepho5221e212009-01-28 21:32:59 -0300884 if (btv->input == btv->dig) {
Joe Perches8af443e2011-08-21 19:56:48 -0300885 dprintk("%d: load digital timing table (table_idx=%d)\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 btv->c.nr,table_idx);
887
888 /* timing change...reset timing generator address */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800889 btwrite(0x00, BT848_TGCTRL);
890 btwrite(0x02, BT848_TGCTRL);
891 btwrite(0x00, BT848_TGCTRL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892
893 len=SRAM_Table[table_idx][0];
894 for(i = 1; i <= len; i++)
895 btwrite(SRAM_Table[table_idx][i],BT848_TGLB);
896 btv->pll.pll_ofreq = 27000000;
897
898 set_pll(btv);
899 btwrite(0x11, BT848_TGCTRL);
900 btwrite(0x41, BT848_DVSIF);
901 } else {
902 btv->pll.pll_ofreq = fsc;
903 set_pll(btv);
904 btwrite(0x0, BT848_DVSIF);
905 }
906}
907
908/* ----------------------------------------------------------------------- */
909
910static void bt848_bright(struct bttv *btv, int bright)
911{
912 int value;
913
Joe Perches8af443e2011-08-21 19:56:48 -0300914 // printk("set bright: %d\n", bright); // DEBUG
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 btv->bright = bright;
916
917 /* We want -128 to 127 we get 0-65535 */
918 value = (bright >> 8) - 128;
919 btwrite(value & 0xff, BT848_BRIGHT);
920}
921
922static void bt848_hue(struct bttv *btv, int hue)
923{
924 int value;
925
926 btv->hue = hue;
927
928 /* -128 to 127 */
929 value = (hue >> 8) - 128;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800930 btwrite(value & 0xff, BT848_HUE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931}
932
933static void bt848_contrast(struct bttv *btv, int cont)
934{
935 int value,hibit;
936
937 btv->contrast = cont;
938
939 /* 0-511 */
940 value = (cont >> 7);
941 hibit = (value >> 6) & 4;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800942 btwrite(value & 0xff, BT848_CONTRAST_LO);
943 btaor(hibit, ~4, BT848_E_CONTROL);
944 btaor(hibit, ~4, BT848_O_CONTROL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945}
946
947static void bt848_sat(struct bttv *btv, int color)
948{
949 int val_u,val_v,hibits;
950
951 btv->saturation = color;
952
953 /* 0-511 for the color */
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700954 val_u = ((color * btv->opt_uv_ratio) / 50) >> 7;
955 val_v = (((color * (100 - btv->opt_uv_ratio) / 50) >>7)*180L)/254;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800956 hibits = (val_u >> 7) & 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 hibits |= (val_v >> 8) & 1;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800958 btwrite(val_u & 0xff, BT848_SAT_U_LO);
959 btwrite(val_v & 0xff, BT848_SAT_V_LO);
960 btaor(hibits, ~3, BT848_E_CONTROL);
961 btaor(hibits, ~3, BT848_O_CONTROL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962}
963
964/* ----------------------------------------------------------------------- */
965
966static int
967video_mux(struct bttv *btv, unsigned int input)
968{
969 int mux,mask2;
970
971 if (input >= bttv_tvcards[btv->c.type].video_inputs)
972 return -EINVAL;
973
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800974 /* needed by RemoteVideo MX */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 mask2 = bttv_tvcards[btv->c.type].gpiomask2;
976 if (mask2)
977 gpio_inout(mask2,mask2);
978
979 if (input == btv->svhs) {
980 btor(BT848_CONTROL_COMP, BT848_E_CONTROL);
981 btor(BT848_CONTROL_COMP, BT848_O_CONTROL);
982 } else {
983 btand(~BT848_CONTROL_COMP, BT848_E_CONTROL);
984 btand(~BT848_CONTROL_COMP, BT848_O_CONTROL);
985 }
Trent Piepho6f987002009-01-28 21:32:59 -0300986 mux = bttv_muxsel(btv, input);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 btaor(mux<<5, ~(3<<5), BT848_IFORM);
Joe Perches8af443e2011-08-21 19:56:48 -0300988 dprintk("%d: video mux: input=%d mux=%d\n", btv->c.nr, input, mux);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989
990 /* card specific hook */
991 if(bttv_tvcards[btv->c.type].muxsel_hook)
992 bttv_tvcards[btv->c.type].muxsel_hook (btv, input);
993 return 0;
994}
995
996static char *audio_modes[] = {
997 "audio: tuner", "audio: radio", "audio: extern",
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -0300998 "audio: intern", "audio: mute"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999};
1000
Frank Schaefer5f4567812013-03-21 13:51:17 -03001001static void
1002audio_mux_gpio(struct bttv *btv, int input, int mute)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003{
Frank Schaefer28cafc32013-03-21 13:51:13 -03001004 int gpio_val, signal, mute_gpio;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005
1006 gpio_inout(bttv_tvcards[btv->c.type].gpiomask,
1007 bttv_tvcards[btv->c.type].gpiomask);
1008 signal = btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC;
1009
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001010 /* automute */
Frank Schaefer28cafc32013-03-21 13:51:13 -03001011 mute_gpio = mute || (btv->opt_automute && (!signal || !btv->users)
Hans Verkuilb8e2a362013-02-10 09:24:14 -03001012 && !btv->has_radio_tuner);
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001013
Frank Schaefer28cafc32013-03-21 13:51:13 -03001014 if (mute_gpio)
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001015 gpio_val = bttv_tvcards[btv->c.type].gpiomute;
1016 else
1017 gpio_val = bttv_tvcards[btv->c.type].gpiomux[input];
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001018
Trent Piepho72134a62009-01-28 21:32:59 -03001019 switch (btv->c.type) {
1020 case BTTV_BOARD_VOODOOTV_FM:
1021 case BTTV_BOARD_VOODOOTV_200:
1022 gpio_val = bttv_tda9880_setnorm(btv, gpio_val);
1023 break;
1024
1025 default:
1026 gpio_bits(bttv_tvcards[btv->c.type].gpiomask, gpio_val);
1027 }
1028
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 if (bttv_gpio)
Frank Schaefer28cafc32013-03-21 13:51:13 -03001030 bttv_gpio_tracking(btv, audio_modes[mute_gpio ? 4 : input]);
Frank Schaefer5f4567812013-03-21 13:51:17 -03001031}
1032
1033static int
Frank Schaeferb1a30152013-03-21 13:51:18 -03001034audio_mute(struct bttv *btv, int mute)
Frank Schaefer5f4567812013-03-21 13:51:17 -03001035{
1036 struct v4l2_ctrl *ctrl;
1037
Frank Schaeferb1a30152013-03-21 13:51:18 -03001038 audio_mux_gpio(btv, btv->audio_input, mute);
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001039
Hans Verkuil859f0272009-03-28 08:29:00 -03001040 if (btv->sd_msp34xx) {
Hans Verkuil01df5302013-02-06 12:40:28 -03001041 ctrl = v4l2_ctrl_find(btv->sd_msp34xx->ctrl_handler, V4L2_CID_AUDIO_MUTE);
1042 if (ctrl)
Frank Schaefer598728e2013-03-21 13:51:14 -03001043 v4l2_ctrl_s_ctrl(ctrl, mute);
Frank Schaeferb1a30152013-03-21 13:51:18 -03001044 }
1045 if (btv->sd_tvaudio) {
1046 ctrl = v4l2_ctrl_find(btv->sd_tvaudio->ctrl_handler, V4L2_CID_AUDIO_MUTE);
1047 if (ctrl)
1048 v4l2_ctrl_s_ctrl(ctrl, mute);
1049 }
1050 if (btv->sd_tda7432) {
1051 ctrl = v4l2_ctrl_find(btv->sd_tda7432->ctrl_handler, V4L2_CID_AUDIO_MUTE);
1052 if (ctrl)
1053 v4l2_ctrl_s_ctrl(ctrl, mute);
1054 }
1055 return 0;
1056}
1057
1058static int
1059audio_input(struct bttv *btv, int input)
1060{
1061 audio_mux_gpio(btv, input, btv->mute);
1062
1063 if (btv->sd_msp34xx) {
1064 u32 in;
Hans Verkuil01df5302013-02-06 12:40:28 -03001065
Hans Verkuil2474ed42006-03-19 12:35:57 -03001066 /* Note: the inputs tuner/radio/extern/intern are translated
1067 to msp routings. This assumes common behavior for all msp3400
1068 based TV cards. When this assumption fails, then the
1069 specific MSP routing must be added to the card table.
1070 For now this is sufficient. */
1071 switch (input) {
1072 case TVAUDIO_INPUT_RADIO:
Hans de Goede7025e522012-05-21 07:46:22 -03001073 /* Some boards need the msp do to the radio demod */
1074 if (btv->radio_uses_msp_demodulator) {
1075 in = MSP_INPUT_DEFAULT;
1076 break;
1077 }
Hans Verkuil5325b422009-04-02 11:26:22 -03001078 in = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1,
Hans Verkuil07151722006-04-01 18:03:23 -03001079 MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001080 break;
1081 case TVAUDIO_INPUT_EXTERN:
Hans Verkuil5325b422009-04-02 11:26:22 -03001082 in = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1,
Hans Verkuil07151722006-04-01 18:03:23 -03001083 MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001084 break;
1085 case TVAUDIO_INPUT_INTERN:
1086 /* Yes, this is the same input as for RADIO. I doubt
1087 if this is ever used. The only board with an INTERN
1088 input is the BTTV_BOARD_AVERMEDIA98. I wonder how
1089 that was tested. My guess is that the whole INTERN
1090 input does not work. */
Hans Verkuil5325b422009-04-02 11:26:22 -03001091 in = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1,
Hans Verkuil07151722006-04-01 18:03:23 -03001092 MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001093 break;
1094 case TVAUDIO_INPUT_TUNER:
1095 default:
Wade Berrier434b2522007-06-25 13:02:16 -03001096 /* This is the only card that uses TUNER2, and afaik,
1097 is the only difference between the VOODOOTV_FM
1098 and VOODOOTV_200 */
1099 if (btv->c.type == BTTV_BOARD_VOODOOTV_200)
Hans Verkuil5325b422009-04-02 11:26:22 -03001100 in = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER2, \
Wade Berrier434b2522007-06-25 13:02:16 -03001101 MSP_DSP_IN_TUNER, MSP_DSP_IN_TUNER);
1102 else
Hans Verkuil5325b422009-04-02 11:26:22 -03001103 in = MSP_INPUT_DEFAULT;
Hans Verkuil2474ed42006-03-19 12:35:57 -03001104 break;
1105 }
Hans Verkuil5325b422009-04-02 11:26:22 -03001106 v4l2_subdev_call(btv->sd_msp34xx, audio, s_routing,
1107 in, MSP_OUTPUT_DEFAULT, 0);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001108 }
Hans Verkuil859f0272009-03-28 08:29:00 -03001109 if (btv->sd_tvaudio) {
Hans Verkuil5325b422009-04-02 11:26:22 -03001110 v4l2_subdev_call(btv->sd_tvaudio, audio, s_routing,
Frank Schaeferb1a30152013-03-21 13:51:18 -03001111 input, 0, 0);
Hans Verkuil01df5302013-02-06 12:40:28 -03001112 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 return 0;
1114}
1115
1116static void
Michael Schimeke5bd0262007-01-18 16:17:39 -03001117bttv_crop_calc_limits(struct bttv_crop *c)
1118{
1119 /* Scale factor min. 1:1, max. 16:1. Min. image size
1120 48 x 32. Scaled width must be a multiple of 4. */
1121
1122 if (1) {
1123 /* For bug compatibility with VIDIOCGCAP and image
1124 size checks in earlier driver versions. */
1125 c->min_scaled_width = 48;
1126 c->min_scaled_height = 32;
1127 } else {
1128 c->min_scaled_width =
Ricardo Ribaldaf90580c2013-11-26 05:31:42 -03001129 (max_t(unsigned int, 48, c->rect.width >> 4) + 3) & ~3;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001130 c->min_scaled_height =
Ricardo Ribaldaf90580c2013-11-26 05:31:42 -03001131 max_t(unsigned int, 32, c->rect.height >> 4);
Michael Schimeke5bd0262007-01-18 16:17:39 -03001132 }
1133
1134 c->max_scaled_width = c->rect.width & ~3;
1135 c->max_scaled_height = c->rect.height;
1136}
1137
1138static void
Trent Piepho4ef2ccc2009-01-28 21:32:58 -03001139bttv_crop_reset(struct bttv_crop *c, unsigned int norm)
Michael Schimeke5bd0262007-01-18 16:17:39 -03001140{
1141 c->rect = bttv_tvnorms[norm].cropcap.defrect;
1142 bttv_crop_calc_limits(c);
1143}
1144
1145/* Call with btv->lock down. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146static int
1147set_tvnorm(struct bttv *btv, unsigned int norm)
1148{
1149 const struct bttv_tvnorm *tvnorm;
Nickolay V. Shmyrev302f61a2007-10-26 10:53:21 -03001150 v4l2_std_id id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151
Trent Piepho4ef2ccc2009-01-28 21:32:58 -03001152 BUG_ON(norm >= BTTV_TVNORMS);
1153 BUG_ON(btv->tvnorm >= BTTV_TVNORMS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 tvnorm = &bttv_tvnorms[norm];
1156
Mike Isely2de26c02009-09-21 12:42:22 -03001157 if (memcmp(&bttv_tvnorms[btv->tvnorm].cropcap, &tvnorm->cropcap,
Trent Piepho4ef2ccc2009-01-28 21:32:58 -03001158 sizeof (tvnorm->cropcap))) {
Michael Schimeke5bd0262007-01-18 16:17:39 -03001159 bttv_crop_reset(&btv->crop[0], norm);
1160 btv->crop[1] = btv->crop[0]; /* current = default */
1161
1162 if (0 == (btv->resources & VIDEO_RESOURCES)) {
1163 btv->crop_start = tvnorm->cropcap.bounds.top
1164 + tvnorm->cropcap.bounds.height;
1165 }
1166 }
1167
1168 btv->tvnorm = norm;
1169
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 btwrite(tvnorm->adelay, BT848_ADELAY);
1171 btwrite(tvnorm->bdelay, BT848_BDELAY);
1172 btaor(tvnorm->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH),
1173 BT848_IFORM);
1174 btwrite(tvnorm->vbipack, BT848_VBI_PACK_SIZE);
1175 btwrite(1, BT848_VBI_PACK_DEL);
1176 bt848A_set_timing(btv);
1177
1178 switch (btv->c.type) {
Mauro Carvalho Chehab5a25e842005-11-08 21:36:52 -08001179 case BTTV_BOARD_VOODOOTV_FM:
Wade Berrier434b2522007-06-25 13:02:16 -03001180 case BTTV_BOARD_VOODOOTV_200:
Trent Piepho72134a62009-01-28 21:32:59 -03001181 bttv_tda9880_setnorm(btv, gpio_read());
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 }
Nickolay V. Shmyrev302f61a2007-10-26 10:53:21 -03001184 id = tvnorm->v4l2_id;
Laurent Pinchart8774bed2014-04-28 16:53:01 -03001185 bttv_call_all(btv, video, s_std, id);
Nickolay V. Shmyrev302f61a2007-10-26 10:53:21 -03001186
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 return 0;
1188}
1189
Michael Schimeke5bd0262007-01-18 16:17:39 -03001190/* Call with btv->lock down. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191static void
Trent Piepho333408f2007-07-03 15:08:10 -03001192set_input(struct bttv *btv, unsigned int input, unsigned int norm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193{
1194 unsigned long flags;
1195
1196 btv->input = input;
1197 if (irq_iswitch) {
1198 spin_lock_irqsave(&btv->s_lock,flags);
1199 if (btv->curr.frame_irq) {
1200 /* active capture -> delayed input switch */
1201 btv->new_input = input;
1202 } else {
1203 video_mux(btv,input);
1204 }
1205 spin_unlock_irqrestore(&btv->s_lock,flags);
1206 } else {
1207 video_mux(btv,input);
1208 }
Frank Schaefer2166f0a2013-03-21 13:51:16 -03001209 btv->audio_input = (btv->tuner_type != TUNER_ABSENT && input == 0) ?
1210 TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN;
1211 audio_input(btv, btv->audio_input);
Trent Piepho333408f2007-07-03 15:08:10 -03001212 set_tvnorm(btv, norm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213}
1214
1215static void init_irqreg(struct bttv *btv)
1216{
1217 /* clear status */
1218 btwrite(0xfffffUL, BT848_INT_STAT);
1219
1220 if (bttv_tvcards[btv->c.type].no_video) {
1221 /* i2c only */
1222 btwrite(BT848_INT_I2CDONE,
1223 BT848_INT_MASK);
1224 } else {
1225 /* full video */
1226 btwrite((btv->triton1) |
1227 (btv->gpioirq ? BT848_INT_GPINT : 0) |
1228 BT848_INT_SCERR |
1229 (fdsr ? BT848_INT_FDSR : 0) |
Jean Delvareeb1b27b2008-08-30 10:18:21 -03001230 BT848_INT_RISCI | BT848_INT_OCERR |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 BT848_INT_FMTCHG|BT848_INT_HLOCK|
1232 BT848_INT_I2CDONE,
1233 BT848_INT_MASK);
1234 }
1235}
1236
1237static void init_bt848(struct bttv *btv)
1238{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239 if (bttv_tvcards[btv->c.type].no_video) {
1240 /* very basic init only */
1241 init_irqreg(btv);
1242 return;
1243 }
1244
1245 btwrite(0x00, BT848_CAP_CTL);
1246 btwrite(BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL);
1247 btwrite(BT848_IFORM_XTAUTO | BT848_IFORM_AUTO, BT848_IFORM);
1248
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001249 /* set planar and packed mode trigger points and */
1250 /* set rising edge of inverted GPINTR pin as irq trigger */
1251 btwrite(BT848_GPIO_DMA_CTL_PKTP_32|
1252 BT848_GPIO_DMA_CTL_PLTP1_16|
1253 BT848_GPIO_DMA_CTL_PLTP23_16|
1254 BT848_GPIO_DMA_CTL_GPINTC|
1255 BT848_GPIO_DMA_CTL_GPINTI,
1256 BT848_GPIO_DMA_CTL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001258 btwrite(0x20, BT848_E_VSCALE_HI);
1259 btwrite(0x20, BT848_O_VSCALE_HI);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260
Hans Verkuil01df5302013-02-06 12:40:28 -03001261 v4l2_ctrl_handler_setup(&btv->ctrl_handler);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001263 /* interrupt */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264 init_irqreg(btv);
1265}
1266
1267static void bttv_reinit_bt848(struct bttv *btv)
1268{
1269 unsigned long flags;
1270
1271 if (bttv_verbose)
Joe Perches8af443e2011-08-21 19:56:48 -03001272 pr_info("%d: reset, reinitialize\n", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 spin_lock_irqsave(&btv->s_lock,flags);
1274 btv->errors=0;
1275 bttv_set_dma(btv,0);
1276 spin_unlock_irqrestore(&btv->s_lock,flags);
1277
1278 init_bt848(btv);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001279 btv->pll.pll_current = -1;
Trent Piepho333408f2007-07-03 15:08:10 -03001280 set_input(btv, btv->input, btv->tvnorm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281}
1282
Hans Verkuil01df5302013-02-06 12:40:28 -03001283static int bttv_s_ctrl(struct v4l2_ctrl *c)
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001284{
Hans Verkuil01df5302013-02-06 12:40:28 -03001285 struct bttv *btv = container_of(c->handler, struct bttv, ctrl_handler);
1286 int val;
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001287
1288 switch (c->id) {
1289 case V4L2_CID_BRIGHTNESS:
Hans Verkuil01df5302013-02-06 12:40:28 -03001290 bt848_bright(btv, c->val);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001291 break;
1292 case V4L2_CID_HUE:
Hans Verkuil01df5302013-02-06 12:40:28 -03001293 bt848_hue(btv, c->val);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001294 break;
1295 case V4L2_CID_CONTRAST:
Hans Verkuil01df5302013-02-06 12:40:28 -03001296 bt848_contrast(btv, c->val);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001297 break;
1298 case V4L2_CID_SATURATION:
Hans Verkuil01df5302013-02-06 12:40:28 -03001299 bt848_sat(btv, c->val);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001300 break;
Guilherme Herrmann Destefani34e59a72012-09-25 18:10:52 -03001301 case V4L2_CID_COLOR_KILLER:
Hans Verkuil01df5302013-02-06 12:40:28 -03001302 if (c->val) {
Guilherme Herrmann Destefani34e59a72012-09-25 18:10:52 -03001303 btor(BT848_SCLOOP_CKILL, BT848_E_SCLOOP);
1304 btor(BT848_SCLOOP_CKILL, BT848_O_SCLOOP);
1305 } else {
1306 btand(~BT848_SCLOOP_CKILL, BT848_E_SCLOOP);
1307 btand(~BT848_SCLOOP_CKILL, BT848_O_SCLOOP);
1308 }
1309 break;
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001310 case V4L2_CID_AUDIO_MUTE:
Hans Verkuil01df5302013-02-06 12:40:28 -03001311 audio_mute(btv, c->val);
Frank Schaefer598728e2013-03-21 13:51:14 -03001312 btv->mute = c->val;
Hans Verkuil01df5302013-02-06 12:40:28 -03001313 break;
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001314 case V4L2_CID_AUDIO_VOLUME:
Hans Verkuil01df5302013-02-06 12:40:28 -03001315 btv->volume_gpio(btv, c->val);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001316 break;
1317
Hans Verkuil01df5302013-02-06 12:40:28 -03001318 case V4L2_CID_CHROMA_AGC:
1319 val = c->val ? BT848_SCLOOP_CAGC : 0;
1320 btwrite(val, BT848_E_SCLOOP);
1321 btwrite(val, BT848_O_SCLOOP);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001322 break;
1323 case V4L2_CID_PRIVATE_COMBFILTER:
Hans Verkuil01df5302013-02-06 12:40:28 -03001324 btv->opt_combfilter = c->val;
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001325 break;
1326 case V4L2_CID_PRIVATE_LUMAFILTER:
Hans Verkuil01df5302013-02-06 12:40:28 -03001327 if (c->val) {
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001328 btand(~BT848_CONTROL_LDEC, BT848_E_CONTROL);
1329 btand(~BT848_CONTROL_LDEC, BT848_O_CONTROL);
1330 } else {
1331 btor(BT848_CONTROL_LDEC, BT848_E_CONTROL);
1332 btor(BT848_CONTROL_LDEC, BT848_O_CONTROL);
1333 }
1334 break;
1335 case V4L2_CID_PRIVATE_AUTOMUTE:
Hans Verkuil01df5302013-02-06 12:40:28 -03001336 btv->opt_automute = c->val;
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001337 break;
1338 case V4L2_CID_PRIVATE_AGC_CRUSH:
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001339 btwrite(BT848_ADC_RESERVED |
Hans Verkuil01df5302013-02-06 12:40:28 -03001340 (c->val ? BT848_ADC_CRUSH : 0),
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001341 BT848_ADC);
1342 break;
1343 case V4L2_CID_PRIVATE_VCR_HACK:
Hans Verkuil01df5302013-02-06 12:40:28 -03001344 btv->opt_vcr_hack = c->val;
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001345 break;
1346 case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
Hans Verkuil01df5302013-02-06 12:40:28 -03001347 btwrite(c->val, BT848_WC_UP);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001348 break;
1349 case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
Hans Verkuil01df5302013-02-06 12:40:28 -03001350 btwrite(c->val, BT848_WC_DOWN);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001351 break;
1352 case V4L2_CID_PRIVATE_UV_RATIO:
Hans Verkuil01df5302013-02-06 12:40:28 -03001353 btv->opt_uv_ratio = c->val;
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001354 bt848_sat(btv, btv->saturation);
1355 break;
1356 case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
Hans Verkuil01df5302013-02-06 12:40:28 -03001357 btaor((c->val << 7), ~BT848_OFORM_RANGE, BT848_OFORM);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001358 break;
1359 case V4L2_CID_PRIVATE_CORING:
Hans Verkuil01df5302013-02-06 12:40:28 -03001360 btaor((c->val << 5), ~BT848_OFORM_CORE32, BT848_OFORM);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001361 break;
1362 default:
1363 return -EINVAL;
1364 }
1365 return 0;
1366}
1367
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368/* ----------------------------------------------------------------------- */
1369
Hans Verkuil01df5302013-02-06 12:40:28 -03001370static const struct v4l2_ctrl_ops bttv_ctrl_ops = {
1371 .s_ctrl = bttv_s_ctrl,
1372};
1373
1374static struct v4l2_ctrl_config bttv_ctrl_combfilter = {
1375 .ops = &bttv_ctrl_ops,
1376 .id = V4L2_CID_PRIVATE_COMBFILTER,
1377 .name = "Comb Filter",
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_automute = {
1386 .ops = &bttv_ctrl_ops,
1387 .id = V4L2_CID_PRIVATE_AUTOMUTE,
1388 .name = "Auto Mute",
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_lumafilter = {
1397 .ops = &bttv_ctrl_ops,
1398 .id = V4L2_CID_PRIVATE_LUMAFILTER,
1399 .name = "Luma Decimation Filter",
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_agc_crush = {
1408 .ops = &bttv_ctrl_ops,
1409 .id = V4L2_CID_PRIVATE_AGC_CRUSH,
1410 .name = "AGC Crush",
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_vcr_hack = {
1419 .ops = &bttv_ctrl_ops,
1420 .id = V4L2_CID_PRIVATE_VCR_HACK,
1421 .name = "VCR Hack",
1422 .type = V4L2_CTRL_TYPE_BOOLEAN,
1423 .min = 0,
1424 .max = 1,
1425 .step = 1,
1426 .def = 1,
1427};
1428
1429static struct v4l2_ctrl_config bttv_ctrl_whitecrush_lower = {
1430 .ops = &bttv_ctrl_ops,
1431 .id = V4L2_CID_PRIVATE_WHITECRUSH_LOWER,
1432 .name = "Whitecrush Lower",
1433 .type = V4L2_CTRL_TYPE_INTEGER,
1434 .min = 0,
1435 .max = 255,
1436 .step = 1,
1437 .def = 0x7f,
1438};
1439
1440static struct v4l2_ctrl_config bttv_ctrl_whitecrush_upper = {
1441 .ops = &bttv_ctrl_ops,
1442 .id = V4L2_CID_PRIVATE_WHITECRUSH_UPPER,
1443 .name = "Whitecrush Upper",
1444 .type = V4L2_CTRL_TYPE_INTEGER,
1445 .min = 0,
1446 .max = 255,
1447 .step = 1,
1448 .def = 0xcf,
1449};
1450
1451static struct v4l2_ctrl_config bttv_ctrl_uv_ratio = {
1452 .ops = &bttv_ctrl_ops,
1453 .id = V4L2_CID_PRIVATE_UV_RATIO,
1454 .name = "UV Ratio",
1455 .type = V4L2_CTRL_TYPE_INTEGER,
1456 .min = 0,
1457 .max = 100,
1458 .step = 1,
1459 .def = 50,
1460};
1461
1462static struct v4l2_ctrl_config bttv_ctrl_full_luma = {
1463 .ops = &bttv_ctrl_ops,
1464 .id = V4L2_CID_PRIVATE_FULL_LUMA_RANGE,
1465 .name = "Full Luma Range",
1466 .type = V4L2_CTRL_TYPE_BOOLEAN,
1467 .min = 0,
1468 .max = 1,
1469 .step = 1,
1470};
1471
1472static struct v4l2_ctrl_config bttv_ctrl_coring = {
1473 .ops = &bttv_ctrl_ops,
1474 .id = V4L2_CID_PRIVATE_CORING,
1475 .name = "Coring",
1476 .type = V4L2_CTRL_TYPE_INTEGER,
1477 .min = 0,
1478 .max = 3,
1479 .step = 1,
1480};
1481
1482
1483/* ----------------------------------------------------------------------- */
1484
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485void bttv_gpio_tracking(struct bttv *btv, char *comment)
1486{
1487 unsigned int outbits, data;
1488 outbits = btread(BT848_GPIO_OUT_EN);
1489 data = btread(BT848_GPIO_DATA);
Joe Perches8af443e2011-08-21 19:56:48 -03001490 pr_debug("%d: gpio: en=%08x, out=%08x in=%08x [%s]\n",
1491 btv->c.nr, outbits, data & outbits, data & ~outbits, comment);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492}
1493
1494static void bttv_field_count(struct bttv *btv)
1495{
1496 int need_count = 0;
1497
1498 if (btv->users)
1499 need_count++;
1500
1501 if (need_count) {
1502 /* start field counter */
1503 btor(BT848_INT_VSYNC,BT848_INT_MASK);
1504 } else {
1505 /* stop field counter */
1506 btand(~BT848_INT_VSYNC,BT848_INT_MASK);
1507 btv->field_count = 0;
1508 }
1509}
1510
1511static const struct bttv_format*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512format_by_fourcc(int fourcc)
1513{
1514 unsigned int i;
1515
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001516 for (i = 0; i < FORMATS; i++) {
1517 if (-1 == formats[i].fourcc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518 continue;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001519 if (formats[i].fourcc == fourcc)
1520 return formats+i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 }
1522 return NULL;
1523}
1524
1525/* ----------------------------------------------------------------------- */
1526/* misc helpers */
1527
1528static int
1529bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh,
1530 struct bttv_buffer *new)
1531{
1532 struct bttv_buffer *old;
1533 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534
Joe Perches8af443e2011-08-21 19:56:48 -03001535 dprintk("switch_overlay: enter [new=%p]\n", new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536 if (new)
Brandon Philips0fc06862007-11-06 20:02:36 -03001537 new->vb.state = VIDEOBUF_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538 spin_lock_irqsave(&btv->s_lock,flags);
1539 old = btv->screen;
1540 btv->screen = new;
1541 btv->loop_irq |= 1;
1542 bttv_set_dma(btv, 0x03);
1543 spin_unlock_irqrestore(&btv->s_lock,flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544 if (NULL != old) {
Joe Perches8af443e2011-08-21 19:56:48 -03001545 dprintk("switch_overlay: old=%p state is %d\n",
1546 old, old->vb.state);
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001547 bttv_dma_free(&fh->cap,btv, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 kfree(old);
1549 }
Michael Schimeke5bd0262007-01-18 16:17:39 -03001550 if (NULL == new)
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03001551 free_btres_lock(btv,fh,RESOURCE_OVERLAY);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552 dprintk("switch_overlay: done\n");
Mauro Carvalho Chehaba896dc72014-09-03 15:30:41 -03001553 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554}
1555
1556/* ----------------------------------------------------------------------- */
1557/* video4linux (1) interface */
1558
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001559static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv,
1560 struct bttv_buffer *buf,
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001561 const struct bttv_format *fmt,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562 unsigned int width, unsigned int height,
1563 enum v4l2_field field)
1564{
Michael Schimeke5bd0262007-01-18 16:17:39 -03001565 struct bttv_fh *fh = q->priv_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566 int redo_dma_risc = 0;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001567 struct bttv_crop c;
1568 int norm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569 int rc;
1570
1571 /* check settings */
1572 if (NULL == fmt)
1573 return -EINVAL;
1574 if (fmt->btformat == BT848_COLOR_FMT_RAW) {
1575 width = RAW_BPL;
1576 height = RAW_LINES*2;
1577 if (width*height > buf->vb.bsize)
1578 return -EINVAL;
1579 buf->vb.size = buf->vb.bsize;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001580
1581 /* Make sure tvnorm and vbi_end remain consistent
1582 until we're done. */
Michael Schimeke5bd0262007-01-18 16:17:39 -03001583
1584 norm = btv->tvnorm;
1585
1586 /* In this mode capturing always starts at defrect.top
1587 (default VDELAY), ignoring cropping parameters. */
1588 if (btv->vbi_end > bttv_tvnorms[norm].cropcap.defrect.top) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589 return -EINVAL;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001590 }
1591
Michael Schimeke5bd0262007-01-18 16:17:39 -03001592 c.rect = bttv_tvnorms[norm].cropcap.defrect;
1593 } else {
Michael Schimeke5bd0262007-01-18 16:17:39 -03001594 norm = btv->tvnorm;
1595 c = btv->crop[!!fh->do_crop];
1596
Michael Schimeke5bd0262007-01-18 16:17:39 -03001597 if (width < c.min_scaled_width ||
1598 width > c.max_scaled_width ||
1599 height < c.min_scaled_height)
1600 return -EINVAL;
1601
1602 switch (field) {
1603 case V4L2_FIELD_TOP:
1604 case V4L2_FIELD_BOTTOM:
1605 case V4L2_FIELD_ALTERNATE:
1606 /* btv->crop counts frame lines. Max. scale
1607 factor is 16:1 for frames, 8:1 for fields. */
1608 if (height * 2 > c.max_scaled_height)
1609 return -EINVAL;
1610 break;
1611
1612 default:
1613 if (height > c.max_scaled_height)
1614 return -EINVAL;
1615 break;
1616 }
1617
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618 buf->vb.size = (width * height * fmt->depth) >> 3;
1619 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
1620 return -EINVAL;
1621 }
1622
1623 /* alloc + fill struct bttv_buffer (if changed) */
1624 if (buf->vb.width != width || buf->vb.height != height ||
1625 buf->vb.field != field ||
Michael Schimeke5bd0262007-01-18 16:17:39 -03001626 buf->tvnorm != norm || buf->fmt != fmt ||
1627 buf->crop.top != c.rect.top ||
1628 buf->crop.left != c.rect.left ||
1629 buf->crop.width != c.rect.width ||
1630 buf->crop.height != c.rect.height) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631 buf->vb.width = width;
1632 buf->vb.height = height;
1633 buf->vb.field = field;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001634 buf->tvnorm = norm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635 buf->fmt = fmt;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001636 buf->crop = c.rect;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637 redo_dma_risc = 1;
1638 }
1639
1640 /* alloc risc memory */
Brandon Philips0fc06862007-11-06 20:02:36 -03001641 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642 redo_dma_risc = 1;
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001643 if (0 != (rc = videobuf_iolock(q,&buf->vb,&btv->fbuf)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644 goto fail;
1645 }
1646
1647 if (redo_dma_risc)
1648 if (0 != (rc = bttv_buffer_risc(btv,buf)))
1649 goto fail;
1650
Brandon Philips0fc06862007-11-06 20:02:36 -03001651 buf->vb.state = VIDEOBUF_PREPARED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652 return 0;
1653
1654 fail:
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001655 bttv_dma_free(q,btv,buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656 return rc;
1657}
1658
1659static int
1660buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
1661{
1662 struct bttv_fh *fh = q->priv_data;
1663
1664 *size = fh->fmt->depth*fh->width*fh->height >> 3;
1665 if (0 == *count)
1666 *count = gbuffers;
Andreas Bombedab7e312010-03-21 16:02:45 -03001667 if (*size * *count > gbuffers * gbufsize)
1668 *count = (gbuffers * gbufsize) / *size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669 return 0;
1670}
1671
1672static int
1673buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
1674 enum v4l2_field field)
1675{
1676 struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
1677 struct bttv_fh *fh = q->priv_data;
1678
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001679 return bttv_prepare_buffer(q,fh->btv, buf, fh->fmt,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680 fh->width, fh->height, field);
1681}
1682
1683static void
1684buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
1685{
1686 struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
1687 struct bttv_fh *fh = q->priv_data;
1688 struct bttv *btv = fh->btv;
1689
Brandon Philips0fc06862007-11-06 20:02:36 -03001690 buf->vb.state = VIDEOBUF_QUEUED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691 list_add_tail(&buf->vb.queue,&btv->capture);
1692 if (!btv->curr.frame_irq) {
1693 btv->loop_irq |= 1;
1694 bttv_set_dma(btv, 0x03);
1695 }
1696}
1697
1698static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
1699{
1700 struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
1701 struct bttv_fh *fh = q->priv_data;
1702
Michael Schimekfeaba7a2007-01-26 08:30:05 -03001703 bttv_dma_free(q,fh->btv,buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704}
1705
1706static struct videobuf_queue_ops bttv_video_qops = {
1707 .buf_setup = buffer_setup,
1708 .buf_prepare = buffer_prepare,
1709 .buf_queue = buffer_queue,
1710 .buf_release = buffer_release,
1711};
1712
Hans Verkuilb8e2a362013-02-10 09:24:14 -03001713static void radio_enable(struct bttv *btv)
1714{
1715 /* Switch to the radio tuner */
1716 if (!btv->has_radio_tuner) {
1717 btv->has_radio_tuner = 1;
1718 bttv_call_all(btv, tuner, s_radio);
Frank Schaefer2166f0a2013-03-21 13:51:16 -03001719 btv->audio_input = TVAUDIO_INPUT_RADIO;
1720 audio_input(btv, btv->audio_input);
Hans Verkuilb8e2a362013-02-10 09:24:14 -03001721 }
1722}
1723
Hans Verkuil314527a2013-03-15 06:10:40 -03001724static int bttv_s_std(struct file *file, void *priv, v4l2_std_id id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001726 struct bttv_fh *fh = priv;
1727 struct bttv *btv = fh->btv;
1728 unsigned int i;
Hans Verkuil8c14cc12013-02-06 12:42:40 -03001729 int err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001731 for (i = 0; i < BTTV_TVNORMS; i++)
Hans Verkuil314527a2013-03-15 06:10:40 -03001732 if (id & bttv_tvnorms[i].v4l2_id)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001733 break;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001734 if (i == BTTV_TVNORMS) {
1735 err = -EINVAL;
1736 goto err;
1737 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738
Hans Verkuil314527a2013-03-15 06:10:40 -03001739 btv->std = id;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001740 set_tvnorm(btv, i);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001741
1742err:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001743
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001744 return err;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001745}
1746
Hans Verkuil6795cc52013-02-06 12:43:07 -03001747static int bttv_g_std(struct file *file, void *priv, v4l2_std_id *id)
1748{
1749 struct bttv_fh *fh = priv;
1750 struct bttv *btv = fh->btv;
1751
1752 *id = btv->std;
1753 return 0;
1754}
1755
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001756static int bttv_querystd(struct file *file, void *f, v4l2_std_id *id)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001757{
1758 struct bttv_fh *fh = f;
1759 struct bttv *btv = fh->btv;
1760
1761 if (btread(BT848_DSTATUS) & BT848_DSTATUS_NUML)
Hans Verkuil0bde6c32013-05-29 10:19:02 -03001762 *id &= V4L2_STD_625_50;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001763 else
Hans Verkuil0bde6c32013-05-29 10:19:02 -03001764 *id &= V4L2_STD_525_60;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001765 return 0;
1766}
1767
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001768static int bttv_enum_input(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001769 struct v4l2_input *i)
1770{
1771 struct bttv_fh *fh = priv;
1772 struct bttv *btv = fh->btv;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001773 int rc = 0;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001774
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001775 if (i->index >= bttv_tvcards[btv->c.type].video_inputs) {
1776 rc = -EINVAL;
1777 goto err;
1778 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001779
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001780 i->type = V4L2_INPUT_TYPE_CAMERA;
Hans Verkuilf74f89cb2013-01-31 08:45:13 -03001781 i->audioset = 0;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001782
Trent Piephoabb03622009-01-28 21:32:59 -03001783 if (btv->tuner_type != TUNER_ABSENT && i->index == 0) {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001784 sprintf(i->name, "Television");
1785 i->type = V4L2_INPUT_TYPE_TUNER;
1786 i->tuner = 0;
1787 } else if (i->index == btv->svhs) {
1788 sprintf(i->name, "S-Video");
1789 } else {
1790 sprintf(i->name, "Composite%d", i->index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791 }
1792
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001793 if (i->index == btv->input) {
1794 __u32 dstatus = btread(BT848_DSTATUS);
1795 if (0 == (dstatus & BT848_DSTATUS_PRES))
1796 i->status |= V4L2_IN_ST_NO_SIGNAL;
1797 if (0 == (dstatus & BT848_DSTATUS_HLOC))
1798 i->status |= V4L2_IN_ST_NO_H_LOCK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799 }
1800
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001801 i->std = BTTV_NORMS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001803err:
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001804
1805 return rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001806}
Nickolay V. Shmyrev4b9b9362006-08-25 16:53:04 -03001807
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001808static int bttv_g_input(struct file *file, void *priv, unsigned int *i)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001809{
1810 struct bttv_fh *fh = priv;
1811 struct bttv *btv = fh->btv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001813 *i = btv->input;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001814
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001815 return 0;
1816}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001818static int bttv_s_input(struct file *file, void *priv, unsigned int i)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001819{
1820 struct bttv_fh *fh = priv;
1821 struct bttv *btv = fh->btv;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001822
Hans Verkuilf74f89cb2013-01-31 08:45:13 -03001823 if (i >= bttv_tvcards[btv->c.type].video_inputs)
1824 return -EINVAL;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001825
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001826 set_input(btv, i, btv->tvnorm);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001827 return 0;
1828}
1829
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001830static int bttv_s_tuner(struct file *file, void *priv,
Hans Verkuil2f73c7c2013-03-15 06:10:06 -03001831 const struct v4l2_tuner *t)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001832{
1833 struct bttv_fh *fh = priv;
1834 struct bttv *btv = fh->btv;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001835
Hans Verkuild9b67072013-02-06 11:43:07 -03001836 if (t->index)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001837 return -EINVAL;
1838
Hans Verkuil859f0272009-03-28 08:29:00 -03001839 bttv_call_all(btv, tuner, s_tuner, t);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001840
Hans Verkuil2f73c7c2013-03-15 06:10:06 -03001841 if (btv->audio_mode_gpio) {
1842 struct v4l2_tuner copy = *t;
1843
1844 btv->audio_mode_gpio(btv, &copy, 1);
1845 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001846 return 0;
1847}
1848
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001849static int bttv_g_frequency(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001850 struct v4l2_frequency *f)
1851{
1852 struct bttv_fh *fh = priv;
1853 struct bttv *btv = fh->btv;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001854
Hans Verkuild9b67072013-02-06 11:43:07 -03001855 if (f->tuner)
1856 return -EINVAL;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001857
Hans Verkuilb8e2a362013-02-10 09:24:14 -03001858 if (f->type == V4L2_TUNER_RADIO)
1859 radio_enable(btv);
Hans Verkuil76ea9922013-02-06 11:49:14 -03001860 f->frequency = f->type == V4L2_TUNER_RADIO ?
1861 btv->radio_freq : btv->tv_freq;
1862
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001863 return 0;
1864}
1865
Hans Verkuilb530a442013-03-19 04:09:26 -03001866static void bttv_set_frequency(struct bttv *btv, const struct v4l2_frequency *f)
Hans Verkuil76ea9922013-02-06 11:49:14 -03001867{
Hans Verkuilb530a442013-03-19 04:09:26 -03001868 struct v4l2_frequency new_freq = *f;
1869
Hans Verkuil76ea9922013-02-06 11:49:14 -03001870 bttv_call_all(btv, tuner, s_frequency, f);
1871 /* s_frequency may clamp the frequency, so get the actual
1872 frequency before assigning radio/tv_freq. */
Hans Verkuilb530a442013-03-19 04:09:26 -03001873 bttv_call_all(btv, tuner, g_frequency, &new_freq);
1874 if (new_freq.type == V4L2_TUNER_RADIO) {
Hans Verkuilb8e2a362013-02-10 09:24:14 -03001875 radio_enable(btv);
Hans Verkuilb530a442013-03-19 04:09:26 -03001876 btv->radio_freq = new_freq.frequency;
Ondrej Zary1b500372015-01-15 17:10:45 -03001877 if (btv->has_tea575x) {
1878 btv->tea.freq = btv->radio_freq;
1879 snd_tea575x_set_freq(&btv->tea);
1880 }
Hans Verkuil76ea9922013-02-06 11:49:14 -03001881 } else {
Hans Verkuilb530a442013-03-19 04:09:26 -03001882 btv->tv_freq = new_freq.frequency;
Hans Verkuil76ea9922013-02-06 11:49:14 -03001883 }
1884}
1885
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001886static int bttv_s_frequency(struct file *file, void *priv,
Hans Verkuilb530a442013-03-19 04:09:26 -03001887 const struct v4l2_frequency *f)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001888{
1889 struct bttv_fh *fh = priv;
1890 struct bttv *btv = fh->btv;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001891
Hans Verkuild9b67072013-02-06 11:43:07 -03001892 if (f->tuner)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001893 return -EINVAL;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001894
Hans Verkuil76ea9922013-02-06 11:49:14 -03001895 bttv_set_frequency(btv, f);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001896 return 0;
1897}
1898
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001899static int bttv_log_status(struct file *file, void *f)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001900{
Hans Verkuil01df5302013-02-06 12:40:28 -03001901 struct video_device *vdev = video_devdata(file);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001902 struct bttv_fh *fh = f;
1903 struct bttv *btv = fh->btv;
1904
Hans Verkuil01df5302013-02-06 12:40:28 -03001905 v4l2_ctrl_handler_log_status(vdev->ctrl_handler, btv->c.v4l2_dev.name);
Hans Verkuil859f0272009-03-28 08:29:00 -03001906 bttv_call_all(btv, core, log_status);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001907 return 0;
1908}
1909
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001910#ifdef CONFIG_VIDEO_ADV_DEBUG
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001911static int bttv_g_register(struct file *file, void *f,
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001912 struct v4l2_dbg_register *reg)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001913{
1914 struct bttv_fh *fh = f;
1915 struct bttv *btv = fh->btv;
1916
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001917 /* bt848 has a 12-bit register space */
1918 reg->reg &= 0xfff;
1919 reg->val = btread(reg->reg);
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001920 reg->size = 1;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001921
1922 return 0;
1923}
1924
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001925static int bttv_s_register(struct file *file, void *f,
Hans Verkuil977ba3b2013-03-24 08:28:46 -03001926 const struct v4l2_dbg_register *reg)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001927{
1928 struct bttv_fh *fh = f;
1929 struct bttv *btv = fh->btv;
1930
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001931 /* bt848 has a 12-bit register space */
Hans Verkuil977ba3b2013-03-24 08:28:46 -03001932 btwrite(reg->val, reg->reg & 0xfff);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001933
1934 return 0;
1935}
1936#endif
1937
Michael Schimeke5bd0262007-01-18 16:17:39 -03001938/* Given cropping boundaries b and the scaled width and height of a
1939 single field or frame, which must not exceed hardware limits, this
1940 function adjusts the cropping parameters c. */
1941static void
1942bttv_crop_adjust (struct bttv_crop * c,
1943 const struct v4l2_rect * b,
1944 __s32 width,
1945 __s32 height,
1946 enum v4l2_field field)
1947{
1948 __s32 frame_height = height << !V4L2_FIELD_HAS_BOTH(field);
1949 __s32 max_left;
1950 __s32 max_top;
1951
1952 if (width < c->min_scaled_width) {
1953 /* Max. hor. scale factor 16:1. */
1954 c->rect.width = width * 16;
1955 } else if (width > c->max_scaled_width) {
1956 /* Min. hor. scale factor 1:1. */
1957 c->rect.width = width;
1958
1959 max_left = b->left + b->width - width;
1960 max_left = min(max_left, (__s32) MAX_HDELAY);
1961 if (c->rect.left > max_left)
1962 c->rect.left = max_left;
1963 }
1964
1965 if (height < c->min_scaled_height) {
1966 /* Max. vert. scale factor 16:1, single fields 8:1. */
1967 c->rect.height = height * 16;
1968 } else if (frame_height > c->max_scaled_height) {
1969 /* Min. vert. scale factor 1:1.
1970 Top and height count field lines times two. */
1971 c->rect.height = (frame_height + 1) & ~1;
1972
1973 max_top = b->top + b->height - c->rect.height;
1974 if (c->rect.top > max_top)
1975 c->rect.top = max_top;
1976 }
1977
1978 bttv_crop_calc_limits(c);
1979}
1980
1981/* Returns an error if scaling to a frame or single field with the given
1982 width and height is not possible with the current cropping parameters
1983 and width aligned according to width_mask. If adjust_size is TRUE the
1984 function may adjust the width and/or height instead, rounding width
1985 to (width + width_bias) & width_mask. If adjust_crop is TRUE it may
1986 also adjust the current cropping parameters to get closer to the
1987 desired image size. */
1988static int
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03001989limit_scaled_size_lock (struct bttv_fh * fh,
Michael Schimeke5bd0262007-01-18 16:17:39 -03001990 __s32 * width,
1991 __s32 * height,
1992 enum v4l2_field field,
1993 unsigned int width_mask,
1994 unsigned int width_bias,
1995 int adjust_size,
1996 int adjust_crop)
1997{
1998 struct bttv *btv = fh->btv;
1999 const struct v4l2_rect *b;
2000 struct bttv_crop *c;
2001 __s32 min_width;
2002 __s32 min_height;
2003 __s32 max_width;
2004 __s32 max_height;
2005 int rc;
2006
2007 BUG_ON((int) width_mask >= 0 ||
2008 width_bias >= (unsigned int) -width_mask);
2009
2010 /* Make sure tvnorm, vbi_end and the current cropping parameters
2011 remain consistent until we're done. */
Michael Schimeke5bd0262007-01-18 16:17:39 -03002012
2013 b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
2014
2015 /* Do crop - use current, don't - use default parameters. */
2016 c = &btv->crop[!!fh->do_crop];
2017
2018 if (fh->do_crop
2019 && adjust_size
2020 && adjust_crop
2021 && !locked_btres(btv, VIDEO_RESOURCES)) {
2022 min_width = 48;
2023 min_height = 32;
2024
2025 /* We cannot scale up. When the scaled image is larger
2026 than crop.rect we adjust the crop.rect as required
2027 by the V4L2 spec, hence cropcap.bounds are our limit. */
Ricardo Ribaldaf90580c2013-11-26 05:31:42 -03002028 max_width = min_t(unsigned int, b->width, MAX_HACTIVE);
Michael Schimeke5bd0262007-01-18 16:17:39 -03002029 max_height = b->height;
2030
2031 /* We cannot capture the same line as video and VBI data.
2032 Note btv->vbi_end is really a minimum, see
2033 bttv_vbi_try_fmt(). */
2034 if (btv->vbi_end > b->top) {
2035 max_height -= btv->vbi_end - b->top;
2036 rc = -EBUSY;
2037 if (min_height > max_height)
2038 goto fail;
2039 }
2040 } else {
2041 rc = -EBUSY;
2042 if (btv->vbi_end > c->rect.top)
2043 goto fail;
2044
2045 min_width = c->min_scaled_width;
2046 min_height = c->min_scaled_height;
2047 max_width = c->max_scaled_width;
2048 max_height = c->max_scaled_height;
2049
2050 adjust_crop = 0;
2051 }
2052
2053 min_width = (min_width - width_mask - 1) & width_mask;
2054 max_width = max_width & width_mask;
2055
2056 /* Max. scale factor is 16:1 for frames, 8:1 for fields. */
2057 min_height = min_height;
2058 /* Min. scale factor is 1:1. */
2059 max_height >>= !V4L2_FIELD_HAS_BOTH(field);
2060
2061 if (adjust_size) {
2062 *width = clamp(*width, min_width, max_width);
2063 *height = clamp(*height, min_height, max_height);
2064
2065 /* Round after clamping to avoid overflow. */
2066 *width = (*width + width_bias) & width_mask;
2067
2068 if (adjust_crop) {
2069 bttv_crop_adjust(c, b, *width, *height, field);
2070
2071 if (btv->vbi_end > c->rect.top) {
2072 /* Move the crop window out of the way. */
2073 c->rect.top = btv->vbi_end;
2074 }
2075 }
2076 } else {
2077 rc = -EINVAL;
2078 if (*width < min_width ||
2079 *height < min_height ||
2080 *width > max_width ||
2081 *height > max_height ||
2082 0 != (*width & ~width_mask))
2083 goto fail;
2084 }
2085
2086 rc = 0; /* success */
2087
2088 fail:
Michael Schimeke5bd0262007-01-18 16:17:39 -03002089
2090 return rc;
2091}
2092
2093/* Returns an error if the given overlay window dimensions are not
2094 possible with the current cropping parameters. If adjust_size is
2095 TRUE the function may adjust the window width and/or height
2096 instead, however it always rounds the horizontal position and
2097 width as btcx_align() does. If adjust_crop is TRUE the function
2098 may also adjust the current cropping parameters to get closer
2099 to the desired window size. */
2100static int
Hans Verkuilc13eb702013-02-07 07:56:11 -03002101verify_window_lock(struct bttv_fh *fh, struct v4l2_window *win,
2102 int adjust_size, int adjust_crop)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103{
2104 enum v4l2_field field;
Michael Schimeke5bd0262007-01-18 16:17:39 -03002105 unsigned int width_mask;
2106 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107
Hans Verkuilc13eb702013-02-07 07:56:11 -03002108 if (win->w.width < 48)
2109 win->w.width = 48;
2110 if (win->w.height < 32)
2111 win->w.height = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002112 if (win->clipcount > 2048)
Hans Verkuilc13eb702013-02-07 07:56:11 -03002113 win->clipcount = 2048;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114
Hans Verkuilc13eb702013-02-07 07:56:11 -03002115 win->chromakey = 0;
2116 win->global_alpha = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117 field = win->field;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118
Hans Verkuilc13eb702013-02-07 07:56:11 -03002119 switch (field) {
2120 case V4L2_FIELD_TOP:
2121 case V4L2_FIELD_BOTTOM:
2122 case V4L2_FIELD_INTERLACED:
2123 break;
2124 default:
2125 field = V4L2_FIELD_ANY;
2126 break;
2127 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128 if (V4L2_FIELD_ANY == field) {
Michael Schimeke5bd0262007-01-18 16:17:39 -03002129 __s32 height2;
2130
2131 height2 = fh->btv->crop[!!fh->do_crop].rect.height >> 1;
2132 field = (win->w.height > height2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133 ? V4L2_FIELD_INTERLACED
2134 : V4L2_FIELD_TOP;
2135 }
Hans Verkuilc13eb702013-02-07 07:56:11 -03002136 win->field = field;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137
Michael Schimeke5bd0262007-01-18 16:17:39 -03002138 if (NULL == fh->ovfmt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139 return -EINVAL;
Hans Verkuilc13eb702013-02-07 07:56:11 -03002140 /* 4-byte alignment. */
Michael Schimeke5bd0262007-01-18 16:17:39 -03002141 width_mask = ~0;
2142 switch (fh->ovfmt->depth) {
2143 case 8:
2144 case 24:
2145 width_mask = ~3;
2146 break;
2147 case 16:
2148 width_mask = ~1;
2149 break;
2150 case 32:
2151 break;
2152 default:
2153 BUG();
2154 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155
Michael Schimeke5bd0262007-01-18 16:17:39 -03002156 win->w.width -= win->w.left & ~width_mask;
2157 win->w.left = (win->w.left - width_mask - 1) & width_mask;
2158
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002159 rc = limit_scaled_size_lock(fh, &win->w.width, &win->w.height,
Michael Schimeke5bd0262007-01-18 16:17:39 -03002160 field, width_mask,
2161 /* width_bias: round down */ 0,
2162 adjust_size, adjust_crop);
2163 if (0 != rc)
2164 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002165 return 0;
2166}
2167
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002168static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169 struct v4l2_window *win, int fixup)
2170{
2171 struct v4l2_clip *clips = NULL;
2172 int n,size,retval = 0;
2173
2174 if (NULL == fh->ovfmt)
2175 return -EINVAL;
2176 if (!(fh->ovfmt->flags & FORMAT_FLAGS_PACKED))
2177 return -EINVAL;
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002178 retval = verify_window_lock(fh, win,
Michael Schimeke5bd0262007-01-18 16:17:39 -03002179 /* adjust_size */ fixup,
2180 /* adjust_crop */ fixup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181 if (0 != retval)
2182 return retval;
2183
2184 /* copy clips -- luckily v4l1 + v4l2 are binary
2185 compatible here ...*/
2186 n = win->clipcount;
2187 size = sizeof(*clips)*(n+4);
2188 clips = kmalloc(size,GFP_KERNEL);
2189 if (NULL == clips)
2190 return -ENOMEM;
2191 if (n > 0) {
2192 if (copy_from_user(clips,win->clips,sizeof(struct v4l2_clip)*n)) {
2193 kfree(clips);
2194 return -EFAULT;
2195 }
2196 }
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002197
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198 /* clip against screen */
2199 if (NULL != btv->fbuf.base)
2200 n = btcx_screen_clips(btv->fbuf.fmt.width, btv->fbuf.fmt.height,
2201 &win->w, clips, n);
2202 btcx_sort_clips(clips,n);
2203
2204 /* 4-byte alignments */
2205 switch (fh->ovfmt->depth) {
2206 case 8:
2207 case 24:
2208 btcx_align(&win->w, clips, n, 3);
2209 break;
2210 case 16:
2211 btcx_align(&win->w, clips, n, 1);
2212 break;
2213 case 32:
2214 /* no alignment fixups needed */
2215 break;
2216 default:
2217 BUG();
2218 }
2219
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03002220 kfree(fh->ov.clips);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221 fh->ov.clips = clips;
2222 fh->ov.nclips = n;
2223
2224 fh->ov.w = win->w;
2225 fh->ov.field = win->field;
2226 fh->ov.setup_ok = 1;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002227
Linus Torvalds1da177e2005-04-16 15:20:36 -07002228 btv->init.ov.w.width = win->w.width;
2229 btv->init.ov.w.height = win->w.height;
2230 btv->init.ov.field = win->field;
2231
2232 /* update overlay if needed */
2233 retval = 0;
2234 if (check_btres(fh, RESOURCE_OVERLAY)) {
2235 struct bttv_buffer *new;
2236
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03002237 new = videobuf_sg_alloc(sizeof(*new));
Michael Schimeke5bd0262007-01-18 16:17:39 -03002238 new->crop = btv->crop[!!fh->do_crop].rect;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239 bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
2240 retval = bttv_switch_overlay(btv,fh,new);
2241 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242 return retval;
2243}
2244
2245/* ----------------------------------------------------------------------- */
2246
2247static struct videobuf_queue* bttv_queue(struct bttv_fh *fh)
2248{
2249 struct videobuf_queue* q = NULL;
2250
2251 switch (fh->type) {
2252 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2253 q = &fh->cap;
2254 break;
2255 case V4L2_BUF_TYPE_VBI_CAPTURE:
2256 q = &fh->vbi;
2257 break;
2258 default:
2259 BUG();
2260 }
2261 return q;
2262}
2263
2264static int bttv_resource(struct bttv_fh *fh)
2265{
2266 int res = 0;
2267
2268 switch (fh->type) {
2269 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Michael Schimeke5bd0262007-01-18 16:17:39 -03002270 res = RESOURCE_VIDEO_STREAM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002271 break;
2272 case V4L2_BUF_TYPE_VBI_CAPTURE:
2273 res = RESOURCE_VBI;
2274 break;
2275 default:
2276 BUG();
2277 }
2278 return res;
2279}
2280
2281static int bttv_switch_type(struct bttv_fh *fh, enum v4l2_buf_type type)
2282{
2283 struct videobuf_queue *q = bttv_queue(fh);
2284 int res = bttv_resource(fh);
2285
2286 if (check_btres(fh,res))
2287 return -EBUSY;
2288 if (videobuf_queue_is_busy(q))
2289 return -EBUSY;
2290 fh->type = type;
2291 return 0;
2292}
2293
Michael H. Schimekc87c9482005-12-01 00:51:33 -08002294static void
2295pix_format_set_size (struct v4l2_pix_format * f,
2296 const struct bttv_format * fmt,
2297 unsigned int width,
2298 unsigned int height)
2299{
2300 f->width = width;
2301 f->height = height;
2302
2303 if (fmt->flags & FORMAT_FLAGS_PLANAR) {
2304 f->bytesperline = width; /* Y plane */
2305 f->sizeimage = (width * height * fmt->depth) >> 3;
2306 } else {
2307 f->bytesperline = (width * fmt->depth) >> 3;
2308 f->sizeimage = height * f->bytesperline;
2309 }
2310}
2311
Hans Verkuil78b526a2008-05-28 12:16:41 -03002312static int bttv_g_fmt_vid_cap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002313 struct v4l2_format *f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002315 struct bttv_fh *fh = priv;
2316
2317 pix_format_set_size(&f->fmt.pix, fh->fmt,
2318 fh->width, fh->height);
2319 f->fmt.pix.field = fh->cap.field;
2320 f->fmt.pix.pixelformat = fh->fmt->fourcc;
Hans Verkuilf5864892013-02-06 11:58:59 -03002321 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002322
2323 return 0;
2324}
2325
Hans Verkuil78b526a2008-05-28 12:16:41 -03002326static int bttv_g_fmt_vid_overlay(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002327 struct v4l2_format *f)
2328{
2329 struct bttv_fh *fh = priv;
2330
2331 f->fmt.win.w = fh->ov.w;
2332 f->fmt.win.field = fh->ov.field;
2333
2334 return 0;
2335}
2336
Hans Verkuil78b526a2008-05-28 12:16:41 -03002337static int bttv_try_fmt_vid_cap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002338 struct v4l2_format *f)
2339{
2340 const struct bttv_format *fmt;
2341 struct bttv_fh *fh = priv;
2342 struct bttv *btv = fh->btv;
2343 enum v4l2_field field;
2344 __s32 width, height;
Hans Verkuilee70e3d2013-02-06 12:03:30 -03002345 __s32 height2;
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002346 int rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002347
2348 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
2349 if (NULL == fmt)
2350 return -EINVAL;
2351
2352 field = f->fmt.pix.field;
2353
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002354 switch (field) {
2355 case V4L2_FIELD_TOP:
2356 case V4L2_FIELD_BOTTOM:
2357 case V4L2_FIELD_ALTERNATE:
2358 case V4L2_FIELD_INTERLACED:
2359 break;
Hans Verkuilee70e3d2013-02-06 12:03:30 -03002360 case V4L2_FIELD_SEQ_BT:
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002361 case V4L2_FIELD_SEQ_TB:
Hans Verkuilee70e3d2013-02-06 12:03:30 -03002362 if (!(fmt->flags & FORMAT_FLAGS_PLANAR)) {
2363 field = V4L2_FIELD_SEQ_TB;
2364 break;
2365 }
2366 /* fall through */
2367 default: /* FIELD_ANY case */
2368 height2 = btv->crop[!!fh->do_crop].rect.height >> 1;
2369 field = (f->fmt.pix.height > height2)
2370 ? V4L2_FIELD_INTERLACED
2371 : V4L2_FIELD_BOTTOM;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002372 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002374
2375 width = f->fmt.pix.width;
2376 height = f->fmt.pix.height;
2377
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002378 rc = limit_scaled_size_lock(fh, &width, &height, field,
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002379 /* width_mask: 4 pixels */ ~3,
2380 /* width_bias: nearest */ 2,
2381 /* adjust_size */ 1,
2382 /* adjust_crop */ 0);
2383 if (0 != rc)
2384 return rc;
2385
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002386 /* update data for the application */
2387 f->fmt.pix.field = field;
2388 pix_format_set_size(&f->fmt.pix, fmt, width, height);
Hans Verkuilf5864892013-02-06 11:58:59 -03002389 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002390
2391 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002392}
2393
Hans Verkuil78b526a2008-05-28 12:16:41 -03002394static int bttv_try_fmt_vid_overlay(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002395 struct v4l2_format *f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002397 struct bttv_fh *fh = priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398
Hans Verkuilc13eb702013-02-07 07:56:11 -03002399 verify_window_lock(fh, &f->fmt.win,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002400 /* adjust_size */ 1,
2401 /* adjust_crop */ 0);
Hans Verkuilc13eb702013-02-07 07:56:11 -03002402 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403}
2404
Hans Verkuil78b526a2008-05-28 12:16:41 -03002405static int bttv_s_fmt_vid_cap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002406 struct v4l2_format *f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407{
2408 int retval;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002409 const struct bttv_format *fmt;
2410 struct bttv_fh *fh = priv;
2411 struct bttv *btv = fh->btv;
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002412 __s32 width, height;
2413 enum v4l2_field field;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002415 retval = bttv_switch_type(fh, f->type);
2416 if (0 != retval)
2417 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418
Hans Verkuil78b526a2008-05-28 12:16:41 -03002419 retval = bttv_try_fmt_vid_cap(file, priv, f);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002420 if (0 != retval)
2421 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002423 width = f->fmt.pix.width;
2424 height = f->fmt.pix.height;
2425 field = f->fmt.pix.field;
2426
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002427 retval = limit_scaled_size_lock(fh, &width, &height, f->fmt.pix.field,
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002428 /* width_mask: 4 pixels */ ~3,
2429 /* width_bias: nearest */ 2,
2430 /* adjust_size */ 1,
2431 /* adjust_crop */ 1);
2432 if (0 != retval)
2433 return retval;
2434
2435 f->fmt.pix.field = field;
2436
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002437 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002439 /* update our state informations */
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002440 fh->fmt = fmt;
2441 fh->cap.field = f->fmt.pix.field;
2442 fh->cap.last = V4L2_FIELD_NONE;
2443 fh->width = f->fmt.pix.width;
2444 fh->height = f->fmt.pix.height;
2445 btv->init.fmt = fmt;
2446 btv->init.width = f->fmt.pix.width;
2447 btv->init.height = f->fmt.pix.height;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002448
2449 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450}
2451
Hans Verkuil78b526a2008-05-28 12:16:41 -03002452static int bttv_s_fmt_vid_overlay(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002453 struct v4l2_format *f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002455 struct bttv_fh *fh = priv;
2456 struct bttv *btv = fh->btv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002458 if (no_overlay > 0) {
Joe Perches8af443e2011-08-21 19:56:48 -03002459 pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002460 return -EINVAL;
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002461 }
Michael Krufky5e453dc2006-01-09 15:32:31 -02002462
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002463 return setup_window_lock(fh, btv, &f->fmt.win, 1);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002464}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002466static int bttv_querycap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002467 struct v4l2_capability *cap)
2468{
Hans Verkuil78dea1a2012-09-09 09:03:29 -03002469 struct video_device *vdev = video_devdata(file);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002470 struct bttv_fh *fh = priv;
2471 struct bttv *btv = fh->btv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002473 if (0 == v4l2)
2474 return -EINVAL;
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07002475
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002476 strlcpy(cap->driver, "bttv", sizeof(cap->driver));
Hans Verkuil23fb4c52015-03-09 13:34:02 -03002477 strlcpy(cap->card, btv->video_dev.name, sizeof(cap->card));
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002478 snprintf(cap->bus_info, sizeof(cap->bus_info),
2479 "PCI:%s", pci_name(btv->c.pci));
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002480 cap->capabilities =
2481 V4L2_CAP_VIDEO_CAPTURE |
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002482 V4L2_CAP_READWRITE |
Hans Verkuil78dea1a2012-09-09 09:03:29 -03002483 V4L2_CAP_STREAMING |
2484 V4L2_CAP_DEVICE_CAPS;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002485 if (no_overlay <= 0)
2486 cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
Hans Verkuil23fb4c52015-03-09 13:34:02 -03002487 if (video_is_registered(&btv->vbi_dev))
Hans Verkuil78dea1a2012-09-09 09:03:29 -03002488 cap->capabilities |= V4L2_CAP_VBI_CAPTURE;
Hans Verkuil23fb4c52015-03-09 13:34:02 -03002489 if (video_is_registered(&btv->radio_dev))
Hans Verkuil78dea1a2012-09-09 09:03:29 -03002490 cap->capabilities |= V4L2_CAP_RADIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002491
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002492 /*
2493 * No need to lock here: those vars are initialized during board
2494 * probe and remains untouched during the rest of the driver lifecycle
2495 */
2496 if (btv->has_saa6588)
2497 cap->capabilities |= V4L2_CAP_RDS_CAPTURE;
Trent Piephoabb03622009-01-28 21:32:59 -03002498 if (btv->tuner_type != TUNER_ABSENT)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002499 cap->capabilities |= V4L2_CAP_TUNER;
Hans Verkuil78dea1a2012-09-09 09:03:29 -03002500 if (vdev->vfl_type == VFL_TYPE_GRABBER)
2501 cap->device_caps = cap->capabilities &
2502 (V4L2_CAP_VIDEO_CAPTURE |
2503 V4L2_CAP_READWRITE |
2504 V4L2_CAP_STREAMING |
2505 V4L2_CAP_VIDEO_OVERLAY |
2506 V4L2_CAP_TUNER);
2507 else if (vdev->vfl_type == VFL_TYPE_VBI)
2508 cap->device_caps = cap->capabilities &
2509 (V4L2_CAP_VBI_CAPTURE |
2510 V4L2_CAP_READWRITE |
2511 V4L2_CAP_STREAMING |
2512 V4L2_CAP_TUNER);
2513 else {
2514 cap->device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER;
2515 if (btv->has_saa6588)
2516 cap->device_caps |= V4L2_CAP_READWRITE |
2517 V4L2_CAP_RDS_CAPTURE;
Ondrej Zary35655bf2015-01-16 06:58:32 -03002518 if (btv->has_tea575x)
2519 cap->device_caps |= V4L2_CAP_HW_FREQ_SEEK;
Hans Verkuil78dea1a2012-09-09 09:03:29 -03002520 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002521 return 0;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002522}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002523
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002524static int bttv_enum_fmt_cap_ovr(struct v4l2_fmtdesc *f)
2525{
2526 int index = -1, i;
2527
2528 for (i = 0; i < FORMATS; i++) {
2529 if (formats[i].fourcc != -1)
2530 index++;
2531 if ((unsigned int)index == f->index)
2532 break;
2533 }
2534 if (FORMATS == i)
2535 return -EINVAL;
2536
2537 f->pixelformat = formats[i].fourcc;
2538 strlcpy(f->description, formats[i].name, sizeof(f->description));
2539
2540 return i;
2541}
2542
Hans Verkuil78b526a2008-05-28 12:16:41 -03002543static int bttv_enum_fmt_vid_cap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002544 struct v4l2_fmtdesc *f)
2545{
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002546 int rc = bttv_enum_fmt_cap_ovr(f);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002547
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002548 if (rc < 0)
2549 return rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002550
2551 return 0;
2552}
2553
Hans Verkuil78b526a2008-05-28 12:16:41 -03002554static int bttv_enum_fmt_vid_overlay(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002555 struct v4l2_fmtdesc *f)
2556{
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002557 int rc;
2558
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002559 if (no_overlay > 0) {
Joe Perches8af443e2011-08-21 19:56:48 -03002560 pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002561 return -EINVAL;
2562 }
2563
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002564 rc = bttv_enum_fmt_cap_ovr(f);
2565
2566 if (rc < 0)
2567 return rc;
2568
2569 if (!(formats[rc].flags & FORMAT_FLAGS_PACKED))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002570 return -EINVAL;
2571
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002572 return 0;
2573}
2574
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002575static int bttv_g_fbuf(struct file *file, void *f,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002576 struct v4l2_framebuffer *fb)
2577{
2578 struct bttv_fh *fh = f;
2579 struct bttv *btv = fh->btv;
2580
2581 *fb = btv->fbuf;
2582 fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
Hans Verkuila12fd702013-02-06 12:00:03 -03002583 fb->flags = V4L2_FBUF_FLAG_PRIMARY;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002584 if (fh->ovfmt)
2585 fb->fmt.pixelformat = fh->ovfmt->fourcc;
2586 return 0;
2587}
2588
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002589static int bttv_overlay(struct file *file, void *f, unsigned int on)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002590{
2591 struct bttv_fh *fh = f;
2592 struct bttv *btv = fh->btv;
2593 struct bttv_buffer *new;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002594 int retval = 0;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002595
2596 if (on) {
2597 /* verify args */
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002598 if (unlikely(!btv->fbuf.base)) {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002599 return -EINVAL;
2600 }
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002601 if (unlikely(!fh->ov.setup_ok)) {
Joe Perches8af443e2011-08-21 19:56:48 -03002602 dprintk("%d: overlay: !setup_ok\n", btv->c.nr);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002603 retval = -EINVAL;
2604 }
2605 if (retval)
2606 return retval;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002607 }
2608
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002609 if (!check_alloc_btres_lock(btv, fh, RESOURCE_OVERLAY))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002610 return -EBUSY;
2611
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002612 if (on) {
2613 fh->ov.tvnorm = btv->tvnorm;
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03002614 new = videobuf_sg_alloc(sizeof(*new));
Robert Fitzsimons7c018802008-02-13 16:38:11 -03002615 new->crop = btv->crop[!!fh->do_crop].rect;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002616 bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
2617 } else {
2618 new = NULL;
2619 }
2620
2621 /* switch over */
2622 retval = bttv_switch_overlay(btv, fh, new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002623 return retval;
2624}
2625
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002626static int bttv_s_fbuf(struct file *file, void *f,
Hans Verkuile6eb28c2012-09-04 10:26:45 -03002627 const struct v4l2_framebuffer *fb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002628{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002629 struct bttv_fh *fh = f;
2630 struct bttv *btv = fh->btv;
2631 const struct bttv_format *fmt;
2632 int retval;
2633
2634 if (!capable(CAP_SYS_ADMIN) &&
2635 !capable(CAP_SYS_RAWIO))
2636 return -EPERM;
2637
2638 /* check args */
2639 fmt = format_by_fourcc(fb->fmt.pixelformat);
2640 if (NULL == fmt)
2641 return -EINVAL;
2642 if (0 == (fmt->flags & FORMAT_FLAGS_PACKED))
2643 return -EINVAL;
2644
2645 retval = -EINVAL;
2646 if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
2647 __s32 width = fb->fmt.width;
2648 __s32 height = fb->fmt.height;
2649
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002650 retval = limit_scaled_size_lock(fh, &width, &height,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002651 V4L2_FIELD_INTERLACED,
2652 /* width_mask */ ~3,
2653 /* width_bias */ 2,
2654 /* adjust_size */ 0,
2655 /* adjust_crop */ 0);
2656 if (0 != retval)
2657 return retval;
2658 }
2659
2660 /* ok, accept it */
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002661 btv->fbuf.base = fb->base;
2662 btv->fbuf.fmt.width = fb->fmt.width;
2663 btv->fbuf.fmt.height = fb->fmt.height;
2664 if (0 != fb->fmt.bytesperline)
2665 btv->fbuf.fmt.bytesperline = fb->fmt.bytesperline;
2666 else
2667 btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fmt->depth/8;
2668
2669 retval = 0;
2670 fh->ovfmt = fmt;
2671 btv->init.ovfmt = fmt;
2672 if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
2673 fh->ov.w.left = 0;
2674 fh->ov.w.top = 0;
2675 fh->ov.w.width = fb->fmt.width;
2676 fh->ov.w.height = fb->fmt.height;
2677 btv->init.ov.w.width = fb->fmt.width;
2678 btv->init.ov.w.height = fb->fmt.height;
Mauro Carvalho Chehab57eedc32015-04-29 09:41:34 -03002679
2680 kfree(fh->ov.clips);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002681 fh->ov.clips = NULL;
2682 fh->ov.nclips = 0;
2683
2684 if (check_btres(fh, RESOURCE_OVERLAY)) {
2685 struct bttv_buffer *new;
2686
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03002687 new = videobuf_sg_alloc(sizeof(*new));
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002688 new->crop = btv->crop[!!fh->do_crop].rect;
2689 bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
2690 retval = bttv_switch_overlay(btv, fh, new);
2691 }
2692 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002693 return retval;
2694}
2695
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002696static int bttv_reqbufs(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002697 struct v4l2_requestbuffers *p)
2698{
2699 struct bttv_fh *fh = priv;
2700 return videobuf_reqbufs(bttv_queue(fh), p);
2701}
2702
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002703static int bttv_querybuf(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002704 struct v4l2_buffer *b)
2705{
2706 struct bttv_fh *fh = priv;
2707 return videobuf_querybuf(bttv_queue(fh), b);
2708}
2709
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002710static int bttv_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002711{
2712 struct bttv_fh *fh = priv;
2713 struct bttv *btv = fh->btv;
2714 int res = bttv_resource(fh);
2715
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002716 if (!check_alloc_btres_lock(btv, fh, res))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002717 return -EBUSY;
2718
2719 return videobuf_qbuf(bttv_queue(fh), b);
2720}
2721
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002722static int bttv_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002723{
2724 struct bttv_fh *fh = priv;
2725 return videobuf_dqbuf(bttv_queue(fh), b,
2726 file->f_flags & O_NONBLOCK);
2727}
2728
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002729static int bttv_streamon(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002730 enum v4l2_buf_type type)
2731{
2732 struct bttv_fh *fh = priv;
2733 struct bttv *btv = fh->btv;
2734 int res = bttv_resource(fh);
2735
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002736 if (!check_alloc_btres_lock(btv, fh, res))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002737 return -EBUSY;
2738 return videobuf_streamon(bttv_queue(fh));
2739}
2740
2741
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002742static int bttv_streamoff(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002743 enum v4l2_buf_type type)
2744{
2745 struct bttv_fh *fh = priv;
2746 struct bttv *btv = fh->btv;
2747 int retval;
2748 int res = bttv_resource(fh);
2749
2750
2751 retval = videobuf_streamoff(bttv_queue(fh));
2752 if (retval < 0)
2753 return retval;
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002754 free_btres_lock(btv, fh, res);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002755 return 0;
2756}
2757
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002758static int bttv_g_parm(struct file *file, void *f,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002759 struct v4l2_streamparm *parm)
2760{
2761 struct bttv_fh *fh = f;
2762 struct bttv *btv = fh->btv;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002763
Hans Verkuila652ef62012-09-09 10:27:57 -03002764 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
2765 return -EINVAL;
2766 parm->parm.capture.readbuffers = gbuffers;
Trent Piepho51f0b8d52009-03-04 01:21:02 -03002767 v4l2_video_std_frame_period(bttv_tvnorms[btv->tvnorm].v4l2_id,
2768 &parm->parm.capture.timeperframe);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002769
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002770 return 0;
2771}
2772
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002773static int bttv_g_tuner(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002774 struct v4l2_tuner *t)
2775{
2776 struct bttv_fh *fh = priv;
2777 struct bttv *btv = fh->btv;
2778
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002779 if (0 != t->index)
2780 return -EINVAL;
2781
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002782 t->rxsubchans = V4L2_TUNER_SUB_MONO;
Hans Verkuil3d4b8032013-02-06 12:44:07 -03002783 t->capability = V4L2_TUNER_CAP_NORM;
Hans Verkuil859f0272009-03-28 08:29:00 -03002784 bttv_call_all(btv, tuner, g_tuner, t);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002785 strcpy(t->name, "Television");
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002786 t->type = V4L2_TUNER_ANALOG_TV;
2787 if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)
2788 t->signal = 0xffff;
2789
2790 if (btv->audio_mode_gpio)
2791 btv->audio_mode_gpio(btv, t, 0);
2792
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002793 return 0;
2794}
2795
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002796static int bttv_cropcap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002797 struct v4l2_cropcap *cap)
2798{
2799 struct bttv_fh *fh = priv;
2800 struct bttv *btv = fh->btv;
2801
2802 if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
2803 cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
2804 return -EINVAL;
2805
2806 *cap = bttv_tvnorms[btv->tvnorm].cropcap;
2807
2808 return 0;
2809}
2810
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002811static int bttv_g_crop(struct file *file, void *f, struct v4l2_crop *crop)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002812{
2813 struct bttv_fh *fh = f;
2814 struct bttv *btv = fh->btv;
2815
2816 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
2817 crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
2818 return -EINVAL;
2819
2820 /* No fh->do_crop = 1; because btv->crop[1] may be
2821 inconsistent with fh->width or fh->height and apps
2822 do not expect a change here. */
2823
2824 crop->c = btv->crop[!!fh->do_crop].rect;
2825
2826 return 0;
2827}
2828
Hans Verkuil4f996592012-09-05 05:10:48 -03002829static int bttv_s_crop(struct file *file, void *f, const struct v4l2_crop *crop)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002830{
2831 struct bttv_fh *fh = f;
2832 struct bttv *btv = fh->btv;
2833 const struct v4l2_rect *b;
2834 int retval;
2835 struct bttv_crop c;
2836 __s32 b_left;
2837 __s32 b_top;
2838 __s32 b_right;
2839 __s32 b_bottom;
2840
2841 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
2842 crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
2843 return -EINVAL;
2844
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002845 /* Make sure tvnorm, vbi_end and the current cropping
2846 parameters remain consistent until we're done. Note
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002847 read() may change vbi_end in check_alloc_btres_lock(). */
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002848 retval = -EBUSY;
2849
2850 if (locked_btres(fh->btv, VIDEO_RESOURCES)) {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002851 return retval;
2852 }
2853
2854 b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
2855
2856 b_left = b->left;
2857 b_right = b_left + b->width;
2858 b_bottom = b->top + b->height;
2859
2860 b_top = max(b->top, btv->vbi_end);
2861 if (b_top + 32 >= b_bottom) {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002862 return retval;
2863 }
2864
2865 /* Min. scaled size 48 x 32. */
Hans Verkuil4f996592012-09-05 05:10:48 -03002866 c.rect.left = clamp_t(s32, crop->c.left, b_left, b_right - 48);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002867 c.rect.left = min(c.rect.left, (__s32) MAX_HDELAY);
2868
Hans Verkuil4f996592012-09-05 05:10:48 -03002869 c.rect.width = clamp_t(s32, crop->c.width,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002870 48, b_right - c.rect.left);
2871
Hans Verkuil4f996592012-09-05 05:10:48 -03002872 c.rect.top = clamp_t(s32, crop->c.top, b_top, b_bottom - 32);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002873 /* Top and height must be a multiple of two. */
2874 c.rect.top = (c.rect.top + 1) & ~1;
2875
Hans Verkuil4f996592012-09-05 05:10:48 -03002876 c.rect.height = clamp_t(s32, crop->c.height,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002877 32, b_bottom - c.rect.top);
2878 c.rect.height = (c.rect.height + 1) & ~1;
2879
2880 bttv_crop_calc_limits(&c);
2881
2882 btv->crop[1] = c;
2883
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002884 fh->do_crop = 1;
2885
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002886 if (fh->width < c.min_scaled_width) {
2887 fh->width = c.min_scaled_width;
2888 btv->init.width = c.min_scaled_width;
2889 } else if (fh->width > c.max_scaled_width) {
2890 fh->width = c.max_scaled_width;
2891 btv->init.width = c.max_scaled_width;
2892 }
2893
2894 if (fh->height < c.min_scaled_height) {
2895 fh->height = c.min_scaled_height;
2896 btv->init.height = c.min_scaled_height;
2897 } else if (fh->height > c.max_scaled_height) {
2898 fh->height = c.max_scaled_height;
2899 btv->init.height = c.max_scaled_height;
2900 }
2901
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002902 return 0;
2903}
2904
Linus Torvalds1da177e2005-04-16 15:20:36 -07002905static ssize_t bttv_read(struct file *file, char __user *data,
2906 size_t count, loff_t *ppos)
2907{
2908 struct bttv_fh *fh = file->private_data;
2909 int retval = 0;
2910
2911 if (fh->btv->errors)
2912 bttv_reinit_bt848(fh->btv);
Joe Perches8af443e2011-08-21 19:56:48 -03002913 dprintk("%d: read count=%d type=%s\n",
2914 fh->btv->c.nr, (int)count, v4l2_type_names[fh->type]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002915
2916 switch (fh->type) {
2917 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002918 if (!check_alloc_btres_lock(fh->btv, fh, RESOURCE_VIDEO_READ)) {
Michael Schimeke5bd0262007-01-18 16:17:39 -03002919 /* VIDEO_READ in use by another fh,
2920 or VIDEO_STREAM by any fh. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002921 return -EBUSY;
Michael Schimeke5bd0262007-01-18 16:17:39 -03002922 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002923 retval = videobuf_read_one(&fh->cap, data, count, ppos,
2924 file->f_flags & O_NONBLOCK);
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002925 free_btres_lock(fh->btv, fh, RESOURCE_VIDEO_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002926 break;
2927 case V4L2_BUF_TYPE_VBI_CAPTURE:
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002928 if (!check_alloc_btres_lock(fh->btv,fh,RESOURCE_VBI))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002929 return -EBUSY;
2930 retval = videobuf_read_stream(&fh->vbi, data, count, ppos, 1,
2931 file->f_flags & O_NONBLOCK);
2932 break;
2933 default:
2934 BUG();
2935 }
2936 return retval;
2937}
2938
2939static unsigned int bttv_poll(struct file *file, poll_table *wait)
2940{
2941 struct bttv_fh *fh = file->private_data;
2942 struct bttv_buffer *buf;
2943 enum v4l2_field field;
Hans Verkuilae50f0f2013-02-06 12:42:13 -03002944 unsigned int rc = 0;
2945 unsigned long req_events = poll_requested_events(wait);
2946
2947 if (v4l2_event_pending(&fh->fh))
2948 rc = POLLPRI;
2949 else if (req_events & POLLPRI)
2950 poll_wait(file, &fh->fh.wait, wait);
2951
2952 if (!(req_events & (POLLIN | POLLRDNORM)))
2953 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002954
2955 if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002956 if (!check_alloc_btres_lock(fh->btv,fh,RESOURCE_VBI))
Hans Verkuilae50f0f2013-02-06 12:42:13 -03002957 return rc | POLLERR;
2958 return rc | videobuf_poll_stream(file, &fh->vbi, wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002959 }
2960
Michael Schimeke5bd0262007-01-18 16:17:39 -03002961 if (check_btres(fh,RESOURCE_VIDEO_STREAM)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002962 /* streaming capture */
2963 if (list_empty(&fh->cap.stream))
Hans Verkuilae50f0f2013-02-06 12:42:13 -03002964 return rc | POLLERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002965 buf = list_entry(fh->cap.stream.next,struct bttv_buffer,vb.stream);
2966 } else {
2967 /* read() capture */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002968 if (NULL == fh->cap.read_buf) {
2969 /* need to capture a new frame */
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03002970 if (locked_btres(fh->btv,RESOURCE_VIDEO_STREAM))
Hans Verkuilae50f0f2013-02-06 12:42:13 -03002971 return rc | POLLERR;
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03002972 fh->cap.read_buf = videobuf_sg_alloc(fh->cap.msize);
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03002973 if (NULL == fh->cap.read_buf)
Hans Verkuilae50f0f2013-02-06 12:42:13 -03002974 return rc | POLLERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002975 fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR;
2976 field = videobuf_next_field(&fh->cap);
2977 if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,field)) {
Nickolay V. Shmyrev50ab5ed2005-12-01 00:51:32 -08002978 kfree (fh->cap.read_buf);
2979 fh->cap.read_buf = NULL;
Hans Verkuilae50f0f2013-02-06 12:42:13 -03002980 return rc | POLLERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002981 }
2982 fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf);
2983 fh->cap.read_off = 0;
2984 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002985 buf = (struct bttv_buffer*)fh->cap.read_buf;
2986 }
2987
2988 poll_wait(file, &buf->vb.done, wait);
Brandon Philips0fc06862007-11-06 20:02:36 -03002989 if (buf->vb.state == VIDEOBUF_DONE ||
2990 buf->vb.state == VIDEOBUF_ERROR)
Hans Verkuilae50f0f2013-02-06 12:42:13 -03002991 rc = rc | POLLIN|POLLRDNORM;
Figo.zhang9fd64182009-06-16 13:31:29 -03002992 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002993}
2994
Hans Verkuilbec43662008-12-30 06:58:20 -03002995static int bttv_open(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002996{
Laurent Pinchart50462eb2009-12-10 11:47:13 -02002997 struct video_device *vdev = video_devdata(file);
Trent Piepho4b10d3b2009-01-28 21:32:59 -03002998 struct bttv *btv = video_drvdata(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999 struct bttv_fh *fh;
3000 enum v4l2_buf_type type = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003001
Joe Perches8af443e2011-08-21 19:56:48 -03003002 dprintk("open dev=%s\n", video_device_node_name(vdev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003003
Laurent Pinchart327ae592009-11-27 13:57:55 -03003004 if (vdev->vfl_type == VFL_TYPE_GRABBER) {
Trent Piepho4b10d3b2009-01-28 21:32:59 -03003005 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Laurent Pinchart327ae592009-11-27 13:57:55 -03003006 } else if (vdev->vfl_type == VFL_TYPE_VBI) {
Trent Piepho4b10d3b2009-01-28 21:32:59 -03003007 type = V4L2_BUF_TYPE_VBI_CAPTURE;
3008 } else {
3009 WARN_ON(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003010 return -ENODEV;
Hans Verkuild56dc612008-07-30 08:43:36 -03003011 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003012
Joe Perches8af443e2011-08-21 19:56:48 -03003013 dprintk("%d: open called (type=%s)\n",
3014 btv->c.nr, v4l2_type_names[type]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003015
3016 /* allocate per filehandle data */
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003017 fh = kmalloc(sizeof(*fh), GFP_KERNEL);
3018 if (unlikely(!fh))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003019 return -ENOMEM;
Hans Verkuil01df5302013-02-06 12:40:28 -03003020 btv->users++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003021 file->private_data = fh;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003022
Linus Torvalds1da177e2005-04-16 15:20:36 -07003023 *fh = btv->init;
Hans Verkuilae50f0f2013-02-06 12:42:13 -03003024 v4l2_fh_init(&fh->fh, vdev);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003025
Linus Torvalds1da177e2005-04-16 15:20:36 -07003026 fh->type = type;
3027 fh->ov.setup_ok = 0;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003028
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03003029 videobuf_queue_sg_init(&fh->cap, &bttv_video_qops,
3030 &btv->c.pci->dev, &btv->s_lock,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003031 V4L2_BUF_TYPE_VIDEO_CAPTURE,
3032 V4L2_FIELD_INTERLACED,
3033 sizeof(struct bttv_buffer),
Mauro Carvalho Chehab587f0d52010-12-15 18:45:42 -03003034 fh, &btv->lock);
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03003035 videobuf_queue_sg_init(&fh->vbi, &bttv_vbi_qops,
3036 &btv->c.pci->dev, &btv->s_lock,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037 V4L2_BUF_TYPE_VBI_CAPTURE,
3038 V4L2_FIELD_SEQ_TB,
3039 sizeof(struct bttv_buffer),
Mauro Carvalho Chehab587f0d52010-12-15 18:45:42 -03003040 fh, &btv->lock);
Nickolay V. Shmyrev302f61a2007-10-26 10:53:21 -03003041 set_tvnorm(btv,btv->tvnorm);
Mauro Carvalho Chehabb46a9c82008-08-05 10:12:35 -03003042 set_input(btv, btv->input, btv->tvnorm);
Frank Schaefer0757f5c2013-03-21 13:51:20 -03003043 audio_mute(btv, btv->mute);
Michael Schimeke5bd0262007-01-18 16:17:39 -03003044
3045 /* The V4L2 spec requires one global set of cropping parameters
3046 which only change on request. These are stored in btv->crop[1].
3047 However for compatibility with V4L apps and cropping unaware
3048 V4L2 apps we now reset the cropping parameters as seen through
3049 this fh, which is to say VIDIOC_G_CROP and scaling limit checks
3050 will use btv->crop[0], the default cropping parameters for the
3051 current video standard, and VIDIOC_S_FMT will not implicitely
3052 change the cropping parameters until VIDIOC_S_CROP has been
3053 called. */
3054 fh->do_crop = !reset_crop; /* module parameter */
3055
3056 /* Likewise there should be one global set of VBI capture
3057 parameters, but for compatibility with V4L apps and earlier
3058 driver versions each fh has its own parameters. */
3059 bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm);
3060
Linus Torvalds1da177e2005-04-16 15:20:36 -07003061 bttv_field_count(btv);
Hans Verkuilae50f0f2013-02-06 12:42:13 -03003062 v4l2_fh_add(&fh->fh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003063 return 0;
3064}
3065
Hans Verkuilbec43662008-12-30 06:58:20 -03003066static int bttv_release(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003067{
3068 struct bttv_fh *fh = file->private_data;
3069 struct bttv *btv = fh->btv;
3070
3071 /* turn off overlay */
3072 if (check_btres(fh, RESOURCE_OVERLAY))
3073 bttv_switch_overlay(btv,fh,NULL);
3074
3075 /* stop video capture */
Michael Schimeke5bd0262007-01-18 16:17:39 -03003076 if (check_btres(fh, RESOURCE_VIDEO_STREAM)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003077 videobuf_streamoff(&fh->cap);
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003078 free_btres_lock(btv,fh,RESOURCE_VIDEO_STREAM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003079 }
3080 if (fh->cap.read_buf) {
3081 buffer_release(&fh->cap,fh->cap.read_buf);
3082 kfree(fh->cap.read_buf);
3083 }
Michael Schimeke5bd0262007-01-18 16:17:39 -03003084 if (check_btres(fh, RESOURCE_VIDEO_READ)) {
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003085 free_btres_lock(btv, fh, RESOURCE_VIDEO_READ);
Michael Schimeke5bd0262007-01-18 16:17:39 -03003086 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003087
3088 /* stop vbi capture */
3089 if (check_btres(fh, RESOURCE_VBI)) {
Brandon Philips053fcb62007-11-13 20:11:26 -03003090 videobuf_stop(&fh->vbi);
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003091 free_btres_lock(btv,fh,RESOURCE_VBI);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003092 }
3093
3094 /* free stuff */
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003095
Linus Torvalds1da177e2005-04-16 15:20:36 -07003096 videobuf_mmap_free(&fh->cap);
3097 videobuf_mmap_free(&fh->vbi);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003098 file->private_data = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003099
3100 btv->users--;
3101 bttv_field_count(btv);
Mauro Carvalho Chehabb46a9c82008-08-05 10:12:35 -03003102
3103 if (!btv->users)
Hans Verkuil01df5302013-02-06 12:40:28 -03003104 audio_mute(btv, btv->mute);
Mauro Carvalho Chehabb46a9c82008-08-05 10:12:35 -03003105
Hans Verkuilae50f0f2013-02-06 12:42:13 -03003106 v4l2_fh_del(&fh->fh);
3107 v4l2_fh_exit(&fh->fh);
3108 kfree(fh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003109 return 0;
3110}
3111
3112static int
3113bttv_mmap(struct file *file, struct vm_area_struct *vma)
3114{
3115 struct bttv_fh *fh = file->private_data;
3116
Joe Perches8af443e2011-08-21 19:56:48 -03003117 dprintk("%d: mmap type=%s 0x%lx+%ld\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003118 fh->btv->c.nr, v4l2_type_names[fh->type],
3119 vma->vm_start, vma->vm_end - vma->vm_start);
3120 return videobuf_mmap_mapper(bttv_queue(fh),vma);
3121}
3122
Hans Verkuilbec43662008-12-30 06:58:20 -03003123static const struct v4l2_file_operations bttv_fops =
Linus Torvalds1da177e2005-04-16 15:20:36 -07003124{
Mauro Carvalho Chehab8979e9d2010-09-15 08:22:09 -03003125 .owner = THIS_MODULE,
3126 .open = bttv_open,
3127 .release = bttv_release,
3128 .unlocked_ioctl = video_ioctl2,
3129 .read = bttv_read,
3130 .mmap = bttv_mmap,
3131 .poll = bttv_poll,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003132};
3133
Hans Verkuila3998102008-07-21 02:57:38 -03003134static const struct v4l2_ioctl_ops bttv_ioctl_ops = {
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003135 .vidioc_querycap = bttv_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03003136 .vidioc_enum_fmt_vid_cap = bttv_enum_fmt_vid_cap,
3137 .vidioc_g_fmt_vid_cap = bttv_g_fmt_vid_cap,
3138 .vidioc_try_fmt_vid_cap = bttv_try_fmt_vid_cap,
3139 .vidioc_s_fmt_vid_cap = bttv_s_fmt_vid_cap,
3140 .vidioc_enum_fmt_vid_overlay = bttv_enum_fmt_vid_overlay,
3141 .vidioc_g_fmt_vid_overlay = bttv_g_fmt_vid_overlay,
3142 .vidioc_try_fmt_vid_overlay = bttv_try_fmt_vid_overlay,
3143 .vidioc_s_fmt_vid_overlay = bttv_s_fmt_vid_overlay,
Hans Verkuil78b526a2008-05-28 12:16:41 -03003144 .vidioc_g_fmt_vbi_cap = bttv_g_fmt_vbi_cap,
3145 .vidioc_try_fmt_vbi_cap = bttv_try_fmt_vbi_cap,
3146 .vidioc_s_fmt_vbi_cap = bttv_s_fmt_vbi_cap,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003147 .vidioc_cropcap = bttv_cropcap,
3148 .vidioc_reqbufs = bttv_reqbufs,
3149 .vidioc_querybuf = bttv_querybuf,
3150 .vidioc_qbuf = bttv_qbuf,
3151 .vidioc_dqbuf = bttv_dqbuf,
3152 .vidioc_s_std = bttv_s_std,
Hans Verkuil6795cc52013-02-06 12:43:07 -03003153 .vidioc_g_std = bttv_g_std,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003154 .vidioc_enum_input = bttv_enum_input,
3155 .vidioc_g_input = bttv_g_input,
3156 .vidioc_s_input = bttv_s_input,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003157 .vidioc_streamon = bttv_streamon,
3158 .vidioc_streamoff = bttv_streamoff,
3159 .vidioc_g_tuner = bttv_g_tuner,
3160 .vidioc_s_tuner = bttv_s_tuner,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003161 .vidioc_g_crop = bttv_g_crop,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003162 .vidioc_s_crop = bttv_s_crop,
3163 .vidioc_g_fbuf = bttv_g_fbuf,
3164 .vidioc_s_fbuf = bttv_s_fbuf,
3165 .vidioc_overlay = bttv_overlay,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003166 .vidioc_g_parm = bttv_g_parm,
3167 .vidioc_g_frequency = bttv_g_frequency,
3168 .vidioc_s_frequency = bttv_s_frequency,
3169 .vidioc_log_status = bttv_log_status,
3170 .vidioc_querystd = bttv_querystd,
Hans Verkuilae50f0f2013-02-06 12:42:13 -03003171 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
3172 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Zoltan Devai43846832008-01-14 13:24:38 -03003173#ifdef CONFIG_VIDEO_ADV_DEBUG
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003174 .vidioc_g_register = bttv_g_register,
3175 .vidioc_s_register = bttv_s_register,
Zoltan Devai43846832008-01-14 13:24:38 -03003176#endif
Hans Verkuila3998102008-07-21 02:57:38 -03003177};
3178
3179static struct video_device bttv_video_template = {
3180 .fops = &bttv_fops,
Hans Verkuila3998102008-07-21 02:57:38 -03003181 .ioctl_ops = &bttv_ioctl_ops,
3182 .tvnorms = BTTV_NORMS,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003183};
3184
Linus Torvalds1da177e2005-04-16 15:20:36 -07003185/* ----------------------------------------------------------------------- */
3186/* radio interface */
3187
Hans Verkuilbec43662008-12-30 06:58:20 -03003188static int radio_open(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003189{
Laurent Pinchart50462eb2009-12-10 11:47:13 -02003190 struct video_device *vdev = video_devdata(file);
Trent Piepho4b10d3b2009-01-28 21:32:59 -03003191 struct bttv *btv = video_drvdata(file);
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003192 struct bttv_fh *fh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003193
Joe Perches8af443e2011-08-21 19:56:48 -03003194 dprintk("open dev=%s\n", video_device_node_name(vdev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003195
Joe Perches8af443e2011-08-21 19:56:48 -03003196 dprintk("%d: open called (radio)\n", btv->c.nr);
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003197
3198 /* allocate per filehandle data */
3199 fh = kmalloc(sizeof(*fh), GFP_KERNEL);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003200 if (unlikely(!fh))
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003201 return -ENOMEM;
3202 file->private_data = fh;
3203 *fh = btv->init;
Hans Verkuil8c14cc12013-02-06 12:42:40 -03003204 v4l2_fh_init(&fh->fh, vdev);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003205
Linus Torvalds1da177e2005-04-16 15:20:36 -07003206 btv->radio_user++;
Frank Schaefer0757f5c2013-03-21 13:51:20 -03003207 audio_mute(btv, btv->mute);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003208
Hans Verkuil8c14cc12013-02-06 12:42:40 -03003209 v4l2_fh_add(&fh->fh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003210
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003211 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003212}
3213
Hans Verkuilbec43662008-12-30 06:58:20 -03003214static int radio_release(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003215{
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003216 struct bttv_fh *fh = file->private_data;
3217 struct bttv *btv = fh->btv;
Hans Verkuilb9218f22010-12-27 12:22:46 -03003218 struct saa6588_command cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003219
Robert Fitzsimonsb9bc07a2008-04-10 09:40:31 -03003220 file->private_data = NULL;
Hans Verkuil8c14cc12013-02-06 12:42:40 -03003221 v4l2_fh_del(&fh->fh);
3222 v4l2_fh_exit(&fh->fh);
Robert Fitzsimonsb9bc07a2008-04-10 09:40:31 -03003223 kfree(fh);
3224
Linus Torvalds1da177e2005-04-16 15:20:36 -07003225 btv->radio_user--;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003226
Hans Verkuilb9218f22010-12-27 12:22:46 -03003227 bttv_call_all(btv, core, ioctl, SAA6588_CMD_CLOSE, &cmd);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003228
Hans Verkuilb8e2a362013-02-10 09:24:14 -03003229 if (btv->radio_user == 0)
3230 btv->has_radio_tuner = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003231 return 0;
3232}
3233
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003234static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003235{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003236 struct bttv_fh *fh = priv;
3237 struct bttv *btv = fh->btv;
3238
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003239 if (0 != t->index)
3240 return -EINVAL;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003241 strcpy(t->name, "Radio");
3242 t->type = V4L2_TUNER_RADIO;
Hans Verkuilb8e2a362013-02-10 09:24:14 -03003243 radio_enable(btv);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003244
Hans Verkuil859f0272009-03-28 08:29:00 -03003245 bttv_call_all(btv, tuner, g_tuner, t);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003246
3247 if (btv->audio_mode_gpio)
3248 btv->audio_mode_gpio(btv, t, 0);
3249
Ondrej Zary35655bf2015-01-16 06:58:32 -03003250 if (btv->has_tea575x)
3251 return snd_tea575x_g_tuner(&btv->tea, t);
3252
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003253 return 0;
3254}
3255
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003256static int radio_s_tuner(struct file *file, void *priv,
Hans Verkuil2f73c7c2013-03-15 06:10:06 -03003257 const struct v4l2_tuner *t)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003258{
3259 struct bttv_fh *fh = priv;
3260 struct bttv *btv = fh->btv;
3261
3262 if (0 != t->index)
3263 return -EINVAL;
3264
Hans Verkuilb8e2a362013-02-10 09:24:14 -03003265 radio_enable(btv);
Hans Verkuila024c1a2011-06-12 07:02:43 -03003266 bttv_call_all(btv, tuner, s_tuner, t);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003267 return 0;
3268}
3269
Ondrej Zary35655bf2015-01-16 06:58:32 -03003270static int radio_s_hw_freq_seek(struct file *file, void *priv,
3271 const struct v4l2_hw_freq_seek *a)
3272{
3273 struct bttv_fh *fh = priv;
3274 struct bttv *btv = fh->btv;
3275
3276 if (btv->has_tea575x)
3277 return snd_tea575x_s_hw_freq_seek(file, &btv->tea, a);
3278
3279 return -ENOTTY;
3280}
3281
3282static int radio_enum_freq_bands(struct file *file, void *priv,
3283 struct v4l2_frequency_band *band)
3284{
3285 struct bttv_fh *fh = priv;
3286 struct bttv *btv = fh->btv;
3287
3288 if (btv->has_tea575x)
3289 return snd_tea575x_enum_freq_bands(&btv->tea, band);
3290
3291 return -ENOTTY;
3292}
3293
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003294static ssize_t radio_read(struct file *file, char __user *data,
3295 size_t count, loff_t *ppos)
3296{
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003297 struct bttv_fh *fh = file->private_data;
3298 struct bttv *btv = fh->btv;
Hans Verkuilb9218f22010-12-27 12:22:46 -03003299 struct saa6588_command cmd;
Hans Verkuil09092782013-12-14 08:28:36 -03003300
3301 cmd.block_count = count / 3;
3302 cmd.nonblocking = file->f_flags & O_NONBLOCK;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003303 cmd.buffer = data;
3304 cmd.instance = file;
3305 cmd.result = -ENODEV;
Hans Verkuilb8e2a362013-02-10 09:24:14 -03003306 radio_enable(btv);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003307
Hans Verkuilb9218f22010-12-27 12:22:46 -03003308 bttv_call_all(btv, core, ioctl, SAA6588_CMD_READ, &cmd);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003309
3310 return cmd.result;
3311}
3312
3313static unsigned int radio_poll(struct file *file, poll_table *wait)
3314{
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003315 struct bttv_fh *fh = file->private_data;
3316 struct bttv *btv = fh->btv;
Hans Verkuilae50f0f2013-02-06 12:42:13 -03003317 unsigned long req_events = poll_requested_events(wait);
Hans Verkuilb9218f22010-12-27 12:22:46 -03003318 struct saa6588_command cmd;
Hans Verkuilae50f0f2013-02-06 12:42:13 -03003319 unsigned int res = 0;
3320
3321 if (v4l2_event_pending(&fh->fh))
3322 res = POLLPRI;
3323 else if (req_events & POLLPRI)
3324 poll_wait(file, &fh->fh.wait, wait);
Hans Verkuilb8e2a362013-02-10 09:24:14 -03003325 radio_enable(btv);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003326 cmd.instance = file;
3327 cmd.event_list = wait;
Hans Verkuilae50f0f2013-02-06 12:42:13 -03003328 cmd.result = res;
Hans Verkuilb9218f22010-12-27 12:22:46 -03003329 bttv_call_all(btv, core, ioctl, SAA6588_CMD_POLL, &cmd);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003330
3331 return cmd.result;
3332}
3333
Hans Verkuilbec43662008-12-30 06:58:20 -03003334static const struct v4l2_file_operations radio_fops =
Linus Torvalds1da177e2005-04-16 15:20:36 -07003335{
3336 .owner = THIS_MODULE,
3337 .open = radio_open,
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003338 .read = radio_read,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003339 .release = radio_release,
Mauro Carvalho Chehab587f0d52010-12-15 18:45:42 -03003340 .unlocked_ioctl = video_ioctl2,
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003341 .poll = radio_poll,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003342};
3343
Hans Verkuila3998102008-07-21 02:57:38 -03003344static const struct v4l2_ioctl_ops radio_ioctl_ops = {
Hans Verkuil78dea1a2012-09-09 09:03:29 -03003345 .vidioc_querycap = bttv_querycap,
Hans Verkuil01df5302013-02-06 12:40:28 -03003346 .vidioc_log_status = bttv_log_status,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003347 .vidioc_g_tuner = radio_g_tuner,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003348 .vidioc_s_tuner = radio_s_tuner,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003349 .vidioc_g_frequency = bttv_g_frequency,
3350 .vidioc_s_frequency = bttv_s_frequency,
Ondrej Zary35655bf2015-01-16 06:58:32 -03003351 .vidioc_s_hw_freq_seek = radio_s_hw_freq_seek,
3352 .vidioc_enum_freq_bands = radio_enum_freq_bands,
Hans Verkuilae50f0f2013-02-06 12:42:13 -03003353 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
3354 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003355};
3356
Hans Verkuila3998102008-07-21 02:57:38 -03003357static struct video_device radio_template = {
3358 .fops = &radio_fops,
Hans Verkuila3998102008-07-21 02:57:38 -03003359 .ioctl_ops = &radio_ioctl_ops,
3360};
3361
Linus Torvalds1da177e2005-04-16 15:20:36 -07003362/* ----------------------------------------------------------------------- */
3363/* some debug code */
3364
Adrian Bunk408b6642005-05-01 08:59:29 -07003365static int bttv_risc_decode(u32 risc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003366{
3367 static char *instr[16] = {
3368 [ BT848_RISC_WRITE >> 28 ] = "write",
3369 [ BT848_RISC_SKIP >> 28 ] = "skip",
3370 [ BT848_RISC_WRITEC >> 28 ] = "writec",
3371 [ BT848_RISC_JUMP >> 28 ] = "jump",
3372 [ BT848_RISC_SYNC >> 28 ] = "sync",
3373 [ BT848_RISC_WRITE123 >> 28 ] = "write123",
3374 [ BT848_RISC_SKIP123 >> 28 ] = "skip123",
3375 [ BT848_RISC_WRITE1S23 >> 28 ] = "write1s23",
3376 };
3377 static int incr[16] = {
3378 [ BT848_RISC_WRITE >> 28 ] = 2,
3379 [ BT848_RISC_JUMP >> 28 ] = 2,
3380 [ BT848_RISC_SYNC >> 28 ] = 2,
3381 [ BT848_RISC_WRITE123 >> 28 ] = 5,
3382 [ BT848_RISC_SKIP123 >> 28 ] = 2,
3383 [ BT848_RISC_WRITE1S23 >> 28 ] = 3,
3384 };
3385 static char *bits[] = {
3386 "be0", "be1", "be2", "be3/resync",
3387 "set0", "set1", "set2", "set3",
3388 "clr0", "clr1", "clr2", "clr3",
3389 "irq", "res", "eol", "sol",
3390 };
3391 int i;
3392
Joe Perches8af443e2011-08-21 19:56:48 -03003393 pr_cont("0x%08x [ %s", risc,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003394 instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
3395 for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
3396 if (risc & (1 << (i + 12)))
Joe Perches8af443e2011-08-21 19:56:48 -03003397 pr_cont(" %s", bits[i]);
3398 pr_cont(" count=%d ]\n", risc & 0xfff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003399 return incr[risc >> 28] ? incr[risc >> 28] : 1;
3400}
3401
Adrian Bunk408b6642005-05-01 08:59:29 -07003402static void bttv_risc_disasm(struct bttv *btv,
3403 struct btcx_riscmem *risc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003404{
3405 unsigned int i,j,n;
3406
Joe Perches8af443e2011-08-21 19:56:48 -03003407 pr_info("%s: risc disasm: %p [dma=0x%08lx]\n",
3408 btv->c.v4l2_dev.name, risc->cpu, (unsigned long)risc->dma);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003409 for (i = 0; i < (risc->size >> 2); i += n) {
Joe Perches8af443e2011-08-21 19:56:48 -03003410 pr_info("%s: 0x%lx: ",
3411 btv->c.v4l2_dev.name,
3412 (unsigned long)(risc->dma + (i<<2)));
Al Viro3aa71102008-06-22 14:20:09 -03003413 n = bttv_risc_decode(le32_to_cpu(risc->cpu[i]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003414 for (j = 1; j < n; j++)
Joe Perches8af443e2011-08-21 19:56:48 -03003415 pr_info("%s: 0x%lx: 0x%08x [ arg #%d ]\n",
3416 btv->c.v4l2_dev.name,
3417 (unsigned long)(risc->dma + ((i+j)<<2)),
3418 risc->cpu[i+j], j);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003419 if (0 == risc->cpu[i])
3420 break;
3421 }
3422}
3423
3424static void bttv_print_riscaddr(struct bttv *btv)
3425{
Joe Perches8af443e2011-08-21 19:56:48 -03003426 pr_info(" main: %08llx\n", (unsigned long long)btv->main.dma);
3427 pr_info(" vbi : o=%08llx e=%08llx\n",
3428 btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
3429 btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0);
3430 pr_info(" cap : o=%08llx e=%08llx\n",
3431 btv->curr.top
3432 ? (unsigned long long)btv->curr.top->top.dma : 0,
3433 btv->curr.bottom
3434 ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
3435 pr_info(" scr : o=%08llx e=%08llx\n",
3436 btv->screen ? (unsigned long long)btv->screen->top.dma : 0,
3437 btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003438 bttv_risc_disasm(btv, &btv->main);
3439}
3440
3441/* ----------------------------------------------------------------------- */
3442/* irq handler */
3443
3444static char *irq_name[] = {
3445 "FMTCHG", // format change detected (525 vs. 625)
3446 "VSYNC", // vertical sync (new field)
3447 "HSYNC", // horizontal sync
3448 "OFLOW", // chroma/luma AGC overflow
3449 "HLOCK", // horizontal lock changed
3450 "VPRES", // video presence changed
3451 "6", "7",
3452 "I2CDONE", // hw irc operation finished
3453 "GPINT", // gpio port triggered irq
3454 "10",
3455 "RISCI", // risc instruction triggered irq
3456 "FBUS", // pixel data fifo dropped data (high pci bus latencies)
3457 "FTRGT", // pixel data fifo overrun
3458 "FDSR", // fifo data stream resyncronisation
3459 "PPERR", // parity error (data transfer)
3460 "RIPERR", // parity error (read risc instructions)
3461 "PABORT", // pci abort
3462 "OCERR", // risc instruction error
3463 "SCERR", // syncronisation error
3464};
3465
3466static void bttv_print_irqbits(u32 print, u32 mark)
3467{
3468 unsigned int i;
3469
Joe Perches8af443e2011-08-21 19:56:48 -03003470 pr_cont("bits:");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003471 for (i = 0; i < ARRAY_SIZE(irq_name); i++) {
3472 if (print & (1 << i))
Joe Perches8af443e2011-08-21 19:56:48 -03003473 pr_cont(" %s", irq_name[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003474 if (mark & (1 << i))
Joe Perches8af443e2011-08-21 19:56:48 -03003475 pr_cont("*");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003476 }
3477}
3478
3479static void bttv_irq_debug_low_latency(struct bttv *btv, u32 rc)
3480{
Joe Perches8af443e2011-08-21 19:56:48 -03003481 pr_warn("%d: irq: skipped frame [main=%lx,o_vbi=%lx,o_field=%lx,rc=%lx]\n",
3482 btv->c.nr,
3483 (unsigned long)btv->main.dma,
3484 (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_VBI+1]),
3485 (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_FIELD+1]),
3486 (unsigned long)rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003487
3488 if (0 == (btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC)) {
Joe Perches8af443e2011-08-21 19:56:48 -03003489 pr_notice("%d: Oh, there (temporarily?) is no input signal. "
3490 "Ok, then this is harmless, don't worry ;)\n",
3491 btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003492 return;
3493 }
Joe Perches8af443e2011-08-21 19:56:48 -03003494 pr_notice("%d: Uhm. Looks like we have unusual high IRQ latencies\n",
3495 btv->c.nr);
3496 pr_notice("%d: Lets try to catch the culpit red-handed ...\n",
3497 btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003498 dump_stack();
3499}
3500
3501static int
3502bttv_irq_next_video(struct bttv *btv, struct bttv_buffer_set *set)
3503{
3504 struct bttv_buffer *item;
3505
3506 memset(set,0,sizeof(*set));
3507
3508 /* capture request ? */
3509 if (!list_empty(&btv->capture)) {
3510 set->frame_irq = 1;
3511 item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
3512 if (V4L2_FIELD_HAS_TOP(item->vb.field))
3513 set->top = item;
3514 if (V4L2_FIELD_HAS_BOTTOM(item->vb.field))
3515 set->bottom = item;
3516
3517 /* capture request for other field ? */
3518 if (!V4L2_FIELD_HAS_BOTH(item->vb.field) &&
3519 (item->vb.queue.next != &btv->capture)) {
3520 item = list_entry(item->vb.queue.next, struct bttv_buffer, vb.queue);
Mike Isely66349b42009-09-21 12:09:08 -03003521 /* Mike Isely <isely@pobox.com> - Only check
3522 * and set up the bottom field in the logic
3523 * below. Don't ever do the top field. This
3524 * of course means that if we set up the
3525 * bottom field in the above code that we'll
3526 * actually skip a field. But that's OK.
3527 * Having processed only a single buffer this
3528 * time, then the next time around the first
3529 * available buffer should be for a top field.
3530 * That will then cause us here to set up a
3531 * top then a bottom field in the normal way.
3532 * The alternative to this understanding is
3533 * that we set up the second available buffer
3534 * as a top field, but that's out of order
3535 * since this driver always processes the top
3536 * field first - the effect will be the two
3537 * buffers being returned in the wrong order,
3538 * with the second buffer also being delayed
3539 * by one field time (owing to the fifo nature
3540 * of videobuf). Worse still, we'll be stuck
3541 * doing fields out of order now every time
3542 * until something else causes a field to be
3543 * dropped. By effectively forcing a field to
3544 * drop this way then we always get back into
3545 * sync within a single frame time. (Out of
3546 * order fields can screw up deinterlacing
3547 * algorithms.) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003548 if (!V4L2_FIELD_HAS_BOTH(item->vb.field)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003549 if (NULL == set->bottom &&
3550 V4L2_FIELD_BOTTOM == item->vb.field) {
3551 set->bottom = item;
3552 }
3553 if (NULL != set->top && NULL != set->bottom)
3554 set->top_irq = 2;
3555 }
3556 }
3557 }
3558
3559 /* screen overlay ? */
3560 if (NULL != btv->screen) {
3561 if (V4L2_FIELD_HAS_BOTH(btv->screen->vb.field)) {
3562 if (NULL == set->top && NULL == set->bottom) {
3563 set->top = btv->screen;
3564 set->bottom = btv->screen;
3565 }
3566 } else {
3567 if (V4L2_FIELD_TOP == btv->screen->vb.field &&
3568 NULL == set->top) {
3569 set->top = btv->screen;
3570 }
3571 if (V4L2_FIELD_BOTTOM == btv->screen->vb.field &&
3572 NULL == set->bottom) {
3573 set->bottom = btv->screen;
3574 }
3575 }
3576 }
3577
Joe Perches8af443e2011-08-21 19:56:48 -03003578 dprintk("%d: next set: top=%p bottom=%p [screen=%p,irq=%d,%d]\n",
3579 btv->c.nr, set->top, set->bottom,
3580 btv->screen, set->frame_irq, set->top_irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003581 return 0;
3582}
3583
3584static void
3585bttv_irq_wakeup_video(struct bttv *btv, struct bttv_buffer_set *wakeup,
3586 struct bttv_buffer_set *curr, unsigned int state)
3587{
3588 struct timeval ts;
3589
Sakari Ailus8e6057b2012-09-15 15:14:42 -03003590 v4l2_get_timestamp(&ts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003591
3592 if (wakeup->top == wakeup->bottom) {
3593 if (NULL != wakeup->top && curr->top != wakeup->top) {
3594 if (irq_debug > 1)
Joe Perches8af443e2011-08-21 19:56:48 -03003595 pr_debug("%d: wakeup: both=%p\n",
3596 btv->c.nr, wakeup->top);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003597 wakeup->top->vb.ts = ts;
3598 wakeup->top->vb.field_count = btv->field_count;
3599 wakeup->top->vb.state = state;
3600 wake_up(&wakeup->top->vb.done);
3601 }
3602 } else {
3603 if (NULL != wakeup->top && curr->top != wakeup->top) {
3604 if (irq_debug > 1)
Joe Perches8af443e2011-08-21 19:56:48 -03003605 pr_debug("%d: wakeup: top=%p\n",
3606 btv->c.nr, wakeup->top);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003607 wakeup->top->vb.ts = ts;
3608 wakeup->top->vb.field_count = btv->field_count;
3609 wakeup->top->vb.state = state;
3610 wake_up(&wakeup->top->vb.done);
3611 }
3612 if (NULL != wakeup->bottom && curr->bottom != wakeup->bottom) {
3613 if (irq_debug > 1)
Joe Perches8af443e2011-08-21 19:56:48 -03003614 pr_debug("%d: wakeup: bottom=%p\n",
3615 btv->c.nr, wakeup->bottom);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003616 wakeup->bottom->vb.ts = ts;
3617 wakeup->bottom->vb.field_count = btv->field_count;
3618 wakeup->bottom->vb.state = state;
3619 wake_up(&wakeup->bottom->vb.done);
3620 }
3621 }
3622}
3623
3624static void
3625bttv_irq_wakeup_vbi(struct bttv *btv, struct bttv_buffer *wakeup,
3626 unsigned int state)
3627{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003628 if (NULL == wakeup)
3629 return;
3630
Arnd Bergmann5ba0e2c32015-09-17 18:19:37 -03003631 v4l2_get_timestamp(&wakeup->vb.ts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003632 wakeup->vb.field_count = btv->field_count;
3633 wakeup->vb.state = state;
3634 wake_up(&wakeup->vb.done);
3635}
3636
3637static void bttv_irq_timeout(unsigned long data)
3638{
3639 struct bttv *btv = (struct bttv *)data;
3640 struct bttv_buffer_set old,new;
3641 struct bttv_buffer *ovbi;
3642 struct bttv_buffer *item;
3643 unsigned long flags;
3644
3645 if (bttv_verbose) {
Joe Perches8af443e2011-08-21 19:56:48 -03003646 pr_info("%d: timeout: drop=%d irq=%d/%d, risc=%08x, ",
3647 btv->c.nr, btv->framedrop, btv->irq_me, btv->irq_total,
3648 btread(BT848_RISC_COUNT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003649 bttv_print_irqbits(btread(BT848_INT_STAT),0);
Joe Perches8af443e2011-08-21 19:56:48 -03003650 pr_cont("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651 }
3652
3653 spin_lock_irqsave(&btv->s_lock,flags);
3654
3655 /* deactivate stuff */
3656 memset(&new,0,sizeof(new));
3657 old = btv->curr;
3658 ovbi = btv->cvbi;
3659 btv->curr = new;
3660 btv->cvbi = NULL;
3661 btv->loop_irq = 0;
3662 bttv_buffer_activate_video(btv, &new);
3663 bttv_buffer_activate_vbi(btv, NULL);
3664 bttv_set_dma(btv, 0);
3665
3666 /* wake up */
Brandon Philips0fc06862007-11-06 20:02:36 -03003667 bttv_irq_wakeup_video(btv, &old, &new, VIDEOBUF_ERROR);
3668 bttv_irq_wakeup_vbi(btv, ovbi, VIDEOBUF_ERROR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003669
3670 /* cancel all outstanding capture / vbi requests */
3671 while (!list_empty(&btv->capture)) {
3672 item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
3673 list_del(&item->vb.queue);
Brandon Philips0fc06862007-11-06 20:02:36 -03003674 item->vb.state = VIDEOBUF_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003675 wake_up(&item->vb.done);
3676 }
3677 while (!list_empty(&btv->vcapture)) {
3678 item = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
3679 list_del(&item->vb.queue);
Brandon Philips0fc06862007-11-06 20:02:36 -03003680 item->vb.state = VIDEOBUF_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003681 wake_up(&item->vb.done);
3682 }
3683
3684 btv->errors++;
3685 spin_unlock_irqrestore(&btv->s_lock,flags);
3686}
3687
3688static void
3689bttv_irq_wakeup_top(struct bttv *btv)
3690{
3691 struct bttv_buffer *wakeup = btv->curr.top;
3692
3693 if (NULL == wakeup)
3694 return;
3695
3696 spin_lock(&btv->s_lock);
3697 btv->curr.top_irq = 0;
3698 btv->curr.top = NULL;
3699 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
3700
Sakari Ailus8e6057b2012-09-15 15:14:42 -03003701 v4l2_get_timestamp(&wakeup->vb.ts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003702 wakeup->vb.field_count = btv->field_count;
Brandon Philips0fc06862007-11-06 20:02:36 -03003703 wakeup->vb.state = VIDEOBUF_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003704 wake_up(&wakeup->vb.done);
3705 spin_unlock(&btv->s_lock);
3706}
3707
3708static inline int is_active(struct btcx_riscmem *risc, u32 rc)
3709{
3710 if (rc < risc->dma)
3711 return 0;
3712 if (rc > risc->dma + risc->size)
3713 return 0;
3714 return 1;
3715}
3716
3717static void
3718bttv_irq_switch_video(struct bttv *btv)
3719{
3720 struct bttv_buffer_set new;
3721 struct bttv_buffer_set old;
3722 dma_addr_t rc;
3723
3724 spin_lock(&btv->s_lock);
3725
3726 /* new buffer set */
3727 bttv_irq_next_video(btv, &new);
3728 rc = btread(BT848_RISC_COUNT);
3729 if ((btv->curr.top && is_active(&btv->curr.top->top, rc)) ||
3730 (btv->curr.bottom && is_active(&btv->curr.bottom->bottom, rc))) {
3731 btv->framedrop++;
3732 if (debug_latency)
3733 bttv_irq_debug_low_latency(btv, rc);
3734 spin_unlock(&btv->s_lock);
3735 return;
3736 }
3737
3738 /* switch over */
3739 old = btv->curr;
3740 btv->curr = new;
3741 btv->loop_irq &= ~1;
3742 bttv_buffer_activate_video(btv, &new);
3743 bttv_set_dma(btv, 0);
3744
3745 /* switch input */
3746 if (UNSET != btv->new_input) {
3747 video_mux(btv,btv->new_input);
3748 btv->new_input = UNSET;
3749 }
3750
3751 /* wake up finished buffers */
Brandon Philips0fc06862007-11-06 20:02:36 -03003752 bttv_irq_wakeup_video(btv, &old, &new, VIDEOBUF_DONE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003753 spin_unlock(&btv->s_lock);
3754}
3755
3756static void
3757bttv_irq_switch_vbi(struct bttv *btv)
3758{
3759 struct bttv_buffer *new = NULL;
3760 struct bttv_buffer *old;
3761 u32 rc;
3762
3763 spin_lock(&btv->s_lock);
3764
3765 if (!list_empty(&btv->vcapture))
3766 new = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
3767 old = btv->cvbi;
3768
3769 rc = btread(BT848_RISC_COUNT);
3770 if (NULL != old && (is_active(&old->top, rc) ||
3771 is_active(&old->bottom, rc))) {
3772 btv->framedrop++;
3773 if (debug_latency)
3774 bttv_irq_debug_low_latency(btv, rc);
3775 spin_unlock(&btv->s_lock);
3776 return;
3777 }
3778
3779 /* switch */
3780 btv->cvbi = new;
3781 btv->loop_irq &= ~4;
3782 bttv_buffer_activate_vbi(btv, new);
3783 bttv_set_dma(btv, 0);
3784
Brandon Philips0fc06862007-11-06 20:02:36 -03003785 bttv_irq_wakeup_vbi(btv, old, VIDEOBUF_DONE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003786 spin_unlock(&btv->s_lock);
3787}
3788
David Howells7d12e782006-10-05 14:55:46 +01003789static irqreturn_t bttv_irq(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003790{
3791 u32 stat,astat;
3792 u32 dstat;
3793 int count;
3794 struct bttv *btv;
3795 int handled = 0;
3796
3797 btv=(struct bttv *)dev_id;
Mark Weaver6c6c0b22005-11-13 16:07:52 -08003798
Linus Torvalds1da177e2005-04-16 15:20:36 -07003799 count=0;
3800 while (1) {
3801 /* get/clear interrupt status bits */
3802 stat=btread(BT848_INT_STAT);
3803 astat=stat&btread(BT848_INT_MASK);
3804 if (!astat)
3805 break;
3806 handled = 1;
3807 btwrite(stat,BT848_INT_STAT);
3808
3809 /* get device status bits */
3810 dstat=btread(BT848_DSTATUS);
3811
3812 if (irq_debug) {
Joe Perches8af443e2011-08-21 19:56:48 -03003813 pr_debug("%d: irq loop=%d fc=%d riscs=%x, riscc=%08x, ",
3814 btv->c.nr, count, btv->field_count,
3815 stat>>28, btread(BT848_RISC_COUNT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003816 bttv_print_irqbits(stat,astat);
3817 if (stat & BT848_INT_HLOCK)
Joe Perches8af443e2011-08-21 19:56:48 -03003818 pr_cont(" HLOC => %s",
3819 dstat & BT848_DSTATUS_HLOC
3820 ? "yes" : "no");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003821 if (stat & BT848_INT_VPRES)
Joe Perches8af443e2011-08-21 19:56:48 -03003822 pr_cont(" PRES => %s",
3823 dstat & BT848_DSTATUS_PRES
3824 ? "yes" : "no");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003825 if (stat & BT848_INT_FMTCHG)
Joe Perches8af443e2011-08-21 19:56:48 -03003826 pr_cont(" NUML => %s",
3827 dstat & BT848_DSTATUS_NUML
3828 ? "625" : "525");
3829 pr_cont("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003830 }
3831
3832 if (astat&BT848_INT_VSYNC)
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003833 btv->field_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003834
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02003835 if ((astat & BT848_INT_GPINT) && btv->remote) {
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02003836 bttv_input_irq(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837 }
3838
3839 if (astat & BT848_INT_I2CDONE) {
3840 btv->i2c_done = stat;
3841 wake_up(&btv->i2c_queue);
3842 }
3843
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003844 if ((astat & BT848_INT_RISCI) && (stat & (4<<28)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003845 bttv_irq_switch_vbi(btv);
3846
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003847 if ((astat & BT848_INT_RISCI) && (stat & (2<<28)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003848 bttv_irq_wakeup_top(btv);
3849
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003850 if ((astat & BT848_INT_RISCI) && (stat & (1<<28)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003851 bttv_irq_switch_video(btv);
3852
3853 if ((astat & BT848_INT_HLOCK) && btv->opt_automute)
Frank Schaefer5f4567812013-03-21 13:51:17 -03003854 /* trigger automute */
3855 audio_mux_gpio(btv, btv->audio_input, btv->mute);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003856
3857 if (astat & (BT848_INT_SCERR|BT848_INT_OCERR)) {
Joe Perches8af443e2011-08-21 19:56:48 -03003858 pr_info("%d: %s%s @ %08x,",
3859 btv->c.nr,
3860 (astat & BT848_INT_SCERR) ? "SCERR" : "",
3861 (astat & BT848_INT_OCERR) ? "OCERR" : "",
3862 btread(BT848_RISC_COUNT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003863 bttv_print_irqbits(stat,astat);
Joe Perches8af443e2011-08-21 19:56:48 -03003864 pr_cont("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003865 if (bttv_debug)
3866 bttv_print_riscaddr(btv);
3867 }
3868 if (fdsr && astat & BT848_INT_FDSR) {
Joe Perches8af443e2011-08-21 19:56:48 -03003869 pr_info("%d: FDSR @ %08x\n",
3870 btv->c.nr, btread(BT848_RISC_COUNT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003871 if (bttv_debug)
3872 bttv_print_riscaddr(btv);
3873 }
3874
3875 count++;
3876 if (count > 4) {
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08003877
3878 if (count > 8 || !(astat & BT848_INT_GPINT)) {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003879 btwrite(0, BT848_INT_MASK);
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08003880
Joe Perches8af443e2011-08-21 19:56:48 -03003881 pr_err("%d: IRQ lockup, cleared int mask [",
3882 btv->c.nr);
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08003883 } else {
Joe Perches8af443e2011-08-21 19:56:48 -03003884 pr_err("%d: IRQ lockup, clearing GPINT from int mask [",
3885 btv->c.nr);
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08003886
3887 btwrite(btread(BT848_INT_MASK) & (-1 ^ BT848_INT_GPINT),
3888 BT848_INT_MASK);
Mauro Carvalho Chehabc3142a62014-09-03 15:32:07 -03003889 }
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08003890
Linus Torvalds1da177e2005-04-16 15:20:36 -07003891 bttv_print_irqbits(stat,astat);
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08003892
Joe Perches8af443e2011-08-21 19:56:48 -03003893 pr_cont("]\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003894 }
3895 }
3896 btv->irq_total++;
3897 if (handled)
3898 btv->irq_me++;
3899 return IRQ_RETVAL(handled);
3900}
3901
3902
3903/* ----------------------------------------------------------------------- */
Hans Verkuild9b67072013-02-06 11:43:07 -03003904/* initialization */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003905
Hans Verkuil23fb4c52015-03-09 13:34:02 -03003906static void vdev_init(struct bttv *btv,
3907 struct video_device *vfd,
3908 const struct video_device *template,
3909 const char *type_name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003910{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003911 *vfd = *template;
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03003912 vfd->v4l2_dev = &btv->c.v4l2_dev;
Hans Verkuil23fb4c52015-03-09 13:34:02 -03003913 vfd->release = video_device_release_empty;
Trent Piepho4b10d3b2009-01-28 21:32:59 -03003914 video_set_drvdata(vfd, btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003915 snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
3916 btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "",
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03003917 type_name, bttv_tvcards[btv->c.type].name);
Hans Verkuild9b67072013-02-06 11:43:07 -03003918 if (btv->tuner_type == TUNER_ABSENT) {
3919 v4l2_disable_ioctl(vfd, VIDIOC_G_FREQUENCY);
3920 v4l2_disable_ioctl(vfd, VIDIOC_S_FREQUENCY);
3921 v4l2_disable_ioctl(vfd, VIDIOC_G_TUNER);
3922 v4l2_disable_ioctl(vfd, VIDIOC_S_TUNER);
3923 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003924}
3925
3926static void bttv_unregister_video(struct bttv *btv)
3927{
Hans Verkuil23fb4c52015-03-09 13:34:02 -03003928 video_unregister_device(&btv->video_dev);
3929 video_unregister_device(&btv->vbi_dev);
3930 video_unregister_device(&btv->radio_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003931}
3932
3933/* register video4linux devices */
Greg Kroah-Hartman4c62e972012-12-21 13:17:53 -08003934static int bttv_register_video(struct bttv *btv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003935{
Hans Verkuil0ea6bc82008-07-26 08:26:43 -03003936 if (no_overlay > 0)
Joe Perches8af443e2011-08-21 19:56:48 -03003937 pr_notice("Overlay support disabled\n");
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07003938
Linus Torvalds1da177e2005-04-16 15:20:36 -07003939 /* video */
Hans Verkuil23fb4c52015-03-09 13:34:02 -03003940 vdev_init(btv, &btv->video_dev, &bttv_video_template, "video");
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03003941
Hans Verkuil23fb4c52015-03-09 13:34:02 -03003942 if (video_register_device(&btv->video_dev, VFL_TYPE_GRABBER,
Jean Delvare176c2f32008-09-07 12:49:59 -03003943 video_nr[btv->c.nr]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003944 goto err;
Joe Perches8af443e2011-08-21 19:56:48 -03003945 pr_info("%d: registered device %s\n",
Hans Verkuil23fb4c52015-03-09 13:34:02 -03003946 btv->c.nr, video_device_node_name(&btv->video_dev));
3947 if (device_create_file(&btv->video_dev.dev,
Kay Sievers54bd5b62007-10-08 16:26:13 -03003948 &dev_attr_card)<0) {
Joe Perches8af443e2011-08-21 19:56:48 -03003949 pr_err("%d: device_create_file 'card' failed\n", btv->c.nr);
Trent Piephod94fc9a2006-07-29 17:18:06 -03003950 goto err;
3951 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003952
3953 /* vbi */
Hans Verkuil23fb4c52015-03-09 13:34:02 -03003954 vdev_init(btv, &btv->vbi_dev, &bttv_video_template, "vbi");
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03003955
Hans Verkuil23fb4c52015-03-09 13:34:02 -03003956 if (video_register_device(&btv->vbi_dev, VFL_TYPE_VBI,
Jean Delvare176c2f32008-09-07 12:49:59 -03003957 vbi_nr[btv->c.nr]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958 goto err;
Joe Perches8af443e2011-08-21 19:56:48 -03003959 pr_info("%d: registered device %s\n",
Hans Verkuil23fb4c52015-03-09 13:34:02 -03003960 btv->c.nr, video_device_node_name(&btv->vbi_dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003961
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003962 if (!btv->has_radio)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003963 return 0;
3964 /* radio */
Hans Verkuil23fb4c52015-03-09 13:34:02 -03003965 vdev_init(btv, &btv->radio_dev, &radio_template, "radio");
3966 btv->radio_dev.ctrl_handler = &btv->radio_ctrl_handler;
3967 if (video_register_device(&btv->radio_dev, VFL_TYPE_RADIO,
Jean Delvare176c2f32008-09-07 12:49:59 -03003968 radio_nr[btv->c.nr]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003969 goto err;
Joe Perches8af443e2011-08-21 19:56:48 -03003970 pr_info("%d: registered device %s\n",
Hans Verkuil23fb4c52015-03-09 13:34:02 -03003971 btv->c.nr, video_device_node_name(&btv->radio_dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003972
3973 /* all done */
3974 return 0;
3975
3976 err:
3977 bttv_unregister_video(btv);
3978 return -1;
3979}
3980
3981
3982/* on OpenFirmware machines (PowerMac at least), PCI memory cycle */
3983/* response on cards with no firmware is not enabled by OF */
3984static void pci_set_command(struct pci_dev *dev)
3985{
3986#if defined(__powerpc__)
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003987 unsigned int cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003988
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003989 pci_read_config_dword(dev, PCI_COMMAND, &cmd);
3990 cmd = (cmd | PCI_COMMAND_MEMORY );
3991 pci_write_config_dword(dev, PCI_COMMAND, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003992#endif
3993}
3994
Greg Kroah-Hartman4c62e972012-12-21 13:17:53 -08003995static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003996{
Hans Verkuil76ea9922013-02-06 11:49:14 -03003997 struct v4l2_frequency init_freq = {
3998 .tuner = 0,
3999 .type = V4L2_TUNER_ANALOG_TV,
4000 .frequency = 980,
4001 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07004002 int result;
4003 unsigned char lat;
4004 struct bttv *btv;
Hans Verkuil01df5302013-02-06 12:40:28 -03004005 struct v4l2_ctrl_handler *hdl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004006
4007 if (bttv_num == BTTV_MAX)
4008 return -ENOMEM;
Joe Perches8af443e2011-08-21 19:56:48 -03004009 pr_info("Bt8xx card found (%d)\n", bttv_num);
Trent Piepho4b10d3b2009-01-28 21:32:59 -03004010 bttvs[bttv_num] = btv = kzalloc(sizeof(*btv), GFP_KERNEL);
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004011 if (btv == NULL) {
Joe Perches8af443e2011-08-21 19:56:48 -03004012 pr_err("out of memory\n");
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004013 return -ENOMEM;
4014 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004015 btv->c.nr = bttv_num;
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004016 snprintf(btv->c.v4l2_dev.name, sizeof(btv->c.v4l2_dev.name),
4017 "bttv%d", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004018
4019 /* initialize structs / fill in defaults */
Ingo Molnarbd5f0ac2006-01-13 14:10:24 -02004020 mutex_init(&btv->lock);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004021 spin_lock_init(&btv->s_lock);
4022 spin_lock_init(&btv->gpio_lock);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004023 init_waitqueue_head(&btv->i2c_queue);
4024 INIT_LIST_HEAD(&btv->c.subs);
4025 INIT_LIST_HEAD(&btv->capture);
4026 INIT_LIST_HEAD(&btv->vcapture);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004027
4028 init_timer(&btv->timeout);
4029 btv->timeout.function = bttv_irq_timeout;
4030 btv->timeout.data = (unsigned long)btv;
4031
Michael Krufky7c08fb02005-11-08 21:36:21 -08004032 btv->i2c_rc = -1;
4033 btv->tuner_type = UNSET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004034 btv->new_input = UNSET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004035 btv->has_radio=radio[btv->c.nr];
4036
4037 /* pci stuff (init, get irq/mmio, ... */
4038 btv->c.pci = dev;
Michael Krufky7c08fb02005-11-08 21:36:21 -08004039 btv->id = dev->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004040 if (pci_enable_device(dev)) {
Joe Perches8af443e2011-08-21 19:56:48 -03004041 pr_warn("%d: Can't enable device\n", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042 return -EIO;
4043 }
Yang Hongyang284901a2009-04-06 19:01:15 -07004044 if (pci_set_dma_mask(dev, DMA_BIT_MASK(32))) {
Joe Perches8af443e2011-08-21 19:56:48 -03004045 pr_warn("%d: No suitable DMA available\n", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046 return -EIO;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004047 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004048 if (!request_mem_region(pci_resource_start(dev,0),
4049 pci_resource_len(dev,0),
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004050 btv->c.v4l2_dev.name)) {
Joe Perches8af443e2011-08-21 19:56:48 -03004051 pr_warn("%d: can't request iomem (0x%llx)\n",
4052 btv->c.nr,
4053 (unsigned long long)pci_resource_start(dev, 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004054 return -EBUSY;
4055 }
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004056 pci_set_master(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004057 pci_set_command(dev);
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004058
4059 result = v4l2_device_register(&dev->dev, &btv->c.v4l2_dev);
4060 if (result < 0) {
Joe Perches8af443e2011-08-21 19:56:48 -03004061 pr_warn("%d: v4l2_device_register() failed\n", btv->c.nr);
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004062 goto fail0;
4063 }
Hans Verkuil01df5302013-02-06 12:40:28 -03004064 hdl = &btv->ctrl_handler;
4065 v4l2_ctrl_handler_init(hdl, 20);
4066 btv->c.v4l2_dev.ctrl_handler = hdl;
4067 v4l2_ctrl_handler_init(&btv->radio_ctrl_handler, 6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004068
Bjørn Morkabd34d82011-03-21 11:35:56 -03004069 btv->revision = dev->revision;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004070 pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
Joe Perches8af443e2011-08-21 19:56:48 -03004071 pr_info("%d: Bt%d (rev %d) at %s, irq: %d, latency: %d, mmio: 0x%llx\n",
4072 bttv_num, btv->id, btv->revision, pci_name(dev),
4073 btv->c.pci->irq, lat,
4074 (unsigned long long)pci_resource_start(dev, 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075 schedule();
4076
Akinobu Mita5f1693f2006-12-20 10:08:56 -03004077 btv->bt848_mmio = ioremap(pci_resource_start(dev, 0), 0x1000);
4078 if (NULL == btv->bt848_mmio) {
Joe Perches8af443e2011-08-21 19:56:48 -03004079 pr_err("%d: ioremap() failed\n", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004080 result = -EIO;
4081 goto fail1;
4082 }
4083
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004084 /* identify card */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004085 bttv_idcard(btv);
4086
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004087 /* disable irqs, register irq handler */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004088 btwrite(0, BT848_INT_MASK);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004089 result = request_irq(btv->c.pci->irq, bttv_irq,
Michael Opdenacker3e018fe2013-10-13 02:49:29 -03004090 IRQF_SHARED, btv->c.v4l2_dev.name, (void *)btv);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004091 if (result < 0) {
Joe Perches8af443e2011-08-21 19:56:48 -03004092 pr_err("%d: can't get IRQ %d\n",
4093 bttv_num, btv->c.pci->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004094 goto fail1;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004095 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004096
4097 if (0 != bttv_handle_chipset(btv)) {
4098 result = -EIO;
4099 goto fail2;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004100 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004101
4102 /* init options from insmod args */
4103 btv->opt_combfilter = combfilter;
Hans Verkuil01df5302013-02-06 12:40:28 -03004104 bttv_ctrl_combfilter.def = combfilter;
4105 bttv_ctrl_lumafilter.def = lumafilter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106 btv->opt_automute = automute;
Hans Verkuil01df5302013-02-06 12:40:28 -03004107 bttv_ctrl_automute.def = automute;
4108 bttv_ctrl_agc_crush.def = agc_crush;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004109 btv->opt_vcr_hack = vcr_hack;
Hans Verkuil01df5302013-02-06 12:40:28 -03004110 bttv_ctrl_vcr_hack.def = vcr_hack;
4111 bttv_ctrl_whitecrush_upper.def = whitecrush_upper;
4112 bttv_ctrl_whitecrush_lower.def = whitecrush_lower;
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -07004113 btv->opt_uv_ratio = uv_ratio;
Hans Verkuil01df5302013-02-06 12:40:28 -03004114 bttv_ctrl_uv_ratio.def = uv_ratio;
4115 bttv_ctrl_full_luma.def = full_luma_range;
4116 bttv_ctrl_coring.def = coring;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004117
4118 /* fill struct bttv with some useful defaults */
4119 btv->init.btv = btv;
4120 btv->init.ov.w.width = 320;
4121 btv->init.ov.w.height = 240;
Mauro Carvalho Chehabc96dd072007-10-26 16:51:47 -03004122 btv->init.fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123 btv->init.width = 320;
4124 btv->init.height = 240;
Hans Verkuilc13eb702013-02-07 07:56:11 -03004125 btv->init.ov.w.width = 320;
4126 btv->init.ov.w.height = 240;
4127 btv->init.ov.field = V4L2_FIELD_INTERLACED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004128 btv->input = 0;
4129
Hans Verkuil01df5302013-02-06 12:40:28 -03004130 v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
4131 V4L2_CID_BRIGHTNESS, 0, 0xff00, 0x100, 32768);
4132 v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
4133 V4L2_CID_CONTRAST, 0, 0xff80, 0x80, 0x6c00);
4134 v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
4135 V4L2_CID_SATURATION, 0, 0xff80, 0x80, 32768);
4136 v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
4137 V4L2_CID_COLOR_KILLER, 0, 1, 1, 0);
4138 v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
4139 V4L2_CID_HUE, 0, 0xff00, 0x100, 32768);
4140 v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
4141 V4L2_CID_CHROMA_AGC, 0, 1, 1, !!chroma_agc);
4142 v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
4143 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
4144 if (btv->volume_gpio)
4145 v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
4146 V4L2_CID_AUDIO_VOLUME, 0, 0xff00, 0x100, 0xff00);
4147 v4l2_ctrl_new_custom(hdl, &bttv_ctrl_combfilter, NULL);
4148 v4l2_ctrl_new_custom(hdl, &bttv_ctrl_automute, NULL);
4149 v4l2_ctrl_new_custom(hdl, &bttv_ctrl_lumafilter, NULL);
4150 v4l2_ctrl_new_custom(hdl, &bttv_ctrl_agc_crush, NULL);
4151 v4l2_ctrl_new_custom(hdl, &bttv_ctrl_vcr_hack, NULL);
4152 v4l2_ctrl_new_custom(hdl, &bttv_ctrl_whitecrush_lower, NULL);
4153 v4l2_ctrl_new_custom(hdl, &bttv_ctrl_whitecrush_upper, NULL);
4154 v4l2_ctrl_new_custom(hdl, &bttv_ctrl_uv_ratio, NULL);
4155 v4l2_ctrl_new_custom(hdl, &bttv_ctrl_full_luma, NULL);
4156 v4l2_ctrl_new_custom(hdl, &bttv_ctrl_coring, NULL);
4157
Linus Torvalds1da177e2005-04-16 15:20:36 -07004158 /* initialize hardware */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004159 if (bttv_gpio)
4160 bttv_gpio_tracking(btv,"pre-init");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004161
4162 bttv_risc_init_main(btv);
4163 init_bt848(btv);
4164
4165 /* gpio */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004166 btwrite(0x00, BT848_GPIO_REG_INP);
4167 btwrite(0x00, BT848_GPIO_OUT_EN);
4168 if (bttv_verbose)
4169 bttv_gpio_tracking(btv,"init");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004170
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004171 /* needs to be done before i2c is registered */
4172 bttv_init_card1(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004174 /* register i2c + gpio */
4175 init_bttv_i2c(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004176
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004177 /* some card-specific stuff (needs working i2c) */
4178 bttv_init_card2(btv);
Hans Verkuil2c905772009-07-20 08:14:17 -03004179 bttv_init_tuner(btv);
Hans Verkuil76ea9922013-02-06 11:49:14 -03004180 if (btv->tuner_type != TUNER_ABSENT) {
4181 bttv_set_frequency(btv, &init_freq);
4182 btv->radio_freq = 90500 * 16; /* 90.5Mhz default */
4183 }
Hans Verkuil6795cc52013-02-06 12:43:07 -03004184 btv->std = V4L2_STD_PAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004185 init_irqreg(btv);
Hans Verkuilf8e1b692013-11-11 08:16:03 -03004186 if (!bttv_tvcards[btv->c.type].no_video)
4187 v4l2_ctrl_handler_setup(hdl);
Hans Verkuil01df5302013-02-06 12:40:28 -03004188 if (hdl->error) {
4189 result = hdl->error;
4190 goto fail2;
4191 }
Frank Schaeferda9f07f2013-03-21 13:51:19 -03004192 /* mute device */
4193 audio_mute(btv, 1);
4194
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004195 /* register video4linux + input */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004196 if (!bttv_tvcards[btv->c.type].no_video) {
Hans Verkuil01df5302013-02-06 12:40:28 -03004197 v4l2_ctrl_add_handler(&btv->radio_ctrl_handler, hdl,
4198 v4l2_ctrl_radio_filter);
4199 if (btv->radio_ctrl_handler.error) {
4200 result = btv->radio_ctrl_handler.error;
4201 goto fail2;
4202 }
Trent Piepho333408f2007-07-03 15:08:10 -03004203 set_input(btv, 0, btv->tvnorm);
Michael Schimeke5bd0262007-01-18 16:17:39 -03004204 bttv_crop_reset(&btv->crop[0], btv->tvnorm);
4205 btv->crop[1] = btv->crop[0]; /* current = default */
4206 disclaim_vbi_lines(btv);
4207 disclaim_video_lines(btv);
Hans Verkuil01df5302013-02-06 12:40:28 -03004208 bttv_register_video(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004209 }
4210
Jarod Wilsonf992a492007-03-24 15:23:50 -03004211 /* add subdevices and autoload dvb-bt8xx if needed */
4212 if (bttv_tvcards[btv->c.type].has_dvb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004213 bttv_sub_add_device(&btv->c, "dvb");
Jarod Wilsonf992a492007-03-24 15:23:50 -03004214 request_modules(btv);
4215 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004216
Jean Delvared90a4ae2010-02-16 14:22:37 -03004217 if (!disable_ir) {
4218 init_bttv_i2c_ir(btv);
4219 bttv_input_init(btv);
4220 }
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02004221
Linus Torvalds1da177e2005-04-16 15:20:36 -07004222 /* everything is fine */
4223 bttv_num++;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004224 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004225
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004226fail2:
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004227 free_irq(btv->c.pci->irq,btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004228
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004229fail1:
Hans Verkuil01df5302013-02-06 12:40:28 -03004230 v4l2_ctrl_handler_free(&btv->ctrl_handler);
4231 v4l2_ctrl_handler_free(&btv->radio_ctrl_handler);
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004232 v4l2_device_unregister(&btv->c.v4l2_dev);
4233
4234fail0:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004235 if (btv->bt848_mmio)
4236 iounmap(btv->bt848_mmio);
4237 release_mem_region(pci_resource_start(btv->c.pci,0),
4238 pci_resource_len(btv->c.pci,0));
Hans Verkuilde73e132015-04-03 08:13:14 -03004239 pci_disable_device(btv->c.pci);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004240 return result;
4241}
4242
Greg Kroah-Hartman4c62e972012-12-21 13:17:53 -08004243static void bttv_remove(struct pci_dev *pci_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004244{
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004245 struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
4246 struct bttv *btv = to_bttv(v4l2_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004247
4248 if (bttv_verbose)
Joe Perches8af443e2011-08-21 19:56:48 -03004249 pr_info("%d: unloading\n", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004250
Tejun Heo707bcf32010-12-24 16:14:20 +01004251 if (bttv_tvcards[btv->c.type].has_dvb)
4252 flush_request_modules(btv);
4253
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004254 /* shutdown everything (DMA+IRQs) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004255 btand(~15, BT848_GPIO_DMA_CTL);
4256 btwrite(0, BT848_INT_MASK);
4257 btwrite(~0x0, BT848_INT_STAT);
4258 btwrite(0x0, BT848_GPIO_OUT_EN);
4259 if (bttv_gpio)
4260 bttv_gpio_tracking(btv,"cleanup");
4261
4262 /* tell gpio modules we are leaving ... */
4263 btv->shutdown=1;
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02004264 bttv_input_fini(btv);
Christopher Pascoe889aee82006-01-09 15:25:28 -02004265 bttv_sub_del_devices(&btv->c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004266
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004267 /* unregister i2c_bus + input */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004268 fini_bttv_i2c(btv);
4269
4270 /* unregister video4linux */
4271 bttv_unregister_video(btv);
4272
4273 /* free allocated memory */
Hans Verkuil01df5302013-02-06 12:40:28 -03004274 v4l2_ctrl_handler_free(&btv->ctrl_handler);
4275 v4l2_ctrl_handler_free(&btv->radio_ctrl_handler);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004276 btcx_riscmem_free(btv->c.pci,&btv->main);
4277
Hans Verkuil01df5302013-02-06 12:40:28 -03004278 /* free resources */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004279 free_irq(btv->c.pci->irq,btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004280 iounmap(btv->bt848_mmio);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004281 release_mem_region(pci_resource_start(btv->c.pci,0),
4282 pci_resource_len(btv->c.pci,0));
Hans Verkuilde73e132015-04-03 08:13:14 -03004283 pci_disable_device(btv->c.pci);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004284
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004285 v4l2_device_unregister(&btv->c.v4l2_dev);
Trent Piepho4b10d3b2009-01-28 21:32:59 -03004286 bttvs[btv->c.nr] = NULL;
4287 kfree(btv);
4288
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004289 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004290}
4291
Alexey Dobriyan17bc98a2006-08-12 22:01:27 -03004292#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -07004293static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state)
4294{
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004295 struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
4296 struct bttv *btv = to_bttv(v4l2_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004297 struct bttv_buffer_set idle;
4298 unsigned long flags;
4299
Joe Perches8af443e2011-08-21 19:56:48 -03004300 dprintk("%d: suspend %d\n", btv->c.nr, state.event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004301
4302 /* stop dma + irqs */
4303 spin_lock_irqsave(&btv->s_lock,flags);
4304 memset(&idle, 0, sizeof(idle));
4305 btv->state.video = btv->curr;
4306 btv->state.vbi = btv->cvbi;
4307 btv->state.loop_irq = btv->loop_irq;
4308 btv->curr = idle;
4309 btv->loop_irq = 0;
4310 bttv_buffer_activate_video(btv, &idle);
4311 bttv_buffer_activate_vbi(btv, NULL);
4312 bttv_set_dma(btv, 0);
4313 btwrite(0, BT848_INT_MASK);
4314 spin_unlock_irqrestore(&btv->s_lock,flags);
4315
4316 /* save bt878 state */
4317 btv->state.gpio_enable = btread(BT848_GPIO_OUT_EN);
4318 btv->state.gpio_data = gpio_read();
4319
4320 /* save pci state */
4321 pci_save_state(pci_dev);
4322 if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
4323 pci_disable_device(pci_dev);
4324 btv->state.disabled = 1;
4325 }
4326 return 0;
4327}
4328
4329static int bttv_resume(struct pci_dev *pci_dev)
4330{
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004331 struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
4332 struct bttv *btv = to_bttv(v4l2_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004333 unsigned long flags;
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004334 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004335
Joe Perches8af443e2011-08-21 19:56:48 -03004336 dprintk("%d: resume\n", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004337
4338 /* restore pci state */
4339 if (btv->state.disabled) {
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004340 err=pci_enable_device(pci_dev);
4341 if (err) {
Joe Perches8af443e2011-08-21 19:56:48 -03004342 pr_warn("%d: Can't enable device\n", btv->c.nr);
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004343 return err;
4344 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004345 btv->state.disabled = 0;
4346 }
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004347 err=pci_set_power_state(pci_dev, PCI_D0);
4348 if (err) {
4349 pci_disable_device(pci_dev);
Joe Perches8af443e2011-08-21 19:56:48 -03004350 pr_warn("%d: Can't enable device\n", btv->c.nr);
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004351 btv->state.disabled = 1;
4352 return err;
4353 }
4354
Linus Torvalds1da177e2005-04-16 15:20:36 -07004355 pci_restore_state(pci_dev);
4356
4357 /* restore bt878 state */
4358 bttv_reinit_bt848(btv);
4359 gpio_inout(0xffffff, btv->state.gpio_enable);
4360 gpio_write(btv->state.gpio_data);
4361
4362 /* restart dma */
4363 spin_lock_irqsave(&btv->s_lock,flags);
4364 btv->curr = btv->state.video;
4365 btv->cvbi = btv->state.vbi;
4366 btv->loop_irq = btv->state.loop_irq;
4367 bttv_buffer_activate_video(btv, &btv->curr);
4368 bttv_buffer_activate_vbi(btv, btv->cvbi);
4369 bttv_set_dma(btv, 0);
4370 spin_unlock_irqrestore(&btv->s_lock,flags);
4371 return 0;
4372}
Alexey Dobriyan17bc98a2006-08-12 22:01:27 -03004373#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07004374
4375static struct pci_device_id bttv_pci_tbl[] = {
Joe Perches76e97412009-07-05 15:59:21 -03004376 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT848), 0},
4377 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT849), 0},
4378 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT878), 0},
4379 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT879), 0},
Peter De Schrijverc540d9f2011-11-06 10:47:58 -03004380 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_FUSION879), 0},
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004381 {0,}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004382};
4383
4384MODULE_DEVICE_TABLE(pci, bttv_pci_tbl);
4385
4386static struct pci_driver bttv_pci_driver = {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004387 .name = "bttv",
4388 .id_table = bttv_pci_tbl,
4389 .probe = bttv_probe,
Greg Kroah-Hartman4c62e972012-12-21 13:17:53 -08004390 .remove = bttv_remove,
Alexey Dobriyan17bc98a2006-08-12 22:01:27 -03004391#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -07004392 .suspend = bttv_suspend,
4393 .resume = bttv_resume,
Alexey Dobriyan17bc98a2006-08-12 22:01:27 -03004394#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07004395};
4396
Adrian Bunk7d44e892007-12-11 19:23:43 -03004397static int __init bttv_init_module(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398{
Randy Dunlapc526e222006-07-15 09:08:26 -03004399 int ret;
4400
Linus Torvalds1da177e2005-04-16 15:20:36 -07004401 bttv_num = 0;
4402
Joe Perches8af443e2011-08-21 19:56:48 -03004403 pr_info("driver version %s loaded\n", BTTV_VERSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004404 if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME)
4405 gbuffers = 2;
Filipe Rossetf41b6962009-05-28 11:11:53 -03004406 if (gbufsize > BTTV_MAX_FBUF)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004407 gbufsize = BTTV_MAX_FBUF;
4408 gbufsize = (gbufsize + PAGE_SIZE - 1) & PAGE_MASK;
4409 if (bttv_verbose)
Joe Perches8af443e2011-08-21 19:56:48 -03004410 pr_info("using %d buffers with %dk (%d pages) each for capture\n",
4411 gbuffers, gbufsize >> 10, gbufsize >> PAGE_SHIFT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004412
4413 bttv_check_chipset();
4414
Randy Dunlapc526e222006-07-15 09:08:26 -03004415 ret = bus_register(&bttv_sub_bus_type);
4416 if (ret < 0) {
Joe Perches8af443e2011-08-21 19:56:48 -03004417 pr_warn("bus_register error: %d\n", ret);
Randy Dunlapc526e222006-07-15 09:08:26 -03004418 return ret;
4419 }
Akinobu Mita9e7e85e2007-12-17 14:26:29 -03004420 ret = pci_register_driver(&bttv_pci_driver);
4421 if (ret < 0)
4422 bus_unregister(&bttv_sub_bus_type);
4423
4424 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004425}
4426
Adrian Bunk7d44e892007-12-11 19:23:43 -03004427static void __exit bttv_cleanup_module(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004428{
4429 pci_unregister_driver(&bttv_pci_driver);
4430 bus_unregister(&bttv_sub_bus_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004431}
4432
4433module_init(bttv_init_module);
4434module_exit(bttv_cleanup_module);