blob: 16f5ca23698c69af3795d5e6a3c90168fc6fee4c [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002
3 bttv - Bt848 frame grabber driver
4
5 Copyright (C) 1996,97,98 Ralph Metzler <rjkm@thp.uni-koeln.de>
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08006 & Marcus Metzler <mocm@thp.uni-koeln.de>
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 (c) 1999-2002 Gerd Knorr <kraxel@bytesex.org>
8
9 some v4l2 code lines are taken from Justin's bttv2 driver which is
10 (c) 2000 Justin Schoeman <justin@suntiger.ee.up.ac.za>
11
Nickolay V. Shmyreve84619b2007-10-26 11:01:08 -030012 V4L1 removal from:
13 (c) 2005-2006 Nickolay V. Shmyrev <nshmyrev@yandex.ru>
14
Mauro Carvalho Chehabc96dd072007-10-26 16:51:47 -030015 Fixes to be fully V4L2 compliant by
16 (c) 2006 Mauro Carvalho Chehab <mchehab@infradead.org>
17
Michael Schimeke5bd0262007-01-18 16:17:39 -030018 Cropping and overscan support
19 Copyright (C) 2005, 2006 Michael H. Schimek <mschimek@gmx.at>
20 Sponsored by OPQ Systems AB
21
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 This program is free software; you can redistribute it and/or modify
23 it under the terms of the GNU General Public License as published by
24 the Free Software Foundation; either version 2 of the License, or
25 (at your option) any later version.
26
27 This program is distributed in the hope that it will be useful,
28 but WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 GNU General Public License for more details.
31
32 You should have received a copy of the GNU General Public License
33 along with this program; if not, write to the Free Software
34 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35*/
36
Joe Perches8af443e2011-08-21 19:56:48 -030037#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
38
Linus Torvalds1da177e2005-04-16 15:20:36 -070039#include <linux/init.h>
40#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <linux/delay.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090042#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/errno.h>
44#include <linux/fs.h>
45#include <linux/kernel.h>
46#include <linux/sched.h>
47#include <linux/interrupt.h>
48#include <linux/kdev_t.h>
Mauro Carvalho Chehabb5b8ab82006-01-09 15:25:20 -020049#include "bttvp.h"
Michael Krufky5e453dc2006-01-09 15:32:31 -020050#include <media/v4l2-common.h>
Hans Verkuil35ea11f2008-07-20 08:12:02 -030051#include <media/v4l2-ioctl.h>
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -030052#include <media/tvaudio.h>
Hans Verkuil2474ed42006-03-19 12:35:57 -030053#include <media/msp3400.h>
Mauro Carvalho Chehabb5b8ab82006-01-09 15:25:20 -020054
Mauro Carvalho Chehabfa9846a2005-07-12 13:58:42 -070055#include <linux/dma-mapping.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070056
57#include <asm/io.h>
58#include <asm/byteorder.h>
59
Hans Verkuilb9218f22010-12-27 12:22:46 -030060#include <media/saa6588.h>
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -070061
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -030062#define BTTV_VERSION "0.9.19"
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -070063
Linus Torvalds1da177e2005-04-16 15:20:36 -070064unsigned int bttv_num; /* number of Bt848s in use */
Trent Piepho4b10d3b2009-01-28 21:32:59 -030065struct bttv *bttvs[BTTV_MAX];
Linus Torvalds1da177e2005-04-16 15:20:36 -070066
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020067unsigned int bttv_debug;
Linus Torvalds1da177e2005-04-16 15:20:36 -070068unsigned int bttv_verbose = 1;
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020069unsigned int bttv_gpio;
Linus Torvalds1da177e2005-04-16 15:20:36 -070070
71/* config variables */
72#ifdef __BIG_ENDIAN
73static unsigned int bigendian=1;
74#else
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020075static unsigned int bigendian;
Linus Torvalds1da177e2005-04-16 15:20:36 -070076#endif
77static unsigned int radio[BTTV_MAX];
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020078static unsigned int irq_debug;
Linus Torvalds1da177e2005-04-16 15:20:36 -070079static unsigned int gbuffers = 8;
80static unsigned int gbufsize = 0x208000;
Michael Schimeke5bd0262007-01-18 16:17:39 -030081static unsigned int reset_crop = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -070082
Jean Delvare176c2f32008-09-07 12:49:59 -030083static int video_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
84static int radio_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
85static int vbi_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020086static int debug_latency;
Jean Delvared90a4ae2010-02-16 14:22:37 -030087static int disable_ir;
Linus Torvalds1da177e2005-04-16 15:20:36 -070088
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020089static unsigned int fdsr;
Linus Torvalds1da177e2005-04-16 15:20:36 -070090
91/* options */
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020092static unsigned int combfilter;
93static unsigned int lumafilter;
Linus Torvalds1da177e2005-04-16 15:20:36 -070094static unsigned int automute = 1;
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020095static unsigned int chroma_agc;
Linus Torvalds1da177e2005-04-16 15:20:36 -070096static unsigned int adc_crush = 1;
97static unsigned int whitecrush_upper = 0xCF;
98static unsigned int whitecrush_lower = 0x7F;
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020099static unsigned int vcr_hack;
100static unsigned int irq_iswitch;
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700101static unsigned int uv_ratio = 50;
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -0200102static unsigned int full_luma_range;
103static unsigned int coring;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104
105/* API features (turn on/off stuff for testing) */
106static unsigned int v4l2 = 1;
107
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108/* insmod args */
109module_param(bttv_verbose, int, 0644);
110module_param(bttv_gpio, int, 0644);
111module_param(bttv_debug, int, 0644);
112module_param(irq_debug, int, 0644);
113module_param(debug_latency, int, 0644);
Jean Delvared90a4ae2010-02-16 14:22:37 -0300114module_param(disable_ir, int, 0444);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115
116module_param(fdsr, int, 0444);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117module_param(gbuffers, int, 0444);
118module_param(gbufsize, int, 0444);
Michael Schimeke5bd0262007-01-18 16:17:39 -0300119module_param(reset_crop, int, 0444);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120
121module_param(v4l2, int, 0644);
122module_param(bigendian, int, 0644);
123module_param(irq_iswitch, int, 0644);
124module_param(combfilter, int, 0444);
125module_param(lumafilter, int, 0444);
126module_param(automute, int, 0444);
127module_param(chroma_agc, int, 0444);
128module_param(adc_crush, int, 0444);
129module_param(whitecrush_upper, int, 0444);
130module_param(whitecrush_lower, int, 0444);
131module_param(vcr_hack, int, 0444);
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700132module_param(uv_ratio, int, 0444);
133module_param(full_luma_range, int, 0444);
134module_param(coring, int, 0444);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135
Jean Delvare176c2f32008-09-07 12:49:59 -0300136module_param_array(radio, int, NULL, 0444);
137module_param_array(video_nr, int, NULL, 0444);
138module_param_array(radio_nr, int, NULL, 0444);
139module_param_array(vbi_nr, int, NULL, 0444);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140
141MODULE_PARM_DESC(radio,"The TV card supports radio, default is 0 (no)");
142MODULE_PARM_DESC(bigendian,"byte order of the framebuffer, default is native endian");
143MODULE_PARM_DESC(bttv_verbose,"verbose startup messages, default is 1 (yes)");
144MODULE_PARM_DESC(bttv_gpio,"log gpio changes, default is 0 (no)");
145MODULE_PARM_DESC(bttv_debug,"debug messages, default is 0 (no)");
146MODULE_PARM_DESC(irq_debug,"irq handler debug messages, default is 0 (no)");
Jean Delvared90a4ae2010-02-16 14:22:37 -0300147MODULE_PARM_DESC(disable_ir, "disable infrared remote support");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148MODULE_PARM_DESC(gbuffers,"number of capture buffers. range 2-32, default 8");
149MODULE_PARM_DESC(gbufsize,"size of the capture buffers, default is 0x208000");
Michael Schimeke5bd0262007-01-18 16:17:39 -0300150MODULE_PARM_DESC(reset_crop,"reset cropping parameters at open(), default "
151 "is 1 (yes) for compatibility with older applications");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152MODULE_PARM_DESC(automute,"mute audio on bad/missing video signal, default is 1 (yes)");
153MODULE_PARM_DESC(chroma_agc,"enables the AGC of chroma signal, default is 0 (no)");
154MODULE_PARM_DESC(adc_crush,"enables the luminance ADC crush, default is 1 (yes)");
155MODULE_PARM_DESC(whitecrush_upper,"sets the white crush upper value, default is 207");
156MODULE_PARM_DESC(whitecrush_lower,"sets the white crush lower value, default is 127");
157MODULE_PARM_DESC(vcr_hack,"enables the VCR hack (improves synch on poor VCR tapes), default is 0 (no)");
158MODULE_PARM_DESC(irq_iswitch,"switch inputs in irq handler");
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700159MODULE_PARM_DESC(uv_ratio,"ratio between u and v gains, default is 50");
160MODULE_PARM_DESC(full_luma_range,"use the full luma range, default is 0 (no)");
161MODULE_PARM_DESC(coring,"set the luma coring level, default is 0 (no)");
Jean Delvare176c2f32008-09-07 12:49:59 -0300162MODULE_PARM_DESC(video_nr, "video device numbers");
163MODULE_PARM_DESC(vbi_nr, "vbi device numbers");
164MODULE_PARM_DESC(radio_nr, "radio device numbers");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165
166MODULE_DESCRIPTION("bttv - v4l/v4l2 driver module for bt848/878 based cards");
167MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr");
168MODULE_LICENSE("GPL");
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -0300169MODULE_VERSION(BTTV_VERSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170
171/* ----------------------------------------------------------------------- */
172/* sysfs */
173
Kay Sievers54bd5b62007-10-08 16:26:13 -0300174static ssize_t show_card(struct device *cd,
175 struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176{
Hans Verkuil22a04f12008-07-20 06:35:02 -0300177 struct video_device *vfd = container_of(cd, struct video_device, dev);
Hans Verkuil74fc7bd2009-03-14 12:36:54 -0300178 struct bttv *btv = video_get_drvdata(vfd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179 return sprintf(buf, "%d\n", btv ? btv->c.type : UNSET);
180}
Kay Sievers54bd5b62007-10-08 16:26:13 -0300181static DEVICE_ATTR(card, S_IRUGO, show_card, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182
183/* ----------------------------------------------------------------------- */
Jarod Wilsonf992a492007-03-24 15:23:50 -0300184/* dvb auto-load setup */
185#if defined(CONFIG_MODULES) && defined(MODULE)
186static void request_module_async(struct work_struct *work)
187{
188 request_module("dvb-bt8xx");
189}
190
191static void request_modules(struct bttv *dev)
192{
193 INIT_WORK(&dev->request_module_wk, request_module_async);
194 schedule_work(&dev->request_module_wk);
195}
Tejun Heo707bcf32010-12-24 16:14:20 +0100196
197static void flush_request_modules(struct bttv *dev)
198{
199 flush_work_sync(&dev->request_module_wk);
200}
Jarod Wilsonf992a492007-03-24 15:23:50 -0300201#else
202#define request_modules(dev)
Tejun Heo707bcf32010-12-24 16:14:20 +0100203#define flush_request_modules(dev)
Jarod Wilsonf992a492007-03-24 15:23:50 -0300204#endif /* CONFIG_MODULES */
205
206
207/* ----------------------------------------------------------------------- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208/* static data */
209
210/* special timing tables from conexant... */
211static u8 SRAM_Table[][60] =
212{
213 /* PAL digital input over GPIO[7:0] */
214 {
215 45, // 45 bytes following
216 0x36,0x11,0x01,0x00,0x90,0x02,0x05,0x10,0x04,0x16,
217 0x12,0x05,0x11,0x00,0x04,0x12,0xC0,0x00,0x31,0x00,
218 0x06,0x51,0x08,0x03,0x89,0x08,0x07,0xC0,0x44,0x00,
219 0x81,0x01,0x01,0xA9,0x0D,0x02,0x02,0x50,0x03,0x37,
220 0x37,0x00,0xAF,0x21,0x00
221 },
222 /* NTSC digital input over GPIO[7:0] */
223 {
224 51, // 51 bytes following
225 0x0C,0xC0,0x00,0x00,0x90,0x02,0x03,0x10,0x03,0x06,
226 0x10,0x04,0x12,0x12,0x05,0x02,0x13,0x04,0x19,0x00,
227 0x04,0x39,0x00,0x06,0x59,0x08,0x03,0x83,0x08,0x07,
228 0x03,0x50,0x00,0xC0,0x40,0x00,0x86,0x01,0x01,0xA6,
229 0x0D,0x02,0x03,0x11,0x01,0x05,0x37,0x00,0xAC,0x21,
230 0x00,
231 },
232 // TGB_NTSC392 // quartzsight
233 // This table has been modified to be used for Fusion Rev D
234 {
235 0x2A, // size of table = 42
236 0x06, 0x08, 0x04, 0x0a, 0xc0, 0x00, 0x18, 0x08, 0x03, 0x24,
237 0x08, 0x07, 0x02, 0x90, 0x02, 0x08, 0x10, 0x04, 0x0c, 0x10,
238 0x05, 0x2c, 0x11, 0x04, 0x55, 0x48, 0x00, 0x05, 0x50, 0x00,
239 0xbf, 0x0c, 0x02, 0x2f, 0x3d, 0x00, 0x2f, 0x3f, 0x00, 0xc3,
240 0x20, 0x00
241 }
242};
243
Michael Schimeke5bd0262007-01-18 16:17:39 -0300244/* minhdelayx1 first video pixel we can capture on a line and
245 hdelayx1 start of active video, both relative to rising edge of
246 /HRESET pulse (0H) in 1 / fCLKx1.
247 swidth width of active video and
248 totalwidth total line width, both in 1 / fCLKx1.
249 sqwidth total line width in square pixels.
250 vdelay start of active video in 2 * field lines relative to
251 trailing edge of /VRESET pulse (VDELAY register).
252 sheight height of active video in 2 * field lines.
253 videostart0 ITU-R frame line number of the line corresponding
254 to vdelay in the first field. */
255#define CROPCAP(minhdelayx1, hdelayx1, swidth, totalwidth, sqwidth, \
256 vdelay, sheight, videostart0) \
257 .cropcap.bounds.left = minhdelayx1, \
258 /* * 2 because vertically we count field lines times two, */ \
259 /* e.g. 23 * 2 to 23 * 2 + 576 in PAL-BGHI defrect. */ \
260 .cropcap.bounds.top = (videostart0) * 2 - (vdelay) + MIN_VDELAY, \
261 /* 4 is a safety margin at the end of the line. */ \
262 .cropcap.bounds.width = (totalwidth) - (minhdelayx1) - 4, \
263 .cropcap.bounds.height = (sheight) + (vdelay) - MIN_VDELAY, \
264 .cropcap.defrect.left = hdelayx1, \
265 .cropcap.defrect.top = (videostart0) * 2, \
266 .cropcap.defrect.width = swidth, \
267 .cropcap.defrect.height = sheight, \
268 .cropcap.pixelaspect.numerator = totalwidth, \
269 .cropcap.pixelaspect.denominator = sqwidth,
270
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271const struct bttv_tvnorm bttv_tvnorms[] = {
272 /* PAL-BDGHI */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800273 /* max. active video is actually 922, but 924 is divisible by 4 and 3! */
274 /* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 {
276 .v4l2_id = V4L2_STD_PAL,
277 .name = "PAL",
278 .Fsc = 35468950,
279 .swidth = 924,
280 .sheight = 576,
281 .totalwidth = 1135,
282 .adelay = 0x7f,
283 .bdelay = 0x72,
284 .iform = (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
285 .scaledtwidth = 1135,
286 .hdelayx1 = 186,
287 .hactivex1 = 924,
288 .vdelay = 0x20,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300289 .vbipack = 255, /* min (2048 / 4, 0x1ff) & 0xff */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 .sram = 0,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200291 /* ITU-R frame line number of the first VBI line
Michael Schimeke5bd0262007-01-18 16:17:39 -0300292 we can capture, of the first and second field.
293 The last line is determined by cropcap.bounds. */
294 .vbistart = { 7, 320 },
295 CROPCAP(/* minhdelayx1 */ 68,
296 /* hdelayx1 */ 186,
297 /* Should be (768 * 1135 + 944 / 2) / 944.
298 cropcap.defrect is used for image width
299 checks, so we keep the old value 924. */
300 /* swidth */ 924,
301 /* totalwidth */ 1135,
302 /* sqwidth */ 944,
303 /* vdelay */ 0x20,
304 /* sheight */ 576,
305 /* videostart0 */ 23)
306 /* bt878 (and bt848?) can capture another
307 line below active video. */
308 .cropcap.bounds.height = (576 + 2) + 0x20 - 2,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309 },{
Hans Verkuild97a11e2006-02-07 06:48:40 -0200310 .v4l2_id = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 .name = "NTSC",
312 .Fsc = 28636363,
313 .swidth = 768,
314 .sheight = 480,
315 .totalwidth = 910,
316 .adelay = 0x68,
317 .bdelay = 0x5d,
318 .iform = (BT848_IFORM_NTSC|BT848_IFORM_XT0),
319 .scaledtwidth = 910,
320 .hdelayx1 = 128,
321 .hactivex1 = 910,
322 .vdelay = 0x1a,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300323 .vbipack = 144, /* min (1600 / 4, 0x1ff) & 0xff */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 .sram = 1,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200325 .vbistart = { 10, 273 },
Michael Schimeke5bd0262007-01-18 16:17:39 -0300326 CROPCAP(/* minhdelayx1 */ 68,
327 /* hdelayx1 */ 128,
328 /* Should be (640 * 910 + 780 / 2) / 780? */
329 /* swidth */ 768,
330 /* totalwidth */ 910,
331 /* sqwidth */ 780,
332 /* vdelay */ 0x1a,
333 /* sheight */ 480,
334 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335 },{
336 .v4l2_id = V4L2_STD_SECAM,
337 .name = "SECAM",
338 .Fsc = 35468950,
339 .swidth = 924,
340 .sheight = 576,
341 .totalwidth = 1135,
342 .adelay = 0x7f,
343 .bdelay = 0xb0,
344 .iform = (BT848_IFORM_SECAM|BT848_IFORM_XT1),
345 .scaledtwidth = 1135,
346 .hdelayx1 = 186,
347 .hactivex1 = 922,
348 .vdelay = 0x20,
349 .vbipack = 255,
350 .sram = 0, /* like PAL, correct? */
Michael H. Schimek67f15702006-01-09 15:25:27 -0200351 .vbistart = { 7, 320 },
Michael Schimeke5bd0262007-01-18 16:17:39 -0300352 CROPCAP(/* minhdelayx1 */ 68,
353 /* hdelayx1 */ 186,
354 /* swidth */ 924,
355 /* totalwidth */ 1135,
356 /* sqwidth */ 944,
357 /* vdelay */ 0x20,
358 /* sheight */ 576,
359 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 },{
361 .v4l2_id = V4L2_STD_PAL_Nc,
362 .name = "PAL-Nc",
363 .Fsc = 28636363,
364 .swidth = 640,
365 .sheight = 576,
366 .totalwidth = 910,
367 .adelay = 0x68,
368 .bdelay = 0x5d,
369 .iform = (BT848_IFORM_PAL_NC|BT848_IFORM_XT0),
370 .scaledtwidth = 780,
371 .hdelayx1 = 130,
372 .hactivex1 = 734,
373 .vdelay = 0x1a,
374 .vbipack = 144,
375 .sram = -1,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200376 .vbistart = { 7, 320 },
Michael Schimeke5bd0262007-01-18 16:17:39 -0300377 CROPCAP(/* minhdelayx1 */ 68,
378 /* hdelayx1 */ 130,
379 /* swidth */ (640 * 910 + 780 / 2) / 780,
380 /* totalwidth */ 910,
381 /* sqwidth */ 780,
382 /* vdelay */ 0x1a,
383 /* sheight */ 576,
384 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 },{
386 .v4l2_id = V4L2_STD_PAL_M,
387 .name = "PAL-M",
388 .Fsc = 28636363,
389 .swidth = 640,
390 .sheight = 480,
391 .totalwidth = 910,
392 .adelay = 0x68,
393 .bdelay = 0x5d,
394 .iform = (BT848_IFORM_PAL_M|BT848_IFORM_XT0),
395 .scaledtwidth = 780,
396 .hdelayx1 = 135,
397 .hactivex1 = 754,
398 .vdelay = 0x1a,
399 .vbipack = 144,
400 .sram = -1,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200401 .vbistart = { 10, 273 },
Michael Schimeke5bd0262007-01-18 16:17:39 -0300402 CROPCAP(/* minhdelayx1 */ 68,
403 /* hdelayx1 */ 135,
404 /* swidth */ (640 * 910 + 780 / 2) / 780,
405 /* totalwidth */ 910,
406 /* sqwidth */ 780,
407 /* vdelay */ 0x1a,
408 /* sheight */ 480,
409 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 },{
411 .v4l2_id = V4L2_STD_PAL_N,
412 .name = "PAL-N",
413 .Fsc = 35468950,
414 .swidth = 768,
415 .sheight = 576,
416 .totalwidth = 1135,
417 .adelay = 0x7f,
418 .bdelay = 0x72,
419 .iform = (BT848_IFORM_PAL_N|BT848_IFORM_XT1),
420 .scaledtwidth = 944,
421 .hdelayx1 = 186,
422 .hactivex1 = 922,
423 .vdelay = 0x20,
424 .vbipack = 144,
425 .sram = -1,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300426 .vbistart = { 7, 320 },
427 CROPCAP(/* minhdelayx1 */ 68,
428 /* hdelayx1 */ 186,
429 /* swidth */ (768 * 1135 + 944 / 2) / 944,
430 /* totalwidth */ 1135,
431 /* sqwidth */ 944,
432 /* vdelay */ 0x20,
433 /* sheight */ 576,
434 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 },{
436 .v4l2_id = V4L2_STD_NTSC_M_JP,
437 .name = "NTSC-JP",
438 .Fsc = 28636363,
439 .swidth = 640,
440 .sheight = 480,
441 .totalwidth = 910,
442 .adelay = 0x68,
443 .bdelay = 0x5d,
444 .iform = (BT848_IFORM_NTSC_J|BT848_IFORM_XT0),
445 .scaledtwidth = 780,
446 .hdelayx1 = 135,
447 .hactivex1 = 754,
448 .vdelay = 0x16,
449 .vbipack = 144,
450 .sram = -1,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300451 .vbistart = { 10, 273 },
452 CROPCAP(/* minhdelayx1 */ 68,
453 /* hdelayx1 */ 135,
454 /* swidth */ (640 * 910 + 780 / 2) / 780,
455 /* totalwidth */ 910,
456 /* sqwidth */ 780,
457 /* vdelay */ 0x16,
458 /* sheight */ 480,
459 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 },{
461 /* that one hopefully works with the strange timing
462 * which video recorders produce when playing a NTSC
463 * tape on a PAL TV ... */
464 .v4l2_id = V4L2_STD_PAL_60,
465 .name = "PAL-60",
466 .Fsc = 35468950,
467 .swidth = 924,
468 .sheight = 480,
469 .totalwidth = 1135,
470 .adelay = 0x7f,
471 .bdelay = 0x72,
472 .iform = (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
473 .scaledtwidth = 1135,
474 .hdelayx1 = 186,
475 .hactivex1 = 924,
476 .vdelay = 0x1a,
477 .vbipack = 255,
478 .vtotal = 524,
479 .sram = -1,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200480 .vbistart = { 10, 273 },
Michael Schimeke5bd0262007-01-18 16:17:39 -0300481 CROPCAP(/* minhdelayx1 */ 68,
482 /* hdelayx1 */ 186,
483 /* swidth */ 924,
484 /* totalwidth */ 1135,
485 /* sqwidth */ 944,
486 /* vdelay */ 0x1a,
487 /* sheight */ 480,
488 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 }
490};
491static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms);
492
493/* ----------------------------------------------------------------------- */
494/* bttv format list
495 packed pixel formats must come first */
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -0300496static const struct bttv_format formats[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 {
498 .name = "8 bpp, gray",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 .fourcc = V4L2_PIX_FMT_GREY,
500 .btformat = BT848_COLOR_FMT_Y8,
501 .depth = 8,
502 .flags = FORMAT_FLAGS_PACKED,
503 },{
504 .name = "8 bpp, dithered color",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 .fourcc = V4L2_PIX_FMT_HI240,
506 .btformat = BT848_COLOR_FMT_RGB8,
507 .depth = 8,
508 .flags = FORMAT_FLAGS_PACKED | FORMAT_FLAGS_DITHER,
509 },{
510 .name = "15 bpp RGB, le",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511 .fourcc = V4L2_PIX_FMT_RGB555,
512 .btformat = BT848_COLOR_FMT_RGB15,
513 .depth = 16,
514 .flags = FORMAT_FLAGS_PACKED,
515 },{
516 .name = "15 bpp RGB, be",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 .fourcc = V4L2_PIX_FMT_RGB555X,
518 .btformat = BT848_COLOR_FMT_RGB15,
519 .btswap = 0x03, /* byteswap */
520 .depth = 16,
521 .flags = FORMAT_FLAGS_PACKED,
522 },{
523 .name = "16 bpp RGB, le",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 .fourcc = V4L2_PIX_FMT_RGB565,
525 .btformat = BT848_COLOR_FMT_RGB16,
526 .depth = 16,
527 .flags = FORMAT_FLAGS_PACKED,
528 },{
529 .name = "16 bpp RGB, be",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 .fourcc = V4L2_PIX_FMT_RGB565X,
531 .btformat = BT848_COLOR_FMT_RGB16,
532 .btswap = 0x03, /* byteswap */
533 .depth = 16,
534 .flags = FORMAT_FLAGS_PACKED,
535 },{
536 .name = "24 bpp RGB, le",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 .fourcc = V4L2_PIX_FMT_BGR24,
538 .btformat = BT848_COLOR_FMT_RGB24,
539 .depth = 24,
540 .flags = FORMAT_FLAGS_PACKED,
541 },{
542 .name = "32 bpp RGB, le",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 .fourcc = V4L2_PIX_FMT_BGR32,
544 .btformat = BT848_COLOR_FMT_RGB32,
545 .depth = 32,
546 .flags = FORMAT_FLAGS_PACKED,
547 },{
548 .name = "32 bpp RGB, be",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 .fourcc = V4L2_PIX_FMT_RGB32,
550 .btformat = BT848_COLOR_FMT_RGB32,
551 .btswap = 0x0f, /* byte+word swap */
552 .depth = 32,
553 .flags = FORMAT_FLAGS_PACKED,
554 },{
555 .name = "4:2:2, packed, YUYV",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 .fourcc = V4L2_PIX_FMT_YUYV,
557 .btformat = BT848_COLOR_FMT_YUY2,
558 .depth = 16,
559 .flags = FORMAT_FLAGS_PACKED,
560 },{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561 .name = "4:2:2, packed, UYVY",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 .fourcc = V4L2_PIX_FMT_UYVY,
563 .btformat = BT848_COLOR_FMT_YUY2,
564 .btswap = 0x03, /* byteswap */
565 .depth = 16,
566 .flags = FORMAT_FLAGS_PACKED,
567 },{
568 .name = "4:2:2, planar, Y-Cb-Cr",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 .fourcc = V4L2_PIX_FMT_YUV422P,
570 .btformat = BT848_COLOR_FMT_YCrCb422,
571 .depth = 16,
572 .flags = FORMAT_FLAGS_PLANAR,
573 .hshift = 1,
574 .vshift = 0,
575 },{
576 .name = "4:2:0, planar, Y-Cb-Cr",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 .fourcc = V4L2_PIX_FMT_YUV420,
578 .btformat = BT848_COLOR_FMT_YCrCb422,
579 .depth = 12,
580 .flags = FORMAT_FLAGS_PLANAR,
581 .hshift = 1,
582 .vshift = 1,
583 },{
584 .name = "4:2:0, planar, Y-Cr-Cb",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585 .fourcc = V4L2_PIX_FMT_YVU420,
586 .btformat = BT848_COLOR_FMT_YCrCb422,
587 .depth = 12,
588 .flags = FORMAT_FLAGS_PLANAR | FORMAT_FLAGS_CrCb,
589 .hshift = 1,
590 .vshift = 1,
591 },{
592 .name = "4:1:1, planar, Y-Cb-Cr",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593 .fourcc = V4L2_PIX_FMT_YUV411P,
594 .btformat = BT848_COLOR_FMT_YCrCb411,
595 .depth = 12,
596 .flags = FORMAT_FLAGS_PLANAR,
597 .hshift = 2,
598 .vshift = 0,
599 },{
600 .name = "4:1:0, planar, Y-Cb-Cr",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 .fourcc = V4L2_PIX_FMT_YUV410,
602 .btformat = BT848_COLOR_FMT_YCrCb411,
603 .depth = 9,
604 .flags = FORMAT_FLAGS_PLANAR,
605 .hshift = 2,
606 .vshift = 2,
607 },{
608 .name = "4:1:0, planar, Y-Cr-Cb",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 .fourcc = V4L2_PIX_FMT_YVU410,
610 .btformat = BT848_COLOR_FMT_YCrCb411,
611 .depth = 9,
612 .flags = FORMAT_FLAGS_PLANAR | FORMAT_FLAGS_CrCb,
613 .hshift = 2,
614 .vshift = 2,
615 },{
616 .name = "raw scanlines",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 .fourcc = -1,
618 .btformat = BT848_COLOR_FMT_RAW,
619 .depth = 8,
620 .flags = FORMAT_FLAGS_RAW,
621 }
622};
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -0300623static const unsigned int FORMATS = ARRAY_SIZE(formats);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624
625/* ----------------------------------------------------------------------- */
626
627#define V4L2_CID_PRIVATE_CHROMA_AGC (V4L2_CID_PRIVATE_BASE + 0)
628#define V4L2_CID_PRIVATE_COMBFILTER (V4L2_CID_PRIVATE_BASE + 1)
629#define V4L2_CID_PRIVATE_AUTOMUTE (V4L2_CID_PRIVATE_BASE + 2)
630#define V4L2_CID_PRIVATE_LUMAFILTER (V4L2_CID_PRIVATE_BASE + 3)
631#define V4L2_CID_PRIVATE_AGC_CRUSH (V4L2_CID_PRIVATE_BASE + 4)
632#define V4L2_CID_PRIVATE_VCR_HACK (V4L2_CID_PRIVATE_BASE + 5)
633#define V4L2_CID_PRIVATE_WHITECRUSH_UPPER (V4L2_CID_PRIVATE_BASE + 6)
634#define V4L2_CID_PRIVATE_WHITECRUSH_LOWER (V4L2_CID_PRIVATE_BASE + 7)
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700635#define V4L2_CID_PRIVATE_UV_RATIO (V4L2_CID_PRIVATE_BASE + 8)
636#define V4L2_CID_PRIVATE_FULL_LUMA_RANGE (V4L2_CID_PRIVATE_BASE + 9)
637#define V4L2_CID_PRIVATE_CORING (V4L2_CID_PRIVATE_BASE + 10)
638#define V4L2_CID_PRIVATE_LASTP1 (V4L2_CID_PRIVATE_BASE + 11)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639
640static const struct v4l2_queryctrl no_ctl = {
641 .name = "42",
642 .flags = V4L2_CTRL_FLAG_DISABLED,
643};
644static const struct v4l2_queryctrl bttv_ctls[] = {
645 /* --- video --- */
646 {
647 .id = V4L2_CID_BRIGHTNESS,
648 .name = "Brightness",
649 .minimum = 0,
650 .maximum = 65535,
651 .step = 256,
652 .default_value = 32768,
653 .type = V4L2_CTRL_TYPE_INTEGER,
654 },{
655 .id = V4L2_CID_CONTRAST,
656 .name = "Contrast",
657 .minimum = 0,
658 .maximum = 65535,
659 .step = 128,
Alan McIvor961e6682012-04-01 21:11:08 -0300660 .default_value = 27648,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 .type = V4L2_CTRL_TYPE_INTEGER,
662 },{
663 .id = V4L2_CID_SATURATION,
664 .name = "Saturation",
665 .minimum = 0,
666 .maximum = 65535,
667 .step = 128,
668 .default_value = 32768,
669 .type = V4L2_CTRL_TYPE_INTEGER,
670 },{
671 .id = V4L2_CID_HUE,
672 .name = "Hue",
673 .minimum = 0,
674 .maximum = 65535,
675 .step = 256,
676 .default_value = 32768,
677 .type = V4L2_CTRL_TYPE_INTEGER,
678 },
679 /* --- audio --- */
680 {
681 .id = V4L2_CID_AUDIO_MUTE,
682 .name = "Mute",
683 .minimum = 0,
684 .maximum = 1,
685 .type = V4L2_CTRL_TYPE_BOOLEAN,
686 },{
687 .id = V4L2_CID_AUDIO_VOLUME,
688 .name = "Volume",
689 .minimum = 0,
690 .maximum = 65535,
691 .step = 65535/100,
692 .default_value = 65535,
693 .type = V4L2_CTRL_TYPE_INTEGER,
694 },{
695 .id = V4L2_CID_AUDIO_BALANCE,
696 .name = "Balance",
697 .minimum = 0,
698 .maximum = 65535,
699 .step = 65535/100,
700 .default_value = 32768,
701 .type = V4L2_CTRL_TYPE_INTEGER,
702 },{
703 .id = V4L2_CID_AUDIO_BASS,
704 .name = "Bass",
705 .minimum = 0,
706 .maximum = 65535,
707 .step = 65535/100,
708 .default_value = 32768,
709 .type = V4L2_CTRL_TYPE_INTEGER,
710 },{
711 .id = V4L2_CID_AUDIO_TREBLE,
712 .name = "Treble",
713 .minimum = 0,
714 .maximum = 65535,
715 .step = 65535/100,
716 .default_value = 32768,
717 .type = V4L2_CTRL_TYPE_INTEGER,
718 },
719 /* --- private --- */
720 {
721 .id = V4L2_CID_PRIVATE_CHROMA_AGC,
722 .name = "chroma agc",
723 .minimum = 0,
724 .maximum = 1,
725 .type = V4L2_CTRL_TYPE_BOOLEAN,
726 },{
727 .id = V4L2_CID_PRIVATE_COMBFILTER,
728 .name = "combfilter",
729 .minimum = 0,
730 .maximum = 1,
731 .type = V4L2_CTRL_TYPE_BOOLEAN,
732 },{
733 .id = V4L2_CID_PRIVATE_AUTOMUTE,
734 .name = "automute",
735 .minimum = 0,
736 .maximum = 1,
737 .type = V4L2_CTRL_TYPE_BOOLEAN,
738 },{
739 .id = V4L2_CID_PRIVATE_LUMAFILTER,
740 .name = "luma decimation filter",
741 .minimum = 0,
742 .maximum = 1,
743 .type = V4L2_CTRL_TYPE_BOOLEAN,
744 },{
745 .id = V4L2_CID_PRIVATE_AGC_CRUSH,
746 .name = "agc crush",
747 .minimum = 0,
748 .maximum = 1,
749 .type = V4L2_CTRL_TYPE_BOOLEAN,
750 },{
751 .id = V4L2_CID_PRIVATE_VCR_HACK,
752 .name = "vcr hack",
753 .minimum = 0,
754 .maximum = 1,
755 .type = V4L2_CTRL_TYPE_BOOLEAN,
756 },{
757 .id = V4L2_CID_PRIVATE_WHITECRUSH_UPPER,
758 .name = "whitecrush upper",
759 .minimum = 0,
760 .maximum = 255,
761 .step = 1,
762 .default_value = 0xCF,
763 .type = V4L2_CTRL_TYPE_INTEGER,
764 },{
765 .id = V4L2_CID_PRIVATE_WHITECRUSH_LOWER,
766 .name = "whitecrush lower",
767 .minimum = 0,
768 .maximum = 255,
769 .step = 1,
770 .default_value = 0x7F,
771 .type = V4L2_CTRL_TYPE_INTEGER,
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700772 },{
773 .id = V4L2_CID_PRIVATE_UV_RATIO,
774 .name = "uv ratio",
775 .minimum = 0,
776 .maximum = 100,
777 .step = 1,
778 .default_value = 50,
779 .type = V4L2_CTRL_TYPE_INTEGER,
780 },{
781 .id = V4L2_CID_PRIVATE_FULL_LUMA_RANGE,
782 .name = "full luma range",
783 .minimum = 0,
784 .maximum = 1,
785 .type = V4L2_CTRL_TYPE_BOOLEAN,
786 },{
787 .id = V4L2_CID_PRIVATE_CORING,
788 .name = "coring",
789 .minimum = 0,
790 .maximum = 3,
791 .step = 1,
792 .default_value = 0,
793 .type = V4L2_CTRL_TYPE_INTEGER,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 }
795
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700796
797
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -0300800static const struct v4l2_queryctrl *ctrl_by_id(int id)
801{
802 int i;
803
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -0300804 for (i = 0; i < ARRAY_SIZE(bttv_ctls); i++)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -0300805 if (bttv_ctls[i].id == id)
806 return bttv_ctls+i;
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -0300807
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -0300808 return NULL;
809}
810
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811/* ----------------------------------------------------------------------- */
812/* resource management */
813
Michael Schimeke5bd0262007-01-18 16:17:39 -0300814/*
815 RESOURCE_ allocated by freed by
816
817 VIDEO_READ bttv_read 1) bttv_read 2)
818
819 VIDEO_STREAM VIDIOC_STREAMON VIDIOC_STREAMOFF
820 VIDIOC_QBUF 1) bttv_release
821 VIDIOCMCAPTURE 1)
822
823 OVERLAY VIDIOCCAPTURE on VIDIOCCAPTURE off
824 VIDIOC_OVERLAY on VIDIOC_OVERLAY off
825 3) bttv_release
826
827 VBI VIDIOC_STREAMON VIDIOC_STREAMOFF
828 VIDIOC_QBUF 1) bttv_release
829 bttv_read, bttv_poll 1) 4)
830
831 1) The resource must be allocated when we enter buffer prepare functions
832 and remain allocated while buffers are in the DMA queue.
833 2) This is a single frame read.
834 3) VIDIOC_S_FBUF and VIDIOC_S_FMT (OVERLAY) still work when
835 RESOURCE_OVERLAY is allocated.
836 4) This is a continuous read, implies VIDIOC_STREAMON.
837
838 Note this driver permits video input and standard changes regardless if
839 resources are allocated.
840*/
841
842#define VBI_RESOURCES (RESOURCE_VBI)
843#define VIDEO_RESOURCES (RESOURCE_VIDEO_READ | \
844 RESOURCE_VIDEO_STREAM | \
845 RESOURCE_OVERLAY)
846
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847static
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -0300848int check_alloc_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849{
Michael Schimeke5bd0262007-01-18 16:17:39 -0300850 int xbits; /* mutual exclusive resources */
851
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 if (fh->resources & bit)
853 /* have it already allocated */
854 return 1;
855
Michael Schimeke5bd0262007-01-18 16:17:39 -0300856 xbits = bit;
857 if (bit & (RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM))
858 xbits |= RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM;
859
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860 /* is it free? */
Michael Schimeke5bd0262007-01-18 16:17:39 -0300861 if (btv->resources & xbits) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 /* no, someone else uses it */
Michael Schimeke5bd0262007-01-18 16:17:39 -0300863 goto fail;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 }
Michael Schimeke5bd0262007-01-18 16:17:39 -0300865
866 if ((bit & VIDEO_RESOURCES)
867 && 0 == (btv->resources & VIDEO_RESOURCES)) {
868 /* Do crop - use current, don't - use default parameters. */
869 __s32 top = btv->crop[!!fh->do_crop].rect.top;
870
871 if (btv->vbi_end > top)
872 goto fail;
873
874 /* We cannot capture the same line as video and VBI data.
875 Claim scan lines crop[].rect.top to bottom. */
876 btv->crop_start = top;
877 } else if (bit & VBI_RESOURCES) {
878 __s32 end = fh->vbi_fmt.end;
879
880 if (end > btv->crop_start)
881 goto fail;
882
883 /* Claim scan lines above fh->vbi_fmt.end. */
884 btv->vbi_end = end;
885 }
886
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887 /* it's free, grab it */
888 fh->resources |= bit;
889 btv->resources |= bit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 return 1;
Michael Schimeke5bd0262007-01-18 16:17:39 -0300891
892 fail:
Michael Schimeke5bd0262007-01-18 16:17:39 -0300893 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894}
895
896static
897int check_btres(struct bttv_fh *fh, int bit)
898{
899 return (fh->resources & bit);
900}
901
902static
903int locked_btres(struct bttv *btv, int bit)
904{
905 return (btv->resources & bit);
906}
907
Michael Schimeke5bd0262007-01-18 16:17:39 -0300908/* Call with btv->lock down. */
909static void
910disclaim_vbi_lines(struct bttv *btv)
911{
912 btv->vbi_end = 0;
913}
914
915/* Call with btv->lock down. */
916static void
917disclaim_video_lines(struct bttv *btv)
918{
919 const struct bttv_tvnorm *tvnorm;
920 u8 crop;
921
922 tvnorm = &bttv_tvnorms[btv->tvnorm];
923 btv->crop_start = tvnorm->cropcap.bounds.top
924 + tvnorm->cropcap.bounds.height;
925
926 /* VBI capturing ends at VDELAY, start of video capturing, no
927 matter how many lines the VBI RISC program expects. When video
928 capturing is off, it shall no longer "preempt" VBI capturing,
929 so we set VDELAY to maximum. */
930 crop = btread(BT848_E_CROP) | 0xc0;
931 btwrite(crop, BT848_E_CROP);
932 btwrite(0xfe, BT848_E_VDELAY_LO);
933 btwrite(crop, BT848_O_CROP);
934 btwrite(0xfe, BT848_O_VDELAY_LO);
935}
936
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937static
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -0300938void free_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bits)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 if ((fh->resources & bits) != bits) {
Joe Perches8af443e2011-08-21 19:56:48 -0300941 /* trying to free resources not allocated by us ... */
942 pr_err("BUG! (btres)\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 fh->resources &= ~bits;
945 btv->resources &= ~bits;
Michael Schimeke5bd0262007-01-18 16:17:39 -0300946
947 bits = btv->resources;
948
949 if (0 == (bits & VIDEO_RESOURCES))
950 disclaim_video_lines(btv);
951
952 if (0 == (bits & VBI_RESOURCES))
953 disclaim_vbi_lines(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954}
955
956/* ----------------------------------------------------------------------- */
957/* If Bt848a or Bt849, use PLL for PAL/SECAM and crystal for NTSC */
958
959/* Frequency = (F_input / PLL_X) * PLL_I.PLL_F/PLL_C
960 PLL_X = Reference pre-divider (0=1, 1=2)
961 PLL_C = Post divider (0=6, 1=4)
962 PLL_I = Integer input
963 PLL_F = Fractional input
964
965 F_input = 28.636363 MHz:
966 PAL (CLKx2 = 35.46895 MHz): PLL_X = 1, PLL_I = 0x0E, PLL_F = 0xDCF9, PLL_C = 0
967*/
968
969static void set_pll_freq(struct bttv *btv, unsigned int fin, unsigned int fout)
970{
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800971 unsigned char fl, fh, fi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800973 /* prevent overflows */
974 fin/=4;
975 fout/=4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800977 fout*=12;
978 fi=fout/fin;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800980 fout=(fout%fin)*256;
981 fh=fout/fin;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800983 fout=(fout%fin)*256;
984 fl=fout/fin;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800986 btwrite(fl, BT848_PLL_F_LO);
987 btwrite(fh, BT848_PLL_F_HI);
988 btwrite(fi|BT848_PLL_X, BT848_PLL_XCI);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989}
990
991static void set_pll(struct bttv *btv)
992{
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800993 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800995 if (!btv->pll.pll_crystal)
996 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997
998 if (btv->pll.pll_ofreq == btv->pll.pll_current) {
Joe Perches8af443e2011-08-21 19:56:48 -0300999 dprintk("%d: PLL: no change required\n", btv->c.nr);
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -08001000 return;
1001 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -08001003 if (btv->pll.pll_ifreq == btv->pll.pll_ofreq) {
1004 /* no PLL needed */
1005 if (btv->pll.pll_current == 0)
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -08001006 return;
Joe Perches8af443e2011-08-21 19:56:48 -03001007 if (bttv_verbose)
1008 pr_info("%d: PLL can sleep, using XTAL (%d)\n",
1009 btv->c.nr, btv->pll.pll_ifreq);
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -08001010 btwrite(0x00,BT848_TGCTRL);
1011 btwrite(0x00,BT848_PLL_XCI);
1012 btv->pll.pll_current = 0;
1013 return;
1014 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015
Joe Perches8af443e2011-08-21 19:56:48 -03001016 if (bttv_verbose)
1017 pr_info("%d: Setting PLL: %d => %d (needs up to 100ms)\n",
1018 btv->c.nr,
1019 btv->pll.pll_ifreq, btv->pll.pll_ofreq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 set_pll_freq(btv, btv->pll.pll_ifreq, btv->pll.pll_ofreq);
1021
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -08001022 for (i=0; i<10; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 /* Let other people run while the PLL stabilizes */
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;
Joe Perches8af443e2011-08-21 19:56:48 -03001031 if (bttv_verbose)
1032 pr_info("PLL set ok\n");
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -08001033 return;
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -08001034 }
1035 }
1036 btv->pll.pll_current = -1;
Joe Perches8af443e2011-08-21 19:56:48 -03001037 if (bttv_verbose)
1038 pr_info("Setting PLL failed\n");
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -08001039 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040}
1041
1042/* used to switch between the bt848's analog/digital video capture modes */
1043static void bt848A_set_timing(struct bttv *btv)
1044{
1045 int i, len;
1046 int table_idx = bttv_tvnorms[btv->tvnorm].sram;
1047 int fsc = bttv_tvnorms[btv->tvnorm].Fsc;
1048
Trent Piepho5221e212009-01-28 21:32:59 -03001049 if (btv->input == btv->dig) {
Joe Perches8af443e2011-08-21 19:56:48 -03001050 dprintk("%d: load digital timing table (table_idx=%d)\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 btv->c.nr,table_idx);
1052
1053 /* timing change...reset timing generator address */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001054 btwrite(0x00, BT848_TGCTRL);
1055 btwrite(0x02, BT848_TGCTRL);
1056 btwrite(0x00, BT848_TGCTRL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057
1058 len=SRAM_Table[table_idx][0];
1059 for(i = 1; i <= len; i++)
1060 btwrite(SRAM_Table[table_idx][i],BT848_TGLB);
1061 btv->pll.pll_ofreq = 27000000;
1062
1063 set_pll(btv);
1064 btwrite(0x11, BT848_TGCTRL);
1065 btwrite(0x41, BT848_DVSIF);
1066 } else {
1067 btv->pll.pll_ofreq = fsc;
1068 set_pll(btv);
1069 btwrite(0x0, BT848_DVSIF);
1070 }
1071}
1072
1073/* ----------------------------------------------------------------------- */
1074
1075static void bt848_bright(struct bttv *btv, int bright)
1076{
1077 int value;
1078
Joe Perches8af443e2011-08-21 19:56:48 -03001079 // printk("set bright: %d\n", bright); // DEBUG
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 btv->bright = bright;
1081
1082 /* We want -128 to 127 we get 0-65535 */
1083 value = (bright >> 8) - 128;
1084 btwrite(value & 0xff, BT848_BRIGHT);
1085}
1086
1087static void bt848_hue(struct bttv *btv, int hue)
1088{
1089 int value;
1090
1091 btv->hue = hue;
1092
1093 /* -128 to 127 */
1094 value = (hue >> 8) - 128;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001095 btwrite(value & 0xff, BT848_HUE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096}
1097
1098static void bt848_contrast(struct bttv *btv, int cont)
1099{
1100 int value,hibit;
1101
1102 btv->contrast = cont;
1103
1104 /* 0-511 */
1105 value = (cont >> 7);
1106 hibit = (value >> 6) & 4;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001107 btwrite(value & 0xff, BT848_CONTRAST_LO);
1108 btaor(hibit, ~4, BT848_E_CONTROL);
1109 btaor(hibit, ~4, BT848_O_CONTROL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110}
1111
1112static void bt848_sat(struct bttv *btv, int color)
1113{
1114 int val_u,val_v,hibits;
1115
1116 btv->saturation = color;
1117
1118 /* 0-511 for the color */
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -07001119 val_u = ((color * btv->opt_uv_ratio) / 50) >> 7;
1120 val_v = (((color * (100 - btv->opt_uv_ratio) / 50) >>7)*180L)/254;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001121 hibits = (val_u >> 7) & 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 hibits |= (val_v >> 8) & 1;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001123 btwrite(val_u & 0xff, BT848_SAT_U_LO);
1124 btwrite(val_v & 0xff, BT848_SAT_V_LO);
1125 btaor(hibits, ~3, BT848_E_CONTROL);
1126 btaor(hibits, ~3, BT848_O_CONTROL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127}
1128
1129/* ----------------------------------------------------------------------- */
1130
1131static int
1132video_mux(struct bttv *btv, unsigned int input)
1133{
1134 int mux,mask2;
1135
1136 if (input >= bttv_tvcards[btv->c.type].video_inputs)
1137 return -EINVAL;
1138
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001139 /* needed by RemoteVideo MX */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 mask2 = bttv_tvcards[btv->c.type].gpiomask2;
1141 if (mask2)
1142 gpio_inout(mask2,mask2);
1143
1144 if (input == btv->svhs) {
1145 btor(BT848_CONTROL_COMP, BT848_E_CONTROL);
1146 btor(BT848_CONTROL_COMP, BT848_O_CONTROL);
1147 } else {
1148 btand(~BT848_CONTROL_COMP, BT848_E_CONTROL);
1149 btand(~BT848_CONTROL_COMP, BT848_O_CONTROL);
1150 }
Trent Piepho6f987002009-01-28 21:32:59 -03001151 mux = bttv_muxsel(btv, input);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152 btaor(mux<<5, ~(3<<5), BT848_IFORM);
Joe Perches8af443e2011-08-21 19:56:48 -03001153 dprintk("%d: video mux: input=%d mux=%d\n", btv->c.nr, input, mux);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154
1155 /* card specific hook */
1156 if(bttv_tvcards[btv->c.type].muxsel_hook)
1157 bttv_tvcards[btv->c.type].muxsel_hook (btv, input);
1158 return 0;
1159}
1160
1161static char *audio_modes[] = {
1162 "audio: tuner", "audio: radio", "audio: extern",
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001163 "audio: intern", "audio: mute"
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164};
1165
1166static int
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001167audio_mux(struct bttv *btv, int input, int mute)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168{
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001169 int gpio_val, signal;
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001170 struct v4l2_control ctrl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171
1172 gpio_inout(bttv_tvcards[btv->c.type].gpiomask,
1173 bttv_tvcards[btv->c.type].gpiomask);
1174 signal = btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC;
1175
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001176 btv->mute = mute;
1177 btv->audio = input;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001179 /* automute */
1180 mute = mute || (btv->opt_automute && !signal && !btv->radio_user);
1181
1182 if (mute)
1183 gpio_val = bttv_tvcards[btv->c.type].gpiomute;
1184 else
1185 gpio_val = bttv_tvcards[btv->c.type].gpiomux[input];
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001186
Trent Piepho72134a62009-01-28 21:32:59 -03001187 switch (btv->c.type) {
1188 case BTTV_BOARD_VOODOOTV_FM:
1189 case BTTV_BOARD_VOODOOTV_200:
1190 gpio_val = bttv_tda9880_setnorm(btv, gpio_val);
1191 break;
1192
1193 default:
1194 gpio_bits(bttv_tvcards[btv->c.type].gpiomask, gpio_val);
1195 }
1196
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197 if (bttv_gpio)
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001198 bttv_gpio_tracking(btv, audio_modes[mute ? 4 : input]);
1199 if (in_interrupt())
1200 return 0;
1201
1202 ctrl.id = V4L2_CID_AUDIO_MUTE;
Hans Verkuil2474ed42006-03-19 12:35:57 -03001203 ctrl.value = btv->mute;
Hans Verkuil859f0272009-03-28 08:29:00 -03001204 bttv_call_all(btv, core, s_ctrl, &ctrl);
1205 if (btv->sd_msp34xx) {
Hans Verkuil5325b422009-04-02 11:26:22 -03001206 u32 in;
Hans Verkuil2474ed42006-03-19 12:35:57 -03001207
1208 /* Note: the inputs tuner/radio/extern/intern are translated
1209 to msp routings. This assumes common behavior for all msp3400
1210 based TV cards. When this assumption fails, then the
1211 specific MSP routing must be added to the card table.
1212 For now this is sufficient. */
1213 switch (input) {
1214 case TVAUDIO_INPUT_RADIO:
Hans de Goede7025e522012-05-21 07:46:22 -03001215 /* Some boards need the msp do to the radio demod */
1216 if (btv->radio_uses_msp_demodulator) {
1217 in = MSP_INPUT_DEFAULT;
1218 break;
1219 }
Hans Verkuil5325b422009-04-02 11:26:22 -03001220 in = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1,
Hans Verkuil07151722006-04-01 18:03:23 -03001221 MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001222 break;
1223 case TVAUDIO_INPUT_EXTERN:
Hans Verkuil5325b422009-04-02 11:26:22 -03001224 in = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1,
Hans Verkuil07151722006-04-01 18:03:23 -03001225 MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001226 break;
1227 case TVAUDIO_INPUT_INTERN:
1228 /* Yes, this is the same input as for RADIO. I doubt
1229 if this is ever used. The only board with an INTERN
1230 input is the BTTV_BOARD_AVERMEDIA98. I wonder how
1231 that was tested. My guess is that the whole INTERN
1232 input does not work. */
Hans Verkuil5325b422009-04-02 11:26:22 -03001233 in = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1,
Hans Verkuil07151722006-04-01 18:03:23 -03001234 MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001235 break;
1236 case TVAUDIO_INPUT_TUNER:
1237 default:
Wade Berrier434b2522007-06-25 13:02:16 -03001238 /* This is the only card that uses TUNER2, and afaik,
1239 is the only difference between the VOODOOTV_FM
1240 and VOODOOTV_200 */
1241 if (btv->c.type == BTTV_BOARD_VOODOOTV_200)
Hans Verkuil5325b422009-04-02 11:26:22 -03001242 in = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER2, \
Wade Berrier434b2522007-06-25 13:02:16 -03001243 MSP_DSP_IN_TUNER, MSP_DSP_IN_TUNER);
1244 else
Hans Verkuil5325b422009-04-02 11:26:22 -03001245 in = MSP_INPUT_DEFAULT;
Hans Verkuil2474ed42006-03-19 12:35:57 -03001246 break;
1247 }
Hans Verkuil5325b422009-04-02 11:26:22 -03001248 v4l2_subdev_call(btv->sd_msp34xx, audio, s_routing,
1249 in, MSP_OUTPUT_DEFAULT, 0);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001250 }
Hans Verkuil859f0272009-03-28 08:29:00 -03001251 if (btv->sd_tvaudio) {
Hans Verkuil5325b422009-04-02 11:26:22 -03001252 v4l2_subdev_call(btv->sd_tvaudio, audio, s_routing,
1253 input, 0, 0);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001254 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255 return 0;
1256}
1257
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001258static inline int
1259audio_mute(struct bttv *btv, int mute)
1260{
1261 return audio_mux(btv, btv->audio, mute);
1262}
1263
1264static inline int
1265audio_input(struct bttv *btv, int input)
1266{
1267 return audio_mux(btv, input, btv->mute);
1268}
1269
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270static void
Michael Schimeke5bd0262007-01-18 16:17:39 -03001271bttv_crop_calc_limits(struct bttv_crop *c)
1272{
1273 /* Scale factor min. 1:1, max. 16:1. Min. image size
1274 48 x 32. Scaled width must be a multiple of 4. */
1275
1276 if (1) {
1277 /* For bug compatibility with VIDIOCGCAP and image
1278 size checks in earlier driver versions. */
1279 c->min_scaled_width = 48;
1280 c->min_scaled_height = 32;
1281 } else {
1282 c->min_scaled_width =
1283 (max(48, c->rect.width >> 4) + 3) & ~3;
1284 c->min_scaled_height =
1285 max(32, c->rect.height >> 4);
1286 }
1287
1288 c->max_scaled_width = c->rect.width & ~3;
1289 c->max_scaled_height = c->rect.height;
1290}
1291
1292static void
Trent Piepho4ef2ccc2009-01-28 21:32:58 -03001293bttv_crop_reset(struct bttv_crop *c, unsigned int norm)
Michael Schimeke5bd0262007-01-18 16:17:39 -03001294{
1295 c->rect = bttv_tvnorms[norm].cropcap.defrect;
1296 bttv_crop_calc_limits(c);
1297}
1298
1299/* Call with btv->lock down. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300static int
1301set_tvnorm(struct bttv *btv, unsigned int norm)
1302{
1303 const struct bttv_tvnorm *tvnorm;
Nickolay V. Shmyrev302f61a2007-10-26 10:53:21 -03001304 v4l2_std_id id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305
Trent Piepho4ef2ccc2009-01-28 21:32:58 -03001306 BUG_ON(norm >= BTTV_TVNORMS);
1307 BUG_ON(btv->tvnorm >= BTTV_TVNORMS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 tvnorm = &bttv_tvnorms[norm];
1310
Mike Isely2de26c02009-09-21 12:42:22 -03001311 if (memcmp(&bttv_tvnorms[btv->tvnorm].cropcap, &tvnorm->cropcap,
Trent Piepho4ef2ccc2009-01-28 21:32:58 -03001312 sizeof (tvnorm->cropcap))) {
Michael Schimeke5bd0262007-01-18 16:17:39 -03001313 bttv_crop_reset(&btv->crop[0], norm);
1314 btv->crop[1] = btv->crop[0]; /* current = default */
1315
1316 if (0 == (btv->resources & VIDEO_RESOURCES)) {
1317 btv->crop_start = tvnorm->cropcap.bounds.top
1318 + tvnorm->cropcap.bounds.height;
1319 }
1320 }
1321
1322 btv->tvnorm = norm;
1323
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 btwrite(tvnorm->adelay, BT848_ADELAY);
1325 btwrite(tvnorm->bdelay, BT848_BDELAY);
1326 btaor(tvnorm->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH),
1327 BT848_IFORM);
1328 btwrite(tvnorm->vbipack, BT848_VBI_PACK_SIZE);
1329 btwrite(1, BT848_VBI_PACK_DEL);
1330 bt848A_set_timing(btv);
1331
1332 switch (btv->c.type) {
Mauro Carvalho Chehab5a25e842005-11-08 21:36:52 -08001333 case BTTV_BOARD_VOODOOTV_FM:
Wade Berrier434b2522007-06-25 13:02:16 -03001334 case BTTV_BOARD_VOODOOTV_200:
Trent Piepho72134a62009-01-28 21:32:59 -03001335 bttv_tda9880_setnorm(btv, gpio_read());
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337 }
Nickolay V. Shmyrev302f61a2007-10-26 10:53:21 -03001338 id = tvnorm->v4l2_id;
Hans Verkuilf41737e2009-04-01 03:52:39 -03001339 bttv_call_all(btv, core, s_std, id);
Nickolay V. Shmyrev302f61a2007-10-26 10:53:21 -03001340
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 return 0;
1342}
1343
Michael Schimeke5bd0262007-01-18 16:17:39 -03001344/* Call with btv->lock down. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345static void
Trent Piepho333408f2007-07-03 15:08:10 -03001346set_input(struct bttv *btv, unsigned int input, unsigned int norm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347{
1348 unsigned long flags;
1349
1350 btv->input = input;
1351 if (irq_iswitch) {
1352 spin_lock_irqsave(&btv->s_lock,flags);
1353 if (btv->curr.frame_irq) {
1354 /* active capture -> delayed input switch */
1355 btv->new_input = input;
1356 } else {
1357 video_mux(btv,input);
1358 }
1359 spin_unlock_irqrestore(&btv->s_lock,flags);
1360 } else {
1361 video_mux(btv,input);
1362 }
Trent Piephoabb03622009-01-28 21:32:59 -03001363 audio_input(btv, (btv->tuner_type != TUNER_ABSENT && input == 0) ?
1364 TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN);
Trent Piepho333408f2007-07-03 15:08:10 -03001365 set_tvnorm(btv, norm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366}
1367
1368static void init_irqreg(struct bttv *btv)
1369{
1370 /* clear status */
1371 btwrite(0xfffffUL, BT848_INT_STAT);
1372
1373 if (bttv_tvcards[btv->c.type].no_video) {
1374 /* i2c only */
1375 btwrite(BT848_INT_I2CDONE,
1376 BT848_INT_MASK);
1377 } else {
1378 /* full video */
1379 btwrite((btv->triton1) |
1380 (btv->gpioirq ? BT848_INT_GPINT : 0) |
1381 BT848_INT_SCERR |
1382 (fdsr ? BT848_INT_FDSR : 0) |
Jean Delvareeb1b27b2008-08-30 10:18:21 -03001383 BT848_INT_RISCI | BT848_INT_OCERR |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384 BT848_INT_FMTCHG|BT848_INT_HLOCK|
1385 BT848_INT_I2CDONE,
1386 BT848_INT_MASK);
1387 }
1388}
1389
1390static void init_bt848(struct bttv *btv)
1391{
1392 int val;
1393
1394 if (bttv_tvcards[btv->c.type].no_video) {
1395 /* very basic init only */
1396 init_irqreg(btv);
1397 return;
1398 }
1399
1400 btwrite(0x00, BT848_CAP_CTL);
1401 btwrite(BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL);
1402 btwrite(BT848_IFORM_XTAUTO | BT848_IFORM_AUTO, BT848_IFORM);
1403
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001404 /* set planar and packed mode trigger points and */
1405 /* set rising edge of inverted GPINTR pin as irq trigger */
1406 btwrite(BT848_GPIO_DMA_CTL_PKTP_32|
1407 BT848_GPIO_DMA_CTL_PLTP1_16|
1408 BT848_GPIO_DMA_CTL_PLTP23_16|
1409 BT848_GPIO_DMA_CTL_GPINTC|
1410 BT848_GPIO_DMA_CTL_GPINTI,
1411 BT848_GPIO_DMA_CTL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412
1413 val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001414 btwrite(val, BT848_E_SCLOOP);
1415 btwrite(val, BT848_O_SCLOOP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001417 btwrite(0x20, BT848_E_VSCALE_HI);
1418 btwrite(0x20, BT848_O_VSCALE_HI);
1419 btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420 BT848_ADC);
1421
1422 btwrite(whitecrush_upper, BT848_WC_UP);
1423 btwrite(whitecrush_lower, BT848_WC_DOWN);
1424
1425 if (btv->opt_lumafilter) {
1426 btwrite(0, BT848_E_CONTROL);
1427 btwrite(0, BT848_O_CONTROL);
1428 } else {
1429 btwrite(BT848_CONTROL_LDEC, BT848_E_CONTROL);
1430 btwrite(BT848_CONTROL_LDEC, BT848_O_CONTROL);
1431 }
1432
1433 bt848_bright(btv, btv->bright);
1434 bt848_hue(btv, btv->hue);
1435 bt848_contrast(btv, btv->contrast);
1436 bt848_sat(btv, btv->saturation);
1437
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001438 /* interrupt */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439 init_irqreg(btv);
1440}
1441
1442static void bttv_reinit_bt848(struct bttv *btv)
1443{
1444 unsigned long flags;
1445
1446 if (bttv_verbose)
Joe Perches8af443e2011-08-21 19:56:48 -03001447 pr_info("%d: reset, reinitialize\n", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448 spin_lock_irqsave(&btv->s_lock,flags);
1449 btv->errors=0;
1450 bttv_set_dma(btv,0);
1451 spin_unlock_irqrestore(&btv->s_lock,flags);
1452
1453 init_bt848(btv);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001454 btv->pll.pll_current = -1;
Trent Piepho333408f2007-07-03 15:08:10 -03001455 set_input(btv, btv->input, btv->tvnorm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456}
1457
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001458static int bttv_g_ctrl(struct file *file, void *priv,
1459 struct v4l2_control *c)
1460{
1461 struct bttv_fh *fh = priv;
1462 struct bttv *btv = fh->btv;
1463
1464 switch (c->id) {
1465 case V4L2_CID_BRIGHTNESS:
1466 c->value = btv->bright;
1467 break;
1468 case V4L2_CID_HUE:
1469 c->value = btv->hue;
1470 break;
1471 case V4L2_CID_CONTRAST:
1472 c->value = btv->contrast;
1473 break;
1474 case V4L2_CID_SATURATION:
1475 c->value = btv->saturation;
1476 break;
1477
1478 case V4L2_CID_AUDIO_MUTE:
1479 case V4L2_CID_AUDIO_VOLUME:
1480 case V4L2_CID_AUDIO_BALANCE:
1481 case V4L2_CID_AUDIO_BASS:
1482 case V4L2_CID_AUDIO_TREBLE:
Hans Verkuil859f0272009-03-28 08:29:00 -03001483 bttv_call_all(btv, core, g_ctrl, c);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001484 break;
1485
1486 case V4L2_CID_PRIVATE_CHROMA_AGC:
1487 c->value = btv->opt_chroma_agc;
1488 break;
1489 case V4L2_CID_PRIVATE_COMBFILTER:
1490 c->value = btv->opt_combfilter;
1491 break;
1492 case V4L2_CID_PRIVATE_LUMAFILTER:
1493 c->value = btv->opt_lumafilter;
1494 break;
1495 case V4L2_CID_PRIVATE_AUTOMUTE:
1496 c->value = btv->opt_automute;
1497 break;
1498 case V4L2_CID_PRIVATE_AGC_CRUSH:
1499 c->value = btv->opt_adc_crush;
1500 break;
1501 case V4L2_CID_PRIVATE_VCR_HACK:
1502 c->value = btv->opt_vcr_hack;
1503 break;
1504 case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
1505 c->value = btv->opt_whitecrush_upper;
1506 break;
1507 case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
1508 c->value = btv->opt_whitecrush_lower;
1509 break;
1510 case V4L2_CID_PRIVATE_UV_RATIO:
1511 c->value = btv->opt_uv_ratio;
1512 break;
1513 case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
1514 c->value = btv->opt_full_luma_range;
1515 break;
1516 case V4L2_CID_PRIVATE_CORING:
1517 c->value = btv->opt_coring;
1518 break;
1519 default:
1520 return -EINVAL;
1521 }
1522 return 0;
1523}
1524
1525static int bttv_s_ctrl(struct file *file, void *f,
1526 struct v4l2_control *c)
1527{
1528 int err;
1529 int val;
1530 struct bttv_fh *fh = f;
1531 struct bttv *btv = fh->btv;
1532
Hans Verkuilffb48772010-05-01 08:03:24 -03001533 err = v4l2_prio_check(&btv->prio, fh->prio);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001534 if (0 != err)
1535 return err;
1536
1537 switch (c->id) {
1538 case V4L2_CID_BRIGHTNESS:
1539 bt848_bright(btv, c->value);
1540 break;
1541 case V4L2_CID_HUE:
1542 bt848_hue(btv, c->value);
1543 break;
1544 case V4L2_CID_CONTRAST:
1545 bt848_contrast(btv, c->value);
1546 break;
1547 case V4L2_CID_SATURATION:
1548 bt848_sat(btv, c->value);
1549 break;
1550 case V4L2_CID_AUDIO_MUTE:
1551 audio_mute(btv, c->value);
1552 /* fall through */
1553 case V4L2_CID_AUDIO_VOLUME:
1554 if (btv->volume_gpio)
1555 btv->volume_gpio(btv, c->value);
1556
Hans Verkuil859f0272009-03-28 08:29:00 -03001557 bttv_call_all(btv, core, s_ctrl, c);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001558 break;
1559 case V4L2_CID_AUDIO_BALANCE:
1560 case V4L2_CID_AUDIO_BASS:
1561 case V4L2_CID_AUDIO_TREBLE:
Hans Verkuil859f0272009-03-28 08:29:00 -03001562 bttv_call_all(btv, core, s_ctrl, c);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001563 break;
1564
1565 case V4L2_CID_PRIVATE_CHROMA_AGC:
1566 btv->opt_chroma_agc = c->value;
1567 val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
1568 btwrite(val, BT848_E_SCLOOP);
1569 btwrite(val, BT848_O_SCLOOP);
1570 break;
1571 case V4L2_CID_PRIVATE_COMBFILTER:
1572 btv->opt_combfilter = c->value;
1573 break;
1574 case V4L2_CID_PRIVATE_LUMAFILTER:
1575 btv->opt_lumafilter = c->value;
1576 if (btv->opt_lumafilter) {
1577 btand(~BT848_CONTROL_LDEC, BT848_E_CONTROL);
1578 btand(~BT848_CONTROL_LDEC, BT848_O_CONTROL);
1579 } else {
1580 btor(BT848_CONTROL_LDEC, BT848_E_CONTROL);
1581 btor(BT848_CONTROL_LDEC, BT848_O_CONTROL);
1582 }
1583 break;
1584 case V4L2_CID_PRIVATE_AUTOMUTE:
1585 btv->opt_automute = c->value;
1586 break;
1587 case V4L2_CID_PRIVATE_AGC_CRUSH:
1588 btv->opt_adc_crush = c->value;
1589 btwrite(BT848_ADC_RESERVED |
1590 (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
1591 BT848_ADC);
1592 break;
1593 case V4L2_CID_PRIVATE_VCR_HACK:
1594 btv->opt_vcr_hack = c->value;
1595 break;
1596 case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
1597 btv->opt_whitecrush_upper = c->value;
1598 btwrite(c->value, BT848_WC_UP);
1599 break;
1600 case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
1601 btv->opt_whitecrush_lower = c->value;
1602 btwrite(c->value, BT848_WC_DOWN);
1603 break;
1604 case V4L2_CID_PRIVATE_UV_RATIO:
1605 btv->opt_uv_ratio = c->value;
1606 bt848_sat(btv, btv->saturation);
1607 break;
1608 case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
1609 btv->opt_full_luma_range = c->value;
1610 btaor((c->value<<7), ~BT848_OFORM_RANGE, BT848_OFORM);
1611 break;
1612 case V4L2_CID_PRIVATE_CORING:
1613 btv->opt_coring = c->value;
1614 btaor((c->value<<5), ~BT848_OFORM_CORE32, BT848_OFORM);
1615 break;
1616 default:
1617 return -EINVAL;
1618 }
1619 return 0;
1620}
1621
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622/* ----------------------------------------------------------------------- */
1623
1624void bttv_gpio_tracking(struct bttv *btv, char *comment)
1625{
1626 unsigned int outbits, data;
1627 outbits = btread(BT848_GPIO_OUT_EN);
1628 data = btread(BT848_GPIO_DATA);
Joe Perches8af443e2011-08-21 19:56:48 -03001629 pr_debug("%d: gpio: en=%08x, out=%08x in=%08x [%s]\n",
1630 btv->c.nr, outbits, data & outbits, data & ~outbits, comment);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631}
1632
1633static void bttv_field_count(struct bttv *btv)
1634{
1635 int need_count = 0;
1636
1637 if (btv->users)
1638 need_count++;
1639
1640 if (need_count) {
1641 /* start field counter */
1642 btor(BT848_INT_VSYNC,BT848_INT_MASK);
1643 } else {
1644 /* stop field counter */
1645 btand(~BT848_INT_VSYNC,BT848_INT_MASK);
1646 btv->field_count = 0;
1647 }
1648}
1649
1650static const struct bttv_format*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651format_by_fourcc(int fourcc)
1652{
1653 unsigned int i;
1654
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001655 for (i = 0; i < FORMATS; i++) {
1656 if (-1 == formats[i].fourcc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 continue;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001658 if (formats[i].fourcc == fourcc)
1659 return formats+i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 }
1661 return NULL;
1662}
1663
1664/* ----------------------------------------------------------------------- */
1665/* misc helpers */
1666
1667static int
1668bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh,
1669 struct bttv_buffer *new)
1670{
1671 struct bttv_buffer *old;
1672 unsigned long flags;
1673 int retval = 0;
1674
Joe Perches8af443e2011-08-21 19:56:48 -03001675 dprintk("switch_overlay: enter [new=%p]\n", new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676 if (new)
Brandon Philips0fc06862007-11-06 20:02:36 -03001677 new->vb.state = VIDEOBUF_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 spin_lock_irqsave(&btv->s_lock,flags);
1679 old = btv->screen;
1680 btv->screen = new;
1681 btv->loop_irq |= 1;
1682 bttv_set_dma(btv, 0x03);
1683 spin_unlock_irqrestore(&btv->s_lock,flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684 if (NULL != old) {
Joe Perches8af443e2011-08-21 19:56:48 -03001685 dprintk("switch_overlay: old=%p state is %d\n",
1686 old, old->vb.state);
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001687 bttv_dma_free(&fh->cap,btv, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688 kfree(old);
1689 }
Michael Schimeke5bd0262007-01-18 16:17:39 -03001690 if (NULL == new)
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03001691 free_btres_lock(btv,fh,RESOURCE_OVERLAY);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692 dprintk("switch_overlay: done\n");
1693 return retval;
1694}
1695
1696/* ----------------------------------------------------------------------- */
1697/* video4linux (1) interface */
1698
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001699static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv,
1700 struct bttv_buffer *buf,
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001701 const struct bttv_format *fmt,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 unsigned int width, unsigned int height,
1703 enum v4l2_field field)
1704{
Michael Schimeke5bd0262007-01-18 16:17:39 -03001705 struct bttv_fh *fh = q->priv_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706 int redo_dma_risc = 0;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001707 struct bttv_crop c;
1708 int norm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 int rc;
1710
1711 /* check settings */
1712 if (NULL == fmt)
1713 return -EINVAL;
1714 if (fmt->btformat == BT848_COLOR_FMT_RAW) {
1715 width = RAW_BPL;
1716 height = RAW_LINES*2;
1717 if (width*height > buf->vb.bsize)
1718 return -EINVAL;
1719 buf->vb.size = buf->vb.bsize;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001720
1721 /* Make sure tvnorm and vbi_end remain consistent
1722 until we're done. */
Michael Schimeke5bd0262007-01-18 16:17:39 -03001723
1724 norm = btv->tvnorm;
1725
1726 /* In this mode capturing always starts at defrect.top
1727 (default VDELAY), ignoring cropping parameters. */
1728 if (btv->vbi_end > bttv_tvnorms[norm].cropcap.defrect.top) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729 return -EINVAL;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001730 }
1731
Michael Schimeke5bd0262007-01-18 16:17:39 -03001732 c.rect = bttv_tvnorms[norm].cropcap.defrect;
1733 } else {
Michael Schimeke5bd0262007-01-18 16:17:39 -03001734 norm = btv->tvnorm;
1735 c = btv->crop[!!fh->do_crop];
1736
Michael Schimeke5bd0262007-01-18 16:17:39 -03001737 if (width < c.min_scaled_width ||
1738 width > c.max_scaled_width ||
1739 height < c.min_scaled_height)
1740 return -EINVAL;
1741
1742 switch (field) {
1743 case V4L2_FIELD_TOP:
1744 case V4L2_FIELD_BOTTOM:
1745 case V4L2_FIELD_ALTERNATE:
1746 /* btv->crop counts frame lines. Max. scale
1747 factor is 16:1 for frames, 8:1 for fields. */
1748 if (height * 2 > c.max_scaled_height)
1749 return -EINVAL;
1750 break;
1751
1752 default:
1753 if (height > c.max_scaled_height)
1754 return -EINVAL;
1755 break;
1756 }
1757
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758 buf->vb.size = (width * height * fmt->depth) >> 3;
1759 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
1760 return -EINVAL;
1761 }
1762
1763 /* alloc + fill struct bttv_buffer (if changed) */
1764 if (buf->vb.width != width || buf->vb.height != height ||
1765 buf->vb.field != field ||
Michael Schimeke5bd0262007-01-18 16:17:39 -03001766 buf->tvnorm != norm || buf->fmt != fmt ||
1767 buf->crop.top != c.rect.top ||
1768 buf->crop.left != c.rect.left ||
1769 buf->crop.width != c.rect.width ||
1770 buf->crop.height != c.rect.height) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771 buf->vb.width = width;
1772 buf->vb.height = height;
1773 buf->vb.field = field;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001774 buf->tvnorm = norm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775 buf->fmt = fmt;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001776 buf->crop = c.rect;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777 redo_dma_risc = 1;
1778 }
1779
1780 /* alloc risc memory */
Brandon Philips0fc06862007-11-06 20:02:36 -03001781 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782 redo_dma_risc = 1;
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001783 if (0 != (rc = videobuf_iolock(q,&buf->vb,&btv->fbuf)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001784 goto fail;
1785 }
1786
1787 if (redo_dma_risc)
1788 if (0 != (rc = bttv_buffer_risc(btv,buf)))
1789 goto fail;
1790
Brandon Philips0fc06862007-11-06 20:02:36 -03001791 buf->vb.state = VIDEOBUF_PREPARED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792 return 0;
1793
1794 fail:
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001795 bttv_dma_free(q,btv,buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796 return rc;
1797}
1798
1799static int
1800buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
1801{
1802 struct bttv_fh *fh = q->priv_data;
1803
1804 *size = fh->fmt->depth*fh->width*fh->height >> 3;
1805 if (0 == *count)
1806 *count = gbuffers;
Andreas Bombedab7e312010-03-21 16:02:45 -03001807 if (*size * *count > gbuffers * gbufsize)
1808 *count = (gbuffers * gbufsize) / *size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809 return 0;
1810}
1811
1812static int
1813buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
1814 enum v4l2_field field)
1815{
1816 struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
1817 struct bttv_fh *fh = q->priv_data;
1818
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001819 return bttv_prepare_buffer(q,fh->btv, buf, fh->fmt,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820 fh->width, fh->height, field);
1821}
1822
1823static void
1824buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
1825{
1826 struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
1827 struct bttv_fh *fh = q->priv_data;
1828 struct bttv *btv = fh->btv;
1829
Brandon Philips0fc06862007-11-06 20:02:36 -03001830 buf->vb.state = VIDEOBUF_QUEUED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831 list_add_tail(&buf->vb.queue,&btv->capture);
1832 if (!btv->curr.frame_irq) {
1833 btv->loop_irq |= 1;
1834 bttv_set_dma(btv, 0x03);
1835 }
1836}
1837
1838static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
1839{
1840 struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
1841 struct bttv_fh *fh = q->priv_data;
1842
Michael Schimekfeaba7a2007-01-26 08:30:05 -03001843 bttv_dma_free(q,fh->btv,buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844}
1845
1846static struct videobuf_queue_ops bttv_video_qops = {
1847 .buf_setup = buffer_setup,
1848 .buf_prepare = buffer_prepare,
1849 .buf_queue = buffer_queue,
1850 .buf_release = buffer_release,
1851};
1852
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001853static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001855 struct bttv_fh *fh = priv;
1856 struct bttv *btv = fh->btv;
1857 unsigned int i;
1858 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859
Hans Verkuilffb48772010-05-01 08:03:24 -03001860 err = v4l2_prio_check(&btv->prio, fh->prio);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001861 if (err)
1862 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001864 for (i = 0; i < BTTV_TVNORMS; i++)
1865 if (*id & bttv_tvnorms[i].v4l2_id)
1866 break;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001867 if (i == BTTV_TVNORMS) {
1868 err = -EINVAL;
1869 goto err;
1870 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001872 set_tvnorm(btv, i);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001873
1874err:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001876 return err;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001877}
1878
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001879static int bttv_querystd(struct file *file, void *f, v4l2_std_id *id)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001880{
1881 struct bttv_fh *fh = f;
1882 struct bttv *btv = fh->btv;
1883
1884 if (btread(BT848_DSTATUS) & BT848_DSTATUS_NUML)
1885 *id = V4L2_STD_625_50;
1886 else
1887 *id = V4L2_STD_525_60;
1888 return 0;
1889}
1890
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001891static int bttv_enum_input(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001892 struct v4l2_input *i)
1893{
1894 struct bttv_fh *fh = priv;
1895 struct bttv *btv = fh->btv;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001896 int rc = 0;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001897
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001898 if (i->index >= bttv_tvcards[btv->c.type].video_inputs) {
1899 rc = -EINVAL;
1900 goto err;
1901 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001902
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001903 i->type = V4L2_INPUT_TYPE_CAMERA;
1904 i->audioset = 1;
1905
Trent Piephoabb03622009-01-28 21:32:59 -03001906 if (btv->tuner_type != TUNER_ABSENT && i->index == 0) {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001907 sprintf(i->name, "Television");
1908 i->type = V4L2_INPUT_TYPE_TUNER;
1909 i->tuner = 0;
1910 } else if (i->index == btv->svhs) {
1911 sprintf(i->name, "S-Video");
1912 } else {
1913 sprintf(i->name, "Composite%d", i->index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914 }
1915
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001916 if (i->index == btv->input) {
1917 __u32 dstatus = btread(BT848_DSTATUS);
1918 if (0 == (dstatus & BT848_DSTATUS_PRES))
1919 i->status |= V4L2_IN_ST_NO_SIGNAL;
1920 if (0 == (dstatus & BT848_DSTATUS_HLOC))
1921 i->status |= V4L2_IN_ST_NO_H_LOCK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922 }
1923
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001924 i->std = BTTV_NORMS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001926err:
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001927
1928 return rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001929}
Nickolay V. Shmyrev4b9b9362006-08-25 16:53:04 -03001930
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001931static int bttv_g_input(struct file *file, void *priv, unsigned int *i)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001932{
1933 struct bttv_fh *fh = priv;
1934 struct bttv *btv = fh->btv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001936 *i = btv->input;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001937
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001938 return 0;
1939}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001941static int bttv_s_input(struct file *file, void *priv, unsigned int i)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001942{
1943 struct bttv_fh *fh = priv;
1944 struct bttv *btv = fh->btv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001946 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001947
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001948 err = v4l2_prio_check(&btv->prio, fh->prio);
1949 if (unlikely(err))
1950 goto err;
1951
1952 if (i > bttv_tvcards[btv->c.type].video_inputs) {
1953 err = -EINVAL;
1954 goto err;
1955 }
1956
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001957 set_input(btv, i, btv->tvnorm);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001958
1959err:
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001960 return 0;
1961}
1962
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001963static int bttv_s_tuner(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001964 struct v4l2_tuner *t)
1965{
1966 struct bttv_fh *fh = priv;
1967 struct bttv *btv = fh->btv;
1968 int err;
1969
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001970 if (unlikely(0 != t->index))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001971 return -EINVAL;
1972
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001973 if (unlikely(btv->tuner_type == TUNER_ABSENT)) {
1974 err = -EINVAL;
1975 goto err;
1976 }
1977
1978 err = v4l2_prio_check(&btv->prio, fh->prio);
1979 if (unlikely(err))
1980 goto err;
1981
Hans Verkuil859f0272009-03-28 08:29:00 -03001982 bttv_call_all(btv, tuner, s_tuner, t);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001983
1984 if (btv->audio_mode_gpio)
1985 btv->audio_mode_gpio(btv, t, 1);
1986
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001987err:
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001988
1989 return 0;
1990}
1991
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001992static int bttv_g_frequency(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001993 struct v4l2_frequency *f)
1994{
1995 struct bttv_fh *fh = priv;
1996 struct bttv *btv = fh->btv;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001997
Robert Fitzsimons1b069012008-04-01 11:41:54 -03001998 f->type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001999 f->frequency = btv->freq;
2000
2001 return 0;
2002}
2003
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002004static int bttv_s_frequency(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002005 struct v4l2_frequency *f)
2006{
2007 struct bttv_fh *fh = priv;
2008 struct bttv *btv = fh->btv;
2009 int err;
2010
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002011 if (unlikely(f->tuner != 0))
2012 return -EINVAL;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002013
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002014 err = v4l2_prio_check(&btv->prio, fh->prio);
2015 if (unlikely(err))
2016 goto err;
2017
2018 if (unlikely(f->type != (btv->radio_user
2019 ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV))) {
2020 err = -EINVAL;
2021 goto err;
2022 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002023 btv->freq = f->frequency;
Hans Verkuil859f0272009-03-28 08:29:00 -03002024 bttv_call_all(btv, tuner, s_frequency, f);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002025 if (btv->has_matchbox && btv->radio_user)
2026 tea5757_set_freq(btv, btv->freq);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002027err:
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002028
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002029 return 0;
2030}
2031
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002032static int bttv_log_status(struct file *file, void *f)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002033{
2034 struct bttv_fh *fh = f;
2035 struct bttv *btv = fh->btv;
2036
Hans Verkuil859f0272009-03-28 08:29:00 -03002037 bttv_call_all(btv, core, log_status);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002038 return 0;
2039}
2040
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002041#ifdef CONFIG_VIDEO_ADV_DEBUG
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002042static int bttv_g_register(struct file *file, void *f,
Hans Verkuilaecde8b52008-12-30 07:14:19 -03002043 struct v4l2_dbg_register *reg)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002044{
2045 struct bttv_fh *fh = f;
2046 struct bttv *btv = fh->btv;
2047
2048 if (!capable(CAP_SYS_ADMIN))
2049 return -EPERM;
2050
Hans Verkuilaecde8b52008-12-30 07:14:19 -03002051 if (!v4l2_chip_match_host(&reg->match))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002052 return -EINVAL;
2053
2054 /* bt848 has a 12-bit register space */
2055 reg->reg &= 0xfff;
2056 reg->val = btread(reg->reg);
Hans Verkuilaecde8b52008-12-30 07:14:19 -03002057 reg->size = 1;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002058
2059 return 0;
2060}
2061
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002062static int bttv_s_register(struct file *file, void *f,
Hans Verkuilaecde8b52008-12-30 07:14:19 -03002063 struct v4l2_dbg_register *reg)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002064{
2065 struct bttv_fh *fh = f;
2066 struct bttv *btv = fh->btv;
2067
2068 if (!capable(CAP_SYS_ADMIN))
2069 return -EPERM;
2070
Hans Verkuilaecde8b52008-12-30 07:14:19 -03002071 if (!v4l2_chip_match_host(&reg->match))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002072 return -EINVAL;
2073
2074 /* bt848 has a 12-bit register space */
2075 reg->reg &= 0xfff;
2076 btwrite(reg->val, reg->reg);
2077
2078 return 0;
2079}
2080#endif
2081
Michael Schimeke5bd0262007-01-18 16:17:39 -03002082/* Given cropping boundaries b and the scaled width and height of a
2083 single field or frame, which must not exceed hardware limits, this
2084 function adjusts the cropping parameters c. */
2085static void
2086bttv_crop_adjust (struct bttv_crop * c,
2087 const struct v4l2_rect * b,
2088 __s32 width,
2089 __s32 height,
2090 enum v4l2_field field)
2091{
2092 __s32 frame_height = height << !V4L2_FIELD_HAS_BOTH(field);
2093 __s32 max_left;
2094 __s32 max_top;
2095
2096 if (width < c->min_scaled_width) {
2097 /* Max. hor. scale factor 16:1. */
2098 c->rect.width = width * 16;
2099 } else if (width > c->max_scaled_width) {
2100 /* Min. hor. scale factor 1:1. */
2101 c->rect.width = width;
2102
2103 max_left = b->left + b->width - width;
2104 max_left = min(max_left, (__s32) MAX_HDELAY);
2105 if (c->rect.left > max_left)
2106 c->rect.left = max_left;
2107 }
2108
2109 if (height < c->min_scaled_height) {
2110 /* Max. vert. scale factor 16:1, single fields 8:1. */
2111 c->rect.height = height * 16;
2112 } else if (frame_height > c->max_scaled_height) {
2113 /* Min. vert. scale factor 1:1.
2114 Top and height count field lines times two. */
2115 c->rect.height = (frame_height + 1) & ~1;
2116
2117 max_top = b->top + b->height - c->rect.height;
2118 if (c->rect.top > max_top)
2119 c->rect.top = max_top;
2120 }
2121
2122 bttv_crop_calc_limits(c);
2123}
2124
2125/* Returns an error if scaling to a frame or single field with the given
2126 width and height is not possible with the current cropping parameters
2127 and width aligned according to width_mask. If adjust_size is TRUE the
2128 function may adjust the width and/or height instead, rounding width
2129 to (width + width_bias) & width_mask. If adjust_crop is TRUE it may
2130 also adjust the current cropping parameters to get closer to the
2131 desired image size. */
2132static int
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002133limit_scaled_size_lock (struct bttv_fh * fh,
Michael Schimeke5bd0262007-01-18 16:17:39 -03002134 __s32 * width,
2135 __s32 * height,
2136 enum v4l2_field field,
2137 unsigned int width_mask,
2138 unsigned int width_bias,
2139 int adjust_size,
2140 int adjust_crop)
2141{
2142 struct bttv *btv = fh->btv;
2143 const struct v4l2_rect *b;
2144 struct bttv_crop *c;
2145 __s32 min_width;
2146 __s32 min_height;
2147 __s32 max_width;
2148 __s32 max_height;
2149 int rc;
2150
2151 BUG_ON((int) width_mask >= 0 ||
2152 width_bias >= (unsigned int) -width_mask);
2153
2154 /* Make sure tvnorm, vbi_end and the current cropping parameters
2155 remain consistent until we're done. */
Michael Schimeke5bd0262007-01-18 16:17:39 -03002156
2157 b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
2158
2159 /* Do crop - use current, don't - use default parameters. */
2160 c = &btv->crop[!!fh->do_crop];
2161
2162 if (fh->do_crop
2163 && adjust_size
2164 && adjust_crop
2165 && !locked_btres(btv, VIDEO_RESOURCES)) {
2166 min_width = 48;
2167 min_height = 32;
2168
2169 /* We cannot scale up. When the scaled image is larger
2170 than crop.rect we adjust the crop.rect as required
2171 by the V4L2 spec, hence cropcap.bounds are our limit. */
2172 max_width = min(b->width, (__s32) MAX_HACTIVE);
2173 max_height = b->height;
2174
2175 /* We cannot capture the same line as video and VBI data.
2176 Note btv->vbi_end is really a minimum, see
2177 bttv_vbi_try_fmt(). */
2178 if (btv->vbi_end > b->top) {
2179 max_height -= btv->vbi_end - b->top;
2180 rc = -EBUSY;
2181 if (min_height > max_height)
2182 goto fail;
2183 }
2184 } else {
2185 rc = -EBUSY;
2186 if (btv->vbi_end > c->rect.top)
2187 goto fail;
2188
2189 min_width = c->min_scaled_width;
2190 min_height = c->min_scaled_height;
2191 max_width = c->max_scaled_width;
2192 max_height = c->max_scaled_height;
2193
2194 adjust_crop = 0;
2195 }
2196
2197 min_width = (min_width - width_mask - 1) & width_mask;
2198 max_width = max_width & width_mask;
2199
2200 /* Max. scale factor is 16:1 for frames, 8:1 for fields. */
2201 min_height = min_height;
2202 /* Min. scale factor is 1:1. */
2203 max_height >>= !V4L2_FIELD_HAS_BOTH(field);
2204
2205 if (adjust_size) {
2206 *width = clamp(*width, min_width, max_width);
2207 *height = clamp(*height, min_height, max_height);
2208
2209 /* Round after clamping to avoid overflow. */
2210 *width = (*width + width_bias) & width_mask;
2211
2212 if (adjust_crop) {
2213 bttv_crop_adjust(c, b, *width, *height, field);
2214
2215 if (btv->vbi_end > c->rect.top) {
2216 /* Move the crop window out of the way. */
2217 c->rect.top = btv->vbi_end;
2218 }
2219 }
2220 } else {
2221 rc = -EINVAL;
2222 if (*width < min_width ||
2223 *height < min_height ||
2224 *width > max_width ||
2225 *height > max_height ||
2226 0 != (*width & ~width_mask))
2227 goto fail;
2228 }
2229
2230 rc = 0; /* success */
2231
2232 fail:
Michael Schimeke5bd0262007-01-18 16:17:39 -03002233
2234 return rc;
2235}
2236
2237/* Returns an error if the given overlay window dimensions are not
2238 possible with the current cropping parameters. If adjust_size is
2239 TRUE the function may adjust the window width and/or height
2240 instead, however it always rounds the horizontal position and
2241 width as btcx_align() does. If adjust_crop is TRUE the function
2242 may also adjust the current cropping parameters to get closer
2243 to the desired window size. */
2244static int
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002245verify_window_lock (struct bttv_fh * fh,
Michael Schimeke5bd0262007-01-18 16:17:39 -03002246 struct v4l2_window * win,
2247 int adjust_size,
2248 int adjust_crop)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249{
2250 enum v4l2_field field;
Michael Schimeke5bd0262007-01-18 16:17:39 -03002251 unsigned int width_mask;
2252 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253
2254 if (win->w.width < 48 || win->w.height < 32)
2255 return -EINVAL;
2256 if (win->clipcount > 2048)
2257 return -EINVAL;
2258
2259 field = win->field;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002260
2261 if (V4L2_FIELD_ANY == field) {
Michael Schimeke5bd0262007-01-18 16:17:39 -03002262 __s32 height2;
2263
2264 height2 = fh->btv->crop[!!fh->do_crop].rect.height >> 1;
2265 field = (win->w.height > height2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266 ? V4L2_FIELD_INTERLACED
2267 : V4L2_FIELD_TOP;
2268 }
2269 switch (field) {
2270 case V4L2_FIELD_TOP:
2271 case V4L2_FIELD_BOTTOM:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272 case V4L2_FIELD_INTERLACED:
2273 break;
2274 default:
2275 return -EINVAL;
2276 }
2277
Michael Schimeke5bd0262007-01-18 16:17:39 -03002278 /* 4-byte alignment. */
2279 if (NULL == fh->ovfmt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002280 return -EINVAL;
Michael Schimeke5bd0262007-01-18 16:17:39 -03002281 width_mask = ~0;
2282 switch (fh->ovfmt->depth) {
2283 case 8:
2284 case 24:
2285 width_mask = ~3;
2286 break;
2287 case 16:
2288 width_mask = ~1;
2289 break;
2290 case 32:
2291 break;
2292 default:
2293 BUG();
2294 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295
Michael Schimeke5bd0262007-01-18 16:17:39 -03002296 win->w.width -= win->w.left & ~width_mask;
2297 win->w.left = (win->w.left - width_mask - 1) & width_mask;
2298
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002299 rc = limit_scaled_size_lock(fh, &win->w.width, &win->w.height,
Michael Schimeke5bd0262007-01-18 16:17:39 -03002300 field, width_mask,
2301 /* width_bias: round down */ 0,
2302 adjust_size, adjust_crop);
2303 if (0 != rc)
2304 return rc;
2305
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306 win->field = field;
2307 return 0;
2308}
2309
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002310static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311 struct v4l2_window *win, int fixup)
2312{
2313 struct v4l2_clip *clips = NULL;
2314 int n,size,retval = 0;
2315
2316 if (NULL == fh->ovfmt)
2317 return -EINVAL;
2318 if (!(fh->ovfmt->flags & FORMAT_FLAGS_PACKED))
2319 return -EINVAL;
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002320 retval = verify_window_lock(fh, win,
Michael Schimeke5bd0262007-01-18 16:17:39 -03002321 /* adjust_size */ fixup,
2322 /* adjust_crop */ fixup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323 if (0 != retval)
2324 return retval;
2325
2326 /* copy clips -- luckily v4l1 + v4l2 are binary
2327 compatible here ...*/
2328 n = win->clipcount;
2329 size = sizeof(*clips)*(n+4);
2330 clips = kmalloc(size,GFP_KERNEL);
2331 if (NULL == clips)
2332 return -ENOMEM;
2333 if (n > 0) {
2334 if (copy_from_user(clips,win->clips,sizeof(struct v4l2_clip)*n)) {
2335 kfree(clips);
2336 return -EFAULT;
2337 }
2338 }
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002339
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340 /* clip against screen */
2341 if (NULL != btv->fbuf.base)
2342 n = btcx_screen_clips(btv->fbuf.fmt.width, btv->fbuf.fmt.height,
2343 &win->w, clips, n);
2344 btcx_sort_clips(clips,n);
2345
2346 /* 4-byte alignments */
2347 switch (fh->ovfmt->depth) {
2348 case 8:
2349 case 24:
2350 btcx_align(&win->w, clips, n, 3);
2351 break;
2352 case 16:
2353 btcx_align(&win->w, clips, n, 1);
2354 break;
2355 case 32:
2356 /* no alignment fixups needed */
2357 break;
2358 default:
2359 BUG();
2360 }
2361
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03002362 kfree(fh->ov.clips);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363 fh->ov.clips = clips;
2364 fh->ov.nclips = n;
2365
2366 fh->ov.w = win->w;
2367 fh->ov.field = win->field;
2368 fh->ov.setup_ok = 1;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002369
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370 btv->init.ov.w.width = win->w.width;
2371 btv->init.ov.w.height = win->w.height;
2372 btv->init.ov.field = win->field;
2373
2374 /* update overlay if needed */
2375 retval = 0;
2376 if (check_btres(fh, RESOURCE_OVERLAY)) {
2377 struct bttv_buffer *new;
2378
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03002379 new = videobuf_sg_alloc(sizeof(*new));
Michael Schimeke5bd0262007-01-18 16:17:39 -03002380 new->crop = btv->crop[!!fh->do_crop].rect;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381 bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
2382 retval = bttv_switch_overlay(btv,fh,new);
2383 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384 return retval;
2385}
2386
2387/* ----------------------------------------------------------------------- */
2388
2389static struct videobuf_queue* bttv_queue(struct bttv_fh *fh)
2390{
2391 struct videobuf_queue* q = NULL;
2392
2393 switch (fh->type) {
2394 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2395 q = &fh->cap;
2396 break;
2397 case V4L2_BUF_TYPE_VBI_CAPTURE:
2398 q = &fh->vbi;
2399 break;
2400 default:
2401 BUG();
2402 }
2403 return q;
2404}
2405
2406static int bttv_resource(struct bttv_fh *fh)
2407{
2408 int res = 0;
2409
2410 switch (fh->type) {
2411 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Michael Schimeke5bd0262007-01-18 16:17:39 -03002412 res = RESOURCE_VIDEO_STREAM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413 break;
2414 case V4L2_BUF_TYPE_VBI_CAPTURE:
2415 res = RESOURCE_VBI;
2416 break;
2417 default:
2418 BUG();
2419 }
2420 return res;
2421}
2422
2423static int bttv_switch_type(struct bttv_fh *fh, enum v4l2_buf_type type)
2424{
2425 struct videobuf_queue *q = bttv_queue(fh);
2426 int res = bttv_resource(fh);
2427
2428 if (check_btres(fh,res))
2429 return -EBUSY;
2430 if (videobuf_queue_is_busy(q))
2431 return -EBUSY;
2432 fh->type = type;
2433 return 0;
2434}
2435
Michael H. Schimekc87c9482005-12-01 00:51:33 -08002436static void
2437pix_format_set_size (struct v4l2_pix_format * f,
2438 const struct bttv_format * fmt,
2439 unsigned int width,
2440 unsigned int height)
2441{
2442 f->width = width;
2443 f->height = height;
2444
2445 if (fmt->flags & FORMAT_FLAGS_PLANAR) {
2446 f->bytesperline = width; /* Y plane */
2447 f->sizeimage = (width * height * fmt->depth) >> 3;
2448 } else {
2449 f->bytesperline = (width * fmt->depth) >> 3;
2450 f->sizeimage = height * f->bytesperline;
2451 }
2452}
2453
Hans Verkuil78b526a2008-05-28 12:16:41 -03002454static int bttv_g_fmt_vid_cap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002455 struct v4l2_format *f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002457 struct bttv_fh *fh = priv;
2458
2459 pix_format_set_size(&f->fmt.pix, fh->fmt,
2460 fh->width, fh->height);
2461 f->fmt.pix.field = fh->cap.field;
2462 f->fmt.pix.pixelformat = fh->fmt->fourcc;
2463
2464 return 0;
2465}
2466
Hans Verkuil78b526a2008-05-28 12:16:41 -03002467static int bttv_g_fmt_vid_overlay(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002468 struct v4l2_format *f)
2469{
2470 struct bttv_fh *fh = priv;
2471
2472 f->fmt.win.w = fh->ov.w;
2473 f->fmt.win.field = fh->ov.field;
2474
2475 return 0;
2476}
2477
Hans Verkuil78b526a2008-05-28 12:16:41 -03002478static int bttv_try_fmt_vid_cap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002479 struct v4l2_format *f)
2480{
2481 const struct bttv_format *fmt;
2482 struct bttv_fh *fh = priv;
2483 struct bttv *btv = fh->btv;
2484 enum v4l2_field field;
2485 __s32 width, height;
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002486 int rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002487
2488 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
2489 if (NULL == fmt)
2490 return -EINVAL;
2491
2492 field = f->fmt.pix.field;
2493
2494 if (V4L2_FIELD_ANY == field) {
2495 __s32 height2;
2496
2497 height2 = btv->crop[!!fh->do_crop].rect.height >> 1;
2498 field = (f->fmt.pix.height > height2)
2499 ? V4L2_FIELD_INTERLACED
2500 : V4L2_FIELD_BOTTOM;
2501 }
2502
2503 if (V4L2_FIELD_SEQ_BT == field)
2504 field = V4L2_FIELD_SEQ_TB;
2505
2506 switch (field) {
2507 case V4L2_FIELD_TOP:
2508 case V4L2_FIELD_BOTTOM:
2509 case V4L2_FIELD_ALTERNATE:
2510 case V4L2_FIELD_INTERLACED:
2511 break;
2512 case V4L2_FIELD_SEQ_TB:
2513 if (fmt->flags & FORMAT_FLAGS_PLANAR)
2514 return -EINVAL;
2515 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002516 default:
2517 return -EINVAL;
2518 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002519
2520 width = f->fmt.pix.width;
2521 height = f->fmt.pix.height;
2522
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002523 rc = limit_scaled_size_lock(fh, &width, &height, field,
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002524 /* width_mask: 4 pixels */ ~3,
2525 /* width_bias: nearest */ 2,
2526 /* adjust_size */ 1,
2527 /* adjust_crop */ 0);
2528 if (0 != rc)
2529 return rc;
2530
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002531 /* update data for the application */
2532 f->fmt.pix.field = field;
2533 pix_format_set_size(&f->fmt.pix, fmt, width, height);
2534
2535 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002536}
2537
Hans Verkuil78b526a2008-05-28 12:16:41 -03002538static int bttv_try_fmt_vid_overlay(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002539 struct v4l2_format *f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002541 struct bttv_fh *fh = priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002542
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002543 return verify_window_lock(fh, &f->fmt.win,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002544 /* adjust_size */ 1,
2545 /* adjust_crop */ 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002546}
2547
Hans Verkuil78b526a2008-05-28 12:16:41 -03002548static int bttv_s_fmt_vid_cap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002549 struct v4l2_format *f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002550{
2551 int retval;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002552 const struct bttv_format *fmt;
2553 struct bttv_fh *fh = priv;
2554 struct bttv *btv = fh->btv;
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002555 __s32 width, height;
2556 enum v4l2_field field;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002557
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002558 retval = bttv_switch_type(fh, f->type);
2559 if (0 != retval)
2560 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561
Hans Verkuil78b526a2008-05-28 12:16:41 -03002562 retval = bttv_try_fmt_vid_cap(file, priv, f);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002563 if (0 != retval)
2564 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002566 width = f->fmt.pix.width;
2567 height = f->fmt.pix.height;
2568 field = f->fmt.pix.field;
2569
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002570 retval = limit_scaled_size_lock(fh, &width, &height, f->fmt.pix.field,
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002571 /* width_mask: 4 pixels */ ~3,
2572 /* width_bias: nearest */ 2,
2573 /* adjust_size */ 1,
2574 /* adjust_crop */ 1);
2575 if (0 != retval)
2576 return retval;
2577
2578 f->fmt.pix.field = field;
2579
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002580 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002581
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002582 /* update our state informations */
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002583 fh->fmt = fmt;
2584 fh->cap.field = f->fmt.pix.field;
2585 fh->cap.last = V4L2_FIELD_NONE;
2586 fh->width = f->fmt.pix.width;
2587 fh->height = f->fmt.pix.height;
2588 btv->init.fmt = fmt;
2589 btv->init.width = f->fmt.pix.width;
2590 btv->init.height = f->fmt.pix.height;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002591
2592 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002593}
2594
Hans Verkuil78b526a2008-05-28 12:16:41 -03002595static int bttv_s_fmt_vid_overlay(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002596 struct v4l2_format *f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002597{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002598 struct bttv_fh *fh = priv;
2599 struct bttv *btv = fh->btv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002600
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002601 if (no_overlay > 0) {
Joe Perches8af443e2011-08-21 19:56:48 -03002602 pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002603 return -EINVAL;
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002604 }
Michael Krufky5e453dc2006-01-09 15:32:31 -02002605
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002606 return setup_window_lock(fh, btv, &f->fmt.win, 1);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002607}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002608
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002609static int bttv_querycap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002610 struct v4l2_capability *cap)
2611{
2612 struct bttv_fh *fh = priv;
2613 struct bttv *btv = fh->btv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002614
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002615 if (0 == v4l2)
2616 return -EINVAL;
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07002617
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002618 strlcpy(cap->driver, "bttv", sizeof(cap->driver));
2619 strlcpy(cap->card, btv->video_dev->name, sizeof(cap->card));
2620 snprintf(cap->bus_info, sizeof(cap->bus_info),
2621 "PCI:%s", pci_name(btv->c.pci));
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002622 cap->capabilities =
2623 V4L2_CAP_VIDEO_CAPTURE |
2624 V4L2_CAP_VBI_CAPTURE |
2625 V4L2_CAP_READWRITE |
2626 V4L2_CAP_STREAMING;
2627 if (no_overlay <= 0)
2628 cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002630 /*
2631 * No need to lock here: those vars are initialized during board
2632 * probe and remains untouched during the rest of the driver lifecycle
2633 */
2634 if (btv->has_saa6588)
2635 cap->capabilities |= V4L2_CAP_RDS_CAPTURE;
Trent Piephoabb03622009-01-28 21:32:59 -03002636 if (btv->tuner_type != TUNER_ABSENT)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002637 cap->capabilities |= V4L2_CAP_TUNER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002638 return 0;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002639}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002641static int bttv_enum_fmt_cap_ovr(struct v4l2_fmtdesc *f)
2642{
2643 int index = -1, i;
2644
2645 for (i = 0; i < FORMATS; i++) {
2646 if (formats[i].fourcc != -1)
2647 index++;
2648 if ((unsigned int)index == f->index)
2649 break;
2650 }
2651 if (FORMATS == i)
2652 return -EINVAL;
2653
2654 f->pixelformat = formats[i].fourcc;
2655 strlcpy(f->description, formats[i].name, sizeof(f->description));
2656
2657 return i;
2658}
2659
Hans Verkuil78b526a2008-05-28 12:16:41 -03002660static int bttv_enum_fmt_vid_cap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002661 struct v4l2_fmtdesc *f)
2662{
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002663 int rc = bttv_enum_fmt_cap_ovr(f);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002664
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002665 if (rc < 0)
2666 return rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002667
2668 return 0;
2669}
2670
Hans Verkuil78b526a2008-05-28 12:16:41 -03002671static int bttv_enum_fmt_vid_overlay(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002672 struct v4l2_fmtdesc *f)
2673{
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002674 int rc;
2675
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002676 if (no_overlay > 0) {
Joe Perches8af443e2011-08-21 19:56:48 -03002677 pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002678 return -EINVAL;
2679 }
2680
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002681 rc = bttv_enum_fmt_cap_ovr(f);
2682
2683 if (rc < 0)
2684 return rc;
2685
2686 if (!(formats[rc].flags & FORMAT_FLAGS_PACKED))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002687 return -EINVAL;
2688
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002689 return 0;
2690}
2691
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002692static int bttv_g_fbuf(struct file *file, void *f,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002693 struct v4l2_framebuffer *fb)
2694{
2695 struct bttv_fh *fh = f;
2696 struct bttv *btv = fh->btv;
2697
2698 *fb = btv->fbuf;
2699 fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
2700 if (fh->ovfmt)
2701 fb->fmt.pixelformat = fh->ovfmt->fourcc;
2702 return 0;
2703}
2704
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002705static int bttv_overlay(struct file *file, void *f, unsigned int on)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002706{
2707 struct bttv_fh *fh = f;
2708 struct bttv *btv = fh->btv;
2709 struct bttv_buffer *new;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002710 int retval = 0;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002711
2712 if (on) {
2713 /* verify args */
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002714 if (unlikely(!btv->fbuf.base)) {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002715 return -EINVAL;
2716 }
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002717 if (unlikely(!fh->ov.setup_ok)) {
Joe Perches8af443e2011-08-21 19:56:48 -03002718 dprintk("%d: overlay: !setup_ok\n", btv->c.nr);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002719 retval = -EINVAL;
2720 }
2721 if (retval)
2722 return retval;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002723 }
2724
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002725 if (!check_alloc_btres_lock(btv, fh, RESOURCE_OVERLAY))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002726 return -EBUSY;
2727
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002728 if (on) {
2729 fh->ov.tvnorm = btv->tvnorm;
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03002730 new = videobuf_sg_alloc(sizeof(*new));
Robert Fitzsimons7c018802008-02-13 16:38:11 -03002731 new->crop = btv->crop[!!fh->do_crop].rect;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002732 bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
2733 } else {
2734 new = NULL;
2735 }
2736
2737 /* switch over */
2738 retval = bttv_switch_overlay(btv, fh, new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739 return retval;
2740}
2741
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002742static int bttv_s_fbuf(struct file *file, void *f,
Hans Verkuile6eb28c2012-09-04 10:26:45 -03002743 const struct v4l2_framebuffer *fb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002744{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002745 struct bttv_fh *fh = f;
2746 struct bttv *btv = fh->btv;
2747 const struct bttv_format *fmt;
2748 int retval;
2749
2750 if (!capable(CAP_SYS_ADMIN) &&
2751 !capable(CAP_SYS_RAWIO))
2752 return -EPERM;
2753
2754 /* check args */
2755 fmt = format_by_fourcc(fb->fmt.pixelformat);
2756 if (NULL == fmt)
2757 return -EINVAL;
2758 if (0 == (fmt->flags & FORMAT_FLAGS_PACKED))
2759 return -EINVAL;
2760
2761 retval = -EINVAL;
2762 if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
2763 __s32 width = fb->fmt.width;
2764 __s32 height = fb->fmt.height;
2765
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002766 retval = limit_scaled_size_lock(fh, &width, &height,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002767 V4L2_FIELD_INTERLACED,
2768 /* width_mask */ ~3,
2769 /* width_bias */ 2,
2770 /* adjust_size */ 0,
2771 /* adjust_crop */ 0);
2772 if (0 != retval)
2773 return retval;
2774 }
2775
2776 /* ok, accept it */
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002777 btv->fbuf.base = fb->base;
2778 btv->fbuf.fmt.width = fb->fmt.width;
2779 btv->fbuf.fmt.height = fb->fmt.height;
2780 if (0 != fb->fmt.bytesperline)
2781 btv->fbuf.fmt.bytesperline = fb->fmt.bytesperline;
2782 else
2783 btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fmt->depth/8;
2784
2785 retval = 0;
2786 fh->ovfmt = fmt;
2787 btv->init.ovfmt = fmt;
2788 if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
2789 fh->ov.w.left = 0;
2790 fh->ov.w.top = 0;
2791 fh->ov.w.width = fb->fmt.width;
2792 fh->ov.w.height = fb->fmt.height;
2793 btv->init.ov.w.width = fb->fmt.width;
2794 btv->init.ov.w.height = fb->fmt.height;
2795 kfree(fh->ov.clips);
2796 fh->ov.clips = NULL;
2797 fh->ov.nclips = 0;
2798
2799 if (check_btres(fh, RESOURCE_OVERLAY)) {
2800 struct bttv_buffer *new;
2801
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03002802 new = videobuf_sg_alloc(sizeof(*new));
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002803 new->crop = btv->crop[!!fh->do_crop].rect;
2804 bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
2805 retval = bttv_switch_overlay(btv, fh, new);
2806 }
2807 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002808 return retval;
2809}
2810
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002811static int bttv_reqbufs(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002812 struct v4l2_requestbuffers *p)
2813{
2814 struct bttv_fh *fh = priv;
2815 return videobuf_reqbufs(bttv_queue(fh), p);
2816}
2817
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002818static int bttv_querybuf(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002819 struct v4l2_buffer *b)
2820{
2821 struct bttv_fh *fh = priv;
2822 return videobuf_querybuf(bttv_queue(fh), b);
2823}
2824
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002825static int bttv_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002826{
2827 struct bttv_fh *fh = priv;
2828 struct bttv *btv = fh->btv;
2829 int res = bttv_resource(fh);
2830
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002831 if (!check_alloc_btres_lock(btv, fh, res))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002832 return -EBUSY;
2833
2834 return videobuf_qbuf(bttv_queue(fh), b);
2835}
2836
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002837static int bttv_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002838{
2839 struct bttv_fh *fh = priv;
2840 return videobuf_dqbuf(bttv_queue(fh), b,
2841 file->f_flags & O_NONBLOCK);
2842}
2843
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002844static int bttv_streamon(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002845 enum v4l2_buf_type type)
2846{
2847 struct bttv_fh *fh = priv;
2848 struct bttv *btv = fh->btv;
2849 int res = bttv_resource(fh);
2850
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002851 if (!check_alloc_btres_lock(btv, fh, res))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002852 return -EBUSY;
2853 return videobuf_streamon(bttv_queue(fh));
2854}
2855
2856
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002857static int bttv_streamoff(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002858 enum v4l2_buf_type type)
2859{
2860 struct bttv_fh *fh = priv;
2861 struct bttv *btv = fh->btv;
2862 int retval;
2863 int res = bttv_resource(fh);
2864
2865
2866 retval = videobuf_streamoff(bttv_queue(fh));
2867 if (retval < 0)
2868 return retval;
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002869 free_btres_lock(btv, fh, res);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002870 return 0;
2871}
2872
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002873static int bttv_queryctrl(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002874 struct v4l2_queryctrl *c)
2875{
2876 struct bttv_fh *fh = priv;
2877 struct bttv *btv = fh->btv;
2878 const struct v4l2_queryctrl *ctrl;
2879
2880 if ((c->id < V4L2_CID_BASE ||
2881 c->id >= V4L2_CID_LASTP1) &&
2882 (c->id < V4L2_CID_PRIVATE_BASE ||
2883 c->id >= V4L2_CID_PRIVATE_LASTP1))
2884 return -EINVAL;
2885
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002886 if (!btv->volume_gpio && (c->id == V4L2_CID_AUDIO_VOLUME))
2887 *c = no_ctl;
2888 else {
2889 ctrl = ctrl_by_id(c->id);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002890
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002891 *c = (NULL != ctrl) ? *ctrl : no_ctl;
2892 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002893
2894 return 0;
2895}
2896
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002897static int bttv_g_parm(struct file *file, void *f,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002898 struct v4l2_streamparm *parm)
2899{
2900 struct bttv_fh *fh = f;
2901 struct bttv *btv = fh->btv;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002902
Trent Piepho51f0b8d52009-03-04 01:21:02 -03002903 v4l2_video_std_frame_period(bttv_tvnorms[btv->tvnorm].v4l2_id,
2904 &parm->parm.capture.timeperframe);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002905
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002906 return 0;
2907}
2908
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002909static int bttv_g_tuner(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002910 struct v4l2_tuner *t)
2911{
2912 struct bttv_fh *fh = priv;
2913 struct bttv *btv = fh->btv;
2914
Trent Piephoabb03622009-01-28 21:32:59 -03002915 if (btv->tuner_type == TUNER_ABSENT)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002916 return -EINVAL;
2917 if (0 != t->index)
2918 return -EINVAL;
2919
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002920 t->rxsubchans = V4L2_TUNER_SUB_MONO;
Hans Verkuil859f0272009-03-28 08:29:00 -03002921 bttv_call_all(btv, tuner, g_tuner, t);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002922 strcpy(t->name, "Television");
2923 t->capability = V4L2_TUNER_CAP_NORM;
2924 t->type = V4L2_TUNER_ANALOG_TV;
2925 if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)
2926 t->signal = 0xffff;
2927
2928 if (btv->audio_mode_gpio)
2929 btv->audio_mode_gpio(btv, t, 0);
2930
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002931 return 0;
2932}
2933
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002934static int bttv_g_priority(struct file *file, void *f, enum v4l2_priority *p)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002935{
2936 struct bttv_fh *fh = f;
2937 struct bttv *btv = fh->btv;
2938
2939 *p = v4l2_prio_max(&btv->prio);
2940
2941 return 0;
2942}
2943
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002944static int bttv_s_priority(struct file *file, void *f,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002945 enum v4l2_priority prio)
2946{
2947 struct bttv_fh *fh = f;
2948 struct bttv *btv = fh->btv;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002949 int rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002950
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002951 rc = v4l2_prio_change(&btv->prio, &fh->prio, prio);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002952
2953 return rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002954}
2955
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002956static int bttv_cropcap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002957 struct v4l2_cropcap *cap)
2958{
2959 struct bttv_fh *fh = priv;
2960 struct bttv *btv = fh->btv;
2961
2962 if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
2963 cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
2964 return -EINVAL;
2965
2966 *cap = bttv_tvnorms[btv->tvnorm].cropcap;
2967
2968 return 0;
2969}
2970
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002971static int bttv_g_crop(struct file *file, void *f, struct v4l2_crop *crop)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002972{
2973 struct bttv_fh *fh = f;
2974 struct bttv *btv = fh->btv;
2975
2976 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
2977 crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
2978 return -EINVAL;
2979
2980 /* No fh->do_crop = 1; because btv->crop[1] may be
2981 inconsistent with fh->width or fh->height and apps
2982 do not expect a change here. */
2983
2984 crop->c = btv->crop[!!fh->do_crop].rect;
2985
2986 return 0;
2987}
2988
Hans Verkuil4f996592012-09-05 05:10:48 -03002989static int bttv_s_crop(struct file *file, void *f, const struct v4l2_crop *crop)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002990{
2991 struct bttv_fh *fh = f;
2992 struct bttv *btv = fh->btv;
2993 const struct v4l2_rect *b;
2994 int retval;
2995 struct bttv_crop c;
2996 __s32 b_left;
2997 __s32 b_top;
2998 __s32 b_right;
2999 __s32 b_bottom;
3000
3001 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
3002 crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
3003 return -EINVAL;
3004
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003005 /* Make sure tvnorm, vbi_end and the current cropping
3006 parameters remain consistent until we're done. Note
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003007 read() may change vbi_end in check_alloc_btres_lock(). */
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003008 retval = v4l2_prio_check(&btv->prio, fh->prio);
3009 if (0 != retval) {
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003010 return retval;
3011 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003012
3013 retval = -EBUSY;
3014
3015 if (locked_btres(fh->btv, VIDEO_RESOURCES)) {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003016 return retval;
3017 }
3018
3019 b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
3020
3021 b_left = b->left;
3022 b_right = b_left + b->width;
3023 b_bottom = b->top + b->height;
3024
3025 b_top = max(b->top, btv->vbi_end);
3026 if (b_top + 32 >= b_bottom) {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003027 return retval;
3028 }
3029
3030 /* Min. scaled size 48 x 32. */
Hans Verkuil4f996592012-09-05 05:10:48 -03003031 c.rect.left = clamp_t(s32, crop->c.left, b_left, b_right - 48);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003032 c.rect.left = min(c.rect.left, (__s32) MAX_HDELAY);
3033
Hans Verkuil4f996592012-09-05 05:10:48 -03003034 c.rect.width = clamp_t(s32, crop->c.width,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003035 48, b_right - c.rect.left);
3036
Hans Verkuil4f996592012-09-05 05:10:48 -03003037 c.rect.top = clamp_t(s32, crop->c.top, b_top, b_bottom - 32);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003038 /* Top and height must be a multiple of two. */
3039 c.rect.top = (c.rect.top + 1) & ~1;
3040
Hans Verkuil4f996592012-09-05 05:10:48 -03003041 c.rect.height = clamp_t(s32, crop->c.height,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003042 32, b_bottom - c.rect.top);
3043 c.rect.height = (c.rect.height + 1) & ~1;
3044
3045 bttv_crop_calc_limits(&c);
3046
3047 btv->crop[1] = c;
3048
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003049 fh->do_crop = 1;
3050
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003051 if (fh->width < c.min_scaled_width) {
3052 fh->width = c.min_scaled_width;
3053 btv->init.width = c.min_scaled_width;
3054 } else if (fh->width > c.max_scaled_width) {
3055 fh->width = c.max_scaled_width;
3056 btv->init.width = c.max_scaled_width;
3057 }
3058
3059 if (fh->height < c.min_scaled_height) {
3060 fh->height = c.min_scaled_height;
3061 btv->init.height = c.min_scaled_height;
3062 } else if (fh->height > c.max_scaled_height) {
3063 fh->height = c.max_scaled_height;
3064 btv->init.height = c.max_scaled_height;
3065 }
3066
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003067 return 0;
3068}
3069
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003070static int bttv_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003071{
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03003072 if (unlikely(a->index))
3073 return -EINVAL;
3074
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003075 strcpy(a->name, "audio");
3076 return 0;
3077}
3078
Hans Verkuil0e8025b92012-09-04 11:59:31 -03003079static int bttv_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003080{
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03003081 if (unlikely(a->index))
3082 return -EINVAL;
3083
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003084 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003085}
3086
3087static ssize_t bttv_read(struct file *file, char __user *data,
3088 size_t count, loff_t *ppos)
3089{
3090 struct bttv_fh *fh = file->private_data;
3091 int retval = 0;
3092
3093 if (fh->btv->errors)
3094 bttv_reinit_bt848(fh->btv);
Joe Perches8af443e2011-08-21 19:56:48 -03003095 dprintk("%d: read count=%d type=%s\n",
3096 fh->btv->c.nr, (int)count, v4l2_type_names[fh->type]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003097
3098 switch (fh->type) {
3099 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003100 if (!check_alloc_btres_lock(fh->btv, fh, RESOURCE_VIDEO_READ)) {
Michael Schimeke5bd0262007-01-18 16:17:39 -03003101 /* VIDEO_READ in use by another fh,
3102 or VIDEO_STREAM by any fh. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003103 return -EBUSY;
Michael Schimeke5bd0262007-01-18 16:17:39 -03003104 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003105 retval = videobuf_read_one(&fh->cap, data, count, ppos,
3106 file->f_flags & O_NONBLOCK);
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003107 free_btres_lock(fh->btv, fh, RESOURCE_VIDEO_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003108 break;
3109 case V4L2_BUF_TYPE_VBI_CAPTURE:
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003110 if (!check_alloc_btres_lock(fh->btv,fh,RESOURCE_VBI))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003111 return -EBUSY;
3112 retval = videobuf_read_stream(&fh->vbi, data, count, ppos, 1,
3113 file->f_flags & O_NONBLOCK);
3114 break;
3115 default:
3116 BUG();
3117 }
3118 return retval;
3119}
3120
3121static unsigned int bttv_poll(struct file *file, poll_table *wait)
3122{
3123 struct bttv_fh *fh = file->private_data;
3124 struct bttv_buffer *buf;
3125 enum v4l2_field field;
Figo.zhang9fd64182009-06-16 13:31:29 -03003126 unsigned int rc = POLLERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003127
3128 if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003129 if (!check_alloc_btres_lock(fh->btv,fh,RESOURCE_VBI))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003130 return POLLERR;
3131 return videobuf_poll_stream(file, &fh->vbi, wait);
3132 }
3133
Michael Schimeke5bd0262007-01-18 16:17:39 -03003134 if (check_btres(fh,RESOURCE_VIDEO_STREAM)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003135 /* streaming capture */
3136 if (list_empty(&fh->cap.stream))
Figo.zhang9fd64182009-06-16 13:31:29 -03003137 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003138 buf = list_entry(fh->cap.stream.next,struct bttv_buffer,vb.stream);
3139 } else {
3140 /* read() capture */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003141 if (NULL == fh->cap.read_buf) {
3142 /* need to capture a new frame */
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03003143 if (locked_btres(fh->btv,RESOURCE_VIDEO_STREAM))
3144 goto err;
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03003145 fh->cap.read_buf = videobuf_sg_alloc(fh->cap.msize);
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03003146 if (NULL == fh->cap.read_buf)
3147 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003148 fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR;
3149 field = videobuf_next_field(&fh->cap);
3150 if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,field)) {
Nickolay V. Shmyrev50ab5ed2005-12-01 00:51:32 -08003151 kfree (fh->cap.read_buf);
3152 fh->cap.read_buf = NULL;
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03003153 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003154 }
3155 fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf);
3156 fh->cap.read_off = 0;
3157 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003158 buf = (struct bttv_buffer*)fh->cap.read_buf;
3159 }
3160
3161 poll_wait(file, &buf->vb.done, wait);
Brandon Philips0fc06862007-11-06 20:02:36 -03003162 if (buf->vb.state == VIDEOBUF_DONE ||
3163 buf->vb.state == VIDEOBUF_ERROR)
Figo.zhang9fd64182009-06-16 13:31:29 -03003164 rc = POLLIN|POLLRDNORM;
3165 else
3166 rc = 0;
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03003167err:
Figo.zhang9fd64182009-06-16 13:31:29 -03003168 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003169}
3170
Hans Verkuilbec43662008-12-30 06:58:20 -03003171static int bttv_open(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003172{
Laurent Pinchart50462eb2009-12-10 11:47:13 -02003173 struct video_device *vdev = video_devdata(file);
Trent Piepho4b10d3b2009-01-28 21:32:59 -03003174 struct bttv *btv = video_drvdata(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003175 struct bttv_fh *fh;
3176 enum v4l2_buf_type type = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003177
Joe Perches8af443e2011-08-21 19:56:48 -03003178 dprintk("open dev=%s\n", video_device_node_name(vdev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003179
Laurent Pinchart327ae592009-11-27 13:57:55 -03003180 if (vdev->vfl_type == VFL_TYPE_GRABBER) {
Trent Piepho4b10d3b2009-01-28 21:32:59 -03003181 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Laurent Pinchart327ae592009-11-27 13:57:55 -03003182 } else if (vdev->vfl_type == VFL_TYPE_VBI) {
Trent Piepho4b10d3b2009-01-28 21:32:59 -03003183 type = V4L2_BUF_TYPE_VBI_CAPTURE;
3184 } else {
3185 WARN_ON(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003186 return -ENODEV;
Hans Verkuild56dc612008-07-30 08:43:36 -03003187 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003188
Joe Perches8af443e2011-08-21 19:56:48 -03003189 dprintk("%d: open called (type=%s)\n",
3190 btv->c.nr, v4l2_type_names[type]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003191
3192 /* allocate per filehandle data */
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003193 fh = kmalloc(sizeof(*fh), GFP_KERNEL);
3194 if (unlikely(!fh))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003195 return -ENOMEM;
3196 file->private_data = fh;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003197
Linus Torvalds1da177e2005-04-16 15:20:36 -07003198 *fh = btv->init;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003199
Linus Torvalds1da177e2005-04-16 15:20:36 -07003200 fh->type = type;
3201 fh->ov.setup_ok = 0;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003202
Hans Verkuilffb48772010-05-01 08:03:24 -03003203 v4l2_prio_open(&btv->prio, &fh->prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003204
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03003205 videobuf_queue_sg_init(&fh->cap, &bttv_video_qops,
3206 &btv->c.pci->dev, &btv->s_lock,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003207 V4L2_BUF_TYPE_VIDEO_CAPTURE,
3208 V4L2_FIELD_INTERLACED,
3209 sizeof(struct bttv_buffer),
Mauro Carvalho Chehab587f0d52010-12-15 18:45:42 -03003210 fh, &btv->lock);
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03003211 videobuf_queue_sg_init(&fh->vbi, &bttv_vbi_qops,
3212 &btv->c.pci->dev, &btv->s_lock,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003213 V4L2_BUF_TYPE_VBI_CAPTURE,
3214 V4L2_FIELD_SEQ_TB,
3215 sizeof(struct bttv_buffer),
Mauro Carvalho Chehab587f0d52010-12-15 18:45:42 -03003216 fh, &btv->lock);
Nickolay V. Shmyrev302f61a2007-10-26 10:53:21 -03003217 set_tvnorm(btv,btv->tvnorm);
Mauro Carvalho Chehabb46a9c82008-08-05 10:12:35 -03003218 set_input(btv, btv->input, btv->tvnorm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003219
3220 btv->users++;
Michael Schimeke5bd0262007-01-18 16:17:39 -03003221
3222 /* The V4L2 spec requires one global set of cropping parameters
3223 which only change on request. These are stored in btv->crop[1].
3224 However for compatibility with V4L apps and cropping unaware
3225 V4L2 apps we now reset the cropping parameters as seen through
3226 this fh, which is to say VIDIOC_G_CROP and scaling limit checks
3227 will use btv->crop[0], the default cropping parameters for the
3228 current video standard, and VIDIOC_S_FMT will not implicitely
3229 change the cropping parameters until VIDIOC_S_CROP has been
3230 called. */
3231 fh->do_crop = !reset_crop; /* module parameter */
3232
3233 /* Likewise there should be one global set of VBI capture
3234 parameters, but for compatibility with V4L apps and earlier
3235 driver versions each fh has its own parameters. */
3236 bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm);
3237
Linus Torvalds1da177e2005-04-16 15:20:36 -07003238 bttv_field_count(btv);
3239 return 0;
3240}
3241
Hans Verkuilbec43662008-12-30 06:58:20 -03003242static int bttv_release(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003243{
3244 struct bttv_fh *fh = file->private_data;
3245 struct bttv *btv = fh->btv;
3246
3247 /* turn off overlay */
3248 if (check_btres(fh, RESOURCE_OVERLAY))
3249 bttv_switch_overlay(btv,fh,NULL);
3250
3251 /* stop video capture */
Michael Schimeke5bd0262007-01-18 16:17:39 -03003252 if (check_btres(fh, RESOURCE_VIDEO_STREAM)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003253 videobuf_streamoff(&fh->cap);
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003254 free_btres_lock(btv,fh,RESOURCE_VIDEO_STREAM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003255 }
3256 if (fh->cap.read_buf) {
3257 buffer_release(&fh->cap,fh->cap.read_buf);
3258 kfree(fh->cap.read_buf);
3259 }
Michael Schimeke5bd0262007-01-18 16:17:39 -03003260 if (check_btres(fh, RESOURCE_VIDEO_READ)) {
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003261 free_btres_lock(btv, fh, RESOURCE_VIDEO_READ);
Michael Schimeke5bd0262007-01-18 16:17:39 -03003262 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003263
3264 /* stop vbi capture */
3265 if (check_btres(fh, RESOURCE_VBI)) {
Brandon Philips053fcb62007-11-13 20:11:26 -03003266 videobuf_stop(&fh->vbi);
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003267 free_btres_lock(btv,fh,RESOURCE_VBI);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003268 }
3269
3270 /* free stuff */
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003271
Linus Torvalds1da177e2005-04-16 15:20:36 -07003272 videobuf_mmap_free(&fh->cap);
3273 videobuf_mmap_free(&fh->vbi);
Hans Verkuilffb48772010-05-01 08:03:24 -03003274 v4l2_prio_close(&btv->prio, fh->prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003275 file->private_data = NULL;
3276 kfree(fh);
3277
3278 btv->users--;
3279 bttv_field_count(btv);
Mauro Carvalho Chehabb46a9c82008-08-05 10:12:35 -03003280
3281 if (!btv->users)
3282 audio_mute(btv, 1);
3283
Linus Torvalds1da177e2005-04-16 15:20:36 -07003284 return 0;
3285}
3286
3287static int
3288bttv_mmap(struct file *file, struct vm_area_struct *vma)
3289{
3290 struct bttv_fh *fh = file->private_data;
3291
Joe Perches8af443e2011-08-21 19:56:48 -03003292 dprintk("%d: mmap type=%s 0x%lx+%ld\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003293 fh->btv->c.nr, v4l2_type_names[fh->type],
3294 vma->vm_start, vma->vm_end - vma->vm_start);
3295 return videobuf_mmap_mapper(bttv_queue(fh),vma);
3296}
3297
Hans Verkuilbec43662008-12-30 06:58:20 -03003298static const struct v4l2_file_operations bttv_fops =
Linus Torvalds1da177e2005-04-16 15:20:36 -07003299{
Mauro Carvalho Chehab8979e9d2010-09-15 08:22:09 -03003300 .owner = THIS_MODULE,
3301 .open = bttv_open,
3302 .release = bttv_release,
3303 .unlocked_ioctl = video_ioctl2,
3304 .read = bttv_read,
3305 .mmap = bttv_mmap,
3306 .poll = bttv_poll,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003307};
3308
Hans Verkuila3998102008-07-21 02:57:38 -03003309static const struct v4l2_ioctl_ops bttv_ioctl_ops = {
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003310 .vidioc_querycap = bttv_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03003311 .vidioc_enum_fmt_vid_cap = bttv_enum_fmt_vid_cap,
3312 .vidioc_g_fmt_vid_cap = bttv_g_fmt_vid_cap,
3313 .vidioc_try_fmt_vid_cap = bttv_try_fmt_vid_cap,
3314 .vidioc_s_fmt_vid_cap = bttv_s_fmt_vid_cap,
3315 .vidioc_enum_fmt_vid_overlay = bttv_enum_fmt_vid_overlay,
3316 .vidioc_g_fmt_vid_overlay = bttv_g_fmt_vid_overlay,
3317 .vidioc_try_fmt_vid_overlay = bttv_try_fmt_vid_overlay,
3318 .vidioc_s_fmt_vid_overlay = bttv_s_fmt_vid_overlay,
Hans Verkuil78b526a2008-05-28 12:16:41 -03003319 .vidioc_g_fmt_vbi_cap = bttv_g_fmt_vbi_cap,
3320 .vidioc_try_fmt_vbi_cap = bttv_try_fmt_vbi_cap,
3321 .vidioc_s_fmt_vbi_cap = bttv_s_fmt_vbi_cap,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003322 .vidioc_g_audio = bttv_g_audio,
3323 .vidioc_s_audio = bttv_s_audio,
3324 .vidioc_cropcap = bttv_cropcap,
3325 .vidioc_reqbufs = bttv_reqbufs,
3326 .vidioc_querybuf = bttv_querybuf,
3327 .vidioc_qbuf = bttv_qbuf,
3328 .vidioc_dqbuf = bttv_dqbuf,
3329 .vidioc_s_std = bttv_s_std,
3330 .vidioc_enum_input = bttv_enum_input,
3331 .vidioc_g_input = bttv_g_input,
3332 .vidioc_s_input = bttv_s_input,
3333 .vidioc_queryctrl = bttv_queryctrl,
3334 .vidioc_g_ctrl = bttv_g_ctrl,
3335 .vidioc_s_ctrl = bttv_s_ctrl,
3336 .vidioc_streamon = bttv_streamon,
3337 .vidioc_streamoff = bttv_streamoff,
3338 .vidioc_g_tuner = bttv_g_tuner,
3339 .vidioc_s_tuner = bttv_s_tuner,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003340 .vidioc_g_crop = bttv_g_crop,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003341 .vidioc_s_crop = bttv_s_crop,
3342 .vidioc_g_fbuf = bttv_g_fbuf,
3343 .vidioc_s_fbuf = bttv_s_fbuf,
3344 .vidioc_overlay = bttv_overlay,
3345 .vidioc_g_priority = bttv_g_priority,
3346 .vidioc_s_priority = bttv_s_priority,
3347 .vidioc_g_parm = bttv_g_parm,
3348 .vidioc_g_frequency = bttv_g_frequency,
3349 .vidioc_s_frequency = bttv_s_frequency,
3350 .vidioc_log_status = bttv_log_status,
3351 .vidioc_querystd = bttv_querystd,
Zoltan Devai43846832008-01-14 13:24:38 -03003352#ifdef CONFIG_VIDEO_ADV_DEBUG
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003353 .vidioc_g_register = bttv_g_register,
3354 .vidioc_s_register = bttv_s_register,
Zoltan Devai43846832008-01-14 13:24:38 -03003355#endif
Hans Verkuila3998102008-07-21 02:57:38 -03003356};
3357
3358static struct video_device bttv_video_template = {
3359 .fops = &bttv_fops,
Hans Verkuila3998102008-07-21 02:57:38 -03003360 .ioctl_ops = &bttv_ioctl_ops,
3361 .tvnorms = BTTV_NORMS,
3362 .current_norm = V4L2_STD_PAL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003363};
3364
Linus Torvalds1da177e2005-04-16 15:20:36 -07003365/* ----------------------------------------------------------------------- */
3366/* radio interface */
3367
Hans Verkuilbec43662008-12-30 06:58:20 -03003368static int radio_open(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003369{
Laurent Pinchart50462eb2009-12-10 11:47:13 -02003370 struct video_device *vdev = video_devdata(file);
Trent Piepho4b10d3b2009-01-28 21:32:59 -03003371 struct bttv *btv = video_drvdata(file);
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003372 struct bttv_fh *fh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003373
Joe Perches8af443e2011-08-21 19:56:48 -03003374 dprintk("open dev=%s\n", video_device_node_name(vdev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003375
Joe Perches8af443e2011-08-21 19:56:48 -03003376 dprintk("%d: open called (radio)\n", btv->c.nr);
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003377
3378 /* allocate per filehandle data */
3379 fh = kmalloc(sizeof(*fh), GFP_KERNEL);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003380 if (unlikely(!fh))
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003381 return -ENOMEM;
3382 file->private_data = fh;
3383 *fh = btv->init;
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003384
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003385 v4l2_prio_open(&btv->prio, &fh->prio);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003386
Linus Torvalds1da177e2005-04-16 15:20:36 -07003387 btv->radio_user++;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003388
Hans Verkuil859f0272009-03-28 08:29:00 -03003389 bttv_call_all(btv, tuner, s_radio);
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03003390 audio_input(btv,TVAUDIO_INPUT_RADIO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003391
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003392 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003393}
3394
Hans Verkuilbec43662008-12-30 06:58:20 -03003395static int radio_release(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003396{
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003397 struct bttv_fh *fh = file->private_data;
3398 struct bttv *btv = fh->btv;
Hans Verkuilb9218f22010-12-27 12:22:46 -03003399 struct saa6588_command cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003400
Hans Verkuilffb48772010-05-01 08:03:24 -03003401 v4l2_prio_close(&btv->prio, fh->prio);
Robert Fitzsimonsb9bc07a2008-04-10 09:40:31 -03003402 file->private_data = NULL;
3403 kfree(fh);
3404
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405 btv->radio_user--;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003406
Hans Verkuilb9218f22010-12-27 12:22:46 -03003407 bttv_call_all(btv, core, ioctl, SAA6588_CMD_CLOSE, &cmd);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003408
Linus Torvalds1da177e2005-04-16 15:20:36 -07003409 return 0;
3410}
3411
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003412static int radio_querycap(struct file *file, void *priv,
3413 struct v4l2_capability *cap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003414{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003415 struct bttv_fh *fh = priv;
3416 struct bttv *btv = fh->btv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003417
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003418 strcpy(cap->driver, "bttv");
3419 strlcpy(cap->card, btv->radio_dev->name, sizeof(cap->card));
3420 sprintf(cap->bus_info, "PCI:%s", pci_name(btv->c.pci));
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003421 cap->capabilities = V4L2_CAP_TUNER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003422
Linus Torvalds1da177e2005-04-16 15:20:36 -07003423 return 0;
3424}
3425
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003426static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003427{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003428 struct bttv_fh *fh = priv;
3429 struct bttv *btv = fh->btv;
3430
Trent Piephoabb03622009-01-28 21:32:59 -03003431 if (btv->tuner_type == TUNER_ABSENT)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003432 return -EINVAL;
3433 if (0 != t->index)
3434 return -EINVAL;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003435 strcpy(t->name, "Radio");
3436 t->type = V4L2_TUNER_RADIO;
3437
Hans Verkuil859f0272009-03-28 08:29:00 -03003438 bttv_call_all(btv, tuner, g_tuner, t);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003439
3440 if (btv->audio_mode_gpio)
3441 btv->audio_mode_gpio(btv, t, 0);
3442
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003443 return 0;
3444}
3445
3446static int radio_enum_input(struct file *file, void *priv,
3447 struct v4l2_input *i)
3448{
3449 if (i->index != 0)
3450 return -EINVAL;
3451
3452 strcpy(i->name, "Radio");
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03003453 i->type = V4L2_INPUT_TYPE_TUNER;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003454
3455 return 0;
3456}
3457
3458static int radio_g_audio(struct file *file, void *priv,
3459 struct v4l2_audio *a)
3460{
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03003461 if (unlikely(a->index))
Cyrill Gorcunov1a002eb2008-04-01 17:49:13 -03003462 return -EINVAL;
3463
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003464 strcpy(a->name, "Radio");
Cyrill Gorcunov1a002eb2008-04-01 17:49:13 -03003465
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003466 return 0;
3467}
3468
3469static int radio_s_tuner(struct file *file, void *priv,
3470 struct v4l2_tuner *t)
3471{
3472 struct bttv_fh *fh = priv;
3473 struct bttv *btv = fh->btv;
3474
3475 if (0 != t->index)
3476 return -EINVAL;
3477
Hans Verkuila024c1a2011-06-12 07:02:43 -03003478 bttv_call_all(btv, tuner, s_tuner, t);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003479 return 0;
3480}
3481
3482static int radio_s_audio(struct file *file, void *priv,
Hans Verkuil0e8025b92012-09-04 11:59:31 -03003483 const struct v4l2_audio *a)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003484{
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03003485 if (unlikely(a->index))
3486 return -EINVAL;
3487
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003488 return 0;
3489}
3490
3491static int radio_s_input(struct file *filp, void *priv, unsigned int i)
3492{
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03003493 if (unlikely(i))
3494 return -EINVAL;
3495
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003496 return 0;
3497}
3498
3499static int radio_s_std(struct file *file, void *fh, v4l2_std_id *norm)
3500{
3501 return 0;
3502}
3503
3504static int radio_queryctrl(struct file *file, void *priv,
3505 struct v4l2_queryctrl *c)
3506{
3507 const struct v4l2_queryctrl *ctrl;
3508
3509 if (c->id < V4L2_CID_BASE ||
3510 c->id >= V4L2_CID_LASTP1)
3511 return -EINVAL;
3512
3513 if (c->id == V4L2_CID_AUDIO_MUTE) {
3514 ctrl = ctrl_by_id(c->id);
3515 *c = *ctrl;
3516 } else
3517 *c = no_ctl;
3518
3519 return 0;
3520}
3521
3522static int radio_g_input(struct file *filp, void *priv, unsigned int *i)
3523{
3524 *i = 0;
3525 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003526}
3527
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003528static ssize_t radio_read(struct file *file, char __user *data,
3529 size_t count, loff_t *ppos)
3530{
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003531 struct bttv_fh *fh = file->private_data;
3532 struct bttv *btv = fh->btv;
Hans Verkuilb9218f22010-12-27 12:22:46 -03003533 struct saa6588_command cmd;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003534 cmd.block_count = count/3;
3535 cmd.buffer = data;
3536 cmd.instance = file;
3537 cmd.result = -ENODEV;
3538
Hans Verkuilb9218f22010-12-27 12:22:46 -03003539 bttv_call_all(btv, core, ioctl, SAA6588_CMD_READ, &cmd);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003540
3541 return cmd.result;
3542}
3543
3544static unsigned int radio_poll(struct file *file, poll_table *wait)
3545{
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003546 struct bttv_fh *fh = file->private_data;
3547 struct bttv *btv = fh->btv;
Hans Verkuilb9218f22010-12-27 12:22:46 -03003548 struct saa6588_command cmd;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003549 cmd.instance = file;
3550 cmd.event_list = wait;
3551 cmd.result = -ENODEV;
Hans Verkuilb9218f22010-12-27 12:22:46 -03003552 bttv_call_all(btv, core, ioctl, SAA6588_CMD_POLL, &cmd);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003553
3554 return cmd.result;
3555}
3556
Hans Verkuilbec43662008-12-30 06:58:20 -03003557static const struct v4l2_file_operations radio_fops =
Linus Torvalds1da177e2005-04-16 15:20:36 -07003558{
3559 .owner = THIS_MODULE,
3560 .open = radio_open,
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003561 .read = radio_read,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003562 .release = radio_release,
Mauro Carvalho Chehab587f0d52010-12-15 18:45:42 -03003563 .unlocked_ioctl = video_ioctl2,
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003564 .poll = radio_poll,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003565};
3566
Hans Verkuila3998102008-07-21 02:57:38 -03003567static const struct v4l2_ioctl_ops radio_ioctl_ops = {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003568 .vidioc_querycap = radio_querycap,
3569 .vidioc_g_tuner = radio_g_tuner,
3570 .vidioc_enum_input = radio_enum_input,
3571 .vidioc_g_audio = radio_g_audio,
3572 .vidioc_s_tuner = radio_s_tuner,
3573 .vidioc_s_audio = radio_s_audio,
3574 .vidioc_s_input = radio_s_input,
3575 .vidioc_s_std = radio_s_std,
3576 .vidioc_queryctrl = radio_queryctrl,
3577 .vidioc_g_input = radio_g_input,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003578 .vidioc_g_ctrl = bttv_g_ctrl,
3579 .vidioc_s_ctrl = bttv_s_ctrl,
3580 .vidioc_g_frequency = bttv_g_frequency,
3581 .vidioc_s_frequency = bttv_s_frequency,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003582};
3583
Hans Verkuila3998102008-07-21 02:57:38 -03003584static struct video_device radio_template = {
3585 .fops = &radio_fops,
Hans Verkuila3998102008-07-21 02:57:38 -03003586 .ioctl_ops = &radio_ioctl_ops,
3587};
3588
Linus Torvalds1da177e2005-04-16 15:20:36 -07003589/* ----------------------------------------------------------------------- */
3590/* some debug code */
3591
Adrian Bunk408b6642005-05-01 08:59:29 -07003592static int bttv_risc_decode(u32 risc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003593{
3594 static char *instr[16] = {
3595 [ BT848_RISC_WRITE >> 28 ] = "write",
3596 [ BT848_RISC_SKIP >> 28 ] = "skip",
3597 [ BT848_RISC_WRITEC >> 28 ] = "writec",
3598 [ BT848_RISC_JUMP >> 28 ] = "jump",
3599 [ BT848_RISC_SYNC >> 28 ] = "sync",
3600 [ BT848_RISC_WRITE123 >> 28 ] = "write123",
3601 [ BT848_RISC_SKIP123 >> 28 ] = "skip123",
3602 [ BT848_RISC_WRITE1S23 >> 28 ] = "write1s23",
3603 };
3604 static int incr[16] = {
3605 [ BT848_RISC_WRITE >> 28 ] = 2,
3606 [ BT848_RISC_JUMP >> 28 ] = 2,
3607 [ BT848_RISC_SYNC >> 28 ] = 2,
3608 [ BT848_RISC_WRITE123 >> 28 ] = 5,
3609 [ BT848_RISC_SKIP123 >> 28 ] = 2,
3610 [ BT848_RISC_WRITE1S23 >> 28 ] = 3,
3611 };
3612 static char *bits[] = {
3613 "be0", "be1", "be2", "be3/resync",
3614 "set0", "set1", "set2", "set3",
3615 "clr0", "clr1", "clr2", "clr3",
3616 "irq", "res", "eol", "sol",
3617 };
3618 int i;
3619
Joe Perches8af443e2011-08-21 19:56:48 -03003620 pr_cont("0x%08x [ %s", risc,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003621 instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
3622 for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
3623 if (risc & (1 << (i + 12)))
Joe Perches8af443e2011-08-21 19:56:48 -03003624 pr_cont(" %s", bits[i]);
3625 pr_cont(" count=%d ]\n", risc & 0xfff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003626 return incr[risc >> 28] ? incr[risc >> 28] : 1;
3627}
3628
Adrian Bunk408b6642005-05-01 08:59:29 -07003629static void bttv_risc_disasm(struct bttv *btv,
3630 struct btcx_riscmem *risc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631{
3632 unsigned int i,j,n;
3633
Joe Perches8af443e2011-08-21 19:56:48 -03003634 pr_info("%s: risc disasm: %p [dma=0x%08lx]\n",
3635 btv->c.v4l2_dev.name, risc->cpu, (unsigned long)risc->dma);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003636 for (i = 0; i < (risc->size >> 2); i += n) {
Joe Perches8af443e2011-08-21 19:56:48 -03003637 pr_info("%s: 0x%lx: ",
3638 btv->c.v4l2_dev.name,
3639 (unsigned long)(risc->dma + (i<<2)));
Al Viro3aa71102008-06-22 14:20:09 -03003640 n = bttv_risc_decode(le32_to_cpu(risc->cpu[i]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003641 for (j = 1; j < n; j++)
Joe Perches8af443e2011-08-21 19:56:48 -03003642 pr_info("%s: 0x%lx: 0x%08x [ arg #%d ]\n",
3643 btv->c.v4l2_dev.name,
3644 (unsigned long)(risc->dma + ((i+j)<<2)),
3645 risc->cpu[i+j], j);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003646 if (0 == risc->cpu[i])
3647 break;
3648 }
3649}
3650
3651static void bttv_print_riscaddr(struct bttv *btv)
3652{
Joe Perches8af443e2011-08-21 19:56:48 -03003653 pr_info(" main: %08llx\n", (unsigned long long)btv->main.dma);
3654 pr_info(" vbi : o=%08llx e=%08llx\n",
3655 btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
3656 btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0);
3657 pr_info(" cap : o=%08llx e=%08llx\n",
3658 btv->curr.top
3659 ? (unsigned long long)btv->curr.top->top.dma : 0,
3660 btv->curr.bottom
3661 ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
3662 pr_info(" scr : o=%08llx e=%08llx\n",
3663 btv->screen ? (unsigned long long)btv->screen->top.dma : 0,
3664 btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003665 bttv_risc_disasm(btv, &btv->main);
3666}
3667
3668/* ----------------------------------------------------------------------- */
3669/* irq handler */
3670
3671static char *irq_name[] = {
3672 "FMTCHG", // format change detected (525 vs. 625)
3673 "VSYNC", // vertical sync (new field)
3674 "HSYNC", // horizontal sync
3675 "OFLOW", // chroma/luma AGC overflow
3676 "HLOCK", // horizontal lock changed
3677 "VPRES", // video presence changed
3678 "6", "7",
3679 "I2CDONE", // hw irc operation finished
3680 "GPINT", // gpio port triggered irq
3681 "10",
3682 "RISCI", // risc instruction triggered irq
3683 "FBUS", // pixel data fifo dropped data (high pci bus latencies)
3684 "FTRGT", // pixel data fifo overrun
3685 "FDSR", // fifo data stream resyncronisation
3686 "PPERR", // parity error (data transfer)
3687 "RIPERR", // parity error (read risc instructions)
3688 "PABORT", // pci abort
3689 "OCERR", // risc instruction error
3690 "SCERR", // syncronisation error
3691};
3692
3693static void bttv_print_irqbits(u32 print, u32 mark)
3694{
3695 unsigned int i;
3696
Joe Perches8af443e2011-08-21 19:56:48 -03003697 pr_cont("bits:");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003698 for (i = 0; i < ARRAY_SIZE(irq_name); i++) {
3699 if (print & (1 << i))
Joe Perches8af443e2011-08-21 19:56:48 -03003700 pr_cont(" %s", irq_name[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003701 if (mark & (1 << i))
Joe Perches8af443e2011-08-21 19:56:48 -03003702 pr_cont("*");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003703 }
3704}
3705
3706static void bttv_irq_debug_low_latency(struct bttv *btv, u32 rc)
3707{
Joe Perches8af443e2011-08-21 19:56:48 -03003708 pr_warn("%d: irq: skipped frame [main=%lx,o_vbi=%lx,o_field=%lx,rc=%lx]\n",
3709 btv->c.nr,
3710 (unsigned long)btv->main.dma,
3711 (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_VBI+1]),
3712 (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_FIELD+1]),
3713 (unsigned long)rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003714
3715 if (0 == (btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC)) {
Joe Perches8af443e2011-08-21 19:56:48 -03003716 pr_notice("%d: Oh, there (temporarily?) is no input signal. "
3717 "Ok, then this is harmless, don't worry ;)\n",
3718 btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003719 return;
3720 }
Joe Perches8af443e2011-08-21 19:56:48 -03003721 pr_notice("%d: Uhm. Looks like we have unusual high IRQ latencies\n",
3722 btv->c.nr);
3723 pr_notice("%d: Lets try to catch the culpit red-handed ...\n",
3724 btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003725 dump_stack();
3726}
3727
3728static int
3729bttv_irq_next_video(struct bttv *btv, struct bttv_buffer_set *set)
3730{
3731 struct bttv_buffer *item;
3732
3733 memset(set,0,sizeof(*set));
3734
3735 /* capture request ? */
3736 if (!list_empty(&btv->capture)) {
3737 set->frame_irq = 1;
3738 item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
3739 if (V4L2_FIELD_HAS_TOP(item->vb.field))
3740 set->top = item;
3741 if (V4L2_FIELD_HAS_BOTTOM(item->vb.field))
3742 set->bottom = item;
3743
3744 /* capture request for other field ? */
3745 if (!V4L2_FIELD_HAS_BOTH(item->vb.field) &&
3746 (item->vb.queue.next != &btv->capture)) {
3747 item = list_entry(item->vb.queue.next, struct bttv_buffer, vb.queue);
Mike Isely66349b42009-09-21 12:09:08 -03003748 /* Mike Isely <isely@pobox.com> - Only check
3749 * and set up the bottom field in the logic
3750 * below. Don't ever do the top field. This
3751 * of course means that if we set up the
3752 * bottom field in the above code that we'll
3753 * actually skip a field. But that's OK.
3754 * Having processed only a single buffer this
3755 * time, then the next time around the first
3756 * available buffer should be for a top field.
3757 * That will then cause us here to set up a
3758 * top then a bottom field in the normal way.
3759 * The alternative to this understanding is
3760 * that we set up the second available buffer
3761 * as a top field, but that's out of order
3762 * since this driver always processes the top
3763 * field first - the effect will be the two
3764 * buffers being returned in the wrong order,
3765 * with the second buffer also being delayed
3766 * by one field time (owing to the fifo nature
3767 * of videobuf). Worse still, we'll be stuck
3768 * doing fields out of order now every time
3769 * until something else causes a field to be
3770 * dropped. By effectively forcing a field to
3771 * drop this way then we always get back into
3772 * sync within a single frame time. (Out of
3773 * order fields can screw up deinterlacing
3774 * algorithms.) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003775 if (!V4L2_FIELD_HAS_BOTH(item->vb.field)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003776 if (NULL == set->bottom &&
3777 V4L2_FIELD_BOTTOM == item->vb.field) {
3778 set->bottom = item;
3779 }
3780 if (NULL != set->top && NULL != set->bottom)
3781 set->top_irq = 2;
3782 }
3783 }
3784 }
3785
3786 /* screen overlay ? */
3787 if (NULL != btv->screen) {
3788 if (V4L2_FIELD_HAS_BOTH(btv->screen->vb.field)) {
3789 if (NULL == set->top && NULL == set->bottom) {
3790 set->top = btv->screen;
3791 set->bottom = btv->screen;
3792 }
3793 } else {
3794 if (V4L2_FIELD_TOP == btv->screen->vb.field &&
3795 NULL == set->top) {
3796 set->top = btv->screen;
3797 }
3798 if (V4L2_FIELD_BOTTOM == btv->screen->vb.field &&
3799 NULL == set->bottom) {
3800 set->bottom = btv->screen;
3801 }
3802 }
3803 }
3804
Joe Perches8af443e2011-08-21 19:56:48 -03003805 dprintk("%d: next set: top=%p bottom=%p [screen=%p,irq=%d,%d]\n",
3806 btv->c.nr, set->top, set->bottom,
3807 btv->screen, set->frame_irq, set->top_irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003808 return 0;
3809}
3810
3811static void
3812bttv_irq_wakeup_video(struct bttv *btv, struct bttv_buffer_set *wakeup,
3813 struct bttv_buffer_set *curr, unsigned int state)
3814{
3815 struct timeval ts;
3816
3817 do_gettimeofday(&ts);
3818
3819 if (wakeup->top == wakeup->bottom) {
3820 if (NULL != wakeup->top && curr->top != wakeup->top) {
3821 if (irq_debug > 1)
Joe Perches8af443e2011-08-21 19:56:48 -03003822 pr_debug("%d: wakeup: both=%p\n",
3823 btv->c.nr, wakeup->top);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003824 wakeup->top->vb.ts = ts;
3825 wakeup->top->vb.field_count = btv->field_count;
3826 wakeup->top->vb.state = state;
3827 wake_up(&wakeup->top->vb.done);
3828 }
3829 } else {
3830 if (NULL != wakeup->top && curr->top != wakeup->top) {
3831 if (irq_debug > 1)
Joe Perches8af443e2011-08-21 19:56:48 -03003832 pr_debug("%d: wakeup: top=%p\n",
3833 btv->c.nr, wakeup->top);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003834 wakeup->top->vb.ts = ts;
3835 wakeup->top->vb.field_count = btv->field_count;
3836 wakeup->top->vb.state = state;
3837 wake_up(&wakeup->top->vb.done);
3838 }
3839 if (NULL != wakeup->bottom && curr->bottom != wakeup->bottom) {
3840 if (irq_debug > 1)
Joe Perches8af443e2011-08-21 19:56:48 -03003841 pr_debug("%d: wakeup: bottom=%p\n",
3842 btv->c.nr, wakeup->bottom);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003843 wakeup->bottom->vb.ts = ts;
3844 wakeup->bottom->vb.field_count = btv->field_count;
3845 wakeup->bottom->vb.state = state;
3846 wake_up(&wakeup->bottom->vb.done);
3847 }
3848 }
3849}
3850
3851static void
3852bttv_irq_wakeup_vbi(struct bttv *btv, struct bttv_buffer *wakeup,
3853 unsigned int state)
3854{
3855 struct timeval ts;
3856
3857 if (NULL == wakeup)
3858 return;
3859
3860 do_gettimeofday(&ts);
3861 wakeup->vb.ts = ts;
3862 wakeup->vb.field_count = btv->field_count;
3863 wakeup->vb.state = state;
3864 wake_up(&wakeup->vb.done);
3865}
3866
3867static void bttv_irq_timeout(unsigned long data)
3868{
3869 struct bttv *btv = (struct bttv *)data;
3870 struct bttv_buffer_set old,new;
3871 struct bttv_buffer *ovbi;
3872 struct bttv_buffer *item;
3873 unsigned long flags;
3874
3875 if (bttv_verbose) {
Joe Perches8af443e2011-08-21 19:56:48 -03003876 pr_info("%d: timeout: drop=%d irq=%d/%d, risc=%08x, ",
3877 btv->c.nr, btv->framedrop, btv->irq_me, btv->irq_total,
3878 btread(BT848_RISC_COUNT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003879 bttv_print_irqbits(btread(BT848_INT_STAT),0);
Joe Perches8af443e2011-08-21 19:56:48 -03003880 pr_cont("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003881 }
3882
3883 spin_lock_irqsave(&btv->s_lock,flags);
3884
3885 /* deactivate stuff */
3886 memset(&new,0,sizeof(new));
3887 old = btv->curr;
3888 ovbi = btv->cvbi;
3889 btv->curr = new;
3890 btv->cvbi = NULL;
3891 btv->loop_irq = 0;
3892 bttv_buffer_activate_video(btv, &new);
3893 bttv_buffer_activate_vbi(btv, NULL);
3894 bttv_set_dma(btv, 0);
3895
3896 /* wake up */
Brandon Philips0fc06862007-11-06 20:02:36 -03003897 bttv_irq_wakeup_video(btv, &old, &new, VIDEOBUF_ERROR);
3898 bttv_irq_wakeup_vbi(btv, ovbi, VIDEOBUF_ERROR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003899
3900 /* cancel all outstanding capture / vbi requests */
3901 while (!list_empty(&btv->capture)) {
3902 item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
3903 list_del(&item->vb.queue);
Brandon Philips0fc06862007-11-06 20:02:36 -03003904 item->vb.state = VIDEOBUF_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003905 wake_up(&item->vb.done);
3906 }
3907 while (!list_empty(&btv->vcapture)) {
3908 item = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
3909 list_del(&item->vb.queue);
Brandon Philips0fc06862007-11-06 20:02:36 -03003910 item->vb.state = VIDEOBUF_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003911 wake_up(&item->vb.done);
3912 }
3913
3914 btv->errors++;
3915 spin_unlock_irqrestore(&btv->s_lock,flags);
3916}
3917
3918static void
3919bttv_irq_wakeup_top(struct bttv *btv)
3920{
3921 struct bttv_buffer *wakeup = btv->curr.top;
3922
3923 if (NULL == wakeup)
3924 return;
3925
3926 spin_lock(&btv->s_lock);
3927 btv->curr.top_irq = 0;
3928 btv->curr.top = NULL;
3929 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
3930
3931 do_gettimeofday(&wakeup->vb.ts);
3932 wakeup->vb.field_count = btv->field_count;
Brandon Philips0fc06862007-11-06 20:02:36 -03003933 wakeup->vb.state = VIDEOBUF_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003934 wake_up(&wakeup->vb.done);
3935 spin_unlock(&btv->s_lock);
3936}
3937
3938static inline int is_active(struct btcx_riscmem *risc, u32 rc)
3939{
3940 if (rc < risc->dma)
3941 return 0;
3942 if (rc > risc->dma + risc->size)
3943 return 0;
3944 return 1;
3945}
3946
3947static void
3948bttv_irq_switch_video(struct bttv *btv)
3949{
3950 struct bttv_buffer_set new;
3951 struct bttv_buffer_set old;
3952 dma_addr_t rc;
3953
3954 spin_lock(&btv->s_lock);
3955
3956 /* new buffer set */
3957 bttv_irq_next_video(btv, &new);
3958 rc = btread(BT848_RISC_COUNT);
3959 if ((btv->curr.top && is_active(&btv->curr.top->top, rc)) ||
3960 (btv->curr.bottom && is_active(&btv->curr.bottom->bottom, rc))) {
3961 btv->framedrop++;
3962 if (debug_latency)
3963 bttv_irq_debug_low_latency(btv, rc);
3964 spin_unlock(&btv->s_lock);
3965 return;
3966 }
3967
3968 /* switch over */
3969 old = btv->curr;
3970 btv->curr = new;
3971 btv->loop_irq &= ~1;
3972 bttv_buffer_activate_video(btv, &new);
3973 bttv_set_dma(btv, 0);
3974
3975 /* switch input */
3976 if (UNSET != btv->new_input) {
3977 video_mux(btv,btv->new_input);
3978 btv->new_input = UNSET;
3979 }
3980
3981 /* wake up finished buffers */
Brandon Philips0fc06862007-11-06 20:02:36 -03003982 bttv_irq_wakeup_video(btv, &old, &new, VIDEOBUF_DONE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003983 spin_unlock(&btv->s_lock);
3984}
3985
3986static void
3987bttv_irq_switch_vbi(struct bttv *btv)
3988{
3989 struct bttv_buffer *new = NULL;
3990 struct bttv_buffer *old;
3991 u32 rc;
3992
3993 spin_lock(&btv->s_lock);
3994
3995 if (!list_empty(&btv->vcapture))
3996 new = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
3997 old = btv->cvbi;
3998
3999 rc = btread(BT848_RISC_COUNT);
4000 if (NULL != old && (is_active(&old->top, rc) ||
4001 is_active(&old->bottom, rc))) {
4002 btv->framedrop++;
4003 if (debug_latency)
4004 bttv_irq_debug_low_latency(btv, rc);
4005 spin_unlock(&btv->s_lock);
4006 return;
4007 }
4008
4009 /* switch */
4010 btv->cvbi = new;
4011 btv->loop_irq &= ~4;
4012 bttv_buffer_activate_vbi(btv, new);
4013 bttv_set_dma(btv, 0);
4014
Brandon Philips0fc06862007-11-06 20:02:36 -03004015 bttv_irq_wakeup_vbi(btv, old, VIDEOBUF_DONE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016 spin_unlock(&btv->s_lock);
4017}
4018
David Howells7d12e782006-10-05 14:55:46 +01004019static irqreturn_t bttv_irq(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004020{
4021 u32 stat,astat;
4022 u32 dstat;
4023 int count;
4024 struct bttv *btv;
4025 int handled = 0;
4026
4027 btv=(struct bttv *)dev_id;
Mark Weaver6c6c0b22005-11-13 16:07:52 -08004028
Linus Torvalds1da177e2005-04-16 15:20:36 -07004029 count=0;
4030 while (1) {
4031 /* get/clear interrupt status bits */
4032 stat=btread(BT848_INT_STAT);
4033 astat=stat&btread(BT848_INT_MASK);
4034 if (!astat)
4035 break;
4036 handled = 1;
4037 btwrite(stat,BT848_INT_STAT);
4038
4039 /* get device status bits */
4040 dstat=btread(BT848_DSTATUS);
4041
4042 if (irq_debug) {
Joe Perches8af443e2011-08-21 19:56:48 -03004043 pr_debug("%d: irq loop=%d fc=%d riscs=%x, riscc=%08x, ",
4044 btv->c.nr, count, btv->field_count,
4045 stat>>28, btread(BT848_RISC_COUNT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046 bttv_print_irqbits(stat,astat);
4047 if (stat & BT848_INT_HLOCK)
Joe Perches8af443e2011-08-21 19:56:48 -03004048 pr_cont(" HLOC => %s",
4049 dstat & BT848_DSTATUS_HLOC
4050 ? "yes" : "no");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051 if (stat & BT848_INT_VPRES)
Joe Perches8af443e2011-08-21 19:56:48 -03004052 pr_cont(" PRES => %s",
4053 dstat & BT848_DSTATUS_PRES
4054 ? "yes" : "no");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004055 if (stat & BT848_INT_FMTCHG)
Joe Perches8af443e2011-08-21 19:56:48 -03004056 pr_cont(" NUML => %s",
4057 dstat & BT848_DSTATUS_NUML
4058 ? "625" : "525");
4059 pr_cont("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060 }
4061
4062 if (astat&BT848_INT_VSYNC)
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004063 btv->field_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004064
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02004065 if ((astat & BT848_INT_GPINT) && btv->remote) {
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02004066 bttv_input_irq(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067 }
4068
4069 if (astat & BT848_INT_I2CDONE) {
4070 btv->i2c_done = stat;
4071 wake_up(&btv->i2c_queue);
4072 }
4073
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004074 if ((astat & BT848_INT_RISCI) && (stat & (4<<28)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075 bttv_irq_switch_vbi(btv);
4076
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004077 if ((astat & BT848_INT_RISCI) && (stat & (2<<28)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078 bttv_irq_wakeup_top(btv);
4079
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004080 if ((astat & BT848_INT_RISCI) && (stat & (1<<28)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004081 bttv_irq_switch_video(btv);
4082
4083 if ((astat & BT848_INT_HLOCK) && btv->opt_automute)
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03004084 audio_mute(btv, btv->mute); /* trigger automute */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004085
4086 if (astat & (BT848_INT_SCERR|BT848_INT_OCERR)) {
Joe Perches8af443e2011-08-21 19:56:48 -03004087 pr_info("%d: %s%s @ %08x,",
4088 btv->c.nr,
4089 (astat & BT848_INT_SCERR) ? "SCERR" : "",
4090 (astat & BT848_INT_OCERR) ? "OCERR" : "",
4091 btread(BT848_RISC_COUNT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004092 bttv_print_irqbits(stat,astat);
Joe Perches8af443e2011-08-21 19:56:48 -03004093 pr_cont("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004094 if (bttv_debug)
4095 bttv_print_riscaddr(btv);
4096 }
4097 if (fdsr && astat & BT848_INT_FDSR) {
Joe Perches8af443e2011-08-21 19:56:48 -03004098 pr_info("%d: FDSR @ %08x\n",
4099 btv->c.nr, btread(BT848_RISC_COUNT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004100 if (bttv_debug)
4101 bttv_print_riscaddr(btv);
4102 }
4103
4104 count++;
4105 if (count > 4) {
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08004106
4107 if (count > 8 || !(astat & BT848_INT_GPINT)) {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004108 btwrite(0, BT848_INT_MASK);
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08004109
Joe Perches8af443e2011-08-21 19:56:48 -03004110 pr_err("%d: IRQ lockup, cleared int mask [",
4111 btv->c.nr);
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08004112 } else {
Joe Perches8af443e2011-08-21 19:56:48 -03004113 pr_err("%d: IRQ lockup, clearing GPINT from int mask [",
4114 btv->c.nr);
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08004115
4116 btwrite(btread(BT848_INT_MASK) & (-1 ^ BT848_INT_GPINT),
4117 BT848_INT_MASK);
4118 };
4119
Linus Torvalds1da177e2005-04-16 15:20:36 -07004120 bttv_print_irqbits(stat,astat);
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08004121
Joe Perches8af443e2011-08-21 19:56:48 -03004122 pr_cont("]\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123 }
4124 }
4125 btv->irq_total++;
4126 if (handled)
4127 btv->irq_me++;
4128 return IRQ_RETVAL(handled);
4129}
4130
4131
4132/* ----------------------------------------------------------------------- */
4133/* initialitation */
4134
4135static struct video_device *vdev_init(struct bttv *btv,
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03004136 const struct video_device *template,
Hans Verkuil0ea6bc82008-07-26 08:26:43 -03004137 const char *type_name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004138{
4139 struct video_device *vfd;
4140
4141 vfd = video_device_alloc();
4142 if (NULL == vfd)
4143 return NULL;
4144 *vfd = *template;
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004145 vfd->v4l2_dev = &btv->c.v4l2_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004146 vfd->release = video_device_release;
Mauro Carvalho Chehab1d0a4362008-06-23 12:31:29 -03004147 vfd->debug = bttv_debug;
Trent Piepho4b10d3b2009-01-28 21:32:59 -03004148 video_set_drvdata(vfd, btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004149 snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
4150 btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "",
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03004151 type_name, bttv_tvcards[btv->c.type].name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004152 return vfd;
4153}
4154
4155static void bttv_unregister_video(struct bttv *btv)
4156{
4157 if (btv->video_dev) {
Laurent Pinchartf0813b42009-11-27 13:57:30 -03004158 if (video_is_registered(btv->video_dev))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004159 video_unregister_device(btv->video_dev);
4160 else
4161 video_device_release(btv->video_dev);
4162 btv->video_dev = NULL;
4163 }
4164 if (btv->vbi_dev) {
Laurent Pinchartf0813b42009-11-27 13:57:30 -03004165 if (video_is_registered(btv->vbi_dev))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004166 video_unregister_device(btv->vbi_dev);
4167 else
4168 video_device_release(btv->vbi_dev);
4169 btv->vbi_dev = NULL;
4170 }
4171 if (btv->radio_dev) {
Laurent Pinchartf0813b42009-11-27 13:57:30 -03004172 if (video_is_registered(btv->radio_dev))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173 video_unregister_device(btv->radio_dev);
4174 else
4175 video_device_release(btv->radio_dev);
4176 btv->radio_dev = NULL;
4177 }
4178}
4179
4180/* register video4linux devices */
4181static int __devinit bttv_register_video(struct bttv *btv)
4182{
Hans Verkuil0ea6bc82008-07-26 08:26:43 -03004183 if (no_overlay > 0)
Joe Perches8af443e2011-08-21 19:56:48 -03004184 pr_notice("Overlay support disabled\n");
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07004185
Linus Torvalds1da177e2005-04-16 15:20:36 -07004186 /* video */
Hans Verkuil0ea6bc82008-07-26 08:26:43 -03004187 btv->video_dev = vdev_init(btv, &bttv_video_template, "video");
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03004188
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004189 if (NULL == btv->video_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004190 goto err;
Jean Delvare176c2f32008-09-07 12:49:59 -03004191 if (video_register_device(btv->video_dev, VFL_TYPE_GRABBER,
4192 video_nr[btv->c.nr]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004193 goto err;
Joe Perches8af443e2011-08-21 19:56:48 -03004194 pr_info("%d: registered device %s\n",
4195 btv->c.nr, video_device_node_name(btv->video_dev));
Hans Verkuil22a04f12008-07-20 06:35:02 -03004196 if (device_create_file(&btv->video_dev->dev,
Kay Sievers54bd5b62007-10-08 16:26:13 -03004197 &dev_attr_card)<0) {
Joe Perches8af443e2011-08-21 19:56:48 -03004198 pr_err("%d: device_create_file 'card' failed\n", btv->c.nr);
Trent Piephod94fc9a2006-07-29 17:18:06 -03004199 goto err;
4200 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004201
4202 /* vbi */
Hans Verkuil0ea6bc82008-07-26 08:26:43 -03004203 btv->vbi_dev = vdev_init(btv, &bttv_video_template, "vbi");
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03004204
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004205 if (NULL == btv->vbi_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004206 goto err;
Jean Delvare176c2f32008-09-07 12:49:59 -03004207 if (video_register_device(btv->vbi_dev, VFL_TYPE_VBI,
4208 vbi_nr[btv->c.nr]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004209 goto err;
Joe Perches8af443e2011-08-21 19:56:48 -03004210 pr_info("%d: registered device %s\n",
4211 btv->c.nr, video_device_node_name(btv->vbi_dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004212
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004213 if (!btv->has_radio)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004214 return 0;
4215 /* radio */
Hans Verkuil0ea6bc82008-07-26 08:26:43 -03004216 btv->radio_dev = vdev_init(btv, &radio_template, "radio");
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004217 if (NULL == btv->radio_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004218 goto err;
Jean Delvare176c2f32008-09-07 12:49:59 -03004219 if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,
4220 radio_nr[btv->c.nr]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004221 goto err;
Joe Perches8af443e2011-08-21 19:56:48 -03004222 pr_info("%d: registered device %s\n",
4223 btv->c.nr, video_device_node_name(btv->radio_dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004224
4225 /* all done */
4226 return 0;
4227
4228 err:
4229 bttv_unregister_video(btv);
4230 return -1;
4231}
4232
4233
4234/* on OpenFirmware machines (PowerMac at least), PCI memory cycle */
4235/* response on cards with no firmware is not enabled by OF */
4236static void pci_set_command(struct pci_dev *dev)
4237{
4238#if defined(__powerpc__)
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004239 unsigned int cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004240
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004241 pci_read_config_dword(dev, PCI_COMMAND, &cmd);
4242 cmd = (cmd | PCI_COMMAND_MEMORY );
4243 pci_write_config_dword(dev, PCI_COMMAND, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004244#endif
4245}
4246
4247static int __devinit bttv_probe(struct pci_dev *dev,
4248 const struct pci_device_id *pci_id)
4249{
4250 int result;
4251 unsigned char lat;
4252 struct bttv *btv;
4253
4254 if (bttv_num == BTTV_MAX)
4255 return -ENOMEM;
Joe Perches8af443e2011-08-21 19:56:48 -03004256 pr_info("Bt8xx card found (%d)\n", bttv_num);
Trent Piepho4b10d3b2009-01-28 21:32:59 -03004257 bttvs[bttv_num] = btv = kzalloc(sizeof(*btv), GFP_KERNEL);
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004258 if (btv == NULL) {
Joe Perches8af443e2011-08-21 19:56:48 -03004259 pr_err("out of memory\n");
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004260 return -ENOMEM;
4261 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004262 btv->c.nr = bttv_num;
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004263 snprintf(btv->c.v4l2_dev.name, sizeof(btv->c.v4l2_dev.name),
4264 "bttv%d", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004265
4266 /* initialize structs / fill in defaults */
Ingo Molnarbd5f0ac2006-01-13 14:10:24 -02004267 mutex_init(&btv->lock);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004268 spin_lock_init(&btv->s_lock);
4269 spin_lock_init(&btv->gpio_lock);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004270 init_waitqueue_head(&btv->i2c_queue);
4271 INIT_LIST_HEAD(&btv->c.subs);
4272 INIT_LIST_HEAD(&btv->capture);
4273 INIT_LIST_HEAD(&btv->vcapture);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004274 v4l2_prio_init(&btv->prio);
4275
4276 init_timer(&btv->timeout);
4277 btv->timeout.function = bttv_irq_timeout;
4278 btv->timeout.data = (unsigned long)btv;
4279
Michael Krufky7c08fb02005-11-08 21:36:21 -08004280 btv->i2c_rc = -1;
4281 btv->tuner_type = UNSET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004282 btv->new_input = UNSET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004283 btv->has_radio=radio[btv->c.nr];
4284
4285 /* pci stuff (init, get irq/mmio, ... */
4286 btv->c.pci = dev;
Michael Krufky7c08fb02005-11-08 21:36:21 -08004287 btv->id = dev->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004288 if (pci_enable_device(dev)) {
Joe Perches8af443e2011-08-21 19:56:48 -03004289 pr_warn("%d: Can't enable device\n", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004290 return -EIO;
4291 }
Yang Hongyang284901a2009-04-06 19:01:15 -07004292 if (pci_set_dma_mask(dev, DMA_BIT_MASK(32))) {
Joe Perches8af443e2011-08-21 19:56:48 -03004293 pr_warn("%d: No suitable DMA available\n", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004294 return -EIO;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004295 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004296 if (!request_mem_region(pci_resource_start(dev,0),
4297 pci_resource_len(dev,0),
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004298 btv->c.v4l2_dev.name)) {
Joe Perches8af443e2011-08-21 19:56:48 -03004299 pr_warn("%d: can't request iomem (0x%llx)\n",
4300 btv->c.nr,
4301 (unsigned long long)pci_resource_start(dev, 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004302 return -EBUSY;
4303 }
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004304 pci_set_master(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305 pci_set_command(dev);
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004306
4307 result = v4l2_device_register(&dev->dev, &btv->c.v4l2_dev);
4308 if (result < 0) {
Joe Perches8af443e2011-08-21 19:56:48 -03004309 pr_warn("%d: v4l2_device_register() failed\n", btv->c.nr);
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004310 goto fail0;
4311 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004312
Bjørn Morkabd34d82011-03-21 11:35:56 -03004313 btv->revision = dev->revision;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004314 pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
Joe Perches8af443e2011-08-21 19:56:48 -03004315 pr_info("%d: Bt%d (rev %d) at %s, irq: %d, latency: %d, mmio: 0x%llx\n",
4316 bttv_num, btv->id, btv->revision, pci_name(dev),
4317 btv->c.pci->irq, lat,
4318 (unsigned long long)pci_resource_start(dev, 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004319 schedule();
4320
Akinobu Mita5f1693f2006-12-20 10:08:56 -03004321 btv->bt848_mmio = ioremap(pci_resource_start(dev, 0), 0x1000);
4322 if (NULL == btv->bt848_mmio) {
Joe Perches8af443e2011-08-21 19:56:48 -03004323 pr_err("%d: ioremap() failed\n", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004324 result = -EIO;
4325 goto fail1;
4326 }
4327
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004328 /* identify card */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004329 bttv_idcard(btv);
4330
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004331 /* disable irqs, register irq handler */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004332 btwrite(0, BT848_INT_MASK);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004333 result = request_irq(btv->c.pci->irq, bttv_irq,
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004334 IRQF_SHARED | IRQF_DISABLED, btv->c.v4l2_dev.name, (void *)btv);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004335 if (result < 0) {
Joe Perches8af443e2011-08-21 19:56:48 -03004336 pr_err("%d: can't get IRQ %d\n",
4337 bttv_num, btv->c.pci->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004338 goto fail1;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004339 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004340
4341 if (0 != bttv_handle_chipset(btv)) {
4342 result = -EIO;
4343 goto fail2;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004344 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004345
4346 /* init options from insmod args */
4347 btv->opt_combfilter = combfilter;
4348 btv->opt_lumafilter = lumafilter;
4349 btv->opt_automute = automute;
4350 btv->opt_chroma_agc = chroma_agc;
4351 btv->opt_adc_crush = adc_crush;
4352 btv->opt_vcr_hack = vcr_hack;
4353 btv->opt_whitecrush_upper = whitecrush_upper;
4354 btv->opt_whitecrush_lower = whitecrush_lower;
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -07004355 btv->opt_uv_ratio = uv_ratio;
4356 btv->opt_full_luma_range = full_luma_range;
4357 btv->opt_coring = coring;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004358
4359 /* fill struct bttv with some useful defaults */
4360 btv->init.btv = btv;
4361 btv->init.ov.w.width = 320;
4362 btv->init.ov.w.height = 240;
Mauro Carvalho Chehabc96dd072007-10-26 16:51:47 -03004363 btv->init.fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004364 btv->init.width = 320;
4365 btv->init.height = 240;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004366 btv->input = 0;
4367
4368 /* initialize hardware */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004369 if (bttv_gpio)
4370 bttv_gpio_tracking(btv,"pre-init");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004371
4372 bttv_risc_init_main(btv);
4373 init_bt848(btv);
4374
4375 /* gpio */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004376 btwrite(0x00, BT848_GPIO_REG_INP);
4377 btwrite(0x00, BT848_GPIO_OUT_EN);
4378 if (bttv_verbose)
4379 bttv_gpio_tracking(btv,"init");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004380
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004381 /* needs to be done before i2c is registered */
4382 bttv_init_card1(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004383
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004384 /* register i2c + gpio */
4385 init_bttv_i2c(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004386
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004387 /* some card-specific stuff (needs working i2c) */
4388 bttv_init_card2(btv);
Hans Verkuil2c905772009-07-20 08:14:17 -03004389 bttv_init_tuner(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004390 init_irqreg(btv);
4391
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004392 /* register video4linux + input */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004393 if (!bttv_tvcards[btv->c.type].no_video) {
4394 bttv_register_video(btv);
4395 bt848_bright(btv,32768);
Alan McIvor961e6682012-04-01 21:11:08 -03004396 bt848_contrast(btv, 27648);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004397 bt848_hue(btv,32768);
4398 bt848_sat(btv,32768);
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03004399 audio_mute(btv, 1);
Trent Piepho333408f2007-07-03 15:08:10 -03004400 set_input(btv, 0, btv->tvnorm);
Michael Schimeke5bd0262007-01-18 16:17:39 -03004401 bttv_crop_reset(&btv->crop[0], btv->tvnorm);
4402 btv->crop[1] = btv->crop[0]; /* current = default */
4403 disclaim_vbi_lines(btv);
4404 disclaim_video_lines(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004405 }
4406
Jarod Wilsonf992a492007-03-24 15:23:50 -03004407 /* add subdevices and autoload dvb-bt8xx if needed */
4408 if (bttv_tvcards[btv->c.type].has_dvb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004409 bttv_sub_add_device(&btv->c, "dvb");
Jarod Wilsonf992a492007-03-24 15:23:50 -03004410 request_modules(btv);
4411 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004412
Jean Delvared90a4ae2010-02-16 14:22:37 -03004413 if (!disable_ir) {
4414 init_bttv_i2c_ir(btv);
4415 bttv_input_init(btv);
4416 }
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02004417
Linus Torvalds1da177e2005-04-16 15:20:36 -07004418 /* everything is fine */
4419 bttv_num++;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004420 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004421
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004422fail2:
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004423 free_irq(btv->c.pci->irq,btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004424
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004425fail1:
4426 v4l2_device_unregister(&btv->c.v4l2_dev);
4427
4428fail0:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004429 if (btv->bt848_mmio)
4430 iounmap(btv->bt848_mmio);
4431 release_mem_region(pci_resource_start(btv->c.pci,0),
4432 pci_resource_len(btv->c.pci,0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004433 return result;
4434}
4435
4436static void __devexit bttv_remove(struct pci_dev *pci_dev)
4437{
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004438 struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
4439 struct bttv *btv = to_bttv(v4l2_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004440
4441 if (bttv_verbose)
Joe Perches8af443e2011-08-21 19:56:48 -03004442 pr_info("%d: unloading\n", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004443
Tejun Heo707bcf32010-12-24 16:14:20 +01004444 if (bttv_tvcards[btv->c.type].has_dvb)
4445 flush_request_modules(btv);
4446
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004447 /* shutdown everything (DMA+IRQs) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004448 btand(~15, BT848_GPIO_DMA_CTL);
4449 btwrite(0, BT848_INT_MASK);
4450 btwrite(~0x0, BT848_INT_STAT);
4451 btwrite(0x0, BT848_GPIO_OUT_EN);
4452 if (bttv_gpio)
4453 bttv_gpio_tracking(btv,"cleanup");
4454
4455 /* tell gpio modules we are leaving ... */
4456 btv->shutdown=1;
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02004457 bttv_input_fini(btv);
Christopher Pascoe889aee82006-01-09 15:25:28 -02004458 bttv_sub_del_devices(&btv->c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004459
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004460 /* unregister i2c_bus + input */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004461 fini_bttv_i2c(btv);
4462
4463 /* unregister video4linux */
4464 bttv_unregister_video(btv);
4465
4466 /* free allocated memory */
4467 btcx_riscmem_free(btv->c.pci,&btv->main);
4468
4469 /* free ressources */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004470 free_irq(btv->c.pci->irq,btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004471 iounmap(btv->bt848_mmio);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004472 release_mem_region(pci_resource_start(btv->c.pci,0),
4473 pci_resource_len(btv->c.pci,0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004474
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004475 v4l2_device_unregister(&btv->c.v4l2_dev);
Trent Piepho4b10d3b2009-01-28 21:32:59 -03004476 bttvs[btv->c.nr] = NULL;
4477 kfree(btv);
4478
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004479 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004480}
4481
Alexey Dobriyan17bc98a2006-08-12 22:01:27 -03004482#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -07004483static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state)
4484{
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004485 struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
4486 struct bttv *btv = to_bttv(v4l2_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004487 struct bttv_buffer_set idle;
4488 unsigned long flags;
4489
Joe Perches8af443e2011-08-21 19:56:48 -03004490 dprintk("%d: suspend %d\n", btv->c.nr, state.event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004491
4492 /* stop dma + irqs */
4493 spin_lock_irqsave(&btv->s_lock,flags);
4494 memset(&idle, 0, sizeof(idle));
4495 btv->state.video = btv->curr;
4496 btv->state.vbi = btv->cvbi;
4497 btv->state.loop_irq = btv->loop_irq;
4498 btv->curr = idle;
4499 btv->loop_irq = 0;
4500 bttv_buffer_activate_video(btv, &idle);
4501 bttv_buffer_activate_vbi(btv, NULL);
4502 bttv_set_dma(btv, 0);
4503 btwrite(0, BT848_INT_MASK);
4504 spin_unlock_irqrestore(&btv->s_lock,flags);
4505
4506 /* save bt878 state */
4507 btv->state.gpio_enable = btread(BT848_GPIO_OUT_EN);
4508 btv->state.gpio_data = gpio_read();
4509
4510 /* save pci state */
4511 pci_save_state(pci_dev);
4512 if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
4513 pci_disable_device(pci_dev);
4514 btv->state.disabled = 1;
4515 }
4516 return 0;
4517}
4518
4519static int bttv_resume(struct pci_dev *pci_dev)
4520{
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004521 struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
4522 struct bttv *btv = to_bttv(v4l2_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004523 unsigned long flags;
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004524 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004525
Joe Perches8af443e2011-08-21 19:56:48 -03004526 dprintk("%d: resume\n", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004527
4528 /* restore pci state */
4529 if (btv->state.disabled) {
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004530 err=pci_enable_device(pci_dev);
4531 if (err) {
Joe Perches8af443e2011-08-21 19:56:48 -03004532 pr_warn("%d: Can't enable device\n", btv->c.nr);
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004533 return err;
4534 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004535 btv->state.disabled = 0;
4536 }
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004537 err=pci_set_power_state(pci_dev, PCI_D0);
4538 if (err) {
4539 pci_disable_device(pci_dev);
Joe Perches8af443e2011-08-21 19:56:48 -03004540 pr_warn("%d: Can't enable device\n", btv->c.nr);
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004541 btv->state.disabled = 1;
4542 return err;
4543 }
4544
Linus Torvalds1da177e2005-04-16 15:20:36 -07004545 pci_restore_state(pci_dev);
4546
4547 /* restore bt878 state */
4548 bttv_reinit_bt848(btv);
4549 gpio_inout(0xffffff, btv->state.gpio_enable);
4550 gpio_write(btv->state.gpio_data);
4551
4552 /* restart dma */
4553 spin_lock_irqsave(&btv->s_lock,flags);
4554 btv->curr = btv->state.video;
4555 btv->cvbi = btv->state.vbi;
4556 btv->loop_irq = btv->state.loop_irq;
4557 bttv_buffer_activate_video(btv, &btv->curr);
4558 bttv_buffer_activate_vbi(btv, btv->cvbi);
4559 bttv_set_dma(btv, 0);
4560 spin_unlock_irqrestore(&btv->s_lock,flags);
4561 return 0;
4562}
Alexey Dobriyan17bc98a2006-08-12 22:01:27 -03004563#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07004564
4565static struct pci_device_id bttv_pci_tbl[] = {
Joe Perches76e97412009-07-05 15:59:21 -03004566 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT848), 0},
4567 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT849), 0},
4568 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT878), 0},
4569 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT879), 0},
Peter De Schrijverc540d9f2011-11-06 10:47:58 -03004570 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_FUSION879), 0},
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004571 {0,}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004572};
4573
4574MODULE_DEVICE_TABLE(pci, bttv_pci_tbl);
4575
4576static struct pci_driver bttv_pci_driver = {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004577 .name = "bttv",
4578 .id_table = bttv_pci_tbl,
4579 .probe = bttv_probe,
4580 .remove = __devexit_p(bttv_remove),
Alexey Dobriyan17bc98a2006-08-12 22:01:27 -03004581#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -07004582 .suspend = bttv_suspend,
4583 .resume = bttv_resume,
Alexey Dobriyan17bc98a2006-08-12 22:01:27 -03004584#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07004585};
4586
Adrian Bunk7d44e892007-12-11 19:23:43 -03004587static int __init bttv_init_module(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004588{
Randy Dunlapc526e222006-07-15 09:08:26 -03004589 int ret;
4590
Linus Torvalds1da177e2005-04-16 15:20:36 -07004591 bttv_num = 0;
4592
Joe Perches8af443e2011-08-21 19:56:48 -03004593 pr_info("driver version %s loaded\n", BTTV_VERSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004594 if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME)
4595 gbuffers = 2;
Filipe Rossetf41b6962009-05-28 11:11:53 -03004596 if (gbufsize > BTTV_MAX_FBUF)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004597 gbufsize = BTTV_MAX_FBUF;
4598 gbufsize = (gbufsize + PAGE_SIZE - 1) & PAGE_MASK;
4599 if (bttv_verbose)
Joe Perches8af443e2011-08-21 19:56:48 -03004600 pr_info("using %d buffers with %dk (%d pages) each for capture\n",
4601 gbuffers, gbufsize >> 10, gbufsize >> PAGE_SHIFT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004602
4603 bttv_check_chipset();
4604
Randy Dunlapc526e222006-07-15 09:08:26 -03004605 ret = bus_register(&bttv_sub_bus_type);
4606 if (ret < 0) {
Joe Perches8af443e2011-08-21 19:56:48 -03004607 pr_warn("bus_register error: %d\n", ret);
Randy Dunlapc526e222006-07-15 09:08:26 -03004608 return ret;
4609 }
Akinobu Mita9e7e85e2007-12-17 14:26:29 -03004610 ret = pci_register_driver(&bttv_pci_driver);
4611 if (ret < 0)
4612 bus_unregister(&bttv_sub_bus_type);
4613
4614 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004615}
4616
Adrian Bunk7d44e892007-12-11 19:23:43 -03004617static void __exit bttv_cleanup_module(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004618{
4619 pci_unregister_driver(&bttv_pci_driver);
4620 bus_unregister(&bttv_sub_bus_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004621}
4622
4623module_init(bttv_init_module);
4624module_exit(bttv_cleanup_module);
4625
4626/*
4627 * Local variables:
4628 * c-basic-offset: 8
4629 * End:
4630 */