blob: ff7a589d8e0f5e0486dd72c8870e4d965a8ce50e [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,
Alan McIvor961e6682012-04-01 21:11:08 -0300666 .default_value = 27648,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667 .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 de Goede7025e522012-05-21 07:46:22 -03001221 /* Some boards need the msp do to the radio demod */
1222 if (btv->radio_uses_msp_demodulator) {
1223 in = MSP_INPUT_DEFAULT;
1224 break;
1225 }
Hans Verkuil5325b422009-04-02 11:26:22 -03001226 in = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1,
Hans Verkuil07151722006-04-01 18:03:23 -03001227 MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001228 break;
1229 case TVAUDIO_INPUT_EXTERN:
Hans Verkuil5325b422009-04-02 11:26:22 -03001230 in = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1,
Hans Verkuil07151722006-04-01 18:03:23 -03001231 MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001232 break;
1233 case TVAUDIO_INPUT_INTERN:
1234 /* Yes, this is the same input as for RADIO. I doubt
1235 if this is ever used. The only board with an INTERN
1236 input is the BTTV_BOARD_AVERMEDIA98. I wonder how
1237 that was tested. My guess is that the whole INTERN
1238 input does not work. */
Hans Verkuil5325b422009-04-02 11:26:22 -03001239 in = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1,
Hans Verkuil07151722006-04-01 18:03:23 -03001240 MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001241 break;
1242 case TVAUDIO_INPUT_TUNER:
1243 default:
Wade Berrier434b2522007-06-25 13:02:16 -03001244 /* This is the only card that uses TUNER2, and afaik,
1245 is the only difference between the VOODOOTV_FM
1246 and VOODOOTV_200 */
1247 if (btv->c.type == BTTV_BOARD_VOODOOTV_200)
Hans Verkuil5325b422009-04-02 11:26:22 -03001248 in = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER2, \
Wade Berrier434b2522007-06-25 13:02:16 -03001249 MSP_DSP_IN_TUNER, MSP_DSP_IN_TUNER);
1250 else
Hans Verkuil5325b422009-04-02 11:26:22 -03001251 in = MSP_INPUT_DEFAULT;
Hans Verkuil2474ed42006-03-19 12:35:57 -03001252 break;
1253 }
Hans Verkuil5325b422009-04-02 11:26:22 -03001254 v4l2_subdev_call(btv->sd_msp34xx, audio, s_routing,
1255 in, MSP_OUTPUT_DEFAULT, 0);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001256 }
Hans Verkuil859f0272009-03-28 08:29:00 -03001257 if (btv->sd_tvaudio) {
Hans Verkuil5325b422009-04-02 11:26:22 -03001258 v4l2_subdev_call(btv->sd_tvaudio, audio, s_routing,
1259 input, 0, 0);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001260 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261 return 0;
1262}
1263
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001264static inline int
1265audio_mute(struct bttv *btv, int mute)
1266{
1267 return audio_mux(btv, btv->audio, mute);
1268}
1269
1270static inline int
1271audio_input(struct bttv *btv, int input)
1272{
1273 return audio_mux(btv, input, btv->mute);
1274}
1275
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276static void
Michael Schimeke5bd0262007-01-18 16:17:39 -03001277bttv_crop_calc_limits(struct bttv_crop *c)
1278{
1279 /* Scale factor min. 1:1, max. 16:1. Min. image size
1280 48 x 32. Scaled width must be a multiple of 4. */
1281
1282 if (1) {
1283 /* For bug compatibility with VIDIOCGCAP and image
1284 size checks in earlier driver versions. */
1285 c->min_scaled_width = 48;
1286 c->min_scaled_height = 32;
1287 } else {
1288 c->min_scaled_width =
1289 (max(48, c->rect.width >> 4) + 3) & ~3;
1290 c->min_scaled_height =
1291 max(32, c->rect.height >> 4);
1292 }
1293
1294 c->max_scaled_width = c->rect.width & ~3;
1295 c->max_scaled_height = c->rect.height;
1296}
1297
1298static void
Trent Piepho4ef2ccc2009-01-28 21:32:58 -03001299bttv_crop_reset(struct bttv_crop *c, unsigned int norm)
Michael Schimeke5bd0262007-01-18 16:17:39 -03001300{
1301 c->rect = bttv_tvnorms[norm].cropcap.defrect;
1302 bttv_crop_calc_limits(c);
1303}
1304
1305/* Call with btv->lock down. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306static int
1307set_tvnorm(struct bttv *btv, unsigned int norm)
1308{
1309 const struct bttv_tvnorm *tvnorm;
Nickolay V. Shmyrev302f61a2007-10-26 10:53:21 -03001310 v4l2_std_id id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311
Trent Piepho4ef2ccc2009-01-28 21:32:58 -03001312 BUG_ON(norm >= BTTV_TVNORMS);
1313 BUG_ON(btv->tvnorm >= BTTV_TVNORMS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315 tvnorm = &bttv_tvnorms[norm];
1316
Mike Isely2de26c02009-09-21 12:42:22 -03001317 if (memcmp(&bttv_tvnorms[btv->tvnorm].cropcap, &tvnorm->cropcap,
Trent Piepho4ef2ccc2009-01-28 21:32:58 -03001318 sizeof (tvnorm->cropcap))) {
Michael Schimeke5bd0262007-01-18 16:17:39 -03001319 bttv_crop_reset(&btv->crop[0], norm);
1320 btv->crop[1] = btv->crop[0]; /* current = default */
1321
1322 if (0 == (btv->resources & VIDEO_RESOURCES)) {
1323 btv->crop_start = tvnorm->cropcap.bounds.top
1324 + tvnorm->cropcap.bounds.height;
1325 }
1326 }
1327
1328 btv->tvnorm = norm;
1329
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330 btwrite(tvnorm->adelay, BT848_ADELAY);
1331 btwrite(tvnorm->bdelay, BT848_BDELAY);
1332 btaor(tvnorm->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH),
1333 BT848_IFORM);
1334 btwrite(tvnorm->vbipack, BT848_VBI_PACK_SIZE);
1335 btwrite(1, BT848_VBI_PACK_DEL);
1336 bt848A_set_timing(btv);
1337
1338 switch (btv->c.type) {
Mauro Carvalho Chehab5a25e842005-11-08 21:36:52 -08001339 case BTTV_BOARD_VOODOOTV_FM:
Wade Berrier434b2522007-06-25 13:02:16 -03001340 case BTTV_BOARD_VOODOOTV_200:
Trent Piepho72134a62009-01-28 21:32:59 -03001341 bttv_tda9880_setnorm(btv, gpio_read());
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 }
Nickolay V. Shmyrev302f61a2007-10-26 10:53:21 -03001344 id = tvnorm->v4l2_id;
Hans Verkuilf41737e2009-04-01 03:52:39 -03001345 bttv_call_all(btv, core, s_std, id);
Nickolay V. Shmyrev302f61a2007-10-26 10:53:21 -03001346
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 return 0;
1348}
1349
Michael Schimeke5bd0262007-01-18 16:17:39 -03001350/* Call with btv->lock down. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351static void
Trent Piepho333408f2007-07-03 15:08:10 -03001352set_input(struct bttv *btv, unsigned int input, unsigned int norm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353{
1354 unsigned long flags;
1355
1356 btv->input = input;
1357 if (irq_iswitch) {
1358 spin_lock_irqsave(&btv->s_lock,flags);
1359 if (btv->curr.frame_irq) {
1360 /* active capture -> delayed input switch */
1361 btv->new_input = input;
1362 } else {
1363 video_mux(btv,input);
1364 }
1365 spin_unlock_irqrestore(&btv->s_lock,flags);
1366 } else {
1367 video_mux(btv,input);
1368 }
Trent Piephoabb03622009-01-28 21:32:59 -03001369 audio_input(btv, (btv->tuner_type != TUNER_ABSENT && input == 0) ?
1370 TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN);
Trent Piepho333408f2007-07-03 15:08:10 -03001371 set_tvnorm(btv, norm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372}
1373
1374static void init_irqreg(struct bttv *btv)
1375{
1376 /* clear status */
1377 btwrite(0xfffffUL, BT848_INT_STAT);
1378
1379 if (bttv_tvcards[btv->c.type].no_video) {
1380 /* i2c only */
1381 btwrite(BT848_INT_I2CDONE,
1382 BT848_INT_MASK);
1383 } else {
1384 /* full video */
1385 btwrite((btv->triton1) |
1386 (btv->gpioirq ? BT848_INT_GPINT : 0) |
1387 BT848_INT_SCERR |
1388 (fdsr ? BT848_INT_FDSR : 0) |
Jean Delvareeb1b27b2008-08-30 10:18:21 -03001389 BT848_INT_RISCI | BT848_INT_OCERR |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390 BT848_INT_FMTCHG|BT848_INT_HLOCK|
1391 BT848_INT_I2CDONE,
1392 BT848_INT_MASK);
1393 }
1394}
1395
1396static void init_bt848(struct bttv *btv)
1397{
1398 int val;
1399
1400 if (bttv_tvcards[btv->c.type].no_video) {
1401 /* very basic init only */
1402 init_irqreg(btv);
1403 return;
1404 }
1405
1406 btwrite(0x00, BT848_CAP_CTL);
1407 btwrite(BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL);
1408 btwrite(BT848_IFORM_XTAUTO | BT848_IFORM_AUTO, BT848_IFORM);
1409
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001410 /* set planar and packed mode trigger points and */
1411 /* set rising edge of inverted GPINTR pin as irq trigger */
1412 btwrite(BT848_GPIO_DMA_CTL_PKTP_32|
1413 BT848_GPIO_DMA_CTL_PLTP1_16|
1414 BT848_GPIO_DMA_CTL_PLTP23_16|
1415 BT848_GPIO_DMA_CTL_GPINTC|
1416 BT848_GPIO_DMA_CTL_GPINTI,
1417 BT848_GPIO_DMA_CTL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418
1419 val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001420 btwrite(val, BT848_E_SCLOOP);
1421 btwrite(val, BT848_O_SCLOOP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001423 btwrite(0x20, BT848_E_VSCALE_HI);
1424 btwrite(0x20, BT848_O_VSCALE_HI);
1425 btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426 BT848_ADC);
1427
1428 btwrite(whitecrush_upper, BT848_WC_UP);
1429 btwrite(whitecrush_lower, BT848_WC_DOWN);
1430
1431 if (btv->opt_lumafilter) {
1432 btwrite(0, BT848_E_CONTROL);
1433 btwrite(0, BT848_O_CONTROL);
1434 } else {
1435 btwrite(BT848_CONTROL_LDEC, BT848_E_CONTROL);
1436 btwrite(BT848_CONTROL_LDEC, BT848_O_CONTROL);
1437 }
1438
1439 bt848_bright(btv, btv->bright);
1440 bt848_hue(btv, btv->hue);
1441 bt848_contrast(btv, btv->contrast);
1442 bt848_sat(btv, btv->saturation);
1443
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001444 /* interrupt */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 init_irqreg(btv);
1446}
1447
1448static void bttv_reinit_bt848(struct bttv *btv)
1449{
1450 unsigned long flags;
1451
1452 if (bttv_verbose)
Joe Perches8af443e2011-08-21 19:56:48 -03001453 pr_info("%d: reset, reinitialize\n", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 spin_lock_irqsave(&btv->s_lock,flags);
1455 btv->errors=0;
1456 bttv_set_dma(btv,0);
1457 spin_unlock_irqrestore(&btv->s_lock,flags);
1458
1459 init_bt848(btv);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001460 btv->pll.pll_current = -1;
Trent Piepho333408f2007-07-03 15:08:10 -03001461 set_input(btv, btv->input, btv->tvnorm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462}
1463
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001464static int bttv_g_ctrl(struct file *file, void *priv,
1465 struct v4l2_control *c)
1466{
1467 struct bttv_fh *fh = priv;
1468 struct bttv *btv = fh->btv;
1469
1470 switch (c->id) {
1471 case V4L2_CID_BRIGHTNESS:
1472 c->value = btv->bright;
1473 break;
1474 case V4L2_CID_HUE:
1475 c->value = btv->hue;
1476 break;
1477 case V4L2_CID_CONTRAST:
1478 c->value = btv->contrast;
1479 break;
1480 case V4L2_CID_SATURATION:
1481 c->value = btv->saturation;
1482 break;
1483
1484 case V4L2_CID_AUDIO_MUTE:
1485 case V4L2_CID_AUDIO_VOLUME:
1486 case V4L2_CID_AUDIO_BALANCE:
1487 case V4L2_CID_AUDIO_BASS:
1488 case V4L2_CID_AUDIO_TREBLE:
Hans Verkuil859f0272009-03-28 08:29:00 -03001489 bttv_call_all(btv, core, g_ctrl, c);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001490 break;
1491
1492 case V4L2_CID_PRIVATE_CHROMA_AGC:
1493 c->value = btv->opt_chroma_agc;
1494 break;
1495 case V4L2_CID_PRIVATE_COMBFILTER:
1496 c->value = btv->opt_combfilter;
1497 break;
1498 case V4L2_CID_PRIVATE_LUMAFILTER:
1499 c->value = btv->opt_lumafilter;
1500 break;
1501 case V4L2_CID_PRIVATE_AUTOMUTE:
1502 c->value = btv->opt_automute;
1503 break;
1504 case V4L2_CID_PRIVATE_AGC_CRUSH:
1505 c->value = btv->opt_adc_crush;
1506 break;
1507 case V4L2_CID_PRIVATE_VCR_HACK:
1508 c->value = btv->opt_vcr_hack;
1509 break;
1510 case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
1511 c->value = btv->opt_whitecrush_upper;
1512 break;
1513 case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
1514 c->value = btv->opt_whitecrush_lower;
1515 break;
1516 case V4L2_CID_PRIVATE_UV_RATIO:
1517 c->value = btv->opt_uv_ratio;
1518 break;
1519 case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
1520 c->value = btv->opt_full_luma_range;
1521 break;
1522 case V4L2_CID_PRIVATE_CORING:
1523 c->value = btv->opt_coring;
1524 break;
1525 default:
1526 return -EINVAL;
1527 }
1528 return 0;
1529}
1530
1531static int bttv_s_ctrl(struct file *file, void *f,
1532 struct v4l2_control *c)
1533{
1534 int err;
1535 int val;
1536 struct bttv_fh *fh = f;
1537 struct bttv *btv = fh->btv;
1538
Hans Verkuilffb48772010-05-01 08:03:24 -03001539 err = v4l2_prio_check(&btv->prio, fh->prio);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001540 if (0 != err)
1541 return err;
1542
1543 switch (c->id) {
1544 case V4L2_CID_BRIGHTNESS:
1545 bt848_bright(btv, c->value);
1546 break;
1547 case V4L2_CID_HUE:
1548 bt848_hue(btv, c->value);
1549 break;
1550 case V4L2_CID_CONTRAST:
1551 bt848_contrast(btv, c->value);
1552 break;
1553 case V4L2_CID_SATURATION:
1554 bt848_sat(btv, c->value);
1555 break;
1556 case V4L2_CID_AUDIO_MUTE:
1557 audio_mute(btv, c->value);
1558 /* fall through */
1559 case V4L2_CID_AUDIO_VOLUME:
1560 if (btv->volume_gpio)
1561 btv->volume_gpio(btv, c->value);
1562
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 case V4L2_CID_AUDIO_BALANCE:
1566 case V4L2_CID_AUDIO_BASS:
1567 case V4L2_CID_AUDIO_TREBLE:
Hans Verkuil859f0272009-03-28 08:29:00 -03001568 bttv_call_all(btv, core, s_ctrl, c);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001569 break;
1570
1571 case V4L2_CID_PRIVATE_CHROMA_AGC:
1572 btv->opt_chroma_agc = c->value;
1573 val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
1574 btwrite(val, BT848_E_SCLOOP);
1575 btwrite(val, BT848_O_SCLOOP);
1576 break;
1577 case V4L2_CID_PRIVATE_COMBFILTER:
1578 btv->opt_combfilter = c->value;
1579 break;
1580 case V4L2_CID_PRIVATE_LUMAFILTER:
1581 btv->opt_lumafilter = c->value;
1582 if (btv->opt_lumafilter) {
1583 btand(~BT848_CONTROL_LDEC, BT848_E_CONTROL);
1584 btand(~BT848_CONTROL_LDEC, BT848_O_CONTROL);
1585 } else {
1586 btor(BT848_CONTROL_LDEC, BT848_E_CONTROL);
1587 btor(BT848_CONTROL_LDEC, BT848_O_CONTROL);
1588 }
1589 break;
1590 case V4L2_CID_PRIVATE_AUTOMUTE:
1591 btv->opt_automute = c->value;
1592 break;
1593 case V4L2_CID_PRIVATE_AGC_CRUSH:
1594 btv->opt_adc_crush = c->value;
1595 btwrite(BT848_ADC_RESERVED |
1596 (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
1597 BT848_ADC);
1598 break;
1599 case V4L2_CID_PRIVATE_VCR_HACK:
1600 btv->opt_vcr_hack = c->value;
1601 break;
1602 case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
1603 btv->opt_whitecrush_upper = c->value;
1604 btwrite(c->value, BT848_WC_UP);
1605 break;
1606 case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
1607 btv->opt_whitecrush_lower = c->value;
1608 btwrite(c->value, BT848_WC_DOWN);
1609 break;
1610 case V4L2_CID_PRIVATE_UV_RATIO:
1611 btv->opt_uv_ratio = c->value;
1612 bt848_sat(btv, btv->saturation);
1613 break;
1614 case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
1615 btv->opt_full_luma_range = c->value;
1616 btaor((c->value<<7), ~BT848_OFORM_RANGE, BT848_OFORM);
1617 break;
1618 case V4L2_CID_PRIVATE_CORING:
1619 btv->opt_coring = c->value;
1620 btaor((c->value<<5), ~BT848_OFORM_CORE32, BT848_OFORM);
1621 break;
1622 default:
1623 return -EINVAL;
1624 }
1625 return 0;
1626}
1627
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628/* ----------------------------------------------------------------------- */
1629
1630void bttv_gpio_tracking(struct bttv *btv, char *comment)
1631{
1632 unsigned int outbits, data;
1633 outbits = btread(BT848_GPIO_OUT_EN);
1634 data = btread(BT848_GPIO_DATA);
Joe Perches8af443e2011-08-21 19:56:48 -03001635 pr_debug("%d: gpio: en=%08x, out=%08x in=%08x [%s]\n",
1636 btv->c.nr, outbits, data & outbits, data & ~outbits, comment);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637}
1638
1639static void bttv_field_count(struct bttv *btv)
1640{
1641 int need_count = 0;
1642
1643 if (btv->users)
1644 need_count++;
1645
1646 if (need_count) {
1647 /* start field counter */
1648 btor(BT848_INT_VSYNC,BT848_INT_MASK);
1649 } else {
1650 /* stop field counter */
1651 btand(~BT848_INT_VSYNC,BT848_INT_MASK);
1652 btv->field_count = 0;
1653 }
1654}
1655
1656static const struct bttv_format*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657format_by_fourcc(int fourcc)
1658{
1659 unsigned int i;
1660
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001661 for (i = 0; i < FORMATS; i++) {
1662 if (-1 == formats[i].fourcc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663 continue;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001664 if (formats[i].fourcc == fourcc)
1665 return formats+i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666 }
1667 return NULL;
1668}
1669
1670/* ----------------------------------------------------------------------- */
1671/* misc helpers */
1672
1673static int
1674bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh,
1675 struct bttv_buffer *new)
1676{
1677 struct bttv_buffer *old;
1678 unsigned long flags;
1679 int retval = 0;
1680
Joe Perches8af443e2011-08-21 19:56:48 -03001681 dprintk("switch_overlay: enter [new=%p]\n", new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682 if (new)
Brandon Philips0fc06862007-11-06 20:02:36 -03001683 new->vb.state = VIDEOBUF_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684 spin_lock_irqsave(&btv->s_lock,flags);
1685 old = btv->screen;
1686 btv->screen = new;
1687 btv->loop_irq |= 1;
1688 bttv_set_dma(btv, 0x03);
1689 spin_unlock_irqrestore(&btv->s_lock,flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690 if (NULL != old) {
Joe Perches8af443e2011-08-21 19:56:48 -03001691 dprintk("switch_overlay: old=%p state is %d\n",
1692 old, old->vb.state);
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001693 bttv_dma_free(&fh->cap,btv, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694 kfree(old);
1695 }
Michael Schimeke5bd0262007-01-18 16:17:39 -03001696 if (NULL == new)
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03001697 free_btres_lock(btv,fh,RESOURCE_OVERLAY);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001698 dprintk("switch_overlay: done\n");
1699 return retval;
1700}
1701
1702/* ----------------------------------------------------------------------- */
1703/* video4linux (1) interface */
1704
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001705static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv,
1706 struct bttv_buffer *buf,
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001707 const struct bttv_format *fmt,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708 unsigned int width, unsigned int height,
1709 enum v4l2_field field)
1710{
Michael Schimeke5bd0262007-01-18 16:17:39 -03001711 struct bttv_fh *fh = q->priv_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 int redo_dma_risc = 0;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001713 struct bttv_crop c;
1714 int norm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 int rc;
1716
1717 /* check settings */
1718 if (NULL == fmt)
1719 return -EINVAL;
1720 if (fmt->btformat == BT848_COLOR_FMT_RAW) {
1721 width = RAW_BPL;
1722 height = RAW_LINES*2;
1723 if (width*height > buf->vb.bsize)
1724 return -EINVAL;
1725 buf->vb.size = buf->vb.bsize;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001726
1727 /* Make sure tvnorm and vbi_end remain consistent
1728 until we're done. */
Michael Schimeke5bd0262007-01-18 16:17:39 -03001729
1730 norm = btv->tvnorm;
1731
1732 /* In this mode capturing always starts at defrect.top
1733 (default VDELAY), ignoring cropping parameters. */
1734 if (btv->vbi_end > bttv_tvnorms[norm].cropcap.defrect.top) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735 return -EINVAL;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001736 }
1737
Michael Schimeke5bd0262007-01-18 16:17:39 -03001738 c.rect = bttv_tvnorms[norm].cropcap.defrect;
1739 } else {
Michael Schimeke5bd0262007-01-18 16:17:39 -03001740 norm = btv->tvnorm;
1741 c = btv->crop[!!fh->do_crop];
1742
Michael Schimeke5bd0262007-01-18 16:17:39 -03001743 if (width < c.min_scaled_width ||
1744 width > c.max_scaled_width ||
1745 height < c.min_scaled_height)
1746 return -EINVAL;
1747
1748 switch (field) {
1749 case V4L2_FIELD_TOP:
1750 case V4L2_FIELD_BOTTOM:
1751 case V4L2_FIELD_ALTERNATE:
1752 /* btv->crop counts frame lines. Max. scale
1753 factor is 16:1 for frames, 8:1 for fields. */
1754 if (height * 2 > c.max_scaled_height)
1755 return -EINVAL;
1756 break;
1757
1758 default:
1759 if (height > c.max_scaled_height)
1760 return -EINVAL;
1761 break;
1762 }
1763
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764 buf->vb.size = (width * height * fmt->depth) >> 3;
1765 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
1766 return -EINVAL;
1767 }
1768
1769 /* alloc + fill struct bttv_buffer (if changed) */
1770 if (buf->vb.width != width || buf->vb.height != height ||
1771 buf->vb.field != field ||
Michael Schimeke5bd0262007-01-18 16:17:39 -03001772 buf->tvnorm != norm || buf->fmt != fmt ||
1773 buf->crop.top != c.rect.top ||
1774 buf->crop.left != c.rect.left ||
1775 buf->crop.width != c.rect.width ||
1776 buf->crop.height != c.rect.height) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777 buf->vb.width = width;
1778 buf->vb.height = height;
1779 buf->vb.field = field;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001780 buf->tvnorm = norm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781 buf->fmt = fmt;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001782 buf->crop = c.rect;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783 redo_dma_risc = 1;
1784 }
1785
1786 /* alloc risc memory */
Brandon Philips0fc06862007-11-06 20:02:36 -03001787 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788 redo_dma_risc = 1;
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001789 if (0 != (rc = videobuf_iolock(q,&buf->vb,&btv->fbuf)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001790 goto fail;
1791 }
1792
1793 if (redo_dma_risc)
1794 if (0 != (rc = bttv_buffer_risc(btv,buf)))
1795 goto fail;
1796
Brandon Philips0fc06862007-11-06 20:02:36 -03001797 buf->vb.state = VIDEOBUF_PREPARED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798 return 0;
1799
1800 fail:
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001801 bttv_dma_free(q,btv,buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802 return rc;
1803}
1804
1805static int
1806buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
1807{
1808 struct bttv_fh *fh = q->priv_data;
1809
1810 *size = fh->fmt->depth*fh->width*fh->height >> 3;
1811 if (0 == *count)
1812 *count = gbuffers;
Andreas Bombedab7e312010-03-21 16:02:45 -03001813 if (*size * *count > gbuffers * gbufsize)
1814 *count = (gbuffers * gbufsize) / *size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815 return 0;
1816}
1817
1818static int
1819buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
1820 enum v4l2_field field)
1821{
1822 struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
1823 struct bttv_fh *fh = q->priv_data;
1824
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001825 return bttv_prepare_buffer(q,fh->btv, buf, fh->fmt,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826 fh->width, fh->height, field);
1827}
1828
1829static void
1830buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
1831{
1832 struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
1833 struct bttv_fh *fh = q->priv_data;
1834 struct bttv *btv = fh->btv;
1835
Brandon Philips0fc06862007-11-06 20:02:36 -03001836 buf->vb.state = VIDEOBUF_QUEUED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837 list_add_tail(&buf->vb.queue,&btv->capture);
1838 if (!btv->curr.frame_irq) {
1839 btv->loop_irq |= 1;
1840 bttv_set_dma(btv, 0x03);
1841 }
1842}
1843
1844static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
1845{
1846 struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
1847 struct bttv_fh *fh = q->priv_data;
1848
Michael Schimekfeaba7a2007-01-26 08:30:05 -03001849 bttv_dma_free(q,fh->btv,buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850}
1851
1852static struct videobuf_queue_ops bttv_video_qops = {
1853 .buf_setup = buffer_setup,
1854 .buf_prepare = buffer_prepare,
1855 .buf_queue = buffer_queue,
1856 .buf_release = buffer_release,
1857};
1858
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001859static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001861 struct bttv_fh *fh = priv;
1862 struct bttv *btv = fh->btv;
1863 unsigned int i;
1864 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865
Hans Verkuilffb48772010-05-01 08:03:24 -03001866 err = v4l2_prio_check(&btv->prio, fh->prio);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001867 if (err)
1868 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001870 for (i = 0; i < BTTV_TVNORMS; i++)
1871 if (*id & bttv_tvnorms[i].v4l2_id)
1872 break;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001873 if (i == BTTV_TVNORMS) {
1874 err = -EINVAL;
1875 goto err;
1876 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001878 set_tvnorm(btv, i);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001879
1880err:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001882 return err;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001883}
1884
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001885static int bttv_querystd(struct file *file, void *f, v4l2_std_id *id)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001886{
1887 struct bttv_fh *fh = f;
1888 struct bttv *btv = fh->btv;
1889
1890 if (btread(BT848_DSTATUS) & BT848_DSTATUS_NUML)
1891 *id = V4L2_STD_625_50;
1892 else
1893 *id = V4L2_STD_525_60;
1894 return 0;
1895}
1896
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001897static int bttv_enum_input(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001898 struct v4l2_input *i)
1899{
1900 struct bttv_fh *fh = priv;
1901 struct bttv *btv = fh->btv;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001902 int rc = 0;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001903
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001904 if (i->index >= bttv_tvcards[btv->c.type].video_inputs) {
1905 rc = -EINVAL;
1906 goto err;
1907 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001908
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001909 i->type = V4L2_INPUT_TYPE_CAMERA;
1910 i->audioset = 1;
1911
Trent Piephoabb03622009-01-28 21:32:59 -03001912 if (btv->tuner_type != TUNER_ABSENT && i->index == 0) {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001913 sprintf(i->name, "Television");
1914 i->type = V4L2_INPUT_TYPE_TUNER;
1915 i->tuner = 0;
1916 } else if (i->index == btv->svhs) {
1917 sprintf(i->name, "S-Video");
1918 } else {
1919 sprintf(i->name, "Composite%d", i->index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920 }
1921
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001922 if (i->index == btv->input) {
1923 __u32 dstatus = btread(BT848_DSTATUS);
1924 if (0 == (dstatus & BT848_DSTATUS_PRES))
1925 i->status |= V4L2_IN_ST_NO_SIGNAL;
1926 if (0 == (dstatus & BT848_DSTATUS_HLOC))
1927 i->status |= V4L2_IN_ST_NO_H_LOCK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928 }
1929
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001930 i->std = BTTV_NORMS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001932err:
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001933
1934 return rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001935}
Nickolay V. Shmyrev4b9b9362006-08-25 16:53:04 -03001936
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001937static int bttv_g_input(struct file *file, void *priv, unsigned int *i)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001938{
1939 struct bttv_fh *fh = priv;
1940 struct bttv *btv = fh->btv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001942 *i = btv->input;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001943
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001944 return 0;
1945}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001947static int bttv_s_input(struct file *file, void *priv, unsigned int i)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001948{
1949 struct bttv_fh *fh = priv;
1950 struct bttv *btv = fh->btv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001951
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001952 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001954 err = v4l2_prio_check(&btv->prio, fh->prio);
1955 if (unlikely(err))
1956 goto err;
1957
1958 if (i > bttv_tvcards[btv->c.type].video_inputs) {
1959 err = -EINVAL;
1960 goto err;
1961 }
1962
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001963 set_input(btv, i, btv->tvnorm);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001964
1965err:
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001966 return 0;
1967}
1968
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001969static int bttv_s_tuner(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001970 struct v4l2_tuner *t)
1971{
1972 struct bttv_fh *fh = priv;
1973 struct bttv *btv = fh->btv;
1974 int err;
1975
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001976 if (unlikely(0 != t->index))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001977 return -EINVAL;
1978
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001979 if (unlikely(btv->tuner_type == TUNER_ABSENT)) {
1980 err = -EINVAL;
1981 goto err;
1982 }
1983
1984 err = v4l2_prio_check(&btv->prio, fh->prio);
1985 if (unlikely(err))
1986 goto err;
1987
Hans Verkuil859f0272009-03-28 08:29:00 -03001988 bttv_call_all(btv, tuner, s_tuner, t);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001989
1990 if (btv->audio_mode_gpio)
1991 btv->audio_mode_gpio(btv, t, 1);
1992
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001993err:
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001994
1995 return 0;
1996}
1997
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001998static int bttv_g_frequency(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001999 struct v4l2_frequency *f)
2000{
2001 struct bttv_fh *fh = priv;
2002 struct bttv *btv = fh->btv;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002003
Robert Fitzsimons1b069012008-04-01 11:41:54 -03002004 f->type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002005 f->frequency = btv->freq;
2006
2007 return 0;
2008}
2009
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002010static int bttv_s_frequency(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002011 struct v4l2_frequency *f)
2012{
2013 struct bttv_fh *fh = priv;
2014 struct bttv *btv = fh->btv;
2015 int err;
2016
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002017 if (unlikely(f->tuner != 0))
2018 return -EINVAL;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002019
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002020 err = v4l2_prio_check(&btv->prio, fh->prio);
2021 if (unlikely(err))
2022 goto err;
2023
2024 if (unlikely(f->type != (btv->radio_user
2025 ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV))) {
2026 err = -EINVAL;
2027 goto err;
2028 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002029 btv->freq = f->frequency;
Hans Verkuil859f0272009-03-28 08:29:00 -03002030 bttv_call_all(btv, tuner, s_frequency, f);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002031 if (btv->has_matchbox && btv->radio_user)
2032 tea5757_set_freq(btv, btv->freq);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002033err:
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002034
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002035 return 0;
2036}
2037
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002038static int bttv_log_status(struct file *file, void *f)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002039{
2040 struct bttv_fh *fh = f;
2041 struct bttv *btv = fh->btv;
2042
Hans Verkuil859f0272009-03-28 08:29:00 -03002043 bttv_call_all(btv, core, log_status);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002044 return 0;
2045}
2046
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002047#ifdef CONFIG_VIDEO_ADV_DEBUG
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002048static int bttv_g_register(struct file *file, void *f,
Hans Verkuilaecde8b2008-12-30 07:14:19 -03002049 struct v4l2_dbg_register *reg)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002050{
2051 struct bttv_fh *fh = f;
2052 struct bttv *btv = fh->btv;
2053
2054 if (!capable(CAP_SYS_ADMIN))
2055 return -EPERM;
2056
Hans Verkuilaecde8b2008-12-30 07:14:19 -03002057 if (!v4l2_chip_match_host(&reg->match))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002058 return -EINVAL;
2059
2060 /* bt848 has a 12-bit register space */
2061 reg->reg &= 0xfff;
2062 reg->val = btread(reg->reg);
Hans Verkuilaecde8b2008-12-30 07:14:19 -03002063 reg->size = 1;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002064
2065 return 0;
2066}
2067
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002068static int bttv_s_register(struct file *file, void *f,
Hans Verkuilaecde8b2008-12-30 07:14:19 -03002069 struct v4l2_dbg_register *reg)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002070{
2071 struct bttv_fh *fh = f;
2072 struct bttv *btv = fh->btv;
2073
2074 if (!capable(CAP_SYS_ADMIN))
2075 return -EPERM;
2076
Hans Verkuilaecde8b2008-12-30 07:14:19 -03002077 if (!v4l2_chip_match_host(&reg->match))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002078 return -EINVAL;
2079
2080 /* bt848 has a 12-bit register space */
2081 reg->reg &= 0xfff;
2082 btwrite(reg->val, reg->reg);
2083
2084 return 0;
2085}
2086#endif
2087
Michael Schimeke5bd0262007-01-18 16:17:39 -03002088/* Given cropping boundaries b and the scaled width and height of a
2089 single field or frame, which must not exceed hardware limits, this
2090 function adjusts the cropping parameters c. */
2091static void
2092bttv_crop_adjust (struct bttv_crop * c,
2093 const struct v4l2_rect * b,
2094 __s32 width,
2095 __s32 height,
2096 enum v4l2_field field)
2097{
2098 __s32 frame_height = height << !V4L2_FIELD_HAS_BOTH(field);
2099 __s32 max_left;
2100 __s32 max_top;
2101
2102 if (width < c->min_scaled_width) {
2103 /* Max. hor. scale factor 16:1. */
2104 c->rect.width = width * 16;
2105 } else if (width > c->max_scaled_width) {
2106 /* Min. hor. scale factor 1:1. */
2107 c->rect.width = width;
2108
2109 max_left = b->left + b->width - width;
2110 max_left = min(max_left, (__s32) MAX_HDELAY);
2111 if (c->rect.left > max_left)
2112 c->rect.left = max_left;
2113 }
2114
2115 if (height < c->min_scaled_height) {
2116 /* Max. vert. scale factor 16:1, single fields 8:1. */
2117 c->rect.height = height * 16;
2118 } else if (frame_height > c->max_scaled_height) {
2119 /* Min. vert. scale factor 1:1.
2120 Top and height count field lines times two. */
2121 c->rect.height = (frame_height + 1) & ~1;
2122
2123 max_top = b->top + b->height - c->rect.height;
2124 if (c->rect.top > max_top)
2125 c->rect.top = max_top;
2126 }
2127
2128 bttv_crop_calc_limits(c);
2129}
2130
2131/* Returns an error if scaling to a frame or single field with the given
2132 width and height is not possible with the current cropping parameters
2133 and width aligned according to width_mask. If adjust_size is TRUE the
2134 function may adjust the width and/or height instead, rounding width
2135 to (width + width_bias) & width_mask. If adjust_crop is TRUE it may
2136 also adjust the current cropping parameters to get closer to the
2137 desired image size. */
2138static int
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002139limit_scaled_size_lock (struct bttv_fh * fh,
Michael Schimeke5bd0262007-01-18 16:17:39 -03002140 __s32 * width,
2141 __s32 * height,
2142 enum v4l2_field field,
2143 unsigned int width_mask,
2144 unsigned int width_bias,
2145 int adjust_size,
2146 int adjust_crop)
2147{
2148 struct bttv *btv = fh->btv;
2149 const struct v4l2_rect *b;
2150 struct bttv_crop *c;
2151 __s32 min_width;
2152 __s32 min_height;
2153 __s32 max_width;
2154 __s32 max_height;
2155 int rc;
2156
2157 BUG_ON((int) width_mask >= 0 ||
2158 width_bias >= (unsigned int) -width_mask);
2159
2160 /* Make sure tvnorm, vbi_end and the current cropping parameters
2161 remain consistent until we're done. */
Michael Schimeke5bd0262007-01-18 16:17:39 -03002162
2163 b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
2164
2165 /* Do crop - use current, don't - use default parameters. */
2166 c = &btv->crop[!!fh->do_crop];
2167
2168 if (fh->do_crop
2169 && adjust_size
2170 && adjust_crop
2171 && !locked_btres(btv, VIDEO_RESOURCES)) {
2172 min_width = 48;
2173 min_height = 32;
2174
2175 /* We cannot scale up. When the scaled image is larger
2176 than crop.rect we adjust the crop.rect as required
2177 by the V4L2 spec, hence cropcap.bounds are our limit. */
2178 max_width = min(b->width, (__s32) MAX_HACTIVE);
2179 max_height = b->height;
2180
2181 /* We cannot capture the same line as video and VBI data.
2182 Note btv->vbi_end is really a minimum, see
2183 bttv_vbi_try_fmt(). */
2184 if (btv->vbi_end > b->top) {
2185 max_height -= btv->vbi_end - b->top;
2186 rc = -EBUSY;
2187 if (min_height > max_height)
2188 goto fail;
2189 }
2190 } else {
2191 rc = -EBUSY;
2192 if (btv->vbi_end > c->rect.top)
2193 goto fail;
2194
2195 min_width = c->min_scaled_width;
2196 min_height = c->min_scaled_height;
2197 max_width = c->max_scaled_width;
2198 max_height = c->max_scaled_height;
2199
2200 adjust_crop = 0;
2201 }
2202
2203 min_width = (min_width - width_mask - 1) & width_mask;
2204 max_width = max_width & width_mask;
2205
2206 /* Max. scale factor is 16:1 for frames, 8:1 for fields. */
2207 min_height = min_height;
2208 /* Min. scale factor is 1:1. */
2209 max_height >>= !V4L2_FIELD_HAS_BOTH(field);
2210
2211 if (adjust_size) {
2212 *width = clamp(*width, min_width, max_width);
2213 *height = clamp(*height, min_height, max_height);
2214
2215 /* Round after clamping to avoid overflow. */
2216 *width = (*width + width_bias) & width_mask;
2217
2218 if (adjust_crop) {
2219 bttv_crop_adjust(c, b, *width, *height, field);
2220
2221 if (btv->vbi_end > c->rect.top) {
2222 /* Move the crop window out of the way. */
2223 c->rect.top = btv->vbi_end;
2224 }
2225 }
2226 } else {
2227 rc = -EINVAL;
2228 if (*width < min_width ||
2229 *height < min_height ||
2230 *width > max_width ||
2231 *height > max_height ||
2232 0 != (*width & ~width_mask))
2233 goto fail;
2234 }
2235
2236 rc = 0; /* success */
2237
2238 fail:
Michael Schimeke5bd0262007-01-18 16:17:39 -03002239
2240 return rc;
2241}
2242
2243/* Returns an error if the given overlay window dimensions are not
2244 possible with the current cropping parameters. If adjust_size is
2245 TRUE the function may adjust the window width and/or height
2246 instead, however it always rounds the horizontal position and
2247 width as btcx_align() does. If adjust_crop is TRUE the function
2248 may also adjust the current cropping parameters to get closer
2249 to the desired window size. */
2250static int
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002251verify_window_lock (struct bttv_fh * fh,
Michael Schimeke5bd0262007-01-18 16:17:39 -03002252 struct v4l2_window * win,
2253 int adjust_size,
2254 int adjust_crop)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255{
2256 enum v4l2_field field;
Michael Schimeke5bd0262007-01-18 16:17:39 -03002257 unsigned int width_mask;
2258 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002259
2260 if (win->w.width < 48 || win->w.height < 32)
2261 return -EINVAL;
2262 if (win->clipcount > 2048)
2263 return -EINVAL;
2264
2265 field = win->field;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266
2267 if (V4L2_FIELD_ANY == field) {
Michael Schimeke5bd0262007-01-18 16:17:39 -03002268 __s32 height2;
2269
2270 height2 = fh->btv->crop[!!fh->do_crop].rect.height >> 1;
2271 field = (win->w.height > height2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272 ? V4L2_FIELD_INTERLACED
2273 : V4L2_FIELD_TOP;
2274 }
2275 switch (field) {
2276 case V4L2_FIELD_TOP:
2277 case V4L2_FIELD_BOTTOM:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278 case V4L2_FIELD_INTERLACED:
2279 break;
2280 default:
2281 return -EINVAL;
2282 }
2283
Michael Schimeke5bd0262007-01-18 16:17:39 -03002284 /* 4-byte alignment. */
2285 if (NULL == fh->ovfmt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286 return -EINVAL;
Michael Schimeke5bd0262007-01-18 16:17:39 -03002287 width_mask = ~0;
2288 switch (fh->ovfmt->depth) {
2289 case 8:
2290 case 24:
2291 width_mask = ~3;
2292 break;
2293 case 16:
2294 width_mask = ~1;
2295 break;
2296 case 32:
2297 break;
2298 default:
2299 BUG();
2300 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301
Michael Schimeke5bd0262007-01-18 16:17:39 -03002302 win->w.width -= win->w.left & ~width_mask;
2303 win->w.left = (win->w.left - width_mask - 1) & width_mask;
2304
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002305 rc = limit_scaled_size_lock(fh, &win->w.width, &win->w.height,
Michael Schimeke5bd0262007-01-18 16:17:39 -03002306 field, width_mask,
2307 /* width_bias: round down */ 0,
2308 adjust_size, adjust_crop);
2309 if (0 != rc)
2310 return rc;
2311
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312 win->field = field;
2313 return 0;
2314}
2315
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002316static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317 struct v4l2_window *win, int fixup)
2318{
2319 struct v4l2_clip *clips = NULL;
2320 int n,size,retval = 0;
2321
2322 if (NULL == fh->ovfmt)
2323 return -EINVAL;
2324 if (!(fh->ovfmt->flags & FORMAT_FLAGS_PACKED))
2325 return -EINVAL;
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002326 retval = verify_window_lock(fh, win,
Michael Schimeke5bd0262007-01-18 16:17:39 -03002327 /* adjust_size */ fixup,
2328 /* adjust_crop */ fixup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329 if (0 != retval)
2330 return retval;
2331
2332 /* copy clips -- luckily v4l1 + v4l2 are binary
2333 compatible here ...*/
2334 n = win->clipcount;
2335 size = sizeof(*clips)*(n+4);
2336 clips = kmalloc(size,GFP_KERNEL);
2337 if (NULL == clips)
2338 return -ENOMEM;
2339 if (n > 0) {
2340 if (copy_from_user(clips,win->clips,sizeof(struct v4l2_clip)*n)) {
2341 kfree(clips);
2342 return -EFAULT;
2343 }
2344 }
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002345
Linus Torvalds1da177e2005-04-16 15:20:36 -07002346 /* clip against screen */
2347 if (NULL != btv->fbuf.base)
2348 n = btcx_screen_clips(btv->fbuf.fmt.width, btv->fbuf.fmt.height,
2349 &win->w, clips, n);
2350 btcx_sort_clips(clips,n);
2351
2352 /* 4-byte alignments */
2353 switch (fh->ovfmt->depth) {
2354 case 8:
2355 case 24:
2356 btcx_align(&win->w, clips, n, 3);
2357 break;
2358 case 16:
2359 btcx_align(&win->w, clips, n, 1);
2360 break;
2361 case 32:
2362 /* no alignment fixups needed */
2363 break;
2364 default:
2365 BUG();
2366 }
2367
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03002368 kfree(fh->ov.clips);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369 fh->ov.clips = clips;
2370 fh->ov.nclips = n;
2371
2372 fh->ov.w = win->w;
2373 fh->ov.field = win->field;
2374 fh->ov.setup_ok = 1;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002375
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376 btv->init.ov.w.width = win->w.width;
2377 btv->init.ov.w.height = win->w.height;
2378 btv->init.ov.field = win->field;
2379
2380 /* update overlay if needed */
2381 retval = 0;
2382 if (check_btres(fh, RESOURCE_OVERLAY)) {
2383 struct bttv_buffer *new;
2384
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03002385 new = videobuf_sg_alloc(sizeof(*new));
Michael Schimeke5bd0262007-01-18 16:17:39 -03002386 new->crop = btv->crop[!!fh->do_crop].rect;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387 bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
2388 retval = bttv_switch_overlay(btv,fh,new);
2389 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390 return retval;
2391}
2392
2393/* ----------------------------------------------------------------------- */
2394
2395static struct videobuf_queue* bttv_queue(struct bttv_fh *fh)
2396{
2397 struct videobuf_queue* q = NULL;
2398
2399 switch (fh->type) {
2400 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2401 q = &fh->cap;
2402 break;
2403 case V4L2_BUF_TYPE_VBI_CAPTURE:
2404 q = &fh->vbi;
2405 break;
2406 default:
2407 BUG();
2408 }
2409 return q;
2410}
2411
2412static int bttv_resource(struct bttv_fh *fh)
2413{
2414 int res = 0;
2415
2416 switch (fh->type) {
2417 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Michael Schimeke5bd0262007-01-18 16:17:39 -03002418 res = RESOURCE_VIDEO_STREAM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002419 break;
2420 case V4L2_BUF_TYPE_VBI_CAPTURE:
2421 res = RESOURCE_VBI;
2422 break;
2423 default:
2424 BUG();
2425 }
2426 return res;
2427}
2428
2429static int bttv_switch_type(struct bttv_fh *fh, enum v4l2_buf_type type)
2430{
2431 struct videobuf_queue *q = bttv_queue(fh);
2432 int res = bttv_resource(fh);
2433
2434 if (check_btres(fh,res))
2435 return -EBUSY;
2436 if (videobuf_queue_is_busy(q))
2437 return -EBUSY;
2438 fh->type = type;
2439 return 0;
2440}
2441
Michael H. Schimekc87c9482005-12-01 00:51:33 -08002442static void
2443pix_format_set_size (struct v4l2_pix_format * f,
2444 const struct bttv_format * fmt,
2445 unsigned int width,
2446 unsigned int height)
2447{
2448 f->width = width;
2449 f->height = height;
2450
2451 if (fmt->flags & FORMAT_FLAGS_PLANAR) {
2452 f->bytesperline = width; /* Y plane */
2453 f->sizeimage = (width * height * fmt->depth) >> 3;
2454 } else {
2455 f->bytesperline = (width * fmt->depth) >> 3;
2456 f->sizeimage = height * f->bytesperline;
2457 }
2458}
2459
Hans Verkuil78b526a2008-05-28 12:16:41 -03002460static int bttv_g_fmt_vid_cap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002461 struct v4l2_format *f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002463 struct bttv_fh *fh = priv;
2464
2465 pix_format_set_size(&f->fmt.pix, fh->fmt,
2466 fh->width, fh->height);
2467 f->fmt.pix.field = fh->cap.field;
2468 f->fmt.pix.pixelformat = fh->fmt->fourcc;
2469
2470 return 0;
2471}
2472
Hans Verkuil78b526a2008-05-28 12:16:41 -03002473static int bttv_g_fmt_vid_overlay(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002474 struct v4l2_format *f)
2475{
2476 struct bttv_fh *fh = priv;
2477
2478 f->fmt.win.w = fh->ov.w;
2479 f->fmt.win.field = fh->ov.field;
2480
2481 return 0;
2482}
2483
Hans Verkuil78b526a2008-05-28 12:16:41 -03002484static int bttv_try_fmt_vid_cap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002485 struct v4l2_format *f)
2486{
2487 const struct bttv_format *fmt;
2488 struct bttv_fh *fh = priv;
2489 struct bttv *btv = fh->btv;
2490 enum v4l2_field field;
2491 __s32 width, height;
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002492 int rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002493
2494 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
2495 if (NULL == fmt)
2496 return -EINVAL;
2497
2498 field = f->fmt.pix.field;
2499
2500 if (V4L2_FIELD_ANY == field) {
2501 __s32 height2;
2502
2503 height2 = btv->crop[!!fh->do_crop].rect.height >> 1;
2504 field = (f->fmt.pix.height > height2)
2505 ? V4L2_FIELD_INTERLACED
2506 : V4L2_FIELD_BOTTOM;
2507 }
2508
2509 if (V4L2_FIELD_SEQ_BT == field)
2510 field = V4L2_FIELD_SEQ_TB;
2511
2512 switch (field) {
2513 case V4L2_FIELD_TOP:
2514 case V4L2_FIELD_BOTTOM:
2515 case V4L2_FIELD_ALTERNATE:
2516 case V4L2_FIELD_INTERLACED:
2517 break;
2518 case V4L2_FIELD_SEQ_TB:
2519 if (fmt->flags & FORMAT_FLAGS_PLANAR)
2520 return -EINVAL;
2521 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522 default:
2523 return -EINVAL;
2524 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002525
2526 width = f->fmt.pix.width;
2527 height = f->fmt.pix.height;
2528
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002529 rc = limit_scaled_size_lock(fh, &width, &height, field,
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002530 /* width_mask: 4 pixels */ ~3,
2531 /* width_bias: nearest */ 2,
2532 /* adjust_size */ 1,
2533 /* adjust_crop */ 0);
2534 if (0 != rc)
2535 return rc;
2536
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002537 /* update data for the application */
2538 f->fmt.pix.field = field;
2539 pix_format_set_size(&f->fmt.pix, fmt, width, height);
2540
2541 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002542}
2543
Hans Verkuil78b526a2008-05-28 12:16:41 -03002544static int bttv_try_fmt_vid_overlay(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002545 struct v4l2_format *f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002546{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002547 struct bttv_fh *fh = priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002549 return verify_window_lock(fh, &f->fmt.win,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002550 /* adjust_size */ 1,
2551 /* adjust_crop */ 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002552}
2553
Hans Verkuil78b526a2008-05-28 12:16:41 -03002554static int bttv_s_fmt_vid_cap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002555 struct v4l2_format *f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002556{
2557 int retval;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002558 const struct bttv_format *fmt;
2559 struct bttv_fh *fh = priv;
2560 struct bttv *btv = fh->btv;
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002561 __s32 width, height;
2562 enum v4l2_field field;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002563
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002564 retval = bttv_switch_type(fh, f->type);
2565 if (0 != retval)
2566 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567
Hans Verkuil78b526a2008-05-28 12:16:41 -03002568 retval = bttv_try_fmt_vid_cap(file, priv, f);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002569 if (0 != retval)
2570 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002572 width = f->fmt.pix.width;
2573 height = f->fmt.pix.height;
2574 field = f->fmt.pix.field;
2575
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002576 retval = limit_scaled_size_lock(fh, &width, &height, f->fmt.pix.field,
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002577 /* width_mask: 4 pixels */ ~3,
2578 /* width_bias: nearest */ 2,
2579 /* adjust_size */ 1,
2580 /* adjust_crop */ 1);
2581 if (0 != retval)
2582 return retval;
2583
2584 f->fmt.pix.field = field;
2585
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002586 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002588 /* update our state informations */
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002589 fh->fmt = fmt;
2590 fh->cap.field = f->fmt.pix.field;
2591 fh->cap.last = V4L2_FIELD_NONE;
2592 fh->width = f->fmt.pix.width;
2593 fh->height = f->fmt.pix.height;
2594 btv->init.fmt = fmt;
2595 btv->init.width = f->fmt.pix.width;
2596 btv->init.height = f->fmt.pix.height;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002597
2598 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002599}
2600
Hans Verkuil78b526a2008-05-28 12:16:41 -03002601static int bttv_s_fmt_vid_overlay(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002602 struct v4l2_format *f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002604 struct bttv_fh *fh = priv;
2605 struct bttv *btv = fh->btv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002607 if (no_overlay > 0) {
Joe Perches8af443e2011-08-21 19:56:48 -03002608 pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002609 return -EINVAL;
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002610 }
Michael Krufky5e453dc2006-01-09 15:32:31 -02002611
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002612 return setup_window_lock(fh, btv, &f->fmt.win, 1);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002613}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002614
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002615static int bttv_querycap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002616 struct v4l2_capability *cap)
2617{
2618 struct bttv_fh *fh = priv;
2619 struct bttv *btv = fh->btv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002621 if (0 == v4l2)
2622 return -EINVAL;
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07002623
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002624 strlcpy(cap->driver, "bttv", sizeof(cap->driver));
2625 strlcpy(cap->card, btv->video_dev->name, sizeof(cap->card));
2626 snprintf(cap->bus_info, sizeof(cap->bus_info),
2627 "PCI:%s", pci_name(btv->c.pci));
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002628 cap->capabilities =
2629 V4L2_CAP_VIDEO_CAPTURE |
2630 V4L2_CAP_VBI_CAPTURE |
2631 V4L2_CAP_READWRITE |
2632 V4L2_CAP_STREAMING;
2633 if (no_overlay <= 0)
2634 cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002636 /*
2637 * No need to lock here: those vars are initialized during board
2638 * probe and remains untouched during the rest of the driver lifecycle
2639 */
2640 if (btv->has_saa6588)
2641 cap->capabilities |= V4L2_CAP_RDS_CAPTURE;
Trent Piephoabb03622009-01-28 21:32:59 -03002642 if (btv->tuner_type != TUNER_ABSENT)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002643 cap->capabilities |= V4L2_CAP_TUNER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002644 return 0;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002645}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002647static int bttv_enum_fmt_cap_ovr(struct v4l2_fmtdesc *f)
2648{
2649 int index = -1, i;
2650
2651 for (i = 0; i < FORMATS; i++) {
2652 if (formats[i].fourcc != -1)
2653 index++;
2654 if ((unsigned int)index == f->index)
2655 break;
2656 }
2657 if (FORMATS == i)
2658 return -EINVAL;
2659
2660 f->pixelformat = formats[i].fourcc;
2661 strlcpy(f->description, formats[i].name, sizeof(f->description));
2662
2663 return i;
2664}
2665
Hans Verkuil78b526a2008-05-28 12:16:41 -03002666static int bttv_enum_fmt_vid_cap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002667 struct v4l2_fmtdesc *f)
2668{
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002669 int rc = bttv_enum_fmt_cap_ovr(f);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002670
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002671 if (rc < 0)
2672 return rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002673
2674 return 0;
2675}
2676
Hans Verkuil78b526a2008-05-28 12:16:41 -03002677static int bttv_enum_fmt_vid_overlay(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002678 struct v4l2_fmtdesc *f)
2679{
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002680 int rc;
2681
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002682 if (no_overlay > 0) {
Joe Perches8af443e2011-08-21 19:56:48 -03002683 pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002684 return -EINVAL;
2685 }
2686
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002687 rc = bttv_enum_fmt_cap_ovr(f);
2688
2689 if (rc < 0)
2690 return rc;
2691
2692 if (!(formats[rc].flags & FORMAT_FLAGS_PACKED))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002693 return -EINVAL;
2694
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002695 return 0;
2696}
2697
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002698static int bttv_g_fbuf(struct file *file, void *f,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002699 struct v4l2_framebuffer *fb)
2700{
2701 struct bttv_fh *fh = f;
2702 struct bttv *btv = fh->btv;
2703
2704 *fb = btv->fbuf;
2705 fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
2706 if (fh->ovfmt)
2707 fb->fmt.pixelformat = fh->ovfmt->fourcc;
2708 return 0;
2709}
2710
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002711static int bttv_overlay(struct file *file, void *f, unsigned int on)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002712{
2713 struct bttv_fh *fh = f;
2714 struct bttv *btv = fh->btv;
2715 struct bttv_buffer *new;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002716 int retval = 0;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002717
2718 if (on) {
2719 /* verify args */
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002720 if (unlikely(!btv->fbuf.base)) {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002721 return -EINVAL;
2722 }
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002723 if (unlikely(!fh->ov.setup_ok)) {
Joe Perches8af443e2011-08-21 19:56:48 -03002724 dprintk("%d: overlay: !setup_ok\n", btv->c.nr);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002725 retval = -EINVAL;
2726 }
2727 if (retval)
2728 return retval;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002729 }
2730
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002731 if (!check_alloc_btres_lock(btv, fh, RESOURCE_OVERLAY))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002732 return -EBUSY;
2733
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002734 if (on) {
2735 fh->ov.tvnorm = btv->tvnorm;
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03002736 new = videobuf_sg_alloc(sizeof(*new));
Robert Fitzsimons7c018802008-02-13 16:38:11 -03002737 new->crop = btv->crop[!!fh->do_crop].rect;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002738 bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
2739 } else {
2740 new = NULL;
2741 }
2742
2743 /* switch over */
2744 retval = bttv_switch_overlay(btv, fh, new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745 return retval;
2746}
2747
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002748static int bttv_s_fbuf(struct file *file, void *f,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002749 struct v4l2_framebuffer *fb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002751 struct bttv_fh *fh = f;
2752 struct bttv *btv = fh->btv;
2753 const struct bttv_format *fmt;
2754 int retval;
2755
2756 if (!capable(CAP_SYS_ADMIN) &&
2757 !capable(CAP_SYS_RAWIO))
2758 return -EPERM;
2759
2760 /* check args */
2761 fmt = format_by_fourcc(fb->fmt.pixelformat);
2762 if (NULL == fmt)
2763 return -EINVAL;
2764 if (0 == (fmt->flags & FORMAT_FLAGS_PACKED))
2765 return -EINVAL;
2766
2767 retval = -EINVAL;
2768 if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
2769 __s32 width = fb->fmt.width;
2770 __s32 height = fb->fmt.height;
2771
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002772 retval = limit_scaled_size_lock(fh, &width, &height,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002773 V4L2_FIELD_INTERLACED,
2774 /* width_mask */ ~3,
2775 /* width_bias */ 2,
2776 /* adjust_size */ 0,
2777 /* adjust_crop */ 0);
2778 if (0 != retval)
2779 return retval;
2780 }
2781
2782 /* ok, accept it */
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002783 btv->fbuf.base = fb->base;
2784 btv->fbuf.fmt.width = fb->fmt.width;
2785 btv->fbuf.fmt.height = fb->fmt.height;
2786 if (0 != fb->fmt.bytesperline)
2787 btv->fbuf.fmt.bytesperline = fb->fmt.bytesperline;
2788 else
2789 btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fmt->depth/8;
2790
2791 retval = 0;
2792 fh->ovfmt = fmt;
2793 btv->init.ovfmt = fmt;
2794 if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
2795 fh->ov.w.left = 0;
2796 fh->ov.w.top = 0;
2797 fh->ov.w.width = fb->fmt.width;
2798 fh->ov.w.height = fb->fmt.height;
2799 btv->init.ov.w.width = fb->fmt.width;
2800 btv->init.ov.w.height = fb->fmt.height;
2801 kfree(fh->ov.clips);
2802 fh->ov.clips = NULL;
2803 fh->ov.nclips = 0;
2804
2805 if (check_btres(fh, RESOURCE_OVERLAY)) {
2806 struct bttv_buffer *new;
2807
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03002808 new = videobuf_sg_alloc(sizeof(*new));
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002809 new->crop = btv->crop[!!fh->do_crop].rect;
2810 bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
2811 retval = bttv_switch_overlay(btv, fh, new);
2812 }
2813 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002814 return retval;
2815}
2816
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002817static int bttv_reqbufs(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002818 struct v4l2_requestbuffers *p)
2819{
2820 struct bttv_fh *fh = priv;
2821 return videobuf_reqbufs(bttv_queue(fh), p);
2822}
2823
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002824static int bttv_querybuf(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002825 struct v4l2_buffer *b)
2826{
2827 struct bttv_fh *fh = priv;
2828 return videobuf_querybuf(bttv_queue(fh), b);
2829}
2830
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002831static int bttv_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002832{
2833 struct bttv_fh *fh = priv;
2834 struct bttv *btv = fh->btv;
2835 int res = bttv_resource(fh);
2836
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002837 if (!check_alloc_btres_lock(btv, fh, res))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002838 return -EBUSY;
2839
2840 return videobuf_qbuf(bttv_queue(fh), b);
2841}
2842
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002843static int bttv_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002844{
2845 struct bttv_fh *fh = priv;
2846 return videobuf_dqbuf(bttv_queue(fh), b,
2847 file->f_flags & O_NONBLOCK);
2848}
2849
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002850static int bttv_streamon(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002851 enum v4l2_buf_type type)
2852{
2853 struct bttv_fh *fh = priv;
2854 struct bttv *btv = fh->btv;
2855 int res = bttv_resource(fh);
2856
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002857 if (!check_alloc_btres_lock(btv, fh, res))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002858 return -EBUSY;
2859 return videobuf_streamon(bttv_queue(fh));
2860}
2861
2862
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002863static int bttv_streamoff(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002864 enum v4l2_buf_type type)
2865{
2866 struct bttv_fh *fh = priv;
2867 struct bttv *btv = fh->btv;
2868 int retval;
2869 int res = bttv_resource(fh);
2870
2871
2872 retval = videobuf_streamoff(bttv_queue(fh));
2873 if (retval < 0)
2874 return retval;
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002875 free_btres_lock(btv, fh, res);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002876 return 0;
2877}
2878
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002879static int bttv_queryctrl(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002880 struct v4l2_queryctrl *c)
2881{
2882 struct bttv_fh *fh = priv;
2883 struct bttv *btv = fh->btv;
2884 const struct v4l2_queryctrl *ctrl;
2885
2886 if ((c->id < V4L2_CID_BASE ||
2887 c->id >= V4L2_CID_LASTP1) &&
2888 (c->id < V4L2_CID_PRIVATE_BASE ||
2889 c->id >= V4L2_CID_PRIVATE_LASTP1))
2890 return -EINVAL;
2891
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002892 if (!btv->volume_gpio && (c->id == V4L2_CID_AUDIO_VOLUME))
2893 *c = no_ctl;
2894 else {
2895 ctrl = ctrl_by_id(c->id);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002896
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002897 *c = (NULL != ctrl) ? *ctrl : no_ctl;
2898 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002899
2900 return 0;
2901}
2902
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002903static int bttv_g_parm(struct file *file, void *f,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002904 struct v4l2_streamparm *parm)
2905{
2906 struct bttv_fh *fh = f;
2907 struct bttv *btv = fh->btv;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002908
Trent Piepho51f0b8d2009-03-04 01:21:02 -03002909 v4l2_video_std_frame_period(bttv_tvnorms[btv->tvnorm].v4l2_id,
2910 &parm->parm.capture.timeperframe);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002911
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002912 return 0;
2913}
2914
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002915static int bttv_g_tuner(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002916 struct v4l2_tuner *t)
2917{
2918 struct bttv_fh *fh = priv;
2919 struct bttv *btv = fh->btv;
2920
Trent Piephoabb03622009-01-28 21:32:59 -03002921 if (btv->tuner_type == TUNER_ABSENT)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002922 return -EINVAL;
2923 if (0 != t->index)
2924 return -EINVAL;
2925
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002926 t->rxsubchans = V4L2_TUNER_SUB_MONO;
Hans Verkuil859f0272009-03-28 08:29:00 -03002927 bttv_call_all(btv, tuner, g_tuner, t);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002928 strcpy(t->name, "Television");
2929 t->capability = V4L2_TUNER_CAP_NORM;
2930 t->type = V4L2_TUNER_ANALOG_TV;
2931 if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)
2932 t->signal = 0xffff;
2933
2934 if (btv->audio_mode_gpio)
2935 btv->audio_mode_gpio(btv, t, 0);
2936
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002937 return 0;
2938}
2939
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002940static int bttv_g_priority(struct file *file, void *f, enum v4l2_priority *p)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002941{
2942 struct bttv_fh *fh = f;
2943 struct bttv *btv = fh->btv;
2944
2945 *p = v4l2_prio_max(&btv->prio);
2946
2947 return 0;
2948}
2949
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002950static int bttv_s_priority(struct file *file, void *f,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002951 enum v4l2_priority prio)
2952{
2953 struct bttv_fh *fh = f;
2954 struct bttv *btv = fh->btv;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002955 int rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002956
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002957 rc = v4l2_prio_change(&btv->prio, &fh->prio, prio);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002958
2959 return rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002960}
2961
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002962static int bttv_cropcap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002963 struct v4l2_cropcap *cap)
2964{
2965 struct bttv_fh *fh = priv;
2966 struct bttv *btv = fh->btv;
2967
2968 if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
2969 cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
2970 return -EINVAL;
2971
2972 *cap = bttv_tvnorms[btv->tvnorm].cropcap;
2973
2974 return 0;
2975}
2976
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002977static int bttv_g_crop(struct file *file, void *f, struct v4l2_crop *crop)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002978{
2979 struct bttv_fh *fh = f;
2980 struct bttv *btv = fh->btv;
2981
2982 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
2983 crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
2984 return -EINVAL;
2985
2986 /* No fh->do_crop = 1; because btv->crop[1] may be
2987 inconsistent with fh->width or fh->height and apps
2988 do not expect a change here. */
2989
2990 crop->c = btv->crop[!!fh->do_crop].rect;
2991
2992 return 0;
2993}
2994
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002995static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002996{
2997 struct bttv_fh *fh = f;
2998 struct bttv *btv = fh->btv;
2999 const struct v4l2_rect *b;
3000 int retval;
3001 struct bttv_crop c;
3002 __s32 b_left;
3003 __s32 b_top;
3004 __s32 b_right;
3005 __s32 b_bottom;
3006
3007 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
3008 crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
3009 return -EINVAL;
3010
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003011 /* Make sure tvnorm, vbi_end and the current cropping
3012 parameters remain consistent until we're done. Note
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003013 read() may change vbi_end in check_alloc_btres_lock(). */
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003014 retval = v4l2_prio_check(&btv->prio, fh->prio);
3015 if (0 != retval) {
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003016 return retval;
3017 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003018
3019 retval = -EBUSY;
3020
3021 if (locked_btres(fh->btv, VIDEO_RESOURCES)) {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003022 return retval;
3023 }
3024
3025 b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
3026
3027 b_left = b->left;
3028 b_right = b_left + b->width;
3029 b_bottom = b->top + b->height;
3030
3031 b_top = max(b->top, btv->vbi_end);
3032 if (b_top + 32 >= b_bottom) {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003033 return retval;
3034 }
3035
3036 /* Min. scaled size 48 x 32. */
3037 c.rect.left = clamp(crop->c.left, b_left, b_right - 48);
3038 c.rect.left = min(c.rect.left, (__s32) MAX_HDELAY);
3039
3040 c.rect.width = clamp(crop->c.width,
3041 48, b_right - c.rect.left);
3042
3043 c.rect.top = clamp(crop->c.top, b_top, b_bottom - 32);
3044 /* Top and height must be a multiple of two. */
3045 c.rect.top = (c.rect.top + 1) & ~1;
3046
3047 c.rect.height = clamp(crop->c.height,
3048 32, b_bottom - c.rect.top);
3049 c.rect.height = (c.rect.height + 1) & ~1;
3050
3051 bttv_crop_calc_limits(&c);
3052
3053 btv->crop[1] = c;
3054
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003055 fh->do_crop = 1;
3056
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003057 if (fh->width < c.min_scaled_width) {
3058 fh->width = c.min_scaled_width;
3059 btv->init.width = c.min_scaled_width;
3060 } else if (fh->width > c.max_scaled_width) {
3061 fh->width = c.max_scaled_width;
3062 btv->init.width = c.max_scaled_width;
3063 }
3064
3065 if (fh->height < c.min_scaled_height) {
3066 fh->height = c.min_scaled_height;
3067 btv->init.height = c.min_scaled_height;
3068 } else if (fh->height > c.max_scaled_height) {
3069 fh->height = c.max_scaled_height;
3070 btv->init.height = c.max_scaled_height;
3071 }
3072
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003073 return 0;
3074}
3075
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003076static int bttv_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003077{
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03003078 if (unlikely(a->index))
3079 return -EINVAL;
3080
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003081 strcpy(a->name, "audio");
3082 return 0;
3083}
3084
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003085static int bttv_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003086{
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03003087 if (unlikely(a->index))
3088 return -EINVAL;
3089
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003090 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003091}
3092
3093static ssize_t bttv_read(struct file *file, char __user *data,
3094 size_t count, loff_t *ppos)
3095{
3096 struct bttv_fh *fh = file->private_data;
3097 int retval = 0;
3098
3099 if (fh->btv->errors)
3100 bttv_reinit_bt848(fh->btv);
Joe Perches8af443e2011-08-21 19:56:48 -03003101 dprintk("%d: read count=%d type=%s\n",
3102 fh->btv->c.nr, (int)count, v4l2_type_names[fh->type]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003103
3104 switch (fh->type) {
3105 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003106 if (!check_alloc_btres_lock(fh->btv, fh, RESOURCE_VIDEO_READ)) {
Michael Schimeke5bd0262007-01-18 16:17:39 -03003107 /* VIDEO_READ in use by another fh,
3108 or VIDEO_STREAM by any fh. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003109 return -EBUSY;
Michael Schimeke5bd0262007-01-18 16:17:39 -03003110 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003111 retval = videobuf_read_one(&fh->cap, data, count, ppos,
3112 file->f_flags & O_NONBLOCK);
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003113 free_btres_lock(fh->btv, fh, RESOURCE_VIDEO_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003114 break;
3115 case V4L2_BUF_TYPE_VBI_CAPTURE:
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003116 if (!check_alloc_btres_lock(fh->btv,fh,RESOURCE_VBI))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003117 return -EBUSY;
3118 retval = videobuf_read_stream(&fh->vbi, data, count, ppos, 1,
3119 file->f_flags & O_NONBLOCK);
3120 break;
3121 default:
3122 BUG();
3123 }
3124 return retval;
3125}
3126
3127static unsigned int bttv_poll(struct file *file, poll_table *wait)
3128{
3129 struct bttv_fh *fh = file->private_data;
3130 struct bttv_buffer *buf;
3131 enum v4l2_field field;
Figo.zhang9fd64182009-06-16 13:31:29 -03003132 unsigned int rc = POLLERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003133
3134 if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003135 if (!check_alloc_btres_lock(fh->btv,fh,RESOURCE_VBI))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003136 return POLLERR;
3137 return videobuf_poll_stream(file, &fh->vbi, wait);
3138 }
3139
Michael Schimeke5bd0262007-01-18 16:17:39 -03003140 if (check_btres(fh,RESOURCE_VIDEO_STREAM)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003141 /* streaming capture */
3142 if (list_empty(&fh->cap.stream))
Figo.zhang9fd64182009-06-16 13:31:29 -03003143 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003144 buf = list_entry(fh->cap.stream.next,struct bttv_buffer,vb.stream);
3145 } else {
3146 /* read() capture */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003147 if (NULL == fh->cap.read_buf) {
3148 /* need to capture a new frame */
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03003149 if (locked_btres(fh->btv,RESOURCE_VIDEO_STREAM))
3150 goto err;
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03003151 fh->cap.read_buf = videobuf_sg_alloc(fh->cap.msize);
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03003152 if (NULL == fh->cap.read_buf)
3153 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003154 fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR;
3155 field = videobuf_next_field(&fh->cap);
3156 if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,field)) {
Nickolay V. Shmyrev50ab5ed2005-12-01 00:51:32 -08003157 kfree (fh->cap.read_buf);
3158 fh->cap.read_buf = NULL;
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03003159 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003160 }
3161 fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf);
3162 fh->cap.read_off = 0;
3163 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003164 buf = (struct bttv_buffer*)fh->cap.read_buf;
3165 }
3166
3167 poll_wait(file, &buf->vb.done, wait);
Brandon Philips0fc06862007-11-06 20:02:36 -03003168 if (buf->vb.state == VIDEOBUF_DONE ||
3169 buf->vb.state == VIDEOBUF_ERROR)
Figo.zhang9fd64182009-06-16 13:31:29 -03003170 rc = POLLIN|POLLRDNORM;
3171 else
3172 rc = 0;
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03003173err:
Figo.zhang9fd64182009-06-16 13:31:29 -03003174 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003175}
3176
Hans Verkuilbec43662008-12-30 06:58:20 -03003177static int bttv_open(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003178{
Laurent Pinchart50462eb2009-12-10 11:47:13 -02003179 struct video_device *vdev = video_devdata(file);
Trent Piepho4b10d3b2009-01-28 21:32:59 -03003180 struct bttv *btv = video_drvdata(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003181 struct bttv_fh *fh;
3182 enum v4l2_buf_type type = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003183
Joe Perches8af443e2011-08-21 19:56:48 -03003184 dprintk("open dev=%s\n", video_device_node_name(vdev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003185
Laurent Pinchart327ae592009-11-27 13:57:55 -03003186 if (vdev->vfl_type == VFL_TYPE_GRABBER) {
Trent Piepho4b10d3b2009-01-28 21:32:59 -03003187 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Laurent Pinchart327ae592009-11-27 13:57:55 -03003188 } else if (vdev->vfl_type == VFL_TYPE_VBI) {
Trent Piepho4b10d3b2009-01-28 21:32:59 -03003189 type = V4L2_BUF_TYPE_VBI_CAPTURE;
3190 } else {
3191 WARN_ON(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003192 return -ENODEV;
Hans Verkuild56dc612008-07-30 08:43:36 -03003193 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003194
Joe Perches8af443e2011-08-21 19:56:48 -03003195 dprintk("%d: open called (type=%s)\n",
3196 btv->c.nr, v4l2_type_names[type]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197
3198 /* allocate per filehandle data */
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003199 fh = kmalloc(sizeof(*fh), GFP_KERNEL);
3200 if (unlikely(!fh))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003201 return -ENOMEM;
3202 file->private_data = fh;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003203
Linus Torvalds1da177e2005-04-16 15:20:36 -07003204 *fh = btv->init;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003205
Linus Torvalds1da177e2005-04-16 15:20:36 -07003206 fh->type = type;
3207 fh->ov.setup_ok = 0;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003208
Hans Verkuilffb48772010-05-01 08:03:24 -03003209 v4l2_prio_open(&btv->prio, &fh->prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003210
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03003211 videobuf_queue_sg_init(&fh->cap, &bttv_video_qops,
3212 &btv->c.pci->dev, &btv->s_lock,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003213 V4L2_BUF_TYPE_VIDEO_CAPTURE,
3214 V4L2_FIELD_INTERLACED,
3215 sizeof(struct bttv_buffer),
Mauro Carvalho Chehab587f0d52010-12-15 18:45:42 -03003216 fh, &btv->lock);
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03003217 videobuf_queue_sg_init(&fh->vbi, &bttv_vbi_qops,
3218 &btv->c.pci->dev, &btv->s_lock,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003219 V4L2_BUF_TYPE_VBI_CAPTURE,
3220 V4L2_FIELD_SEQ_TB,
3221 sizeof(struct bttv_buffer),
Mauro Carvalho Chehab587f0d52010-12-15 18:45:42 -03003222 fh, &btv->lock);
Nickolay V. Shmyrev302f61a2007-10-26 10:53:21 -03003223 set_tvnorm(btv,btv->tvnorm);
Mauro Carvalho Chehabb46a9c82008-08-05 10:12:35 -03003224 set_input(btv, btv->input, btv->tvnorm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003225
3226 btv->users++;
Michael Schimeke5bd0262007-01-18 16:17:39 -03003227
3228 /* The V4L2 spec requires one global set of cropping parameters
3229 which only change on request. These are stored in btv->crop[1].
3230 However for compatibility with V4L apps and cropping unaware
3231 V4L2 apps we now reset the cropping parameters as seen through
3232 this fh, which is to say VIDIOC_G_CROP and scaling limit checks
3233 will use btv->crop[0], the default cropping parameters for the
3234 current video standard, and VIDIOC_S_FMT will not implicitely
3235 change the cropping parameters until VIDIOC_S_CROP has been
3236 called. */
3237 fh->do_crop = !reset_crop; /* module parameter */
3238
3239 /* Likewise there should be one global set of VBI capture
3240 parameters, but for compatibility with V4L apps and earlier
3241 driver versions each fh has its own parameters. */
3242 bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm);
3243
Linus Torvalds1da177e2005-04-16 15:20:36 -07003244 bttv_field_count(btv);
3245 return 0;
3246}
3247
Hans Verkuilbec43662008-12-30 06:58:20 -03003248static int bttv_release(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003249{
3250 struct bttv_fh *fh = file->private_data;
3251 struct bttv *btv = fh->btv;
3252
3253 /* turn off overlay */
3254 if (check_btres(fh, RESOURCE_OVERLAY))
3255 bttv_switch_overlay(btv,fh,NULL);
3256
3257 /* stop video capture */
Michael Schimeke5bd0262007-01-18 16:17:39 -03003258 if (check_btres(fh, RESOURCE_VIDEO_STREAM)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003259 videobuf_streamoff(&fh->cap);
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003260 free_btres_lock(btv,fh,RESOURCE_VIDEO_STREAM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003261 }
3262 if (fh->cap.read_buf) {
3263 buffer_release(&fh->cap,fh->cap.read_buf);
3264 kfree(fh->cap.read_buf);
3265 }
Michael Schimeke5bd0262007-01-18 16:17:39 -03003266 if (check_btres(fh, RESOURCE_VIDEO_READ)) {
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003267 free_btres_lock(btv, fh, RESOURCE_VIDEO_READ);
Michael Schimeke5bd0262007-01-18 16:17:39 -03003268 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003269
3270 /* stop vbi capture */
3271 if (check_btres(fh, RESOURCE_VBI)) {
Brandon Philips053fcb62007-11-13 20:11:26 -03003272 videobuf_stop(&fh->vbi);
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003273 free_btres_lock(btv,fh,RESOURCE_VBI);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003274 }
3275
3276 /* free stuff */
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003277
Linus Torvalds1da177e2005-04-16 15:20:36 -07003278 videobuf_mmap_free(&fh->cap);
3279 videobuf_mmap_free(&fh->vbi);
Hans Verkuilffb48772010-05-01 08:03:24 -03003280 v4l2_prio_close(&btv->prio, fh->prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003281 file->private_data = NULL;
3282 kfree(fh);
3283
3284 btv->users--;
3285 bttv_field_count(btv);
Mauro Carvalho Chehabb46a9c82008-08-05 10:12:35 -03003286
3287 if (!btv->users)
3288 audio_mute(btv, 1);
3289
Linus Torvalds1da177e2005-04-16 15:20:36 -07003290 return 0;
3291}
3292
3293static int
3294bttv_mmap(struct file *file, struct vm_area_struct *vma)
3295{
3296 struct bttv_fh *fh = file->private_data;
3297
Joe Perches8af443e2011-08-21 19:56:48 -03003298 dprintk("%d: mmap type=%s 0x%lx+%ld\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003299 fh->btv->c.nr, v4l2_type_names[fh->type],
3300 vma->vm_start, vma->vm_end - vma->vm_start);
3301 return videobuf_mmap_mapper(bttv_queue(fh),vma);
3302}
3303
Hans Verkuilbec43662008-12-30 06:58:20 -03003304static const struct v4l2_file_operations bttv_fops =
Linus Torvalds1da177e2005-04-16 15:20:36 -07003305{
Mauro Carvalho Chehab8979e9d2010-09-15 08:22:09 -03003306 .owner = THIS_MODULE,
3307 .open = bttv_open,
3308 .release = bttv_release,
3309 .unlocked_ioctl = video_ioctl2,
3310 .read = bttv_read,
3311 .mmap = bttv_mmap,
3312 .poll = bttv_poll,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003313};
3314
Hans Verkuila3998102008-07-21 02:57:38 -03003315static const struct v4l2_ioctl_ops bttv_ioctl_ops = {
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003316 .vidioc_querycap = bttv_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03003317 .vidioc_enum_fmt_vid_cap = bttv_enum_fmt_vid_cap,
3318 .vidioc_g_fmt_vid_cap = bttv_g_fmt_vid_cap,
3319 .vidioc_try_fmt_vid_cap = bttv_try_fmt_vid_cap,
3320 .vidioc_s_fmt_vid_cap = bttv_s_fmt_vid_cap,
3321 .vidioc_enum_fmt_vid_overlay = bttv_enum_fmt_vid_overlay,
3322 .vidioc_g_fmt_vid_overlay = bttv_g_fmt_vid_overlay,
3323 .vidioc_try_fmt_vid_overlay = bttv_try_fmt_vid_overlay,
3324 .vidioc_s_fmt_vid_overlay = bttv_s_fmt_vid_overlay,
Hans Verkuil78b526a2008-05-28 12:16:41 -03003325 .vidioc_g_fmt_vbi_cap = bttv_g_fmt_vbi_cap,
3326 .vidioc_try_fmt_vbi_cap = bttv_try_fmt_vbi_cap,
3327 .vidioc_s_fmt_vbi_cap = bttv_s_fmt_vbi_cap,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003328 .vidioc_g_audio = bttv_g_audio,
3329 .vidioc_s_audio = bttv_s_audio,
3330 .vidioc_cropcap = bttv_cropcap,
3331 .vidioc_reqbufs = bttv_reqbufs,
3332 .vidioc_querybuf = bttv_querybuf,
3333 .vidioc_qbuf = bttv_qbuf,
3334 .vidioc_dqbuf = bttv_dqbuf,
3335 .vidioc_s_std = bttv_s_std,
3336 .vidioc_enum_input = bttv_enum_input,
3337 .vidioc_g_input = bttv_g_input,
3338 .vidioc_s_input = bttv_s_input,
3339 .vidioc_queryctrl = bttv_queryctrl,
3340 .vidioc_g_ctrl = bttv_g_ctrl,
3341 .vidioc_s_ctrl = bttv_s_ctrl,
3342 .vidioc_streamon = bttv_streamon,
3343 .vidioc_streamoff = bttv_streamoff,
3344 .vidioc_g_tuner = bttv_g_tuner,
3345 .vidioc_s_tuner = bttv_s_tuner,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003346 .vidioc_g_crop = bttv_g_crop,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003347 .vidioc_s_crop = bttv_s_crop,
3348 .vidioc_g_fbuf = bttv_g_fbuf,
3349 .vidioc_s_fbuf = bttv_s_fbuf,
3350 .vidioc_overlay = bttv_overlay,
3351 .vidioc_g_priority = bttv_g_priority,
3352 .vidioc_s_priority = bttv_s_priority,
3353 .vidioc_g_parm = bttv_g_parm,
3354 .vidioc_g_frequency = bttv_g_frequency,
3355 .vidioc_s_frequency = bttv_s_frequency,
3356 .vidioc_log_status = bttv_log_status,
3357 .vidioc_querystd = bttv_querystd,
Zoltan Devai43846832008-01-14 13:24:38 -03003358#ifdef CONFIG_VIDEO_ADV_DEBUG
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003359 .vidioc_g_register = bttv_g_register,
3360 .vidioc_s_register = bttv_s_register,
Zoltan Devai43846832008-01-14 13:24:38 -03003361#endif
Hans Verkuila3998102008-07-21 02:57:38 -03003362};
3363
3364static struct video_device bttv_video_template = {
3365 .fops = &bttv_fops,
Hans Verkuila3998102008-07-21 02:57:38 -03003366 .ioctl_ops = &bttv_ioctl_ops,
3367 .tvnorms = BTTV_NORMS,
3368 .current_norm = V4L2_STD_PAL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003369};
3370
Linus Torvalds1da177e2005-04-16 15:20:36 -07003371/* ----------------------------------------------------------------------- */
3372/* radio interface */
3373
Hans Verkuilbec43662008-12-30 06:58:20 -03003374static int radio_open(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003375{
Laurent Pinchart50462eb2009-12-10 11:47:13 -02003376 struct video_device *vdev = video_devdata(file);
Trent Piepho4b10d3b2009-01-28 21:32:59 -03003377 struct bttv *btv = video_drvdata(file);
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003378 struct bttv_fh *fh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003379
Joe Perches8af443e2011-08-21 19:56:48 -03003380 dprintk("open dev=%s\n", video_device_node_name(vdev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003381
Joe Perches8af443e2011-08-21 19:56:48 -03003382 dprintk("%d: open called (radio)\n", btv->c.nr);
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003383
3384 /* allocate per filehandle data */
3385 fh = kmalloc(sizeof(*fh), GFP_KERNEL);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003386 if (unlikely(!fh))
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003387 return -ENOMEM;
3388 file->private_data = fh;
3389 *fh = btv->init;
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003390
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003391 v4l2_prio_open(&btv->prio, &fh->prio);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003392
Linus Torvalds1da177e2005-04-16 15:20:36 -07003393 btv->radio_user++;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003394
Hans Verkuil859f0272009-03-28 08:29:00 -03003395 bttv_call_all(btv, tuner, s_radio);
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03003396 audio_input(btv,TVAUDIO_INPUT_RADIO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003397
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003398 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003399}
3400
Hans Verkuilbec43662008-12-30 06:58:20 -03003401static int radio_release(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003402{
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003403 struct bttv_fh *fh = file->private_data;
3404 struct bttv *btv = fh->btv;
Hans Verkuilb9218f22010-12-27 12:22:46 -03003405 struct saa6588_command cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003406
Hans Verkuilffb48772010-05-01 08:03:24 -03003407 v4l2_prio_close(&btv->prio, fh->prio);
Robert Fitzsimonsb9bc07a2008-04-10 09:40:31 -03003408 file->private_data = NULL;
3409 kfree(fh);
3410
Linus Torvalds1da177e2005-04-16 15:20:36 -07003411 btv->radio_user--;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003412
Hans Verkuilb9218f22010-12-27 12:22:46 -03003413 bttv_call_all(btv, core, ioctl, SAA6588_CMD_CLOSE, &cmd);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003414
Linus Torvalds1da177e2005-04-16 15:20:36 -07003415 return 0;
3416}
3417
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003418static int radio_querycap(struct file *file, void *priv,
3419 struct v4l2_capability *cap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003420{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003421 struct bttv_fh *fh = priv;
3422 struct bttv *btv = fh->btv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003423
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003424 strcpy(cap->driver, "bttv");
3425 strlcpy(cap->card, btv->radio_dev->name, sizeof(cap->card));
3426 sprintf(cap->bus_info, "PCI:%s", pci_name(btv->c.pci));
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003427 cap->capabilities = V4L2_CAP_TUNER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003428
Linus Torvalds1da177e2005-04-16 15:20:36 -07003429 return 0;
3430}
3431
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003432static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003433{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003434 struct bttv_fh *fh = priv;
3435 struct bttv *btv = fh->btv;
3436
Trent Piephoabb03622009-01-28 21:32:59 -03003437 if (btv->tuner_type == TUNER_ABSENT)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003438 return -EINVAL;
3439 if (0 != t->index)
3440 return -EINVAL;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003441 strcpy(t->name, "Radio");
3442 t->type = V4L2_TUNER_RADIO;
3443
Hans Verkuil859f0272009-03-28 08:29:00 -03003444 bttv_call_all(btv, tuner, g_tuner, t);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003445
3446 if (btv->audio_mode_gpio)
3447 btv->audio_mode_gpio(btv, t, 0);
3448
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003449 return 0;
3450}
3451
3452static int radio_enum_input(struct file *file, void *priv,
3453 struct v4l2_input *i)
3454{
3455 if (i->index != 0)
3456 return -EINVAL;
3457
3458 strcpy(i->name, "Radio");
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03003459 i->type = V4L2_INPUT_TYPE_TUNER;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003460
3461 return 0;
3462}
3463
3464static int radio_g_audio(struct file *file, void *priv,
3465 struct v4l2_audio *a)
3466{
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03003467 if (unlikely(a->index))
Cyrill Gorcunov1a002eb2008-04-01 17:49:13 -03003468 return -EINVAL;
3469
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003470 strcpy(a->name, "Radio");
Cyrill Gorcunov1a002eb2008-04-01 17:49:13 -03003471
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003472 return 0;
3473}
3474
3475static int radio_s_tuner(struct file *file, void *priv,
3476 struct v4l2_tuner *t)
3477{
3478 struct bttv_fh *fh = priv;
3479 struct bttv *btv = fh->btv;
3480
3481 if (0 != t->index)
3482 return -EINVAL;
3483
Hans Verkuila024c1a2011-06-12 07:02:43 -03003484 bttv_call_all(btv, tuner, s_tuner, t);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003485 return 0;
3486}
3487
3488static int radio_s_audio(struct file *file, void *priv,
3489 struct v4l2_audio *a)
3490{
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03003491 if (unlikely(a->index))
3492 return -EINVAL;
3493
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003494 return 0;
3495}
3496
3497static int radio_s_input(struct file *filp, void *priv, unsigned int i)
3498{
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03003499 if (unlikely(i))
3500 return -EINVAL;
3501
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003502 return 0;
3503}
3504
3505static int radio_s_std(struct file *file, void *fh, v4l2_std_id *norm)
3506{
3507 return 0;
3508}
3509
3510static int radio_queryctrl(struct file *file, void *priv,
3511 struct v4l2_queryctrl *c)
3512{
3513 const struct v4l2_queryctrl *ctrl;
3514
3515 if (c->id < V4L2_CID_BASE ||
3516 c->id >= V4L2_CID_LASTP1)
3517 return -EINVAL;
3518
3519 if (c->id == V4L2_CID_AUDIO_MUTE) {
3520 ctrl = ctrl_by_id(c->id);
3521 *c = *ctrl;
3522 } else
3523 *c = no_ctl;
3524
3525 return 0;
3526}
3527
3528static int radio_g_input(struct file *filp, void *priv, unsigned int *i)
3529{
3530 *i = 0;
3531 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003532}
3533
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003534static ssize_t radio_read(struct file *file, char __user *data,
3535 size_t count, loff_t *ppos)
3536{
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003537 struct bttv_fh *fh = file->private_data;
3538 struct bttv *btv = fh->btv;
Hans Verkuilb9218f22010-12-27 12:22:46 -03003539 struct saa6588_command cmd;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003540 cmd.block_count = count/3;
3541 cmd.buffer = data;
3542 cmd.instance = file;
3543 cmd.result = -ENODEV;
3544
Hans Verkuilb9218f22010-12-27 12:22:46 -03003545 bttv_call_all(btv, core, ioctl, SAA6588_CMD_READ, &cmd);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003546
3547 return cmd.result;
3548}
3549
3550static unsigned int radio_poll(struct file *file, poll_table *wait)
3551{
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003552 struct bttv_fh *fh = file->private_data;
3553 struct bttv *btv = fh->btv;
Hans Verkuilb9218f22010-12-27 12:22:46 -03003554 struct saa6588_command cmd;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003555 cmd.instance = file;
3556 cmd.event_list = wait;
3557 cmd.result = -ENODEV;
Hans Verkuilb9218f22010-12-27 12:22:46 -03003558 bttv_call_all(btv, core, ioctl, SAA6588_CMD_POLL, &cmd);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003559
3560 return cmd.result;
3561}
3562
Hans Verkuilbec43662008-12-30 06:58:20 -03003563static const struct v4l2_file_operations radio_fops =
Linus Torvalds1da177e2005-04-16 15:20:36 -07003564{
3565 .owner = THIS_MODULE,
3566 .open = radio_open,
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003567 .read = radio_read,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003568 .release = radio_release,
Mauro Carvalho Chehab587f0d52010-12-15 18:45:42 -03003569 .unlocked_ioctl = video_ioctl2,
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003570 .poll = radio_poll,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003571};
3572
Hans Verkuila3998102008-07-21 02:57:38 -03003573static const struct v4l2_ioctl_ops radio_ioctl_ops = {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003574 .vidioc_querycap = radio_querycap,
3575 .vidioc_g_tuner = radio_g_tuner,
3576 .vidioc_enum_input = radio_enum_input,
3577 .vidioc_g_audio = radio_g_audio,
3578 .vidioc_s_tuner = radio_s_tuner,
3579 .vidioc_s_audio = radio_s_audio,
3580 .vidioc_s_input = radio_s_input,
3581 .vidioc_s_std = radio_s_std,
3582 .vidioc_queryctrl = radio_queryctrl,
3583 .vidioc_g_input = radio_g_input,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003584 .vidioc_g_ctrl = bttv_g_ctrl,
3585 .vidioc_s_ctrl = bttv_s_ctrl,
3586 .vidioc_g_frequency = bttv_g_frequency,
3587 .vidioc_s_frequency = bttv_s_frequency,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003588};
3589
Hans Verkuila3998102008-07-21 02:57:38 -03003590static struct video_device radio_template = {
3591 .fops = &radio_fops,
Hans Verkuila3998102008-07-21 02:57:38 -03003592 .ioctl_ops = &radio_ioctl_ops,
3593};
3594
Linus Torvalds1da177e2005-04-16 15:20:36 -07003595/* ----------------------------------------------------------------------- */
3596/* some debug code */
3597
Adrian Bunk408b6642005-05-01 08:59:29 -07003598static int bttv_risc_decode(u32 risc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003599{
3600 static char *instr[16] = {
3601 [ BT848_RISC_WRITE >> 28 ] = "write",
3602 [ BT848_RISC_SKIP >> 28 ] = "skip",
3603 [ BT848_RISC_WRITEC >> 28 ] = "writec",
3604 [ BT848_RISC_JUMP >> 28 ] = "jump",
3605 [ BT848_RISC_SYNC >> 28 ] = "sync",
3606 [ BT848_RISC_WRITE123 >> 28 ] = "write123",
3607 [ BT848_RISC_SKIP123 >> 28 ] = "skip123",
3608 [ BT848_RISC_WRITE1S23 >> 28 ] = "write1s23",
3609 };
3610 static int incr[16] = {
3611 [ BT848_RISC_WRITE >> 28 ] = 2,
3612 [ BT848_RISC_JUMP >> 28 ] = 2,
3613 [ BT848_RISC_SYNC >> 28 ] = 2,
3614 [ BT848_RISC_WRITE123 >> 28 ] = 5,
3615 [ BT848_RISC_SKIP123 >> 28 ] = 2,
3616 [ BT848_RISC_WRITE1S23 >> 28 ] = 3,
3617 };
3618 static char *bits[] = {
3619 "be0", "be1", "be2", "be3/resync",
3620 "set0", "set1", "set2", "set3",
3621 "clr0", "clr1", "clr2", "clr3",
3622 "irq", "res", "eol", "sol",
3623 };
3624 int i;
3625
Joe Perches8af443e2011-08-21 19:56:48 -03003626 pr_cont("0x%08x [ %s", risc,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003627 instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
3628 for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
3629 if (risc & (1 << (i + 12)))
Joe Perches8af443e2011-08-21 19:56:48 -03003630 pr_cont(" %s", bits[i]);
3631 pr_cont(" count=%d ]\n", risc & 0xfff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003632 return incr[risc >> 28] ? incr[risc >> 28] : 1;
3633}
3634
Adrian Bunk408b6642005-05-01 08:59:29 -07003635static void bttv_risc_disasm(struct bttv *btv,
3636 struct btcx_riscmem *risc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003637{
3638 unsigned int i,j,n;
3639
Joe Perches8af443e2011-08-21 19:56:48 -03003640 pr_info("%s: risc disasm: %p [dma=0x%08lx]\n",
3641 btv->c.v4l2_dev.name, risc->cpu, (unsigned long)risc->dma);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003642 for (i = 0; i < (risc->size >> 2); i += n) {
Joe Perches8af443e2011-08-21 19:56:48 -03003643 pr_info("%s: 0x%lx: ",
3644 btv->c.v4l2_dev.name,
3645 (unsigned long)(risc->dma + (i<<2)));
Al Viro3aa71102008-06-22 14:20:09 -03003646 n = bttv_risc_decode(le32_to_cpu(risc->cpu[i]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003647 for (j = 1; j < n; j++)
Joe Perches8af443e2011-08-21 19:56:48 -03003648 pr_info("%s: 0x%lx: 0x%08x [ arg #%d ]\n",
3649 btv->c.v4l2_dev.name,
3650 (unsigned long)(risc->dma + ((i+j)<<2)),
3651 risc->cpu[i+j], j);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003652 if (0 == risc->cpu[i])
3653 break;
3654 }
3655}
3656
3657static void bttv_print_riscaddr(struct bttv *btv)
3658{
Joe Perches8af443e2011-08-21 19:56:48 -03003659 pr_info(" main: %08llx\n", (unsigned long long)btv->main.dma);
3660 pr_info(" vbi : o=%08llx e=%08llx\n",
3661 btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
3662 btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0);
3663 pr_info(" cap : o=%08llx e=%08llx\n",
3664 btv->curr.top
3665 ? (unsigned long long)btv->curr.top->top.dma : 0,
3666 btv->curr.bottom
3667 ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
3668 pr_info(" scr : o=%08llx e=%08llx\n",
3669 btv->screen ? (unsigned long long)btv->screen->top.dma : 0,
3670 btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003671 bttv_risc_disasm(btv, &btv->main);
3672}
3673
3674/* ----------------------------------------------------------------------- */
3675/* irq handler */
3676
3677static char *irq_name[] = {
3678 "FMTCHG", // format change detected (525 vs. 625)
3679 "VSYNC", // vertical sync (new field)
3680 "HSYNC", // horizontal sync
3681 "OFLOW", // chroma/luma AGC overflow
3682 "HLOCK", // horizontal lock changed
3683 "VPRES", // video presence changed
3684 "6", "7",
3685 "I2CDONE", // hw irc operation finished
3686 "GPINT", // gpio port triggered irq
3687 "10",
3688 "RISCI", // risc instruction triggered irq
3689 "FBUS", // pixel data fifo dropped data (high pci bus latencies)
3690 "FTRGT", // pixel data fifo overrun
3691 "FDSR", // fifo data stream resyncronisation
3692 "PPERR", // parity error (data transfer)
3693 "RIPERR", // parity error (read risc instructions)
3694 "PABORT", // pci abort
3695 "OCERR", // risc instruction error
3696 "SCERR", // syncronisation error
3697};
3698
3699static void bttv_print_irqbits(u32 print, u32 mark)
3700{
3701 unsigned int i;
3702
Joe Perches8af443e2011-08-21 19:56:48 -03003703 pr_cont("bits:");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003704 for (i = 0; i < ARRAY_SIZE(irq_name); i++) {
3705 if (print & (1 << i))
Joe Perches8af443e2011-08-21 19:56:48 -03003706 pr_cont(" %s", irq_name[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003707 if (mark & (1 << i))
Joe Perches8af443e2011-08-21 19:56:48 -03003708 pr_cont("*");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003709 }
3710}
3711
3712static void bttv_irq_debug_low_latency(struct bttv *btv, u32 rc)
3713{
Joe Perches8af443e2011-08-21 19:56:48 -03003714 pr_warn("%d: irq: skipped frame [main=%lx,o_vbi=%lx,o_field=%lx,rc=%lx]\n",
3715 btv->c.nr,
3716 (unsigned long)btv->main.dma,
3717 (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_VBI+1]),
3718 (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_FIELD+1]),
3719 (unsigned long)rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003720
3721 if (0 == (btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC)) {
Joe Perches8af443e2011-08-21 19:56:48 -03003722 pr_notice("%d: Oh, there (temporarily?) is no input signal. "
3723 "Ok, then this is harmless, don't worry ;)\n",
3724 btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003725 return;
3726 }
Joe Perches8af443e2011-08-21 19:56:48 -03003727 pr_notice("%d: Uhm. Looks like we have unusual high IRQ latencies\n",
3728 btv->c.nr);
3729 pr_notice("%d: Lets try to catch the culpit red-handed ...\n",
3730 btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003731 dump_stack();
3732}
3733
3734static int
3735bttv_irq_next_video(struct bttv *btv, struct bttv_buffer_set *set)
3736{
3737 struct bttv_buffer *item;
3738
3739 memset(set,0,sizeof(*set));
3740
3741 /* capture request ? */
3742 if (!list_empty(&btv->capture)) {
3743 set->frame_irq = 1;
3744 item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
3745 if (V4L2_FIELD_HAS_TOP(item->vb.field))
3746 set->top = item;
3747 if (V4L2_FIELD_HAS_BOTTOM(item->vb.field))
3748 set->bottom = item;
3749
3750 /* capture request for other field ? */
3751 if (!V4L2_FIELD_HAS_BOTH(item->vb.field) &&
3752 (item->vb.queue.next != &btv->capture)) {
3753 item = list_entry(item->vb.queue.next, struct bttv_buffer, vb.queue);
Mike Isely66349b42009-09-21 12:09:08 -03003754 /* Mike Isely <isely@pobox.com> - Only check
3755 * and set up the bottom field in the logic
3756 * below. Don't ever do the top field. This
3757 * of course means that if we set up the
3758 * bottom field in the above code that we'll
3759 * actually skip a field. But that's OK.
3760 * Having processed only a single buffer this
3761 * time, then the next time around the first
3762 * available buffer should be for a top field.
3763 * That will then cause us here to set up a
3764 * top then a bottom field in the normal way.
3765 * The alternative to this understanding is
3766 * that we set up the second available buffer
3767 * as a top field, but that's out of order
3768 * since this driver always processes the top
3769 * field first - the effect will be the two
3770 * buffers being returned in the wrong order,
3771 * with the second buffer also being delayed
3772 * by one field time (owing to the fifo nature
3773 * of videobuf). Worse still, we'll be stuck
3774 * doing fields out of order now every time
3775 * until something else causes a field to be
3776 * dropped. By effectively forcing a field to
3777 * drop this way then we always get back into
3778 * sync within a single frame time. (Out of
3779 * order fields can screw up deinterlacing
3780 * algorithms.) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003781 if (!V4L2_FIELD_HAS_BOTH(item->vb.field)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003782 if (NULL == set->bottom &&
3783 V4L2_FIELD_BOTTOM == item->vb.field) {
3784 set->bottom = item;
3785 }
3786 if (NULL != set->top && NULL != set->bottom)
3787 set->top_irq = 2;
3788 }
3789 }
3790 }
3791
3792 /* screen overlay ? */
3793 if (NULL != btv->screen) {
3794 if (V4L2_FIELD_HAS_BOTH(btv->screen->vb.field)) {
3795 if (NULL == set->top && NULL == set->bottom) {
3796 set->top = btv->screen;
3797 set->bottom = btv->screen;
3798 }
3799 } else {
3800 if (V4L2_FIELD_TOP == btv->screen->vb.field &&
3801 NULL == set->top) {
3802 set->top = btv->screen;
3803 }
3804 if (V4L2_FIELD_BOTTOM == btv->screen->vb.field &&
3805 NULL == set->bottom) {
3806 set->bottom = btv->screen;
3807 }
3808 }
3809 }
3810
Joe Perches8af443e2011-08-21 19:56:48 -03003811 dprintk("%d: next set: top=%p bottom=%p [screen=%p,irq=%d,%d]\n",
3812 btv->c.nr, set->top, set->bottom,
3813 btv->screen, set->frame_irq, set->top_irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003814 return 0;
3815}
3816
3817static void
3818bttv_irq_wakeup_video(struct bttv *btv, struct bttv_buffer_set *wakeup,
3819 struct bttv_buffer_set *curr, unsigned int state)
3820{
3821 struct timeval ts;
3822
3823 do_gettimeofday(&ts);
3824
3825 if (wakeup->top == wakeup->bottom) {
3826 if (NULL != wakeup->top && curr->top != wakeup->top) {
3827 if (irq_debug > 1)
Joe Perches8af443e2011-08-21 19:56:48 -03003828 pr_debug("%d: wakeup: both=%p\n",
3829 btv->c.nr, wakeup->top);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003830 wakeup->top->vb.ts = ts;
3831 wakeup->top->vb.field_count = btv->field_count;
3832 wakeup->top->vb.state = state;
3833 wake_up(&wakeup->top->vb.done);
3834 }
3835 } else {
3836 if (NULL != wakeup->top && curr->top != wakeup->top) {
3837 if (irq_debug > 1)
Joe Perches8af443e2011-08-21 19:56:48 -03003838 pr_debug("%d: wakeup: top=%p\n",
3839 btv->c.nr, wakeup->top);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003840 wakeup->top->vb.ts = ts;
3841 wakeup->top->vb.field_count = btv->field_count;
3842 wakeup->top->vb.state = state;
3843 wake_up(&wakeup->top->vb.done);
3844 }
3845 if (NULL != wakeup->bottom && curr->bottom != wakeup->bottom) {
3846 if (irq_debug > 1)
Joe Perches8af443e2011-08-21 19:56:48 -03003847 pr_debug("%d: wakeup: bottom=%p\n",
3848 btv->c.nr, wakeup->bottom);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003849 wakeup->bottom->vb.ts = ts;
3850 wakeup->bottom->vb.field_count = btv->field_count;
3851 wakeup->bottom->vb.state = state;
3852 wake_up(&wakeup->bottom->vb.done);
3853 }
3854 }
3855}
3856
3857static void
3858bttv_irq_wakeup_vbi(struct bttv *btv, struct bttv_buffer *wakeup,
3859 unsigned int state)
3860{
3861 struct timeval ts;
3862
3863 if (NULL == wakeup)
3864 return;
3865
3866 do_gettimeofday(&ts);
3867 wakeup->vb.ts = ts;
3868 wakeup->vb.field_count = btv->field_count;
3869 wakeup->vb.state = state;
3870 wake_up(&wakeup->vb.done);
3871}
3872
3873static void bttv_irq_timeout(unsigned long data)
3874{
3875 struct bttv *btv = (struct bttv *)data;
3876 struct bttv_buffer_set old,new;
3877 struct bttv_buffer *ovbi;
3878 struct bttv_buffer *item;
3879 unsigned long flags;
3880
3881 if (bttv_verbose) {
Joe Perches8af443e2011-08-21 19:56:48 -03003882 pr_info("%d: timeout: drop=%d irq=%d/%d, risc=%08x, ",
3883 btv->c.nr, btv->framedrop, btv->irq_me, btv->irq_total,
3884 btread(BT848_RISC_COUNT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003885 bttv_print_irqbits(btread(BT848_INT_STAT),0);
Joe Perches8af443e2011-08-21 19:56:48 -03003886 pr_cont("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003887 }
3888
3889 spin_lock_irqsave(&btv->s_lock,flags);
3890
3891 /* deactivate stuff */
3892 memset(&new,0,sizeof(new));
3893 old = btv->curr;
3894 ovbi = btv->cvbi;
3895 btv->curr = new;
3896 btv->cvbi = NULL;
3897 btv->loop_irq = 0;
3898 bttv_buffer_activate_video(btv, &new);
3899 bttv_buffer_activate_vbi(btv, NULL);
3900 bttv_set_dma(btv, 0);
3901
3902 /* wake up */
Brandon Philips0fc06862007-11-06 20:02:36 -03003903 bttv_irq_wakeup_video(btv, &old, &new, VIDEOBUF_ERROR);
3904 bttv_irq_wakeup_vbi(btv, ovbi, VIDEOBUF_ERROR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003905
3906 /* cancel all outstanding capture / vbi requests */
3907 while (!list_empty(&btv->capture)) {
3908 item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
3909 list_del(&item->vb.queue);
Brandon Philips0fc06862007-11-06 20:02:36 -03003910 item->vb.state = VIDEOBUF_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003911 wake_up(&item->vb.done);
3912 }
3913 while (!list_empty(&btv->vcapture)) {
3914 item = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
3915 list_del(&item->vb.queue);
Brandon Philips0fc06862007-11-06 20:02:36 -03003916 item->vb.state = VIDEOBUF_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003917 wake_up(&item->vb.done);
3918 }
3919
3920 btv->errors++;
3921 spin_unlock_irqrestore(&btv->s_lock,flags);
3922}
3923
3924static void
3925bttv_irq_wakeup_top(struct bttv *btv)
3926{
3927 struct bttv_buffer *wakeup = btv->curr.top;
3928
3929 if (NULL == wakeup)
3930 return;
3931
3932 spin_lock(&btv->s_lock);
3933 btv->curr.top_irq = 0;
3934 btv->curr.top = NULL;
3935 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
3936
3937 do_gettimeofday(&wakeup->vb.ts);
3938 wakeup->vb.field_count = btv->field_count;
Brandon Philips0fc06862007-11-06 20:02:36 -03003939 wakeup->vb.state = VIDEOBUF_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003940 wake_up(&wakeup->vb.done);
3941 spin_unlock(&btv->s_lock);
3942}
3943
3944static inline int is_active(struct btcx_riscmem *risc, u32 rc)
3945{
3946 if (rc < risc->dma)
3947 return 0;
3948 if (rc > risc->dma + risc->size)
3949 return 0;
3950 return 1;
3951}
3952
3953static void
3954bttv_irq_switch_video(struct bttv *btv)
3955{
3956 struct bttv_buffer_set new;
3957 struct bttv_buffer_set old;
3958 dma_addr_t rc;
3959
3960 spin_lock(&btv->s_lock);
3961
3962 /* new buffer set */
3963 bttv_irq_next_video(btv, &new);
3964 rc = btread(BT848_RISC_COUNT);
3965 if ((btv->curr.top && is_active(&btv->curr.top->top, rc)) ||
3966 (btv->curr.bottom && is_active(&btv->curr.bottom->bottom, rc))) {
3967 btv->framedrop++;
3968 if (debug_latency)
3969 bttv_irq_debug_low_latency(btv, rc);
3970 spin_unlock(&btv->s_lock);
3971 return;
3972 }
3973
3974 /* switch over */
3975 old = btv->curr;
3976 btv->curr = new;
3977 btv->loop_irq &= ~1;
3978 bttv_buffer_activate_video(btv, &new);
3979 bttv_set_dma(btv, 0);
3980
3981 /* switch input */
3982 if (UNSET != btv->new_input) {
3983 video_mux(btv,btv->new_input);
3984 btv->new_input = UNSET;
3985 }
3986
3987 /* wake up finished buffers */
Brandon Philips0fc06862007-11-06 20:02:36 -03003988 bttv_irq_wakeup_video(btv, &old, &new, VIDEOBUF_DONE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003989 spin_unlock(&btv->s_lock);
3990}
3991
3992static void
3993bttv_irq_switch_vbi(struct bttv *btv)
3994{
3995 struct bttv_buffer *new = NULL;
3996 struct bttv_buffer *old;
3997 u32 rc;
3998
3999 spin_lock(&btv->s_lock);
4000
4001 if (!list_empty(&btv->vcapture))
4002 new = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
4003 old = btv->cvbi;
4004
4005 rc = btread(BT848_RISC_COUNT);
4006 if (NULL != old && (is_active(&old->top, rc) ||
4007 is_active(&old->bottom, rc))) {
4008 btv->framedrop++;
4009 if (debug_latency)
4010 bttv_irq_debug_low_latency(btv, rc);
4011 spin_unlock(&btv->s_lock);
4012 return;
4013 }
4014
4015 /* switch */
4016 btv->cvbi = new;
4017 btv->loop_irq &= ~4;
4018 bttv_buffer_activate_vbi(btv, new);
4019 bttv_set_dma(btv, 0);
4020
Brandon Philips0fc06862007-11-06 20:02:36 -03004021 bttv_irq_wakeup_vbi(btv, old, VIDEOBUF_DONE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004022 spin_unlock(&btv->s_lock);
4023}
4024
David Howells7d12e782006-10-05 14:55:46 +01004025static irqreturn_t bttv_irq(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004026{
4027 u32 stat,astat;
4028 u32 dstat;
4029 int count;
4030 struct bttv *btv;
4031 int handled = 0;
4032
4033 btv=(struct bttv *)dev_id;
Mark Weaver6c6c0b22005-11-13 16:07:52 -08004034
Linus Torvalds1da177e2005-04-16 15:20:36 -07004035 count=0;
4036 while (1) {
4037 /* get/clear interrupt status bits */
4038 stat=btread(BT848_INT_STAT);
4039 astat=stat&btread(BT848_INT_MASK);
4040 if (!astat)
4041 break;
4042 handled = 1;
4043 btwrite(stat,BT848_INT_STAT);
4044
4045 /* get device status bits */
4046 dstat=btread(BT848_DSTATUS);
4047
4048 if (irq_debug) {
Joe Perches8af443e2011-08-21 19:56:48 -03004049 pr_debug("%d: irq loop=%d fc=%d riscs=%x, riscc=%08x, ",
4050 btv->c.nr, count, btv->field_count,
4051 stat>>28, btread(BT848_RISC_COUNT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004052 bttv_print_irqbits(stat,astat);
4053 if (stat & BT848_INT_HLOCK)
Joe Perches8af443e2011-08-21 19:56:48 -03004054 pr_cont(" HLOC => %s",
4055 dstat & BT848_DSTATUS_HLOC
4056 ? "yes" : "no");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004057 if (stat & BT848_INT_VPRES)
Joe Perches8af443e2011-08-21 19:56:48 -03004058 pr_cont(" PRES => %s",
4059 dstat & BT848_DSTATUS_PRES
4060 ? "yes" : "no");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004061 if (stat & BT848_INT_FMTCHG)
Joe Perches8af443e2011-08-21 19:56:48 -03004062 pr_cont(" NUML => %s",
4063 dstat & BT848_DSTATUS_NUML
4064 ? "625" : "525");
4065 pr_cont("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004066 }
4067
4068 if (astat&BT848_INT_VSYNC)
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004069 btv->field_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004070
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02004071 if ((astat & BT848_INT_GPINT) && btv->remote) {
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02004072 bttv_input_irq(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004073 }
4074
4075 if (astat & BT848_INT_I2CDONE) {
4076 btv->i2c_done = stat;
4077 wake_up(&btv->i2c_queue);
4078 }
4079
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004080 if ((astat & BT848_INT_RISCI) && (stat & (4<<28)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004081 bttv_irq_switch_vbi(btv);
4082
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004083 if ((astat & BT848_INT_RISCI) && (stat & (2<<28)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004084 bttv_irq_wakeup_top(btv);
4085
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004086 if ((astat & BT848_INT_RISCI) && (stat & (1<<28)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087 bttv_irq_switch_video(btv);
4088
4089 if ((astat & BT848_INT_HLOCK) && btv->opt_automute)
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03004090 audio_mute(btv, btv->mute); /* trigger automute */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004091
4092 if (astat & (BT848_INT_SCERR|BT848_INT_OCERR)) {
Joe Perches8af443e2011-08-21 19:56:48 -03004093 pr_info("%d: %s%s @ %08x,",
4094 btv->c.nr,
4095 (astat & BT848_INT_SCERR) ? "SCERR" : "",
4096 (astat & BT848_INT_OCERR) ? "OCERR" : "",
4097 btread(BT848_RISC_COUNT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004098 bttv_print_irqbits(stat,astat);
Joe Perches8af443e2011-08-21 19:56:48 -03004099 pr_cont("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004100 if (bttv_debug)
4101 bttv_print_riscaddr(btv);
4102 }
4103 if (fdsr && astat & BT848_INT_FDSR) {
Joe Perches8af443e2011-08-21 19:56:48 -03004104 pr_info("%d: FDSR @ %08x\n",
4105 btv->c.nr, btread(BT848_RISC_COUNT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106 if (bttv_debug)
4107 bttv_print_riscaddr(btv);
4108 }
4109
4110 count++;
4111 if (count > 4) {
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08004112
4113 if (count > 8 || !(astat & BT848_INT_GPINT)) {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004114 btwrite(0, BT848_INT_MASK);
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08004115
Joe Perches8af443e2011-08-21 19:56:48 -03004116 pr_err("%d: IRQ lockup, cleared int mask [",
4117 btv->c.nr);
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08004118 } else {
Joe Perches8af443e2011-08-21 19:56:48 -03004119 pr_err("%d: IRQ lockup, clearing GPINT from int mask [",
4120 btv->c.nr);
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08004121
4122 btwrite(btread(BT848_INT_MASK) & (-1 ^ BT848_INT_GPINT),
4123 BT848_INT_MASK);
4124 };
4125
Linus Torvalds1da177e2005-04-16 15:20:36 -07004126 bttv_print_irqbits(stat,astat);
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08004127
Joe Perches8af443e2011-08-21 19:56:48 -03004128 pr_cont("]\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004129 }
4130 }
4131 btv->irq_total++;
4132 if (handled)
4133 btv->irq_me++;
4134 return IRQ_RETVAL(handled);
4135}
4136
4137
4138/* ----------------------------------------------------------------------- */
4139/* initialitation */
4140
4141static struct video_device *vdev_init(struct bttv *btv,
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03004142 const struct video_device *template,
Hans Verkuil0ea6bc82008-07-26 08:26:43 -03004143 const char *type_name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004144{
4145 struct video_device *vfd;
4146
4147 vfd = video_device_alloc();
4148 if (NULL == vfd)
4149 return NULL;
4150 *vfd = *template;
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004151 vfd->v4l2_dev = &btv->c.v4l2_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004152 vfd->release = video_device_release;
Mauro Carvalho Chehab1d0a4362008-06-23 12:31:29 -03004153 vfd->debug = bttv_debug;
Trent Piepho4b10d3b2009-01-28 21:32:59 -03004154 video_set_drvdata(vfd, btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004155 snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
4156 btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "",
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03004157 type_name, bttv_tvcards[btv->c.type].name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004158 return vfd;
4159}
4160
4161static void bttv_unregister_video(struct bttv *btv)
4162{
4163 if (btv->video_dev) {
Laurent Pinchartf0813b42009-11-27 13:57:30 -03004164 if (video_is_registered(btv->video_dev))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004165 video_unregister_device(btv->video_dev);
4166 else
4167 video_device_release(btv->video_dev);
4168 btv->video_dev = NULL;
4169 }
4170 if (btv->vbi_dev) {
Laurent Pinchartf0813b42009-11-27 13:57:30 -03004171 if (video_is_registered(btv->vbi_dev))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004172 video_unregister_device(btv->vbi_dev);
4173 else
4174 video_device_release(btv->vbi_dev);
4175 btv->vbi_dev = NULL;
4176 }
4177 if (btv->radio_dev) {
Laurent Pinchartf0813b42009-11-27 13:57:30 -03004178 if (video_is_registered(btv->radio_dev))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004179 video_unregister_device(btv->radio_dev);
4180 else
4181 video_device_release(btv->radio_dev);
4182 btv->radio_dev = NULL;
4183 }
4184}
4185
4186/* register video4linux devices */
4187static int __devinit bttv_register_video(struct bttv *btv)
4188{
Hans Verkuil0ea6bc82008-07-26 08:26:43 -03004189 if (no_overlay > 0)
Joe Perches8af443e2011-08-21 19:56:48 -03004190 pr_notice("Overlay support disabled\n");
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07004191
Linus Torvalds1da177e2005-04-16 15:20:36 -07004192 /* video */
Hans Verkuil0ea6bc82008-07-26 08:26:43 -03004193 btv->video_dev = vdev_init(btv, &bttv_video_template, "video");
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03004194
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004195 if (NULL == btv->video_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004196 goto err;
Jean Delvare176c2f32008-09-07 12:49:59 -03004197 if (video_register_device(btv->video_dev, VFL_TYPE_GRABBER,
4198 video_nr[btv->c.nr]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004199 goto err;
Joe Perches8af443e2011-08-21 19:56:48 -03004200 pr_info("%d: registered device %s\n",
4201 btv->c.nr, video_device_node_name(btv->video_dev));
Hans Verkuil22a04f12008-07-20 06:35:02 -03004202 if (device_create_file(&btv->video_dev->dev,
Kay Sievers54bd5b62007-10-08 16:26:13 -03004203 &dev_attr_card)<0) {
Joe Perches8af443e2011-08-21 19:56:48 -03004204 pr_err("%d: device_create_file 'card' failed\n", btv->c.nr);
Trent Piephod94fc9a2006-07-29 17:18:06 -03004205 goto err;
4206 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004207
4208 /* vbi */
Hans Verkuil0ea6bc82008-07-26 08:26:43 -03004209 btv->vbi_dev = vdev_init(btv, &bttv_video_template, "vbi");
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03004210
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004211 if (NULL == btv->vbi_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004212 goto err;
Jean Delvare176c2f32008-09-07 12:49:59 -03004213 if (video_register_device(btv->vbi_dev, VFL_TYPE_VBI,
4214 vbi_nr[btv->c.nr]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004215 goto err;
Joe Perches8af443e2011-08-21 19:56:48 -03004216 pr_info("%d: registered device %s\n",
4217 btv->c.nr, video_device_node_name(btv->vbi_dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004218
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004219 if (!btv->has_radio)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004220 return 0;
4221 /* radio */
Hans Verkuil0ea6bc82008-07-26 08:26:43 -03004222 btv->radio_dev = vdev_init(btv, &radio_template, "radio");
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004223 if (NULL == btv->radio_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004224 goto err;
Jean Delvare176c2f32008-09-07 12:49:59 -03004225 if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,
4226 radio_nr[btv->c.nr]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004227 goto err;
Joe Perches8af443e2011-08-21 19:56:48 -03004228 pr_info("%d: registered device %s\n",
4229 btv->c.nr, video_device_node_name(btv->radio_dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004230
4231 /* all done */
4232 return 0;
4233
4234 err:
4235 bttv_unregister_video(btv);
4236 return -1;
4237}
4238
4239
4240/* on OpenFirmware machines (PowerMac at least), PCI memory cycle */
4241/* response on cards with no firmware is not enabled by OF */
4242static void pci_set_command(struct pci_dev *dev)
4243{
4244#if defined(__powerpc__)
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004245 unsigned int cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004246
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004247 pci_read_config_dword(dev, PCI_COMMAND, &cmd);
4248 cmd = (cmd | PCI_COMMAND_MEMORY );
4249 pci_write_config_dword(dev, PCI_COMMAND, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004250#endif
4251}
4252
4253static int __devinit bttv_probe(struct pci_dev *dev,
4254 const struct pci_device_id *pci_id)
4255{
4256 int result;
4257 unsigned char lat;
4258 struct bttv *btv;
4259
4260 if (bttv_num == BTTV_MAX)
4261 return -ENOMEM;
Joe Perches8af443e2011-08-21 19:56:48 -03004262 pr_info("Bt8xx card found (%d)\n", bttv_num);
Trent Piepho4b10d3b2009-01-28 21:32:59 -03004263 bttvs[bttv_num] = btv = kzalloc(sizeof(*btv), GFP_KERNEL);
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004264 if (btv == NULL) {
Joe Perches8af443e2011-08-21 19:56:48 -03004265 pr_err("out of memory\n");
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004266 return -ENOMEM;
4267 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004268 btv->c.nr = bttv_num;
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004269 snprintf(btv->c.v4l2_dev.name, sizeof(btv->c.v4l2_dev.name),
4270 "bttv%d", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004271
4272 /* initialize structs / fill in defaults */
Ingo Molnarbd5f0ac2006-01-13 14:10:24 -02004273 mutex_init(&btv->lock);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004274 spin_lock_init(&btv->s_lock);
4275 spin_lock_init(&btv->gpio_lock);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004276 init_waitqueue_head(&btv->i2c_queue);
4277 INIT_LIST_HEAD(&btv->c.subs);
4278 INIT_LIST_HEAD(&btv->capture);
4279 INIT_LIST_HEAD(&btv->vcapture);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004280 v4l2_prio_init(&btv->prio);
4281
4282 init_timer(&btv->timeout);
4283 btv->timeout.function = bttv_irq_timeout;
4284 btv->timeout.data = (unsigned long)btv;
4285
Michael Krufky7c08fb02005-11-08 21:36:21 -08004286 btv->i2c_rc = -1;
4287 btv->tuner_type = UNSET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004288 btv->new_input = UNSET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004289 btv->has_radio=radio[btv->c.nr];
4290
4291 /* pci stuff (init, get irq/mmio, ... */
4292 btv->c.pci = dev;
Michael Krufky7c08fb02005-11-08 21:36:21 -08004293 btv->id = dev->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004294 if (pci_enable_device(dev)) {
Joe Perches8af443e2011-08-21 19:56:48 -03004295 pr_warn("%d: Can't enable device\n", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004296 return -EIO;
4297 }
Yang Hongyang284901a2009-04-06 19:01:15 -07004298 if (pci_set_dma_mask(dev, DMA_BIT_MASK(32))) {
Joe Perches8af443e2011-08-21 19:56:48 -03004299 pr_warn("%d: No suitable DMA available\n", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004300 return -EIO;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004301 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004302 if (!request_mem_region(pci_resource_start(dev,0),
4303 pci_resource_len(dev,0),
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004304 btv->c.v4l2_dev.name)) {
Joe Perches8af443e2011-08-21 19:56:48 -03004305 pr_warn("%d: can't request iomem (0x%llx)\n",
4306 btv->c.nr,
4307 (unsigned long long)pci_resource_start(dev, 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004308 return -EBUSY;
4309 }
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004310 pci_set_master(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004311 pci_set_command(dev);
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004312
4313 result = v4l2_device_register(&dev->dev, &btv->c.v4l2_dev);
4314 if (result < 0) {
Joe Perches8af443e2011-08-21 19:56:48 -03004315 pr_warn("%d: v4l2_device_register() failed\n", btv->c.nr);
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004316 goto fail0;
4317 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004318
Bjørn Morkabd34d82011-03-21 11:35:56 -03004319 btv->revision = dev->revision;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004320 pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
Joe Perches8af443e2011-08-21 19:56:48 -03004321 pr_info("%d: Bt%d (rev %d) at %s, irq: %d, latency: %d, mmio: 0x%llx\n",
4322 bttv_num, btv->id, btv->revision, pci_name(dev),
4323 btv->c.pci->irq, lat,
4324 (unsigned long long)pci_resource_start(dev, 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004325 schedule();
4326
Akinobu Mita5f1693f2006-12-20 10:08:56 -03004327 btv->bt848_mmio = ioremap(pci_resource_start(dev, 0), 0x1000);
4328 if (NULL == btv->bt848_mmio) {
Joe Perches8af443e2011-08-21 19:56:48 -03004329 pr_err("%d: ioremap() failed\n", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004330 result = -EIO;
4331 goto fail1;
4332 }
4333
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004334 /* identify card */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004335 bttv_idcard(btv);
4336
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004337 /* disable irqs, register irq handler */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004338 btwrite(0, BT848_INT_MASK);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004339 result = request_irq(btv->c.pci->irq, bttv_irq,
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004340 IRQF_SHARED | IRQF_DISABLED, btv->c.v4l2_dev.name, (void *)btv);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004341 if (result < 0) {
Joe Perches8af443e2011-08-21 19:56:48 -03004342 pr_err("%d: can't get IRQ %d\n",
4343 bttv_num, btv->c.pci->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004344 goto fail1;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004345 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004346
4347 if (0 != bttv_handle_chipset(btv)) {
4348 result = -EIO;
4349 goto fail2;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004350 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004351
4352 /* init options from insmod args */
4353 btv->opt_combfilter = combfilter;
4354 btv->opt_lumafilter = lumafilter;
4355 btv->opt_automute = automute;
4356 btv->opt_chroma_agc = chroma_agc;
4357 btv->opt_adc_crush = adc_crush;
4358 btv->opt_vcr_hack = vcr_hack;
4359 btv->opt_whitecrush_upper = whitecrush_upper;
4360 btv->opt_whitecrush_lower = whitecrush_lower;
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -07004361 btv->opt_uv_ratio = uv_ratio;
4362 btv->opt_full_luma_range = full_luma_range;
4363 btv->opt_coring = coring;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004364
4365 /* fill struct bttv with some useful defaults */
4366 btv->init.btv = btv;
4367 btv->init.ov.w.width = 320;
4368 btv->init.ov.w.height = 240;
Mauro Carvalho Chehabc96dd072007-10-26 16:51:47 -03004369 btv->init.fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004370 btv->init.width = 320;
4371 btv->init.height = 240;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004372 btv->input = 0;
4373
4374 /* initialize hardware */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004375 if (bttv_gpio)
4376 bttv_gpio_tracking(btv,"pre-init");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004377
4378 bttv_risc_init_main(btv);
4379 init_bt848(btv);
4380
4381 /* gpio */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004382 btwrite(0x00, BT848_GPIO_REG_INP);
4383 btwrite(0x00, BT848_GPIO_OUT_EN);
4384 if (bttv_verbose)
4385 bttv_gpio_tracking(btv,"init");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004386
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004387 /* needs to be done before i2c is registered */
4388 bttv_init_card1(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004389
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004390 /* register i2c + gpio */
4391 init_bttv_i2c(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004392
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004393 /* some card-specific stuff (needs working i2c) */
4394 bttv_init_card2(btv);
Hans Verkuil2c905772009-07-20 08:14:17 -03004395 bttv_init_tuner(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004396 init_irqreg(btv);
4397
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004398 /* register video4linux + input */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004399 if (!bttv_tvcards[btv->c.type].no_video) {
4400 bttv_register_video(btv);
4401 bt848_bright(btv,32768);
Alan McIvor961e6682012-04-01 21:11:08 -03004402 bt848_contrast(btv, 27648);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004403 bt848_hue(btv,32768);
4404 bt848_sat(btv,32768);
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03004405 audio_mute(btv, 1);
Trent Piepho333408f2007-07-03 15:08:10 -03004406 set_input(btv, 0, btv->tvnorm);
Michael Schimeke5bd0262007-01-18 16:17:39 -03004407 bttv_crop_reset(&btv->crop[0], btv->tvnorm);
4408 btv->crop[1] = btv->crop[0]; /* current = default */
4409 disclaim_vbi_lines(btv);
4410 disclaim_video_lines(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004411 }
4412
Jarod Wilsonf992a492007-03-24 15:23:50 -03004413 /* add subdevices and autoload dvb-bt8xx if needed */
4414 if (bttv_tvcards[btv->c.type].has_dvb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004415 bttv_sub_add_device(&btv->c, "dvb");
Jarod Wilsonf992a492007-03-24 15:23:50 -03004416 request_modules(btv);
4417 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004418
Jean Delvared90a4ae2010-02-16 14:22:37 -03004419 if (!disable_ir) {
4420 init_bttv_i2c_ir(btv);
4421 bttv_input_init(btv);
4422 }
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02004423
Linus Torvalds1da177e2005-04-16 15:20:36 -07004424 /* everything is fine */
4425 bttv_num++;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004426 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004427
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004428fail2:
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004429 free_irq(btv->c.pci->irq,btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004430
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004431fail1:
4432 v4l2_device_unregister(&btv->c.v4l2_dev);
4433
4434fail0:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004435 if (btv->bt848_mmio)
4436 iounmap(btv->bt848_mmio);
4437 release_mem_region(pci_resource_start(btv->c.pci,0),
4438 pci_resource_len(btv->c.pci,0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004439 return result;
4440}
4441
4442static void __devexit bttv_remove(struct pci_dev *pci_dev)
4443{
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004444 struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
4445 struct bttv *btv = to_bttv(v4l2_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004446
4447 if (bttv_verbose)
Joe Perches8af443e2011-08-21 19:56:48 -03004448 pr_info("%d: unloading\n", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004449
Tejun Heo707bcf32010-12-24 16:14:20 +01004450 if (bttv_tvcards[btv->c.type].has_dvb)
4451 flush_request_modules(btv);
4452
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004453 /* shutdown everything (DMA+IRQs) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004454 btand(~15, BT848_GPIO_DMA_CTL);
4455 btwrite(0, BT848_INT_MASK);
4456 btwrite(~0x0, BT848_INT_STAT);
4457 btwrite(0x0, BT848_GPIO_OUT_EN);
4458 if (bttv_gpio)
4459 bttv_gpio_tracking(btv,"cleanup");
4460
4461 /* tell gpio modules we are leaving ... */
4462 btv->shutdown=1;
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02004463 bttv_input_fini(btv);
Christopher Pascoe889aee82006-01-09 15:25:28 -02004464 bttv_sub_del_devices(&btv->c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004465
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004466 /* unregister i2c_bus + input */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004467 fini_bttv_i2c(btv);
4468
4469 /* unregister video4linux */
4470 bttv_unregister_video(btv);
4471
4472 /* free allocated memory */
4473 btcx_riscmem_free(btv->c.pci,&btv->main);
4474
4475 /* free ressources */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004476 free_irq(btv->c.pci->irq,btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004477 iounmap(btv->bt848_mmio);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004478 release_mem_region(pci_resource_start(btv->c.pci,0),
4479 pci_resource_len(btv->c.pci,0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004480
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004481 v4l2_device_unregister(&btv->c.v4l2_dev);
Trent Piepho4b10d3b2009-01-28 21:32:59 -03004482 bttvs[btv->c.nr] = NULL;
4483 kfree(btv);
4484
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004485 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004486}
4487
Alexey Dobriyan17bc98a2006-08-12 22:01:27 -03004488#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -07004489static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state)
4490{
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004491 struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
4492 struct bttv *btv = to_bttv(v4l2_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004493 struct bttv_buffer_set idle;
4494 unsigned long flags;
4495
Joe Perches8af443e2011-08-21 19:56:48 -03004496 dprintk("%d: suspend %d\n", btv->c.nr, state.event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004497
4498 /* stop dma + irqs */
4499 spin_lock_irqsave(&btv->s_lock,flags);
4500 memset(&idle, 0, sizeof(idle));
4501 btv->state.video = btv->curr;
4502 btv->state.vbi = btv->cvbi;
4503 btv->state.loop_irq = btv->loop_irq;
4504 btv->curr = idle;
4505 btv->loop_irq = 0;
4506 bttv_buffer_activate_video(btv, &idle);
4507 bttv_buffer_activate_vbi(btv, NULL);
4508 bttv_set_dma(btv, 0);
4509 btwrite(0, BT848_INT_MASK);
4510 spin_unlock_irqrestore(&btv->s_lock,flags);
4511
4512 /* save bt878 state */
4513 btv->state.gpio_enable = btread(BT848_GPIO_OUT_EN);
4514 btv->state.gpio_data = gpio_read();
4515
4516 /* save pci state */
4517 pci_save_state(pci_dev);
4518 if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
4519 pci_disable_device(pci_dev);
4520 btv->state.disabled = 1;
4521 }
4522 return 0;
4523}
4524
4525static int bttv_resume(struct pci_dev *pci_dev)
4526{
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004527 struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
4528 struct bttv *btv = to_bttv(v4l2_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004529 unsigned long flags;
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004530 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004531
Joe Perches8af443e2011-08-21 19:56:48 -03004532 dprintk("%d: resume\n", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004533
4534 /* restore pci state */
4535 if (btv->state.disabled) {
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004536 err=pci_enable_device(pci_dev);
4537 if (err) {
Joe Perches8af443e2011-08-21 19:56:48 -03004538 pr_warn("%d: Can't enable device\n", btv->c.nr);
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004539 return err;
4540 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004541 btv->state.disabled = 0;
4542 }
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004543 err=pci_set_power_state(pci_dev, PCI_D0);
4544 if (err) {
4545 pci_disable_device(pci_dev);
Joe Perches8af443e2011-08-21 19:56:48 -03004546 pr_warn("%d: Can't enable device\n", btv->c.nr);
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004547 btv->state.disabled = 1;
4548 return err;
4549 }
4550
Linus Torvalds1da177e2005-04-16 15:20:36 -07004551 pci_restore_state(pci_dev);
4552
4553 /* restore bt878 state */
4554 bttv_reinit_bt848(btv);
4555 gpio_inout(0xffffff, btv->state.gpio_enable);
4556 gpio_write(btv->state.gpio_data);
4557
4558 /* restart dma */
4559 spin_lock_irqsave(&btv->s_lock,flags);
4560 btv->curr = btv->state.video;
4561 btv->cvbi = btv->state.vbi;
4562 btv->loop_irq = btv->state.loop_irq;
4563 bttv_buffer_activate_video(btv, &btv->curr);
4564 bttv_buffer_activate_vbi(btv, btv->cvbi);
4565 bttv_set_dma(btv, 0);
4566 spin_unlock_irqrestore(&btv->s_lock,flags);
4567 return 0;
4568}
Alexey Dobriyan17bc98a2006-08-12 22:01:27 -03004569#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07004570
4571static struct pci_device_id bttv_pci_tbl[] = {
Joe Perches76e97412009-07-05 15:59:21 -03004572 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT848), 0},
4573 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT849), 0},
4574 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT878), 0},
4575 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT879), 0},
Peter De Schrijverc540d9f2011-11-06 10:47:58 -03004576 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_FUSION879), 0},
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004577 {0,}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004578};
4579
4580MODULE_DEVICE_TABLE(pci, bttv_pci_tbl);
4581
4582static struct pci_driver bttv_pci_driver = {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004583 .name = "bttv",
4584 .id_table = bttv_pci_tbl,
4585 .probe = bttv_probe,
4586 .remove = __devexit_p(bttv_remove),
Alexey Dobriyan17bc98a2006-08-12 22:01:27 -03004587#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -07004588 .suspend = bttv_suspend,
4589 .resume = bttv_resume,
Alexey Dobriyan17bc98a2006-08-12 22:01:27 -03004590#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07004591};
4592
Adrian Bunk7d44e892007-12-11 19:23:43 -03004593static int __init bttv_init_module(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004594{
Randy Dunlapc526e222006-07-15 09:08:26 -03004595 int ret;
4596
Linus Torvalds1da177e2005-04-16 15:20:36 -07004597 bttv_num = 0;
4598
Joe Perches8af443e2011-08-21 19:56:48 -03004599 pr_info("driver version %s loaded\n", BTTV_VERSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004600 if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME)
4601 gbuffers = 2;
Filipe Rossetf41b6962009-05-28 11:11:53 -03004602 if (gbufsize > BTTV_MAX_FBUF)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004603 gbufsize = BTTV_MAX_FBUF;
4604 gbufsize = (gbufsize + PAGE_SIZE - 1) & PAGE_MASK;
4605 if (bttv_verbose)
Joe Perches8af443e2011-08-21 19:56:48 -03004606 pr_info("using %d buffers with %dk (%d pages) each for capture\n",
4607 gbuffers, gbufsize >> 10, gbufsize >> PAGE_SHIFT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004608
4609 bttv_check_chipset();
4610
Randy Dunlapc526e222006-07-15 09:08:26 -03004611 ret = bus_register(&bttv_sub_bus_type);
4612 if (ret < 0) {
Joe Perches8af443e2011-08-21 19:56:48 -03004613 pr_warn("bus_register error: %d\n", ret);
Randy Dunlapc526e222006-07-15 09:08:26 -03004614 return ret;
4615 }
Akinobu Mita9e7e85e2007-12-17 14:26:29 -03004616 ret = pci_register_driver(&bttv_pci_driver);
4617 if (ret < 0)
4618 bus_unregister(&bttv_sub_bus_type);
4619
4620 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004621}
4622
Adrian Bunk7d44e892007-12-11 19:23:43 -03004623static void __exit bttv_cleanup_module(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004624{
4625 pci_unregister_driver(&bttv_pci_driver);
4626 bus_unregister(&bttv_sub_bus_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004627}
4628
4629module_init(bttv_init_module);
4630module_exit(bttv_cleanup_module);
4631
4632/*
4633 * Local variables:
4634 * c-basic-offset: 8
4635 * End:
4636 */