blob: 834a48394bce1bc4546f2754c24553a54119d862 [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
37#include <linux/init.h>
38#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070039#include <linux/delay.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090040#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <linux/errno.h>
42#include <linux/fs.h>
43#include <linux/kernel.h>
44#include <linux/sched.h>
45#include <linux/interrupt.h>
46#include <linux/kdev_t.h>
Mauro Carvalho Chehabb5b8ab82006-01-09 15:25:20 -020047#include "bttvp.h"
Michael Krufky5e453dc2006-01-09 15:32:31 -020048#include <media/v4l2-common.h>
Hans Verkuil35ea11f2008-07-20 08:12:02 -030049#include <media/v4l2-ioctl.h>
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -030050#include <media/tvaudio.h>
Hans Verkuil2474ed42006-03-19 12:35:57 -030051#include <media/msp3400.h>
Mauro Carvalho Chehabb5b8ab82006-01-09 15:25:20 -020052
Mauro Carvalho Chehabfa9846a2005-07-12 13:58:42 -070053#include <linux/dma-mapping.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070054
55#include <asm/io.h>
56#include <asm/byteorder.h>
57
Hans Verkuilb9218f22010-12-27 12:22:46 -030058#include <media/saa6588.h>
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -070059
60
Linus Torvalds1da177e2005-04-16 15:20:36 -070061unsigned int bttv_num; /* number of Bt848s in use */
Trent Piepho4b10d3b2009-01-28 21:32:59 -030062struct bttv *bttvs[BTTV_MAX];
Linus Torvalds1da177e2005-04-16 15:20:36 -070063
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020064unsigned int bttv_debug;
Linus Torvalds1da177e2005-04-16 15:20:36 -070065unsigned int bttv_verbose = 1;
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020066unsigned int bttv_gpio;
Linus Torvalds1da177e2005-04-16 15:20:36 -070067
68/* config variables */
69#ifdef __BIG_ENDIAN
70static unsigned int bigendian=1;
71#else
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020072static unsigned int bigendian;
Linus Torvalds1da177e2005-04-16 15:20:36 -070073#endif
74static unsigned int radio[BTTV_MAX];
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020075static unsigned int irq_debug;
Linus Torvalds1da177e2005-04-16 15:20:36 -070076static unsigned int gbuffers = 8;
77static unsigned int gbufsize = 0x208000;
Michael Schimeke5bd0262007-01-18 16:17:39 -030078static unsigned int reset_crop = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -070079
Jean Delvare176c2f32008-09-07 12:49:59 -030080static int video_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
81static int radio_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
82static int vbi_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020083static int debug_latency;
Jean Delvared90a4ae2010-02-16 14:22:37 -030084static int disable_ir;
Linus Torvalds1da177e2005-04-16 15:20:36 -070085
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020086static unsigned int fdsr;
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
88/* options */
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020089static unsigned int combfilter;
90static unsigned int lumafilter;
Linus Torvalds1da177e2005-04-16 15:20:36 -070091static unsigned int automute = 1;
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020092static unsigned int chroma_agc;
Linus Torvalds1da177e2005-04-16 15:20:36 -070093static unsigned int adc_crush = 1;
94static unsigned int whitecrush_upper = 0xCF;
95static unsigned int whitecrush_lower = 0x7F;
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020096static unsigned int vcr_hack;
97static unsigned int irq_iswitch;
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -070098static unsigned int uv_ratio = 50;
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020099static unsigned int full_luma_range;
100static unsigned int coring;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101
102/* API features (turn on/off stuff for testing) */
103static unsigned int v4l2 = 1;
104
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105/* insmod args */
106module_param(bttv_verbose, int, 0644);
107module_param(bttv_gpio, int, 0644);
108module_param(bttv_debug, int, 0644);
109module_param(irq_debug, int, 0644);
110module_param(debug_latency, int, 0644);
Jean Delvared90a4ae2010-02-16 14:22:37 -0300111module_param(disable_ir, int, 0444);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112
113module_param(fdsr, int, 0444);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114module_param(gbuffers, int, 0444);
115module_param(gbufsize, int, 0444);
Michael Schimeke5bd0262007-01-18 16:17:39 -0300116module_param(reset_crop, int, 0444);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117
118module_param(v4l2, int, 0644);
119module_param(bigendian, int, 0644);
120module_param(irq_iswitch, int, 0644);
121module_param(combfilter, int, 0444);
122module_param(lumafilter, int, 0444);
123module_param(automute, int, 0444);
124module_param(chroma_agc, int, 0444);
125module_param(adc_crush, int, 0444);
126module_param(whitecrush_upper, int, 0444);
127module_param(whitecrush_lower, int, 0444);
128module_param(vcr_hack, int, 0444);
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700129module_param(uv_ratio, int, 0444);
130module_param(full_luma_range, int, 0444);
131module_param(coring, int, 0444);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132
Jean Delvare176c2f32008-09-07 12:49:59 -0300133module_param_array(radio, int, NULL, 0444);
134module_param_array(video_nr, int, NULL, 0444);
135module_param_array(radio_nr, int, NULL, 0444);
136module_param_array(vbi_nr, int, NULL, 0444);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137
138MODULE_PARM_DESC(radio,"The TV card supports radio, default is 0 (no)");
139MODULE_PARM_DESC(bigendian,"byte order of the framebuffer, default is native endian");
140MODULE_PARM_DESC(bttv_verbose,"verbose startup messages, default is 1 (yes)");
141MODULE_PARM_DESC(bttv_gpio,"log gpio changes, default is 0 (no)");
142MODULE_PARM_DESC(bttv_debug,"debug messages, default is 0 (no)");
143MODULE_PARM_DESC(irq_debug,"irq handler debug messages, default is 0 (no)");
Jean Delvared90a4ae2010-02-16 14:22:37 -0300144MODULE_PARM_DESC(disable_ir, "disable infrared remote support");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145MODULE_PARM_DESC(gbuffers,"number of capture buffers. range 2-32, default 8");
146MODULE_PARM_DESC(gbufsize,"size of the capture buffers, default is 0x208000");
Michael Schimeke5bd0262007-01-18 16:17:39 -0300147MODULE_PARM_DESC(reset_crop,"reset cropping parameters at open(), default "
148 "is 1 (yes) for compatibility with older applications");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149MODULE_PARM_DESC(automute,"mute audio on bad/missing video signal, default is 1 (yes)");
150MODULE_PARM_DESC(chroma_agc,"enables the AGC of chroma signal, default is 0 (no)");
151MODULE_PARM_DESC(adc_crush,"enables the luminance ADC crush, default is 1 (yes)");
152MODULE_PARM_DESC(whitecrush_upper,"sets the white crush upper value, default is 207");
153MODULE_PARM_DESC(whitecrush_lower,"sets the white crush lower value, default is 127");
154MODULE_PARM_DESC(vcr_hack,"enables the VCR hack (improves synch on poor VCR tapes), default is 0 (no)");
155MODULE_PARM_DESC(irq_iswitch,"switch inputs in irq handler");
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700156MODULE_PARM_DESC(uv_ratio,"ratio between u and v gains, default is 50");
157MODULE_PARM_DESC(full_luma_range,"use the full luma range, default is 0 (no)");
158MODULE_PARM_DESC(coring,"set the luma coring level, default is 0 (no)");
Jean Delvare176c2f32008-09-07 12:49:59 -0300159MODULE_PARM_DESC(video_nr, "video device numbers");
160MODULE_PARM_DESC(vbi_nr, "vbi device numbers");
161MODULE_PARM_DESC(radio_nr, "radio device numbers");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162
163MODULE_DESCRIPTION("bttv - v4l/v4l2 driver module for bt848/878 based cards");
164MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr");
165MODULE_LICENSE("GPL");
166
167/* ----------------------------------------------------------------------- */
168/* sysfs */
169
Kay Sievers54bd5b62007-10-08 16:26:13 -0300170static ssize_t show_card(struct device *cd,
171 struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172{
Hans Verkuil22a04f12008-07-20 06:35:02 -0300173 struct video_device *vfd = container_of(cd, struct video_device, dev);
Hans Verkuil74fc7bd2009-03-14 12:36:54 -0300174 struct bttv *btv = video_get_drvdata(vfd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 return sprintf(buf, "%d\n", btv ? btv->c.type : UNSET);
176}
Kay Sievers54bd5b62007-10-08 16:26:13 -0300177static DEVICE_ATTR(card, S_IRUGO, show_card, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178
179/* ----------------------------------------------------------------------- */
Jarod Wilsonf992a492007-03-24 15:23:50 -0300180/* dvb auto-load setup */
181#if defined(CONFIG_MODULES) && defined(MODULE)
182static void request_module_async(struct work_struct *work)
183{
184 request_module("dvb-bt8xx");
185}
186
187static void request_modules(struct bttv *dev)
188{
189 INIT_WORK(&dev->request_module_wk, request_module_async);
190 schedule_work(&dev->request_module_wk);
191}
Tejun Heo707bcf32010-12-24 16:14:20 +0100192
193static void flush_request_modules(struct bttv *dev)
194{
195 flush_work_sync(&dev->request_module_wk);
196}
Jarod Wilsonf992a492007-03-24 15:23:50 -0300197#else
198#define request_modules(dev)
Tejun Heo707bcf32010-12-24 16:14:20 +0100199#define flush_request_modules(dev)
Jarod Wilsonf992a492007-03-24 15:23:50 -0300200#endif /* CONFIG_MODULES */
201
202
203/* ----------------------------------------------------------------------- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204/* static data */
205
206/* special timing tables from conexant... */
207static u8 SRAM_Table[][60] =
208{
209 /* PAL digital input over GPIO[7:0] */
210 {
211 45, // 45 bytes following
212 0x36,0x11,0x01,0x00,0x90,0x02,0x05,0x10,0x04,0x16,
213 0x12,0x05,0x11,0x00,0x04,0x12,0xC0,0x00,0x31,0x00,
214 0x06,0x51,0x08,0x03,0x89,0x08,0x07,0xC0,0x44,0x00,
215 0x81,0x01,0x01,0xA9,0x0D,0x02,0x02,0x50,0x03,0x37,
216 0x37,0x00,0xAF,0x21,0x00
217 },
218 /* NTSC digital input over GPIO[7:0] */
219 {
220 51, // 51 bytes following
221 0x0C,0xC0,0x00,0x00,0x90,0x02,0x03,0x10,0x03,0x06,
222 0x10,0x04,0x12,0x12,0x05,0x02,0x13,0x04,0x19,0x00,
223 0x04,0x39,0x00,0x06,0x59,0x08,0x03,0x83,0x08,0x07,
224 0x03,0x50,0x00,0xC0,0x40,0x00,0x86,0x01,0x01,0xA6,
225 0x0D,0x02,0x03,0x11,0x01,0x05,0x37,0x00,0xAC,0x21,
226 0x00,
227 },
228 // TGB_NTSC392 // quartzsight
229 // This table has been modified to be used for Fusion Rev D
230 {
231 0x2A, // size of table = 42
232 0x06, 0x08, 0x04, 0x0a, 0xc0, 0x00, 0x18, 0x08, 0x03, 0x24,
233 0x08, 0x07, 0x02, 0x90, 0x02, 0x08, 0x10, 0x04, 0x0c, 0x10,
234 0x05, 0x2c, 0x11, 0x04, 0x55, 0x48, 0x00, 0x05, 0x50, 0x00,
235 0xbf, 0x0c, 0x02, 0x2f, 0x3d, 0x00, 0x2f, 0x3f, 0x00, 0xc3,
236 0x20, 0x00
237 }
238};
239
Michael Schimeke5bd0262007-01-18 16:17:39 -0300240/* minhdelayx1 first video pixel we can capture on a line and
241 hdelayx1 start of active video, both relative to rising edge of
242 /HRESET pulse (0H) in 1 / fCLKx1.
243 swidth width of active video and
244 totalwidth total line width, both in 1 / fCLKx1.
245 sqwidth total line width in square pixels.
246 vdelay start of active video in 2 * field lines relative to
247 trailing edge of /VRESET pulse (VDELAY register).
248 sheight height of active video in 2 * field lines.
249 videostart0 ITU-R frame line number of the line corresponding
250 to vdelay in the first field. */
251#define CROPCAP(minhdelayx1, hdelayx1, swidth, totalwidth, sqwidth, \
252 vdelay, sheight, videostart0) \
253 .cropcap.bounds.left = minhdelayx1, \
254 /* * 2 because vertically we count field lines times two, */ \
255 /* e.g. 23 * 2 to 23 * 2 + 576 in PAL-BGHI defrect. */ \
256 .cropcap.bounds.top = (videostart0) * 2 - (vdelay) + MIN_VDELAY, \
257 /* 4 is a safety margin at the end of the line. */ \
258 .cropcap.bounds.width = (totalwidth) - (minhdelayx1) - 4, \
259 .cropcap.bounds.height = (sheight) + (vdelay) - MIN_VDELAY, \
260 .cropcap.defrect.left = hdelayx1, \
261 .cropcap.defrect.top = (videostart0) * 2, \
262 .cropcap.defrect.width = swidth, \
263 .cropcap.defrect.height = sheight, \
264 .cropcap.pixelaspect.numerator = totalwidth, \
265 .cropcap.pixelaspect.denominator = sqwidth,
266
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267const struct bttv_tvnorm bttv_tvnorms[] = {
268 /* PAL-BDGHI */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800269 /* max. active video is actually 922, but 924 is divisible by 4 and 3! */
270 /* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 {
272 .v4l2_id = V4L2_STD_PAL,
273 .name = "PAL",
274 .Fsc = 35468950,
275 .swidth = 924,
276 .sheight = 576,
277 .totalwidth = 1135,
278 .adelay = 0x7f,
279 .bdelay = 0x72,
280 .iform = (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
281 .scaledtwidth = 1135,
282 .hdelayx1 = 186,
283 .hactivex1 = 924,
284 .vdelay = 0x20,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300285 .vbipack = 255, /* min (2048 / 4, 0x1ff) & 0xff */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 .sram = 0,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200287 /* ITU-R frame line number of the first VBI line
Michael Schimeke5bd0262007-01-18 16:17:39 -0300288 we can capture, of the first and second field.
289 The last line is determined by cropcap.bounds. */
290 .vbistart = { 7, 320 },
291 CROPCAP(/* minhdelayx1 */ 68,
292 /* hdelayx1 */ 186,
293 /* Should be (768 * 1135 + 944 / 2) / 944.
294 cropcap.defrect is used for image width
295 checks, so we keep the old value 924. */
296 /* swidth */ 924,
297 /* totalwidth */ 1135,
298 /* sqwidth */ 944,
299 /* vdelay */ 0x20,
300 /* sheight */ 576,
301 /* videostart0 */ 23)
302 /* bt878 (and bt848?) can capture another
303 line below active video. */
304 .cropcap.bounds.height = (576 + 2) + 0x20 - 2,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305 },{
Hans Verkuild97a11e2006-02-07 06:48:40 -0200306 .v4l2_id = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 .name = "NTSC",
308 .Fsc = 28636363,
309 .swidth = 768,
310 .sheight = 480,
311 .totalwidth = 910,
312 .adelay = 0x68,
313 .bdelay = 0x5d,
314 .iform = (BT848_IFORM_NTSC|BT848_IFORM_XT0),
315 .scaledtwidth = 910,
316 .hdelayx1 = 128,
317 .hactivex1 = 910,
318 .vdelay = 0x1a,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300319 .vbipack = 144, /* min (1600 / 4, 0x1ff) & 0xff */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 .sram = 1,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200321 .vbistart = { 10, 273 },
Michael Schimeke5bd0262007-01-18 16:17:39 -0300322 CROPCAP(/* minhdelayx1 */ 68,
323 /* hdelayx1 */ 128,
324 /* Should be (640 * 910 + 780 / 2) / 780? */
325 /* swidth */ 768,
326 /* totalwidth */ 910,
327 /* sqwidth */ 780,
328 /* vdelay */ 0x1a,
329 /* sheight */ 480,
330 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331 },{
332 .v4l2_id = V4L2_STD_SECAM,
333 .name = "SECAM",
334 .Fsc = 35468950,
335 .swidth = 924,
336 .sheight = 576,
337 .totalwidth = 1135,
338 .adelay = 0x7f,
339 .bdelay = 0xb0,
340 .iform = (BT848_IFORM_SECAM|BT848_IFORM_XT1),
341 .scaledtwidth = 1135,
342 .hdelayx1 = 186,
343 .hactivex1 = 922,
344 .vdelay = 0x20,
345 .vbipack = 255,
346 .sram = 0, /* like PAL, correct? */
Michael H. Schimek67f15702006-01-09 15:25:27 -0200347 .vbistart = { 7, 320 },
Michael Schimeke5bd0262007-01-18 16:17:39 -0300348 CROPCAP(/* minhdelayx1 */ 68,
349 /* hdelayx1 */ 186,
350 /* swidth */ 924,
351 /* totalwidth */ 1135,
352 /* sqwidth */ 944,
353 /* vdelay */ 0x20,
354 /* sheight */ 576,
355 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 },{
357 .v4l2_id = V4L2_STD_PAL_Nc,
358 .name = "PAL-Nc",
359 .Fsc = 28636363,
360 .swidth = 640,
361 .sheight = 576,
362 .totalwidth = 910,
363 .adelay = 0x68,
364 .bdelay = 0x5d,
365 .iform = (BT848_IFORM_PAL_NC|BT848_IFORM_XT0),
366 .scaledtwidth = 780,
367 .hdelayx1 = 130,
368 .hactivex1 = 734,
369 .vdelay = 0x1a,
370 .vbipack = 144,
371 .sram = -1,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200372 .vbistart = { 7, 320 },
Michael Schimeke5bd0262007-01-18 16:17:39 -0300373 CROPCAP(/* minhdelayx1 */ 68,
374 /* hdelayx1 */ 130,
375 /* swidth */ (640 * 910 + 780 / 2) / 780,
376 /* totalwidth */ 910,
377 /* sqwidth */ 780,
378 /* vdelay */ 0x1a,
379 /* sheight */ 576,
380 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381 },{
382 .v4l2_id = V4L2_STD_PAL_M,
383 .name = "PAL-M",
384 .Fsc = 28636363,
385 .swidth = 640,
386 .sheight = 480,
387 .totalwidth = 910,
388 .adelay = 0x68,
389 .bdelay = 0x5d,
390 .iform = (BT848_IFORM_PAL_M|BT848_IFORM_XT0),
391 .scaledtwidth = 780,
392 .hdelayx1 = 135,
393 .hactivex1 = 754,
394 .vdelay = 0x1a,
395 .vbipack = 144,
396 .sram = -1,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200397 .vbistart = { 10, 273 },
Michael Schimeke5bd0262007-01-18 16:17:39 -0300398 CROPCAP(/* minhdelayx1 */ 68,
399 /* hdelayx1 */ 135,
400 /* swidth */ (640 * 910 + 780 / 2) / 780,
401 /* totalwidth */ 910,
402 /* sqwidth */ 780,
403 /* vdelay */ 0x1a,
404 /* sheight */ 480,
405 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 },{
407 .v4l2_id = V4L2_STD_PAL_N,
408 .name = "PAL-N",
409 .Fsc = 35468950,
410 .swidth = 768,
411 .sheight = 576,
412 .totalwidth = 1135,
413 .adelay = 0x7f,
414 .bdelay = 0x72,
415 .iform = (BT848_IFORM_PAL_N|BT848_IFORM_XT1),
416 .scaledtwidth = 944,
417 .hdelayx1 = 186,
418 .hactivex1 = 922,
419 .vdelay = 0x20,
420 .vbipack = 144,
421 .sram = -1,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300422 .vbistart = { 7, 320 },
423 CROPCAP(/* minhdelayx1 */ 68,
424 /* hdelayx1 */ 186,
425 /* swidth */ (768 * 1135 + 944 / 2) / 944,
426 /* totalwidth */ 1135,
427 /* sqwidth */ 944,
428 /* vdelay */ 0x20,
429 /* sheight */ 576,
430 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 },{
432 .v4l2_id = V4L2_STD_NTSC_M_JP,
433 .name = "NTSC-JP",
434 .Fsc = 28636363,
435 .swidth = 640,
436 .sheight = 480,
437 .totalwidth = 910,
438 .adelay = 0x68,
439 .bdelay = 0x5d,
440 .iform = (BT848_IFORM_NTSC_J|BT848_IFORM_XT0),
441 .scaledtwidth = 780,
442 .hdelayx1 = 135,
443 .hactivex1 = 754,
444 .vdelay = 0x16,
445 .vbipack = 144,
446 .sram = -1,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300447 .vbistart = { 10, 273 },
448 CROPCAP(/* minhdelayx1 */ 68,
449 /* hdelayx1 */ 135,
450 /* swidth */ (640 * 910 + 780 / 2) / 780,
451 /* totalwidth */ 910,
452 /* sqwidth */ 780,
453 /* vdelay */ 0x16,
454 /* sheight */ 480,
455 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456 },{
457 /* that one hopefully works with the strange timing
458 * which video recorders produce when playing a NTSC
459 * tape on a PAL TV ... */
460 .v4l2_id = V4L2_STD_PAL_60,
461 .name = "PAL-60",
462 .Fsc = 35468950,
463 .swidth = 924,
464 .sheight = 480,
465 .totalwidth = 1135,
466 .adelay = 0x7f,
467 .bdelay = 0x72,
468 .iform = (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
469 .scaledtwidth = 1135,
470 .hdelayx1 = 186,
471 .hactivex1 = 924,
472 .vdelay = 0x1a,
473 .vbipack = 255,
474 .vtotal = 524,
475 .sram = -1,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200476 .vbistart = { 10, 273 },
Michael Schimeke5bd0262007-01-18 16:17:39 -0300477 CROPCAP(/* minhdelayx1 */ 68,
478 /* hdelayx1 */ 186,
479 /* swidth */ 924,
480 /* totalwidth */ 1135,
481 /* sqwidth */ 944,
482 /* vdelay */ 0x1a,
483 /* sheight */ 480,
484 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 }
486};
487static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms);
488
489/* ----------------------------------------------------------------------- */
490/* bttv format list
491 packed pixel formats must come first */
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -0300492static const struct bttv_format formats[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 {
494 .name = "8 bpp, gray",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 .fourcc = V4L2_PIX_FMT_GREY,
496 .btformat = BT848_COLOR_FMT_Y8,
497 .depth = 8,
498 .flags = FORMAT_FLAGS_PACKED,
499 },{
500 .name = "8 bpp, dithered color",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 .fourcc = V4L2_PIX_FMT_HI240,
502 .btformat = BT848_COLOR_FMT_RGB8,
503 .depth = 8,
504 .flags = FORMAT_FLAGS_PACKED | FORMAT_FLAGS_DITHER,
505 },{
506 .name = "15 bpp RGB, le",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 .fourcc = V4L2_PIX_FMT_RGB555,
508 .btformat = BT848_COLOR_FMT_RGB15,
509 .depth = 16,
510 .flags = FORMAT_FLAGS_PACKED,
511 },{
512 .name = "15 bpp RGB, be",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 .fourcc = V4L2_PIX_FMT_RGB555X,
514 .btformat = BT848_COLOR_FMT_RGB15,
515 .btswap = 0x03, /* byteswap */
516 .depth = 16,
517 .flags = FORMAT_FLAGS_PACKED,
518 },{
519 .name = "16 bpp RGB, le",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 .fourcc = V4L2_PIX_FMT_RGB565,
521 .btformat = BT848_COLOR_FMT_RGB16,
522 .depth = 16,
523 .flags = FORMAT_FLAGS_PACKED,
524 },{
525 .name = "16 bpp RGB, be",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 .fourcc = V4L2_PIX_FMT_RGB565X,
527 .btformat = BT848_COLOR_FMT_RGB16,
528 .btswap = 0x03, /* byteswap */
529 .depth = 16,
530 .flags = FORMAT_FLAGS_PACKED,
531 },{
532 .name = "24 bpp RGB, le",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533 .fourcc = V4L2_PIX_FMT_BGR24,
534 .btformat = BT848_COLOR_FMT_RGB24,
535 .depth = 24,
536 .flags = FORMAT_FLAGS_PACKED,
537 },{
538 .name = "32 bpp RGB, le",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 .fourcc = V4L2_PIX_FMT_BGR32,
540 .btformat = BT848_COLOR_FMT_RGB32,
541 .depth = 32,
542 .flags = FORMAT_FLAGS_PACKED,
543 },{
544 .name = "32 bpp RGB, be",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 .fourcc = V4L2_PIX_FMT_RGB32,
546 .btformat = BT848_COLOR_FMT_RGB32,
547 .btswap = 0x0f, /* byte+word swap */
548 .depth = 32,
549 .flags = FORMAT_FLAGS_PACKED,
550 },{
551 .name = "4:2:2, packed, YUYV",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 .fourcc = V4L2_PIX_FMT_YUYV,
553 .btformat = BT848_COLOR_FMT_YUY2,
554 .depth = 16,
555 .flags = FORMAT_FLAGS_PACKED,
556 },{
557 .name = "4:2:2, packed, YUYV",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 .fourcc = V4L2_PIX_FMT_YUYV,
559 .btformat = BT848_COLOR_FMT_YUY2,
560 .depth = 16,
561 .flags = FORMAT_FLAGS_PACKED,
562 },{
563 .name = "4:2:2, packed, UYVY",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 .fourcc = V4L2_PIX_FMT_UYVY,
565 .btformat = BT848_COLOR_FMT_YUY2,
566 .btswap = 0x03, /* byteswap */
567 .depth = 16,
568 .flags = FORMAT_FLAGS_PACKED,
569 },{
570 .name = "4:2:2, planar, Y-Cb-Cr",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571 .fourcc = V4L2_PIX_FMT_YUV422P,
572 .btformat = BT848_COLOR_FMT_YCrCb422,
573 .depth = 16,
574 .flags = FORMAT_FLAGS_PLANAR,
575 .hshift = 1,
576 .vshift = 0,
577 },{
578 .name = "4:2:0, planar, Y-Cb-Cr",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579 .fourcc = V4L2_PIX_FMT_YUV420,
580 .btformat = BT848_COLOR_FMT_YCrCb422,
581 .depth = 12,
582 .flags = FORMAT_FLAGS_PLANAR,
583 .hshift = 1,
584 .vshift = 1,
585 },{
586 .name = "4:2:0, planar, Y-Cr-Cb",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587 .fourcc = V4L2_PIX_FMT_YVU420,
588 .btformat = BT848_COLOR_FMT_YCrCb422,
589 .depth = 12,
590 .flags = FORMAT_FLAGS_PLANAR | FORMAT_FLAGS_CrCb,
591 .hshift = 1,
592 .vshift = 1,
593 },{
594 .name = "4:1:1, planar, Y-Cb-Cr",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 .fourcc = V4L2_PIX_FMT_YUV411P,
596 .btformat = BT848_COLOR_FMT_YCrCb411,
597 .depth = 12,
598 .flags = FORMAT_FLAGS_PLANAR,
599 .hshift = 2,
600 .vshift = 0,
601 },{
602 .name = "4:1:0, planar, Y-Cb-Cr",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603 .fourcc = V4L2_PIX_FMT_YUV410,
604 .btformat = BT848_COLOR_FMT_YCrCb411,
605 .depth = 9,
606 .flags = FORMAT_FLAGS_PLANAR,
607 .hshift = 2,
608 .vshift = 2,
609 },{
610 .name = "4:1:0, planar, Y-Cr-Cb",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 .fourcc = V4L2_PIX_FMT_YVU410,
612 .btformat = BT848_COLOR_FMT_YCrCb411,
613 .depth = 9,
614 .flags = FORMAT_FLAGS_PLANAR | FORMAT_FLAGS_CrCb,
615 .hshift = 2,
616 .vshift = 2,
617 },{
618 .name = "raw scanlines",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 .fourcc = -1,
620 .btformat = BT848_COLOR_FMT_RAW,
621 .depth = 8,
622 .flags = FORMAT_FLAGS_RAW,
623 }
624};
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -0300625static const unsigned int FORMATS = ARRAY_SIZE(formats);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626
627/* ----------------------------------------------------------------------- */
628
629#define V4L2_CID_PRIVATE_CHROMA_AGC (V4L2_CID_PRIVATE_BASE + 0)
630#define V4L2_CID_PRIVATE_COMBFILTER (V4L2_CID_PRIVATE_BASE + 1)
631#define V4L2_CID_PRIVATE_AUTOMUTE (V4L2_CID_PRIVATE_BASE + 2)
632#define V4L2_CID_PRIVATE_LUMAFILTER (V4L2_CID_PRIVATE_BASE + 3)
633#define V4L2_CID_PRIVATE_AGC_CRUSH (V4L2_CID_PRIVATE_BASE + 4)
634#define V4L2_CID_PRIVATE_VCR_HACK (V4L2_CID_PRIVATE_BASE + 5)
635#define V4L2_CID_PRIVATE_WHITECRUSH_UPPER (V4L2_CID_PRIVATE_BASE + 6)
636#define V4L2_CID_PRIVATE_WHITECRUSH_LOWER (V4L2_CID_PRIVATE_BASE + 7)
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700637#define V4L2_CID_PRIVATE_UV_RATIO (V4L2_CID_PRIVATE_BASE + 8)
638#define V4L2_CID_PRIVATE_FULL_LUMA_RANGE (V4L2_CID_PRIVATE_BASE + 9)
639#define V4L2_CID_PRIVATE_CORING (V4L2_CID_PRIVATE_BASE + 10)
640#define V4L2_CID_PRIVATE_LASTP1 (V4L2_CID_PRIVATE_BASE + 11)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641
642static const struct v4l2_queryctrl no_ctl = {
643 .name = "42",
644 .flags = V4L2_CTRL_FLAG_DISABLED,
645};
646static const struct v4l2_queryctrl bttv_ctls[] = {
647 /* --- video --- */
648 {
649 .id = V4L2_CID_BRIGHTNESS,
650 .name = "Brightness",
651 .minimum = 0,
652 .maximum = 65535,
653 .step = 256,
654 .default_value = 32768,
655 .type = V4L2_CTRL_TYPE_INTEGER,
656 },{
657 .id = V4L2_CID_CONTRAST,
658 .name = "Contrast",
659 .minimum = 0,
660 .maximum = 65535,
661 .step = 128,
662 .default_value = 32768,
663 .type = V4L2_CTRL_TYPE_INTEGER,
664 },{
665 .id = V4L2_CID_SATURATION,
666 .name = "Saturation",
667 .minimum = 0,
668 .maximum = 65535,
669 .step = 128,
670 .default_value = 32768,
671 .type = V4L2_CTRL_TYPE_INTEGER,
672 },{
673 .id = V4L2_CID_HUE,
674 .name = "Hue",
675 .minimum = 0,
676 .maximum = 65535,
677 .step = 256,
678 .default_value = 32768,
679 .type = V4L2_CTRL_TYPE_INTEGER,
680 },
681 /* --- audio --- */
682 {
683 .id = V4L2_CID_AUDIO_MUTE,
684 .name = "Mute",
685 .minimum = 0,
686 .maximum = 1,
687 .type = V4L2_CTRL_TYPE_BOOLEAN,
688 },{
689 .id = V4L2_CID_AUDIO_VOLUME,
690 .name = "Volume",
691 .minimum = 0,
692 .maximum = 65535,
693 .step = 65535/100,
694 .default_value = 65535,
695 .type = V4L2_CTRL_TYPE_INTEGER,
696 },{
697 .id = V4L2_CID_AUDIO_BALANCE,
698 .name = "Balance",
699 .minimum = 0,
700 .maximum = 65535,
701 .step = 65535/100,
702 .default_value = 32768,
703 .type = V4L2_CTRL_TYPE_INTEGER,
704 },{
705 .id = V4L2_CID_AUDIO_BASS,
706 .name = "Bass",
707 .minimum = 0,
708 .maximum = 65535,
709 .step = 65535/100,
710 .default_value = 32768,
711 .type = V4L2_CTRL_TYPE_INTEGER,
712 },{
713 .id = V4L2_CID_AUDIO_TREBLE,
714 .name = "Treble",
715 .minimum = 0,
716 .maximum = 65535,
717 .step = 65535/100,
718 .default_value = 32768,
719 .type = V4L2_CTRL_TYPE_INTEGER,
720 },
721 /* --- private --- */
722 {
723 .id = V4L2_CID_PRIVATE_CHROMA_AGC,
724 .name = "chroma agc",
725 .minimum = 0,
726 .maximum = 1,
727 .type = V4L2_CTRL_TYPE_BOOLEAN,
728 },{
729 .id = V4L2_CID_PRIVATE_COMBFILTER,
730 .name = "combfilter",
731 .minimum = 0,
732 .maximum = 1,
733 .type = V4L2_CTRL_TYPE_BOOLEAN,
734 },{
735 .id = V4L2_CID_PRIVATE_AUTOMUTE,
736 .name = "automute",
737 .minimum = 0,
738 .maximum = 1,
739 .type = V4L2_CTRL_TYPE_BOOLEAN,
740 },{
741 .id = V4L2_CID_PRIVATE_LUMAFILTER,
742 .name = "luma decimation filter",
743 .minimum = 0,
744 .maximum = 1,
745 .type = V4L2_CTRL_TYPE_BOOLEAN,
746 },{
747 .id = V4L2_CID_PRIVATE_AGC_CRUSH,
748 .name = "agc crush",
749 .minimum = 0,
750 .maximum = 1,
751 .type = V4L2_CTRL_TYPE_BOOLEAN,
752 },{
753 .id = V4L2_CID_PRIVATE_VCR_HACK,
754 .name = "vcr hack",
755 .minimum = 0,
756 .maximum = 1,
757 .type = V4L2_CTRL_TYPE_BOOLEAN,
758 },{
759 .id = V4L2_CID_PRIVATE_WHITECRUSH_UPPER,
760 .name = "whitecrush upper",
761 .minimum = 0,
762 .maximum = 255,
763 .step = 1,
764 .default_value = 0xCF,
765 .type = V4L2_CTRL_TYPE_INTEGER,
766 },{
767 .id = V4L2_CID_PRIVATE_WHITECRUSH_LOWER,
768 .name = "whitecrush lower",
769 .minimum = 0,
770 .maximum = 255,
771 .step = 1,
772 .default_value = 0x7F,
773 .type = V4L2_CTRL_TYPE_INTEGER,
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700774 },{
775 .id = V4L2_CID_PRIVATE_UV_RATIO,
776 .name = "uv ratio",
777 .minimum = 0,
778 .maximum = 100,
779 .step = 1,
780 .default_value = 50,
781 .type = V4L2_CTRL_TYPE_INTEGER,
782 },{
783 .id = V4L2_CID_PRIVATE_FULL_LUMA_RANGE,
784 .name = "full luma range",
785 .minimum = 0,
786 .maximum = 1,
787 .type = V4L2_CTRL_TYPE_BOOLEAN,
788 },{
789 .id = V4L2_CID_PRIVATE_CORING,
790 .name = "coring",
791 .minimum = 0,
792 .maximum = 3,
793 .step = 1,
794 .default_value = 0,
795 .type = V4L2_CTRL_TYPE_INTEGER,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 }
797
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700798
799
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -0300802static const struct v4l2_queryctrl *ctrl_by_id(int id)
803{
804 int i;
805
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -0300806 for (i = 0; i < ARRAY_SIZE(bttv_ctls); i++)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -0300807 if (bttv_ctls[i].id == id)
808 return bttv_ctls+i;
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -0300809
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -0300810 return NULL;
811}
812
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813/* ----------------------------------------------------------------------- */
814/* resource management */
815
Michael Schimeke5bd0262007-01-18 16:17:39 -0300816/*
817 RESOURCE_ allocated by freed by
818
819 VIDEO_READ bttv_read 1) bttv_read 2)
820
821 VIDEO_STREAM VIDIOC_STREAMON VIDIOC_STREAMOFF
822 VIDIOC_QBUF 1) bttv_release
823 VIDIOCMCAPTURE 1)
824
825 OVERLAY VIDIOCCAPTURE on VIDIOCCAPTURE off
826 VIDIOC_OVERLAY on VIDIOC_OVERLAY off
827 3) bttv_release
828
829 VBI VIDIOC_STREAMON VIDIOC_STREAMOFF
830 VIDIOC_QBUF 1) bttv_release
831 bttv_read, bttv_poll 1) 4)
832
833 1) The resource must be allocated when we enter buffer prepare functions
834 and remain allocated while buffers are in the DMA queue.
835 2) This is a single frame read.
836 3) VIDIOC_S_FBUF and VIDIOC_S_FMT (OVERLAY) still work when
837 RESOURCE_OVERLAY is allocated.
838 4) This is a continuous read, implies VIDIOC_STREAMON.
839
840 Note this driver permits video input and standard changes regardless if
841 resources are allocated.
842*/
843
844#define VBI_RESOURCES (RESOURCE_VBI)
845#define VIDEO_RESOURCES (RESOURCE_VIDEO_READ | \
846 RESOURCE_VIDEO_STREAM | \
847 RESOURCE_OVERLAY)
848
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849static
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -0300850int check_alloc_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851{
Michael Schimeke5bd0262007-01-18 16:17:39 -0300852 int xbits; /* mutual exclusive resources */
853
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 if (fh->resources & bit)
855 /* have it already allocated */
856 return 1;
857
Michael Schimeke5bd0262007-01-18 16:17:39 -0300858 xbits = bit;
859 if (bit & (RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM))
860 xbits |= RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM;
861
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 /* is it free? */
Michael Schimeke5bd0262007-01-18 16:17:39 -0300863 if (btv->resources & xbits) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 /* no, someone else uses it */
Michael Schimeke5bd0262007-01-18 16:17:39 -0300865 goto fail;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 }
Michael Schimeke5bd0262007-01-18 16:17:39 -0300867
868 if ((bit & VIDEO_RESOURCES)
869 && 0 == (btv->resources & VIDEO_RESOURCES)) {
870 /* Do crop - use current, don't - use default parameters. */
871 __s32 top = btv->crop[!!fh->do_crop].rect.top;
872
873 if (btv->vbi_end > top)
874 goto fail;
875
876 /* We cannot capture the same line as video and VBI data.
877 Claim scan lines crop[].rect.top to bottom. */
878 btv->crop_start = top;
879 } else if (bit & VBI_RESOURCES) {
880 __s32 end = fh->vbi_fmt.end;
881
882 if (end > btv->crop_start)
883 goto fail;
884
885 /* Claim scan lines above fh->vbi_fmt.end. */
886 btv->vbi_end = end;
887 }
888
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 /* it's free, grab it */
890 fh->resources |= bit;
891 btv->resources |= bit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 return 1;
Michael Schimeke5bd0262007-01-18 16:17:39 -0300893
894 fail:
Michael Schimeke5bd0262007-01-18 16:17:39 -0300895 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896}
897
898static
899int check_btres(struct bttv_fh *fh, int bit)
900{
901 return (fh->resources & bit);
902}
903
904static
905int locked_btres(struct bttv *btv, int bit)
906{
907 return (btv->resources & bit);
908}
909
Michael Schimeke5bd0262007-01-18 16:17:39 -0300910/* Call with btv->lock down. */
911static void
912disclaim_vbi_lines(struct bttv *btv)
913{
914 btv->vbi_end = 0;
915}
916
917/* Call with btv->lock down. */
918static void
919disclaim_video_lines(struct bttv *btv)
920{
921 const struct bttv_tvnorm *tvnorm;
922 u8 crop;
923
924 tvnorm = &bttv_tvnorms[btv->tvnorm];
925 btv->crop_start = tvnorm->cropcap.bounds.top
926 + tvnorm->cropcap.bounds.height;
927
928 /* VBI capturing ends at VDELAY, start of video capturing, no
929 matter how many lines the VBI RISC program expects. When video
930 capturing is off, it shall no longer "preempt" VBI capturing,
931 so we set VDELAY to maximum. */
932 crop = btread(BT848_E_CROP) | 0xc0;
933 btwrite(crop, BT848_E_CROP);
934 btwrite(0xfe, BT848_E_VDELAY_LO);
935 btwrite(crop, BT848_O_CROP);
936 btwrite(0xfe, BT848_O_VDELAY_LO);
937}
938
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939static
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -0300940void free_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bits)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 if ((fh->resources & bits) != bits) {
943 /* trying to free ressources not allocated by us ... */
944 printk("bttv: BUG! (btres)\n");
945 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 fh->resources &= ~bits;
947 btv->resources &= ~bits;
Michael Schimeke5bd0262007-01-18 16:17:39 -0300948
949 bits = btv->resources;
950
951 if (0 == (bits & VIDEO_RESOURCES))
952 disclaim_video_lines(btv);
953
954 if (0 == (bits & VBI_RESOURCES))
955 disclaim_vbi_lines(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956}
957
958/* ----------------------------------------------------------------------- */
959/* If Bt848a or Bt849, use PLL for PAL/SECAM and crystal for NTSC */
960
961/* Frequency = (F_input / PLL_X) * PLL_I.PLL_F/PLL_C
962 PLL_X = Reference pre-divider (0=1, 1=2)
963 PLL_C = Post divider (0=6, 1=4)
964 PLL_I = Integer input
965 PLL_F = Fractional input
966
967 F_input = 28.636363 MHz:
968 PAL (CLKx2 = 35.46895 MHz): PLL_X = 1, PLL_I = 0x0E, PLL_F = 0xDCF9, PLL_C = 0
969*/
970
971static void set_pll_freq(struct bttv *btv, unsigned int fin, unsigned int fout)
972{
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800973 unsigned char fl, fh, fi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800975 /* prevent overflows */
976 fin/=4;
977 fout/=4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800979 fout*=12;
980 fi=fout/fin;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800982 fout=(fout%fin)*256;
983 fh=fout/fin;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800985 fout=(fout%fin)*256;
986 fl=fout/fin;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800988 btwrite(fl, BT848_PLL_F_LO);
989 btwrite(fh, BT848_PLL_F_HI);
990 btwrite(fi|BT848_PLL_X, BT848_PLL_XCI);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991}
992
993static void set_pll(struct bttv *btv)
994{
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800995 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800997 if (!btv->pll.pll_crystal)
998 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999
1000 if (btv->pll.pll_ofreq == btv->pll.pll_current) {
1001 dprintk("bttv%d: PLL: no change required\n",btv->c.nr);
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -08001002 return;
1003 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -08001005 if (btv->pll.pll_ifreq == btv->pll.pll_ofreq) {
1006 /* no PLL needed */
1007 if (btv->pll.pll_current == 0)
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -08001008 return;
Bernd Petrovitsche1e70a22005-09-22 21:43:53 -07001009 bttv_printk(KERN_INFO "bttv%d: PLL can sleep, using XTAL (%d).\n",
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -08001010 btv->c.nr,btv->pll.pll_ifreq);
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -08001011 btwrite(0x00,BT848_TGCTRL);
1012 btwrite(0x00,BT848_PLL_XCI);
1013 btv->pll.pll_current = 0;
1014 return;
1015 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016
Bernd Petrovitsche1e70a22005-09-22 21:43:53 -07001017 bttv_printk(KERN_INFO "bttv%d: PLL: %d => %d ",btv->c.nr,
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -08001018 btv->pll.pll_ifreq, btv->pll.pll_ofreq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 set_pll_freq(btv, btv->pll.pll_ifreq, btv->pll.pll_ofreq);
1020
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -08001021 for (i=0; i<10; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 /* Let other people run while the PLL stabilizes */
Bernd Petrovitsche1e70a22005-09-22 21:43:53 -07001023 bttv_printk(".");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 msleep(10);
1025
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -08001026 if (btread(BT848_DSTATUS) & BT848_DSTATUS_PLOCK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 btwrite(0,BT848_DSTATUS);
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -08001028 } else {
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -08001029 btwrite(0x08,BT848_TGCTRL);
1030 btv->pll.pll_current = btv->pll.pll_ofreq;
Bernd Petrovitsche1e70a22005-09-22 21:43:53 -07001031 bttv_printk(" ok\n");
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -08001032 return;
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -08001033 }
1034 }
1035 btv->pll.pll_current = -1;
Bernd Petrovitsche1e70a22005-09-22 21:43:53 -07001036 bttv_printk("failed\n");
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -08001037 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038}
1039
1040/* used to switch between the bt848's analog/digital video capture modes */
1041static void bt848A_set_timing(struct bttv *btv)
1042{
1043 int i, len;
1044 int table_idx = bttv_tvnorms[btv->tvnorm].sram;
1045 int fsc = bttv_tvnorms[btv->tvnorm].Fsc;
1046
Trent Piepho5221e212009-01-28 21:32:59 -03001047 if (btv->input == btv->dig) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 dprintk("bttv%d: load digital timing table (table_idx=%d)\n",
1049 btv->c.nr,table_idx);
1050
1051 /* timing change...reset timing generator address */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001052 btwrite(0x00, BT848_TGCTRL);
1053 btwrite(0x02, BT848_TGCTRL);
1054 btwrite(0x00, BT848_TGCTRL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055
1056 len=SRAM_Table[table_idx][0];
1057 for(i = 1; i <= len; i++)
1058 btwrite(SRAM_Table[table_idx][i],BT848_TGLB);
1059 btv->pll.pll_ofreq = 27000000;
1060
1061 set_pll(btv);
1062 btwrite(0x11, BT848_TGCTRL);
1063 btwrite(0x41, BT848_DVSIF);
1064 } else {
1065 btv->pll.pll_ofreq = fsc;
1066 set_pll(btv);
1067 btwrite(0x0, BT848_DVSIF);
1068 }
1069}
1070
1071/* ----------------------------------------------------------------------- */
1072
1073static void bt848_bright(struct bttv *btv, int bright)
1074{
1075 int value;
1076
1077 // printk("bttv: set bright: %d\n",bright); // DEBUG
1078 btv->bright = bright;
1079
1080 /* We want -128 to 127 we get 0-65535 */
1081 value = (bright >> 8) - 128;
1082 btwrite(value & 0xff, BT848_BRIGHT);
1083}
1084
1085static void bt848_hue(struct bttv *btv, int hue)
1086{
1087 int value;
1088
1089 btv->hue = hue;
1090
1091 /* -128 to 127 */
1092 value = (hue >> 8) - 128;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001093 btwrite(value & 0xff, BT848_HUE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094}
1095
1096static void bt848_contrast(struct bttv *btv, int cont)
1097{
1098 int value,hibit;
1099
1100 btv->contrast = cont;
1101
1102 /* 0-511 */
1103 value = (cont >> 7);
1104 hibit = (value >> 6) & 4;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001105 btwrite(value & 0xff, BT848_CONTRAST_LO);
1106 btaor(hibit, ~4, BT848_E_CONTROL);
1107 btaor(hibit, ~4, BT848_O_CONTROL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108}
1109
1110static void bt848_sat(struct bttv *btv, int color)
1111{
1112 int val_u,val_v,hibits;
1113
1114 btv->saturation = color;
1115
1116 /* 0-511 for the color */
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -07001117 val_u = ((color * btv->opt_uv_ratio) / 50) >> 7;
1118 val_v = (((color * (100 - btv->opt_uv_ratio) / 50) >>7)*180L)/254;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001119 hibits = (val_u >> 7) & 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 hibits |= (val_v >> 8) & 1;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001121 btwrite(val_u & 0xff, BT848_SAT_U_LO);
1122 btwrite(val_v & 0xff, BT848_SAT_V_LO);
1123 btaor(hibits, ~3, BT848_E_CONTROL);
1124 btaor(hibits, ~3, BT848_O_CONTROL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125}
1126
1127/* ----------------------------------------------------------------------- */
1128
1129static int
1130video_mux(struct bttv *btv, unsigned int input)
1131{
1132 int mux,mask2;
1133
1134 if (input >= bttv_tvcards[btv->c.type].video_inputs)
1135 return -EINVAL;
1136
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001137 /* needed by RemoteVideo MX */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 mask2 = bttv_tvcards[btv->c.type].gpiomask2;
1139 if (mask2)
1140 gpio_inout(mask2,mask2);
1141
1142 if (input == btv->svhs) {
1143 btor(BT848_CONTROL_COMP, BT848_E_CONTROL);
1144 btor(BT848_CONTROL_COMP, BT848_O_CONTROL);
1145 } else {
1146 btand(~BT848_CONTROL_COMP, BT848_E_CONTROL);
1147 btand(~BT848_CONTROL_COMP, BT848_O_CONTROL);
1148 }
Trent Piepho6f987002009-01-28 21:32:59 -03001149 mux = bttv_muxsel(btv, input);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 btaor(mux<<5, ~(3<<5), BT848_IFORM);
1151 dprintk(KERN_DEBUG "bttv%d: video mux: input=%d mux=%d\n",
1152 btv->c.nr,input,mux);
1153
1154 /* card specific hook */
1155 if(bttv_tvcards[btv->c.type].muxsel_hook)
1156 bttv_tvcards[btv->c.type].muxsel_hook (btv, input);
1157 return 0;
1158}
1159
1160static char *audio_modes[] = {
1161 "audio: tuner", "audio: radio", "audio: extern",
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001162 "audio: intern", "audio: mute"
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163};
1164
1165static int
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001166audio_mux(struct bttv *btv, int input, int mute)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167{
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001168 int gpio_val, signal;
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001169 struct v4l2_control ctrl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170
1171 gpio_inout(bttv_tvcards[btv->c.type].gpiomask,
1172 bttv_tvcards[btv->c.type].gpiomask);
1173 signal = btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC;
1174
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001175 btv->mute = mute;
1176 btv->audio = input;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001178 /* automute */
1179 mute = mute || (btv->opt_automute && !signal && !btv->radio_user);
1180
1181 if (mute)
1182 gpio_val = bttv_tvcards[btv->c.type].gpiomute;
1183 else
1184 gpio_val = bttv_tvcards[btv->c.type].gpiomux[input];
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001185
Trent Piepho72134a62009-01-28 21:32:59 -03001186 switch (btv->c.type) {
1187 case BTTV_BOARD_VOODOOTV_FM:
1188 case BTTV_BOARD_VOODOOTV_200:
1189 gpio_val = bttv_tda9880_setnorm(btv, gpio_val);
1190 break;
1191
1192 default:
1193 gpio_bits(bttv_tvcards[btv->c.type].gpiomask, gpio_val);
1194 }
1195
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196 if (bttv_gpio)
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001197 bttv_gpio_tracking(btv, audio_modes[mute ? 4 : input]);
1198 if (in_interrupt())
1199 return 0;
1200
1201 ctrl.id = V4L2_CID_AUDIO_MUTE;
Hans Verkuil2474ed42006-03-19 12:35:57 -03001202 ctrl.value = btv->mute;
Hans Verkuil859f0272009-03-28 08:29:00 -03001203 bttv_call_all(btv, core, s_ctrl, &ctrl);
1204 if (btv->sd_msp34xx) {
Hans Verkuil5325b422009-04-02 11:26:22 -03001205 u32 in;
Hans Verkuil2474ed42006-03-19 12:35:57 -03001206
1207 /* Note: the inputs tuner/radio/extern/intern are translated
1208 to msp routings. This assumes common behavior for all msp3400
1209 based TV cards. When this assumption fails, then the
1210 specific MSP routing must be added to the card table.
1211 For now this is sufficient. */
1212 switch (input) {
1213 case TVAUDIO_INPUT_RADIO:
Hans Verkuil5325b422009-04-02 11:26:22 -03001214 in = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1,
Hans Verkuil07151722006-04-01 18:03:23 -03001215 MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001216 break;
1217 case TVAUDIO_INPUT_EXTERN:
Hans Verkuil5325b422009-04-02 11:26:22 -03001218 in = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1,
Hans Verkuil07151722006-04-01 18:03:23 -03001219 MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001220 break;
1221 case TVAUDIO_INPUT_INTERN:
1222 /* Yes, this is the same input as for RADIO. I doubt
1223 if this is ever used. The only board with an INTERN
1224 input is the BTTV_BOARD_AVERMEDIA98. I wonder how
1225 that was tested. My guess is that the whole INTERN
1226 input does not work. */
Hans Verkuil5325b422009-04-02 11:26:22 -03001227 in = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1,
Hans Verkuil07151722006-04-01 18:03:23 -03001228 MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001229 break;
1230 case TVAUDIO_INPUT_TUNER:
1231 default:
Wade Berrier434b2522007-06-25 13:02:16 -03001232 /* This is the only card that uses TUNER2, and afaik,
1233 is the only difference between the VOODOOTV_FM
1234 and VOODOOTV_200 */
1235 if (btv->c.type == BTTV_BOARD_VOODOOTV_200)
Hans Verkuil5325b422009-04-02 11:26:22 -03001236 in = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER2, \
Wade Berrier434b2522007-06-25 13:02:16 -03001237 MSP_DSP_IN_TUNER, MSP_DSP_IN_TUNER);
1238 else
Hans Verkuil5325b422009-04-02 11:26:22 -03001239 in = MSP_INPUT_DEFAULT;
Hans Verkuil2474ed42006-03-19 12:35:57 -03001240 break;
1241 }
Hans Verkuil5325b422009-04-02 11:26:22 -03001242 v4l2_subdev_call(btv->sd_msp34xx, audio, s_routing,
1243 in, MSP_OUTPUT_DEFAULT, 0);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001244 }
Hans Verkuil859f0272009-03-28 08:29:00 -03001245 if (btv->sd_tvaudio) {
Hans Verkuil5325b422009-04-02 11:26:22 -03001246 v4l2_subdev_call(btv->sd_tvaudio, audio, s_routing,
1247 input, 0, 0);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001248 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249 return 0;
1250}
1251
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001252static inline int
1253audio_mute(struct bttv *btv, int mute)
1254{
1255 return audio_mux(btv, btv->audio, mute);
1256}
1257
1258static inline int
1259audio_input(struct bttv *btv, int input)
1260{
1261 return audio_mux(btv, input, btv->mute);
1262}
1263
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264static void
Michael Schimeke5bd0262007-01-18 16:17:39 -03001265bttv_crop_calc_limits(struct bttv_crop *c)
1266{
1267 /* Scale factor min. 1:1, max. 16:1. Min. image size
1268 48 x 32. Scaled width must be a multiple of 4. */
1269
1270 if (1) {
1271 /* For bug compatibility with VIDIOCGCAP and image
1272 size checks in earlier driver versions. */
1273 c->min_scaled_width = 48;
1274 c->min_scaled_height = 32;
1275 } else {
1276 c->min_scaled_width =
1277 (max(48, c->rect.width >> 4) + 3) & ~3;
1278 c->min_scaled_height =
1279 max(32, c->rect.height >> 4);
1280 }
1281
1282 c->max_scaled_width = c->rect.width & ~3;
1283 c->max_scaled_height = c->rect.height;
1284}
1285
1286static void
Trent Piepho4ef2ccc2009-01-28 21:32:58 -03001287bttv_crop_reset(struct bttv_crop *c, unsigned int norm)
Michael Schimeke5bd0262007-01-18 16:17:39 -03001288{
1289 c->rect = bttv_tvnorms[norm].cropcap.defrect;
1290 bttv_crop_calc_limits(c);
1291}
1292
1293/* Call with btv->lock down. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294static int
1295set_tvnorm(struct bttv *btv, unsigned int norm)
1296{
1297 const struct bttv_tvnorm *tvnorm;
Nickolay V. Shmyrev302f61a2007-10-26 10:53:21 -03001298 v4l2_std_id id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299
Trent Piepho4ef2ccc2009-01-28 21:32:58 -03001300 BUG_ON(norm >= BTTV_TVNORMS);
1301 BUG_ON(btv->tvnorm >= BTTV_TVNORMS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 tvnorm = &bttv_tvnorms[norm];
1304
Mike Isely2de26c02009-09-21 12:42:22 -03001305 if (memcmp(&bttv_tvnorms[btv->tvnorm].cropcap, &tvnorm->cropcap,
Trent Piepho4ef2ccc2009-01-28 21:32:58 -03001306 sizeof (tvnorm->cropcap))) {
Michael Schimeke5bd0262007-01-18 16:17:39 -03001307 bttv_crop_reset(&btv->crop[0], norm);
1308 btv->crop[1] = btv->crop[0]; /* current = default */
1309
1310 if (0 == (btv->resources & VIDEO_RESOURCES)) {
1311 btv->crop_start = tvnorm->cropcap.bounds.top
1312 + tvnorm->cropcap.bounds.height;
1313 }
1314 }
1315
1316 btv->tvnorm = norm;
1317
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318 btwrite(tvnorm->adelay, BT848_ADELAY);
1319 btwrite(tvnorm->bdelay, BT848_BDELAY);
1320 btaor(tvnorm->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH),
1321 BT848_IFORM);
1322 btwrite(tvnorm->vbipack, BT848_VBI_PACK_SIZE);
1323 btwrite(1, BT848_VBI_PACK_DEL);
1324 bt848A_set_timing(btv);
1325
1326 switch (btv->c.type) {
Mauro Carvalho Chehab5a25e842005-11-08 21:36:52 -08001327 case BTTV_BOARD_VOODOOTV_FM:
Wade Berrier434b2522007-06-25 13:02:16 -03001328 case BTTV_BOARD_VOODOOTV_200:
Trent Piepho72134a62009-01-28 21:32:59 -03001329 bttv_tda9880_setnorm(btv, gpio_read());
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331 }
Nickolay V. Shmyrev302f61a2007-10-26 10:53:21 -03001332 id = tvnorm->v4l2_id;
Hans Verkuilf41737e2009-04-01 03:52:39 -03001333 bttv_call_all(btv, core, s_std, id);
Nickolay V. Shmyrev302f61a2007-10-26 10:53:21 -03001334
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335 return 0;
1336}
1337
Michael Schimeke5bd0262007-01-18 16:17:39 -03001338/* Call with btv->lock down. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339static void
Trent Piepho333408f2007-07-03 15:08:10 -03001340set_input(struct bttv *btv, unsigned int input, unsigned int norm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341{
1342 unsigned long flags;
1343
1344 btv->input = input;
1345 if (irq_iswitch) {
1346 spin_lock_irqsave(&btv->s_lock,flags);
1347 if (btv->curr.frame_irq) {
1348 /* active capture -> delayed input switch */
1349 btv->new_input = input;
1350 } else {
1351 video_mux(btv,input);
1352 }
1353 spin_unlock_irqrestore(&btv->s_lock,flags);
1354 } else {
1355 video_mux(btv,input);
1356 }
Trent Piephoabb03622009-01-28 21:32:59 -03001357 audio_input(btv, (btv->tuner_type != TUNER_ABSENT && input == 0) ?
1358 TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN);
Trent Piepho333408f2007-07-03 15:08:10 -03001359 set_tvnorm(btv, norm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360}
1361
1362static void init_irqreg(struct bttv *btv)
1363{
1364 /* clear status */
1365 btwrite(0xfffffUL, BT848_INT_STAT);
1366
1367 if (bttv_tvcards[btv->c.type].no_video) {
1368 /* i2c only */
1369 btwrite(BT848_INT_I2CDONE,
1370 BT848_INT_MASK);
1371 } else {
1372 /* full video */
1373 btwrite((btv->triton1) |
1374 (btv->gpioirq ? BT848_INT_GPINT : 0) |
1375 BT848_INT_SCERR |
1376 (fdsr ? BT848_INT_FDSR : 0) |
Jean Delvareeb1b27b2008-08-30 10:18:21 -03001377 BT848_INT_RISCI | BT848_INT_OCERR |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 BT848_INT_FMTCHG|BT848_INT_HLOCK|
1379 BT848_INT_I2CDONE,
1380 BT848_INT_MASK);
1381 }
1382}
1383
1384static void init_bt848(struct bttv *btv)
1385{
1386 int val;
1387
1388 if (bttv_tvcards[btv->c.type].no_video) {
1389 /* very basic init only */
1390 init_irqreg(btv);
1391 return;
1392 }
1393
1394 btwrite(0x00, BT848_CAP_CTL);
1395 btwrite(BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL);
1396 btwrite(BT848_IFORM_XTAUTO | BT848_IFORM_AUTO, BT848_IFORM);
1397
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001398 /* set planar and packed mode trigger points and */
1399 /* set rising edge of inverted GPINTR pin as irq trigger */
1400 btwrite(BT848_GPIO_DMA_CTL_PKTP_32|
1401 BT848_GPIO_DMA_CTL_PLTP1_16|
1402 BT848_GPIO_DMA_CTL_PLTP23_16|
1403 BT848_GPIO_DMA_CTL_GPINTC|
1404 BT848_GPIO_DMA_CTL_GPINTI,
1405 BT848_GPIO_DMA_CTL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406
1407 val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001408 btwrite(val, BT848_E_SCLOOP);
1409 btwrite(val, BT848_O_SCLOOP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001411 btwrite(0x20, BT848_E_VSCALE_HI);
1412 btwrite(0x20, BT848_O_VSCALE_HI);
1413 btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 BT848_ADC);
1415
1416 btwrite(whitecrush_upper, BT848_WC_UP);
1417 btwrite(whitecrush_lower, BT848_WC_DOWN);
1418
1419 if (btv->opt_lumafilter) {
1420 btwrite(0, BT848_E_CONTROL);
1421 btwrite(0, BT848_O_CONTROL);
1422 } else {
1423 btwrite(BT848_CONTROL_LDEC, BT848_E_CONTROL);
1424 btwrite(BT848_CONTROL_LDEC, BT848_O_CONTROL);
1425 }
1426
1427 bt848_bright(btv, btv->bright);
1428 bt848_hue(btv, btv->hue);
1429 bt848_contrast(btv, btv->contrast);
1430 bt848_sat(btv, btv->saturation);
1431
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001432 /* interrupt */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433 init_irqreg(btv);
1434}
1435
1436static void bttv_reinit_bt848(struct bttv *btv)
1437{
1438 unsigned long flags;
1439
1440 if (bttv_verbose)
1441 printk(KERN_INFO "bttv%d: reset, reinitialize\n",btv->c.nr);
1442 spin_lock_irqsave(&btv->s_lock,flags);
1443 btv->errors=0;
1444 bttv_set_dma(btv,0);
1445 spin_unlock_irqrestore(&btv->s_lock,flags);
1446
1447 init_bt848(btv);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001448 btv->pll.pll_current = -1;
Trent Piepho333408f2007-07-03 15:08:10 -03001449 set_input(btv, btv->input, btv->tvnorm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450}
1451
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001452static int bttv_g_ctrl(struct file *file, void *priv,
1453 struct v4l2_control *c)
1454{
1455 struct bttv_fh *fh = priv;
1456 struct bttv *btv = fh->btv;
1457
1458 switch (c->id) {
1459 case V4L2_CID_BRIGHTNESS:
1460 c->value = btv->bright;
1461 break;
1462 case V4L2_CID_HUE:
1463 c->value = btv->hue;
1464 break;
1465 case V4L2_CID_CONTRAST:
1466 c->value = btv->contrast;
1467 break;
1468 case V4L2_CID_SATURATION:
1469 c->value = btv->saturation;
1470 break;
1471
1472 case V4L2_CID_AUDIO_MUTE:
1473 case V4L2_CID_AUDIO_VOLUME:
1474 case V4L2_CID_AUDIO_BALANCE:
1475 case V4L2_CID_AUDIO_BASS:
1476 case V4L2_CID_AUDIO_TREBLE:
Hans Verkuil859f0272009-03-28 08:29:00 -03001477 bttv_call_all(btv, core, g_ctrl, c);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001478 break;
1479
1480 case V4L2_CID_PRIVATE_CHROMA_AGC:
1481 c->value = btv->opt_chroma_agc;
1482 break;
1483 case V4L2_CID_PRIVATE_COMBFILTER:
1484 c->value = btv->opt_combfilter;
1485 break;
1486 case V4L2_CID_PRIVATE_LUMAFILTER:
1487 c->value = btv->opt_lumafilter;
1488 break;
1489 case V4L2_CID_PRIVATE_AUTOMUTE:
1490 c->value = btv->opt_automute;
1491 break;
1492 case V4L2_CID_PRIVATE_AGC_CRUSH:
1493 c->value = btv->opt_adc_crush;
1494 break;
1495 case V4L2_CID_PRIVATE_VCR_HACK:
1496 c->value = btv->opt_vcr_hack;
1497 break;
1498 case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
1499 c->value = btv->opt_whitecrush_upper;
1500 break;
1501 case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
1502 c->value = btv->opt_whitecrush_lower;
1503 break;
1504 case V4L2_CID_PRIVATE_UV_RATIO:
1505 c->value = btv->opt_uv_ratio;
1506 break;
1507 case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
1508 c->value = btv->opt_full_luma_range;
1509 break;
1510 case V4L2_CID_PRIVATE_CORING:
1511 c->value = btv->opt_coring;
1512 break;
1513 default:
1514 return -EINVAL;
1515 }
1516 return 0;
1517}
1518
1519static int bttv_s_ctrl(struct file *file, void *f,
1520 struct v4l2_control *c)
1521{
1522 int err;
1523 int val;
1524 struct bttv_fh *fh = f;
1525 struct bttv *btv = fh->btv;
1526
Hans Verkuilffb48772010-05-01 08:03:24 -03001527 err = v4l2_prio_check(&btv->prio, fh->prio);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001528 if (0 != err)
1529 return err;
1530
1531 switch (c->id) {
1532 case V4L2_CID_BRIGHTNESS:
1533 bt848_bright(btv, c->value);
1534 break;
1535 case V4L2_CID_HUE:
1536 bt848_hue(btv, c->value);
1537 break;
1538 case V4L2_CID_CONTRAST:
1539 bt848_contrast(btv, c->value);
1540 break;
1541 case V4L2_CID_SATURATION:
1542 bt848_sat(btv, c->value);
1543 break;
1544 case V4L2_CID_AUDIO_MUTE:
1545 audio_mute(btv, c->value);
1546 /* fall through */
1547 case V4L2_CID_AUDIO_VOLUME:
1548 if (btv->volume_gpio)
1549 btv->volume_gpio(btv, c->value);
1550
Hans Verkuil859f0272009-03-28 08:29:00 -03001551 bttv_call_all(btv, core, s_ctrl, c);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001552 break;
1553 case V4L2_CID_AUDIO_BALANCE:
1554 case V4L2_CID_AUDIO_BASS:
1555 case V4L2_CID_AUDIO_TREBLE:
Hans Verkuil859f0272009-03-28 08:29:00 -03001556 bttv_call_all(btv, core, s_ctrl, c);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001557 break;
1558
1559 case V4L2_CID_PRIVATE_CHROMA_AGC:
1560 btv->opt_chroma_agc = c->value;
1561 val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
1562 btwrite(val, BT848_E_SCLOOP);
1563 btwrite(val, BT848_O_SCLOOP);
1564 break;
1565 case V4L2_CID_PRIVATE_COMBFILTER:
1566 btv->opt_combfilter = c->value;
1567 break;
1568 case V4L2_CID_PRIVATE_LUMAFILTER:
1569 btv->opt_lumafilter = c->value;
1570 if (btv->opt_lumafilter) {
1571 btand(~BT848_CONTROL_LDEC, BT848_E_CONTROL);
1572 btand(~BT848_CONTROL_LDEC, BT848_O_CONTROL);
1573 } else {
1574 btor(BT848_CONTROL_LDEC, BT848_E_CONTROL);
1575 btor(BT848_CONTROL_LDEC, BT848_O_CONTROL);
1576 }
1577 break;
1578 case V4L2_CID_PRIVATE_AUTOMUTE:
1579 btv->opt_automute = c->value;
1580 break;
1581 case V4L2_CID_PRIVATE_AGC_CRUSH:
1582 btv->opt_adc_crush = c->value;
1583 btwrite(BT848_ADC_RESERVED |
1584 (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
1585 BT848_ADC);
1586 break;
1587 case V4L2_CID_PRIVATE_VCR_HACK:
1588 btv->opt_vcr_hack = c->value;
1589 break;
1590 case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
1591 btv->opt_whitecrush_upper = c->value;
1592 btwrite(c->value, BT848_WC_UP);
1593 break;
1594 case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
1595 btv->opt_whitecrush_lower = c->value;
1596 btwrite(c->value, BT848_WC_DOWN);
1597 break;
1598 case V4L2_CID_PRIVATE_UV_RATIO:
1599 btv->opt_uv_ratio = c->value;
1600 bt848_sat(btv, btv->saturation);
1601 break;
1602 case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
1603 btv->opt_full_luma_range = c->value;
1604 btaor((c->value<<7), ~BT848_OFORM_RANGE, BT848_OFORM);
1605 break;
1606 case V4L2_CID_PRIVATE_CORING:
1607 btv->opt_coring = c->value;
1608 btaor((c->value<<5), ~BT848_OFORM_CORE32, BT848_OFORM);
1609 break;
1610 default:
1611 return -EINVAL;
1612 }
1613 return 0;
1614}
1615
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616/* ----------------------------------------------------------------------- */
1617
1618void bttv_gpio_tracking(struct bttv *btv, char *comment)
1619{
1620 unsigned int outbits, data;
1621 outbits = btread(BT848_GPIO_OUT_EN);
1622 data = btread(BT848_GPIO_DATA);
1623 printk(KERN_DEBUG "bttv%d: gpio: en=%08x, out=%08x in=%08x [%s]\n",
1624 btv->c.nr,outbits,data & outbits, data & ~outbits, comment);
1625}
1626
1627static void bttv_field_count(struct bttv *btv)
1628{
1629 int need_count = 0;
1630
1631 if (btv->users)
1632 need_count++;
1633
1634 if (need_count) {
1635 /* start field counter */
1636 btor(BT848_INT_VSYNC,BT848_INT_MASK);
1637 } else {
1638 /* stop field counter */
1639 btand(~BT848_INT_VSYNC,BT848_INT_MASK);
1640 btv->field_count = 0;
1641 }
1642}
1643
1644static const struct bttv_format*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645format_by_fourcc(int fourcc)
1646{
1647 unsigned int i;
1648
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001649 for (i = 0; i < FORMATS; i++) {
1650 if (-1 == formats[i].fourcc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651 continue;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001652 if (formats[i].fourcc == fourcc)
1653 return formats+i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654 }
1655 return NULL;
1656}
1657
1658/* ----------------------------------------------------------------------- */
1659/* misc helpers */
1660
1661static int
1662bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh,
1663 struct bttv_buffer *new)
1664{
1665 struct bttv_buffer *old;
1666 unsigned long flags;
1667 int retval = 0;
1668
1669 dprintk("switch_overlay: enter [new=%p]\n",new);
1670 if (new)
Brandon Philips0fc06862007-11-06 20:02:36 -03001671 new->vb.state = VIDEOBUF_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672 spin_lock_irqsave(&btv->s_lock,flags);
1673 old = btv->screen;
1674 btv->screen = new;
1675 btv->loop_irq |= 1;
1676 bttv_set_dma(btv, 0x03);
1677 spin_unlock_irqrestore(&btv->s_lock,flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 if (NULL != old) {
1679 dprintk("switch_overlay: old=%p state is %d\n",old,old->vb.state);
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001680 bttv_dma_free(&fh->cap,btv, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681 kfree(old);
1682 }
Michael Schimeke5bd0262007-01-18 16:17:39 -03001683 if (NULL == new)
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03001684 free_btres_lock(btv,fh,RESOURCE_OVERLAY);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685 dprintk("switch_overlay: done\n");
1686 return retval;
1687}
1688
1689/* ----------------------------------------------------------------------- */
1690/* video4linux (1) interface */
1691
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001692static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv,
1693 struct bttv_buffer *buf,
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001694 const struct bttv_format *fmt,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695 unsigned int width, unsigned int height,
1696 enum v4l2_field field)
1697{
Michael Schimeke5bd0262007-01-18 16:17:39 -03001698 struct bttv_fh *fh = q->priv_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699 int redo_dma_risc = 0;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001700 struct bttv_crop c;
1701 int norm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 int rc;
1703
1704 /* check settings */
1705 if (NULL == fmt)
1706 return -EINVAL;
1707 if (fmt->btformat == BT848_COLOR_FMT_RAW) {
1708 width = RAW_BPL;
1709 height = RAW_LINES*2;
1710 if (width*height > buf->vb.bsize)
1711 return -EINVAL;
1712 buf->vb.size = buf->vb.bsize;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001713
1714 /* Make sure tvnorm and vbi_end remain consistent
1715 until we're done. */
Michael Schimeke5bd0262007-01-18 16:17:39 -03001716
1717 norm = btv->tvnorm;
1718
1719 /* In this mode capturing always starts at defrect.top
1720 (default VDELAY), ignoring cropping parameters. */
1721 if (btv->vbi_end > bttv_tvnorms[norm].cropcap.defrect.top) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 return -EINVAL;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001723 }
1724
Michael Schimeke5bd0262007-01-18 16:17:39 -03001725 c.rect = bttv_tvnorms[norm].cropcap.defrect;
1726 } else {
Michael Schimeke5bd0262007-01-18 16:17:39 -03001727 norm = btv->tvnorm;
1728 c = btv->crop[!!fh->do_crop];
1729
Michael Schimeke5bd0262007-01-18 16:17:39 -03001730 if (width < c.min_scaled_width ||
1731 width > c.max_scaled_width ||
1732 height < c.min_scaled_height)
1733 return -EINVAL;
1734
1735 switch (field) {
1736 case V4L2_FIELD_TOP:
1737 case V4L2_FIELD_BOTTOM:
1738 case V4L2_FIELD_ALTERNATE:
1739 /* btv->crop counts frame lines. Max. scale
1740 factor is 16:1 for frames, 8:1 for fields. */
1741 if (height * 2 > c.max_scaled_height)
1742 return -EINVAL;
1743 break;
1744
1745 default:
1746 if (height > c.max_scaled_height)
1747 return -EINVAL;
1748 break;
1749 }
1750
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751 buf->vb.size = (width * height * fmt->depth) >> 3;
1752 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
1753 return -EINVAL;
1754 }
1755
1756 /* alloc + fill struct bttv_buffer (if changed) */
1757 if (buf->vb.width != width || buf->vb.height != height ||
1758 buf->vb.field != field ||
Michael Schimeke5bd0262007-01-18 16:17:39 -03001759 buf->tvnorm != norm || buf->fmt != fmt ||
1760 buf->crop.top != c.rect.top ||
1761 buf->crop.left != c.rect.left ||
1762 buf->crop.width != c.rect.width ||
1763 buf->crop.height != c.rect.height) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764 buf->vb.width = width;
1765 buf->vb.height = height;
1766 buf->vb.field = field;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001767 buf->tvnorm = norm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768 buf->fmt = fmt;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001769 buf->crop = c.rect;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770 redo_dma_risc = 1;
1771 }
1772
1773 /* alloc risc memory */
Brandon Philips0fc06862007-11-06 20:02:36 -03001774 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775 redo_dma_risc = 1;
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001776 if (0 != (rc = videobuf_iolock(q,&buf->vb,&btv->fbuf)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777 goto fail;
1778 }
1779
1780 if (redo_dma_risc)
1781 if (0 != (rc = bttv_buffer_risc(btv,buf)))
1782 goto fail;
1783
Brandon Philips0fc06862007-11-06 20:02:36 -03001784 buf->vb.state = VIDEOBUF_PREPARED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785 return 0;
1786
1787 fail:
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001788 bttv_dma_free(q,btv,buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001789 return rc;
1790}
1791
1792static int
1793buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
1794{
1795 struct bttv_fh *fh = q->priv_data;
1796
1797 *size = fh->fmt->depth*fh->width*fh->height >> 3;
1798 if (0 == *count)
1799 *count = gbuffers;
Andreas Bombedab7e312010-03-21 16:02:45 -03001800 if (*size * *count > gbuffers * gbufsize)
1801 *count = (gbuffers * gbufsize) / *size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802 return 0;
1803}
1804
1805static int
1806buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
1807 enum v4l2_field field)
1808{
1809 struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
1810 struct bttv_fh *fh = q->priv_data;
1811
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001812 return bttv_prepare_buffer(q,fh->btv, buf, fh->fmt,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813 fh->width, fh->height, field);
1814}
1815
1816static void
1817buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
1818{
1819 struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
1820 struct bttv_fh *fh = q->priv_data;
1821 struct bttv *btv = fh->btv;
1822
Brandon Philips0fc06862007-11-06 20:02:36 -03001823 buf->vb.state = VIDEOBUF_QUEUED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824 list_add_tail(&buf->vb.queue,&btv->capture);
1825 if (!btv->curr.frame_irq) {
1826 btv->loop_irq |= 1;
1827 bttv_set_dma(btv, 0x03);
1828 }
1829}
1830
1831static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
1832{
1833 struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
1834 struct bttv_fh *fh = q->priv_data;
1835
Michael Schimekfeaba7a2007-01-26 08:30:05 -03001836 bttv_dma_free(q,fh->btv,buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837}
1838
1839static struct videobuf_queue_ops bttv_video_qops = {
1840 .buf_setup = buffer_setup,
1841 .buf_prepare = buffer_prepare,
1842 .buf_queue = buffer_queue,
1843 .buf_release = buffer_release,
1844};
1845
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001846static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001848 struct bttv_fh *fh = priv;
1849 struct bttv *btv = fh->btv;
1850 unsigned int i;
1851 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852
Hans Verkuilffb48772010-05-01 08:03:24 -03001853 err = v4l2_prio_check(&btv->prio, fh->prio);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001854 if (err)
1855 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001857 for (i = 0; i < BTTV_TVNORMS; i++)
1858 if (*id & bttv_tvnorms[i].v4l2_id)
1859 break;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001860 if (i == BTTV_TVNORMS) {
1861 err = -EINVAL;
1862 goto err;
1863 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001865 set_tvnorm(btv, i);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001866
1867err:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001869 return err;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001870}
1871
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001872static int bttv_querystd(struct file *file, void *f, v4l2_std_id *id)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001873{
1874 struct bttv_fh *fh = f;
1875 struct bttv *btv = fh->btv;
1876
1877 if (btread(BT848_DSTATUS) & BT848_DSTATUS_NUML)
1878 *id = V4L2_STD_625_50;
1879 else
1880 *id = V4L2_STD_525_60;
1881 return 0;
1882}
1883
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001884static int bttv_enum_input(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001885 struct v4l2_input *i)
1886{
1887 struct bttv_fh *fh = priv;
1888 struct bttv *btv = fh->btv;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001889 int rc = 0;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001890
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001891 if (i->index >= bttv_tvcards[btv->c.type].video_inputs) {
1892 rc = -EINVAL;
1893 goto err;
1894 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001895
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001896 i->type = V4L2_INPUT_TYPE_CAMERA;
1897 i->audioset = 1;
1898
Trent Piephoabb03622009-01-28 21:32:59 -03001899 if (btv->tuner_type != TUNER_ABSENT && i->index == 0) {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001900 sprintf(i->name, "Television");
1901 i->type = V4L2_INPUT_TYPE_TUNER;
1902 i->tuner = 0;
1903 } else if (i->index == btv->svhs) {
1904 sprintf(i->name, "S-Video");
1905 } else {
1906 sprintf(i->name, "Composite%d", i->index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907 }
1908
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001909 if (i->index == btv->input) {
1910 __u32 dstatus = btread(BT848_DSTATUS);
1911 if (0 == (dstatus & BT848_DSTATUS_PRES))
1912 i->status |= V4L2_IN_ST_NO_SIGNAL;
1913 if (0 == (dstatus & BT848_DSTATUS_HLOC))
1914 i->status |= V4L2_IN_ST_NO_H_LOCK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001915 }
1916
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001917 i->std = BTTV_NORMS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001918
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001919err:
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001920
1921 return rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001922}
Nickolay V. Shmyrev4b9b9362006-08-25 16:53:04 -03001923
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001924static int bttv_g_input(struct file *file, void *priv, unsigned int *i)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001925{
1926 struct bttv_fh *fh = priv;
1927 struct bttv *btv = fh->btv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001929 *i = btv->input;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001930
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001931 return 0;
1932}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001934static int bttv_s_input(struct file *file, void *priv, unsigned int i)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001935{
1936 struct bttv_fh *fh = priv;
1937 struct bttv *btv = fh->btv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001939 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001941 err = v4l2_prio_check(&btv->prio, fh->prio);
1942 if (unlikely(err))
1943 goto err;
1944
1945 if (i > bttv_tvcards[btv->c.type].video_inputs) {
1946 err = -EINVAL;
1947 goto err;
1948 }
1949
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001950 set_input(btv, i, btv->tvnorm);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001951
1952err:
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001953 return 0;
1954}
1955
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001956static int bttv_s_tuner(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001957 struct v4l2_tuner *t)
1958{
1959 struct bttv_fh *fh = priv;
1960 struct bttv *btv = fh->btv;
1961 int err;
1962
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001963 if (unlikely(0 != t->index))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001964 return -EINVAL;
1965
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001966 if (unlikely(btv->tuner_type == TUNER_ABSENT)) {
1967 err = -EINVAL;
1968 goto err;
1969 }
1970
1971 err = v4l2_prio_check(&btv->prio, fh->prio);
1972 if (unlikely(err))
1973 goto err;
1974
Hans Verkuil859f0272009-03-28 08:29:00 -03001975 bttv_call_all(btv, tuner, s_tuner, t);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001976
1977 if (btv->audio_mode_gpio)
1978 btv->audio_mode_gpio(btv, t, 1);
1979
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001980err:
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001981
1982 return 0;
1983}
1984
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001985static int bttv_g_frequency(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001986 struct v4l2_frequency *f)
1987{
1988 struct bttv_fh *fh = priv;
1989 struct bttv *btv = fh->btv;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001990
Robert Fitzsimons1b069012008-04-01 11:41:54 -03001991 f->type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001992 f->frequency = btv->freq;
1993
1994 return 0;
1995}
1996
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001997static int bttv_s_frequency(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001998 struct v4l2_frequency *f)
1999{
2000 struct bttv_fh *fh = priv;
2001 struct bttv *btv = fh->btv;
2002 int err;
2003
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002004 if (unlikely(f->tuner != 0))
2005 return -EINVAL;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002006
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002007 err = v4l2_prio_check(&btv->prio, fh->prio);
2008 if (unlikely(err))
2009 goto err;
2010
2011 if (unlikely(f->type != (btv->radio_user
2012 ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV))) {
2013 err = -EINVAL;
2014 goto err;
2015 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002016 btv->freq = f->frequency;
Hans Verkuil859f0272009-03-28 08:29:00 -03002017 bttv_call_all(btv, tuner, s_frequency, f);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002018 if (btv->has_matchbox && btv->radio_user)
2019 tea5757_set_freq(btv, btv->freq);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002020err:
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002021
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002022 return 0;
2023}
2024
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002025static int bttv_log_status(struct file *file, void *f)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002026{
2027 struct bttv_fh *fh = f;
2028 struct bttv *btv = fh->btv;
2029
2030 printk(KERN_INFO "bttv%d: ======== START STATUS CARD #%d ========\n",
2031 btv->c.nr, btv->c.nr);
Hans Verkuil859f0272009-03-28 08:29:00 -03002032 bttv_call_all(btv, core, log_status);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002033 printk(KERN_INFO "bttv%d: ======== END STATUS CARD #%d ========\n",
2034 btv->c.nr, btv->c.nr);
2035 return 0;
2036}
2037
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002038#ifdef CONFIG_VIDEO_ADV_DEBUG
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002039static int bttv_g_register(struct file *file, void *f,
Hans Verkuilaecde8b52008-12-30 07:14:19 -03002040 struct v4l2_dbg_register *reg)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002041{
2042 struct bttv_fh *fh = f;
2043 struct bttv *btv = fh->btv;
2044
2045 if (!capable(CAP_SYS_ADMIN))
2046 return -EPERM;
2047
Hans Verkuilaecde8b52008-12-30 07:14:19 -03002048 if (!v4l2_chip_match_host(&reg->match))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002049 return -EINVAL;
2050
2051 /* bt848 has a 12-bit register space */
2052 reg->reg &= 0xfff;
2053 reg->val = btread(reg->reg);
Hans Verkuilaecde8b52008-12-30 07:14:19 -03002054 reg->size = 1;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002055
2056 return 0;
2057}
2058
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002059static int bttv_s_register(struct file *file, void *f,
Hans Verkuilaecde8b52008-12-30 07:14:19 -03002060 struct v4l2_dbg_register *reg)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002061{
2062 struct bttv_fh *fh = f;
2063 struct bttv *btv = fh->btv;
2064
2065 if (!capable(CAP_SYS_ADMIN))
2066 return -EPERM;
2067
Hans Verkuilaecde8b52008-12-30 07:14:19 -03002068 if (!v4l2_chip_match_host(&reg->match))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002069 return -EINVAL;
2070
2071 /* bt848 has a 12-bit register space */
2072 reg->reg &= 0xfff;
2073 btwrite(reg->val, reg->reg);
2074
2075 return 0;
2076}
2077#endif
2078
Michael Schimeke5bd0262007-01-18 16:17:39 -03002079/* Given cropping boundaries b and the scaled width and height of a
2080 single field or frame, which must not exceed hardware limits, this
2081 function adjusts the cropping parameters c. */
2082static void
2083bttv_crop_adjust (struct bttv_crop * c,
2084 const struct v4l2_rect * b,
2085 __s32 width,
2086 __s32 height,
2087 enum v4l2_field field)
2088{
2089 __s32 frame_height = height << !V4L2_FIELD_HAS_BOTH(field);
2090 __s32 max_left;
2091 __s32 max_top;
2092
2093 if (width < c->min_scaled_width) {
2094 /* Max. hor. scale factor 16:1. */
2095 c->rect.width = width * 16;
2096 } else if (width > c->max_scaled_width) {
2097 /* Min. hor. scale factor 1:1. */
2098 c->rect.width = width;
2099
2100 max_left = b->left + b->width - width;
2101 max_left = min(max_left, (__s32) MAX_HDELAY);
2102 if (c->rect.left > max_left)
2103 c->rect.left = max_left;
2104 }
2105
2106 if (height < c->min_scaled_height) {
2107 /* Max. vert. scale factor 16:1, single fields 8:1. */
2108 c->rect.height = height * 16;
2109 } else if (frame_height > c->max_scaled_height) {
2110 /* Min. vert. scale factor 1:1.
2111 Top and height count field lines times two. */
2112 c->rect.height = (frame_height + 1) & ~1;
2113
2114 max_top = b->top + b->height - c->rect.height;
2115 if (c->rect.top > max_top)
2116 c->rect.top = max_top;
2117 }
2118
2119 bttv_crop_calc_limits(c);
2120}
2121
2122/* Returns an error if scaling to a frame or single field with the given
2123 width and height is not possible with the current cropping parameters
2124 and width aligned according to width_mask. If adjust_size is TRUE the
2125 function may adjust the width and/or height instead, rounding width
2126 to (width + width_bias) & width_mask. If adjust_crop is TRUE it may
2127 also adjust the current cropping parameters to get closer to the
2128 desired image size. */
2129static int
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002130limit_scaled_size_lock (struct bttv_fh * fh,
Michael Schimeke5bd0262007-01-18 16:17:39 -03002131 __s32 * width,
2132 __s32 * height,
2133 enum v4l2_field field,
2134 unsigned int width_mask,
2135 unsigned int width_bias,
2136 int adjust_size,
2137 int adjust_crop)
2138{
2139 struct bttv *btv = fh->btv;
2140 const struct v4l2_rect *b;
2141 struct bttv_crop *c;
2142 __s32 min_width;
2143 __s32 min_height;
2144 __s32 max_width;
2145 __s32 max_height;
2146 int rc;
2147
2148 BUG_ON((int) width_mask >= 0 ||
2149 width_bias >= (unsigned int) -width_mask);
2150
2151 /* Make sure tvnorm, vbi_end and the current cropping parameters
2152 remain consistent until we're done. */
Michael Schimeke5bd0262007-01-18 16:17:39 -03002153
2154 b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
2155
2156 /* Do crop - use current, don't - use default parameters. */
2157 c = &btv->crop[!!fh->do_crop];
2158
2159 if (fh->do_crop
2160 && adjust_size
2161 && adjust_crop
2162 && !locked_btres(btv, VIDEO_RESOURCES)) {
2163 min_width = 48;
2164 min_height = 32;
2165
2166 /* We cannot scale up. When the scaled image is larger
2167 than crop.rect we adjust the crop.rect as required
2168 by the V4L2 spec, hence cropcap.bounds are our limit. */
2169 max_width = min(b->width, (__s32) MAX_HACTIVE);
2170 max_height = b->height;
2171
2172 /* We cannot capture the same line as video and VBI data.
2173 Note btv->vbi_end is really a minimum, see
2174 bttv_vbi_try_fmt(). */
2175 if (btv->vbi_end > b->top) {
2176 max_height -= btv->vbi_end - b->top;
2177 rc = -EBUSY;
2178 if (min_height > max_height)
2179 goto fail;
2180 }
2181 } else {
2182 rc = -EBUSY;
2183 if (btv->vbi_end > c->rect.top)
2184 goto fail;
2185
2186 min_width = c->min_scaled_width;
2187 min_height = c->min_scaled_height;
2188 max_width = c->max_scaled_width;
2189 max_height = c->max_scaled_height;
2190
2191 adjust_crop = 0;
2192 }
2193
2194 min_width = (min_width - width_mask - 1) & width_mask;
2195 max_width = max_width & width_mask;
2196
2197 /* Max. scale factor is 16:1 for frames, 8:1 for fields. */
2198 min_height = min_height;
2199 /* Min. scale factor is 1:1. */
2200 max_height >>= !V4L2_FIELD_HAS_BOTH(field);
2201
2202 if (adjust_size) {
2203 *width = clamp(*width, min_width, max_width);
2204 *height = clamp(*height, min_height, max_height);
2205
2206 /* Round after clamping to avoid overflow. */
2207 *width = (*width + width_bias) & width_mask;
2208
2209 if (adjust_crop) {
2210 bttv_crop_adjust(c, b, *width, *height, field);
2211
2212 if (btv->vbi_end > c->rect.top) {
2213 /* Move the crop window out of the way. */
2214 c->rect.top = btv->vbi_end;
2215 }
2216 }
2217 } else {
2218 rc = -EINVAL;
2219 if (*width < min_width ||
2220 *height < min_height ||
2221 *width > max_width ||
2222 *height > max_height ||
2223 0 != (*width & ~width_mask))
2224 goto fail;
2225 }
2226
2227 rc = 0; /* success */
2228
2229 fail:
Michael Schimeke5bd0262007-01-18 16:17:39 -03002230
2231 return rc;
2232}
2233
2234/* Returns an error if the given overlay window dimensions are not
2235 possible with the current cropping parameters. If adjust_size is
2236 TRUE the function may adjust the window width and/or height
2237 instead, however it always rounds the horizontal position and
2238 width as btcx_align() does. If adjust_crop is TRUE the function
2239 may also adjust the current cropping parameters to get closer
2240 to the desired window size. */
2241static int
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002242verify_window_lock (struct bttv_fh * fh,
Michael Schimeke5bd0262007-01-18 16:17:39 -03002243 struct v4l2_window * win,
2244 int adjust_size,
2245 int adjust_crop)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002246{
2247 enum v4l2_field field;
Michael Schimeke5bd0262007-01-18 16:17:39 -03002248 unsigned int width_mask;
2249 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250
2251 if (win->w.width < 48 || win->w.height < 32)
2252 return -EINVAL;
2253 if (win->clipcount > 2048)
2254 return -EINVAL;
2255
2256 field = win->field;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257
2258 if (V4L2_FIELD_ANY == field) {
Michael Schimeke5bd0262007-01-18 16:17:39 -03002259 __s32 height2;
2260
2261 height2 = fh->btv->crop[!!fh->do_crop].rect.height >> 1;
2262 field = (win->w.height > height2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263 ? V4L2_FIELD_INTERLACED
2264 : V4L2_FIELD_TOP;
2265 }
2266 switch (field) {
2267 case V4L2_FIELD_TOP:
2268 case V4L2_FIELD_BOTTOM:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002269 case V4L2_FIELD_INTERLACED:
2270 break;
2271 default:
2272 return -EINVAL;
2273 }
2274
Michael Schimeke5bd0262007-01-18 16:17:39 -03002275 /* 4-byte alignment. */
2276 if (NULL == fh->ovfmt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002277 return -EINVAL;
Michael Schimeke5bd0262007-01-18 16:17:39 -03002278 width_mask = ~0;
2279 switch (fh->ovfmt->depth) {
2280 case 8:
2281 case 24:
2282 width_mask = ~3;
2283 break;
2284 case 16:
2285 width_mask = ~1;
2286 break;
2287 case 32:
2288 break;
2289 default:
2290 BUG();
2291 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292
Michael Schimeke5bd0262007-01-18 16:17:39 -03002293 win->w.width -= win->w.left & ~width_mask;
2294 win->w.left = (win->w.left - width_mask - 1) & width_mask;
2295
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002296 rc = limit_scaled_size_lock(fh, &win->w.width, &win->w.height,
Michael Schimeke5bd0262007-01-18 16:17:39 -03002297 field, width_mask,
2298 /* width_bias: round down */ 0,
2299 adjust_size, adjust_crop);
2300 if (0 != rc)
2301 return rc;
2302
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303 win->field = field;
2304 return 0;
2305}
2306
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002307static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308 struct v4l2_window *win, int fixup)
2309{
2310 struct v4l2_clip *clips = NULL;
2311 int n,size,retval = 0;
2312
2313 if (NULL == fh->ovfmt)
2314 return -EINVAL;
2315 if (!(fh->ovfmt->flags & FORMAT_FLAGS_PACKED))
2316 return -EINVAL;
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002317 retval = verify_window_lock(fh, win,
Michael Schimeke5bd0262007-01-18 16:17:39 -03002318 /* adjust_size */ fixup,
2319 /* adjust_crop */ fixup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320 if (0 != retval)
2321 return retval;
2322
2323 /* copy clips -- luckily v4l1 + v4l2 are binary
2324 compatible here ...*/
2325 n = win->clipcount;
2326 size = sizeof(*clips)*(n+4);
2327 clips = kmalloc(size,GFP_KERNEL);
2328 if (NULL == clips)
2329 return -ENOMEM;
2330 if (n > 0) {
2331 if (copy_from_user(clips,win->clips,sizeof(struct v4l2_clip)*n)) {
2332 kfree(clips);
2333 return -EFAULT;
2334 }
2335 }
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002336
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337 /* clip against screen */
2338 if (NULL != btv->fbuf.base)
2339 n = btcx_screen_clips(btv->fbuf.fmt.width, btv->fbuf.fmt.height,
2340 &win->w, clips, n);
2341 btcx_sort_clips(clips,n);
2342
2343 /* 4-byte alignments */
2344 switch (fh->ovfmt->depth) {
2345 case 8:
2346 case 24:
2347 btcx_align(&win->w, clips, n, 3);
2348 break;
2349 case 16:
2350 btcx_align(&win->w, clips, n, 1);
2351 break;
2352 case 32:
2353 /* no alignment fixups needed */
2354 break;
2355 default:
2356 BUG();
2357 }
2358
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03002359 kfree(fh->ov.clips);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360 fh->ov.clips = clips;
2361 fh->ov.nclips = n;
2362
2363 fh->ov.w = win->w;
2364 fh->ov.field = win->field;
2365 fh->ov.setup_ok = 1;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002366
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367 btv->init.ov.w.width = win->w.width;
2368 btv->init.ov.w.height = win->w.height;
2369 btv->init.ov.field = win->field;
2370
2371 /* update overlay if needed */
2372 retval = 0;
2373 if (check_btres(fh, RESOURCE_OVERLAY)) {
2374 struct bttv_buffer *new;
2375
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03002376 new = videobuf_sg_alloc(sizeof(*new));
Michael Schimeke5bd0262007-01-18 16:17:39 -03002377 new->crop = btv->crop[!!fh->do_crop].rect;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378 bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
2379 retval = bttv_switch_overlay(btv,fh,new);
2380 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381 return retval;
2382}
2383
2384/* ----------------------------------------------------------------------- */
2385
2386static struct videobuf_queue* bttv_queue(struct bttv_fh *fh)
2387{
2388 struct videobuf_queue* q = NULL;
2389
2390 switch (fh->type) {
2391 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2392 q = &fh->cap;
2393 break;
2394 case V4L2_BUF_TYPE_VBI_CAPTURE:
2395 q = &fh->vbi;
2396 break;
2397 default:
2398 BUG();
2399 }
2400 return q;
2401}
2402
2403static int bttv_resource(struct bttv_fh *fh)
2404{
2405 int res = 0;
2406
2407 switch (fh->type) {
2408 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Michael Schimeke5bd0262007-01-18 16:17:39 -03002409 res = RESOURCE_VIDEO_STREAM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410 break;
2411 case V4L2_BUF_TYPE_VBI_CAPTURE:
2412 res = RESOURCE_VBI;
2413 break;
2414 default:
2415 BUG();
2416 }
2417 return res;
2418}
2419
2420static int bttv_switch_type(struct bttv_fh *fh, enum v4l2_buf_type type)
2421{
2422 struct videobuf_queue *q = bttv_queue(fh);
2423 int res = bttv_resource(fh);
2424
2425 if (check_btres(fh,res))
2426 return -EBUSY;
2427 if (videobuf_queue_is_busy(q))
2428 return -EBUSY;
2429 fh->type = type;
2430 return 0;
2431}
2432
Michael H. Schimekc87c9482005-12-01 00:51:33 -08002433static void
2434pix_format_set_size (struct v4l2_pix_format * f,
2435 const struct bttv_format * fmt,
2436 unsigned int width,
2437 unsigned int height)
2438{
2439 f->width = width;
2440 f->height = height;
2441
2442 if (fmt->flags & FORMAT_FLAGS_PLANAR) {
2443 f->bytesperline = width; /* Y plane */
2444 f->sizeimage = (width * height * fmt->depth) >> 3;
2445 } else {
2446 f->bytesperline = (width * fmt->depth) >> 3;
2447 f->sizeimage = height * f->bytesperline;
2448 }
2449}
2450
Hans Verkuil78b526a2008-05-28 12:16:41 -03002451static int bttv_g_fmt_vid_cap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002452 struct v4l2_format *f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002454 struct bttv_fh *fh = priv;
2455
2456 pix_format_set_size(&f->fmt.pix, fh->fmt,
2457 fh->width, fh->height);
2458 f->fmt.pix.field = fh->cap.field;
2459 f->fmt.pix.pixelformat = fh->fmt->fourcc;
2460
2461 return 0;
2462}
2463
Hans Verkuil78b526a2008-05-28 12:16:41 -03002464static int bttv_g_fmt_vid_overlay(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002465 struct v4l2_format *f)
2466{
2467 struct bttv_fh *fh = priv;
2468
2469 f->fmt.win.w = fh->ov.w;
2470 f->fmt.win.field = fh->ov.field;
2471
2472 return 0;
2473}
2474
Hans Verkuil78b526a2008-05-28 12:16:41 -03002475static int bttv_try_fmt_vid_cap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002476 struct v4l2_format *f)
2477{
2478 const struct bttv_format *fmt;
2479 struct bttv_fh *fh = priv;
2480 struct bttv *btv = fh->btv;
2481 enum v4l2_field field;
2482 __s32 width, height;
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002483 int rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002484
2485 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
2486 if (NULL == fmt)
2487 return -EINVAL;
2488
2489 field = f->fmt.pix.field;
2490
2491 if (V4L2_FIELD_ANY == field) {
2492 __s32 height2;
2493
2494 height2 = btv->crop[!!fh->do_crop].rect.height >> 1;
2495 field = (f->fmt.pix.height > height2)
2496 ? V4L2_FIELD_INTERLACED
2497 : V4L2_FIELD_BOTTOM;
2498 }
2499
2500 if (V4L2_FIELD_SEQ_BT == field)
2501 field = V4L2_FIELD_SEQ_TB;
2502
2503 switch (field) {
2504 case V4L2_FIELD_TOP:
2505 case V4L2_FIELD_BOTTOM:
2506 case V4L2_FIELD_ALTERNATE:
2507 case V4L2_FIELD_INTERLACED:
2508 break;
2509 case V4L2_FIELD_SEQ_TB:
2510 if (fmt->flags & FORMAT_FLAGS_PLANAR)
2511 return -EINVAL;
2512 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002513 default:
2514 return -EINVAL;
2515 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002516
2517 width = f->fmt.pix.width;
2518 height = f->fmt.pix.height;
2519
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002520 rc = limit_scaled_size_lock(fh, &width, &height, field,
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002521 /* width_mask: 4 pixels */ ~3,
2522 /* width_bias: nearest */ 2,
2523 /* adjust_size */ 1,
2524 /* adjust_crop */ 0);
2525 if (0 != rc)
2526 return rc;
2527
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002528 /* update data for the application */
2529 f->fmt.pix.field = field;
2530 pix_format_set_size(&f->fmt.pix, fmt, width, height);
2531
2532 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002533}
2534
Hans Verkuil78b526a2008-05-28 12:16:41 -03002535static int bttv_try_fmt_vid_overlay(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002536 struct v4l2_format *f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002537{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002538 struct bttv_fh *fh = priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002539
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002540 return verify_window_lock(fh, &f->fmt.win,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002541 /* adjust_size */ 1,
2542 /* adjust_crop */ 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543}
2544
Hans Verkuil78b526a2008-05-28 12:16:41 -03002545static int bttv_s_fmt_vid_cap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002546 struct v4l2_format *f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002547{
2548 int retval;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002549 const struct bttv_format *fmt;
2550 struct bttv_fh *fh = priv;
2551 struct bttv *btv = fh->btv;
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002552 __s32 width, height;
2553 enum v4l2_field field;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002554
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002555 retval = bttv_switch_type(fh, f->type);
2556 if (0 != retval)
2557 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558
Hans Verkuil78b526a2008-05-28 12:16:41 -03002559 retval = bttv_try_fmt_vid_cap(file, priv, f);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002560 if (0 != retval)
2561 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002562
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002563 width = f->fmt.pix.width;
2564 height = f->fmt.pix.height;
2565 field = f->fmt.pix.field;
2566
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002567 retval = limit_scaled_size_lock(fh, &width, &height, f->fmt.pix.field,
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002568 /* width_mask: 4 pixels */ ~3,
2569 /* width_bias: nearest */ 2,
2570 /* adjust_size */ 1,
2571 /* adjust_crop */ 1);
2572 if (0 != retval)
2573 return retval;
2574
2575 f->fmt.pix.field = field;
2576
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002577 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002579 /* update our state informations */
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002580 fh->fmt = fmt;
2581 fh->cap.field = f->fmt.pix.field;
2582 fh->cap.last = V4L2_FIELD_NONE;
2583 fh->width = f->fmt.pix.width;
2584 fh->height = f->fmt.pix.height;
2585 btv->init.fmt = fmt;
2586 btv->init.width = f->fmt.pix.width;
2587 btv->init.height = f->fmt.pix.height;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002588
2589 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590}
2591
Hans Verkuil78b526a2008-05-28 12:16:41 -03002592static int bttv_s_fmt_vid_overlay(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002593 struct v4l2_format *f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002595 struct bttv_fh *fh = priv;
2596 struct bttv *btv = fh->btv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002597
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002598 if (no_overlay > 0) {
2599 printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002600 return -EINVAL;
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002601 }
Michael Krufky5e453dc2006-01-09 15:32:31 -02002602
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002603 return setup_window_lock(fh, btv, &f->fmt.win, 1);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002604}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002605
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002606static int bttv_querycap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002607 struct v4l2_capability *cap)
2608{
2609 struct bttv_fh *fh = priv;
2610 struct bttv *btv = fh->btv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002612 if (0 == v4l2)
2613 return -EINVAL;
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07002614
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002615 strlcpy(cap->driver, "bttv", sizeof(cap->driver));
2616 strlcpy(cap->card, btv->video_dev->name, sizeof(cap->card));
2617 snprintf(cap->bus_info, sizeof(cap->bus_info),
2618 "PCI:%s", pci_name(btv->c.pci));
2619 cap->version = BTTV_VERSION_CODE;
2620 cap->capabilities =
2621 V4L2_CAP_VIDEO_CAPTURE |
2622 V4L2_CAP_VBI_CAPTURE |
2623 V4L2_CAP_READWRITE |
2624 V4L2_CAP_STREAMING;
2625 if (no_overlay <= 0)
2626 cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002628 /*
2629 * No need to lock here: those vars are initialized during board
2630 * probe and remains untouched during the rest of the driver lifecycle
2631 */
2632 if (btv->has_saa6588)
2633 cap->capabilities |= V4L2_CAP_RDS_CAPTURE;
Trent Piephoabb03622009-01-28 21:32:59 -03002634 if (btv->tuner_type != TUNER_ABSENT)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002635 cap->capabilities |= V4L2_CAP_TUNER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636 return 0;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002637}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002638
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002639static int bttv_enum_fmt_cap_ovr(struct v4l2_fmtdesc *f)
2640{
2641 int index = -1, i;
2642
2643 for (i = 0; i < FORMATS; i++) {
2644 if (formats[i].fourcc != -1)
2645 index++;
2646 if ((unsigned int)index == f->index)
2647 break;
2648 }
2649 if (FORMATS == i)
2650 return -EINVAL;
2651
2652 f->pixelformat = formats[i].fourcc;
2653 strlcpy(f->description, formats[i].name, sizeof(f->description));
2654
2655 return i;
2656}
2657
Hans Verkuil78b526a2008-05-28 12:16:41 -03002658static int bttv_enum_fmt_vid_cap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002659 struct v4l2_fmtdesc *f)
2660{
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002661 int rc = bttv_enum_fmt_cap_ovr(f);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002662
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002663 if (rc < 0)
2664 return rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002665
2666 return 0;
2667}
2668
Hans Verkuil78b526a2008-05-28 12:16:41 -03002669static int bttv_enum_fmt_vid_overlay(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002670 struct v4l2_fmtdesc *f)
2671{
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002672 int rc;
2673
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002674 if (no_overlay > 0) {
2675 printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
2676 return -EINVAL;
2677 }
2678
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002679 rc = bttv_enum_fmt_cap_ovr(f);
2680
2681 if (rc < 0)
2682 return rc;
2683
2684 if (!(formats[rc].flags & FORMAT_FLAGS_PACKED))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002685 return -EINVAL;
2686
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002687 return 0;
2688}
2689
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002690static int bttv_g_fbuf(struct file *file, void *f,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002691 struct v4l2_framebuffer *fb)
2692{
2693 struct bttv_fh *fh = f;
2694 struct bttv *btv = fh->btv;
2695
2696 *fb = btv->fbuf;
2697 fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
2698 if (fh->ovfmt)
2699 fb->fmt.pixelformat = fh->ovfmt->fourcc;
2700 return 0;
2701}
2702
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002703static int bttv_overlay(struct file *file, void *f, unsigned int on)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002704{
2705 struct bttv_fh *fh = f;
2706 struct bttv *btv = fh->btv;
2707 struct bttv_buffer *new;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002708 int retval = 0;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002709
2710 if (on) {
2711 /* verify args */
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002712 if (unlikely(!btv->fbuf.base)) {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002713 return -EINVAL;
2714 }
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002715 if (unlikely(!fh->ov.setup_ok)) {
2716 dprintk("bttv%d: overlay: !setup_ok\n", btv->c.nr);
2717 retval = -EINVAL;
2718 }
2719 if (retval)
2720 return retval;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002721 }
2722
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002723 if (!check_alloc_btres_lock(btv, fh, RESOURCE_OVERLAY))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002724 return -EBUSY;
2725
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002726 if (on) {
2727 fh->ov.tvnorm = btv->tvnorm;
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03002728 new = videobuf_sg_alloc(sizeof(*new));
Robert Fitzsimons7c018802008-02-13 16:38:11 -03002729 new->crop = btv->crop[!!fh->do_crop].rect;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002730 bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
2731 } else {
2732 new = NULL;
2733 }
2734
2735 /* switch over */
2736 retval = bttv_switch_overlay(btv, fh, new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737 return retval;
2738}
2739
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002740static int bttv_s_fbuf(struct file *file, void *f,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002741 struct v4l2_framebuffer *fb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002743 struct bttv_fh *fh = f;
2744 struct bttv *btv = fh->btv;
2745 const struct bttv_format *fmt;
2746 int retval;
2747
2748 if (!capable(CAP_SYS_ADMIN) &&
2749 !capable(CAP_SYS_RAWIO))
2750 return -EPERM;
2751
2752 /* check args */
2753 fmt = format_by_fourcc(fb->fmt.pixelformat);
2754 if (NULL == fmt)
2755 return -EINVAL;
2756 if (0 == (fmt->flags & FORMAT_FLAGS_PACKED))
2757 return -EINVAL;
2758
2759 retval = -EINVAL;
2760 if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
2761 __s32 width = fb->fmt.width;
2762 __s32 height = fb->fmt.height;
2763
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002764 retval = limit_scaled_size_lock(fh, &width, &height,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002765 V4L2_FIELD_INTERLACED,
2766 /* width_mask */ ~3,
2767 /* width_bias */ 2,
2768 /* adjust_size */ 0,
2769 /* adjust_crop */ 0);
2770 if (0 != retval)
2771 return retval;
2772 }
2773
2774 /* ok, accept it */
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002775 btv->fbuf.base = fb->base;
2776 btv->fbuf.fmt.width = fb->fmt.width;
2777 btv->fbuf.fmt.height = fb->fmt.height;
2778 if (0 != fb->fmt.bytesperline)
2779 btv->fbuf.fmt.bytesperline = fb->fmt.bytesperline;
2780 else
2781 btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fmt->depth/8;
2782
2783 retval = 0;
2784 fh->ovfmt = fmt;
2785 btv->init.ovfmt = fmt;
2786 if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
2787 fh->ov.w.left = 0;
2788 fh->ov.w.top = 0;
2789 fh->ov.w.width = fb->fmt.width;
2790 fh->ov.w.height = fb->fmt.height;
2791 btv->init.ov.w.width = fb->fmt.width;
2792 btv->init.ov.w.height = fb->fmt.height;
2793 kfree(fh->ov.clips);
2794 fh->ov.clips = NULL;
2795 fh->ov.nclips = 0;
2796
2797 if (check_btres(fh, RESOURCE_OVERLAY)) {
2798 struct bttv_buffer *new;
2799
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03002800 new = videobuf_sg_alloc(sizeof(*new));
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002801 new->crop = btv->crop[!!fh->do_crop].rect;
2802 bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
2803 retval = bttv_switch_overlay(btv, fh, new);
2804 }
2805 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002806 return retval;
2807}
2808
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002809static int bttv_reqbufs(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002810 struct v4l2_requestbuffers *p)
2811{
2812 struct bttv_fh *fh = priv;
2813 return videobuf_reqbufs(bttv_queue(fh), p);
2814}
2815
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002816static int bttv_querybuf(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002817 struct v4l2_buffer *b)
2818{
2819 struct bttv_fh *fh = priv;
2820 return videobuf_querybuf(bttv_queue(fh), b);
2821}
2822
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002823static int bttv_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002824{
2825 struct bttv_fh *fh = priv;
2826 struct bttv *btv = fh->btv;
2827 int res = bttv_resource(fh);
2828
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002829 if (!check_alloc_btres_lock(btv, fh, res))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002830 return -EBUSY;
2831
2832 return videobuf_qbuf(bttv_queue(fh), b);
2833}
2834
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002835static int bttv_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002836{
2837 struct bttv_fh *fh = priv;
2838 return videobuf_dqbuf(bttv_queue(fh), b,
2839 file->f_flags & O_NONBLOCK);
2840}
2841
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002842static int bttv_streamon(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002843 enum v4l2_buf_type type)
2844{
2845 struct bttv_fh *fh = priv;
2846 struct bttv *btv = fh->btv;
2847 int res = bttv_resource(fh);
2848
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002849 if (!check_alloc_btres_lock(btv, fh, res))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002850 return -EBUSY;
2851 return videobuf_streamon(bttv_queue(fh));
2852}
2853
2854
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002855static int bttv_streamoff(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002856 enum v4l2_buf_type type)
2857{
2858 struct bttv_fh *fh = priv;
2859 struct bttv *btv = fh->btv;
2860 int retval;
2861 int res = bttv_resource(fh);
2862
2863
2864 retval = videobuf_streamoff(bttv_queue(fh));
2865 if (retval < 0)
2866 return retval;
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002867 free_btres_lock(btv, fh, res);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002868 return 0;
2869}
2870
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002871static int bttv_queryctrl(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002872 struct v4l2_queryctrl *c)
2873{
2874 struct bttv_fh *fh = priv;
2875 struct bttv *btv = fh->btv;
2876 const struct v4l2_queryctrl *ctrl;
2877
2878 if ((c->id < V4L2_CID_BASE ||
2879 c->id >= V4L2_CID_LASTP1) &&
2880 (c->id < V4L2_CID_PRIVATE_BASE ||
2881 c->id >= V4L2_CID_PRIVATE_LASTP1))
2882 return -EINVAL;
2883
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002884 if (!btv->volume_gpio && (c->id == V4L2_CID_AUDIO_VOLUME))
2885 *c = no_ctl;
2886 else {
2887 ctrl = ctrl_by_id(c->id);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002888
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002889 *c = (NULL != ctrl) ? *ctrl : no_ctl;
2890 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002891
2892 return 0;
2893}
2894
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002895static int bttv_g_parm(struct file *file, void *f,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002896 struct v4l2_streamparm *parm)
2897{
2898 struct bttv_fh *fh = f;
2899 struct bttv *btv = fh->btv;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002900
Trent Piepho51f0b8d52009-03-04 01:21:02 -03002901 v4l2_video_std_frame_period(bttv_tvnorms[btv->tvnorm].v4l2_id,
2902 &parm->parm.capture.timeperframe);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002903
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002904 return 0;
2905}
2906
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002907static int bttv_g_tuner(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002908 struct v4l2_tuner *t)
2909{
2910 struct bttv_fh *fh = priv;
2911 struct bttv *btv = fh->btv;
2912
Trent Piephoabb03622009-01-28 21:32:59 -03002913 if (btv->tuner_type == TUNER_ABSENT)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002914 return -EINVAL;
2915 if (0 != t->index)
2916 return -EINVAL;
2917
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002918 t->rxsubchans = V4L2_TUNER_SUB_MONO;
Hans Verkuil859f0272009-03-28 08:29:00 -03002919 bttv_call_all(btv, tuner, g_tuner, t);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002920 strcpy(t->name, "Television");
2921 t->capability = V4L2_TUNER_CAP_NORM;
2922 t->type = V4L2_TUNER_ANALOG_TV;
2923 if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)
2924 t->signal = 0xffff;
2925
2926 if (btv->audio_mode_gpio)
2927 btv->audio_mode_gpio(btv, t, 0);
2928
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002929 return 0;
2930}
2931
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002932static int bttv_g_priority(struct file *file, void *f, enum v4l2_priority *p)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002933{
2934 struct bttv_fh *fh = f;
2935 struct bttv *btv = fh->btv;
2936
2937 *p = v4l2_prio_max(&btv->prio);
2938
2939 return 0;
2940}
2941
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002942static int bttv_s_priority(struct file *file, void *f,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002943 enum v4l2_priority prio)
2944{
2945 struct bttv_fh *fh = f;
2946 struct bttv *btv = fh->btv;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002947 int rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002948
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002949 rc = v4l2_prio_change(&btv->prio, &fh->prio, prio);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002950
2951 return rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002952}
2953
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002954static int bttv_cropcap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002955 struct v4l2_cropcap *cap)
2956{
2957 struct bttv_fh *fh = priv;
2958 struct bttv *btv = fh->btv;
2959
2960 if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
2961 cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
2962 return -EINVAL;
2963
2964 *cap = bttv_tvnorms[btv->tvnorm].cropcap;
2965
2966 return 0;
2967}
2968
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002969static int bttv_g_crop(struct file *file, void *f, struct v4l2_crop *crop)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002970{
2971 struct bttv_fh *fh = f;
2972 struct bttv *btv = fh->btv;
2973
2974 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
2975 crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
2976 return -EINVAL;
2977
2978 /* No fh->do_crop = 1; because btv->crop[1] may be
2979 inconsistent with fh->width or fh->height and apps
2980 do not expect a change here. */
2981
2982 crop->c = btv->crop[!!fh->do_crop].rect;
2983
2984 return 0;
2985}
2986
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002987static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002988{
2989 struct bttv_fh *fh = f;
2990 struct bttv *btv = fh->btv;
2991 const struct v4l2_rect *b;
2992 int retval;
2993 struct bttv_crop c;
2994 __s32 b_left;
2995 __s32 b_top;
2996 __s32 b_right;
2997 __s32 b_bottom;
2998
2999 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
3000 crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
3001 return -EINVAL;
3002
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003003 /* Make sure tvnorm, vbi_end and the current cropping
3004 parameters remain consistent until we're done. Note
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003005 read() may change vbi_end in check_alloc_btres_lock(). */
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003006 retval = v4l2_prio_check(&btv->prio, fh->prio);
3007 if (0 != retval) {
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003008 return retval;
3009 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003010
3011 retval = -EBUSY;
3012
3013 if (locked_btres(fh->btv, VIDEO_RESOURCES)) {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003014 return retval;
3015 }
3016
3017 b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
3018
3019 b_left = b->left;
3020 b_right = b_left + b->width;
3021 b_bottom = b->top + b->height;
3022
3023 b_top = max(b->top, btv->vbi_end);
3024 if (b_top + 32 >= b_bottom) {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003025 return retval;
3026 }
3027
3028 /* Min. scaled size 48 x 32. */
3029 c.rect.left = clamp(crop->c.left, b_left, b_right - 48);
3030 c.rect.left = min(c.rect.left, (__s32) MAX_HDELAY);
3031
3032 c.rect.width = clamp(crop->c.width,
3033 48, b_right - c.rect.left);
3034
3035 c.rect.top = clamp(crop->c.top, b_top, b_bottom - 32);
3036 /* Top and height must be a multiple of two. */
3037 c.rect.top = (c.rect.top + 1) & ~1;
3038
3039 c.rect.height = clamp(crop->c.height,
3040 32, b_bottom - c.rect.top);
3041 c.rect.height = (c.rect.height + 1) & ~1;
3042
3043 bttv_crop_calc_limits(&c);
3044
3045 btv->crop[1] = c;
3046
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003047 fh->do_crop = 1;
3048
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003049 if (fh->width < c.min_scaled_width) {
3050 fh->width = c.min_scaled_width;
3051 btv->init.width = c.min_scaled_width;
3052 } else if (fh->width > c.max_scaled_width) {
3053 fh->width = c.max_scaled_width;
3054 btv->init.width = c.max_scaled_width;
3055 }
3056
3057 if (fh->height < c.min_scaled_height) {
3058 fh->height = c.min_scaled_height;
3059 btv->init.height = c.min_scaled_height;
3060 } else if (fh->height > c.max_scaled_height) {
3061 fh->height = c.max_scaled_height;
3062 btv->init.height = c.max_scaled_height;
3063 }
3064
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003065 return 0;
3066}
3067
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003068static int bttv_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003069{
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03003070 if (unlikely(a->index))
3071 return -EINVAL;
3072
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003073 strcpy(a->name, "audio");
3074 return 0;
3075}
3076
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003077static int bttv_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003078{
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03003079 if (unlikely(a->index))
3080 return -EINVAL;
3081
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003082 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003083}
3084
3085static ssize_t bttv_read(struct file *file, char __user *data,
3086 size_t count, loff_t *ppos)
3087{
3088 struct bttv_fh *fh = file->private_data;
3089 int retval = 0;
3090
3091 if (fh->btv->errors)
3092 bttv_reinit_bt848(fh->btv);
3093 dprintk("bttv%d: read count=%d type=%s\n",
3094 fh->btv->c.nr,(int)count,v4l2_type_names[fh->type]);
3095
3096 switch (fh->type) {
3097 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003098 if (!check_alloc_btres_lock(fh->btv, fh, RESOURCE_VIDEO_READ)) {
Michael Schimeke5bd0262007-01-18 16:17:39 -03003099 /* VIDEO_READ in use by another fh,
3100 or VIDEO_STREAM by any fh. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003101 return -EBUSY;
Michael Schimeke5bd0262007-01-18 16:17:39 -03003102 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003103 retval = videobuf_read_one(&fh->cap, data, count, ppos,
3104 file->f_flags & O_NONBLOCK);
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003105 free_btres_lock(fh->btv, fh, RESOURCE_VIDEO_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003106 break;
3107 case V4L2_BUF_TYPE_VBI_CAPTURE:
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003108 if (!check_alloc_btres_lock(fh->btv,fh,RESOURCE_VBI))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003109 return -EBUSY;
3110 retval = videobuf_read_stream(&fh->vbi, data, count, ppos, 1,
3111 file->f_flags & O_NONBLOCK);
3112 break;
3113 default:
3114 BUG();
3115 }
3116 return retval;
3117}
3118
3119static unsigned int bttv_poll(struct file *file, poll_table *wait)
3120{
3121 struct bttv_fh *fh = file->private_data;
3122 struct bttv_buffer *buf;
3123 enum v4l2_field field;
Figo.zhang9fd64182009-06-16 13:31:29 -03003124 unsigned int rc = POLLERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003125
3126 if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003127 if (!check_alloc_btres_lock(fh->btv,fh,RESOURCE_VBI))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128 return POLLERR;
3129 return videobuf_poll_stream(file, &fh->vbi, wait);
3130 }
3131
Michael Schimeke5bd0262007-01-18 16:17:39 -03003132 if (check_btres(fh,RESOURCE_VIDEO_STREAM)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003133 /* streaming capture */
3134 if (list_empty(&fh->cap.stream))
Figo.zhang9fd64182009-06-16 13:31:29 -03003135 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003136 buf = list_entry(fh->cap.stream.next,struct bttv_buffer,vb.stream);
3137 } else {
3138 /* read() capture */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003139 if (NULL == fh->cap.read_buf) {
3140 /* need to capture a new frame */
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03003141 if (locked_btres(fh->btv,RESOURCE_VIDEO_STREAM))
3142 goto err;
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03003143 fh->cap.read_buf = videobuf_sg_alloc(fh->cap.msize);
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03003144 if (NULL == fh->cap.read_buf)
3145 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003146 fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR;
3147 field = videobuf_next_field(&fh->cap);
3148 if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,field)) {
Nickolay V. Shmyrev50ab5ed2005-12-01 00:51:32 -08003149 kfree (fh->cap.read_buf);
3150 fh->cap.read_buf = NULL;
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03003151 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003152 }
3153 fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf);
3154 fh->cap.read_off = 0;
3155 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003156 buf = (struct bttv_buffer*)fh->cap.read_buf;
3157 }
3158
3159 poll_wait(file, &buf->vb.done, wait);
Brandon Philips0fc06862007-11-06 20:02:36 -03003160 if (buf->vb.state == VIDEOBUF_DONE ||
3161 buf->vb.state == VIDEOBUF_ERROR)
Figo.zhang9fd64182009-06-16 13:31:29 -03003162 rc = POLLIN|POLLRDNORM;
3163 else
3164 rc = 0;
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03003165err:
Figo.zhang9fd64182009-06-16 13:31:29 -03003166 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003167}
3168
Hans Verkuilbec43662008-12-30 06:58:20 -03003169static int bttv_open(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003170{
Laurent Pinchart50462eb2009-12-10 11:47:13 -02003171 struct video_device *vdev = video_devdata(file);
Trent Piepho4b10d3b2009-01-28 21:32:59 -03003172 struct bttv *btv = video_drvdata(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003173 struct bttv_fh *fh;
3174 enum v4l2_buf_type type = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003175
Laurent Pinchart50462eb2009-12-10 11:47:13 -02003176 dprintk(KERN_DEBUG "bttv: open dev=%s\n", video_device_node_name(vdev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003177
Laurent Pinchart327ae592009-11-27 13:57:55 -03003178 if (vdev->vfl_type == VFL_TYPE_GRABBER) {
Trent Piepho4b10d3b2009-01-28 21:32:59 -03003179 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Laurent Pinchart327ae592009-11-27 13:57:55 -03003180 } else if (vdev->vfl_type == VFL_TYPE_VBI) {
Trent Piepho4b10d3b2009-01-28 21:32:59 -03003181 type = V4L2_BUF_TYPE_VBI_CAPTURE;
3182 } else {
3183 WARN_ON(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003184 return -ENODEV;
Hans Verkuild56dc612008-07-30 08:43:36 -03003185 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003186
3187 dprintk(KERN_DEBUG "bttv%d: open called (type=%s)\n",
3188 btv->c.nr,v4l2_type_names[type]);
3189
3190 /* allocate per filehandle data */
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003191 fh = kmalloc(sizeof(*fh), GFP_KERNEL);
3192 if (unlikely(!fh))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003193 return -ENOMEM;
3194 file->private_data = fh;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003195
Linus Torvalds1da177e2005-04-16 15:20:36 -07003196 *fh = btv->init;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003197
Linus Torvalds1da177e2005-04-16 15:20:36 -07003198 fh->type = type;
3199 fh->ov.setup_ok = 0;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003200
Hans Verkuilffb48772010-05-01 08:03:24 -03003201 v4l2_prio_open(&btv->prio, &fh->prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003202
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03003203 videobuf_queue_sg_init(&fh->cap, &bttv_video_qops,
3204 &btv->c.pci->dev, &btv->s_lock,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003205 V4L2_BUF_TYPE_VIDEO_CAPTURE,
3206 V4L2_FIELD_INTERLACED,
3207 sizeof(struct bttv_buffer),
Mauro Carvalho Chehab587f0d52010-12-15 18:45:42 -03003208 fh, &btv->lock);
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03003209 videobuf_queue_sg_init(&fh->vbi, &bttv_vbi_qops,
3210 &btv->c.pci->dev, &btv->s_lock,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003211 V4L2_BUF_TYPE_VBI_CAPTURE,
3212 V4L2_FIELD_SEQ_TB,
3213 sizeof(struct bttv_buffer),
Mauro Carvalho Chehab587f0d52010-12-15 18:45:42 -03003214 fh, &btv->lock);
Nickolay V. Shmyrev302f61a2007-10-26 10:53:21 -03003215 set_tvnorm(btv,btv->tvnorm);
Mauro Carvalho Chehabb46a9c82008-08-05 10:12:35 -03003216 set_input(btv, btv->input, btv->tvnorm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003217
3218 btv->users++;
Michael Schimeke5bd0262007-01-18 16:17:39 -03003219
3220 /* The V4L2 spec requires one global set of cropping parameters
3221 which only change on request. These are stored in btv->crop[1].
3222 However for compatibility with V4L apps and cropping unaware
3223 V4L2 apps we now reset the cropping parameters as seen through
3224 this fh, which is to say VIDIOC_G_CROP and scaling limit checks
3225 will use btv->crop[0], the default cropping parameters for the
3226 current video standard, and VIDIOC_S_FMT will not implicitely
3227 change the cropping parameters until VIDIOC_S_CROP has been
3228 called. */
3229 fh->do_crop = !reset_crop; /* module parameter */
3230
3231 /* Likewise there should be one global set of VBI capture
3232 parameters, but for compatibility with V4L apps and earlier
3233 driver versions each fh has its own parameters. */
3234 bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm);
3235
Linus Torvalds1da177e2005-04-16 15:20:36 -07003236 bttv_field_count(btv);
3237 return 0;
3238}
3239
Hans Verkuilbec43662008-12-30 06:58:20 -03003240static int bttv_release(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003241{
3242 struct bttv_fh *fh = file->private_data;
3243 struct bttv *btv = fh->btv;
3244
3245 /* turn off overlay */
3246 if (check_btres(fh, RESOURCE_OVERLAY))
3247 bttv_switch_overlay(btv,fh,NULL);
3248
3249 /* stop video capture */
Michael Schimeke5bd0262007-01-18 16:17:39 -03003250 if (check_btres(fh, RESOURCE_VIDEO_STREAM)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003251 videobuf_streamoff(&fh->cap);
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003252 free_btres_lock(btv,fh,RESOURCE_VIDEO_STREAM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003253 }
3254 if (fh->cap.read_buf) {
3255 buffer_release(&fh->cap,fh->cap.read_buf);
3256 kfree(fh->cap.read_buf);
3257 }
Michael Schimeke5bd0262007-01-18 16:17:39 -03003258 if (check_btres(fh, RESOURCE_VIDEO_READ)) {
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003259 free_btres_lock(btv, fh, RESOURCE_VIDEO_READ);
Michael Schimeke5bd0262007-01-18 16:17:39 -03003260 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003261
3262 /* stop vbi capture */
3263 if (check_btres(fh, RESOURCE_VBI)) {
Brandon Philips053fcb62007-11-13 20:11:26 -03003264 videobuf_stop(&fh->vbi);
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003265 free_btres_lock(btv,fh,RESOURCE_VBI);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003266 }
3267
3268 /* free stuff */
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003269
Linus Torvalds1da177e2005-04-16 15:20:36 -07003270 videobuf_mmap_free(&fh->cap);
3271 videobuf_mmap_free(&fh->vbi);
Hans Verkuilffb48772010-05-01 08:03:24 -03003272 v4l2_prio_close(&btv->prio, fh->prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003273 file->private_data = NULL;
3274 kfree(fh);
3275
3276 btv->users--;
3277 bttv_field_count(btv);
Mauro Carvalho Chehabb46a9c82008-08-05 10:12:35 -03003278
3279 if (!btv->users)
3280 audio_mute(btv, 1);
3281
Linus Torvalds1da177e2005-04-16 15:20:36 -07003282 return 0;
3283}
3284
3285static int
3286bttv_mmap(struct file *file, struct vm_area_struct *vma)
3287{
3288 struct bttv_fh *fh = file->private_data;
3289
3290 dprintk("bttv%d: mmap type=%s 0x%lx+%ld\n",
3291 fh->btv->c.nr, v4l2_type_names[fh->type],
3292 vma->vm_start, vma->vm_end - vma->vm_start);
3293 return videobuf_mmap_mapper(bttv_queue(fh),vma);
3294}
3295
Hans Verkuilbec43662008-12-30 06:58:20 -03003296static const struct v4l2_file_operations bttv_fops =
Linus Torvalds1da177e2005-04-16 15:20:36 -07003297{
Mauro Carvalho Chehab8979e9d2010-09-15 08:22:09 -03003298 .owner = THIS_MODULE,
3299 .open = bttv_open,
3300 .release = bttv_release,
3301 .unlocked_ioctl = video_ioctl2,
3302 .read = bttv_read,
3303 .mmap = bttv_mmap,
3304 .poll = bttv_poll,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003305};
3306
Hans Verkuila3998102008-07-21 02:57:38 -03003307static const struct v4l2_ioctl_ops bttv_ioctl_ops = {
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003308 .vidioc_querycap = bttv_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03003309 .vidioc_enum_fmt_vid_cap = bttv_enum_fmt_vid_cap,
3310 .vidioc_g_fmt_vid_cap = bttv_g_fmt_vid_cap,
3311 .vidioc_try_fmt_vid_cap = bttv_try_fmt_vid_cap,
3312 .vidioc_s_fmt_vid_cap = bttv_s_fmt_vid_cap,
3313 .vidioc_enum_fmt_vid_overlay = bttv_enum_fmt_vid_overlay,
3314 .vidioc_g_fmt_vid_overlay = bttv_g_fmt_vid_overlay,
3315 .vidioc_try_fmt_vid_overlay = bttv_try_fmt_vid_overlay,
3316 .vidioc_s_fmt_vid_overlay = bttv_s_fmt_vid_overlay,
Hans Verkuil78b526a2008-05-28 12:16:41 -03003317 .vidioc_g_fmt_vbi_cap = bttv_g_fmt_vbi_cap,
3318 .vidioc_try_fmt_vbi_cap = bttv_try_fmt_vbi_cap,
3319 .vidioc_s_fmt_vbi_cap = bttv_s_fmt_vbi_cap,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003320 .vidioc_g_audio = bttv_g_audio,
3321 .vidioc_s_audio = bttv_s_audio,
3322 .vidioc_cropcap = bttv_cropcap,
3323 .vidioc_reqbufs = bttv_reqbufs,
3324 .vidioc_querybuf = bttv_querybuf,
3325 .vidioc_qbuf = bttv_qbuf,
3326 .vidioc_dqbuf = bttv_dqbuf,
3327 .vidioc_s_std = bttv_s_std,
3328 .vidioc_enum_input = bttv_enum_input,
3329 .vidioc_g_input = bttv_g_input,
3330 .vidioc_s_input = bttv_s_input,
3331 .vidioc_queryctrl = bttv_queryctrl,
3332 .vidioc_g_ctrl = bttv_g_ctrl,
3333 .vidioc_s_ctrl = bttv_s_ctrl,
3334 .vidioc_streamon = bttv_streamon,
3335 .vidioc_streamoff = bttv_streamoff,
3336 .vidioc_g_tuner = bttv_g_tuner,
3337 .vidioc_s_tuner = bttv_s_tuner,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003338 .vidioc_g_crop = bttv_g_crop,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003339 .vidioc_s_crop = bttv_s_crop,
3340 .vidioc_g_fbuf = bttv_g_fbuf,
3341 .vidioc_s_fbuf = bttv_s_fbuf,
3342 .vidioc_overlay = bttv_overlay,
3343 .vidioc_g_priority = bttv_g_priority,
3344 .vidioc_s_priority = bttv_s_priority,
3345 .vidioc_g_parm = bttv_g_parm,
3346 .vidioc_g_frequency = bttv_g_frequency,
3347 .vidioc_s_frequency = bttv_s_frequency,
3348 .vidioc_log_status = bttv_log_status,
3349 .vidioc_querystd = bttv_querystd,
Zoltan Devai43846832008-01-14 13:24:38 -03003350#ifdef CONFIG_VIDEO_ADV_DEBUG
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003351 .vidioc_g_register = bttv_g_register,
3352 .vidioc_s_register = bttv_s_register,
Zoltan Devai43846832008-01-14 13:24:38 -03003353#endif
Hans Verkuila3998102008-07-21 02:57:38 -03003354};
3355
3356static struct video_device bttv_video_template = {
3357 .fops = &bttv_fops,
Hans Verkuila3998102008-07-21 02:57:38 -03003358 .ioctl_ops = &bttv_ioctl_ops,
3359 .tvnorms = BTTV_NORMS,
3360 .current_norm = V4L2_STD_PAL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003361};
3362
Linus Torvalds1da177e2005-04-16 15:20:36 -07003363/* ----------------------------------------------------------------------- */
3364/* radio interface */
3365
Hans Verkuilbec43662008-12-30 06:58:20 -03003366static int radio_open(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003367{
Laurent Pinchart50462eb2009-12-10 11:47:13 -02003368 struct video_device *vdev = video_devdata(file);
Trent Piepho4b10d3b2009-01-28 21:32:59 -03003369 struct bttv *btv = video_drvdata(file);
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003370 struct bttv_fh *fh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003371
Laurent Pinchart50462eb2009-12-10 11:47:13 -02003372 dprintk("bttv: open dev=%s\n", video_device_node_name(vdev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003373
Linus Torvalds1da177e2005-04-16 15:20:36 -07003374 dprintk("bttv%d: open called (radio)\n",btv->c.nr);
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003375
3376 /* allocate per filehandle data */
3377 fh = kmalloc(sizeof(*fh), GFP_KERNEL);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003378 if (unlikely(!fh))
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003379 return -ENOMEM;
3380 file->private_data = fh;
3381 *fh = btv->init;
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003382
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003383 v4l2_prio_open(&btv->prio, &fh->prio);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003384
Linus Torvalds1da177e2005-04-16 15:20:36 -07003385 btv->radio_user++;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003386
Hans Verkuil859f0272009-03-28 08:29:00 -03003387 bttv_call_all(btv, tuner, s_radio);
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03003388 audio_input(btv,TVAUDIO_INPUT_RADIO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003389
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003390 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003391}
3392
Hans Verkuilbec43662008-12-30 06:58:20 -03003393static int radio_release(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003394{
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003395 struct bttv_fh *fh = file->private_data;
3396 struct bttv *btv = fh->btv;
Hans Verkuilb9218f22010-12-27 12:22:46 -03003397 struct saa6588_command cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003398
Hans Verkuilffb48772010-05-01 08:03:24 -03003399 v4l2_prio_close(&btv->prio, fh->prio);
Robert Fitzsimonsb9bc07a2008-04-10 09:40:31 -03003400 file->private_data = NULL;
3401 kfree(fh);
3402
Linus Torvalds1da177e2005-04-16 15:20:36 -07003403 btv->radio_user--;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003404
Hans Verkuilb9218f22010-12-27 12:22:46 -03003405 bttv_call_all(btv, core, ioctl, SAA6588_CMD_CLOSE, &cmd);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003406
Linus Torvalds1da177e2005-04-16 15:20:36 -07003407 return 0;
3408}
3409
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003410static int radio_querycap(struct file *file, void *priv,
3411 struct v4l2_capability *cap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003412{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003413 struct bttv_fh *fh = priv;
3414 struct bttv *btv = fh->btv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003415
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003416 strcpy(cap->driver, "bttv");
3417 strlcpy(cap->card, btv->radio_dev->name, sizeof(cap->card));
3418 sprintf(cap->bus_info, "PCI:%s", pci_name(btv->c.pci));
3419 cap->version = BTTV_VERSION_CODE;
3420 cap->capabilities = V4L2_CAP_TUNER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003421
Linus Torvalds1da177e2005-04-16 15:20:36 -07003422 return 0;
3423}
3424
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003425static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003426{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003427 struct bttv_fh *fh = priv;
3428 struct bttv *btv = fh->btv;
3429
Trent Piephoabb03622009-01-28 21:32:59 -03003430 if (btv->tuner_type == TUNER_ABSENT)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003431 return -EINVAL;
3432 if (0 != t->index)
3433 return -EINVAL;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003434 strcpy(t->name, "Radio");
3435 t->type = V4L2_TUNER_RADIO;
3436
Hans Verkuil859f0272009-03-28 08:29:00 -03003437 bttv_call_all(btv, tuner, g_tuner, t);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003438
3439 if (btv->audio_mode_gpio)
3440 btv->audio_mode_gpio(btv, t, 0);
3441
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003442 return 0;
3443}
3444
3445static int radio_enum_input(struct file *file, void *priv,
3446 struct v4l2_input *i)
3447{
3448 if (i->index != 0)
3449 return -EINVAL;
3450
3451 strcpy(i->name, "Radio");
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03003452 i->type = V4L2_INPUT_TYPE_TUNER;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003453
3454 return 0;
3455}
3456
3457static int radio_g_audio(struct file *file, void *priv,
3458 struct v4l2_audio *a)
3459{
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03003460 if (unlikely(a->index))
Cyrill Gorcunov1a002eb2008-04-01 17:49:13 -03003461 return -EINVAL;
3462
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003463 strcpy(a->name, "Radio");
Cyrill Gorcunov1a002eb2008-04-01 17:49:13 -03003464
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003465 return 0;
3466}
3467
3468static int radio_s_tuner(struct file *file, void *priv,
3469 struct v4l2_tuner *t)
3470{
3471 struct bttv_fh *fh = priv;
3472 struct bttv *btv = fh->btv;
3473
3474 if (0 != t->index)
3475 return -EINVAL;
3476
Hans Verkuila024c1a2011-06-12 07:02:43 -03003477 bttv_call_all(btv, tuner, s_tuner, t);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003478 return 0;
3479}
3480
3481static int radio_s_audio(struct file *file, void *priv,
3482 struct v4l2_audio *a)
3483{
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03003484 if (unlikely(a->index))
3485 return -EINVAL;
3486
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003487 return 0;
3488}
3489
3490static int radio_s_input(struct file *filp, void *priv, unsigned int i)
3491{
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03003492 if (unlikely(i))
3493 return -EINVAL;
3494
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003495 return 0;
3496}
3497
3498static int radio_s_std(struct file *file, void *fh, v4l2_std_id *norm)
3499{
3500 return 0;
3501}
3502
3503static int radio_queryctrl(struct file *file, void *priv,
3504 struct v4l2_queryctrl *c)
3505{
3506 const struct v4l2_queryctrl *ctrl;
3507
3508 if (c->id < V4L2_CID_BASE ||
3509 c->id >= V4L2_CID_LASTP1)
3510 return -EINVAL;
3511
3512 if (c->id == V4L2_CID_AUDIO_MUTE) {
3513 ctrl = ctrl_by_id(c->id);
3514 *c = *ctrl;
3515 } else
3516 *c = no_ctl;
3517
3518 return 0;
3519}
3520
3521static int radio_g_input(struct file *filp, void *priv, unsigned int *i)
3522{
3523 *i = 0;
3524 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003525}
3526
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003527static ssize_t radio_read(struct file *file, char __user *data,
3528 size_t count, loff_t *ppos)
3529{
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003530 struct bttv_fh *fh = file->private_data;
3531 struct bttv *btv = fh->btv;
Hans Verkuilb9218f22010-12-27 12:22:46 -03003532 struct saa6588_command cmd;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003533 cmd.block_count = count/3;
3534 cmd.buffer = data;
3535 cmd.instance = file;
3536 cmd.result = -ENODEV;
3537
Hans Verkuilb9218f22010-12-27 12:22:46 -03003538 bttv_call_all(btv, core, ioctl, SAA6588_CMD_READ, &cmd);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003539
3540 return cmd.result;
3541}
3542
3543static unsigned int radio_poll(struct file *file, poll_table *wait)
3544{
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003545 struct bttv_fh *fh = file->private_data;
3546 struct bttv *btv = fh->btv;
Hans Verkuilb9218f22010-12-27 12:22:46 -03003547 struct saa6588_command cmd;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003548 cmd.instance = file;
3549 cmd.event_list = wait;
3550 cmd.result = -ENODEV;
Hans Verkuilb9218f22010-12-27 12:22:46 -03003551 bttv_call_all(btv, core, ioctl, SAA6588_CMD_POLL, &cmd);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003552
3553 return cmd.result;
3554}
3555
Hans Verkuilbec43662008-12-30 06:58:20 -03003556static const struct v4l2_file_operations radio_fops =
Linus Torvalds1da177e2005-04-16 15:20:36 -07003557{
3558 .owner = THIS_MODULE,
3559 .open = radio_open,
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003560 .read = radio_read,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003561 .release = radio_release,
Mauro Carvalho Chehab587f0d52010-12-15 18:45:42 -03003562 .unlocked_ioctl = video_ioctl2,
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003563 .poll = radio_poll,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003564};
3565
Hans Verkuila3998102008-07-21 02:57:38 -03003566static const struct v4l2_ioctl_ops radio_ioctl_ops = {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003567 .vidioc_querycap = radio_querycap,
3568 .vidioc_g_tuner = radio_g_tuner,
3569 .vidioc_enum_input = radio_enum_input,
3570 .vidioc_g_audio = radio_g_audio,
3571 .vidioc_s_tuner = radio_s_tuner,
3572 .vidioc_s_audio = radio_s_audio,
3573 .vidioc_s_input = radio_s_input,
3574 .vidioc_s_std = radio_s_std,
3575 .vidioc_queryctrl = radio_queryctrl,
3576 .vidioc_g_input = radio_g_input,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003577 .vidioc_g_ctrl = bttv_g_ctrl,
3578 .vidioc_s_ctrl = bttv_s_ctrl,
3579 .vidioc_g_frequency = bttv_g_frequency,
3580 .vidioc_s_frequency = bttv_s_frequency,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003581};
3582
Hans Verkuila3998102008-07-21 02:57:38 -03003583static struct video_device radio_template = {
3584 .fops = &radio_fops,
Hans Verkuila3998102008-07-21 02:57:38 -03003585 .ioctl_ops = &radio_ioctl_ops,
3586};
3587
Linus Torvalds1da177e2005-04-16 15:20:36 -07003588/* ----------------------------------------------------------------------- */
3589/* some debug code */
3590
Adrian Bunk408b6642005-05-01 08:59:29 -07003591static int bttv_risc_decode(u32 risc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003592{
3593 static char *instr[16] = {
3594 [ BT848_RISC_WRITE >> 28 ] = "write",
3595 [ BT848_RISC_SKIP >> 28 ] = "skip",
3596 [ BT848_RISC_WRITEC >> 28 ] = "writec",
3597 [ BT848_RISC_JUMP >> 28 ] = "jump",
3598 [ BT848_RISC_SYNC >> 28 ] = "sync",
3599 [ BT848_RISC_WRITE123 >> 28 ] = "write123",
3600 [ BT848_RISC_SKIP123 >> 28 ] = "skip123",
3601 [ BT848_RISC_WRITE1S23 >> 28 ] = "write1s23",
3602 };
3603 static int incr[16] = {
3604 [ BT848_RISC_WRITE >> 28 ] = 2,
3605 [ BT848_RISC_JUMP >> 28 ] = 2,
3606 [ BT848_RISC_SYNC >> 28 ] = 2,
3607 [ BT848_RISC_WRITE123 >> 28 ] = 5,
3608 [ BT848_RISC_SKIP123 >> 28 ] = 2,
3609 [ BT848_RISC_WRITE1S23 >> 28 ] = 3,
3610 };
3611 static char *bits[] = {
3612 "be0", "be1", "be2", "be3/resync",
3613 "set0", "set1", "set2", "set3",
3614 "clr0", "clr1", "clr2", "clr3",
3615 "irq", "res", "eol", "sol",
3616 };
3617 int i;
3618
3619 printk("0x%08x [ %s", risc,
3620 instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
3621 for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
3622 if (risc & (1 << (i + 12)))
3623 printk(" %s",bits[i]);
3624 printk(" count=%d ]\n", risc & 0xfff);
3625 return incr[risc >> 28] ? incr[risc >> 28] : 1;
3626}
3627
Adrian Bunk408b6642005-05-01 08:59:29 -07003628static void bttv_risc_disasm(struct bttv *btv,
3629 struct btcx_riscmem *risc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003630{
3631 unsigned int i,j,n;
3632
3633 printk("%s: risc disasm: %p [dma=0x%08lx]\n",
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03003634 btv->c.v4l2_dev.name, risc->cpu, (unsigned long)risc->dma);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003635 for (i = 0; i < (risc->size >> 2); i += n) {
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03003636 printk("%s: 0x%lx: ", btv->c.v4l2_dev.name,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003637 (unsigned long)(risc->dma + (i<<2)));
Al Viro3aa71102008-06-22 14:20:09 -03003638 n = bttv_risc_decode(le32_to_cpu(risc->cpu[i]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003639 for (j = 1; j < n; j++)
3640 printk("%s: 0x%lx: 0x%08x [ arg #%d ]\n",
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03003641 btv->c.v4l2_dev.name, (unsigned long)(risc->dma + ((i+j)<<2)),
Linus Torvalds1da177e2005-04-16 15:20:36 -07003642 risc->cpu[i+j], j);
3643 if (0 == risc->cpu[i])
3644 break;
3645 }
3646}
3647
3648static void bttv_print_riscaddr(struct bttv *btv)
3649{
3650 printk(" main: %08Lx\n",
3651 (unsigned long long)btv->main.dma);
3652 printk(" vbi : o=%08Lx e=%08Lx\n",
3653 btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
3654 btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0);
3655 printk(" cap : o=%08Lx e=%08Lx\n",
3656 btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0,
3657 btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
3658 printk(" scr : o=%08Lx e=%08Lx\n",
3659 btv->screen ? (unsigned long long)btv->screen->top.dma : 0,
3660 btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0);
3661 bttv_risc_disasm(btv, &btv->main);
3662}
3663
3664/* ----------------------------------------------------------------------- */
3665/* irq handler */
3666
3667static char *irq_name[] = {
3668 "FMTCHG", // format change detected (525 vs. 625)
3669 "VSYNC", // vertical sync (new field)
3670 "HSYNC", // horizontal sync
3671 "OFLOW", // chroma/luma AGC overflow
3672 "HLOCK", // horizontal lock changed
3673 "VPRES", // video presence changed
3674 "6", "7",
3675 "I2CDONE", // hw irc operation finished
3676 "GPINT", // gpio port triggered irq
3677 "10",
3678 "RISCI", // risc instruction triggered irq
3679 "FBUS", // pixel data fifo dropped data (high pci bus latencies)
3680 "FTRGT", // pixel data fifo overrun
3681 "FDSR", // fifo data stream resyncronisation
3682 "PPERR", // parity error (data transfer)
3683 "RIPERR", // parity error (read risc instructions)
3684 "PABORT", // pci abort
3685 "OCERR", // risc instruction error
3686 "SCERR", // syncronisation error
3687};
3688
3689static void bttv_print_irqbits(u32 print, u32 mark)
3690{
3691 unsigned int i;
3692
3693 printk("bits:");
3694 for (i = 0; i < ARRAY_SIZE(irq_name); i++) {
3695 if (print & (1 << i))
3696 printk(" %s",irq_name[i]);
3697 if (mark & (1 << i))
3698 printk("*");
3699 }
3700}
3701
3702static void bttv_irq_debug_low_latency(struct bttv *btv, u32 rc)
3703{
3704 printk("bttv%d: irq: skipped frame [main=%lx,o_vbi=%lx,o_field=%lx,rc=%lx]\n",
3705 btv->c.nr,
3706 (unsigned long)btv->main.dma,
Al Viro3aa71102008-06-22 14:20:09 -03003707 (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_VBI+1]),
3708 (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_FIELD+1]),
Linus Torvalds1da177e2005-04-16 15:20:36 -07003709 (unsigned long)rc);
3710
3711 if (0 == (btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC)) {
3712 printk("bttv%d: Oh, there (temporarely?) is no input signal. "
3713 "Ok, then this is harmless, don't worry ;)\n",
3714 btv->c.nr);
3715 return;
3716 }
3717 printk("bttv%d: Uhm. Looks like we have unusual high IRQ latencies.\n",
3718 btv->c.nr);
3719 printk("bttv%d: Lets try to catch the culpit red-handed ...\n",
3720 btv->c.nr);
3721 dump_stack();
3722}
3723
3724static int
3725bttv_irq_next_video(struct bttv *btv, struct bttv_buffer_set *set)
3726{
3727 struct bttv_buffer *item;
3728
3729 memset(set,0,sizeof(*set));
3730
3731 /* capture request ? */
3732 if (!list_empty(&btv->capture)) {
3733 set->frame_irq = 1;
3734 item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
3735 if (V4L2_FIELD_HAS_TOP(item->vb.field))
3736 set->top = item;
3737 if (V4L2_FIELD_HAS_BOTTOM(item->vb.field))
3738 set->bottom = item;
3739
3740 /* capture request for other field ? */
3741 if (!V4L2_FIELD_HAS_BOTH(item->vb.field) &&
3742 (item->vb.queue.next != &btv->capture)) {
3743 item = list_entry(item->vb.queue.next, struct bttv_buffer, vb.queue);
Mike Isely66349b42009-09-21 12:09:08 -03003744 /* Mike Isely <isely@pobox.com> - Only check
3745 * and set up the bottom field in the logic
3746 * below. Don't ever do the top field. This
3747 * of course means that if we set up the
3748 * bottom field in the above code that we'll
3749 * actually skip a field. But that's OK.
3750 * Having processed only a single buffer this
3751 * time, then the next time around the first
3752 * available buffer should be for a top field.
3753 * That will then cause us here to set up a
3754 * top then a bottom field in the normal way.
3755 * The alternative to this understanding is
3756 * that we set up the second available buffer
3757 * as a top field, but that's out of order
3758 * since this driver always processes the top
3759 * field first - the effect will be the two
3760 * buffers being returned in the wrong order,
3761 * with the second buffer also being delayed
3762 * by one field time (owing to the fifo nature
3763 * of videobuf). Worse still, we'll be stuck
3764 * doing fields out of order now every time
3765 * until something else causes a field to be
3766 * dropped. By effectively forcing a field to
3767 * drop this way then we always get back into
3768 * sync within a single frame time. (Out of
3769 * order fields can screw up deinterlacing
3770 * algorithms.) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003771 if (!V4L2_FIELD_HAS_BOTH(item->vb.field)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003772 if (NULL == set->bottom &&
3773 V4L2_FIELD_BOTTOM == item->vb.field) {
3774 set->bottom = item;
3775 }
3776 if (NULL != set->top && NULL != set->bottom)
3777 set->top_irq = 2;
3778 }
3779 }
3780 }
3781
3782 /* screen overlay ? */
3783 if (NULL != btv->screen) {
3784 if (V4L2_FIELD_HAS_BOTH(btv->screen->vb.field)) {
3785 if (NULL == set->top && NULL == set->bottom) {
3786 set->top = btv->screen;
3787 set->bottom = btv->screen;
3788 }
3789 } else {
3790 if (V4L2_FIELD_TOP == btv->screen->vb.field &&
3791 NULL == set->top) {
3792 set->top = btv->screen;
3793 }
3794 if (V4L2_FIELD_BOTTOM == btv->screen->vb.field &&
3795 NULL == set->bottom) {
3796 set->bottom = btv->screen;
3797 }
3798 }
3799 }
3800
3801 dprintk("bttv%d: next set: top=%p bottom=%p [screen=%p,irq=%d,%d]\n",
3802 btv->c.nr,set->top, set->bottom,
3803 btv->screen,set->frame_irq,set->top_irq);
3804 return 0;
3805}
3806
3807static void
3808bttv_irq_wakeup_video(struct bttv *btv, struct bttv_buffer_set *wakeup,
3809 struct bttv_buffer_set *curr, unsigned int state)
3810{
3811 struct timeval ts;
3812
3813 do_gettimeofday(&ts);
3814
3815 if (wakeup->top == wakeup->bottom) {
3816 if (NULL != wakeup->top && curr->top != wakeup->top) {
3817 if (irq_debug > 1)
3818 printk("bttv%d: wakeup: both=%p\n",btv->c.nr,wakeup->top);
3819 wakeup->top->vb.ts = ts;
3820 wakeup->top->vb.field_count = btv->field_count;
3821 wakeup->top->vb.state = state;
3822 wake_up(&wakeup->top->vb.done);
3823 }
3824 } else {
3825 if (NULL != wakeup->top && curr->top != wakeup->top) {
3826 if (irq_debug > 1)
3827 printk("bttv%d: wakeup: top=%p\n",btv->c.nr,wakeup->top);
3828 wakeup->top->vb.ts = ts;
3829 wakeup->top->vb.field_count = btv->field_count;
3830 wakeup->top->vb.state = state;
3831 wake_up(&wakeup->top->vb.done);
3832 }
3833 if (NULL != wakeup->bottom && curr->bottom != wakeup->bottom) {
3834 if (irq_debug > 1)
3835 printk("bttv%d: wakeup: bottom=%p\n",btv->c.nr,wakeup->bottom);
3836 wakeup->bottom->vb.ts = ts;
3837 wakeup->bottom->vb.field_count = btv->field_count;
3838 wakeup->bottom->vb.state = state;
3839 wake_up(&wakeup->bottom->vb.done);
3840 }
3841 }
3842}
3843
3844static void
3845bttv_irq_wakeup_vbi(struct bttv *btv, struct bttv_buffer *wakeup,
3846 unsigned int state)
3847{
3848 struct timeval ts;
3849
3850 if (NULL == wakeup)
3851 return;
3852
3853 do_gettimeofday(&ts);
3854 wakeup->vb.ts = ts;
3855 wakeup->vb.field_count = btv->field_count;
3856 wakeup->vb.state = state;
3857 wake_up(&wakeup->vb.done);
3858}
3859
3860static void bttv_irq_timeout(unsigned long data)
3861{
3862 struct bttv *btv = (struct bttv *)data;
3863 struct bttv_buffer_set old,new;
3864 struct bttv_buffer *ovbi;
3865 struct bttv_buffer *item;
3866 unsigned long flags;
3867
3868 if (bttv_verbose) {
3869 printk(KERN_INFO "bttv%d: timeout: drop=%d irq=%d/%d, risc=%08x, ",
3870 btv->c.nr, btv->framedrop, btv->irq_me, btv->irq_total,
3871 btread(BT848_RISC_COUNT));
3872 bttv_print_irqbits(btread(BT848_INT_STAT),0);
3873 printk("\n");
3874 }
3875
3876 spin_lock_irqsave(&btv->s_lock,flags);
3877
3878 /* deactivate stuff */
3879 memset(&new,0,sizeof(new));
3880 old = btv->curr;
3881 ovbi = btv->cvbi;
3882 btv->curr = new;
3883 btv->cvbi = NULL;
3884 btv->loop_irq = 0;
3885 bttv_buffer_activate_video(btv, &new);
3886 bttv_buffer_activate_vbi(btv, NULL);
3887 bttv_set_dma(btv, 0);
3888
3889 /* wake up */
Brandon Philips0fc06862007-11-06 20:02:36 -03003890 bttv_irq_wakeup_video(btv, &old, &new, VIDEOBUF_ERROR);
3891 bttv_irq_wakeup_vbi(btv, ovbi, VIDEOBUF_ERROR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892
3893 /* cancel all outstanding capture / vbi requests */
3894 while (!list_empty(&btv->capture)) {
3895 item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
3896 list_del(&item->vb.queue);
Brandon Philips0fc06862007-11-06 20:02:36 -03003897 item->vb.state = VIDEOBUF_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003898 wake_up(&item->vb.done);
3899 }
3900 while (!list_empty(&btv->vcapture)) {
3901 item = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
3902 list_del(&item->vb.queue);
Brandon Philips0fc06862007-11-06 20:02:36 -03003903 item->vb.state = VIDEOBUF_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003904 wake_up(&item->vb.done);
3905 }
3906
3907 btv->errors++;
3908 spin_unlock_irqrestore(&btv->s_lock,flags);
3909}
3910
3911static void
3912bttv_irq_wakeup_top(struct bttv *btv)
3913{
3914 struct bttv_buffer *wakeup = btv->curr.top;
3915
3916 if (NULL == wakeup)
3917 return;
3918
3919 spin_lock(&btv->s_lock);
3920 btv->curr.top_irq = 0;
3921 btv->curr.top = NULL;
3922 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
3923
3924 do_gettimeofday(&wakeup->vb.ts);
3925 wakeup->vb.field_count = btv->field_count;
Brandon Philips0fc06862007-11-06 20:02:36 -03003926 wakeup->vb.state = VIDEOBUF_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003927 wake_up(&wakeup->vb.done);
3928 spin_unlock(&btv->s_lock);
3929}
3930
3931static inline int is_active(struct btcx_riscmem *risc, u32 rc)
3932{
3933 if (rc < risc->dma)
3934 return 0;
3935 if (rc > risc->dma + risc->size)
3936 return 0;
3937 return 1;
3938}
3939
3940static void
3941bttv_irq_switch_video(struct bttv *btv)
3942{
3943 struct bttv_buffer_set new;
3944 struct bttv_buffer_set old;
3945 dma_addr_t rc;
3946
3947 spin_lock(&btv->s_lock);
3948
3949 /* new buffer set */
3950 bttv_irq_next_video(btv, &new);
3951 rc = btread(BT848_RISC_COUNT);
3952 if ((btv->curr.top && is_active(&btv->curr.top->top, rc)) ||
3953 (btv->curr.bottom && is_active(&btv->curr.bottom->bottom, rc))) {
3954 btv->framedrop++;
3955 if (debug_latency)
3956 bttv_irq_debug_low_latency(btv, rc);
3957 spin_unlock(&btv->s_lock);
3958 return;
3959 }
3960
3961 /* switch over */
3962 old = btv->curr;
3963 btv->curr = new;
3964 btv->loop_irq &= ~1;
3965 bttv_buffer_activate_video(btv, &new);
3966 bttv_set_dma(btv, 0);
3967
3968 /* switch input */
3969 if (UNSET != btv->new_input) {
3970 video_mux(btv,btv->new_input);
3971 btv->new_input = UNSET;
3972 }
3973
3974 /* wake up finished buffers */
Brandon Philips0fc06862007-11-06 20:02:36 -03003975 bttv_irq_wakeup_video(btv, &old, &new, VIDEOBUF_DONE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003976 spin_unlock(&btv->s_lock);
3977}
3978
3979static void
3980bttv_irq_switch_vbi(struct bttv *btv)
3981{
3982 struct bttv_buffer *new = NULL;
3983 struct bttv_buffer *old;
3984 u32 rc;
3985
3986 spin_lock(&btv->s_lock);
3987
3988 if (!list_empty(&btv->vcapture))
3989 new = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
3990 old = btv->cvbi;
3991
3992 rc = btread(BT848_RISC_COUNT);
3993 if (NULL != old && (is_active(&old->top, rc) ||
3994 is_active(&old->bottom, rc))) {
3995 btv->framedrop++;
3996 if (debug_latency)
3997 bttv_irq_debug_low_latency(btv, rc);
3998 spin_unlock(&btv->s_lock);
3999 return;
4000 }
4001
4002 /* switch */
4003 btv->cvbi = new;
4004 btv->loop_irq &= ~4;
4005 bttv_buffer_activate_vbi(btv, new);
4006 bttv_set_dma(btv, 0);
4007
Brandon Philips0fc06862007-11-06 20:02:36 -03004008 bttv_irq_wakeup_vbi(btv, old, VIDEOBUF_DONE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004009 spin_unlock(&btv->s_lock);
4010}
4011
David Howells7d12e782006-10-05 14:55:46 +01004012static irqreturn_t bttv_irq(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004013{
4014 u32 stat,astat;
4015 u32 dstat;
4016 int count;
4017 struct bttv *btv;
4018 int handled = 0;
4019
4020 btv=(struct bttv *)dev_id;
Mark Weaver6c6c0b22005-11-13 16:07:52 -08004021
Linus Torvalds1da177e2005-04-16 15:20:36 -07004022 count=0;
4023 while (1) {
4024 /* get/clear interrupt status bits */
4025 stat=btread(BT848_INT_STAT);
4026 astat=stat&btread(BT848_INT_MASK);
4027 if (!astat)
4028 break;
4029 handled = 1;
4030 btwrite(stat,BT848_INT_STAT);
4031
4032 /* get device status bits */
4033 dstat=btread(BT848_DSTATUS);
4034
4035 if (irq_debug) {
4036 printk(KERN_DEBUG "bttv%d: irq loop=%d fc=%d "
4037 "riscs=%x, riscc=%08x, ",
4038 btv->c.nr, count, btv->field_count,
4039 stat>>28, btread(BT848_RISC_COUNT));
4040 bttv_print_irqbits(stat,astat);
4041 if (stat & BT848_INT_HLOCK)
4042 printk(" HLOC => %s", (dstat & BT848_DSTATUS_HLOC)
4043 ? "yes" : "no");
4044 if (stat & BT848_INT_VPRES)
4045 printk(" PRES => %s", (dstat & BT848_DSTATUS_PRES)
4046 ? "yes" : "no");
4047 if (stat & BT848_INT_FMTCHG)
4048 printk(" NUML => %s", (dstat & BT848_DSTATUS_NUML)
4049 ? "625" : "525");
4050 printk("\n");
4051 }
4052
4053 if (astat&BT848_INT_VSYNC)
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004054 btv->field_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004055
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02004056 if ((astat & BT848_INT_GPINT) && btv->remote) {
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02004057 bttv_input_irq(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004058 }
4059
4060 if (astat & BT848_INT_I2CDONE) {
4061 btv->i2c_done = stat;
4062 wake_up(&btv->i2c_queue);
4063 }
4064
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004065 if ((astat & BT848_INT_RISCI) && (stat & (4<<28)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004066 bttv_irq_switch_vbi(btv);
4067
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004068 if ((astat & BT848_INT_RISCI) && (stat & (2<<28)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069 bttv_irq_wakeup_top(btv);
4070
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004071 if ((astat & BT848_INT_RISCI) && (stat & (1<<28)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004072 bttv_irq_switch_video(btv);
4073
4074 if ((astat & BT848_INT_HLOCK) && btv->opt_automute)
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03004075 audio_mute(btv, btv->mute); /* trigger automute */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004076
4077 if (astat & (BT848_INT_SCERR|BT848_INT_OCERR)) {
4078 printk(KERN_INFO "bttv%d: %s%s @ %08x,",btv->c.nr,
4079 (astat & BT848_INT_SCERR) ? "SCERR" : "",
4080 (astat & BT848_INT_OCERR) ? "OCERR" : "",
4081 btread(BT848_RISC_COUNT));
4082 bttv_print_irqbits(stat,astat);
4083 printk("\n");
4084 if (bttv_debug)
4085 bttv_print_riscaddr(btv);
4086 }
4087 if (fdsr && astat & BT848_INT_FDSR) {
4088 printk(KERN_INFO "bttv%d: FDSR @ %08x\n",
4089 btv->c.nr,btread(BT848_RISC_COUNT));
4090 if (bttv_debug)
4091 bttv_print_riscaddr(btv);
4092 }
4093
4094 count++;
4095 if (count > 4) {
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08004096
4097 if (count > 8 || !(astat & BT848_INT_GPINT)) {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004098 btwrite(0, BT848_INT_MASK);
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08004099
4100 printk(KERN_ERR
4101 "bttv%d: IRQ lockup, cleared int mask [", btv->c.nr);
4102 } else {
4103 printk(KERN_ERR
4104 "bttv%d: IRQ lockup, clearing GPINT from int mask [", btv->c.nr);
4105
4106 btwrite(btread(BT848_INT_MASK) & (-1 ^ BT848_INT_GPINT),
4107 BT848_INT_MASK);
4108 };
4109
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110 bttv_print_irqbits(stat,astat);
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08004111
Linus Torvalds1da177e2005-04-16 15:20:36 -07004112 printk("]\n");
4113 }
4114 }
4115 btv->irq_total++;
4116 if (handled)
4117 btv->irq_me++;
4118 return IRQ_RETVAL(handled);
4119}
4120
4121
4122/* ----------------------------------------------------------------------- */
4123/* initialitation */
4124
4125static struct video_device *vdev_init(struct bttv *btv,
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03004126 const struct video_device *template,
Hans Verkuil0ea6bc82008-07-26 08:26:43 -03004127 const char *type_name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004128{
4129 struct video_device *vfd;
4130
4131 vfd = video_device_alloc();
4132 if (NULL == vfd)
4133 return NULL;
4134 *vfd = *template;
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004135 vfd->v4l2_dev = &btv->c.v4l2_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004136 vfd->release = video_device_release;
Mauro Carvalho Chehab1d0a4362008-06-23 12:31:29 -03004137 vfd->debug = bttv_debug;
Trent Piepho4b10d3b2009-01-28 21:32:59 -03004138 video_set_drvdata(vfd, btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004139 snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
4140 btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "",
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03004141 type_name, bttv_tvcards[btv->c.type].name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004142 return vfd;
4143}
4144
4145static void bttv_unregister_video(struct bttv *btv)
4146{
4147 if (btv->video_dev) {
Laurent Pinchartf0813b42009-11-27 13:57:30 -03004148 if (video_is_registered(btv->video_dev))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004149 video_unregister_device(btv->video_dev);
4150 else
4151 video_device_release(btv->video_dev);
4152 btv->video_dev = NULL;
4153 }
4154 if (btv->vbi_dev) {
Laurent Pinchartf0813b42009-11-27 13:57:30 -03004155 if (video_is_registered(btv->vbi_dev))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004156 video_unregister_device(btv->vbi_dev);
4157 else
4158 video_device_release(btv->vbi_dev);
4159 btv->vbi_dev = NULL;
4160 }
4161 if (btv->radio_dev) {
Laurent Pinchartf0813b42009-11-27 13:57:30 -03004162 if (video_is_registered(btv->radio_dev))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004163 video_unregister_device(btv->radio_dev);
4164 else
4165 video_device_release(btv->radio_dev);
4166 btv->radio_dev = NULL;
4167 }
4168}
4169
4170/* register video4linux devices */
4171static int __devinit bttv_register_video(struct bttv *btv)
4172{
Hans Verkuil0ea6bc82008-07-26 08:26:43 -03004173 if (no_overlay > 0)
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07004174 printk("bttv: Overlay support disabled.\n");
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07004175
Linus Torvalds1da177e2005-04-16 15:20:36 -07004176 /* video */
Hans Verkuil0ea6bc82008-07-26 08:26:43 -03004177 btv->video_dev = vdev_init(btv, &bttv_video_template, "video");
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03004178
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004179 if (NULL == btv->video_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004180 goto err;
Jean Delvare176c2f32008-09-07 12:49:59 -03004181 if (video_register_device(btv->video_dev, VFL_TYPE_GRABBER,
4182 video_nr[btv->c.nr]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004183 goto err;
Laurent Pinchart38c7c032009-11-27 13:57:15 -03004184 printk(KERN_INFO "bttv%d: registered device %s\n",
4185 btv->c.nr, video_device_node_name(btv->video_dev));
Hans Verkuil22a04f12008-07-20 06:35:02 -03004186 if (device_create_file(&btv->video_dev->dev,
Kay Sievers54bd5b62007-10-08 16:26:13 -03004187 &dev_attr_card)<0) {
4188 printk(KERN_ERR "bttv%d: device_create_file 'card' "
Trent Piephod94fc9a2006-07-29 17:18:06 -03004189 "failed\n", btv->c.nr);
4190 goto err;
4191 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004192
4193 /* vbi */
Hans Verkuil0ea6bc82008-07-26 08:26:43 -03004194 btv->vbi_dev = vdev_init(btv, &bttv_video_template, "vbi");
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03004195
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004196 if (NULL == btv->vbi_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004197 goto err;
Jean Delvare176c2f32008-09-07 12:49:59 -03004198 if (video_register_device(btv->vbi_dev, VFL_TYPE_VBI,
4199 vbi_nr[btv->c.nr]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004200 goto err;
Laurent Pinchart38c7c032009-11-27 13:57:15 -03004201 printk(KERN_INFO "bttv%d: registered device %s\n",
4202 btv->c.nr, video_device_node_name(btv->vbi_dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004203
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004204 if (!btv->has_radio)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004205 return 0;
4206 /* radio */
Hans Verkuil0ea6bc82008-07-26 08:26:43 -03004207 btv->radio_dev = vdev_init(btv, &radio_template, "radio");
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004208 if (NULL == btv->radio_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004209 goto err;
Jean Delvare176c2f32008-09-07 12:49:59 -03004210 if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,
4211 radio_nr[btv->c.nr]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004212 goto err;
Laurent Pinchart38c7c032009-11-27 13:57:15 -03004213 printk(KERN_INFO "bttv%d: registered device %s\n",
4214 btv->c.nr, video_device_node_name(btv->radio_dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004215
4216 /* all done */
4217 return 0;
4218
4219 err:
4220 bttv_unregister_video(btv);
4221 return -1;
4222}
4223
4224
4225/* on OpenFirmware machines (PowerMac at least), PCI memory cycle */
4226/* response on cards with no firmware is not enabled by OF */
4227static void pci_set_command(struct pci_dev *dev)
4228{
4229#if defined(__powerpc__)
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004230 unsigned int cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004231
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004232 pci_read_config_dword(dev, PCI_COMMAND, &cmd);
4233 cmd = (cmd | PCI_COMMAND_MEMORY );
4234 pci_write_config_dword(dev, PCI_COMMAND, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004235#endif
4236}
4237
4238static int __devinit bttv_probe(struct pci_dev *dev,
4239 const struct pci_device_id *pci_id)
4240{
4241 int result;
4242 unsigned char lat;
4243 struct bttv *btv;
4244
4245 if (bttv_num == BTTV_MAX)
4246 return -ENOMEM;
4247 printk(KERN_INFO "bttv: Bt8xx card found (%d).\n", bttv_num);
Trent Piepho4b10d3b2009-01-28 21:32:59 -03004248 bttvs[bttv_num] = btv = kzalloc(sizeof(*btv), GFP_KERNEL);
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004249 if (btv == NULL) {
4250 printk(KERN_ERR "bttv: out of memory.\n");
4251 return -ENOMEM;
4252 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004253 btv->c.nr = bttv_num;
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004254 snprintf(btv->c.v4l2_dev.name, sizeof(btv->c.v4l2_dev.name),
4255 "bttv%d", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004256
4257 /* initialize structs / fill in defaults */
Ingo Molnarbd5f0ac2006-01-13 14:10:24 -02004258 mutex_init(&btv->lock);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004259 spin_lock_init(&btv->s_lock);
4260 spin_lock_init(&btv->gpio_lock);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004261 init_waitqueue_head(&btv->i2c_queue);
4262 INIT_LIST_HEAD(&btv->c.subs);
4263 INIT_LIST_HEAD(&btv->capture);
4264 INIT_LIST_HEAD(&btv->vcapture);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004265 v4l2_prio_init(&btv->prio);
4266
4267 init_timer(&btv->timeout);
4268 btv->timeout.function = bttv_irq_timeout;
4269 btv->timeout.data = (unsigned long)btv;
4270
Michael Krufky7c08fb02005-11-08 21:36:21 -08004271 btv->i2c_rc = -1;
4272 btv->tuner_type = UNSET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004273 btv->new_input = UNSET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004274 btv->has_radio=radio[btv->c.nr];
4275
4276 /* pci stuff (init, get irq/mmio, ... */
4277 btv->c.pci = dev;
Michael Krufky7c08fb02005-11-08 21:36:21 -08004278 btv->id = dev->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004279 if (pci_enable_device(dev)) {
Michael Krufky7c08fb02005-11-08 21:36:21 -08004280 printk(KERN_WARNING "bttv%d: Can't enable device.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004281 btv->c.nr);
4282 return -EIO;
4283 }
Yang Hongyang284901a2009-04-06 19:01:15 -07004284 if (pci_set_dma_mask(dev, DMA_BIT_MASK(32))) {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004285 printk(KERN_WARNING "bttv%d: No suitable DMA available.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004286 btv->c.nr);
4287 return -EIO;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004288 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004289 if (!request_mem_region(pci_resource_start(dev,0),
4290 pci_resource_len(dev,0),
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004291 btv->c.v4l2_dev.name)) {
Greg Kroah-Hartman228aef62006-06-12 15:16:52 -07004292 printk(KERN_WARNING "bttv%d: can't request iomem (0x%llx).\n",
4293 btv->c.nr,
4294 (unsigned long long)pci_resource_start(dev,0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004295 return -EBUSY;
4296 }
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004297 pci_set_master(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004298 pci_set_command(dev);
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004299
4300 result = v4l2_device_register(&dev->dev, &btv->c.v4l2_dev);
4301 if (result < 0) {
4302 printk(KERN_WARNING "bttv%d: v4l2_device_register() failed\n", btv->c.nr);
4303 goto fail0;
4304 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305
Bjørn Morkabd34d82011-03-21 11:35:56 -03004306 btv->revision = dev->revision;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004307 pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
4308 printk(KERN_INFO "bttv%d: Bt%d (rev %d) at %s, ",
4309 bttv_num,btv->id, btv->revision, pci_name(dev));
Greg Kroah-Hartman228aef62006-06-12 15:16:52 -07004310 printk("irq: %d, latency: %d, mmio: 0x%llx\n",
4311 btv->c.pci->irq, lat,
4312 (unsigned long long)pci_resource_start(dev,0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004313 schedule();
4314
Akinobu Mita5f1693f2006-12-20 10:08:56 -03004315 btv->bt848_mmio = ioremap(pci_resource_start(dev, 0), 0x1000);
4316 if (NULL == btv->bt848_mmio) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004317 printk("bttv%d: ioremap() failed\n", btv->c.nr);
4318 result = -EIO;
4319 goto fail1;
4320 }
4321
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004322 /* identify card */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004323 bttv_idcard(btv);
4324
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004325 /* disable irqs, register irq handler */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004326 btwrite(0, BT848_INT_MASK);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004327 result = request_irq(btv->c.pci->irq, bttv_irq,
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004328 IRQF_SHARED | IRQF_DISABLED, btv->c.v4l2_dev.name, (void *)btv);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004329 if (result < 0) {
4330 printk(KERN_ERR "bttv%d: can't get IRQ %d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004331 bttv_num,btv->c.pci->irq);
4332 goto fail1;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004333 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004334
4335 if (0 != bttv_handle_chipset(btv)) {
4336 result = -EIO;
4337 goto fail2;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004338 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004339
4340 /* init options from insmod args */
4341 btv->opt_combfilter = combfilter;
4342 btv->opt_lumafilter = lumafilter;
4343 btv->opt_automute = automute;
4344 btv->opt_chroma_agc = chroma_agc;
4345 btv->opt_adc_crush = adc_crush;
4346 btv->opt_vcr_hack = vcr_hack;
4347 btv->opt_whitecrush_upper = whitecrush_upper;
4348 btv->opt_whitecrush_lower = whitecrush_lower;
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -07004349 btv->opt_uv_ratio = uv_ratio;
4350 btv->opt_full_luma_range = full_luma_range;
4351 btv->opt_coring = coring;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004352
4353 /* fill struct bttv with some useful defaults */
4354 btv->init.btv = btv;
4355 btv->init.ov.w.width = 320;
4356 btv->init.ov.w.height = 240;
Mauro Carvalho Chehabc96dd072007-10-26 16:51:47 -03004357 btv->init.fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004358 btv->init.width = 320;
4359 btv->init.height = 240;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004360 btv->input = 0;
4361
4362 /* initialize hardware */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004363 if (bttv_gpio)
4364 bttv_gpio_tracking(btv,"pre-init");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004365
4366 bttv_risc_init_main(btv);
4367 init_bt848(btv);
4368
4369 /* gpio */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004370 btwrite(0x00, BT848_GPIO_REG_INP);
4371 btwrite(0x00, BT848_GPIO_OUT_EN);
4372 if (bttv_verbose)
4373 bttv_gpio_tracking(btv,"init");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004374
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004375 /* needs to be done before i2c is registered */
4376 bttv_init_card1(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004377
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004378 /* register i2c + gpio */
4379 init_bttv_i2c(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004380
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004381 /* some card-specific stuff (needs working i2c) */
4382 bttv_init_card2(btv);
Hans Verkuil2c905772009-07-20 08:14:17 -03004383 bttv_init_tuner(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004384 init_irqreg(btv);
4385
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004386 /* register video4linux + input */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004387 if (!bttv_tvcards[btv->c.type].no_video) {
4388 bttv_register_video(btv);
4389 bt848_bright(btv,32768);
4390 bt848_contrast(btv,32768);
4391 bt848_hue(btv,32768);
4392 bt848_sat(btv,32768);
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03004393 audio_mute(btv, 1);
Trent Piepho333408f2007-07-03 15:08:10 -03004394 set_input(btv, 0, btv->tvnorm);
Michael Schimeke5bd0262007-01-18 16:17:39 -03004395 bttv_crop_reset(&btv->crop[0], btv->tvnorm);
4396 btv->crop[1] = btv->crop[0]; /* current = default */
4397 disclaim_vbi_lines(btv);
4398 disclaim_video_lines(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004399 }
4400
Jarod Wilsonf992a492007-03-24 15:23:50 -03004401 /* add subdevices and autoload dvb-bt8xx if needed */
4402 if (bttv_tvcards[btv->c.type].has_dvb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004403 bttv_sub_add_device(&btv->c, "dvb");
Jarod Wilsonf992a492007-03-24 15:23:50 -03004404 request_modules(btv);
4405 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004406
Jean Delvared90a4ae2010-02-16 14:22:37 -03004407 if (!disable_ir) {
4408 init_bttv_i2c_ir(btv);
4409 bttv_input_init(btv);
4410 }
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02004411
Linus Torvalds1da177e2005-04-16 15:20:36 -07004412 /* everything is fine */
4413 bttv_num++;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004414 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004415
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004416fail2:
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004417 free_irq(btv->c.pci->irq,btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004418
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004419fail1:
4420 v4l2_device_unregister(&btv->c.v4l2_dev);
4421
4422fail0:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004423 if (btv->bt848_mmio)
4424 iounmap(btv->bt848_mmio);
4425 release_mem_region(pci_resource_start(btv->c.pci,0),
4426 pci_resource_len(btv->c.pci,0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004427 return result;
4428}
4429
4430static void __devexit bttv_remove(struct pci_dev *pci_dev)
4431{
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004432 struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
4433 struct bttv *btv = to_bttv(v4l2_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004434
4435 if (bttv_verbose)
4436 printk("bttv%d: unloading\n",btv->c.nr);
4437
Tejun Heo707bcf32010-12-24 16:14:20 +01004438 if (bttv_tvcards[btv->c.type].has_dvb)
4439 flush_request_modules(btv);
4440
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004441 /* shutdown everything (DMA+IRQs) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004442 btand(~15, BT848_GPIO_DMA_CTL);
4443 btwrite(0, BT848_INT_MASK);
4444 btwrite(~0x0, BT848_INT_STAT);
4445 btwrite(0x0, BT848_GPIO_OUT_EN);
4446 if (bttv_gpio)
4447 bttv_gpio_tracking(btv,"cleanup");
4448
4449 /* tell gpio modules we are leaving ... */
4450 btv->shutdown=1;
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02004451 bttv_input_fini(btv);
Christopher Pascoe889aee82006-01-09 15:25:28 -02004452 bttv_sub_del_devices(&btv->c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004453
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004454 /* unregister i2c_bus + input */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004455 fini_bttv_i2c(btv);
4456
4457 /* unregister video4linux */
4458 bttv_unregister_video(btv);
4459
4460 /* free allocated memory */
4461 btcx_riscmem_free(btv->c.pci,&btv->main);
4462
4463 /* free ressources */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004464 free_irq(btv->c.pci->irq,btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004465 iounmap(btv->bt848_mmio);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004466 release_mem_region(pci_resource_start(btv->c.pci,0),
4467 pci_resource_len(btv->c.pci,0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004468
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004469 v4l2_device_unregister(&btv->c.v4l2_dev);
Trent Piepho4b10d3b2009-01-28 21:32:59 -03004470 bttvs[btv->c.nr] = NULL;
4471 kfree(btv);
4472
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004473 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004474}
4475
Alexey Dobriyan17bc98a2006-08-12 22:01:27 -03004476#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -07004477static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state)
4478{
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004479 struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
4480 struct bttv *btv = to_bttv(v4l2_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004481 struct bttv_buffer_set idle;
4482 unsigned long flags;
4483
Mauro Carvalho Chehab0f97a932005-09-09 13:04:05 -07004484 dprintk("bttv%d: suspend %d\n", btv->c.nr, state.event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004485
4486 /* stop dma + irqs */
4487 spin_lock_irqsave(&btv->s_lock,flags);
4488 memset(&idle, 0, sizeof(idle));
4489 btv->state.video = btv->curr;
4490 btv->state.vbi = btv->cvbi;
4491 btv->state.loop_irq = btv->loop_irq;
4492 btv->curr = idle;
4493 btv->loop_irq = 0;
4494 bttv_buffer_activate_video(btv, &idle);
4495 bttv_buffer_activate_vbi(btv, NULL);
4496 bttv_set_dma(btv, 0);
4497 btwrite(0, BT848_INT_MASK);
4498 spin_unlock_irqrestore(&btv->s_lock,flags);
4499
4500 /* save bt878 state */
4501 btv->state.gpio_enable = btread(BT848_GPIO_OUT_EN);
4502 btv->state.gpio_data = gpio_read();
4503
4504 /* save pci state */
4505 pci_save_state(pci_dev);
4506 if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
4507 pci_disable_device(pci_dev);
4508 btv->state.disabled = 1;
4509 }
4510 return 0;
4511}
4512
4513static int bttv_resume(struct pci_dev *pci_dev)
4514{
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004515 struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
4516 struct bttv *btv = to_bttv(v4l2_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004517 unsigned long flags;
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004518 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004519
4520 dprintk("bttv%d: resume\n", btv->c.nr);
4521
4522 /* restore pci state */
4523 if (btv->state.disabled) {
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004524 err=pci_enable_device(pci_dev);
4525 if (err) {
4526 printk(KERN_WARNING "bttv%d: Can't enable device.\n",
4527 btv->c.nr);
4528 return err;
4529 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004530 btv->state.disabled = 0;
4531 }
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004532 err=pci_set_power_state(pci_dev, PCI_D0);
4533 if (err) {
4534 pci_disable_device(pci_dev);
4535 printk(KERN_WARNING "bttv%d: Can't enable device.\n",
4536 btv->c.nr);
4537 btv->state.disabled = 1;
4538 return err;
4539 }
4540
Linus Torvalds1da177e2005-04-16 15:20:36 -07004541 pci_restore_state(pci_dev);
4542
4543 /* restore bt878 state */
4544 bttv_reinit_bt848(btv);
4545 gpio_inout(0xffffff, btv->state.gpio_enable);
4546 gpio_write(btv->state.gpio_data);
4547
4548 /* restart dma */
4549 spin_lock_irqsave(&btv->s_lock,flags);
4550 btv->curr = btv->state.video;
4551 btv->cvbi = btv->state.vbi;
4552 btv->loop_irq = btv->state.loop_irq;
4553 bttv_buffer_activate_video(btv, &btv->curr);
4554 bttv_buffer_activate_vbi(btv, btv->cvbi);
4555 bttv_set_dma(btv, 0);
4556 spin_unlock_irqrestore(&btv->s_lock,flags);
4557 return 0;
4558}
Alexey Dobriyan17bc98a2006-08-12 22:01:27 -03004559#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07004560
4561static struct pci_device_id bttv_pci_tbl[] = {
Joe Perches76e97412009-07-05 15:59:21 -03004562 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT848), 0},
4563 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT849), 0},
4564 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT878), 0},
4565 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT879), 0},
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004566 {0,}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004567};
4568
4569MODULE_DEVICE_TABLE(pci, bttv_pci_tbl);
4570
4571static struct pci_driver bttv_pci_driver = {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004572 .name = "bttv",
4573 .id_table = bttv_pci_tbl,
4574 .probe = bttv_probe,
4575 .remove = __devexit_p(bttv_remove),
Alexey Dobriyan17bc98a2006-08-12 22:01:27 -03004576#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -07004577 .suspend = bttv_suspend,
4578 .resume = bttv_resume,
Alexey Dobriyan17bc98a2006-08-12 22:01:27 -03004579#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07004580};
4581
Adrian Bunk7d44e892007-12-11 19:23:43 -03004582static int __init bttv_init_module(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004583{
Randy Dunlapc526e222006-07-15 09:08:26 -03004584 int ret;
4585
Linus Torvalds1da177e2005-04-16 15:20:36 -07004586 bttv_num = 0;
4587
4588 printk(KERN_INFO "bttv: driver version %d.%d.%d loaded\n",
4589 (BTTV_VERSION_CODE >> 16) & 0xff,
4590 (BTTV_VERSION_CODE >> 8) & 0xff,
4591 BTTV_VERSION_CODE & 0xff);
4592#ifdef SNAPSHOT
4593 printk(KERN_INFO "bttv: snapshot date %04d-%02d-%02d\n",
4594 SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
4595#endif
4596 if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME)
4597 gbuffers = 2;
Filipe Rossetf41b6962009-05-28 11:11:53 -03004598 if (gbufsize > BTTV_MAX_FBUF)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004599 gbufsize = BTTV_MAX_FBUF;
4600 gbufsize = (gbufsize + PAGE_SIZE - 1) & PAGE_MASK;
4601 if (bttv_verbose)
4602 printk(KERN_INFO "bttv: using %d buffers with %dk (%d pages) each for capture\n",
4603 gbuffers, gbufsize >> 10, gbufsize >> PAGE_SHIFT);
4604
4605 bttv_check_chipset();
4606
Randy Dunlapc526e222006-07-15 09:08:26 -03004607 ret = bus_register(&bttv_sub_bus_type);
4608 if (ret < 0) {
4609 printk(KERN_WARNING "bttv: bus_register error: %d\n", ret);
4610 return ret;
4611 }
Akinobu Mita9e7e85e2007-12-17 14:26:29 -03004612 ret = pci_register_driver(&bttv_pci_driver);
4613 if (ret < 0)
4614 bus_unregister(&bttv_sub_bus_type);
4615
4616 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004617}
4618
Adrian Bunk7d44e892007-12-11 19:23:43 -03004619static void __exit bttv_cleanup_module(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004620{
4621 pci_unregister_driver(&bttv_pci_driver);
4622 bus_unregister(&bttv_sub_bus_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004623}
4624
4625module_init(bttv_init_module);
4626module_exit(bttv_cleanup_module);
4627
4628/*
4629 * Local variables:
4630 * c-basic-offset: 8
4631 * End:
4632 */