blob: 76c301f05095375ec21d6956d00a9d69f8b33da6 [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 Verkuil8bf2f8e2006-03-18 21:31:00 -030052#include <media/tvaudio.h>
Hans Verkuil2474ed42006-03-19 12:35:57 -030053#include <media/msp3400.h>
Mauro Carvalho Chehabb5b8ab82006-01-09 15:25:20 -020054
Mauro Carvalho Chehabfa9846a2005-07-12 13:58:42 -070055#include <linux/dma-mapping.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070056
57#include <asm/io.h>
58#include <asm/byteorder.h>
59
Hans Verkuilb9218f22010-12-27 12:22:46 -030060#include <media/saa6588.h>
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -070061
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -030062#define BTTV_VERSION "0.9.19"
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -070063
Linus Torvalds1da177e2005-04-16 15:20:36 -070064unsigned int bttv_num; /* number of Bt848s in use */
Trent Piepho4b10d3b2009-01-28 21:32:59 -030065struct bttv *bttvs[BTTV_MAX];
Linus Torvalds1da177e2005-04-16 15:20:36 -070066
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020067unsigned int bttv_debug;
Linus Torvalds1da177e2005-04-16 15:20:36 -070068unsigned int bttv_verbose = 1;
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020069unsigned int bttv_gpio;
Linus Torvalds1da177e2005-04-16 15:20:36 -070070
71/* config variables */
72#ifdef __BIG_ENDIAN
73static unsigned int bigendian=1;
74#else
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020075static unsigned int bigendian;
Linus Torvalds1da177e2005-04-16 15:20:36 -070076#endif
77static unsigned int radio[BTTV_MAX];
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020078static unsigned int irq_debug;
Linus Torvalds1da177e2005-04-16 15:20:36 -070079static unsigned int gbuffers = 8;
80static unsigned int gbufsize = 0x208000;
Michael Schimeke5bd0262007-01-18 16:17:39 -030081static unsigned int reset_crop = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -070082
Jean Delvare176c2f32008-09-07 12:49:59 -030083static int video_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
84static int radio_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
85static int vbi_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020086static int debug_latency;
Jean Delvared90a4ae2010-02-16 14:22:37 -030087static int disable_ir;
Linus Torvalds1da177e2005-04-16 15:20:36 -070088
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020089static unsigned int fdsr;
Linus Torvalds1da177e2005-04-16 15:20:36 -070090
91/* options */
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020092static unsigned int combfilter;
93static unsigned int lumafilter;
Linus Torvalds1da177e2005-04-16 15:20:36 -070094static unsigned int automute = 1;
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020095static unsigned int chroma_agc;
Linus Torvalds1da177e2005-04-16 15:20:36 -070096static unsigned int adc_crush = 1;
97static unsigned int whitecrush_upper = 0xCF;
98static unsigned int whitecrush_lower = 0x7F;
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020099static unsigned int vcr_hack;
100static unsigned int irq_iswitch;
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700101static unsigned int uv_ratio = 50;
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -0200102static unsigned int full_luma_range;
103static unsigned int coring;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104
105/* API features (turn on/off stuff for testing) */
106static unsigned int v4l2 = 1;
107
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108/* insmod args */
109module_param(bttv_verbose, int, 0644);
110module_param(bttv_gpio, int, 0644);
111module_param(bttv_debug, int, 0644);
112module_param(irq_debug, int, 0644);
113module_param(debug_latency, int, 0644);
Jean Delvared90a4ae2010-02-16 14:22:37 -0300114module_param(disable_ir, int, 0444);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115
116module_param(fdsr, int, 0444);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117module_param(gbuffers, int, 0444);
118module_param(gbufsize, int, 0444);
Michael Schimeke5bd0262007-01-18 16:17:39 -0300119module_param(reset_crop, int, 0444);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120
121module_param(v4l2, int, 0644);
122module_param(bigendian, int, 0644);
123module_param(irq_iswitch, int, 0644);
124module_param(combfilter, int, 0444);
125module_param(lumafilter, int, 0444);
126module_param(automute, int, 0444);
127module_param(chroma_agc, int, 0444);
128module_param(adc_crush, int, 0444);
129module_param(whitecrush_upper, int, 0444);
130module_param(whitecrush_lower, int, 0444);
131module_param(vcr_hack, int, 0444);
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700132module_param(uv_ratio, int, 0444);
133module_param(full_luma_range, int, 0444);
134module_param(coring, int, 0444);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135
Jean Delvare176c2f32008-09-07 12:49:59 -0300136module_param_array(radio, int, NULL, 0444);
137module_param_array(video_nr, int, NULL, 0444);
138module_param_array(radio_nr, int, NULL, 0444);
139module_param_array(vbi_nr, int, NULL, 0444);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140
141MODULE_PARM_DESC(radio,"The TV card supports radio, default is 0 (no)");
142MODULE_PARM_DESC(bigendian,"byte order of the framebuffer, default is native endian");
143MODULE_PARM_DESC(bttv_verbose,"verbose startup messages, default is 1 (yes)");
144MODULE_PARM_DESC(bttv_gpio,"log gpio changes, default is 0 (no)");
145MODULE_PARM_DESC(bttv_debug,"debug messages, default is 0 (no)");
146MODULE_PARM_DESC(irq_debug,"irq handler debug messages, default is 0 (no)");
Jean Delvared90a4ae2010-02-16 14:22:37 -0300147MODULE_PARM_DESC(disable_ir, "disable infrared remote support");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148MODULE_PARM_DESC(gbuffers,"number of capture buffers. range 2-32, default 8");
149MODULE_PARM_DESC(gbufsize,"size of the capture buffers, default is 0x208000");
Michael Schimeke5bd0262007-01-18 16:17:39 -0300150MODULE_PARM_DESC(reset_crop,"reset cropping parameters at open(), default "
151 "is 1 (yes) for compatibility with older applications");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152MODULE_PARM_DESC(automute,"mute audio on bad/missing video signal, default is 1 (yes)");
153MODULE_PARM_DESC(chroma_agc,"enables the AGC of chroma signal, default is 0 (no)");
154MODULE_PARM_DESC(adc_crush,"enables the luminance ADC crush, default is 1 (yes)");
155MODULE_PARM_DESC(whitecrush_upper,"sets the white crush upper value, default is 207");
156MODULE_PARM_DESC(whitecrush_lower,"sets the white crush lower value, default is 127");
157MODULE_PARM_DESC(vcr_hack,"enables the VCR hack (improves synch on poor VCR tapes), default is 0 (no)");
158MODULE_PARM_DESC(irq_iswitch,"switch inputs in irq handler");
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700159MODULE_PARM_DESC(uv_ratio,"ratio between u and v gains, default is 50");
160MODULE_PARM_DESC(full_luma_range,"use the full luma range, default is 0 (no)");
161MODULE_PARM_DESC(coring,"set the luma coring level, default is 0 (no)");
Jean Delvare176c2f32008-09-07 12:49:59 -0300162MODULE_PARM_DESC(video_nr, "video device numbers");
163MODULE_PARM_DESC(vbi_nr, "vbi device numbers");
164MODULE_PARM_DESC(radio_nr, "radio device numbers");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165
166MODULE_DESCRIPTION("bttv - v4l/v4l2 driver module for bt848/878 based cards");
167MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr");
168MODULE_LICENSE("GPL");
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -0300169MODULE_VERSION(BTTV_VERSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170
171/* ----------------------------------------------------------------------- */
172/* sysfs */
173
Kay Sievers54bd5b62007-10-08 16:26:13 -0300174static ssize_t show_card(struct device *cd,
175 struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176{
Hans Verkuil22a04f12008-07-20 06:35:02 -0300177 struct video_device *vfd = container_of(cd, struct video_device, dev);
Hans Verkuil74fc7bd2009-03-14 12:36:54 -0300178 struct bttv *btv = video_get_drvdata(vfd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179 return sprintf(buf, "%d\n", btv ? btv->c.type : UNSET);
180}
Kay Sievers54bd5b62007-10-08 16:26:13 -0300181static DEVICE_ATTR(card, S_IRUGO, show_card, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182
183/* ----------------------------------------------------------------------- */
Jarod Wilsonf992a492007-03-24 15:23:50 -0300184/* dvb auto-load setup */
185#if defined(CONFIG_MODULES) && defined(MODULE)
186static void request_module_async(struct work_struct *work)
187{
188 request_module("dvb-bt8xx");
189}
190
191static void request_modules(struct bttv *dev)
192{
193 INIT_WORK(&dev->request_module_wk, request_module_async);
194 schedule_work(&dev->request_module_wk);
195}
Tejun Heo707bcf32010-12-24 16:14:20 +0100196
197static void flush_request_modules(struct bttv *dev)
198{
199 flush_work_sync(&dev->request_module_wk);
200}
Jarod Wilsonf992a492007-03-24 15:23:50 -0300201#else
202#define request_modules(dev)
Tejun Heo707bcf32010-12-24 16:14:20 +0100203#define flush_request_modules(dev)
Jarod Wilsonf992a492007-03-24 15:23:50 -0300204#endif /* CONFIG_MODULES */
205
206
207/* ----------------------------------------------------------------------- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208/* static data */
209
210/* special timing tables from conexant... */
211static u8 SRAM_Table[][60] =
212{
213 /* PAL digital input over GPIO[7:0] */
214 {
215 45, // 45 bytes following
216 0x36,0x11,0x01,0x00,0x90,0x02,0x05,0x10,0x04,0x16,
217 0x12,0x05,0x11,0x00,0x04,0x12,0xC0,0x00,0x31,0x00,
218 0x06,0x51,0x08,0x03,0x89,0x08,0x07,0xC0,0x44,0x00,
219 0x81,0x01,0x01,0xA9,0x0D,0x02,0x02,0x50,0x03,0x37,
220 0x37,0x00,0xAF,0x21,0x00
221 },
222 /* NTSC digital input over GPIO[7:0] */
223 {
224 51, // 51 bytes following
225 0x0C,0xC0,0x00,0x00,0x90,0x02,0x03,0x10,0x03,0x06,
226 0x10,0x04,0x12,0x12,0x05,0x02,0x13,0x04,0x19,0x00,
227 0x04,0x39,0x00,0x06,0x59,0x08,0x03,0x83,0x08,0x07,
228 0x03,0x50,0x00,0xC0,0x40,0x00,0x86,0x01,0x01,0xA6,
229 0x0D,0x02,0x03,0x11,0x01,0x05,0x37,0x00,0xAC,0x21,
230 0x00,
231 },
232 // TGB_NTSC392 // quartzsight
233 // This table has been modified to be used for Fusion Rev D
234 {
235 0x2A, // size of table = 42
236 0x06, 0x08, 0x04, 0x0a, 0xc0, 0x00, 0x18, 0x08, 0x03, 0x24,
237 0x08, 0x07, 0x02, 0x90, 0x02, 0x08, 0x10, 0x04, 0x0c, 0x10,
238 0x05, 0x2c, 0x11, 0x04, 0x55, 0x48, 0x00, 0x05, 0x50, 0x00,
239 0xbf, 0x0c, 0x02, 0x2f, 0x3d, 0x00, 0x2f, 0x3f, 0x00, 0xc3,
240 0x20, 0x00
241 }
242};
243
Michael Schimeke5bd0262007-01-18 16:17:39 -0300244/* minhdelayx1 first video pixel we can capture on a line and
245 hdelayx1 start of active video, both relative to rising edge of
246 /HRESET pulse (0H) in 1 / fCLKx1.
247 swidth width of active video and
248 totalwidth total line width, both in 1 / fCLKx1.
249 sqwidth total line width in square pixels.
250 vdelay start of active video in 2 * field lines relative to
251 trailing edge of /VRESET pulse (VDELAY register).
252 sheight height of active video in 2 * field lines.
253 videostart0 ITU-R frame line number of the line corresponding
254 to vdelay in the first field. */
255#define CROPCAP(minhdelayx1, hdelayx1, swidth, totalwidth, sqwidth, \
256 vdelay, sheight, videostart0) \
257 .cropcap.bounds.left = minhdelayx1, \
258 /* * 2 because vertically we count field lines times two, */ \
259 /* e.g. 23 * 2 to 23 * 2 + 576 in PAL-BGHI defrect. */ \
260 .cropcap.bounds.top = (videostart0) * 2 - (vdelay) + MIN_VDELAY, \
261 /* 4 is a safety margin at the end of the line. */ \
262 .cropcap.bounds.width = (totalwidth) - (minhdelayx1) - 4, \
263 .cropcap.bounds.height = (sheight) + (vdelay) - MIN_VDELAY, \
264 .cropcap.defrect.left = hdelayx1, \
265 .cropcap.defrect.top = (videostart0) * 2, \
266 .cropcap.defrect.width = swidth, \
267 .cropcap.defrect.height = sheight, \
268 .cropcap.pixelaspect.numerator = totalwidth, \
269 .cropcap.pixelaspect.denominator = sqwidth,
270
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271const struct bttv_tvnorm bttv_tvnorms[] = {
272 /* PAL-BDGHI */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800273 /* max. active video is actually 922, but 924 is divisible by 4 and 3! */
274 /* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 {
276 .v4l2_id = V4L2_STD_PAL,
277 .name = "PAL",
278 .Fsc = 35468950,
279 .swidth = 924,
280 .sheight = 576,
281 .totalwidth = 1135,
282 .adelay = 0x7f,
283 .bdelay = 0x72,
284 .iform = (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
285 .scaledtwidth = 1135,
286 .hdelayx1 = 186,
287 .hactivex1 = 924,
288 .vdelay = 0x20,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300289 .vbipack = 255, /* min (2048 / 4, 0x1ff) & 0xff */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 .sram = 0,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200291 /* ITU-R frame line number of the first VBI line
Michael Schimeke5bd0262007-01-18 16:17:39 -0300292 we can capture, of the first and second field.
293 The last line is determined by cropcap.bounds. */
294 .vbistart = { 7, 320 },
295 CROPCAP(/* minhdelayx1 */ 68,
296 /* hdelayx1 */ 186,
297 /* Should be (768 * 1135 + 944 / 2) / 944.
298 cropcap.defrect is used for image width
299 checks, so we keep the old value 924. */
300 /* swidth */ 924,
301 /* totalwidth */ 1135,
302 /* sqwidth */ 944,
303 /* vdelay */ 0x20,
304 /* sheight */ 576,
305 /* videostart0 */ 23)
306 /* bt878 (and bt848?) can capture another
307 line below active video. */
308 .cropcap.bounds.height = (576 + 2) + 0x20 - 2,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309 },{
Hans Verkuild97a11e2006-02-07 06:48:40 -0200310 .v4l2_id = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 .name = "NTSC",
312 .Fsc = 28636363,
313 .swidth = 768,
314 .sheight = 480,
315 .totalwidth = 910,
316 .adelay = 0x68,
317 .bdelay = 0x5d,
318 .iform = (BT848_IFORM_NTSC|BT848_IFORM_XT0),
319 .scaledtwidth = 910,
320 .hdelayx1 = 128,
321 .hactivex1 = 910,
322 .vdelay = 0x1a,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300323 .vbipack = 144, /* min (1600 / 4, 0x1ff) & 0xff */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 .sram = 1,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200325 .vbistart = { 10, 273 },
Michael Schimeke5bd0262007-01-18 16:17:39 -0300326 CROPCAP(/* minhdelayx1 */ 68,
327 /* hdelayx1 */ 128,
328 /* Should be (640 * 910 + 780 / 2) / 780? */
329 /* swidth */ 768,
330 /* totalwidth */ 910,
331 /* sqwidth */ 780,
332 /* vdelay */ 0x1a,
333 /* sheight */ 480,
334 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335 },{
336 .v4l2_id = V4L2_STD_SECAM,
337 .name = "SECAM",
338 .Fsc = 35468950,
339 .swidth = 924,
340 .sheight = 576,
341 .totalwidth = 1135,
342 .adelay = 0x7f,
343 .bdelay = 0xb0,
344 .iform = (BT848_IFORM_SECAM|BT848_IFORM_XT1),
345 .scaledtwidth = 1135,
346 .hdelayx1 = 186,
347 .hactivex1 = 922,
348 .vdelay = 0x20,
349 .vbipack = 255,
350 .sram = 0, /* like PAL, correct? */
Michael H. Schimek67f15702006-01-09 15:25:27 -0200351 .vbistart = { 7, 320 },
Michael Schimeke5bd0262007-01-18 16:17:39 -0300352 CROPCAP(/* minhdelayx1 */ 68,
353 /* hdelayx1 */ 186,
354 /* swidth */ 924,
355 /* totalwidth */ 1135,
356 /* sqwidth */ 944,
357 /* vdelay */ 0x20,
358 /* sheight */ 576,
359 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 },{
361 .v4l2_id = V4L2_STD_PAL_Nc,
362 .name = "PAL-Nc",
363 .Fsc = 28636363,
364 .swidth = 640,
365 .sheight = 576,
366 .totalwidth = 910,
367 .adelay = 0x68,
368 .bdelay = 0x5d,
369 .iform = (BT848_IFORM_PAL_NC|BT848_IFORM_XT0),
370 .scaledtwidth = 780,
371 .hdelayx1 = 130,
372 .hactivex1 = 734,
373 .vdelay = 0x1a,
374 .vbipack = 144,
375 .sram = -1,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200376 .vbistart = { 7, 320 },
Michael Schimeke5bd0262007-01-18 16:17:39 -0300377 CROPCAP(/* minhdelayx1 */ 68,
378 /* hdelayx1 */ 130,
379 /* swidth */ (640 * 910 + 780 / 2) / 780,
380 /* totalwidth */ 910,
381 /* sqwidth */ 780,
382 /* vdelay */ 0x1a,
383 /* sheight */ 576,
384 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 },{
386 .v4l2_id = V4L2_STD_PAL_M,
387 .name = "PAL-M",
388 .Fsc = 28636363,
389 .swidth = 640,
390 .sheight = 480,
391 .totalwidth = 910,
392 .adelay = 0x68,
393 .bdelay = 0x5d,
394 .iform = (BT848_IFORM_PAL_M|BT848_IFORM_XT0),
395 .scaledtwidth = 780,
396 .hdelayx1 = 135,
397 .hactivex1 = 754,
398 .vdelay = 0x1a,
399 .vbipack = 144,
400 .sram = -1,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200401 .vbistart = { 10, 273 },
Michael Schimeke5bd0262007-01-18 16:17:39 -0300402 CROPCAP(/* minhdelayx1 */ 68,
403 /* hdelayx1 */ 135,
404 /* swidth */ (640 * 910 + 780 / 2) / 780,
405 /* totalwidth */ 910,
406 /* sqwidth */ 780,
407 /* vdelay */ 0x1a,
408 /* sheight */ 480,
409 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 },{
411 .v4l2_id = V4L2_STD_PAL_N,
412 .name = "PAL-N",
413 .Fsc = 35468950,
414 .swidth = 768,
415 .sheight = 576,
416 .totalwidth = 1135,
417 .adelay = 0x7f,
418 .bdelay = 0x72,
419 .iform = (BT848_IFORM_PAL_N|BT848_IFORM_XT1),
420 .scaledtwidth = 944,
421 .hdelayx1 = 186,
422 .hactivex1 = 922,
423 .vdelay = 0x20,
424 .vbipack = 144,
425 .sram = -1,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300426 .vbistart = { 7, 320 },
427 CROPCAP(/* minhdelayx1 */ 68,
428 /* hdelayx1 */ 186,
429 /* swidth */ (768 * 1135 + 944 / 2) / 944,
430 /* totalwidth */ 1135,
431 /* sqwidth */ 944,
432 /* vdelay */ 0x20,
433 /* sheight */ 576,
434 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 },{
436 .v4l2_id = V4L2_STD_NTSC_M_JP,
437 .name = "NTSC-JP",
438 .Fsc = 28636363,
439 .swidth = 640,
440 .sheight = 480,
441 .totalwidth = 910,
442 .adelay = 0x68,
443 .bdelay = 0x5d,
444 .iform = (BT848_IFORM_NTSC_J|BT848_IFORM_XT0),
445 .scaledtwidth = 780,
446 .hdelayx1 = 135,
447 .hactivex1 = 754,
448 .vdelay = 0x16,
449 .vbipack = 144,
450 .sram = -1,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300451 .vbistart = { 10, 273 },
452 CROPCAP(/* minhdelayx1 */ 68,
453 /* hdelayx1 */ 135,
454 /* swidth */ (640 * 910 + 780 / 2) / 780,
455 /* totalwidth */ 910,
456 /* sqwidth */ 780,
457 /* vdelay */ 0x16,
458 /* sheight */ 480,
459 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 },{
461 /* that one hopefully works with the strange timing
462 * which video recorders produce when playing a NTSC
463 * tape on a PAL TV ... */
464 .v4l2_id = V4L2_STD_PAL_60,
465 .name = "PAL-60",
466 .Fsc = 35468950,
467 .swidth = 924,
468 .sheight = 480,
469 .totalwidth = 1135,
470 .adelay = 0x7f,
471 .bdelay = 0x72,
472 .iform = (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
473 .scaledtwidth = 1135,
474 .hdelayx1 = 186,
475 .hactivex1 = 924,
476 .vdelay = 0x1a,
477 .vbipack = 255,
478 .vtotal = 524,
479 .sram = -1,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200480 .vbistart = { 10, 273 },
Michael Schimeke5bd0262007-01-18 16:17:39 -0300481 CROPCAP(/* minhdelayx1 */ 68,
482 /* hdelayx1 */ 186,
483 /* swidth */ 924,
484 /* totalwidth */ 1135,
485 /* sqwidth */ 944,
486 /* vdelay */ 0x1a,
487 /* sheight */ 480,
488 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 }
490};
491static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms);
492
493/* ----------------------------------------------------------------------- */
494/* bttv format list
495 packed pixel formats must come first */
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -0300496static const struct bttv_format formats[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 {
498 .name = "8 bpp, gray",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 .fourcc = V4L2_PIX_FMT_GREY,
500 .btformat = BT848_COLOR_FMT_Y8,
501 .depth = 8,
502 .flags = FORMAT_FLAGS_PACKED,
503 },{
504 .name = "8 bpp, dithered color",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 .fourcc = V4L2_PIX_FMT_HI240,
506 .btformat = BT848_COLOR_FMT_RGB8,
507 .depth = 8,
508 .flags = FORMAT_FLAGS_PACKED | FORMAT_FLAGS_DITHER,
509 },{
510 .name = "15 bpp RGB, le",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511 .fourcc = V4L2_PIX_FMT_RGB555,
512 .btformat = BT848_COLOR_FMT_RGB15,
513 .depth = 16,
514 .flags = FORMAT_FLAGS_PACKED,
515 },{
516 .name = "15 bpp RGB, be",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 .fourcc = V4L2_PIX_FMT_RGB555X,
518 .btformat = BT848_COLOR_FMT_RGB15,
519 .btswap = 0x03, /* byteswap */
520 .depth = 16,
521 .flags = FORMAT_FLAGS_PACKED,
522 },{
523 .name = "16 bpp RGB, le",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 .fourcc = V4L2_PIX_FMT_RGB565,
525 .btformat = BT848_COLOR_FMT_RGB16,
526 .depth = 16,
527 .flags = FORMAT_FLAGS_PACKED,
528 },{
529 .name = "16 bpp RGB, be",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 .fourcc = V4L2_PIX_FMT_RGB565X,
531 .btformat = BT848_COLOR_FMT_RGB16,
532 .btswap = 0x03, /* byteswap */
533 .depth = 16,
534 .flags = FORMAT_FLAGS_PACKED,
535 },{
536 .name = "24 bpp RGB, le",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 .fourcc = V4L2_PIX_FMT_BGR24,
538 .btformat = BT848_COLOR_FMT_RGB24,
539 .depth = 24,
540 .flags = FORMAT_FLAGS_PACKED,
541 },{
542 .name = "32 bpp RGB, le",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 .fourcc = V4L2_PIX_FMT_BGR32,
544 .btformat = BT848_COLOR_FMT_RGB32,
545 .depth = 32,
546 .flags = FORMAT_FLAGS_PACKED,
547 },{
548 .name = "32 bpp RGB, be",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 .fourcc = V4L2_PIX_FMT_RGB32,
550 .btformat = BT848_COLOR_FMT_RGB32,
551 .btswap = 0x0f, /* byte+word swap */
552 .depth = 32,
553 .flags = FORMAT_FLAGS_PACKED,
554 },{
555 .name = "4:2:2, packed, YUYV",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 .fourcc = V4L2_PIX_FMT_YUYV,
557 .btformat = BT848_COLOR_FMT_YUY2,
558 .depth = 16,
559 .flags = FORMAT_FLAGS_PACKED,
560 },{
561 .name = "4:2:2, packed, YUYV",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 .fourcc = V4L2_PIX_FMT_YUYV,
563 .btformat = BT848_COLOR_FMT_YUY2,
564 .depth = 16,
565 .flags = FORMAT_FLAGS_PACKED,
566 },{
567 .name = "4:2:2, packed, UYVY",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568 .fourcc = V4L2_PIX_FMT_UYVY,
569 .btformat = BT848_COLOR_FMT_YUY2,
570 .btswap = 0x03, /* byteswap */
571 .depth = 16,
572 .flags = FORMAT_FLAGS_PACKED,
573 },{
574 .name = "4:2:2, planar, Y-Cb-Cr",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 .fourcc = V4L2_PIX_FMT_YUV422P,
576 .btformat = BT848_COLOR_FMT_YCrCb422,
577 .depth = 16,
578 .flags = FORMAT_FLAGS_PLANAR,
579 .hshift = 1,
580 .vshift = 0,
581 },{
582 .name = "4:2:0, planar, Y-Cb-Cr",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 .fourcc = V4L2_PIX_FMT_YUV420,
584 .btformat = BT848_COLOR_FMT_YCrCb422,
585 .depth = 12,
586 .flags = FORMAT_FLAGS_PLANAR,
587 .hshift = 1,
588 .vshift = 1,
589 },{
590 .name = "4:2:0, planar, Y-Cr-Cb",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 .fourcc = V4L2_PIX_FMT_YVU420,
592 .btformat = BT848_COLOR_FMT_YCrCb422,
593 .depth = 12,
594 .flags = FORMAT_FLAGS_PLANAR | FORMAT_FLAGS_CrCb,
595 .hshift = 1,
596 .vshift = 1,
597 },{
598 .name = "4:1:1, planar, Y-Cb-Cr",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599 .fourcc = V4L2_PIX_FMT_YUV411P,
600 .btformat = BT848_COLOR_FMT_YCrCb411,
601 .depth = 12,
602 .flags = FORMAT_FLAGS_PLANAR,
603 .hshift = 2,
604 .vshift = 0,
605 },{
606 .name = "4:1:0, planar, Y-Cb-Cr",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 .fourcc = V4L2_PIX_FMT_YUV410,
608 .btformat = BT848_COLOR_FMT_YCrCb411,
609 .depth = 9,
610 .flags = FORMAT_FLAGS_PLANAR,
611 .hshift = 2,
612 .vshift = 2,
613 },{
614 .name = "4:1:0, planar, Y-Cr-Cb",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 .fourcc = V4L2_PIX_FMT_YVU410,
616 .btformat = BT848_COLOR_FMT_YCrCb411,
617 .depth = 9,
618 .flags = FORMAT_FLAGS_PLANAR | FORMAT_FLAGS_CrCb,
619 .hshift = 2,
620 .vshift = 2,
621 },{
622 .name = "raw scanlines",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 .fourcc = -1,
624 .btformat = BT848_COLOR_FMT_RAW,
625 .depth = 8,
626 .flags = FORMAT_FLAGS_RAW,
627 }
628};
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -0300629static const unsigned int FORMATS = ARRAY_SIZE(formats);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630
631/* ----------------------------------------------------------------------- */
632
633#define V4L2_CID_PRIVATE_CHROMA_AGC (V4L2_CID_PRIVATE_BASE + 0)
634#define V4L2_CID_PRIVATE_COMBFILTER (V4L2_CID_PRIVATE_BASE + 1)
635#define V4L2_CID_PRIVATE_AUTOMUTE (V4L2_CID_PRIVATE_BASE + 2)
636#define V4L2_CID_PRIVATE_LUMAFILTER (V4L2_CID_PRIVATE_BASE + 3)
637#define V4L2_CID_PRIVATE_AGC_CRUSH (V4L2_CID_PRIVATE_BASE + 4)
638#define V4L2_CID_PRIVATE_VCR_HACK (V4L2_CID_PRIVATE_BASE + 5)
639#define V4L2_CID_PRIVATE_WHITECRUSH_UPPER (V4L2_CID_PRIVATE_BASE + 6)
640#define V4L2_CID_PRIVATE_WHITECRUSH_LOWER (V4L2_CID_PRIVATE_BASE + 7)
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700641#define V4L2_CID_PRIVATE_UV_RATIO (V4L2_CID_PRIVATE_BASE + 8)
642#define V4L2_CID_PRIVATE_FULL_LUMA_RANGE (V4L2_CID_PRIVATE_BASE + 9)
643#define V4L2_CID_PRIVATE_CORING (V4L2_CID_PRIVATE_BASE + 10)
644#define V4L2_CID_PRIVATE_LASTP1 (V4L2_CID_PRIVATE_BASE + 11)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645
646static const struct v4l2_queryctrl no_ctl = {
647 .name = "42",
648 .flags = V4L2_CTRL_FLAG_DISABLED,
649};
650static const struct v4l2_queryctrl bttv_ctls[] = {
651 /* --- video --- */
652 {
653 .id = V4L2_CID_BRIGHTNESS,
654 .name = "Brightness",
655 .minimum = 0,
656 .maximum = 65535,
657 .step = 256,
658 .default_value = 32768,
659 .type = V4L2_CTRL_TYPE_INTEGER,
660 },{
661 .id = V4L2_CID_CONTRAST,
662 .name = "Contrast",
663 .minimum = 0,
664 .maximum = 65535,
665 .step = 128,
666 .default_value = 32768,
667 .type = V4L2_CTRL_TYPE_INTEGER,
668 },{
669 .id = V4L2_CID_SATURATION,
670 .name = "Saturation",
671 .minimum = 0,
672 .maximum = 65535,
673 .step = 128,
674 .default_value = 32768,
675 .type = V4L2_CTRL_TYPE_INTEGER,
676 },{
677 .id = V4L2_CID_HUE,
678 .name = "Hue",
679 .minimum = 0,
680 .maximum = 65535,
681 .step = 256,
682 .default_value = 32768,
683 .type = V4L2_CTRL_TYPE_INTEGER,
684 },
685 /* --- audio --- */
686 {
687 .id = V4L2_CID_AUDIO_MUTE,
688 .name = "Mute",
689 .minimum = 0,
690 .maximum = 1,
691 .type = V4L2_CTRL_TYPE_BOOLEAN,
692 },{
693 .id = V4L2_CID_AUDIO_VOLUME,
694 .name = "Volume",
695 .minimum = 0,
696 .maximum = 65535,
697 .step = 65535/100,
698 .default_value = 65535,
699 .type = V4L2_CTRL_TYPE_INTEGER,
700 },{
701 .id = V4L2_CID_AUDIO_BALANCE,
702 .name = "Balance",
703 .minimum = 0,
704 .maximum = 65535,
705 .step = 65535/100,
706 .default_value = 32768,
707 .type = V4L2_CTRL_TYPE_INTEGER,
708 },{
709 .id = V4L2_CID_AUDIO_BASS,
710 .name = "Bass",
711 .minimum = 0,
712 .maximum = 65535,
713 .step = 65535/100,
714 .default_value = 32768,
715 .type = V4L2_CTRL_TYPE_INTEGER,
716 },{
717 .id = V4L2_CID_AUDIO_TREBLE,
718 .name = "Treble",
719 .minimum = 0,
720 .maximum = 65535,
721 .step = 65535/100,
722 .default_value = 32768,
723 .type = V4L2_CTRL_TYPE_INTEGER,
724 },
725 /* --- private --- */
726 {
727 .id = V4L2_CID_PRIVATE_CHROMA_AGC,
728 .name = "chroma agc",
729 .minimum = 0,
730 .maximum = 1,
731 .type = V4L2_CTRL_TYPE_BOOLEAN,
732 },{
733 .id = V4L2_CID_PRIVATE_COMBFILTER,
734 .name = "combfilter",
735 .minimum = 0,
736 .maximum = 1,
737 .type = V4L2_CTRL_TYPE_BOOLEAN,
738 },{
739 .id = V4L2_CID_PRIVATE_AUTOMUTE,
740 .name = "automute",
741 .minimum = 0,
742 .maximum = 1,
743 .type = V4L2_CTRL_TYPE_BOOLEAN,
744 },{
745 .id = V4L2_CID_PRIVATE_LUMAFILTER,
746 .name = "luma decimation filter",
747 .minimum = 0,
748 .maximum = 1,
749 .type = V4L2_CTRL_TYPE_BOOLEAN,
750 },{
751 .id = V4L2_CID_PRIVATE_AGC_CRUSH,
752 .name = "agc crush",
753 .minimum = 0,
754 .maximum = 1,
755 .type = V4L2_CTRL_TYPE_BOOLEAN,
756 },{
757 .id = V4L2_CID_PRIVATE_VCR_HACK,
758 .name = "vcr hack",
759 .minimum = 0,
760 .maximum = 1,
761 .type = V4L2_CTRL_TYPE_BOOLEAN,
762 },{
763 .id = V4L2_CID_PRIVATE_WHITECRUSH_UPPER,
764 .name = "whitecrush upper",
765 .minimum = 0,
766 .maximum = 255,
767 .step = 1,
768 .default_value = 0xCF,
769 .type = V4L2_CTRL_TYPE_INTEGER,
770 },{
771 .id = V4L2_CID_PRIVATE_WHITECRUSH_LOWER,
772 .name = "whitecrush lower",
773 .minimum = 0,
774 .maximum = 255,
775 .step = 1,
776 .default_value = 0x7F,
777 .type = V4L2_CTRL_TYPE_INTEGER,
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700778 },{
779 .id = V4L2_CID_PRIVATE_UV_RATIO,
780 .name = "uv ratio",
781 .minimum = 0,
782 .maximum = 100,
783 .step = 1,
784 .default_value = 50,
785 .type = V4L2_CTRL_TYPE_INTEGER,
786 },{
787 .id = V4L2_CID_PRIVATE_FULL_LUMA_RANGE,
788 .name = "full luma range",
789 .minimum = 0,
790 .maximum = 1,
791 .type = V4L2_CTRL_TYPE_BOOLEAN,
792 },{
793 .id = V4L2_CID_PRIVATE_CORING,
794 .name = "coring",
795 .minimum = 0,
796 .maximum = 3,
797 .step = 1,
798 .default_value = 0,
799 .type = V4L2_CTRL_TYPE_INTEGER,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 }
801
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700802
803
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -0300806static const struct v4l2_queryctrl *ctrl_by_id(int id)
807{
808 int i;
809
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -0300810 for (i = 0; i < ARRAY_SIZE(bttv_ctls); i++)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -0300811 if (bttv_ctls[i].id == id)
812 return bttv_ctls+i;
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -0300813
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -0300814 return NULL;
815}
816
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817/* ----------------------------------------------------------------------- */
818/* resource management */
819
Michael Schimeke5bd0262007-01-18 16:17:39 -0300820/*
821 RESOURCE_ allocated by freed by
822
823 VIDEO_READ bttv_read 1) bttv_read 2)
824
825 VIDEO_STREAM VIDIOC_STREAMON VIDIOC_STREAMOFF
826 VIDIOC_QBUF 1) bttv_release
827 VIDIOCMCAPTURE 1)
828
829 OVERLAY VIDIOCCAPTURE on VIDIOCCAPTURE off
830 VIDIOC_OVERLAY on VIDIOC_OVERLAY off
831 3) bttv_release
832
833 VBI VIDIOC_STREAMON VIDIOC_STREAMOFF
834 VIDIOC_QBUF 1) bttv_release
835 bttv_read, bttv_poll 1) 4)
836
837 1) The resource must be allocated when we enter buffer prepare functions
838 and remain allocated while buffers are in the DMA queue.
839 2) This is a single frame read.
840 3) VIDIOC_S_FBUF and VIDIOC_S_FMT (OVERLAY) still work when
841 RESOURCE_OVERLAY is allocated.
842 4) This is a continuous read, implies VIDIOC_STREAMON.
843
844 Note this driver permits video input and standard changes regardless if
845 resources are allocated.
846*/
847
848#define VBI_RESOURCES (RESOURCE_VBI)
849#define VIDEO_RESOURCES (RESOURCE_VIDEO_READ | \
850 RESOURCE_VIDEO_STREAM | \
851 RESOURCE_OVERLAY)
852
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853static
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -0300854int check_alloc_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855{
Michael Schimeke5bd0262007-01-18 16:17:39 -0300856 int xbits; /* mutual exclusive resources */
857
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 if (fh->resources & bit)
859 /* have it already allocated */
860 return 1;
861
Michael Schimeke5bd0262007-01-18 16:17:39 -0300862 xbits = bit;
863 if (bit & (RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM))
864 xbits |= RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM;
865
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 /* is it free? */
Michael Schimeke5bd0262007-01-18 16:17:39 -0300867 if (btv->resources & xbits) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 /* no, someone else uses it */
Michael Schimeke5bd0262007-01-18 16:17:39 -0300869 goto fail;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 }
Michael Schimeke5bd0262007-01-18 16:17:39 -0300871
872 if ((bit & VIDEO_RESOURCES)
873 && 0 == (btv->resources & VIDEO_RESOURCES)) {
874 /* Do crop - use current, don't - use default parameters. */
875 __s32 top = btv->crop[!!fh->do_crop].rect.top;
876
877 if (btv->vbi_end > top)
878 goto fail;
879
880 /* We cannot capture the same line as video and VBI data.
881 Claim scan lines crop[].rect.top to bottom. */
882 btv->crop_start = top;
883 } else if (bit & VBI_RESOURCES) {
884 __s32 end = fh->vbi_fmt.end;
885
886 if (end > btv->crop_start)
887 goto fail;
888
889 /* Claim scan lines above fh->vbi_fmt.end. */
890 btv->vbi_end = end;
891 }
892
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 /* it's free, grab it */
894 fh->resources |= bit;
895 btv->resources |= bit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 return 1;
Michael Schimeke5bd0262007-01-18 16:17:39 -0300897
898 fail:
Michael Schimeke5bd0262007-01-18 16:17:39 -0300899 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900}
901
902static
903int check_btres(struct bttv_fh *fh, int bit)
904{
905 return (fh->resources & bit);
906}
907
908static
909int locked_btres(struct bttv *btv, int bit)
910{
911 return (btv->resources & bit);
912}
913
Michael Schimeke5bd0262007-01-18 16:17:39 -0300914/* Call with btv->lock down. */
915static void
916disclaim_vbi_lines(struct bttv *btv)
917{
918 btv->vbi_end = 0;
919}
920
921/* Call with btv->lock down. */
922static void
923disclaim_video_lines(struct bttv *btv)
924{
925 const struct bttv_tvnorm *tvnorm;
926 u8 crop;
927
928 tvnorm = &bttv_tvnorms[btv->tvnorm];
929 btv->crop_start = tvnorm->cropcap.bounds.top
930 + tvnorm->cropcap.bounds.height;
931
932 /* VBI capturing ends at VDELAY, start of video capturing, no
933 matter how many lines the VBI RISC program expects. When video
934 capturing is off, it shall no longer "preempt" VBI capturing,
935 so we set VDELAY to maximum. */
936 crop = btread(BT848_E_CROP) | 0xc0;
937 btwrite(crop, BT848_E_CROP);
938 btwrite(0xfe, BT848_E_VDELAY_LO);
939 btwrite(crop, BT848_O_CROP);
940 btwrite(0xfe, BT848_O_VDELAY_LO);
941}
942
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943static
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -0300944void free_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bits)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 if ((fh->resources & bits) != bits) {
Joe Perches8af443e2011-08-21 19:56:48 -0300947 /* trying to free resources not allocated by us ... */
948 pr_err("BUG! (btres)\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 fh->resources &= ~bits;
951 btv->resources &= ~bits;
Michael Schimeke5bd0262007-01-18 16:17:39 -0300952
953 bits = btv->resources;
954
955 if (0 == (bits & VIDEO_RESOURCES))
956 disclaim_video_lines(btv);
957
958 if (0 == (bits & VBI_RESOURCES))
959 disclaim_vbi_lines(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960}
961
962/* ----------------------------------------------------------------------- */
963/* If Bt848a or Bt849, use PLL for PAL/SECAM and crystal for NTSC */
964
965/* Frequency = (F_input / PLL_X) * PLL_I.PLL_F/PLL_C
966 PLL_X = Reference pre-divider (0=1, 1=2)
967 PLL_C = Post divider (0=6, 1=4)
968 PLL_I = Integer input
969 PLL_F = Fractional input
970
971 F_input = 28.636363 MHz:
972 PAL (CLKx2 = 35.46895 MHz): PLL_X = 1, PLL_I = 0x0E, PLL_F = 0xDCF9, PLL_C = 0
973*/
974
975static void set_pll_freq(struct bttv *btv, unsigned int fin, unsigned int fout)
976{
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800977 unsigned char fl, fh, fi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800979 /* prevent overflows */
980 fin/=4;
981 fout/=4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800983 fout*=12;
984 fi=fout/fin;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800986 fout=(fout%fin)*256;
987 fh=fout/fin;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800989 fout=(fout%fin)*256;
990 fl=fout/fin;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800992 btwrite(fl, BT848_PLL_F_LO);
993 btwrite(fh, BT848_PLL_F_HI);
994 btwrite(fi|BT848_PLL_X, BT848_PLL_XCI);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995}
996
997static void set_pll(struct bttv *btv)
998{
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800999 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -08001001 if (!btv->pll.pll_crystal)
1002 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003
1004 if (btv->pll.pll_ofreq == btv->pll.pll_current) {
Joe Perches8af443e2011-08-21 19:56:48 -03001005 dprintk("%d: PLL: no change required\n", btv->c.nr);
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -08001006 return;
1007 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -08001009 if (btv->pll.pll_ifreq == btv->pll.pll_ofreq) {
1010 /* no PLL needed */
1011 if (btv->pll.pll_current == 0)
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -08001012 return;
Joe Perches8af443e2011-08-21 19:56:48 -03001013 if (bttv_verbose)
1014 pr_info("%d: PLL can sleep, using XTAL (%d)\n",
1015 btv->c.nr, btv->pll.pll_ifreq);
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -08001016 btwrite(0x00,BT848_TGCTRL);
1017 btwrite(0x00,BT848_PLL_XCI);
1018 btv->pll.pll_current = 0;
1019 return;
1020 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021
Joe Perches8af443e2011-08-21 19:56:48 -03001022 if (bttv_verbose)
1023 pr_info("%d: Setting PLL: %d => %d (needs up to 100ms)\n",
1024 btv->c.nr,
1025 btv->pll.pll_ifreq, btv->pll.pll_ofreq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 set_pll_freq(btv, btv->pll.pll_ifreq, btv->pll.pll_ofreq);
1027
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -08001028 for (i=0; i<10; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 /* Let other people run while the PLL stabilizes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 msleep(10);
1031
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -08001032 if (btread(BT848_DSTATUS) & BT848_DSTATUS_PLOCK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 btwrite(0,BT848_DSTATUS);
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -08001034 } else {
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -08001035 btwrite(0x08,BT848_TGCTRL);
1036 btv->pll.pll_current = btv->pll.pll_ofreq;
Joe Perches8af443e2011-08-21 19:56:48 -03001037 if (bttv_verbose)
1038 pr_info("PLL set ok\n");
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -08001039 return;
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -08001040 }
1041 }
1042 btv->pll.pll_current = -1;
Joe Perches8af443e2011-08-21 19:56:48 -03001043 if (bttv_verbose)
1044 pr_info("Setting PLL failed\n");
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -08001045 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046}
1047
1048/* used to switch between the bt848's analog/digital video capture modes */
1049static void bt848A_set_timing(struct bttv *btv)
1050{
1051 int i, len;
1052 int table_idx = bttv_tvnorms[btv->tvnorm].sram;
1053 int fsc = bttv_tvnorms[btv->tvnorm].Fsc;
1054
Trent Piepho5221e212009-01-28 21:32:59 -03001055 if (btv->input == btv->dig) {
Joe Perches8af443e2011-08-21 19:56:48 -03001056 dprintk("%d: load digital timing table (table_idx=%d)\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 btv->c.nr,table_idx);
1058
1059 /* timing change...reset timing generator address */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001060 btwrite(0x00, BT848_TGCTRL);
1061 btwrite(0x02, BT848_TGCTRL);
1062 btwrite(0x00, BT848_TGCTRL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063
1064 len=SRAM_Table[table_idx][0];
1065 for(i = 1; i <= len; i++)
1066 btwrite(SRAM_Table[table_idx][i],BT848_TGLB);
1067 btv->pll.pll_ofreq = 27000000;
1068
1069 set_pll(btv);
1070 btwrite(0x11, BT848_TGCTRL);
1071 btwrite(0x41, BT848_DVSIF);
1072 } else {
1073 btv->pll.pll_ofreq = fsc;
1074 set_pll(btv);
1075 btwrite(0x0, BT848_DVSIF);
1076 }
1077}
1078
1079/* ----------------------------------------------------------------------- */
1080
1081static void bt848_bright(struct bttv *btv, int bright)
1082{
1083 int value;
1084
Joe Perches8af443e2011-08-21 19:56:48 -03001085 // printk("set bright: %d\n", bright); // DEBUG
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 btv->bright = bright;
1087
1088 /* We want -128 to 127 we get 0-65535 */
1089 value = (bright >> 8) - 128;
1090 btwrite(value & 0xff, BT848_BRIGHT);
1091}
1092
1093static void bt848_hue(struct bttv *btv, int hue)
1094{
1095 int value;
1096
1097 btv->hue = hue;
1098
1099 /* -128 to 127 */
1100 value = (hue >> 8) - 128;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001101 btwrite(value & 0xff, BT848_HUE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102}
1103
1104static void bt848_contrast(struct bttv *btv, int cont)
1105{
1106 int value,hibit;
1107
1108 btv->contrast = cont;
1109
1110 /* 0-511 */
1111 value = (cont >> 7);
1112 hibit = (value >> 6) & 4;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001113 btwrite(value & 0xff, BT848_CONTRAST_LO);
1114 btaor(hibit, ~4, BT848_E_CONTROL);
1115 btaor(hibit, ~4, BT848_O_CONTROL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116}
1117
1118static void bt848_sat(struct bttv *btv, int color)
1119{
1120 int val_u,val_v,hibits;
1121
1122 btv->saturation = color;
1123
1124 /* 0-511 for the color */
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -07001125 val_u = ((color * btv->opt_uv_ratio) / 50) >> 7;
1126 val_v = (((color * (100 - btv->opt_uv_ratio) / 50) >>7)*180L)/254;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001127 hibits = (val_u >> 7) & 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 hibits |= (val_v >> 8) & 1;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001129 btwrite(val_u & 0xff, BT848_SAT_U_LO);
1130 btwrite(val_v & 0xff, BT848_SAT_V_LO);
1131 btaor(hibits, ~3, BT848_E_CONTROL);
1132 btaor(hibits, ~3, BT848_O_CONTROL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133}
1134
1135/* ----------------------------------------------------------------------- */
1136
1137static int
1138video_mux(struct bttv *btv, unsigned int input)
1139{
1140 int mux,mask2;
1141
1142 if (input >= bttv_tvcards[btv->c.type].video_inputs)
1143 return -EINVAL;
1144
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001145 /* needed by RemoteVideo MX */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146 mask2 = bttv_tvcards[btv->c.type].gpiomask2;
1147 if (mask2)
1148 gpio_inout(mask2,mask2);
1149
1150 if (input == btv->svhs) {
1151 btor(BT848_CONTROL_COMP, BT848_E_CONTROL);
1152 btor(BT848_CONTROL_COMP, BT848_O_CONTROL);
1153 } else {
1154 btand(~BT848_CONTROL_COMP, BT848_E_CONTROL);
1155 btand(~BT848_CONTROL_COMP, BT848_O_CONTROL);
1156 }
Trent Piepho6f987002009-01-28 21:32:59 -03001157 mux = bttv_muxsel(btv, input);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158 btaor(mux<<5, ~(3<<5), BT848_IFORM);
Joe Perches8af443e2011-08-21 19:56:48 -03001159 dprintk("%d: video mux: input=%d mux=%d\n", btv->c.nr, input, mux);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160
1161 /* card specific hook */
1162 if(bttv_tvcards[btv->c.type].muxsel_hook)
1163 bttv_tvcards[btv->c.type].muxsel_hook (btv, input);
1164 return 0;
1165}
1166
1167static char *audio_modes[] = {
1168 "audio: tuner", "audio: radio", "audio: extern",
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001169 "audio: intern", "audio: mute"
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170};
1171
1172static int
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001173audio_mux(struct bttv *btv, int input, int mute)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174{
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001175 int gpio_val, signal;
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001176 struct v4l2_control ctrl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177
1178 gpio_inout(bttv_tvcards[btv->c.type].gpiomask,
1179 bttv_tvcards[btv->c.type].gpiomask);
1180 signal = btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC;
1181
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001182 btv->mute = mute;
1183 btv->audio = input;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001185 /* automute */
1186 mute = mute || (btv->opt_automute && !signal && !btv->radio_user);
1187
1188 if (mute)
1189 gpio_val = bttv_tvcards[btv->c.type].gpiomute;
1190 else
1191 gpio_val = bttv_tvcards[btv->c.type].gpiomux[input];
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001192
Trent Piepho72134a62009-01-28 21:32:59 -03001193 switch (btv->c.type) {
1194 case BTTV_BOARD_VOODOOTV_FM:
1195 case BTTV_BOARD_VOODOOTV_200:
1196 gpio_val = bttv_tda9880_setnorm(btv, gpio_val);
1197 break;
1198
1199 default:
1200 gpio_bits(bttv_tvcards[btv->c.type].gpiomask, gpio_val);
1201 }
1202
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203 if (bttv_gpio)
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001204 bttv_gpio_tracking(btv, audio_modes[mute ? 4 : input]);
1205 if (in_interrupt())
1206 return 0;
1207
1208 ctrl.id = V4L2_CID_AUDIO_MUTE;
Hans Verkuil2474ed42006-03-19 12:35:57 -03001209 ctrl.value = btv->mute;
Hans Verkuil859f0272009-03-28 08:29:00 -03001210 bttv_call_all(btv, core, s_ctrl, &ctrl);
1211 if (btv->sd_msp34xx) {
Hans Verkuil5325b422009-04-02 11:26:22 -03001212 u32 in;
Hans Verkuil2474ed42006-03-19 12:35:57 -03001213
1214 /* Note: the inputs tuner/radio/extern/intern are translated
1215 to msp routings. This assumes common behavior for all msp3400
1216 based TV cards. When this assumption fails, then the
1217 specific MSP routing must be added to the card table.
1218 For now this is sufficient. */
1219 switch (input) {
1220 case TVAUDIO_INPUT_RADIO:
Hans Verkuil5325b422009-04-02 11:26:22 -03001221 in = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1,
Hans Verkuil07151722006-04-01 18:03:23 -03001222 MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001223 break;
1224 case TVAUDIO_INPUT_EXTERN:
Hans Verkuil5325b422009-04-02 11:26:22 -03001225 in = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1,
Hans Verkuil07151722006-04-01 18:03:23 -03001226 MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001227 break;
1228 case TVAUDIO_INPUT_INTERN:
1229 /* Yes, this is the same input as for RADIO. I doubt
1230 if this is ever used. The only board with an INTERN
1231 input is the BTTV_BOARD_AVERMEDIA98. I wonder how
1232 that was tested. My guess is that the whole INTERN
1233 input does not work. */
Hans Verkuil5325b422009-04-02 11:26:22 -03001234 in = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1,
Hans Verkuil07151722006-04-01 18:03:23 -03001235 MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001236 break;
1237 case TVAUDIO_INPUT_TUNER:
1238 default:
Wade Berrier434b2522007-06-25 13:02:16 -03001239 /* This is the only card that uses TUNER2, and afaik,
1240 is the only difference between the VOODOOTV_FM
1241 and VOODOOTV_200 */
1242 if (btv->c.type == BTTV_BOARD_VOODOOTV_200)
Hans Verkuil5325b422009-04-02 11:26:22 -03001243 in = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER2, \
Wade Berrier434b2522007-06-25 13:02:16 -03001244 MSP_DSP_IN_TUNER, MSP_DSP_IN_TUNER);
1245 else
Hans Verkuil5325b422009-04-02 11:26:22 -03001246 in = MSP_INPUT_DEFAULT;
Hans Verkuil2474ed42006-03-19 12:35:57 -03001247 break;
1248 }
Hans Verkuil5325b422009-04-02 11:26:22 -03001249 v4l2_subdev_call(btv->sd_msp34xx, audio, s_routing,
1250 in, MSP_OUTPUT_DEFAULT, 0);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001251 }
Hans Verkuil859f0272009-03-28 08:29:00 -03001252 if (btv->sd_tvaudio) {
Hans Verkuil5325b422009-04-02 11:26:22 -03001253 v4l2_subdev_call(btv->sd_tvaudio, audio, s_routing,
1254 input, 0, 0);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001255 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 return 0;
1257}
1258
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001259static inline int
1260audio_mute(struct bttv *btv, int mute)
1261{
1262 return audio_mux(btv, btv->audio, mute);
1263}
1264
1265static inline int
1266audio_input(struct bttv *btv, int input)
1267{
1268 return audio_mux(btv, input, btv->mute);
1269}
1270
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271static void
Michael Schimeke5bd0262007-01-18 16:17:39 -03001272bttv_crop_calc_limits(struct bttv_crop *c)
1273{
1274 /* Scale factor min. 1:1, max. 16:1. Min. image size
1275 48 x 32. Scaled width must be a multiple of 4. */
1276
1277 if (1) {
1278 /* For bug compatibility with VIDIOCGCAP and image
1279 size checks in earlier driver versions. */
1280 c->min_scaled_width = 48;
1281 c->min_scaled_height = 32;
1282 } else {
1283 c->min_scaled_width =
1284 (max(48, c->rect.width >> 4) + 3) & ~3;
1285 c->min_scaled_height =
1286 max(32, c->rect.height >> 4);
1287 }
1288
1289 c->max_scaled_width = c->rect.width & ~3;
1290 c->max_scaled_height = c->rect.height;
1291}
1292
1293static void
Trent Piepho4ef2ccc2009-01-28 21:32:58 -03001294bttv_crop_reset(struct bttv_crop *c, unsigned int norm)
Michael Schimeke5bd0262007-01-18 16:17:39 -03001295{
1296 c->rect = bttv_tvnorms[norm].cropcap.defrect;
1297 bttv_crop_calc_limits(c);
1298}
1299
1300/* Call with btv->lock down. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301static int
1302set_tvnorm(struct bttv *btv, unsigned int norm)
1303{
1304 const struct bttv_tvnorm *tvnorm;
Nickolay V. Shmyrev302f61a2007-10-26 10:53:21 -03001305 v4l2_std_id id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306
Trent Piepho4ef2ccc2009-01-28 21:32:58 -03001307 BUG_ON(norm >= BTTV_TVNORMS);
1308 BUG_ON(btv->tvnorm >= BTTV_TVNORMS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310 tvnorm = &bttv_tvnorms[norm];
1311
Mike Isely2de26c02009-09-21 12:42:22 -03001312 if (memcmp(&bttv_tvnorms[btv->tvnorm].cropcap, &tvnorm->cropcap,
Trent Piepho4ef2ccc2009-01-28 21:32:58 -03001313 sizeof (tvnorm->cropcap))) {
Michael Schimeke5bd0262007-01-18 16:17:39 -03001314 bttv_crop_reset(&btv->crop[0], norm);
1315 btv->crop[1] = btv->crop[0]; /* current = default */
1316
1317 if (0 == (btv->resources & VIDEO_RESOURCES)) {
1318 btv->crop_start = tvnorm->cropcap.bounds.top
1319 + tvnorm->cropcap.bounds.height;
1320 }
1321 }
1322
1323 btv->tvnorm = norm;
1324
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 btwrite(tvnorm->adelay, BT848_ADELAY);
1326 btwrite(tvnorm->bdelay, BT848_BDELAY);
1327 btaor(tvnorm->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH),
1328 BT848_IFORM);
1329 btwrite(tvnorm->vbipack, BT848_VBI_PACK_SIZE);
1330 btwrite(1, BT848_VBI_PACK_DEL);
1331 bt848A_set_timing(btv);
1332
1333 switch (btv->c.type) {
Mauro Carvalho Chehab5a25e842005-11-08 21:36:52 -08001334 case BTTV_BOARD_VOODOOTV_FM:
Wade Berrier434b2522007-06-25 13:02:16 -03001335 case BTTV_BOARD_VOODOOTV_200:
Trent Piepho72134a62009-01-28 21:32:59 -03001336 bttv_tda9880_setnorm(btv, gpio_read());
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 }
Nickolay V. Shmyrev302f61a2007-10-26 10:53:21 -03001339 id = tvnorm->v4l2_id;
Hans Verkuilf41737e2009-04-01 03:52:39 -03001340 bttv_call_all(btv, core, s_std, id);
Nickolay V. Shmyrev302f61a2007-10-26 10:53:21 -03001341
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342 return 0;
1343}
1344
Michael Schimeke5bd0262007-01-18 16:17:39 -03001345/* Call with btv->lock down. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346static void
Trent Piepho333408f2007-07-03 15:08:10 -03001347set_input(struct bttv *btv, unsigned int input, unsigned int norm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348{
1349 unsigned long flags;
1350
1351 btv->input = input;
1352 if (irq_iswitch) {
1353 spin_lock_irqsave(&btv->s_lock,flags);
1354 if (btv->curr.frame_irq) {
1355 /* active capture -> delayed input switch */
1356 btv->new_input = input;
1357 } else {
1358 video_mux(btv,input);
1359 }
1360 spin_unlock_irqrestore(&btv->s_lock,flags);
1361 } else {
1362 video_mux(btv,input);
1363 }
Trent Piephoabb03622009-01-28 21:32:59 -03001364 audio_input(btv, (btv->tuner_type != TUNER_ABSENT && input == 0) ?
1365 TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN);
Trent Piepho333408f2007-07-03 15:08:10 -03001366 set_tvnorm(btv, norm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367}
1368
1369static void init_irqreg(struct bttv *btv)
1370{
1371 /* clear status */
1372 btwrite(0xfffffUL, BT848_INT_STAT);
1373
1374 if (bttv_tvcards[btv->c.type].no_video) {
1375 /* i2c only */
1376 btwrite(BT848_INT_I2CDONE,
1377 BT848_INT_MASK);
1378 } else {
1379 /* full video */
1380 btwrite((btv->triton1) |
1381 (btv->gpioirq ? BT848_INT_GPINT : 0) |
1382 BT848_INT_SCERR |
1383 (fdsr ? BT848_INT_FDSR : 0) |
Jean Delvareeb1b27b2008-08-30 10:18:21 -03001384 BT848_INT_RISCI | BT848_INT_OCERR |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 BT848_INT_FMTCHG|BT848_INT_HLOCK|
1386 BT848_INT_I2CDONE,
1387 BT848_INT_MASK);
1388 }
1389}
1390
1391static void init_bt848(struct bttv *btv)
1392{
1393 int val;
1394
1395 if (bttv_tvcards[btv->c.type].no_video) {
1396 /* very basic init only */
1397 init_irqreg(btv);
1398 return;
1399 }
1400
1401 btwrite(0x00, BT848_CAP_CTL);
1402 btwrite(BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL);
1403 btwrite(BT848_IFORM_XTAUTO | BT848_IFORM_AUTO, BT848_IFORM);
1404
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001405 /* set planar and packed mode trigger points and */
1406 /* set rising edge of inverted GPINTR pin as irq trigger */
1407 btwrite(BT848_GPIO_DMA_CTL_PKTP_32|
1408 BT848_GPIO_DMA_CTL_PLTP1_16|
1409 BT848_GPIO_DMA_CTL_PLTP23_16|
1410 BT848_GPIO_DMA_CTL_GPINTC|
1411 BT848_GPIO_DMA_CTL_GPINTI,
1412 BT848_GPIO_DMA_CTL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413
1414 val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001415 btwrite(val, BT848_E_SCLOOP);
1416 btwrite(val, BT848_O_SCLOOP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001418 btwrite(0x20, BT848_E_VSCALE_HI);
1419 btwrite(0x20, BT848_O_VSCALE_HI);
1420 btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 BT848_ADC);
1422
1423 btwrite(whitecrush_upper, BT848_WC_UP);
1424 btwrite(whitecrush_lower, BT848_WC_DOWN);
1425
1426 if (btv->opt_lumafilter) {
1427 btwrite(0, BT848_E_CONTROL);
1428 btwrite(0, BT848_O_CONTROL);
1429 } else {
1430 btwrite(BT848_CONTROL_LDEC, BT848_E_CONTROL);
1431 btwrite(BT848_CONTROL_LDEC, BT848_O_CONTROL);
1432 }
1433
1434 bt848_bright(btv, btv->bright);
1435 bt848_hue(btv, btv->hue);
1436 bt848_contrast(btv, btv->contrast);
1437 bt848_sat(btv, btv->saturation);
1438
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001439 /* interrupt */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440 init_irqreg(btv);
1441}
1442
1443static void bttv_reinit_bt848(struct bttv *btv)
1444{
1445 unsigned long flags;
1446
1447 if (bttv_verbose)
Joe Perches8af443e2011-08-21 19:56:48 -03001448 pr_info("%d: reset, reinitialize\n", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449 spin_lock_irqsave(&btv->s_lock,flags);
1450 btv->errors=0;
1451 bttv_set_dma(btv,0);
1452 spin_unlock_irqrestore(&btv->s_lock,flags);
1453
1454 init_bt848(btv);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001455 btv->pll.pll_current = -1;
Trent Piepho333408f2007-07-03 15:08:10 -03001456 set_input(btv, btv->input, btv->tvnorm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457}
1458
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001459static int bttv_g_ctrl(struct file *file, void *priv,
1460 struct v4l2_control *c)
1461{
1462 struct bttv_fh *fh = priv;
1463 struct bttv *btv = fh->btv;
1464
1465 switch (c->id) {
1466 case V4L2_CID_BRIGHTNESS:
1467 c->value = btv->bright;
1468 break;
1469 case V4L2_CID_HUE:
1470 c->value = btv->hue;
1471 break;
1472 case V4L2_CID_CONTRAST:
1473 c->value = btv->contrast;
1474 break;
1475 case V4L2_CID_SATURATION:
1476 c->value = btv->saturation;
1477 break;
1478
1479 case V4L2_CID_AUDIO_MUTE:
1480 case V4L2_CID_AUDIO_VOLUME:
1481 case V4L2_CID_AUDIO_BALANCE:
1482 case V4L2_CID_AUDIO_BASS:
1483 case V4L2_CID_AUDIO_TREBLE:
Hans Verkuil859f0272009-03-28 08:29:00 -03001484 bttv_call_all(btv, core, g_ctrl, c);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001485 break;
1486
1487 case V4L2_CID_PRIVATE_CHROMA_AGC:
1488 c->value = btv->opt_chroma_agc;
1489 break;
1490 case V4L2_CID_PRIVATE_COMBFILTER:
1491 c->value = btv->opt_combfilter;
1492 break;
1493 case V4L2_CID_PRIVATE_LUMAFILTER:
1494 c->value = btv->opt_lumafilter;
1495 break;
1496 case V4L2_CID_PRIVATE_AUTOMUTE:
1497 c->value = btv->opt_automute;
1498 break;
1499 case V4L2_CID_PRIVATE_AGC_CRUSH:
1500 c->value = btv->opt_adc_crush;
1501 break;
1502 case V4L2_CID_PRIVATE_VCR_HACK:
1503 c->value = btv->opt_vcr_hack;
1504 break;
1505 case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
1506 c->value = btv->opt_whitecrush_upper;
1507 break;
1508 case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
1509 c->value = btv->opt_whitecrush_lower;
1510 break;
1511 case V4L2_CID_PRIVATE_UV_RATIO:
1512 c->value = btv->opt_uv_ratio;
1513 break;
1514 case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
1515 c->value = btv->opt_full_luma_range;
1516 break;
1517 case V4L2_CID_PRIVATE_CORING:
1518 c->value = btv->opt_coring;
1519 break;
1520 default:
1521 return -EINVAL;
1522 }
1523 return 0;
1524}
1525
1526static int bttv_s_ctrl(struct file *file, void *f,
1527 struct v4l2_control *c)
1528{
1529 int err;
1530 int val;
1531 struct bttv_fh *fh = f;
1532 struct bttv *btv = fh->btv;
1533
Hans Verkuilffb48772010-05-01 08:03:24 -03001534 err = v4l2_prio_check(&btv->prio, fh->prio);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001535 if (0 != err)
1536 return err;
1537
1538 switch (c->id) {
1539 case V4L2_CID_BRIGHTNESS:
1540 bt848_bright(btv, c->value);
1541 break;
1542 case V4L2_CID_HUE:
1543 bt848_hue(btv, c->value);
1544 break;
1545 case V4L2_CID_CONTRAST:
1546 bt848_contrast(btv, c->value);
1547 break;
1548 case V4L2_CID_SATURATION:
1549 bt848_sat(btv, c->value);
1550 break;
1551 case V4L2_CID_AUDIO_MUTE:
1552 audio_mute(btv, c->value);
1553 /* fall through */
1554 case V4L2_CID_AUDIO_VOLUME:
1555 if (btv->volume_gpio)
1556 btv->volume_gpio(btv, c->value);
1557
Hans Verkuil859f0272009-03-28 08:29:00 -03001558 bttv_call_all(btv, core, s_ctrl, c);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001559 break;
1560 case V4L2_CID_AUDIO_BALANCE:
1561 case V4L2_CID_AUDIO_BASS:
1562 case V4L2_CID_AUDIO_TREBLE:
Hans Verkuil859f0272009-03-28 08:29:00 -03001563 bttv_call_all(btv, core, s_ctrl, c);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001564 break;
1565
1566 case V4L2_CID_PRIVATE_CHROMA_AGC:
1567 btv->opt_chroma_agc = c->value;
1568 val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
1569 btwrite(val, BT848_E_SCLOOP);
1570 btwrite(val, BT848_O_SCLOOP);
1571 break;
1572 case V4L2_CID_PRIVATE_COMBFILTER:
1573 btv->opt_combfilter = c->value;
1574 break;
1575 case V4L2_CID_PRIVATE_LUMAFILTER:
1576 btv->opt_lumafilter = c->value;
1577 if (btv->opt_lumafilter) {
1578 btand(~BT848_CONTROL_LDEC, BT848_E_CONTROL);
1579 btand(~BT848_CONTROL_LDEC, BT848_O_CONTROL);
1580 } else {
1581 btor(BT848_CONTROL_LDEC, BT848_E_CONTROL);
1582 btor(BT848_CONTROL_LDEC, BT848_O_CONTROL);
1583 }
1584 break;
1585 case V4L2_CID_PRIVATE_AUTOMUTE:
1586 btv->opt_automute = c->value;
1587 break;
1588 case V4L2_CID_PRIVATE_AGC_CRUSH:
1589 btv->opt_adc_crush = c->value;
1590 btwrite(BT848_ADC_RESERVED |
1591 (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
1592 BT848_ADC);
1593 break;
1594 case V4L2_CID_PRIVATE_VCR_HACK:
1595 btv->opt_vcr_hack = c->value;
1596 break;
1597 case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
1598 btv->opt_whitecrush_upper = c->value;
1599 btwrite(c->value, BT848_WC_UP);
1600 break;
1601 case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
1602 btv->opt_whitecrush_lower = c->value;
1603 btwrite(c->value, BT848_WC_DOWN);
1604 break;
1605 case V4L2_CID_PRIVATE_UV_RATIO:
1606 btv->opt_uv_ratio = c->value;
1607 bt848_sat(btv, btv->saturation);
1608 break;
1609 case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
1610 btv->opt_full_luma_range = c->value;
1611 btaor((c->value<<7), ~BT848_OFORM_RANGE, BT848_OFORM);
1612 break;
1613 case V4L2_CID_PRIVATE_CORING:
1614 btv->opt_coring = c->value;
1615 btaor((c->value<<5), ~BT848_OFORM_CORE32, BT848_OFORM);
1616 break;
1617 default:
1618 return -EINVAL;
1619 }
1620 return 0;
1621}
1622
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623/* ----------------------------------------------------------------------- */
1624
1625void bttv_gpio_tracking(struct bttv *btv, char *comment)
1626{
1627 unsigned int outbits, data;
1628 outbits = btread(BT848_GPIO_OUT_EN);
1629 data = btread(BT848_GPIO_DATA);
Joe Perches8af443e2011-08-21 19:56:48 -03001630 pr_debug("%d: gpio: en=%08x, out=%08x in=%08x [%s]\n",
1631 btv->c.nr, outbits, data & outbits, data & ~outbits, comment);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632}
1633
1634static void bttv_field_count(struct bttv *btv)
1635{
1636 int need_count = 0;
1637
1638 if (btv->users)
1639 need_count++;
1640
1641 if (need_count) {
1642 /* start field counter */
1643 btor(BT848_INT_VSYNC,BT848_INT_MASK);
1644 } else {
1645 /* stop field counter */
1646 btand(~BT848_INT_VSYNC,BT848_INT_MASK);
1647 btv->field_count = 0;
1648 }
1649}
1650
1651static const struct bttv_format*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652format_by_fourcc(int fourcc)
1653{
1654 unsigned int i;
1655
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001656 for (i = 0; i < FORMATS; i++) {
1657 if (-1 == formats[i].fourcc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658 continue;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001659 if (formats[i].fourcc == fourcc)
1660 return formats+i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661 }
1662 return NULL;
1663}
1664
1665/* ----------------------------------------------------------------------- */
1666/* misc helpers */
1667
1668static int
1669bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh,
1670 struct bttv_buffer *new)
1671{
1672 struct bttv_buffer *old;
1673 unsigned long flags;
1674 int retval = 0;
1675
Joe Perches8af443e2011-08-21 19:56:48 -03001676 dprintk("switch_overlay: enter [new=%p]\n", new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677 if (new)
Brandon Philips0fc06862007-11-06 20:02:36 -03001678 new->vb.state = VIDEOBUF_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679 spin_lock_irqsave(&btv->s_lock,flags);
1680 old = btv->screen;
1681 btv->screen = new;
1682 btv->loop_irq |= 1;
1683 bttv_set_dma(btv, 0x03);
1684 spin_unlock_irqrestore(&btv->s_lock,flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685 if (NULL != old) {
Joe Perches8af443e2011-08-21 19:56:48 -03001686 dprintk("switch_overlay: old=%p state is %d\n",
1687 old, old->vb.state);
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001688 bttv_dma_free(&fh->cap,btv, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689 kfree(old);
1690 }
Michael Schimeke5bd0262007-01-18 16:17:39 -03001691 if (NULL == new)
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03001692 free_btres_lock(btv,fh,RESOURCE_OVERLAY);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693 dprintk("switch_overlay: done\n");
1694 return retval;
1695}
1696
1697/* ----------------------------------------------------------------------- */
1698/* video4linux (1) interface */
1699
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001700static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv,
1701 struct bttv_buffer *buf,
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001702 const struct bttv_format *fmt,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703 unsigned int width, unsigned int height,
1704 enum v4l2_field field)
1705{
Michael Schimeke5bd0262007-01-18 16:17:39 -03001706 struct bttv_fh *fh = q->priv_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707 int redo_dma_risc = 0;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001708 struct bttv_crop c;
1709 int norm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 int rc;
1711
1712 /* check settings */
1713 if (NULL == fmt)
1714 return -EINVAL;
1715 if (fmt->btformat == BT848_COLOR_FMT_RAW) {
1716 width = RAW_BPL;
1717 height = RAW_LINES*2;
1718 if (width*height > buf->vb.bsize)
1719 return -EINVAL;
1720 buf->vb.size = buf->vb.bsize;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001721
1722 /* Make sure tvnorm and vbi_end remain consistent
1723 until we're done. */
Michael Schimeke5bd0262007-01-18 16:17:39 -03001724
1725 norm = btv->tvnorm;
1726
1727 /* In this mode capturing always starts at defrect.top
1728 (default VDELAY), ignoring cropping parameters. */
1729 if (btv->vbi_end > bttv_tvnorms[norm].cropcap.defrect.top) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730 return -EINVAL;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001731 }
1732
Michael Schimeke5bd0262007-01-18 16:17:39 -03001733 c.rect = bttv_tvnorms[norm].cropcap.defrect;
1734 } else {
Michael Schimeke5bd0262007-01-18 16:17:39 -03001735 norm = btv->tvnorm;
1736 c = btv->crop[!!fh->do_crop];
1737
Michael Schimeke5bd0262007-01-18 16:17:39 -03001738 if (width < c.min_scaled_width ||
1739 width > c.max_scaled_width ||
1740 height < c.min_scaled_height)
1741 return -EINVAL;
1742
1743 switch (field) {
1744 case V4L2_FIELD_TOP:
1745 case V4L2_FIELD_BOTTOM:
1746 case V4L2_FIELD_ALTERNATE:
1747 /* btv->crop counts frame lines. Max. scale
1748 factor is 16:1 for frames, 8:1 for fields. */
1749 if (height * 2 > c.max_scaled_height)
1750 return -EINVAL;
1751 break;
1752
1753 default:
1754 if (height > c.max_scaled_height)
1755 return -EINVAL;
1756 break;
1757 }
1758
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759 buf->vb.size = (width * height * fmt->depth) >> 3;
1760 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
1761 return -EINVAL;
1762 }
1763
1764 /* alloc + fill struct bttv_buffer (if changed) */
1765 if (buf->vb.width != width || buf->vb.height != height ||
1766 buf->vb.field != field ||
Michael Schimeke5bd0262007-01-18 16:17:39 -03001767 buf->tvnorm != norm || buf->fmt != fmt ||
1768 buf->crop.top != c.rect.top ||
1769 buf->crop.left != c.rect.left ||
1770 buf->crop.width != c.rect.width ||
1771 buf->crop.height != c.rect.height) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772 buf->vb.width = width;
1773 buf->vb.height = height;
1774 buf->vb.field = field;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001775 buf->tvnorm = norm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001776 buf->fmt = fmt;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001777 buf->crop = c.rect;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778 redo_dma_risc = 1;
1779 }
1780
1781 /* alloc risc memory */
Brandon Philips0fc06862007-11-06 20:02:36 -03001782 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783 redo_dma_risc = 1;
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001784 if (0 != (rc = videobuf_iolock(q,&buf->vb,&btv->fbuf)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785 goto fail;
1786 }
1787
1788 if (redo_dma_risc)
1789 if (0 != (rc = bttv_buffer_risc(btv,buf)))
1790 goto fail;
1791
Brandon Philips0fc06862007-11-06 20:02:36 -03001792 buf->vb.state = VIDEOBUF_PREPARED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001793 return 0;
1794
1795 fail:
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001796 bttv_dma_free(q,btv,buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797 return rc;
1798}
1799
1800static int
1801buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
1802{
1803 struct bttv_fh *fh = q->priv_data;
1804
1805 *size = fh->fmt->depth*fh->width*fh->height >> 3;
1806 if (0 == *count)
1807 *count = gbuffers;
Andreas Bombedab7e312010-03-21 16:02:45 -03001808 if (*size * *count > gbuffers * gbufsize)
1809 *count = (gbuffers * gbufsize) / *size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810 return 0;
1811}
1812
1813static int
1814buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
1815 enum v4l2_field field)
1816{
1817 struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
1818 struct bttv_fh *fh = q->priv_data;
1819
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001820 return bttv_prepare_buffer(q,fh->btv, buf, fh->fmt,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001821 fh->width, fh->height, field);
1822}
1823
1824static void
1825buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
1826{
1827 struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
1828 struct bttv_fh *fh = q->priv_data;
1829 struct bttv *btv = fh->btv;
1830
Brandon Philips0fc06862007-11-06 20:02:36 -03001831 buf->vb.state = VIDEOBUF_QUEUED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832 list_add_tail(&buf->vb.queue,&btv->capture);
1833 if (!btv->curr.frame_irq) {
1834 btv->loop_irq |= 1;
1835 bttv_set_dma(btv, 0x03);
1836 }
1837}
1838
1839static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
1840{
1841 struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
1842 struct bttv_fh *fh = q->priv_data;
1843
Michael Schimekfeaba7a2007-01-26 08:30:05 -03001844 bttv_dma_free(q,fh->btv,buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845}
1846
1847static struct videobuf_queue_ops bttv_video_qops = {
1848 .buf_setup = buffer_setup,
1849 .buf_prepare = buffer_prepare,
1850 .buf_queue = buffer_queue,
1851 .buf_release = buffer_release,
1852};
1853
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001854static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001856 struct bttv_fh *fh = priv;
1857 struct bttv *btv = fh->btv;
1858 unsigned int i;
1859 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860
Hans Verkuilffb48772010-05-01 08:03:24 -03001861 err = v4l2_prio_check(&btv->prio, fh->prio);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001862 if (err)
1863 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001865 for (i = 0; i < BTTV_TVNORMS; i++)
1866 if (*id & bttv_tvnorms[i].v4l2_id)
1867 break;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001868 if (i == BTTV_TVNORMS) {
1869 err = -EINVAL;
1870 goto err;
1871 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001872
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001873 set_tvnorm(btv, i);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001874
1875err:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001877 return err;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001878}
1879
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001880static int bttv_querystd(struct file *file, void *f, v4l2_std_id *id)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001881{
1882 struct bttv_fh *fh = f;
1883 struct bttv *btv = fh->btv;
1884
1885 if (btread(BT848_DSTATUS) & BT848_DSTATUS_NUML)
1886 *id = V4L2_STD_625_50;
1887 else
1888 *id = V4L2_STD_525_60;
1889 return 0;
1890}
1891
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001892static int bttv_enum_input(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001893 struct v4l2_input *i)
1894{
1895 struct bttv_fh *fh = priv;
1896 struct bttv *btv = fh->btv;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001897 int rc = 0;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001898
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001899 if (i->index >= bttv_tvcards[btv->c.type].video_inputs) {
1900 rc = -EINVAL;
1901 goto err;
1902 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001903
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001904 i->type = V4L2_INPUT_TYPE_CAMERA;
1905 i->audioset = 1;
1906
Trent Piephoabb03622009-01-28 21:32:59 -03001907 if (btv->tuner_type != TUNER_ABSENT && i->index == 0) {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001908 sprintf(i->name, "Television");
1909 i->type = V4L2_INPUT_TYPE_TUNER;
1910 i->tuner = 0;
1911 } else if (i->index == btv->svhs) {
1912 sprintf(i->name, "S-Video");
1913 } else {
1914 sprintf(i->name, "Composite%d", i->index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001915 }
1916
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001917 if (i->index == btv->input) {
1918 __u32 dstatus = btread(BT848_DSTATUS);
1919 if (0 == (dstatus & BT848_DSTATUS_PRES))
1920 i->status |= V4L2_IN_ST_NO_SIGNAL;
1921 if (0 == (dstatus & BT848_DSTATUS_HLOC))
1922 i->status |= V4L2_IN_ST_NO_H_LOCK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923 }
1924
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001925 i->std = BTTV_NORMS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001927err:
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001928
1929 return rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001930}
Nickolay V. Shmyrev4b9b9362006-08-25 16:53:04 -03001931
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001932static int bttv_g_input(struct file *file, void *priv, unsigned int *i)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001933{
1934 struct bttv_fh *fh = priv;
1935 struct bttv *btv = fh->btv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001937 *i = btv->input;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001938
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001939 return 0;
1940}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001942static int bttv_s_input(struct file *file, void *priv, unsigned int i)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001943{
1944 struct bttv_fh *fh = priv;
1945 struct bttv *btv = fh->btv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001947 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001949 err = v4l2_prio_check(&btv->prio, fh->prio);
1950 if (unlikely(err))
1951 goto err;
1952
1953 if (i > bttv_tvcards[btv->c.type].video_inputs) {
1954 err = -EINVAL;
1955 goto err;
1956 }
1957
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001958 set_input(btv, i, btv->tvnorm);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001959
1960err:
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001961 return 0;
1962}
1963
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001964static int bttv_s_tuner(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001965 struct v4l2_tuner *t)
1966{
1967 struct bttv_fh *fh = priv;
1968 struct bttv *btv = fh->btv;
1969 int err;
1970
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001971 if (unlikely(0 != t->index))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001972 return -EINVAL;
1973
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001974 if (unlikely(btv->tuner_type == TUNER_ABSENT)) {
1975 err = -EINVAL;
1976 goto err;
1977 }
1978
1979 err = v4l2_prio_check(&btv->prio, fh->prio);
1980 if (unlikely(err))
1981 goto err;
1982
Hans Verkuil859f0272009-03-28 08:29:00 -03001983 bttv_call_all(btv, tuner, s_tuner, t);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001984
1985 if (btv->audio_mode_gpio)
1986 btv->audio_mode_gpio(btv, t, 1);
1987
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001988err:
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001989
1990 return 0;
1991}
1992
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001993static int bttv_g_frequency(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001994 struct v4l2_frequency *f)
1995{
1996 struct bttv_fh *fh = priv;
1997 struct bttv *btv = fh->btv;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001998
Robert Fitzsimons1b069012008-04-01 11:41:54 -03001999 f->type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002000 f->frequency = btv->freq;
2001
2002 return 0;
2003}
2004
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002005static int bttv_s_frequency(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002006 struct v4l2_frequency *f)
2007{
2008 struct bttv_fh *fh = priv;
2009 struct bttv *btv = fh->btv;
2010 int err;
2011
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002012 if (unlikely(f->tuner != 0))
2013 return -EINVAL;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002014
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002015 err = v4l2_prio_check(&btv->prio, fh->prio);
2016 if (unlikely(err))
2017 goto err;
2018
2019 if (unlikely(f->type != (btv->radio_user
2020 ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV))) {
2021 err = -EINVAL;
2022 goto err;
2023 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002024 btv->freq = f->frequency;
Hans Verkuil859f0272009-03-28 08:29:00 -03002025 bttv_call_all(btv, tuner, s_frequency, f);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002026 if (btv->has_matchbox && btv->radio_user)
2027 tea5757_set_freq(btv, btv->freq);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002028err:
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002029
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002030 return 0;
2031}
2032
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002033static int bttv_log_status(struct file *file, void *f)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002034{
2035 struct bttv_fh *fh = f;
2036 struct bttv *btv = fh->btv;
2037
Joe Perches8af443e2011-08-21 19:56:48 -03002038 pr_info("%d: ======== START STATUS CARD #%d ========\n",
2039 btv->c.nr, btv->c.nr);
Hans Verkuil859f0272009-03-28 08:29:00 -03002040 bttv_call_all(btv, core, log_status);
Joe Perches8af443e2011-08-21 19:56:48 -03002041 pr_info("%d: ======== END STATUS CARD #%d ========\n",
2042 btv->c.nr, btv->c.nr);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002043 return 0;
2044}
2045
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002046#ifdef CONFIG_VIDEO_ADV_DEBUG
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002047static int bttv_g_register(struct file *file, void *f,
Hans Verkuilaecde8b52008-12-30 07:14:19 -03002048 struct v4l2_dbg_register *reg)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002049{
2050 struct bttv_fh *fh = f;
2051 struct bttv *btv = fh->btv;
2052
2053 if (!capable(CAP_SYS_ADMIN))
2054 return -EPERM;
2055
Hans Verkuilaecde8b52008-12-30 07:14:19 -03002056 if (!v4l2_chip_match_host(&reg->match))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002057 return -EINVAL;
2058
2059 /* bt848 has a 12-bit register space */
2060 reg->reg &= 0xfff;
2061 reg->val = btread(reg->reg);
Hans Verkuilaecde8b52008-12-30 07:14:19 -03002062 reg->size = 1;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002063
2064 return 0;
2065}
2066
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002067static int bttv_s_register(struct file *file, void *f,
Hans Verkuilaecde8b52008-12-30 07:14:19 -03002068 struct v4l2_dbg_register *reg)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002069{
2070 struct bttv_fh *fh = f;
2071 struct bttv *btv = fh->btv;
2072
2073 if (!capable(CAP_SYS_ADMIN))
2074 return -EPERM;
2075
Hans Verkuilaecde8b52008-12-30 07:14:19 -03002076 if (!v4l2_chip_match_host(&reg->match))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002077 return -EINVAL;
2078
2079 /* bt848 has a 12-bit register space */
2080 reg->reg &= 0xfff;
2081 btwrite(reg->val, reg->reg);
2082
2083 return 0;
2084}
2085#endif
2086
Michael Schimeke5bd0262007-01-18 16:17:39 -03002087/* Given cropping boundaries b and the scaled width and height of a
2088 single field or frame, which must not exceed hardware limits, this
2089 function adjusts the cropping parameters c. */
2090static void
2091bttv_crop_adjust (struct bttv_crop * c,
2092 const struct v4l2_rect * b,
2093 __s32 width,
2094 __s32 height,
2095 enum v4l2_field field)
2096{
2097 __s32 frame_height = height << !V4L2_FIELD_HAS_BOTH(field);
2098 __s32 max_left;
2099 __s32 max_top;
2100
2101 if (width < c->min_scaled_width) {
2102 /* Max. hor. scale factor 16:1. */
2103 c->rect.width = width * 16;
2104 } else if (width > c->max_scaled_width) {
2105 /* Min. hor. scale factor 1:1. */
2106 c->rect.width = width;
2107
2108 max_left = b->left + b->width - width;
2109 max_left = min(max_left, (__s32) MAX_HDELAY);
2110 if (c->rect.left > max_left)
2111 c->rect.left = max_left;
2112 }
2113
2114 if (height < c->min_scaled_height) {
2115 /* Max. vert. scale factor 16:1, single fields 8:1. */
2116 c->rect.height = height * 16;
2117 } else if (frame_height > c->max_scaled_height) {
2118 /* Min. vert. scale factor 1:1.
2119 Top and height count field lines times two. */
2120 c->rect.height = (frame_height + 1) & ~1;
2121
2122 max_top = b->top + b->height - c->rect.height;
2123 if (c->rect.top > max_top)
2124 c->rect.top = max_top;
2125 }
2126
2127 bttv_crop_calc_limits(c);
2128}
2129
2130/* Returns an error if scaling to a frame or single field with the given
2131 width and height is not possible with the current cropping parameters
2132 and width aligned according to width_mask. If adjust_size is TRUE the
2133 function may adjust the width and/or height instead, rounding width
2134 to (width + width_bias) & width_mask. If adjust_crop is TRUE it may
2135 also adjust the current cropping parameters to get closer to the
2136 desired image size. */
2137static int
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002138limit_scaled_size_lock (struct bttv_fh * fh,
Michael Schimeke5bd0262007-01-18 16:17:39 -03002139 __s32 * width,
2140 __s32 * height,
2141 enum v4l2_field field,
2142 unsigned int width_mask,
2143 unsigned int width_bias,
2144 int adjust_size,
2145 int adjust_crop)
2146{
2147 struct bttv *btv = fh->btv;
2148 const struct v4l2_rect *b;
2149 struct bttv_crop *c;
2150 __s32 min_width;
2151 __s32 min_height;
2152 __s32 max_width;
2153 __s32 max_height;
2154 int rc;
2155
2156 BUG_ON((int) width_mask >= 0 ||
2157 width_bias >= (unsigned int) -width_mask);
2158
2159 /* Make sure tvnorm, vbi_end and the current cropping parameters
2160 remain consistent until we're done. */
Michael Schimeke5bd0262007-01-18 16:17:39 -03002161
2162 b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
2163
2164 /* Do crop - use current, don't - use default parameters. */
2165 c = &btv->crop[!!fh->do_crop];
2166
2167 if (fh->do_crop
2168 && adjust_size
2169 && adjust_crop
2170 && !locked_btres(btv, VIDEO_RESOURCES)) {
2171 min_width = 48;
2172 min_height = 32;
2173
2174 /* We cannot scale up. When the scaled image is larger
2175 than crop.rect we adjust the crop.rect as required
2176 by the V4L2 spec, hence cropcap.bounds are our limit. */
2177 max_width = min(b->width, (__s32) MAX_HACTIVE);
2178 max_height = b->height;
2179
2180 /* We cannot capture the same line as video and VBI data.
2181 Note btv->vbi_end is really a minimum, see
2182 bttv_vbi_try_fmt(). */
2183 if (btv->vbi_end > b->top) {
2184 max_height -= btv->vbi_end - b->top;
2185 rc = -EBUSY;
2186 if (min_height > max_height)
2187 goto fail;
2188 }
2189 } else {
2190 rc = -EBUSY;
2191 if (btv->vbi_end > c->rect.top)
2192 goto fail;
2193
2194 min_width = c->min_scaled_width;
2195 min_height = c->min_scaled_height;
2196 max_width = c->max_scaled_width;
2197 max_height = c->max_scaled_height;
2198
2199 adjust_crop = 0;
2200 }
2201
2202 min_width = (min_width - width_mask - 1) & width_mask;
2203 max_width = max_width & width_mask;
2204
2205 /* Max. scale factor is 16:1 for frames, 8:1 for fields. */
2206 min_height = min_height;
2207 /* Min. scale factor is 1:1. */
2208 max_height >>= !V4L2_FIELD_HAS_BOTH(field);
2209
2210 if (adjust_size) {
2211 *width = clamp(*width, min_width, max_width);
2212 *height = clamp(*height, min_height, max_height);
2213
2214 /* Round after clamping to avoid overflow. */
2215 *width = (*width + width_bias) & width_mask;
2216
2217 if (adjust_crop) {
2218 bttv_crop_adjust(c, b, *width, *height, field);
2219
2220 if (btv->vbi_end > c->rect.top) {
2221 /* Move the crop window out of the way. */
2222 c->rect.top = btv->vbi_end;
2223 }
2224 }
2225 } else {
2226 rc = -EINVAL;
2227 if (*width < min_width ||
2228 *height < min_height ||
2229 *width > max_width ||
2230 *height > max_height ||
2231 0 != (*width & ~width_mask))
2232 goto fail;
2233 }
2234
2235 rc = 0; /* success */
2236
2237 fail:
Michael Schimeke5bd0262007-01-18 16:17:39 -03002238
2239 return rc;
2240}
2241
2242/* Returns an error if the given overlay window dimensions are not
2243 possible with the current cropping parameters. If adjust_size is
2244 TRUE the function may adjust the window width and/or height
2245 instead, however it always rounds the horizontal position and
2246 width as btcx_align() does. If adjust_crop is TRUE the function
2247 may also adjust the current cropping parameters to get closer
2248 to the desired window size. */
2249static int
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002250verify_window_lock (struct bttv_fh * fh,
Michael Schimeke5bd0262007-01-18 16:17:39 -03002251 struct v4l2_window * win,
2252 int adjust_size,
2253 int adjust_crop)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254{
2255 enum v4l2_field field;
Michael Schimeke5bd0262007-01-18 16:17:39 -03002256 unsigned int width_mask;
2257 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258
2259 if (win->w.width < 48 || win->w.height < 32)
2260 return -EINVAL;
2261 if (win->clipcount > 2048)
2262 return -EINVAL;
2263
2264 field = win->field;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265
2266 if (V4L2_FIELD_ANY == field) {
Michael Schimeke5bd0262007-01-18 16:17:39 -03002267 __s32 height2;
2268
2269 height2 = fh->btv->crop[!!fh->do_crop].rect.height >> 1;
2270 field = (win->w.height > height2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002271 ? V4L2_FIELD_INTERLACED
2272 : V4L2_FIELD_TOP;
2273 }
2274 switch (field) {
2275 case V4L2_FIELD_TOP:
2276 case V4L2_FIELD_BOTTOM:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002277 case V4L2_FIELD_INTERLACED:
2278 break;
2279 default:
2280 return -EINVAL;
2281 }
2282
Michael Schimeke5bd0262007-01-18 16:17:39 -03002283 /* 4-byte alignment. */
2284 if (NULL == fh->ovfmt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285 return -EINVAL;
Michael Schimeke5bd0262007-01-18 16:17:39 -03002286 width_mask = ~0;
2287 switch (fh->ovfmt->depth) {
2288 case 8:
2289 case 24:
2290 width_mask = ~3;
2291 break;
2292 case 16:
2293 width_mask = ~1;
2294 break;
2295 case 32:
2296 break;
2297 default:
2298 BUG();
2299 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300
Michael Schimeke5bd0262007-01-18 16:17:39 -03002301 win->w.width -= win->w.left & ~width_mask;
2302 win->w.left = (win->w.left - width_mask - 1) & width_mask;
2303
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002304 rc = limit_scaled_size_lock(fh, &win->w.width, &win->w.height,
Michael Schimeke5bd0262007-01-18 16:17:39 -03002305 field, width_mask,
2306 /* width_bias: round down */ 0,
2307 adjust_size, adjust_crop);
2308 if (0 != rc)
2309 return rc;
2310
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311 win->field = field;
2312 return 0;
2313}
2314
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002315static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316 struct v4l2_window *win, int fixup)
2317{
2318 struct v4l2_clip *clips = NULL;
2319 int n,size,retval = 0;
2320
2321 if (NULL == fh->ovfmt)
2322 return -EINVAL;
2323 if (!(fh->ovfmt->flags & FORMAT_FLAGS_PACKED))
2324 return -EINVAL;
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002325 retval = verify_window_lock(fh, win,
Michael Schimeke5bd0262007-01-18 16:17:39 -03002326 /* adjust_size */ fixup,
2327 /* adjust_crop */ fixup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328 if (0 != retval)
2329 return retval;
2330
2331 /* copy clips -- luckily v4l1 + v4l2 are binary
2332 compatible here ...*/
2333 n = win->clipcount;
2334 size = sizeof(*clips)*(n+4);
2335 clips = kmalloc(size,GFP_KERNEL);
2336 if (NULL == clips)
2337 return -ENOMEM;
2338 if (n > 0) {
2339 if (copy_from_user(clips,win->clips,sizeof(struct v4l2_clip)*n)) {
2340 kfree(clips);
2341 return -EFAULT;
2342 }
2343 }
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002344
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345 /* clip against screen */
2346 if (NULL != btv->fbuf.base)
2347 n = btcx_screen_clips(btv->fbuf.fmt.width, btv->fbuf.fmt.height,
2348 &win->w, clips, n);
2349 btcx_sort_clips(clips,n);
2350
2351 /* 4-byte alignments */
2352 switch (fh->ovfmt->depth) {
2353 case 8:
2354 case 24:
2355 btcx_align(&win->w, clips, n, 3);
2356 break;
2357 case 16:
2358 btcx_align(&win->w, clips, n, 1);
2359 break;
2360 case 32:
2361 /* no alignment fixups needed */
2362 break;
2363 default:
2364 BUG();
2365 }
2366
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03002367 kfree(fh->ov.clips);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002368 fh->ov.clips = clips;
2369 fh->ov.nclips = n;
2370
2371 fh->ov.w = win->w;
2372 fh->ov.field = win->field;
2373 fh->ov.setup_ok = 1;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002374
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375 btv->init.ov.w.width = win->w.width;
2376 btv->init.ov.w.height = win->w.height;
2377 btv->init.ov.field = win->field;
2378
2379 /* update overlay if needed */
2380 retval = 0;
2381 if (check_btres(fh, RESOURCE_OVERLAY)) {
2382 struct bttv_buffer *new;
2383
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03002384 new = videobuf_sg_alloc(sizeof(*new));
Michael Schimeke5bd0262007-01-18 16:17:39 -03002385 new->crop = btv->crop[!!fh->do_crop].rect;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002386 bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
2387 retval = bttv_switch_overlay(btv,fh,new);
2388 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002389 return retval;
2390}
2391
2392/* ----------------------------------------------------------------------- */
2393
2394static struct videobuf_queue* bttv_queue(struct bttv_fh *fh)
2395{
2396 struct videobuf_queue* q = NULL;
2397
2398 switch (fh->type) {
2399 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2400 q = &fh->cap;
2401 break;
2402 case V4L2_BUF_TYPE_VBI_CAPTURE:
2403 q = &fh->vbi;
2404 break;
2405 default:
2406 BUG();
2407 }
2408 return q;
2409}
2410
2411static int bttv_resource(struct bttv_fh *fh)
2412{
2413 int res = 0;
2414
2415 switch (fh->type) {
2416 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Michael Schimeke5bd0262007-01-18 16:17:39 -03002417 res = RESOURCE_VIDEO_STREAM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418 break;
2419 case V4L2_BUF_TYPE_VBI_CAPTURE:
2420 res = RESOURCE_VBI;
2421 break;
2422 default:
2423 BUG();
2424 }
2425 return res;
2426}
2427
2428static int bttv_switch_type(struct bttv_fh *fh, enum v4l2_buf_type type)
2429{
2430 struct videobuf_queue *q = bttv_queue(fh);
2431 int res = bttv_resource(fh);
2432
2433 if (check_btres(fh,res))
2434 return -EBUSY;
2435 if (videobuf_queue_is_busy(q))
2436 return -EBUSY;
2437 fh->type = type;
2438 return 0;
2439}
2440
Michael H. Schimekc87c9482005-12-01 00:51:33 -08002441static void
2442pix_format_set_size (struct v4l2_pix_format * f,
2443 const struct bttv_format * fmt,
2444 unsigned int width,
2445 unsigned int height)
2446{
2447 f->width = width;
2448 f->height = height;
2449
2450 if (fmt->flags & FORMAT_FLAGS_PLANAR) {
2451 f->bytesperline = width; /* Y plane */
2452 f->sizeimage = (width * height * fmt->depth) >> 3;
2453 } else {
2454 f->bytesperline = (width * fmt->depth) >> 3;
2455 f->sizeimage = height * f->bytesperline;
2456 }
2457}
2458
Hans Verkuil78b526a2008-05-28 12:16:41 -03002459static int bttv_g_fmt_vid_cap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002460 struct v4l2_format *f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002462 struct bttv_fh *fh = priv;
2463
2464 pix_format_set_size(&f->fmt.pix, fh->fmt,
2465 fh->width, fh->height);
2466 f->fmt.pix.field = fh->cap.field;
2467 f->fmt.pix.pixelformat = fh->fmt->fourcc;
2468
2469 return 0;
2470}
2471
Hans Verkuil78b526a2008-05-28 12:16:41 -03002472static int bttv_g_fmt_vid_overlay(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002473 struct v4l2_format *f)
2474{
2475 struct bttv_fh *fh = priv;
2476
2477 f->fmt.win.w = fh->ov.w;
2478 f->fmt.win.field = fh->ov.field;
2479
2480 return 0;
2481}
2482
Hans Verkuil78b526a2008-05-28 12:16:41 -03002483static int bttv_try_fmt_vid_cap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002484 struct v4l2_format *f)
2485{
2486 const struct bttv_format *fmt;
2487 struct bttv_fh *fh = priv;
2488 struct bttv *btv = fh->btv;
2489 enum v4l2_field field;
2490 __s32 width, height;
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002491 int rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002492
2493 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
2494 if (NULL == fmt)
2495 return -EINVAL;
2496
2497 field = f->fmt.pix.field;
2498
2499 if (V4L2_FIELD_ANY == field) {
2500 __s32 height2;
2501
2502 height2 = btv->crop[!!fh->do_crop].rect.height >> 1;
2503 field = (f->fmt.pix.height > height2)
2504 ? V4L2_FIELD_INTERLACED
2505 : V4L2_FIELD_BOTTOM;
2506 }
2507
2508 if (V4L2_FIELD_SEQ_BT == field)
2509 field = V4L2_FIELD_SEQ_TB;
2510
2511 switch (field) {
2512 case V4L2_FIELD_TOP:
2513 case V4L2_FIELD_BOTTOM:
2514 case V4L2_FIELD_ALTERNATE:
2515 case V4L2_FIELD_INTERLACED:
2516 break;
2517 case V4L2_FIELD_SEQ_TB:
2518 if (fmt->flags & FORMAT_FLAGS_PLANAR)
2519 return -EINVAL;
2520 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002521 default:
2522 return -EINVAL;
2523 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002524
2525 width = f->fmt.pix.width;
2526 height = f->fmt.pix.height;
2527
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002528 rc = limit_scaled_size_lock(fh, &width, &height, field,
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002529 /* width_mask: 4 pixels */ ~3,
2530 /* width_bias: nearest */ 2,
2531 /* adjust_size */ 1,
2532 /* adjust_crop */ 0);
2533 if (0 != rc)
2534 return rc;
2535
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002536 /* update data for the application */
2537 f->fmt.pix.field = field;
2538 pix_format_set_size(&f->fmt.pix, fmt, width, height);
2539
2540 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541}
2542
Hans Verkuil78b526a2008-05-28 12:16:41 -03002543static int bttv_try_fmt_vid_overlay(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002544 struct v4l2_format *f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002546 struct bttv_fh *fh = priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002547
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002548 return verify_window_lock(fh, &f->fmt.win,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002549 /* adjust_size */ 1,
2550 /* adjust_crop */ 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002551}
2552
Hans Verkuil78b526a2008-05-28 12:16:41 -03002553static int bttv_s_fmt_vid_cap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002554 struct v4l2_format *f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002555{
2556 int retval;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002557 const struct bttv_format *fmt;
2558 struct bttv_fh *fh = priv;
2559 struct bttv *btv = fh->btv;
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002560 __s32 width, height;
2561 enum v4l2_field field;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002562
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002563 retval = bttv_switch_type(fh, f->type);
2564 if (0 != retval)
2565 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002566
Hans Verkuil78b526a2008-05-28 12:16:41 -03002567 retval = bttv_try_fmt_vid_cap(file, priv, f);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002568 if (0 != retval)
2569 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002571 width = f->fmt.pix.width;
2572 height = f->fmt.pix.height;
2573 field = f->fmt.pix.field;
2574
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002575 retval = limit_scaled_size_lock(fh, &width, &height, f->fmt.pix.field,
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002576 /* width_mask: 4 pixels */ ~3,
2577 /* width_bias: nearest */ 2,
2578 /* adjust_size */ 1,
2579 /* adjust_crop */ 1);
2580 if (0 != retval)
2581 return retval;
2582
2583 f->fmt.pix.field = field;
2584
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002585 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002587 /* update our state informations */
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002588 fh->fmt = fmt;
2589 fh->cap.field = f->fmt.pix.field;
2590 fh->cap.last = V4L2_FIELD_NONE;
2591 fh->width = f->fmt.pix.width;
2592 fh->height = f->fmt.pix.height;
2593 btv->init.fmt = fmt;
2594 btv->init.width = f->fmt.pix.width;
2595 btv->init.height = f->fmt.pix.height;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002596
2597 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598}
2599
Hans Verkuil78b526a2008-05-28 12:16:41 -03002600static int bttv_s_fmt_vid_overlay(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002601 struct v4l2_format *f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002603 struct bttv_fh *fh = priv;
2604 struct bttv *btv = fh->btv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002605
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002606 if (no_overlay > 0) {
Joe Perches8af443e2011-08-21 19:56:48 -03002607 pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002608 return -EINVAL;
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002609 }
Michael Krufky5e453dc2006-01-09 15:32:31 -02002610
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002611 return setup_window_lock(fh, btv, &f->fmt.win, 1);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002612}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002614static int bttv_querycap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002615 struct v4l2_capability *cap)
2616{
2617 struct bttv_fh *fh = priv;
2618 struct bttv *btv = fh->btv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002619
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002620 if (0 == v4l2)
2621 return -EINVAL;
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07002622
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002623 strlcpy(cap->driver, "bttv", sizeof(cap->driver));
2624 strlcpy(cap->card, btv->video_dev->name, sizeof(cap->card));
2625 snprintf(cap->bus_info, sizeof(cap->bus_info),
2626 "PCI:%s", pci_name(btv->c.pci));
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002627 cap->capabilities =
2628 V4L2_CAP_VIDEO_CAPTURE |
2629 V4L2_CAP_VBI_CAPTURE |
2630 V4L2_CAP_READWRITE |
2631 V4L2_CAP_STREAMING;
2632 if (no_overlay <= 0)
2633 cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002634
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002635 /*
2636 * No need to lock here: those vars are initialized during board
2637 * probe and remains untouched during the rest of the driver lifecycle
2638 */
2639 if (btv->has_saa6588)
2640 cap->capabilities |= V4L2_CAP_RDS_CAPTURE;
Trent Piephoabb03622009-01-28 21:32:59 -03002641 if (btv->tuner_type != TUNER_ABSENT)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002642 cap->capabilities |= V4L2_CAP_TUNER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643 return 0;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002644}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002646static int bttv_enum_fmt_cap_ovr(struct v4l2_fmtdesc *f)
2647{
2648 int index = -1, i;
2649
2650 for (i = 0; i < FORMATS; i++) {
2651 if (formats[i].fourcc != -1)
2652 index++;
2653 if ((unsigned int)index == f->index)
2654 break;
2655 }
2656 if (FORMATS == i)
2657 return -EINVAL;
2658
2659 f->pixelformat = formats[i].fourcc;
2660 strlcpy(f->description, formats[i].name, sizeof(f->description));
2661
2662 return i;
2663}
2664
Hans Verkuil78b526a2008-05-28 12:16:41 -03002665static int bttv_enum_fmt_vid_cap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002666 struct v4l2_fmtdesc *f)
2667{
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002668 int rc = bttv_enum_fmt_cap_ovr(f);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002669
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002670 if (rc < 0)
2671 return rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002672
2673 return 0;
2674}
2675
Hans Verkuil78b526a2008-05-28 12:16:41 -03002676static int bttv_enum_fmt_vid_overlay(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002677 struct v4l2_fmtdesc *f)
2678{
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002679 int rc;
2680
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002681 if (no_overlay > 0) {
Joe Perches8af443e2011-08-21 19:56:48 -03002682 pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002683 return -EINVAL;
2684 }
2685
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002686 rc = bttv_enum_fmt_cap_ovr(f);
2687
2688 if (rc < 0)
2689 return rc;
2690
2691 if (!(formats[rc].flags & FORMAT_FLAGS_PACKED))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002692 return -EINVAL;
2693
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002694 return 0;
2695}
2696
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002697static int bttv_g_fbuf(struct file *file, void *f,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002698 struct v4l2_framebuffer *fb)
2699{
2700 struct bttv_fh *fh = f;
2701 struct bttv *btv = fh->btv;
2702
2703 *fb = btv->fbuf;
2704 fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
2705 if (fh->ovfmt)
2706 fb->fmt.pixelformat = fh->ovfmt->fourcc;
2707 return 0;
2708}
2709
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002710static int bttv_overlay(struct file *file, void *f, unsigned int on)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002711{
2712 struct bttv_fh *fh = f;
2713 struct bttv *btv = fh->btv;
2714 struct bttv_buffer *new;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002715 int retval = 0;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002716
2717 if (on) {
2718 /* verify args */
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002719 if (unlikely(!btv->fbuf.base)) {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002720 return -EINVAL;
2721 }
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002722 if (unlikely(!fh->ov.setup_ok)) {
Joe Perches8af443e2011-08-21 19:56:48 -03002723 dprintk("%d: overlay: !setup_ok\n", btv->c.nr);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002724 retval = -EINVAL;
2725 }
2726 if (retval)
2727 return retval;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002728 }
2729
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002730 if (!check_alloc_btres_lock(btv, fh, RESOURCE_OVERLAY))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002731 return -EBUSY;
2732
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002733 if (on) {
2734 fh->ov.tvnorm = btv->tvnorm;
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03002735 new = videobuf_sg_alloc(sizeof(*new));
Robert Fitzsimons7c018802008-02-13 16:38:11 -03002736 new->crop = btv->crop[!!fh->do_crop].rect;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002737 bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
2738 } else {
2739 new = NULL;
2740 }
2741
2742 /* switch over */
2743 retval = bttv_switch_overlay(btv, fh, new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002744 return retval;
2745}
2746
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002747static int bttv_s_fbuf(struct file *file, void *f,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002748 struct v4l2_framebuffer *fb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002750 struct bttv_fh *fh = f;
2751 struct bttv *btv = fh->btv;
2752 const struct bttv_format *fmt;
2753 int retval;
2754
2755 if (!capable(CAP_SYS_ADMIN) &&
2756 !capable(CAP_SYS_RAWIO))
2757 return -EPERM;
2758
2759 /* check args */
2760 fmt = format_by_fourcc(fb->fmt.pixelformat);
2761 if (NULL == fmt)
2762 return -EINVAL;
2763 if (0 == (fmt->flags & FORMAT_FLAGS_PACKED))
2764 return -EINVAL;
2765
2766 retval = -EINVAL;
2767 if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
2768 __s32 width = fb->fmt.width;
2769 __s32 height = fb->fmt.height;
2770
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002771 retval = limit_scaled_size_lock(fh, &width, &height,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002772 V4L2_FIELD_INTERLACED,
2773 /* width_mask */ ~3,
2774 /* width_bias */ 2,
2775 /* adjust_size */ 0,
2776 /* adjust_crop */ 0);
2777 if (0 != retval)
2778 return retval;
2779 }
2780
2781 /* ok, accept it */
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002782 btv->fbuf.base = fb->base;
2783 btv->fbuf.fmt.width = fb->fmt.width;
2784 btv->fbuf.fmt.height = fb->fmt.height;
2785 if (0 != fb->fmt.bytesperline)
2786 btv->fbuf.fmt.bytesperline = fb->fmt.bytesperline;
2787 else
2788 btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fmt->depth/8;
2789
2790 retval = 0;
2791 fh->ovfmt = fmt;
2792 btv->init.ovfmt = fmt;
2793 if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
2794 fh->ov.w.left = 0;
2795 fh->ov.w.top = 0;
2796 fh->ov.w.width = fb->fmt.width;
2797 fh->ov.w.height = fb->fmt.height;
2798 btv->init.ov.w.width = fb->fmt.width;
2799 btv->init.ov.w.height = fb->fmt.height;
2800 kfree(fh->ov.clips);
2801 fh->ov.clips = NULL;
2802 fh->ov.nclips = 0;
2803
2804 if (check_btres(fh, RESOURCE_OVERLAY)) {
2805 struct bttv_buffer *new;
2806
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03002807 new = videobuf_sg_alloc(sizeof(*new));
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002808 new->crop = btv->crop[!!fh->do_crop].rect;
2809 bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
2810 retval = bttv_switch_overlay(btv, fh, new);
2811 }
2812 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002813 return retval;
2814}
2815
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002816static int bttv_reqbufs(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002817 struct v4l2_requestbuffers *p)
2818{
2819 struct bttv_fh *fh = priv;
2820 return videobuf_reqbufs(bttv_queue(fh), p);
2821}
2822
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002823static int bttv_querybuf(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002824 struct v4l2_buffer *b)
2825{
2826 struct bttv_fh *fh = priv;
2827 return videobuf_querybuf(bttv_queue(fh), b);
2828}
2829
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002830static int bttv_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002831{
2832 struct bttv_fh *fh = priv;
2833 struct bttv *btv = fh->btv;
2834 int res = bttv_resource(fh);
2835
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002836 if (!check_alloc_btres_lock(btv, fh, res))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002837 return -EBUSY;
2838
2839 return videobuf_qbuf(bttv_queue(fh), b);
2840}
2841
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002842static int bttv_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002843{
2844 struct bttv_fh *fh = priv;
2845 return videobuf_dqbuf(bttv_queue(fh), b,
2846 file->f_flags & O_NONBLOCK);
2847}
2848
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002849static int bttv_streamon(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002850 enum v4l2_buf_type type)
2851{
2852 struct bttv_fh *fh = priv;
2853 struct bttv *btv = fh->btv;
2854 int res = bttv_resource(fh);
2855
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002856 if (!check_alloc_btres_lock(btv, fh, res))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002857 return -EBUSY;
2858 return videobuf_streamon(bttv_queue(fh));
2859}
2860
2861
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002862static int bttv_streamoff(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002863 enum v4l2_buf_type type)
2864{
2865 struct bttv_fh *fh = priv;
2866 struct bttv *btv = fh->btv;
2867 int retval;
2868 int res = bttv_resource(fh);
2869
2870
2871 retval = videobuf_streamoff(bttv_queue(fh));
2872 if (retval < 0)
2873 return retval;
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002874 free_btres_lock(btv, fh, res);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002875 return 0;
2876}
2877
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002878static int bttv_queryctrl(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002879 struct v4l2_queryctrl *c)
2880{
2881 struct bttv_fh *fh = priv;
2882 struct bttv *btv = fh->btv;
2883 const struct v4l2_queryctrl *ctrl;
2884
2885 if ((c->id < V4L2_CID_BASE ||
2886 c->id >= V4L2_CID_LASTP1) &&
2887 (c->id < V4L2_CID_PRIVATE_BASE ||
2888 c->id >= V4L2_CID_PRIVATE_LASTP1))
2889 return -EINVAL;
2890
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002891 if (!btv->volume_gpio && (c->id == V4L2_CID_AUDIO_VOLUME))
2892 *c = no_ctl;
2893 else {
2894 ctrl = ctrl_by_id(c->id);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002895
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002896 *c = (NULL != ctrl) ? *ctrl : no_ctl;
2897 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002898
2899 return 0;
2900}
2901
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002902static int bttv_g_parm(struct file *file, void *f,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002903 struct v4l2_streamparm *parm)
2904{
2905 struct bttv_fh *fh = f;
2906 struct bttv *btv = fh->btv;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002907
Trent Piepho51f0b8d52009-03-04 01:21:02 -03002908 v4l2_video_std_frame_period(bttv_tvnorms[btv->tvnorm].v4l2_id,
2909 &parm->parm.capture.timeperframe);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002910
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002911 return 0;
2912}
2913
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002914static int bttv_g_tuner(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002915 struct v4l2_tuner *t)
2916{
2917 struct bttv_fh *fh = priv;
2918 struct bttv *btv = fh->btv;
2919
Trent Piephoabb03622009-01-28 21:32:59 -03002920 if (btv->tuner_type == TUNER_ABSENT)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002921 return -EINVAL;
2922 if (0 != t->index)
2923 return -EINVAL;
2924
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002925 t->rxsubchans = V4L2_TUNER_SUB_MONO;
Hans Verkuil859f0272009-03-28 08:29:00 -03002926 bttv_call_all(btv, tuner, g_tuner, t);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002927 strcpy(t->name, "Television");
2928 t->capability = V4L2_TUNER_CAP_NORM;
2929 t->type = V4L2_TUNER_ANALOG_TV;
2930 if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)
2931 t->signal = 0xffff;
2932
2933 if (btv->audio_mode_gpio)
2934 btv->audio_mode_gpio(btv, t, 0);
2935
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002936 return 0;
2937}
2938
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002939static int bttv_g_priority(struct file *file, void *f, enum v4l2_priority *p)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002940{
2941 struct bttv_fh *fh = f;
2942 struct bttv *btv = fh->btv;
2943
2944 *p = v4l2_prio_max(&btv->prio);
2945
2946 return 0;
2947}
2948
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002949static int bttv_s_priority(struct file *file, void *f,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002950 enum v4l2_priority prio)
2951{
2952 struct bttv_fh *fh = f;
2953 struct bttv *btv = fh->btv;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002954 int rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002955
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002956 rc = v4l2_prio_change(&btv->prio, &fh->prio, prio);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002957
2958 return rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002959}
2960
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002961static int bttv_cropcap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002962 struct v4l2_cropcap *cap)
2963{
2964 struct bttv_fh *fh = priv;
2965 struct bttv *btv = fh->btv;
2966
2967 if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
2968 cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
2969 return -EINVAL;
2970
2971 *cap = bttv_tvnorms[btv->tvnorm].cropcap;
2972
2973 return 0;
2974}
2975
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002976static int bttv_g_crop(struct file *file, void *f, struct v4l2_crop *crop)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002977{
2978 struct bttv_fh *fh = f;
2979 struct bttv *btv = fh->btv;
2980
2981 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
2982 crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
2983 return -EINVAL;
2984
2985 /* No fh->do_crop = 1; because btv->crop[1] may be
2986 inconsistent with fh->width or fh->height and apps
2987 do not expect a change here. */
2988
2989 crop->c = btv->crop[!!fh->do_crop].rect;
2990
2991 return 0;
2992}
2993
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002994static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002995{
2996 struct bttv_fh *fh = f;
2997 struct bttv *btv = fh->btv;
2998 const struct v4l2_rect *b;
2999 int retval;
3000 struct bttv_crop c;
3001 __s32 b_left;
3002 __s32 b_top;
3003 __s32 b_right;
3004 __s32 b_bottom;
3005
3006 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
3007 crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
3008 return -EINVAL;
3009
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003010 /* Make sure tvnorm, vbi_end and the current cropping
3011 parameters remain consistent until we're done. Note
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003012 read() may change vbi_end in check_alloc_btres_lock(). */
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003013 retval = v4l2_prio_check(&btv->prio, fh->prio);
3014 if (0 != retval) {
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003015 return retval;
3016 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003017
3018 retval = -EBUSY;
3019
3020 if (locked_btres(fh->btv, VIDEO_RESOURCES)) {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003021 return retval;
3022 }
3023
3024 b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
3025
3026 b_left = b->left;
3027 b_right = b_left + b->width;
3028 b_bottom = b->top + b->height;
3029
3030 b_top = max(b->top, btv->vbi_end);
3031 if (b_top + 32 >= b_bottom) {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003032 return retval;
3033 }
3034
3035 /* Min. scaled size 48 x 32. */
3036 c.rect.left = clamp(crop->c.left, b_left, b_right - 48);
3037 c.rect.left = min(c.rect.left, (__s32) MAX_HDELAY);
3038
3039 c.rect.width = clamp(crop->c.width,
3040 48, b_right - c.rect.left);
3041
3042 c.rect.top = clamp(crop->c.top, b_top, b_bottom - 32);
3043 /* Top and height must be a multiple of two. */
3044 c.rect.top = (c.rect.top + 1) & ~1;
3045
3046 c.rect.height = clamp(crop->c.height,
3047 32, b_bottom - c.rect.top);
3048 c.rect.height = (c.rect.height + 1) & ~1;
3049
3050 bttv_crop_calc_limits(&c);
3051
3052 btv->crop[1] = c;
3053
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003054 fh->do_crop = 1;
3055
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003056 if (fh->width < c.min_scaled_width) {
3057 fh->width = c.min_scaled_width;
3058 btv->init.width = c.min_scaled_width;
3059 } else if (fh->width > c.max_scaled_width) {
3060 fh->width = c.max_scaled_width;
3061 btv->init.width = c.max_scaled_width;
3062 }
3063
3064 if (fh->height < c.min_scaled_height) {
3065 fh->height = c.min_scaled_height;
3066 btv->init.height = c.min_scaled_height;
3067 } else if (fh->height > c.max_scaled_height) {
3068 fh->height = c.max_scaled_height;
3069 btv->init.height = c.max_scaled_height;
3070 }
3071
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003072 return 0;
3073}
3074
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003075static int bttv_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003076{
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03003077 if (unlikely(a->index))
3078 return -EINVAL;
3079
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003080 strcpy(a->name, "audio");
3081 return 0;
3082}
3083
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003084static int bttv_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003085{
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03003086 if (unlikely(a->index))
3087 return -EINVAL;
3088
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003089 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003090}
3091
3092static ssize_t bttv_read(struct file *file, char __user *data,
3093 size_t count, loff_t *ppos)
3094{
3095 struct bttv_fh *fh = file->private_data;
3096 int retval = 0;
3097
3098 if (fh->btv->errors)
3099 bttv_reinit_bt848(fh->btv);
Joe Perches8af443e2011-08-21 19:56:48 -03003100 dprintk("%d: read count=%d type=%s\n",
3101 fh->btv->c.nr, (int)count, v4l2_type_names[fh->type]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003102
3103 switch (fh->type) {
3104 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003105 if (!check_alloc_btres_lock(fh->btv, fh, RESOURCE_VIDEO_READ)) {
Michael Schimeke5bd0262007-01-18 16:17:39 -03003106 /* VIDEO_READ in use by another fh,
3107 or VIDEO_STREAM by any fh. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003108 return -EBUSY;
Michael Schimeke5bd0262007-01-18 16:17:39 -03003109 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003110 retval = videobuf_read_one(&fh->cap, data, count, ppos,
3111 file->f_flags & O_NONBLOCK);
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003112 free_btres_lock(fh->btv, fh, RESOURCE_VIDEO_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003113 break;
3114 case V4L2_BUF_TYPE_VBI_CAPTURE:
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003115 if (!check_alloc_btres_lock(fh->btv,fh,RESOURCE_VBI))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003116 return -EBUSY;
3117 retval = videobuf_read_stream(&fh->vbi, data, count, ppos, 1,
3118 file->f_flags & O_NONBLOCK);
3119 break;
3120 default:
3121 BUG();
3122 }
3123 return retval;
3124}
3125
3126static unsigned int bttv_poll(struct file *file, poll_table *wait)
3127{
3128 struct bttv_fh *fh = file->private_data;
3129 struct bttv_buffer *buf;
3130 enum v4l2_field field;
Figo.zhang9fd64182009-06-16 13:31:29 -03003131 unsigned int rc = POLLERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003132
3133 if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003134 if (!check_alloc_btres_lock(fh->btv,fh,RESOURCE_VBI))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003135 return POLLERR;
3136 return videobuf_poll_stream(file, &fh->vbi, wait);
3137 }
3138
Michael Schimeke5bd0262007-01-18 16:17:39 -03003139 if (check_btres(fh,RESOURCE_VIDEO_STREAM)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003140 /* streaming capture */
3141 if (list_empty(&fh->cap.stream))
Figo.zhang9fd64182009-06-16 13:31:29 -03003142 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003143 buf = list_entry(fh->cap.stream.next,struct bttv_buffer,vb.stream);
3144 } else {
3145 /* read() capture */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003146 if (NULL == fh->cap.read_buf) {
3147 /* need to capture a new frame */
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03003148 if (locked_btres(fh->btv,RESOURCE_VIDEO_STREAM))
3149 goto err;
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03003150 fh->cap.read_buf = videobuf_sg_alloc(fh->cap.msize);
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03003151 if (NULL == fh->cap.read_buf)
3152 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003153 fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR;
3154 field = videobuf_next_field(&fh->cap);
3155 if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,field)) {
Nickolay V. Shmyrev50ab5ed2005-12-01 00:51:32 -08003156 kfree (fh->cap.read_buf);
3157 fh->cap.read_buf = NULL;
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03003158 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003159 }
3160 fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf);
3161 fh->cap.read_off = 0;
3162 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003163 buf = (struct bttv_buffer*)fh->cap.read_buf;
3164 }
3165
3166 poll_wait(file, &buf->vb.done, wait);
Brandon Philips0fc06862007-11-06 20:02:36 -03003167 if (buf->vb.state == VIDEOBUF_DONE ||
3168 buf->vb.state == VIDEOBUF_ERROR)
Figo.zhang9fd64182009-06-16 13:31:29 -03003169 rc = POLLIN|POLLRDNORM;
3170 else
3171 rc = 0;
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03003172err:
Figo.zhang9fd64182009-06-16 13:31:29 -03003173 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003174}
3175
Hans Verkuilbec43662008-12-30 06:58:20 -03003176static int bttv_open(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003177{
Laurent Pinchart50462eb2009-12-10 11:47:13 -02003178 struct video_device *vdev = video_devdata(file);
Trent Piepho4b10d3b2009-01-28 21:32:59 -03003179 struct bttv *btv = video_drvdata(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003180 struct bttv_fh *fh;
3181 enum v4l2_buf_type type = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003182
Joe Perches8af443e2011-08-21 19:56:48 -03003183 dprintk("open dev=%s\n", video_device_node_name(vdev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003184
Laurent Pinchart327ae592009-11-27 13:57:55 -03003185 if (vdev->vfl_type == VFL_TYPE_GRABBER) {
Trent Piepho4b10d3b2009-01-28 21:32:59 -03003186 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Laurent Pinchart327ae592009-11-27 13:57:55 -03003187 } else if (vdev->vfl_type == VFL_TYPE_VBI) {
Trent Piepho4b10d3b2009-01-28 21:32:59 -03003188 type = V4L2_BUF_TYPE_VBI_CAPTURE;
3189 } else {
3190 WARN_ON(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003191 return -ENODEV;
Hans Verkuild56dc612008-07-30 08:43:36 -03003192 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003193
Joe Perches8af443e2011-08-21 19:56:48 -03003194 dprintk("%d: open called (type=%s)\n",
3195 btv->c.nr, v4l2_type_names[type]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003196
3197 /* allocate per filehandle data */
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003198 fh = kmalloc(sizeof(*fh), GFP_KERNEL);
3199 if (unlikely(!fh))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003200 return -ENOMEM;
3201 file->private_data = fh;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003202
Linus Torvalds1da177e2005-04-16 15:20:36 -07003203 *fh = btv->init;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003204
Linus Torvalds1da177e2005-04-16 15:20:36 -07003205 fh->type = type;
3206 fh->ov.setup_ok = 0;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003207
Hans Verkuilffb48772010-05-01 08:03:24 -03003208 v4l2_prio_open(&btv->prio, &fh->prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003209
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03003210 videobuf_queue_sg_init(&fh->cap, &bttv_video_qops,
3211 &btv->c.pci->dev, &btv->s_lock,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003212 V4L2_BUF_TYPE_VIDEO_CAPTURE,
3213 V4L2_FIELD_INTERLACED,
3214 sizeof(struct bttv_buffer),
Mauro Carvalho Chehab587f0d52010-12-15 18:45:42 -03003215 fh, &btv->lock);
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03003216 videobuf_queue_sg_init(&fh->vbi, &bttv_vbi_qops,
3217 &btv->c.pci->dev, &btv->s_lock,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003218 V4L2_BUF_TYPE_VBI_CAPTURE,
3219 V4L2_FIELD_SEQ_TB,
3220 sizeof(struct bttv_buffer),
Mauro Carvalho Chehab587f0d52010-12-15 18:45:42 -03003221 fh, &btv->lock);
Nickolay V. Shmyrev302f61a2007-10-26 10:53:21 -03003222 set_tvnorm(btv,btv->tvnorm);
Mauro Carvalho Chehabb46a9c82008-08-05 10:12:35 -03003223 set_input(btv, btv->input, btv->tvnorm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003224
3225 btv->users++;
Michael Schimeke5bd0262007-01-18 16:17:39 -03003226
3227 /* The V4L2 spec requires one global set of cropping parameters
3228 which only change on request. These are stored in btv->crop[1].
3229 However for compatibility with V4L apps and cropping unaware
3230 V4L2 apps we now reset the cropping parameters as seen through
3231 this fh, which is to say VIDIOC_G_CROP and scaling limit checks
3232 will use btv->crop[0], the default cropping parameters for the
3233 current video standard, and VIDIOC_S_FMT will not implicitely
3234 change the cropping parameters until VIDIOC_S_CROP has been
3235 called. */
3236 fh->do_crop = !reset_crop; /* module parameter */
3237
3238 /* Likewise there should be one global set of VBI capture
3239 parameters, but for compatibility with V4L apps and earlier
3240 driver versions each fh has its own parameters. */
3241 bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm);
3242
Linus Torvalds1da177e2005-04-16 15:20:36 -07003243 bttv_field_count(btv);
3244 return 0;
3245}
3246
Hans Verkuilbec43662008-12-30 06:58:20 -03003247static int bttv_release(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003248{
3249 struct bttv_fh *fh = file->private_data;
3250 struct bttv *btv = fh->btv;
3251
3252 /* turn off overlay */
3253 if (check_btres(fh, RESOURCE_OVERLAY))
3254 bttv_switch_overlay(btv,fh,NULL);
3255
3256 /* stop video capture */
Michael Schimeke5bd0262007-01-18 16:17:39 -03003257 if (check_btres(fh, RESOURCE_VIDEO_STREAM)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003258 videobuf_streamoff(&fh->cap);
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003259 free_btres_lock(btv,fh,RESOURCE_VIDEO_STREAM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003260 }
3261 if (fh->cap.read_buf) {
3262 buffer_release(&fh->cap,fh->cap.read_buf);
3263 kfree(fh->cap.read_buf);
3264 }
Michael Schimeke5bd0262007-01-18 16:17:39 -03003265 if (check_btres(fh, RESOURCE_VIDEO_READ)) {
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003266 free_btres_lock(btv, fh, RESOURCE_VIDEO_READ);
Michael Schimeke5bd0262007-01-18 16:17:39 -03003267 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003268
3269 /* stop vbi capture */
3270 if (check_btres(fh, RESOURCE_VBI)) {
Brandon Philips053fcb62007-11-13 20:11:26 -03003271 videobuf_stop(&fh->vbi);
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003272 free_btres_lock(btv,fh,RESOURCE_VBI);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003273 }
3274
3275 /* free stuff */
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003276
Linus Torvalds1da177e2005-04-16 15:20:36 -07003277 videobuf_mmap_free(&fh->cap);
3278 videobuf_mmap_free(&fh->vbi);
Hans Verkuilffb48772010-05-01 08:03:24 -03003279 v4l2_prio_close(&btv->prio, fh->prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003280 file->private_data = NULL;
3281 kfree(fh);
3282
3283 btv->users--;
3284 bttv_field_count(btv);
Mauro Carvalho Chehabb46a9c82008-08-05 10:12:35 -03003285
3286 if (!btv->users)
3287 audio_mute(btv, 1);
3288
Linus Torvalds1da177e2005-04-16 15:20:36 -07003289 return 0;
3290}
3291
3292static int
3293bttv_mmap(struct file *file, struct vm_area_struct *vma)
3294{
3295 struct bttv_fh *fh = file->private_data;
3296
Joe Perches8af443e2011-08-21 19:56:48 -03003297 dprintk("%d: mmap type=%s 0x%lx+%ld\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003298 fh->btv->c.nr, v4l2_type_names[fh->type],
3299 vma->vm_start, vma->vm_end - vma->vm_start);
3300 return videobuf_mmap_mapper(bttv_queue(fh),vma);
3301}
3302
Hans Verkuilbec43662008-12-30 06:58:20 -03003303static const struct v4l2_file_operations bttv_fops =
Linus Torvalds1da177e2005-04-16 15:20:36 -07003304{
Mauro Carvalho Chehab8979e9d2010-09-15 08:22:09 -03003305 .owner = THIS_MODULE,
3306 .open = bttv_open,
3307 .release = bttv_release,
3308 .unlocked_ioctl = video_ioctl2,
3309 .read = bttv_read,
3310 .mmap = bttv_mmap,
3311 .poll = bttv_poll,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003312};
3313
Hans Verkuila3998102008-07-21 02:57:38 -03003314static const struct v4l2_ioctl_ops bttv_ioctl_ops = {
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003315 .vidioc_querycap = bttv_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03003316 .vidioc_enum_fmt_vid_cap = bttv_enum_fmt_vid_cap,
3317 .vidioc_g_fmt_vid_cap = bttv_g_fmt_vid_cap,
3318 .vidioc_try_fmt_vid_cap = bttv_try_fmt_vid_cap,
3319 .vidioc_s_fmt_vid_cap = bttv_s_fmt_vid_cap,
3320 .vidioc_enum_fmt_vid_overlay = bttv_enum_fmt_vid_overlay,
3321 .vidioc_g_fmt_vid_overlay = bttv_g_fmt_vid_overlay,
3322 .vidioc_try_fmt_vid_overlay = bttv_try_fmt_vid_overlay,
3323 .vidioc_s_fmt_vid_overlay = bttv_s_fmt_vid_overlay,
Hans Verkuil78b526a2008-05-28 12:16:41 -03003324 .vidioc_g_fmt_vbi_cap = bttv_g_fmt_vbi_cap,
3325 .vidioc_try_fmt_vbi_cap = bttv_try_fmt_vbi_cap,
3326 .vidioc_s_fmt_vbi_cap = bttv_s_fmt_vbi_cap,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003327 .vidioc_g_audio = bttv_g_audio,
3328 .vidioc_s_audio = bttv_s_audio,
3329 .vidioc_cropcap = bttv_cropcap,
3330 .vidioc_reqbufs = bttv_reqbufs,
3331 .vidioc_querybuf = bttv_querybuf,
3332 .vidioc_qbuf = bttv_qbuf,
3333 .vidioc_dqbuf = bttv_dqbuf,
3334 .vidioc_s_std = bttv_s_std,
3335 .vidioc_enum_input = bttv_enum_input,
3336 .vidioc_g_input = bttv_g_input,
3337 .vidioc_s_input = bttv_s_input,
3338 .vidioc_queryctrl = bttv_queryctrl,
3339 .vidioc_g_ctrl = bttv_g_ctrl,
3340 .vidioc_s_ctrl = bttv_s_ctrl,
3341 .vidioc_streamon = bttv_streamon,
3342 .vidioc_streamoff = bttv_streamoff,
3343 .vidioc_g_tuner = bttv_g_tuner,
3344 .vidioc_s_tuner = bttv_s_tuner,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003345 .vidioc_g_crop = bttv_g_crop,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003346 .vidioc_s_crop = bttv_s_crop,
3347 .vidioc_g_fbuf = bttv_g_fbuf,
3348 .vidioc_s_fbuf = bttv_s_fbuf,
3349 .vidioc_overlay = bttv_overlay,
3350 .vidioc_g_priority = bttv_g_priority,
3351 .vidioc_s_priority = bttv_s_priority,
3352 .vidioc_g_parm = bttv_g_parm,
3353 .vidioc_g_frequency = bttv_g_frequency,
3354 .vidioc_s_frequency = bttv_s_frequency,
3355 .vidioc_log_status = bttv_log_status,
3356 .vidioc_querystd = bttv_querystd,
Zoltan Devai43846832008-01-14 13:24:38 -03003357#ifdef CONFIG_VIDEO_ADV_DEBUG
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003358 .vidioc_g_register = bttv_g_register,
3359 .vidioc_s_register = bttv_s_register,
Zoltan Devai43846832008-01-14 13:24:38 -03003360#endif
Hans Verkuila3998102008-07-21 02:57:38 -03003361};
3362
3363static struct video_device bttv_video_template = {
3364 .fops = &bttv_fops,
Hans Verkuila3998102008-07-21 02:57:38 -03003365 .ioctl_ops = &bttv_ioctl_ops,
3366 .tvnorms = BTTV_NORMS,
3367 .current_norm = V4L2_STD_PAL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003368};
3369
Linus Torvalds1da177e2005-04-16 15:20:36 -07003370/* ----------------------------------------------------------------------- */
3371/* radio interface */
3372
Hans Verkuilbec43662008-12-30 06:58:20 -03003373static int radio_open(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003374{
Laurent Pinchart50462eb2009-12-10 11:47:13 -02003375 struct video_device *vdev = video_devdata(file);
Trent Piepho4b10d3b2009-01-28 21:32:59 -03003376 struct bttv *btv = video_drvdata(file);
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003377 struct bttv_fh *fh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003378
Joe Perches8af443e2011-08-21 19:56:48 -03003379 dprintk("open dev=%s\n", video_device_node_name(vdev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003380
Joe Perches8af443e2011-08-21 19:56:48 -03003381 dprintk("%d: open called (radio)\n", btv->c.nr);
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003382
3383 /* allocate per filehandle data */
3384 fh = kmalloc(sizeof(*fh), GFP_KERNEL);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003385 if (unlikely(!fh))
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003386 return -ENOMEM;
3387 file->private_data = fh;
3388 *fh = btv->init;
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003389
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003390 v4l2_prio_open(&btv->prio, &fh->prio);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003391
Linus Torvalds1da177e2005-04-16 15:20:36 -07003392 btv->radio_user++;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003393
Hans Verkuil859f0272009-03-28 08:29:00 -03003394 bttv_call_all(btv, tuner, s_radio);
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03003395 audio_input(btv,TVAUDIO_INPUT_RADIO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003396
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003397 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003398}
3399
Hans Verkuilbec43662008-12-30 06:58:20 -03003400static int radio_release(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003401{
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003402 struct bttv_fh *fh = file->private_data;
3403 struct bttv *btv = fh->btv;
Hans Verkuilb9218f22010-12-27 12:22:46 -03003404 struct saa6588_command cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405
Hans Verkuilffb48772010-05-01 08:03:24 -03003406 v4l2_prio_close(&btv->prio, fh->prio);
Robert Fitzsimonsb9bc07a2008-04-10 09:40:31 -03003407 file->private_data = NULL;
3408 kfree(fh);
3409
Linus Torvalds1da177e2005-04-16 15:20:36 -07003410 btv->radio_user--;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003411
Hans Verkuilb9218f22010-12-27 12:22:46 -03003412 bttv_call_all(btv, core, ioctl, SAA6588_CMD_CLOSE, &cmd);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003413
Linus Torvalds1da177e2005-04-16 15:20:36 -07003414 return 0;
3415}
3416
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003417static int radio_querycap(struct file *file, void *priv,
3418 struct v4l2_capability *cap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003419{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003420 struct bttv_fh *fh = priv;
3421 struct bttv *btv = fh->btv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003422
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003423 strcpy(cap->driver, "bttv");
3424 strlcpy(cap->card, btv->radio_dev->name, sizeof(cap->card));
3425 sprintf(cap->bus_info, "PCI:%s", pci_name(btv->c.pci));
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003426 cap->capabilities = V4L2_CAP_TUNER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003427
Linus Torvalds1da177e2005-04-16 15:20:36 -07003428 return 0;
3429}
3430
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003431static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003432{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003433 struct bttv_fh *fh = priv;
3434 struct bttv *btv = fh->btv;
3435
Trent Piephoabb03622009-01-28 21:32:59 -03003436 if (btv->tuner_type == TUNER_ABSENT)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003437 return -EINVAL;
3438 if (0 != t->index)
3439 return -EINVAL;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003440 strcpy(t->name, "Radio");
3441 t->type = V4L2_TUNER_RADIO;
3442
Hans Verkuil859f0272009-03-28 08:29:00 -03003443 bttv_call_all(btv, tuner, g_tuner, t);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003444
3445 if (btv->audio_mode_gpio)
3446 btv->audio_mode_gpio(btv, t, 0);
3447
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003448 return 0;
3449}
3450
3451static int radio_enum_input(struct file *file, void *priv,
3452 struct v4l2_input *i)
3453{
3454 if (i->index != 0)
3455 return -EINVAL;
3456
3457 strcpy(i->name, "Radio");
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03003458 i->type = V4L2_INPUT_TYPE_TUNER;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003459
3460 return 0;
3461}
3462
3463static int radio_g_audio(struct file *file, void *priv,
3464 struct v4l2_audio *a)
3465{
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03003466 if (unlikely(a->index))
Cyrill Gorcunov1a002eb2008-04-01 17:49:13 -03003467 return -EINVAL;
3468
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003469 strcpy(a->name, "Radio");
Cyrill Gorcunov1a002eb2008-04-01 17:49:13 -03003470
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003471 return 0;
3472}
3473
3474static int radio_s_tuner(struct file *file, void *priv,
3475 struct v4l2_tuner *t)
3476{
3477 struct bttv_fh *fh = priv;
3478 struct bttv *btv = fh->btv;
3479
3480 if (0 != t->index)
3481 return -EINVAL;
3482
Hans Verkuila024c1a2011-06-12 07:02:43 -03003483 bttv_call_all(btv, tuner, s_tuner, t);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003484 return 0;
3485}
3486
3487static int radio_s_audio(struct file *file, void *priv,
3488 struct v4l2_audio *a)
3489{
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03003490 if (unlikely(a->index))
3491 return -EINVAL;
3492
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003493 return 0;
3494}
3495
3496static int radio_s_input(struct file *filp, void *priv, unsigned int i)
3497{
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03003498 if (unlikely(i))
3499 return -EINVAL;
3500
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003501 return 0;
3502}
3503
3504static int radio_s_std(struct file *file, void *fh, v4l2_std_id *norm)
3505{
3506 return 0;
3507}
3508
3509static int radio_queryctrl(struct file *file, void *priv,
3510 struct v4l2_queryctrl *c)
3511{
3512 const struct v4l2_queryctrl *ctrl;
3513
3514 if (c->id < V4L2_CID_BASE ||
3515 c->id >= V4L2_CID_LASTP1)
3516 return -EINVAL;
3517
3518 if (c->id == V4L2_CID_AUDIO_MUTE) {
3519 ctrl = ctrl_by_id(c->id);
3520 *c = *ctrl;
3521 } else
3522 *c = no_ctl;
3523
3524 return 0;
3525}
3526
3527static int radio_g_input(struct file *filp, void *priv, unsigned int *i)
3528{
3529 *i = 0;
3530 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003531}
3532
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003533static ssize_t radio_read(struct file *file, char __user *data,
3534 size_t count, loff_t *ppos)
3535{
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003536 struct bttv_fh *fh = file->private_data;
3537 struct bttv *btv = fh->btv;
Hans Verkuilb9218f22010-12-27 12:22:46 -03003538 struct saa6588_command cmd;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003539 cmd.block_count = count/3;
3540 cmd.buffer = data;
3541 cmd.instance = file;
3542 cmd.result = -ENODEV;
3543
Hans Verkuilb9218f22010-12-27 12:22:46 -03003544 bttv_call_all(btv, core, ioctl, SAA6588_CMD_READ, &cmd);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003545
3546 return cmd.result;
3547}
3548
3549static unsigned int radio_poll(struct file *file, poll_table *wait)
3550{
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003551 struct bttv_fh *fh = file->private_data;
3552 struct bttv *btv = fh->btv;
Hans Verkuilb9218f22010-12-27 12:22:46 -03003553 struct saa6588_command cmd;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003554 cmd.instance = file;
3555 cmd.event_list = wait;
3556 cmd.result = -ENODEV;
Hans Verkuilb9218f22010-12-27 12:22:46 -03003557 bttv_call_all(btv, core, ioctl, SAA6588_CMD_POLL, &cmd);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003558
3559 return cmd.result;
3560}
3561
Hans Verkuilbec43662008-12-30 06:58:20 -03003562static const struct v4l2_file_operations radio_fops =
Linus Torvalds1da177e2005-04-16 15:20:36 -07003563{
3564 .owner = THIS_MODULE,
3565 .open = radio_open,
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003566 .read = radio_read,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003567 .release = radio_release,
Mauro Carvalho Chehab587f0d52010-12-15 18:45:42 -03003568 .unlocked_ioctl = video_ioctl2,
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003569 .poll = radio_poll,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003570};
3571
Hans Verkuila3998102008-07-21 02:57:38 -03003572static const struct v4l2_ioctl_ops radio_ioctl_ops = {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003573 .vidioc_querycap = radio_querycap,
3574 .vidioc_g_tuner = radio_g_tuner,
3575 .vidioc_enum_input = radio_enum_input,
3576 .vidioc_g_audio = radio_g_audio,
3577 .vidioc_s_tuner = radio_s_tuner,
3578 .vidioc_s_audio = radio_s_audio,
3579 .vidioc_s_input = radio_s_input,
3580 .vidioc_s_std = radio_s_std,
3581 .vidioc_queryctrl = radio_queryctrl,
3582 .vidioc_g_input = radio_g_input,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003583 .vidioc_g_ctrl = bttv_g_ctrl,
3584 .vidioc_s_ctrl = bttv_s_ctrl,
3585 .vidioc_g_frequency = bttv_g_frequency,
3586 .vidioc_s_frequency = bttv_s_frequency,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003587};
3588
Hans Verkuila3998102008-07-21 02:57:38 -03003589static struct video_device radio_template = {
3590 .fops = &radio_fops,
Hans Verkuila3998102008-07-21 02:57:38 -03003591 .ioctl_ops = &radio_ioctl_ops,
3592};
3593
Linus Torvalds1da177e2005-04-16 15:20:36 -07003594/* ----------------------------------------------------------------------- */
3595/* some debug code */
3596
Adrian Bunk408b6642005-05-01 08:59:29 -07003597static int bttv_risc_decode(u32 risc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003598{
3599 static char *instr[16] = {
3600 [ BT848_RISC_WRITE >> 28 ] = "write",
3601 [ BT848_RISC_SKIP >> 28 ] = "skip",
3602 [ BT848_RISC_WRITEC >> 28 ] = "writec",
3603 [ BT848_RISC_JUMP >> 28 ] = "jump",
3604 [ BT848_RISC_SYNC >> 28 ] = "sync",
3605 [ BT848_RISC_WRITE123 >> 28 ] = "write123",
3606 [ BT848_RISC_SKIP123 >> 28 ] = "skip123",
3607 [ BT848_RISC_WRITE1S23 >> 28 ] = "write1s23",
3608 };
3609 static int incr[16] = {
3610 [ BT848_RISC_WRITE >> 28 ] = 2,
3611 [ BT848_RISC_JUMP >> 28 ] = 2,
3612 [ BT848_RISC_SYNC >> 28 ] = 2,
3613 [ BT848_RISC_WRITE123 >> 28 ] = 5,
3614 [ BT848_RISC_SKIP123 >> 28 ] = 2,
3615 [ BT848_RISC_WRITE1S23 >> 28 ] = 3,
3616 };
3617 static char *bits[] = {
3618 "be0", "be1", "be2", "be3/resync",
3619 "set0", "set1", "set2", "set3",
3620 "clr0", "clr1", "clr2", "clr3",
3621 "irq", "res", "eol", "sol",
3622 };
3623 int i;
3624
Joe Perches8af443e2011-08-21 19:56:48 -03003625 pr_cont("0x%08x [ %s", risc,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003626 instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
3627 for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
3628 if (risc & (1 << (i + 12)))
Joe Perches8af443e2011-08-21 19:56:48 -03003629 pr_cont(" %s", bits[i]);
3630 pr_cont(" count=%d ]\n", risc & 0xfff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631 return incr[risc >> 28] ? incr[risc >> 28] : 1;
3632}
3633
Adrian Bunk408b6642005-05-01 08:59:29 -07003634static void bttv_risc_disasm(struct bttv *btv,
3635 struct btcx_riscmem *risc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003636{
3637 unsigned int i,j,n;
3638
Joe Perches8af443e2011-08-21 19:56:48 -03003639 pr_info("%s: risc disasm: %p [dma=0x%08lx]\n",
3640 btv->c.v4l2_dev.name, risc->cpu, (unsigned long)risc->dma);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003641 for (i = 0; i < (risc->size >> 2); i += n) {
Joe Perches8af443e2011-08-21 19:56:48 -03003642 pr_info("%s: 0x%lx: ",
3643 btv->c.v4l2_dev.name,
3644 (unsigned long)(risc->dma + (i<<2)));
Al Viro3aa71102008-06-22 14:20:09 -03003645 n = bttv_risc_decode(le32_to_cpu(risc->cpu[i]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003646 for (j = 1; j < n; j++)
Joe Perches8af443e2011-08-21 19:56:48 -03003647 pr_info("%s: 0x%lx: 0x%08x [ arg #%d ]\n",
3648 btv->c.v4l2_dev.name,
3649 (unsigned long)(risc->dma + ((i+j)<<2)),
3650 risc->cpu[i+j], j);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651 if (0 == risc->cpu[i])
3652 break;
3653 }
3654}
3655
3656static void bttv_print_riscaddr(struct bttv *btv)
3657{
Joe Perches8af443e2011-08-21 19:56:48 -03003658 pr_info(" main: %08llx\n", (unsigned long long)btv->main.dma);
3659 pr_info(" vbi : o=%08llx e=%08llx\n",
3660 btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
3661 btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0);
3662 pr_info(" cap : o=%08llx e=%08llx\n",
3663 btv->curr.top
3664 ? (unsigned long long)btv->curr.top->top.dma : 0,
3665 btv->curr.bottom
3666 ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
3667 pr_info(" scr : o=%08llx e=%08llx\n",
3668 btv->screen ? (unsigned long long)btv->screen->top.dma : 0,
3669 btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003670 bttv_risc_disasm(btv, &btv->main);
3671}
3672
3673/* ----------------------------------------------------------------------- */
3674/* irq handler */
3675
3676static char *irq_name[] = {
3677 "FMTCHG", // format change detected (525 vs. 625)
3678 "VSYNC", // vertical sync (new field)
3679 "HSYNC", // horizontal sync
3680 "OFLOW", // chroma/luma AGC overflow
3681 "HLOCK", // horizontal lock changed
3682 "VPRES", // video presence changed
3683 "6", "7",
3684 "I2CDONE", // hw irc operation finished
3685 "GPINT", // gpio port triggered irq
3686 "10",
3687 "RISCI", // risc instruction triggered irq
3688 "FBUS", // pixel data fifo dropped data (high pci bus latencies)
3689 "FTRGT", // pixel data fifo overrun
3690 "FDSR", // fifo data stream resyncronisation
3691 "PPERR", // parity error (data transfer)
3692 "RIPERR", // parity error (read risc instructions)
3693 "PABORT", // pci abort
3694 "OCERR", // risc instruction error
3695 "SCERR", // syncronisation error
3696};
3697
3698static void bttv_print_irqbits(u32 print, u32 mark)
3699{
3700 unsigned int i;
3701
Joe Perches8af443e2011-08-21 19:56:48 -03003702 pr_cont("bits:");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003703 for (i = 0; i < ARRAY_SIZE(irq_name); i++) {
3704 if (print & (1 << i))
Joe Perches8af443e2011-08-21 19:56:48 -03003705 pr_cont(" %s", irq_name[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706 if (mark & (1 << i))
Joe Perches8af443e2011-08-21 19:56:48 -03003707 pr_cont("*");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003708 }
3709}
3710
3711static void bttv_irq_debug_low_latency(struct bttv *btv, u32 rc)
3712{
Joe Perches8af443e2011-08-21 19:56:48 -03003713 pr_warn("%d: irq: skipped frame [main=%lx,o_vbi=%lx,o_field=%lx,rc=%lx]\n",
3714 btv->c.nr,
3715 (unsigned long)btv->main.dma,
3716 (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_VBI+1]),
3717 (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_FIELD+1]),
3718 (unsigned long)rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003719
3720 if (0 == (btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC)) {
Joe Perches8af443e2011-08-21 19:56:48 -03003721 pr_notice("%d: Oh, there (temporarily?) is no input signal. "
3722 "Ok, then this is harmless, don't worry ;)\n",
3723 btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003724 return;
3725 }
Joe Perches8af443e2011-08-21 19:56:48 -03003726 pr_notice("%d: Uhm. Looks like we have unusual high IRQ latencies\n",
3727 btv->c.nr);
3728 pr_notice("%d: Lets try to catch the culpit red-handed ...\n",
3729 btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003730 dump_stack();
3731}
3732
3733static int
3734bttv_irq_next_video(struct bttv *btv, struct bttv_buffer_set *set)
3735{
3736 struct bttv_buffer *item;
3737
3738 memset(set,0,sizeof(*set));
3739
3740 /* capture request ? */
3741 if (!list_empty(&btv->capture)) {
3742 set->frame_irq = 1;
3743 item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
3744 if (V4L2_FIELD_HAS_TOP(item->vb.field))
3745 set->top = item;
3746 if (V4L2_FIELD_HAS_BOTTOM(item->vb.field))
3747 set->bottom = item;
3748
3749 /* capture request for other field ? */
3750 if (!V4L2_FIELD_HAS_BOTH(item->vb.field) &&
3751 (item->vb.queue.next != &btv->capture)) {
3752 item = list_entry(item->vb.queue.next, struct bttv_buffer, vb.queue);
Mike Isely66349b42009-09-21 12:09:08 -03003753 /* Mike Isely <isely@pobox.com> - Only check
3754 * and set up the bottom field in the logic
3755 * below. Don't ever do the top field. This
3756 * of course means that if we set up the
3757 * bottom field in the above code that we'll
3758 * actually skip a field. But that's OK.
3759 * Having processed only a single buffer this
3760 * time, then the next time around the first
3761 * available buffer should be for a top field.
3762 * That will then cause us here to set up a
3763 * top then a bottom field in the normal way.
3764 * The alternative to this understanding is
3765 * that we set up the second available buffer
3766 * as a top field, but that's out of order
3767 * since this driver always processes the top
3768 * field first - the effect will be the two
3769 * buffers being returned in the wrong order,
3770 * with the second buffer also being delayed
3771 * by one field time (owing to the fifo nature
3772 * of videobuf). Worse still, we'll be stuck
3773 * doing fields out of order now every time
3774 * until something else causes a field to be
3775 * dropped. By effectively forcing a field to
3776 * drop this way then we always get back into
3777 * sync within a single frame time. (Out of
3778 * order fields can screw up deinterlacing
3779 * algorithms.) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003780 if (!V4L2_FIELD_HAS_BOTH(item->vb.field)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003781 if (NULL == set->bottom &&
3782 V4L2_FIELD_BOTTOM == item->vb.field) {
3783 set->bottom = item;
3784 }
3785 if (NULL != set->top && NULL != set->bottom)
3786 set->top_irq = 2;
3787 }
3788 }
3789 }
3790
3791 /* screen overlay ? */
3792 if (NULL != btv->screen) {
3793 if (V4L2_FIELD_HAS_BOTH(btv->screen->vb.field)) {
3794 if (NULL == set->top && NULL == set->bottom) {
3795 set->top = btv->screen;
3796 set->bottom = btv->screen;
3797 }
3798 } else {
3799 if (V4L2_FIELD_TOP == btv->screen->vb.field &&
3800 NULL == set->top) {
3801 set->top = btv->screen;
3802 }
3803 if (V4L2_FIELD_BOTTOM == btv->screen->vb.field &&
3804 NULL == set->bottom) {
3805 set->bottom = btv->screen;
3806 }
3807 }
3808 }
3809
Joe Perches8af443e2011-08-21 19:56:48 -03003810 dprintk("%d: next set: top=%p bottom=%p [screen=%p,irq=%d,%d]\n",
3811 btv->c.nr, set->top, set->bottom,
3812 btv->screen, set->frame_irq, set->top_irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003813 return 0;
3814}
3815
3816static void
3817bttv_irq_wakeup_video(struct bttv *btv, struct bttv_buffer_set *wakeup,
3818 struct bttv_buffer_set *curr, unsigned int state)
3819{
3820 struct timeval ts;
3821
3822 do_gettimeofday(&ts);
3823
3824 if (wakeup->top == wakeup->bottom) {
3825 if (NULL != wakeup->top && curr->top != wakeup->top) {
3826 if (irq_debug > 1)
Joe Perches8af443e2011-08-21 19:56:48 -03003827 pr_debug("%d: wakeup: both=%p\n",
3828 btv->c.nr, wakeup->top);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003829 wakeup->top->vb.ts = ts;
3830 wakeup->top->vb.field_count = btv->field_count;
3831 wakeup->top->vb.state = state;
3832 wake_up(&wakeup->top->vb.done);
3833 }
3834 } else {
3835 if (NULL != wakeup->top && curr->top != wakeup->top) {
3836 if (irq_debug > 1)
Joe Perches8af443e2011-08-21 19:56:48 -03003837 pr_debug("%d: wakeup: top=%p\n",
3838 btv->c.nr, wakeup->top);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003839 wakeup->top->vb.ts = ts;
3840 wakeup->top->vb.field_count = btv->field_count;
3841 wakeup->top->vb.state = state;
3842 wake_up(&wakeup->top->vb.done);
3843 }
3844 if (NULL != wakeup->bottom && curr->bottom != wakeup->bottom) {
3845 if (irq_debug > 1)
Joe Perches8af443e2011-08-21 19:56:48 -03003846 pr_debug("%d: wakeup: bottom=%p\n",
3847 btv->c.nr, wakeup->bottom);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003848 wakeup->bottom->vb.ts = ts;
3849 wakeup->bottom->vb.field_count = btv->field_count;
3850 wakeup->bottom->vb.state = state;
3851 wake_up(&wakeup->bottom->vb.done);
3852 }
3853 }
3854}
3855
3856static void
3857bttv_irq_wakeup_vbi(struct bttv *btv, struct bttv_buffer *wakeup,
3858 unsigned int state)
3859{
3860 struct timeval ts;
3861
3862 if (NULL == wakeup)
3863 return;
3864
3865 do_gettimeofday(&ts);
3866 wakeup->vb.ts = ts;
3867 wakeup->vb.field_count = btv->field_count;
3868 wakeup->vb.state = state;
3869 wake_up(&wakeup->vb.done);
3870}
3871
3872static void bttv_irq_timeout(unsigned long data)
3873{
3874 struct bttv *btv = (struct bttv *)data;
3875 struct bttv_buffer_set old,new;
3876 struct bttv_buffer *ovbi;
3877 struct bttv_buffer *item;
3878 unsigned long flags;
3879
3880 if (bttv_verbose) {
Joe Perches8af443e2011-08-21 19:56:48 -03003881 pr_info("%d: timeout: drop=%d irq=%d/%d, risc=%08x, ",
3882 btv->c.nr, btv->framedrop, btv->irq_me, btv->irq_total,
3883 btread(BT848_RISC_COUNT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003884 bttv_print_irqbits(btread(BT848_INT_STAT),0);
Joe Perches8af443e2011-08-21 19:56:48 -03003885 pr_cont("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003886 }
3887
3888 spin_lock_irqsave(&btv->s_lock,flags);
3889
3890 /* deactivate stuff */
3891 memset(&new,0,sizeof(new));
3892 old = btv->curr;
3893 ovbi = btv->cvbi;
3894 btv->curr = new;
3895 btv->cvbi = NULL;
3896 btv->loop_irq = 0;
3897 bttv_buffer_activate_video(btv, &new);
3898 bttv_buffer_activate_vbi(btv, NULL);
3899 bttv_set_dma(btv, 0);
3900
3901 /* wake up */
Brandon Philips0fc06862007-11-06 20:02:36 -03003902 bttv_irq_wakeup_video(btv, &old, &new, VIDEOBUF_ERROR);
3903 bttv_irq_wakeup_vbi(btv, ovbi, VIDEOBUF_ERROR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003904
3905 /* cancel all outstanding capture / vbi requests */
3906 while (!list_empty(&btv->capture)) {
3907 item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
3908 list_del(&item->vb.queue);
Brandon Philips0fc06862007-11-06 20:02:36 -03003909 item->vb.state = VIDEOBUF_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003910 wake_up(&item->vb.done);
3911 }
3912 while (!list_empty(&btv->vcapture)) {
3913 item = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
3914 list_del(&item->vb.queue);
Brandon Philips0fc06862007-11-06 20:02:36 -03003915 item->vb.state = VIDEOBUF_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003916 wake_up(&item->vb.done);
3917 }
3918
3919 btv->errors++;
3920 spin_unlock_irqrestore(&btv->s_lock,flags);
3921}
3922
3923static void
3924bttv_irq_wakeup_top(struct bttv *btv)
3925{
3926 struct bttv_buffer *wakeup = btv->curr.top;
3927
3928 if (NULL == wakeup)
3929 return;
3930
3931 spin_lock(&btv->s_lock);
3932 btv->curr.top_irq = 0;
3933 btv->curr.top = NULL;
3934 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
3935
3936 do_gettimeofday(&wakeup->vb.ts);
3937 wakeup->vb.field_count = btv->field_count;
Brandon Philips0fc06862007-11-06 20:02:36 -03003938 wakeup->vb.state = VIDEOBUF_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003939 wake_up(&wakeup->vb.done);
3940 spin_unlock(&btv->s_lock);
3941}
3942
3943static inline int is_active(struct btcx_riscmem *risc, u32 rc)
3944{
3945 if (rc < risc->dma)
3946 return 0;
3947 if (rc > risc->dma + risc->size)
3948 return 0;
3949 return 1;
3950}
3951
3952static void
3953bttv_irq_switch_video(struct bttv *btv)
3954{
3955 struct bttv_buffer_set new;
3956 struct bttv_buffer_set old;
3957 dma_addr_t rc;
3958
3959 spin_lock(&btv->s_lock);
3960
3961 /* new buffer set */
3962 bttv_irq_next_video(btv, &new);
3963 rc = btread(BT848_RISC_COUNT);
3964 if ((btv->curr.top && is_active(&btv->curr.top->top, rc)) ||
3965 (btv->curr.bottom && is_active(&btv->curr.bottom->bottom, rc))) {
3966 btv->framedrop++;
3967 if (debug_latency)
3968 bttv_irq_debug_low_latency(btv, rc);
3969 spin_unlock(&btv->s_lock);
3970 return;
3971 }
3972
3973 /* switch over */
3974 old = btv->curr;
3975 btv->curr = new;
3976 btv->loop_irq &= ~1;
3977 bttv_buffer_activate_video(btv, &new);
3978 bttv_set_dma(btv, 0);
3979
3980 /* switch input */
3981 if (UNSET != btv->new_input) {
3982 video_mux(btv,btv->new_input);
3983 btv->new_input = UNSET;
3984 }
3985
3986 /* wake up finished buffers */
Brandon Philips0fc06862007-11-06 20:02:36 -03003987 bttv_irq_wakeup_video(btv, &old, &new, VIDEOBUF_DONE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003988 spin_unlock(&btv->s_lock);
3989}
3990
3991static void
3992bttv_irq_switch_vbi(struct bttv *btv)
3993{
3994 struct bttv_buffer *new = NULL;
3995 struct bttv_buffer *old;
3996 u32 rc;
3997
3998 spin_lock(&btv->s_lock);
3999
4000 if (!list_empty(&btv->vcapture))
4001 new = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
4002 old = btv->cvbi;
4003
4004 rc = btread(BT848_RISC_COUNT);
4005 if (NULL != old && (is_active(&old->top, rc) ||
4006 is_active(&old->bottom, rc))) {
4007 btv->framedrop++;
4008 if (debug_latency)
4009 bttv_irq_debug_low_latency(btv, rc);
4010 spin_unlock(&btv->s_lock);
4011 return;
4012 }
4013
4014 /* switch */
4015 btv->cvbi = new;
4016 btv->loop_irq &= ~4;
4017 bttv_buffer_activate_vbi(btv, new);
4018 bttv_set_dma(btv, 0);
4019
Brandon Philips0fc06862007-11-06 20:02:36 -03004020 bttv_irq_wakeup_vbi(btv, old, VIDEOBUF_DONE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004021 spin_unlock(&btv->s_lock);
4022}
4023
David Howells7d12e782006-10-05 14:55:46 +01004024static irqreturn_t bttv_irq(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004025{
4026 u32 stat,astat;
4027 u32 dstat;
4028 int count;
4029 struct bttv *btv;
4030 int handled = 0;
4031
4032 btv=(struct bttv *)dev_id;
Mark Weaver6c6c0b22005-11-13 16:07:52 -08004033
Linus Torvalds1da177e2005-04-16 15:20:36 -07004034 count=0;
4035 while (1) {
4036 /* get/clear interrupt status bits */
4037 stat=btread(BT848_INT_STAT);
4038 astat=stat&btread(BT848_INT_MASK);
4039 if (!astat)
4040 break;
4041 handled = 1;
4042 btwrite(stat,BT848_INT_STAT);
4043
4044 /* get device status bits */
4045 dstat=btread(BT848_DSTATUS);
4046
4047 if (irq_debug) {
Joe Perches8af443e2011-08-21 19:56:48 -03004048 pr_debug("%d: irq loop=%d fc=%d riscs=%x, riscc=%08x, ",
4049 btv->c.nr, count, btv->field_count,
4050 stat>>28, btread(BT848_RISC_COUNT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051 bttv_print_irqbits(stat,astat);
4052 if (stat & BT848_INT_HLOCK)
Joe Perches8af443e2011-08-21 19:56:48 -03004053 pr_cont(" HLOC => %s",
4054 dstat & BT848_DSTATUS_HLOC
4055 ? "yes" : "no");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004056 if (stat & BT848_INT_VPRES)
Joe Perches8af443e2011-08-21 19:56:48 -03004057 pr_cont(" PRES => %s",
4058 dstat & BT848_DSTATUS_PRES
4059 ? "yes" : "no");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060 if (stat & BT848_INT_FMTCHG)
Joe Perches8af443e2011-08-21 19:56:48 -03004061 pr_cont(" NUML => %s",
4062 dstat & BT848_DSTATUS_NUML
4063 ? "625" : "525");
4064 pr_cont("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065 }
4066
4067 if (astat&BT848_INT_VSYNC)
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004068 btv->field_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02004070 if ((astat & BT848_INT_GPINT) && btv->remote) {
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02004071 bttv_input_irq(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004072 }
4073
4074 if (astat & BT848_INT_I2CDONE) {
4075 btv->i2c_done = stat;
4076 wake_up(&btv->i2c_queue);
4077 }
4078
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004079 if ((astat & BT848_INT_RISCI) && (stat & (4<<28)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004080 bttv_irq_switch_vbi(btv);
4081
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004082 if ((astat & BT848_INT_RISCI) && (stat & (2<<28)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004083 bttv_irq_wakeup_top(btv);
4084
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004085 if ((astat & BT848_INT_RISCI) && (stat & (1<<28)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004086 bttv_irq_switch_video(btv);
4087
4088 if ((astat & BT848_INT_HLOCK) && btv->opt_automute)
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03004089 audio_mute(btv, btv->mute); /* trigger automute */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004090
4091 if (astat & (BT848_INT_SCERR|BT848_INT_OCERR)) {
Joe Perches8af443e2011-08-21 19:56:48 -03004092 pr_info("%d: %s%s @ %08x,",
4093 btv->c.nr,
4094 (astat & BT848_INT_SCERR) ? "SCERR" : "",
4095 (astat & BT848_INT_OCERR) ? "OCERR" : "",
4096 btread(BT848_RISC_COUNT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004097 bttv_print_irqbits(stat,astat);
Joe Perches8af443e2011-08-21 19:56:48 -03004098 pr_cont("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004099 if (bttv_debug)
4100 bttv_print_riscaddr(btv);
4101 }
4102 if (fdsr && astat & BT848_INT_FDSR) {
Joe Perches8af443e2011-08-21 19:56:48 -03004103 pr_info("%d: FDSR @ %08x\n",
4104 btv->c.nr, btread(BT848_RISC_COUNT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004105 if (bttv_debug)
4106 bttv_print_riscaddr(btv);
4107 }
4108
4109 count++;
4110 if (count > 4) {
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08004111
4112 if (count > 8 || !(astat & BT848_INT_GPINT)) {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004113 btwrite(0, BT848_INT_MASK);
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08004114
Joe Perches8af443e2011-08-21 19:56:48 -03004115 pr_err("%d: IRQ lockup, cleared int mask [",
4116 btv->c.nr);
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08004117 } else {
Joe Perches8af443e2011-08-21 19:56:48 -03004118 pr_err("%d: IRQ lockup, clearing GPINT from int mask [",
4119 btv->c.nr);
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08004120
4121 btwrite(btread(BT848_INT_MASK) & (-1 ^ BT848_INT_GPINT),
4122 BT848_INT_MASK);
4123 };
4124
Linus Torvalds1da177e2005-04-16 15:20:36 -07004125 bttv_print_irqbits(stat,astat);
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08004126
Joe Perches8af443e2011-08-21 19:56:48 -03004127 pr_cont("]\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004128 }
4129 }
4130 btv->irq_total++;
4131 if (handled)
4132 btv->irq_me++;
4133 return IRQ_RETVAL(handled);
4134}
4135
4136
4137/* ----------------------------------------------------------------------- */
4138/* initialitation */
4139
4140static struct video_device *vdev_init(struct bttv *btv,
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03004141 const struct video_device *template,
Hans Verkuil0ea6bc82008-07-26 08:26:43 -03004142 const char *type_name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004143{
4144 struct video_device *vfd;
4145
4146 vfd = video_device_alloc();
4147 if (NULL == vfd)
4148 return NULL;
4149 *vfd = *template;
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004150 vfd->v4l2_dev = &btv->c.v4l2_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004151 vfd->release = video_device_release;
Mauro Carvalho Chehab1d0a4362008-06-23 12:31:29 -03004152 vfd->debug = bttv_debug;
Trent Piepho4b10d3b2009-01-28 21:32:59 -03004153 video_set_drvdata(vfd, btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004154 snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
4155 btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "",
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03004156 type_name, bttv_tvcards[btv->c.type].name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004157 return vfd;
4158}
4159
4160static void bttv_unregister_video(struct bttv *btv)
4161{
4162 if (btv->video_dev) {
Laurent Pinchartf0813b42009-11-27 13:57:30 -03004163 if (video_is_registered(btv->video_dev))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004164 video_unregister_device(btv->video_dev);
4165 else
4166 video_device_release(btv->video_dev);
4167 btv->video_dev = NULL;
4168 }
4169 if (btv->vbi_dev) {
Laurent Pinchartf0813b42009-11-27 13:57:30 -03004170 if (video_is_registered(btv->vbi_dev))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004171 video_unregister_device(btv->vbi_dev);
4172 else
4173 video_device_release(btv->vbi_dev);
4174 btv->vbi_dev = NULL;
4175 }
4176 if (btv->radio_dev) {
Laurent Pinchartf0813b42009-11-27 13:57:30 -03004177 if (video_is_registered(btv->radio_dev))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004178 video_unregister_device(btv->radio_dev);
4179 else
4180 video_device_release(btv->radio_dev);
4181 btv->radio_dev = NULL;
4182 }
4183}
4184
4185/* register video4linux devices */
4186static int __devinit bttv_register_video(struct bttv *btv)
4187{
Hans Verkuil0ea6bc82008-07-26 08:26:43 -03004188 if (no_overlay > 0)
Joe Perches8af443e2011-08-21 19:56:48 -03004189 pr_notice("Overlay support disabled\n");
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07004190
Linus Torvalds1da177e2005-04-16 15:20:36 -07004191 /* video */
Hans Verkuil0ea6bc82008-07-26 08:26:43 -03004192 btv->video_dev = vdev_init(btv, &bttv_video_template, "video");
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03004193
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004194 if (NULL == btv->video_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004195 goto err;
Jean Delvare176c2f32008-09-07 12:49:59 -03004196 if (video_register_device(btv->video_dev, VFL_TYPE_GRABBER,
4197 video_nr[btv->c.nr]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004198 goto err;
Joe Perches8af443e2011-08-21 19:56:48 -03004199 pr_info("%d: registered device %s\n",
4200 btv->c.nr, video_device_node_name(btv->video_dev));
Hans Verkuil22a04f12008-07-20 06:35:02 -03004201 if (device_create_file(&btv->video_dev->dev,
Kay Sievers54bd5b62007-10-08 16:26:13 -03004202 &dev_attr_card)<0) {
Joe Perches8af443e2011-08-21 19:56:48 -03004203 pr_err("%d: device_create_file 'card' failed\n", btv->c.nr);
Trent Piephod94fc9a2006-07-29 17:18:06 -03004204 goto err;
4205 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004206
4207 /* vbi */
Hans Verkuil0ea6bc82008-07-26 08:26:43 -03004208 btv->vbi_dev = vdev_init(btv, &bttv_video_template, "vbi");
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03004209
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004210 if (NULL == btv->vbi_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004211 goto err;
Jean Delvare176c2f32008-09-07 12:49:59 -03004212 if (video_register_device(btv->vbi_dev, VFL_TYPE_VBI,
4213 vbi_nr[btv->c.nr]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004214 goto err;
Joe Perches8af443e2011-08-21 19:56:48 -03004215 pr_info("%d: registered device %s\n",
4216 btv->c.nr, video_device_node_name(btv->vbi_dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004217
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004218 if (!btv->has_radio)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004219 return 0;
4220 /* radio */
Hans Verkuil0ea6bc82008-07-26 08:26:43 -03004221 btv->radio_dev = vdev_init(btv, &radio_template, "radio");
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004222 if (NULL == btv->radio_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004223 goto err;
Jean Delvare176c2f32008-09-07 12:49:59 -03004224 if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,
4225 radio_nr[btv->c.nr]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004226 goto err;
Joe Perches8af443e2011-08-21 19:56:48 -03004227 pr_info("%d: registered device %s\n",
4228 btv->c.nr, video_device_node_name(btv->radio_dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004229
4230 /* all done */
4231 return 0;
4232
4233 err:
4234 bttv_unregister_video(btv);
4235 return -1;
4236}
4237
4238
4239/* on OpenFirmware machines (PowerMac at least), PCI memory cycle */
4240/* response on cards with no firmware is not enabled by OF */
4241static void pci_set_command(struct pci_dev *dev)
4242{
4243#if defined(__powerpc__)
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004244 unsigned int cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004245
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004246 pci_read_config_dword(dev, PCI_COMMAND, &cmd);
4247 cmd = (cmd | PCI_COMMAND_MEMORY );
4248 pci_write_config_dword(dev, PCI_COMMAND, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004249#endif
4250}
4251
4252static int __devinit bttv_probe(struct pci_dev *dev,
4253 const struct pci_device_id *pci_id)
4254{
4255 int result;
4256 unsigned char lat;
4257 struct bttv *btv;
4258
4259 if (bttv_num == BTTV_MAX)
4260 return -ENOMEM;
Joe Perches8af443e2011-08-21 19:56:48 -03004261 pr_info("Bt8xx card found (%d)\n", bttv_num);
Trent Piepho4b10d3b2009-01-28 21:32:59 -03004262 bttvs[bttv_num] = btv = kzalloc(sizeof(*btv), GFP_KERNEL);
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004263 if (btv == NULL) {
Joe Perches8af443e2011-08-21 19:56:48 -03004264 pr_err("out of memory\n");
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004265 return -ENOMEM;
4266 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004267 btv->c.nr = bttv_num;
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004268 snprintf(btv->c.v4l2_dev.name, sizeof(btv->c.v4l2_dev.name),
4269 "bttv%d", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004270
4271 /* initialize structs / fill in defaults */
Ingo Molnarbd5f0ac2006-01-13 14:10:24 -02004272 mutex_init(&btv->lock);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004273 spin_lock_init(&btv->s_lock);
4274 spin_lock_init(&btv->gpio_lock);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004275 init_waitqueue_head(&btv->i2c_queue);
4276 INIT_LIST_HEAD(&btv->c.subs);
4277 INIT_LIST_HEAD(&btv->capture);
4278 INIT_LIST_HEAD(&btv->vcapture);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004279 v4l2_prio_init(&btv->prio);
4280
4281 init_timer(&btv->timeout);
4282 btv->timeout.function = bttv_irq_timeout;
4283 btv->timeout.data = (unsigned long)btv;
4284
Michael Krufky7c08fb02005-11-08 21:36:21 -08004285 btv->i2c_rc = -1;
4286 btv->tuner_type = UNSET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004287 btv->new_input = UNSET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004288 btv->has_radio=radio[btv->c.nr];
4289
4290 /* pci stuff (init, get irq/mmio, ... */
4291 btv->c.pci = dev;
Michael Krufky7c08fb02005-11-08 21:36:21 -08004292 btv->id = dev->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004293 if (pci_enable_device(dev)) {
Joe Perches8af443e2011-08-21 19:56:48 -03004294 pr_warn("%d: Can't enable device\n", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004295 return -EIO;
4296 }
Yang Hongyang284901a2009-04-06 19:01:15 -07004297 if (pci_set_dma_mask(dev, DMA_BIT_MASK(32))) {
Joe Perches8af443e2011-08-21 19:56:48 -03004298 pr_warn("%d: No suitable DMA available\n", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004299 return -EIO;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004300 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004301 if (!request_mem_region(pci_resource_start(dev,0),
4302 pci_resource_len(dev,0),
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004303 btv->c.v4l2_dev.name)) {
Joe Perches8af443e2011-08-21 19:56:48 -03004304 pr_warn("%d: can't request iomem (0x%llx)\n",
4305 btv->c.nr,
4306 (unsigned long long)pci_resource_start(dev, 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004307 return -EBUSY;
4308 }
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004309 pci_set_master(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004310 pci_set_command(dev);
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004311
4312 result = v4l2_device_register(&dev->dev, &btv->c.v4l2_dev);
4313 if (result < 0) {
Joe Perches8af443e2011-08-21 19:56:48 -03004314 pr_warn("%d: v4l2_device_register() failed\n", btv->c.nr);
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004315 goto fail0;
4316 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004317
Bjørn Morkabd34d82011-03-21 11:35:56 -03004318 btv->revision = dev->revision;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004319 pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
Joe Perches8af443e2011-08-21 19:56:48 -03004320 pr_info("%d: Bt%d (rev %d) at %s, irq: %d, latency: %d, mmio: 0x%llx\n",
4321 bttv_num, btv->id, btv->revision, pci_name(dev),
4322 btv->c.pci->irq, lat,
4323 (unsigned long long)pci_resource_start(dev, 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004324 schedule();
4325
Akinobu Mita5f1693f2006-12-20 10:08:56 -03004326 btv->bt848_mmio = ioremap(pci_resource_start(dev, 0), 0x1000);
4327 if (NULL == btv->bt848_mmio) {
Joe Perches8af443e2011-08-21 19:56:48 -03004328 pr_err("%d: ioremap() failed\n", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004329 result = -EIO;
4330 goto fail1;
4331 }
4332
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004333 /* identify card */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004334 bttv_idcard(btv);
4335
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004336 /* disable irqs, register irq handler */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004337 btwrite(0, BT848_INT_MASK);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004338 result = request_irq(btv->c.pci->irq, bttv_irq,
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004339 IRQF_SHARED | IRQF_DISABLED, btv->c.v4l2_dev.name, (void *)btv);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004340 if (result < 0) {
Joe Perches8af443e2011-08-21 19:56:48 -03004341 pr_err("%d: can't get IRQ %d\n",
4342 bttv_num, btv->c.pci->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004343 goto fail1;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004344 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004345
4346 if (0 != bttv_handle_chipset(btv)) {
4347 result = -EIO;
4348 goto fail2;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004349 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004350
4351 /* init options from insmod args */
4352 btv->opt_combfilter = combfilter;
4353 btv->opt_lumafilter = lumafilter;
4354 btv->opt_automute = automute;
4355 btv->opt_chroma_agc = chroma_agc;
4356 btv->opt_adc_crush = adc_crush;
4357 btv->opt_vcr_hack = vcr_hack;
4358 btv->opt_whitecrush_upper = whitecrush_upper;
4359 btv->opt_whitecrush_lower = whitecrush_lower;
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -07004360 btv->opt_uv_ratio = uv_ratio;
4361 btv->opt_full_luma_range = full_luma_range;
4362 btv->opt_coring = coring;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004363
4364 /* fill struct bttv with some useful defaults */
4365 btv->init.btv = btv;
4366 btv->init.ov.w.width = 320;
4367 btv->init.ov.w.height = 240;
Mauro Carvalho Chehabc96dd072007-10-26 16:51:47 -03004368 btv->init.fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004369 btv->init.width = 320;
4370 btv->init.height = 240;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004371 btv->input = 0;
4372
4373 /* initialize hardware */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004374 if (bttv_gpio)
4375 bttv_gpio_tracking(btv,"pre-init");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004376
4377 bttv_risc_init_main(btv);
4378 init_bt848(btv);
4379
4380 /* gpio */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004381 btwrite(0x00, BT848_GPIO_REG_INP);
4382 btwrite(0x00, BT848_GPIO_OUT_EN);
4383 if (bttv_verbose)
4384 bttv_gpio_tracking(btv,"init");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004385
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004386 /* needs to be done before i2c is registered */
4387 bttv_init_card1(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004388
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004389 /* register i2c + gpio */
4390 init_bttv_i2c(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004391
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004392 /* some card-specific stuff (needs working i2c) */
4393 bttv_init_card2(btv);
Hans Verkuil2c905772009-07-20 08:14:17 -03004394 bttv_init_tuner(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004395 init_irqreg(btv);
4396
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004397 /* register video4linux + input */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398 if (!bttv_tvcards[btv->c.type].no_video) {
4399 bttv_register_video(btv);
4400 bt848_bright(btv,32768);
4401 bt848_contrast(btv,32768);
4402 bt848_hue(btv,32768);
4403 bt848_sat(btv,32768);
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03004404 audio_mute(btv, 1);
Trent Piepho333408f2007-07-03 15:08:10 -03004405 set_input(btv, 0, btv->tvnorm);
Michael Schimeke5bd0262007-01-18 16:17:39 -03004406 bttv_crop_reset(&btv->crop[0], btv->tvnorm);
4407 btv->crop[1] = btv->crop[0]; /* current = default */
4408 disclaim_vbi_lines(btv);
4409 disclaim_video_lines(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004410 }
4411
Jarod Wilsonf992a492007-03-24 15:23:50 -03004412 /* add subdevices and autoload dvb-bt8xx if needed */
4413 if (bttv_tvcards[btv->c.type].has_dvb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004414 bttv_sub_add_device(&btv->c, "dvb");
Jarod Wilsonf992a492007-03-24 15:23:50 -03004415 request_modules(btv);
4416 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004417
Jean Delvared90a4ae2010-02-16 14:22:37 -03004418 if (!disable_ir) {
4419 init_bttv_i2c_ir(btv);
4420 bttv_input_init(btv);
4421 }
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02004422
Linus Torvalds1da177e2005-04-16 15:20:36 -07004423 /* everything is fine */
4424 bttv_num++;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004425 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004426
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004427fail2:
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004428 free_irq(btv->c.pci->irq,btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004429
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004430fail1:
4431 v4l2_device_unregister(&btv->c.v4l2_dev);
4432
4433fail0:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004434 if (btv->bt848_mmio)
4435 iounmap(btv->bt848_mmio);
4436 release_mem_region(pci_resource_start(btv->c.pci,0),
4437 pci_resource_len(btv->c.pci,0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004438 return result;
4439}
4440
4441static void __devexit bttv_remove(struct pci_dev *pci_dev)
4442{
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004443 struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
4444 struct bttv *btv = to_bttv(v4l2_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004445
4446 if (bttv_verbose)
Joe Perches8af443e2011-08-21 19:56:48 -03004447 pr_info("%d: unloading\n", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004448
Tejun Heo707bcf32010-12-24 16:14:20 +01004449 if (bttv_tvcards[btv->c.type].has_dvb)
4450 flush_request_modules(btv);
4451
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004452 /* shutdown everything (DMA+IRQs) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004453 btand(~15, BT848_GPIO_DMA_CTL);
4454 btwrite(0, BT848_INT_MASK);
4455 btwrite(~0x0, BT848_INT_STAT);
4456 btwrite(0x0, BT848_GPIO_OUT_EN);
4457 if (bttv_gpio)
4458 bttv_gpio_tracking(btv,"cleanup");
4459
4460 /* tell gpio modules we are leaving ... */
4461 btv->shutdown=1;
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02004462 bttv_input_fini(btv);
Christopher Pascoe889aee82006-01-09 15:25:28 -02004463 bttv_sub_del_devices(&btv->c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004464
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004465 /* unregister i2c_bus + input */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004466 fini_bttv_i2c(btv);
4467
4468 /* unregister video4linux */
4469 bttv_unregister_video(btv);
4470
4471 /* free allocated memory */
4472 btcx_riscmem_free(btv->c.pci,&btv->main);
4473
4474 /* free ressources */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004475 free_irq(btv->c.pci->irq,btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004476 iounmap(btv->bt848_mmio);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004477 release_mem_region(pci_resource_start(btv->c.pci,0),
4478 pci_resource_len(btv->c.pci,0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004479
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004480 v4l2_device_unregister(&btv->c.v4l2_dev);
Trent Piepho4b10d3b2009-01-28 21:32:59 -03004481 bttvs[btv->c.nr] = NULL;
4482 kfree(btv);
4483
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004484 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004485}
4486
Alexey Dobriyan17bc98a2006-08-12 22:01:27 -03004487#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -07004488static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state)
4489{
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004490 struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
4491 struct bttv *btv = to_bttv(v4l2_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004492 struct bttv_buffer_set idle;
4493 unsigned long flags;
4494
Joe Perches8af443e2011-08-21 19:56:48 -03004495 dprintk("%d: suspend %d\n", btv->c.nr, state.event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004496
4497 /* stop dma + irqs */
4498 spin_lock_irqsave(&btv->s_lock,flags);
4499 memset(&idle, 0, sizeof(idle));
4500 btv->state.video = btv->curr;
4501 btv->state.vbi = btv->cvbi;
4502 btv->state.loop_irq = btv->loop_irq;
4503 btv->curr = idle;
4504 btv->loop_irq = 0;
4505 bttv_buffer_activate_video(btv, &idle);
4506 bttv_buffer_activate_vbi(btv, NULL);
4507 bttv_set_dma(btv, 0);
4508 btwrite(0, BT848_INT_MASK);
4509 spin_unlock_irqrestore(&btv->s_lock,flags);
4510
4511 /* save bt878 state */
4512 btv->state.gpio_enable = btread(BT848_GPIO_OUT_EN);
4513 btv->state.gpio_data = gpio_read();
4514
4515 /* save pci state */
4516 pci_save_state(pci_dev);
4517 if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
4518 pci_disable_device(pci_dev);
4519 btv->state.disabled = 1;
4520 }
4521 return 0;
4522}
4523
4524static int bttv_resume(struct pci_dev *pci_dev)
4525{
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004526 struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
4527 struct bttv *btv = to_bttv(v4l2_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004528 unsigned long flags;
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004529 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004530
Joe Perches8af443e2011-08-21 19:56:48 -03004531 dprintk("%d: resume\n", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004532
4533 /* restore pci state */
4534 if (btv->state.disabled) {
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004535 err=pci_enable_device(pci_dev);
4536 if (err) {
Joe Perches8af443e2011-08-21 19:56:48 -03004537 pr_warn("%d: Can't enable device\n", btv->c.nr);
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004538 return err;
4539 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004540 btv->state.disabled = 0;
4541 }
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004542 err=pci_set_power_state(pci_dev, PCI_D0);
4543 if (err) {
4544 pci_disable_device(pci_dev);
Joe Perches8af443e2011-08-21 19:56:48 -03004545 pr_warn("%d: Can't enable device\n", btv->c.nr);
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004546 btv->state.disabled = 1;
4547 return err;
4548 }
4549
Linus Torvalds1da177e2005-04-16 15:20:36 -07004550 pci_restore_state(pci_dev);
4551
4552 /* restore bt878 state */
4553 bttv_reinit_bt848(btv);
4554 gpio_inout(0xffffff, btv->state.gpio_enable);
4555 gpio_write(btv->state.gpio_data);
4556
4557 /* restart dma */
4558 spin_lock_irqsave(&btv->s_lock,flags);
4559 btv->curr = btv->state.video;
4560 btv->cvbi = btv->state.vbi;
4561 btv->loop_irq = btv->state.loop_irq;
4562 bttv_buffer_activate_video(btv, &btv->curr);
4563 bttv_buffer_activate_vbi(btv, btv->cvbi);
4564 bttv_set_dma(btv, 0);
4565 spin_unlock_irqrestore(&btv->s_lock,flags);
4566 return 0;
4567}
Alexey Dobriyan17bc98a2006-08-12 22:01:27 -03004568#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07004569
4570static struct pci_device_id bttv_pci_tbl[] = {
Joe Perches76e97412009-07-05 15:59:21 -03004571 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT848), 0},
4572 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT849), 0},
4573 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT878), 0},
4574 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT879), 0},
Peter De Schrijverc540d9f2011-11-06 10:47:58 -03004575 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_FUSION879), 0},
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004576 {0,}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004577};
4578
4579MODULE_DEVICE_TABLE(pci, bttv_pci_tbl);
4580
4581static struct pci_driver bttv_pci_driver = {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004582 .name = "bttv",
4583 .id_table = bttv_pci_tbl,
4584 .probe = bttv_probe,
4585 .remove = __devexit_p(bttv_remove),
Alexey Dobriyan17bc98a2006-08-12 22:01:27 -03004586#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -07004587 .suspend = bttv_suspend,
4588 .resume = bttv_resume,
Alexey Dobriyan17bc98a2006-08-12 22:01:27 -03004589#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07004590};
4591
Adrian Bunk7d44e892007-12-11 19:23:43 -03004592static int __init bttv_init_module(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004593{
Randy Dunlapc526e222006-07-15 09:08:26 -03004594 int ret;
4595
Linus Torvalds1da177e2005-04-16 15:20:36 -07004596 bttv_num = 0;
4597
Joe Perches8af443e2011-08-21 19:56:48 -03004598 pr_info("driver version %s loaded\n", BTTV_VERSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004599 if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME)
4600 gbuffers = 2;
Filipe Rossetf41b6962009-05-28 11:11:53 -03004601 if (gbufsize > BTTV_MAX_FBUF)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004602 gbufsize = BTTV_MAX_FBUF;
4603 gbufsize = (gbufsize + PAGE_SIZE - 1) & PAGE_MASK;
4604 if (bttv_verbose)
Joe Perches8af443e2011-08-21 19:56:48 -03004605 pr_info("using %d buffers with %dk (%d pages) each for capture\n",
4606 gbuffers, gbufsize >> 10, gbufsize >> PAGE_SHIFT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004607
4608 bttv_check_chipset();
4609
Randy Dunlapc526e222006-07-15 09:08:26 -03004610 ret = bus_register(&bttv_sub_bus_type);
4611 if (ret < 0) {
Joe Perches8af443e2011-08-21 19:56:48 -03004612 pr_warn("bus_register error: %d\n", ret);
Randy Dunlapc526e222006-07-15 09:08:26 -03004613 return ret;
4614 }
Akinobu Mita9e7e85e2007-12-17 14:26:29 -03004615 ret = pci_register_driver(&bttv_pci_driver);
4616 if (ret < 0)
4617 bus_unregister(&bttv_sub_bus_type);
4618
4619 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004620}
4621
Adrian Bunk7d44e892007-12-11 19:23:43 -03004622static void __exit bttv_cleanup_module(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004623{
4624 pci_unregister_driver(&bttv_pci_driver);
4625 bus_unregister(&bttv_sub_bus_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004626}
4627
4628module_init(bttv_init_module);
4629module_exit(bttv_cleanup_module);
4630
4631/*
4632 * Local variables:
4633 * c-basic-offset: 8
4634 * End:
4635 */