blob: 849cd170b821d7fd4646a33b8cd05c517cf9e28a [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002
3 bttv - Bt848 frame grabber driver
4
5 Copyright (C) 1996,97,98 Ralph Metzler <rjkm@thp.uni-koeln.de>
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08006 & Marcus Metzler <mocm@thp.uni-koeln.de>
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 (c) 1999-2002 Gerd Knorr <kraxel@bytesex.org>
8
9 some v4l2 code lines are taken from Justin's bttv2 driver which is
10 (c) 2000 Justin Schoeman <justin@suntiger.ee.up.ac.za>
11
Nickolay V. Shmyreve84619b2007-10-26 11:01:08 -030012 V4L1 removal from:
13 (c) 2005-2006 Nickolay V. Shmyrev <nshmyrev@yandex.ru>
14
Mauro Carvalho Chehabc96dd072007-10-26 16:51:47 -030015 Fixes to be fully V4L2 compliant by
16 (c) 2006 Mauro Carvalho Chehab <mchehab@infradead.org>
17
Michael Schimeke5bd0262007-01-18 16:17:39 -030018 Cropping and overscan support
19 Copyright (C) 2005, 2006 Michael H. Schimek <mschimek@gmx.at>
20 Sponsored by OPQ Systems AB
21
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 This program is free software; you can redistribute it and/or modify
23 it under the terms of the GNU General Public License as published by
24 the Free Software Foundation; either version 2 of the License, or
25 (at your option) any later version.
26
27 This program is distributed in the hope that it will be useful,
28 but WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 GNU General Public License for more details.
31
32 You should have received a copy of the GNU General Public License
33 along with this program; if not, write to the Free Software
34 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35*/
36
37#include <linux/init.h>
38#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070039#include <linux/delay.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090040#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <linux/errno.h>
42#include <linux/fs.h>
43#include <linux/kernel.h>
44#include <linux/sched.h>
45#include <linux/interrupt.h>
46#include <linux/kdev_t.h>
Mauro Carvalho Chehabb5b8ab82006-01-09 15:25:20 -020047#include "bttvp.h"
Michael Krufky5e453dc2006-01-09 15:32:31 -020048#include <media/v4l2-common.h>
Hans Verkuil35ea11f2008-07-20 08:12:02 -030049#include <media/v4l2-ioctl.h>
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -030050#include <media/tvaudio.h>
Hans Verkuil2474ed42006-03-19 12:35:57 -030051#include <media/msp3400.h>
Mauro Carvalho Chehabb5b8ab82006-01-09 15:25:20 -020052
Mauro Carvalho Chehabfa9846a2005-07-12 13:58:42 -070053#include <linux/dma-mapping.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070054
55#include <asm/io.h>
56#include <asm/byteorder.h>
57
Hans Verkuilb9218f22010-12-27 12:22:46 -030058#include <media/saa6588.h>
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -070059
60
Linus Torvalds1da177e2005-04-16 15:20:36 -070061unsigned int bttv_num; /* number of Bt848s in use */
Trent Piepho4b10d3b2009-01-28 21:32:59 -030062struct bttv *bttvs[BTTV_MAX];
Linus Torvalds1da177e2005-04-16 15:20:36 -070063
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020064unsigned int bttv_debug;
Linus Torvalds1da177e2005-04-16 15:20:36 -070065unsigned int bttv_verbose = 1;
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020066unsigned int bttv_gpio;
Linus Torvalds1da177e2005-04-16 15:20:36 -070067
68/* config variables */
69#ifdef __BIG_ENDIAN
70static unsigned int bigendian=1;
71#else
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020072static unsigned int bigendian;
Linus Torvalds1da177e2005-04-16 15:20:36 -070073#endif
74static unsigned int radio[BTTV_MAX];
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020075static unsigned int irq_debug;
Linus Torvalds1da177e2005-04-16 15:20:36 -070076static unsigned int gbuffers = 8;
77static unsigned int gbufsize = 0x208000;
Michael Schimeke5bd0262007-01-18 16:17:39 -030078static unsigned int reset_crop = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -070079
Jean Delvare176c2f32008-09-07 12:49:59 -030080static int video_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
81static int radio_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
82static int vbi_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020083static int debug_latency;
Jean Delvared90a4ae2010-02-16 14:22:37 -030084static int disable_ir;
Linus Torvalds1da177e2005-04-16 15:20:36 -070085
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020086static unsigned int fdsr;
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
88/* options */
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020089static unsigned int combfilter;
90static unsigned int lumafilter;
Linus Torvalds1da177e2005-04-16 15:20:36 -070091static unsigned int automute = 1;
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020092static unsigned int chroma_agc;
Linus Torvalds1da177e2005-04-16 15:20:36 -070093static unsigned int adc_crush = 1;
94static unsigned int whitecrush_upper = 0xCF;
95static unsigned int whitecrush_lower = 0x7F;
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020096static unsigned int vcr_hack;
97static unsigned int irq_iswitch;
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -070098static unsigned int uv_ratio = 50;
Mauro Carvalho Chehaba5ed4252006-01-13 14:10:19 -020099static unsigned int full_luma_range;
100static unsigned int coring;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101
102/* API features (turn on/off stuff for testing) */
103static unsigned int v4l2 = 1;
104
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105/* insmod args */
106module_param(bttv_verbose, int, 0644);
107module_param(bttv_gpio, int, 0644);
108module_param(bttv_debug, int, 0644);
109module_param(irq_debug, int, 0644);
110module_param(debug_latency, int, 0644);
Jean Delvared90a4ae2010-02-16 14:22:37 -0300111module_param(disable_ir, int, 0444);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112
113module_param(fdsr, int, 0444);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114module_param(gbuffers, int, 0444);
115module_param(gbufsize, int, 0444);
Michael Schimeke5bd0262007-01-18 16:17:39 -0300116module_param(reset_crop, int, 0444);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117
118module_param(v4l2, int, 0644);
119module_param(bigendian, int, 0644);
120module_param(irq_iswitch, int, 0644);
121module_param(combfilter, int, 0444);
122module_param(lumafilter, int, 0444);
123module_param(automute, int, 0444);
124module_param(chroma_agc, int, 0444);
125module_param(adc_crush, int, 0444);
126module_param(whitecrush_upper, int, 0444);
127module_param(whitecrush_lower, int, 0444);
128module_param(vcr_hack, int, 0444);
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700129module_param(uv_ratio, int, 0444);
130module_param(full_luma_range, int, 0444);
131module_param(coring, int, 0444);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132
Jean Delvare176c2f32008-09-07 12:49:59 -0300133module_param_array(radio, int, NULL, 0444);
134module_param_array(video_nr, int, NULL, 0444);
135module_param_array(radio_nr, int, NULL, 0444);
136module_param_array(vbi_nr, int, NULL, 0444);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137
138MODULE_PARM_DESC(radio,"The TV card supports radio, default is 0 (no)");
139MODULE_PARM_DESC(bigendian,"byte order of the framebuffer, default is native endian");
140MODULE_PARM_DESC(bttv_verbose,"verbose startup messages, default is 1 (yes)");
141MODULE_PARM_DESC(bttv_gpio,"log gpio changes, default is 0 (no)");
142MODULE_PARM_DESC(bttv_debug,"debug messages, default is 0 (no)");
143MODULE_PARM_DESC(irq_debug,"irq handler debug messages, default is 0 (no)");
Jean Delvared90a4ae2010-02-16 14:22:37 -0300144MODULE_PARM_DESC(disable_ir, "disable infrared remote support");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145MODULE_PARM_DESC(gbuffers,"number of capture buffers. range 2-32, default 8");
146MODULE_PARM_DESC(gbufsize,"size of the capture buffers, default is 0x208000");
Michael Schimeke5bd0262007-01-18 16:17:39 -0300147MODULE_PARM_DESC(reset_crop,"reset cropping parameters at open(), default "
148 "is 1 (yes) for compatibility with older applications");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149MODULE_PARM_DESC(automute,"mute audio on bad/missing video signal, default is 1 (yes)");
150MODULE_PARM_DESC(chroma_agc,"enables the AGC of chroma signal, default is 0 (no)");
151MODULE_PARM_DESC(adc_crush,"enables the luminance ADC crush, default is 1 (yes)");
152MODULE_PARM_DESC(whitecrush_upper,"sets the white crush upper value, default is 207");
153MODULE_PARM_DESC(whitecrush_lower,"sets the white crush lower value, default is 127");
154MODULE_PARM_DESC(vcr_hack,"enables the VCR hack (improves synch on poor VCR tapes), default is 0 (no)");
155MODULE_PARM_DESC(irq_iswitch,"switch inputs in irq handler");
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700156MODULE_PARM_DESC(uv_ratio,"ratio between u and v gains, default is 50");
157MODULE_PARM_DESC(full_luma_range,"use the full luma range, default is 0 (no)");
158MODULE_PARM_DESC(coring,"set the luma coring level, default is 0 (no)");
Jean Delvare176c2f32008-09-07 12:49:59 -0300159MODULE_PARM_DESC(video_nr, "video device numbers");
160MODULE_PARM_DESC(vbi_nr, "vbi device numbers");
161MODULE_PARM_DESC(radio_nr, "radio device numbers");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162
163MODULE_DESCRIPTION("bttv - v4l/v4l2 driver module for bt848/878 based cards");
164MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr");
165MODULE_LICENSE("GPL");
166
167/* ----------------------------------------------------------------------- */
168/* sysfs */
169
Kay Sievers54bd5b62007-10-08 16:26:13 -0300170static ssize_t show_card(struct device *cd,
171 struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172{
Hans Verkuil22a04f12008-07-20 06:35:02 -0300173 struct video_device *vfd = container_of(cd, struct video_device, dev);
Hans Verkuil74fc7bd2009-03-14 12:36:54 -0300174 struct bttv *btv = video_get_drvdata(vfd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 return sprintf(buf, "%d\n", btv ? btv->c.type : UNSET);
176}
Kay Sievers54bd5b62007-10-08 16:26:13 -0300177static DEVICE_ATTR(card, S_IRUGO, show_card, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178
179/* ----------------------------------------------------------------------- */
Jarod Wilsonf992a492007-03-24 15:23:50 -0300180/* dvb auto-load setup */
181#if defined(CONFIG_MODULES) && defined(MODULE)
182static void request_module_async(struct work_struct *work)
183{
184 request_module("dvb-bt8xx");
185}
186
187static void request_modules(struct bttv *dev)
188{
189 INIT_WORK(&dev->request_module_wk, request_module_async);
190 schedule_work(&dev->request_module_wk);
191}
192#else
193#define request_modules(dev)
194#endif /* CONFIG_MODULES */
195
196
197/* ----------------------------------------------------------------------- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198/* static data */
199
200/* special timing tables from conexant... */
201static u8 SRAM_Table[][60] =
202{
203 /* PAL digital input over GPIO[7:0] */
204 {
205 45, // 45 bytes following
206 0x36,0x11,0x01,0x00,0x90,0x02,0x05,0x10,0x04,0x16,
207 0x12,0x05,0x11,0x00,0x04,0x12,0xC0,0x00,0x31,0x00,
208 0x06,0x51,0x08,0x03,0x89,0x08,0x07,0xC0,0x44,0x00,
209 0x81,0x01,0x01,0xA9,0x0D,0x02,0x02,0x50,0x03,0x37,
210 0x37,0x00,0xAF,0x21,0x00
211 },
212 /* NTSC digital input over GPIO[7:0] */
213 {
214 51, // 51 bytes following
215 0x0C,0xC0,0x00,0x00,0x90,0x02,0x03,0x10,0x03,0x06,
216 0x10,0x04,0x12,0x12,0x05,0x02,0x13,0x04,0x19,0x00,
217 0x04,0x39,0x00,0x06,0x59,0x08,0x03,0x83,0x08,0x07,
218 0x03,0x50,0x00,0xC0,0x40,0x00,0x86,0x01,0x01,0xA6,
219 0x0D,0x02,0x03,0x11,0x01,0x05,0x37,0x00,0xAC,0x21,
220 0x00,
221 },
222 // TGB_NTSC392 // quartzsight
223 // This table has been modified to be used for Fusion Rev D
224 {
225 0x2A, // size of table = 42
226 0x06, 0x08, 0x04, 0x0a, 0xc0, 0x00, 0x18, 0x08, 0x03, 0x24,
227 0x08, 0x07, 0x02, 0x90, 0x02, 0x08, 0x10, 0x04, 0x0c, 0x10,
228 0x05, 0x2c, 0x11, 0x04, 0x55, 0x48, 0x00, 0x05, 0x50, 0x00,
229 0xbf, 0x0c, 0x02, 0x2f, 0x3d, 0x00, 0x2f, 0x3f, 0x00, 0xc3,
230 0x20, 0x00
231 }
232};
233
Michael Schimeke5bd0262007-01-18 16:17:39 -0300234/* minhdelayx1 first video pixel we can capture on a line and
235 hdelayx1 start of active video, both relative to rising edge of
236 /HRESET pulse (0H) in 1 / fCLKx1.
237 swidth width of active video and
238 totalwidth total line width, both in 1 / fCLKx1.
239 sqwidth total line width in square pixels.
240 vdelay start of active video in 2 * field lines relative to
241 trailing edge of /VRESET pulse (VDELAY register).
242 sheight height of active video in 2 * field lines.
243 videostart0 ITU-R frame line number of the line corresponding
244 to vdelay in the first field. */
245#define CROPCAP(minhdelayx1, hdelayx1, swidth, totalwidth, sqwidth, \
246 vdelay, sheight, videostart0) \
247 .cropcap.bounds.left = minhdelayx1, \
248 /* * 2 because vertically we count field lines times two, */ \
249 /* e.g. 23 * 2 to 23 * 2 + 576 in PAL-BGHI defrect. */ \
250 .cropcap.bounds.top = (videostart0) * 2 - (vdelay) + MIN_VDELAY, \
251 /* 4 is a safety margin at the end of the line. */ \
252 .cropcap.bounds.width = (totalwidth) - (minhdelayx1) - 4, \
253 .cropcap.bounds.height = (sheight) + (vdelay) - MIN_VDELAY, \
254 .cropcap.defrect.left = hdelayx1, \
255 .cropcap.defrect.top = (videostart0) * 2, \
256 .cropcap.defrect.width = swidth, \
257 .cropcap.defrect.height = sheight, \
258 .cropcap.pixelaspect.numerator = totalwidth, \
259 .cropcap.pixelaspect.denominator = sqwidth,
260
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261const struct bttv_tvnorm bttv_tvnorms[] = {
262 /* PAL-BDGHI */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800263 /* max. active video is actually 922, but 924 is divisible by 4 and 3! */
264 /* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265 {
266 .v4l2_id = V4L2_STD_PAL,
267 .name = "PAL",
268 .Fsc = 35468950,
269 .swidth = 924,
270 .sheight = 576,
271 .totalwidth = 1135,
272 .adelay = 0x7f,
273 .bdelay = 0x72,
274 .iform = (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
275 .scaledtwidth = 1135,
276 .hdelayx1 = 186,
277 .hactivex1 = 924,
278 .vdelay = 0x20,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300279 .vbipack = 255, /* min (2048 / 4, 0x1ff) & 0xff */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 .sram = 0,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200281 /* ITU-R frame line number of the first VBI line
Michael Schimeke5bd0262007-01-18 16:17:39 -0300282 we can capture, of the first and second field.
283 The last line is determined by cropcap.bounds. */
284 .vbistart = { 7, 320 },
285 CROPCAP(/* minhdelayx1 */ 68,
286 /* hdelayx1 */ 186,
287 /* Should be (768 * 1135 + 944 / 2) / 944.
288 cropcap.defrect is used for image width
289 checks, so we keep the old value 924. */
290 /* swidth */ 924,
291 /* totalwidth */ 1135,
292 /* sqwidth */ 944,
293 /* vdelay */ 0x20,
294 /* sheight */ 576,
295 /* videostart0 */ 23)
296 /* bt878 (and bt848?) can capture another
297 line below active video. */
298 .cropcap.bounds.height = (576 + 2) + 0x20 - 2,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 },{
Hans Verkuild97a11e2006-02-07 06:48:40 -0200300 .v4l2_id = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301 .name = "NTSC",
302 .Fsc = 28636363,
303 .swidth = 768,
304 .sheight = 480,
305 .totalwidth = 910,
306 .adelay = 0x68,
307 .bdelay = 0x5d,
308 .iform = (BT848_IFORM_NTSC|BT848_IFORM_XT0),
309 .scaledtwidth = 910,
310 .hdelayx1 = 128,
311 .hactivex1 = 910,
312 .vdelay = 0x1a,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300313 .vbipack = 144, /* min (1600 / 4, 0x1ff) & 0xff */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314 .sram = 1,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200315 .vbistart = { 10, 273 },
Michael Schimeke5bd0262007-01-18 16:17:39 -0300316 CROPCAP(/* minhdelayx1 */ 68,
317 /* hdelayx1 */ 128,
318 /* Should be (640 * 910 + 780 / 2) / 780? */
319 /* swidth */ 768,
320 /* totalwidth */ 910,
321 /* sqwidth */ 780,
322 /* vdelay */ 0x1a,
323 /* sheight */ 480,
324 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 },{
326 .v4l2_id = V4L2_STD_SECAM,
327 .name = "SECAM",
328 .Fsc = 35468950,
329 .swidth = 924,
330 .sheight = 576,
331 .totalwidth = 1135,
332 .adelay = 0x7f,
333 .bdelay = 0xb0,
334 .iform = (BT848_IFORM_SECAM|BT848_IFORM_XT1),
335 .scaledtwidth = 1135,
336 .hdelayx1 = 186,
337 .hactivex1 = 922,
338 .vdelay = 0x20,
339 .vbipack = 255,
340 .sram = 0, /* like PAL, correct? */
Michael H. Schimek67f15702006-01-09 15:25:27 -0200341 .vbistart = { 7, 320 },
Michael Schimeke5bd0262007-01-18 16:17:39 -0300342 CROPCAP(/* minhdelayx1 */ 68,
343 /* hdelayx1 */ 186,
344 /* swidth */ 924,
345 /* totalwidth */ 1135,
346 /* sqwidth */ 944,
347 /* vdelay */ 0x20,
348 /* sheight */ 576,
349 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 },{
351 .v4l2_id = V4L2_STD_PAL_Nc,
352 .name = "PAL-Nc",
353 .Fsc = 28636363,
354 .swidth = 640,
355 .sheight = 576,
356 .totalwidth = 910,
357 .adelay = 0x68,
358 .bdelay = 0x5d,
359 .iform = (BT848_IFORM_PAL_NC|BT848_IFORM_XT0),
360 .scaledtwidth = 780,
361 .hdelayx1 = 130,
362 .hactivex1 = 734,
363 .vdelay = 0x1a,
364 .vbipack = 144,
365 .sram = -1,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200366 .vbistart = { 7, 320 },
Michael Schimeke5bd0262007-01-18 16:17:39 -0300367 CROPCAP(/* minhdelayx1 */ 68,
368 /* hdelayx1 */ 130,
369 /* swidth */ (640 * 910 + 780 / 2) / 780,
370 /* totalwidth */ 910,
371 /* sqwidth */ 780,
372 /* vdelay */ 0x1a,
373 /* sheight */ 576,
374 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 },{
376 .v4l2_id = V4L2_STD_PAL_M,
377 .name = "PAL-M",
378 .Fsc = 28636363,
379 .swidth = 640,
380 .sheight = 480,
381 .totalwidth = 910,
382 .adelay = 0x68,
383 .bdelay = 0x5d,
384 .iform = (BT848_IFORM_PAL_M|BT848_IFORM_XT0),
385 .scaledtwidth = 780,
386 .hdelayx1 = 135,
387 .hactivex1 = 754,
388 .vdelay = 0x1a,
389 .vbipack = 144,
390 .sram = -1,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200391 .vbistart = { 10, 273 },
Michael Schimeke5bd0262007-01-18 16:17:39 -0300392 CROPCAP(/* minhdelayx1 */ 68,
393 /* hdelayx1 */ 135,
394 /* swidth */ (640 * 910 + 780 / 2) / 780,
395 /* totalwidth */ 910,
396 /* sqwidth */ 780,
397 /* vdelay */ 0x1a,
398 /* sheight */ 480,
399 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 },{
401 .v4l2_id = V4L2_STD_PAL_N,
402 .name = "PAL-N",
403 .Fsc = 35468950,
404 .swidth = 768,
405 .sheight = 576,
406 .totalwidth = 1135,
407 .adelay = 0x7f,
408 .bdelay = 0x72,
409 .iform = (BT848_IFORM_PAL_N|BT848_IFORM_XT1),
410 .scaledtwidth = 944,
411 .hdelayx1 = 186,
412 .hactivex1 = 922,
413 .vdelay = 0x20,
414 .vbipack = 144,
415 .sram = -1,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300416 .vbistart = { 7, 320 },
417 CROPCAP(/* minhdelayx1 */ 68,
418 /* hdelayx1 */ 186,
419 /* swidth */ (768 * 1135 + 944 / 2) / 944,
420 /* totalwidth */ 1135,
421 /* sqwidth */ 944,
422 /* vdelay */ 0x20,
423 /* sheight */ 576,
424 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 },{
426 .v4l2_id = V4L2_STD_NTSC_M_JP,
427 .name = "NTSC-JP",
428 .Fsc = 28636363,
429 .swidth = 640,
430 .sheight = 480,
431 .totalwidth = 910,
432 .adelay = 0x68,
433 .bdelay = 0x5d,
434 .iform = (BT848_IFORM_NTSC_J|BT848_IFORM_XT0),
435 .scaledtwidth = 780,
436 .hdelayx1 = 135,
437 .hactivex1 = 754,
438 .vdelay = 0x16,
439 .vbipack = 144,
440 .sram = -1,
Michael Schimeke5bd0262007-01-18 16:17:39 -0300441 .vbistart = { 10, 273 },
442 CROPCAP(/* minhdelayx1 */ 68,
443 /* hdelayx1 */ 135,
444 /* swidth */ (640 * 910 + 780 / 2) / 780,
445 /* totalwidth */ 910,
446 /* sqwidth */ 780,
447 /* vdelay */ 0x16,
448 /* sheight */ 480,
449 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 },{
451 /* that one hopefully works with the strange timing
452 * which video recorders produce when playing a NTSC
453 * tape on a PAL TV ... */
454 .v4l2_id = V4L2_STD_PAL_60,
455 .name = "PAL-60",
456 .Fsc = 35468950,
457 .swidth = 924,
458 .sheight = 480,
459 .totalwidth = 1135,
460 .adelay = 0x7f,
461 .bdelay = 0x72,
462 .iform = (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
463 .scaledtwidth = 1135,
464 .hdelayx1 = 186,
465 .hactivex1 = 924,
466 .vdelay = 0x1a,
467 .vbipack = 255,
468 .vtotal = 524,
469 .sram = -1,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200470 .vbistart = { 10, 273 },
Michael Schimeke5bd0262007-01-18 16:17:39 -0300471 CROPCAP(/* minhdelayx1 */ 68,
472 /* hdelayx1 */ 186,
473 /* swidth */ 924,
474 /* totalwidth */ 1135,
475 /* sqwidth */ 944,
476 /* vdelay */ 0x1a,
477 /* sheight */ 480,
478 /* videostart0 */ 23)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479 }
480};
481static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms);
482
483/* ----------------------------------------------------------------------- */
484/* bttv format list
485 packed pixel formats must come first */
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -0300486static const struct bttv_format formats[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487 {
488 .name = "8 bpp, gray",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 .fourcc = V4L2_PIX_FMT_GREY,
490 .btformat = BT848_COLOR_FMT_Y8,
491 .depth = 8,
492 .flags = FORMAT_FLAGS_PACKED,
493 },{
494 .name = "8 bpp, dithered color",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 .fourcc = V4L2_PIX_FMT_HI240,
496 .btformat = BT848_COLOR_FMT_RGB8,
497 .depth = 8,
498 .flags = FORMAT_FLAGS_PACKED | FORMAT_FLAGS_DITHER,
499 },{
500 .name = "15 bpp RGB, le",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 .fourcc = V4L2_PIX_FMT_RGB555,
502 .btformat = BT848_COLOR_FMT_RGB15,
503 .depth = 16,
504 .flags = FORMAT_FLAGS_PACKED,
505 },{
506 .name = "15 bpp RGB, be",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 .fourcc = V4L2_PIX_FMT_RGB555X,
508 .btformat = BT848_COLOR_FMT_RGB15,
509 .btswap = 0x03, /* byteswap */
510 .depth = 16,
511 .flags = FORMAT_FLAGS_PACKED,
512 },{
513 .name = "16 bpp RGB, le",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 .fourcc = V4L2_PIX_FMT_RGB565,
515 .btformat = BT848_COLOR_FMT_RGB16,
516 .depth = 16,
517 .flags = FORMAT_FLAGS_PACKED,
518 },{
519 .name = "16 bpp RGB, be",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 .fourcc = V4L2_PIX_FMT_RGB565X,
521 .btformat = BT848_COLOR_FMT_RGB16,
522 .btswap = 0x03, /* byteswap */
523 .depth = 16,
524 .flags = FORMAT_FLAGS_PACKED,
525 },{
526 .name = "24 bpp RGB, le",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 .fourcc = V4L2_PIX_FMT_BGR24,
528 .btformat = BT848_COLOR_FMT_RGB24,
529 .depth = 24,
530 .flags = FORMAT_FLAGS_PACKED,
531 },{
532 .name = "32 bpp RGB, le",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533 .fourcc = V4L2_PIX_FMT_BGR32,
534 .btformat = BT848_COLOR_FMT_RGB32,
535 .depth = 32,
536 .flags = FORMAT_FLAGS_PACKED,
537 },{
538 .name = "32 bpp RGB, be",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 .fourcc = V4L2_PIX_FMT_RGB32,
540 .btformat = BT848_COLOR_FMT_RGB32,
541 .btswap = 0x0f, /* byte+word swap */
542 .depth = 32,
543 .flags = FORMAT_FLAGS_PACKED,
544 },{
545 .name = "4:2:2, packed, YUYV",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 .fourcc = V4L2_PIX_FMT_YUYV,
547 .btformat = BT848_COLOR_FMT_YUY2,
548 .depth = 16,
549 .flags = FORMAT_FLAGS_PACKED,
550 },{
551 .name = "4:2:2, packed, YUYV",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 .fourcc = V4L2_PIX_FMT_YUYV,
553 .btformat = BT848_COLOR_FMT_YUY2,
554 .depth = 16,
555 .flags = FORMAT_FLAGS_PACKED,
556 },{
557 .name = "4:2:2, packed, UYVY",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 .fourcc = V4L2_PIX_FMT_UYVY,
559 .btformat = BT848_COLOR_FMT_YUY2,
560 .btswap = 0x03, /* byteswap */
561 .depth = 16,
562 .flags = FORMAT_FLAGS_PACKED,
563 },{
564 .name = "4:2:2, planar, Y-Cb-Cr",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 .fourcc = V4L2_PIX_FMT_YUV422P,
566 .btformat = BT848_COLOR_FMT_YCrCb422,
567 .depth = 16,
568 .flags = FORMAT_FLAGS_PLANAR,
569 .hshift = 1,
570 .vshift = 0,
571 },{
572 .name = "4:2:0, planar, Y-Cb-Cr",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 .fourcc = V4L2_PIX_FMT_YUV420,
574 .btformat = BT848_COLOR_FMT_YCrCb422,
575 .depth = 12,
576 .flags = FORMAT_FLAGS_PLANAR,
577 .hshift = 1,
578 .vshift = 1,
579 },{
580 .name = "4:2:0, planar, Y-Cr-Cb",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 .fourcc = V4L2_PIX_FMT_YVU420,
582 .btformat = BT848_COLOR_FMT_YCrCb422,
583 .depth = 12,
584 .flags = FORMAT_FLAGS_PLANAR | FORMAT_FLAGS_CrCb,
585 .hshift = 1,
586 .vshift = 1,
587 },{
588 .name = "4:1:1, planar, Y-Cb-Cr",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 .fourcc = V4L2_PIX_FMT_YUV411P,
590 .btformat = BT848_COLOR_FMT_YCrCb411,
591 .depth = 12,
592 .flags = FORMAT_FLAGS_PLANAR,
593 .hshift = 2,
594 .vshift = 0,
595 },{
596 .name = "4:1:0, planar, Y-Cb-Cr",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 .fourcc = V4L2_PIX_FMT_YUV410,
598 .btformat = BT848_COLOR_FMT_YCrCb411,
599 .depth = 9,
600 .flags = FORMAT_FLAGS_PLANAR,
601 .hshift = 2,
602 .vshift = 2,
603 },{
604 .name = "4:1:0, planar, Y-Cr-Cb",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 .fourcc = V4L2_PIX_FMT_YVU410,
606 .btformat = BT848_COLOR_FMT_YCrCb411,
607 .depth = 9,
608 .flags = FORMAT_FLAGS_PLANAR | FORMAT_FLAGS_CrCb,
609 .hshift = 2,
610 .vshift = 2,
611 },{
612 .name = "raw scanlines",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 .fourcc = -1,
614 .btformat = BT848_COLOR_FMT_RAW,
615 .depth = 8,
616 .flags = FORMAT_FLAGS_RAW,
617 }
618};
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -0300619static const unsigned int FORMATS = ARRAY_SIZE(formats);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620
621/* ----------------------------------------------------------------------- */
622
623#define V4L2_CID_PRIVATE_CHROMA_AGC (V4L2_CID_PRIVATE_BASE + 0)
624#define V4L2_CID_PRIVATE_COMBFILTER (V4L2_CID_PRIVATE_BASE + 1)
625#define V4L2_CID_PRIVATE_AUTOMUTE (V4L2_CID_PRIVATE_BASE + 2)
626#define V4L2_CID_PRIVATE_LUMAFILTER (V4L2_CID_PRIVATE_BASE + 3)
627#define V4L2_CID_PRIVATE_AGC_CRUSH (V4L2_CID_PRIVATE_BASE + 4)
628#define V4L2_CID_PRIVATE_VCR_HACK (V4L2_CID_PRIVATE_BASE + 5)
629#define V4L2_CID_PRIVATE_WHITECRUSH_UPPER (V4L2_CID_PRIVATE_BASE + 6)
630#define V4L2_CID_PRIVATE_WHITECRUSH_LOWER (V4L2_CID_PRIVATE_BASE + 7)
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700631#define V4L2_CID_PRIVATE_UV_RATIO (V4L2_CID_PRIVATE_BASE + 8)
632#define V4L2_CID_PRIVATE_FULL_LUMA_RANGE (V4L2_CID_PRIVATE_BASE + 9)
633#define V4L2_CID_PRIVATE_CORING (V4L2_CID_PRIVATE_BASE + 10)
634#define V4L2_CID_PRIVATE_LASTP1 (V4L2_CID_PRIVATE_BASE + 11)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635
636static const struct v4l2_queryctrl no_ctl = {
637 .name = "42",
638 .flags = V4L2_CTRL_FLAG_DISABLED,
639};
640static const struct v4l2_queryctrl bttv_ctls[] = {
641 /* --- video --- */
642 {
643 .id = V4L2_CID_BRIGHTNESS,
644 .name = "Brightness",
645 .minimum = 0,
646 .maximum = 65535,
647 .step = 256,
648 .default_value = 32768,
649 .type = V4L2_CTRL_TYPE_INTEGER,
650 },{
651 .id = V4L2_CID_CONTRAST,
652 .name = "Contrast",
653 .minimum = 0,
654 .maximum = 65535,
655 .step = 128,
656 .default_value = 32768,
657 .type = V4L2_CTRL_TYPE_INTEGER,
658 },{
659 .id = V4L2_CID_SATURATION,
660 .name = "Saturation",
661 .minimum = 0,
662 .maximum = 65535,
663 .step = 128,
664 .default_value = 32768,
665 .type = V4L2_CTRL_TYPE_INTEGER,
666 },{
667 .id = V4L2_CID_HUE,
668 .name = "Hue",
669 .minimum = 0,
670 .maximum = 65535,
671 .step = 256,
672 .default_value = 32768,
673 .type = V4L2_CTRL_TYPE_INTEGER,
674 },
675 /* --- audio --- */
676 {
677 .id = V4L2_CID_AUDIO_MUTE,
678 .name = "Mute",
679 .minimum = 0,
680 .maximum = 1,
681 .type = V4L2_CTRL_TYPE_BOOLEAN,
682 },{
683 .id = V4L2_CID_AUDIO_VOLUME,
684 .name = "Volume",
685 .minimum = 0,
686 .maximum = 65535,
687 .step = 65535/100,
688 .default_value = 65535,
689 .type = V4L2_CTRL_TYPE_INTEGER,
690 },{
691 .id = V4L2_CID_AUDIO_BALANCE,
692 .name = "Balance",
693 .minimum = 0,
694 .maximum = 65535,
695 .step = 65535/100,
696 .default_value = 32768,
697 .type = V4L2_CTRL_TYPE_INTEGER,
698 },{
699 .id = V4L2_CID_AUDIO_BASS,
700 .name = "Bass",
701 .minimum = 0,
702 .maximum = 65535,
703 .step = 65535/100,
704 .default_value = 32768,
705 .type = V4L2_CTRL_TYPE_INTEGER,
706 },{
707 .id = V4L2_CID_AUDIO_TREBLE,
708 .name = "Treble",
709 .minimum = 0,
710 .maximum = 65535,
711 .step = 65535/100,
712 .default_value = 32768,
713 .type = V4L2_CTRL_TYPE_INTEGER,
714 },
715 /* --- private --- */
716 {
717 .id = V4L2_CID_PRIVATE_CHROMA_AGC,
718 .name = "chroma agc",
719 .minimum = 0,
720 .maximum = 1,
721 .type = V4L2_CTRL_TYPE_BOOLEAN,
722 },{
723 .id = V4L2_CID_PRIVATE_COMBFILTER,
724 .name = "combfilter",
725 .minimum = 0,
726 .maximum = 1,
727 .type = V4L2_CTRL_TYPE_BOOLEAN,
728 },{
729 .id = V4L2_CID_PRIVATE_AUTOMUTE,
730 .name = "automute",
731 .minimum = 0,
732 .maximum = 1,
733 .type = V4L2_CTRL_TYPE_BOOLEAN,
734 },{
735 .id = V4L2_CID_PRIVATE_LUMAFILTER,
736 .name = "luma decimation filter",
737 .minimum = 0,
738 .maximum = 1,
739 .type = V4L2_CTRL_TYPE_BOOLEAN,
740 },{
741 .id = V4L2_CID_PRIVATE_AGC_CRUSH,
742 .name = "agc crush",
743 .minimum = 0,
744 .maximum = 1,
745 .type = V4L2_CTRL_TYPE_BOOLEAN,
746 },{
747 .id = V4L2_CID_PRIVATE_VCR_HACK,
748 .name = "vcr hack",
749 .minimum = 0,
750 .maximum = 1,
751 .type = V4L2_CTRL_TYPE_BOOLEAN,
752 },{
753 .id = V4L2_CID_PRIVATE_WHITECRUSH_UPPER,
754 .name = "whitecrush upper",
755 .minimum = 0,
756 .maximum = 255,
757 .step = 1,
758 .default_value = 0xCF,
759 .type = V4L2_CTRL_TYPE_INTEGER,
760 },{
761 .id = V4L2_CID_PRIVATE_WHITECRUSH_LOWER,
762 .name = "whitecrush lower",
763 .minimum = 0,
764 .maximum = 255,
765 .step = 1,
766 .default_value = 0x7F,
767 .type = V4L2_CTRL_TYPE_INTEGER,
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700768 },{
769 .id = V4L2_CID_PRIVATE_UV_RATIO,
770 .name = "uv ratio",
771 .minimum = 0,
772 .maximum = 100,
773 .step = 1,
774 .default_value = 50,
775 .type = V4L2_CTRL_TYPE_INTEGER,
776 },{
777 .id = V4L2_CID_PRIVATE_FULL_LUMA_RANGE,
778 .name = "full luma range",
779 .minimum = 0,
780 .maximum = 1,
781 .type = V4L2_CTRL_TYPE_BOOLEAN,
782 },{
783 .id = V4L2_CID_PRIVATE_CORING,
784 .name = "coring",
785 .minimum = 0,
786 .maximum = 3,
787 .step = 1,
788 .default_value = 0,
789 .type = V4L2_CTRL_TYPE_INTEGER,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 }
791
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700792
793
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -0300796static const struct v4l2_queryctrl *ctrl_by_id(int id)
797{
798 int i;
799
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -0300800 for (i = 0; i < ARRAY_SIZE(bttv_ctls); i++)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -0300801 if (bttv_ctls[i].id == id)
802 return bttv_ctls+i;
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -0300803
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -0300804 return NULL;
805}
806
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807/* ----------------------------------------------------------------------- */
808/* resource management */
809
Michael Schimeke5bd0262007-01-18 16:17:39 -0300810/*
811 RESOURCE_ allocated by freed by
812
813 VIDEO_READ bttv_read 1) bttv_read 2)
814
815 VIDEO_STREAM VIDIOC_STREAMON VIDIOC_STREAMOFF
816 VIDIOC_QBUF 1) bttv_release
817 VIDIOCMCAPTURE 1)
818
819 OVERLAY VIDIOCCAPTURE on VIDIOCCAPTURE off
820 VIDIOC_OVERLAY on VIDIOC_OVERLAY off
821 3) bttv_release
822
823 VBI VIDIOC_STREAMON VIDIOC_STREAMOFF
824 VIDIOC_QBUF 1) bttv_release
825 bttv_read, bttv_poll 1) 4)
826
827 1) The resource must be allocated when we enter buffer prepare functions
828 and remain allocated while buffers are in the DMA queue.
829 2) This is a single frame read.
830 3) VIDIOC_S_FBUF and VIDIOC_S_FMT (OVERLAY) still work when
831 RESOURCE_OVERLAY is allocated.
832 4) This is a continuous read, implies VIDIOC_STREAMON.
833
834 Note this driver permits video input and standard changes regardless if
835 resources are allocated.
836*/
837
838#define VBI_RESOURCES (RESOURCE_VBI)
839#define VIDEO_RESOURCES (RESOURCE_VIDEO_READ | \
840 RESOURCE_VIDEO_STREAM | \
841 RESOURCE_OVERLAY)
842
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843static
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -0300844int check_alloc_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845{
Michael Schimeke5bd0262007-01-18 16:17:39 -0300846 int xbits; /* mutual exclusive resources */
847
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 if (fh->resources & bit)
849 /* have it already allocated */
850 return 1;
851
Michael Schimeke5bd0262007-01-18 16:17:39 -0300852 xbits = bit;
853 if (bit & (RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM))
854 xbits |= RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM;
855
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 /* is it free? */
Michael Schimeke5bd0262007-01-18 16:17:39 -0300857 if (btv->resources & xbits) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 /* no, someone else uses it */
Michael Schimeke5bd0262007-01-18 16:17:39 -0300859 goto fail;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860 }
Michael Schimeke5bd0262007-01-18 16:17:39 -0300861
862 if ((bit & VIDEO_RESOURCES)
863 && 0 == (btv->resources & VIDEO_RESOURCES)) {
864 /* Do crop - use current, don't - use default parameters. */
865 __s32 top = btv->crop[!!fh->do_crop].rect.top;
866
867 if (btv->vbi_end > top)
868 goto fail;
869
870 /* We cannot capture the same line as video and VBI data.
871 Claim scan lines crop[].rect.top to bottom. */
872 btv->crop_start = top;
873 } else if (bit & VBI_RESOURCES) {
874 __s32 end = fh->vbi_fmt.end;
875
876 if (end > btv->crop_start)
877 goto fail;
878
879 /* Claim scan lines above fh->vbi_fmt.end. */
880 btv->vbi_end = end;
881 }
882
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 /* it's free, grab it */
884 fh->resources |= bit;
885 btv->resources |= bit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 return 1;
Michael Schimeke5bd0262007-01-18 16:17:39 -0300887
888 fail:
Michael Schimeke5bd0262007-01-18 16:17:39 -0300889 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890}
891
892static
893int check_btres(struct bttv_fh *fh, int bit)
894{
895 return (fh->resources & bit);
896}
897
898static
899int locked_btres(struct bttv *btv, int bit)
900{
901 return (btv->resources & bit);
902}
903
Michael Schimeke5bd0262007-01-18 16:17:39 -0300904/* Call with btv->lock down. */
905static void
906disclaim_vbi_lines(struct bttv *btv)
907{
908 btv->vbi_end = 0;
909}
910
911/* Call with btv->lock down. */
912static void
913disclaim_video_lines(struct bttv *btv)
914{
915 const struct bttv_tvnorm *tvnorm;
916 u8 crop;
917
918 tvnorm = &bttv_tvnorms[btv->tvnorm];
919 btv->crop_start = tvnorm->cropcap.bounds.top
920 + tvnorm->cropcap.bounds.height;
921
922 /* VBI capturing ends at VDELAY, start of video capturing, no
923 matter how many lines the VBI RISC program expects. When video
924 capturing is off, it shall no longer "preempt" VBI capturing,
925 so we set VDELAY to maximum. */
926 crop = btread(BT848_E_CROP) | 0xc0;
927 btwrite(crop, BT848_E_CROP);
928 btwrite(0xfe, BT848_E_VDELAY_LO);
929 btwrite(crop, BT848_O_CROP);
930 btwrite(0xfe, BT848_O_VDELAY_LO);
931}
932
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933static
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -0300934void free_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bits)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 if ((fh->resources & bits) != bits) {
937 /* trying to free ressources not allocated by us ... */
938 printk("bttv: BUG! (btres)\n");
939 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 fh->resources &= ~bits;
941 btv->resources &= ~bits;
Michael Schimeke5bd0262007-01-18 16:17:39 -0300942
943 bits = btv->resources;
944
945 if (0 == (bits & VIDEO_RESOURCES))
946 disclaim_video_lines(btv);
947
948 if (0 == (bits & VBI_RESOURCES))
949 disclaim_vbi_lines(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950}
951
952/* ----------------------------------------------------------------------- */
953/* If Bt848a or Bt849, use PLL for PAL/SECAM and crystal for NTSC */
954
955/* Frequency = (F_input / PLL_X) * PLL_I.PLL_F/PLL_C
956 PLL_X = Reference pre-divider (0=1, 1=2)
957 PLL_C = Post divider (0=6, 1=4)
958 PLL_I = Integer input
959 PLL_F = Fractional input
960
961 F_input = 28.636363 MHz:
962 PAL (CLKx2 = 35.46895 MHz): PLL_X = 1, PLL_I = 0x0E, PLL_F = 0xDCF9, PLL_C = 0
963*/
964
965static void set_pll_freq(struct bttv *btv, unsigned int fin, unsigned int fout)
966{
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800967 unsigned char fl, fh, fi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800969 /* prevent overflows */
970 fin/=4;
971 fout/=4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800973 fout*=12;
974 fi=fout/fin;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800976 fout=(fout%fin)*256;
977 fh=fout/fin;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800979 fout=(fout%fin)*256;
980 fl=fout/fin;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800982 btwrite(fl, BT848_PLL_F_LO);
983 btwrite(fh, BT848_PLL_F_HI);
984 btwrite(fi|BT848_PLL_X, BT848_PLL_XCI);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985}
986
987static void set_pll(struct bttv *btv)
988{
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800989 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800991 if (!btv->pll.pll_crystal)
992 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993
994 if (btv->pll.pll_ofreq == btv->pll.pll_current) {
995 dprintk("bttv%d: PLL: no change required\n",btv->c.nr);
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800996 return;
997 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800999 if (btv->pll.pll_ifreq == btv->pll.pll_ofreq) {
1000 /* no PLL needed */
1001 if (btv->pll.pll_current == 0)
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -08001002 return;
Bernd Petrovitsche1e70a22005-09-22 21:43:53 -07001003 bttv_printk(KERN_INFO "bttv%d: PLL can sleep, using XTAL (%d).\n",
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -08001004 btv->c.nr,btv->pll.pll_ifreq);
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -08001005 btwrite(0x00,BT848_TGCTRL);
1006 btwrite(0x00,BT848_PLL_XCI);
1007 btv->pll.pll_current = 0;
1008 return;
1009 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010
Bernd Petrovitsche1e70a22005-09-22 21:43:53 -07001011 bttv_printk(KERN_INFO "bttv%d: PLL: %d => %d ",btv->c.nr,
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -08001012 btv->pll.pll_ifreq, btv->pll.pll_ofreq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 set_pll_freq(btv, btv->pll.pll_ifreq, btv->pll.pll_ofreq);
1014
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -08001015 for (i=0; i<10; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 /* Let other people run while the PLL stabilizes */
Bernd Petrovitsche1e70a22005-09-22 21:43:53 -07001017 bttv_printk(".");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018 msleep(10);
1019
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -08001020 if (btread(BT848_DSTATUS) & BT848_DSTATUS_PLOCK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 btwrite(0,BT848_DSTATUS);
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -08001022 } else {
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -08001023 btwrite(0x08,BT848_TGCTRL);
1024 btv->pll.pll_current = btv->pll.pll_ofreq;
Bernd Petrovitsche1e70a22005-09-22 21:43:53 -07001025 bttv_printk(" ok\n");
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -08001026 return;
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -08001027 }
1028 }
1029 btv->pll.pll_current = -1;
Bernd Petrovitsche1e70a22005-09-22 21:43:53 -07001030 bttv_printk("failed\n");
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -08001031 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032}
1033
1034/* used to switch between the bt848's analog/digital video capture modes */
1035static void bt848A_set_timing(struct bttv *btv)
1036{
1037 int i, len;
1038 int table_idx = bttv_tvnorms[btv->tvnorm].sram;
1039 int fsc = bttv_tvnorms[btv->tvnorm].Fsc;
1040
Trent Piepho5221e212009-01-28 21:32:59 -03001041 if (btv->input == btv->dig) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 dprintk("bttv%d: load digital timing table (table_idx=%d)\n",
1043 btv->c.nr,table_idx);
1044
1045 /* timing change...reset timing generator address */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001046 btwrite(0x00, BT848_TGCTRL);
1047 btwrite(0x02, BT848_TGCTRL);
1048 btwrite(0x00, BT848_TGCTRL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049
1050 len=SRAM_Table[table_idx][0];
1051 for(i = 1; i <= len; i++)
1052 btwrite(SRAM_Table[table_idx][i],BT848_TGLB);
1053 btv->pll.pll_ofreq = 27000000;
1054
1055 set_pll(btv);
1056 btwrite(0x11, BT848_TGCTRL);
1057 btwrite(0x41, BT848_DVSIF);
1058 } else {
1059 btv->pll.pll_ofreq = fsc;
1060 set_pll(btv);
1061 btwrite(0x0, BT848_DVSIF);
1062 }
1063}
1064
1065/* ----------------------------------------------------------------------- */
1066
1067static void bt848_bright(struct bttv *btv, int bright)
1068{
1069 int value;
1070
1071 // printk("bttv: set bright: %d\n",bright); // DEBUG
1072 btv->bright = bright;
1073
1074 /* We want -128 to 127 we get 0-65535 */
1075 value = (bright >> 8) - 128;
1076 btwrite(value & 0xff, BT848_BRIGHT);
1077}
1078
1079static void bt848_hue(struct bttv *btv, int hue)
1080{
1081 int value;
1082
1083 btv->hue = hue;
1084
1085 /* -128 to 127 */
1086 value = (hue >> 8) - 128;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001087 btwrite(value & 0xff, BT848_HUE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088}
1089
1090static void bt848_contrast(struct bttv *btv, int cont)
1091{
1092 int value,hibit;
1093
1094 btv->contrast = cont;
1095
1096 /* 0-511 */
1097 value = (cont >> 7);
1098 hibit = (value >> 6) & 4;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001099 btwrite(value & 0xff, BT848_CONTRAST_LO);
1100 btaor(hibit, ~4, BT848_E_CONTROL);
1101 btaor(hibit, ~4, BT848_O_CONTROL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102}
1103
1104static void bt848_sat(struct bttv *btv, int color)
1105{
1106 int val_u,val_v,hibits;
1107
1108 btv->saturation = color;
1109
1110 /* 0-511 for the color */
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -07001111 val_u = ((color * btv->opt_uv_ratio) / 50) >> 7;
1112 val_v = (((color * (100 - btv->opt_uv_ratio) / 50) >>7)*180L)/254;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001113 hibits = (val_u >> 7) & 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114 hibits |= (val_v >> 8) & 1;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001115 btwrite(val_u & 0xff, BT848_SAT_U_LO);
1116 btwrite(val_v & 0xff, BT848_SAT_V_LO);
1117 btaor(hibits, ~3, BT848_E_CONTROL);
1118 btaor(hibits, ~3, BT848_O_CONTROL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119}
1120
1121/* ----------------------------------------------------------------------- */
1122
1123static int
1124video_mux(struct bttv *btv, unsigned int input)
1125{
1126 int mux,mask2;
1127
1128 if (input >= bttv_tvcards[btv->c.type].video_inputs)
1129 return -EINVAL;
1130
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001131 /* needed by RemoteVideo MX */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 mask2 = bttv_tvcards[btv->c.type].gpiomask2;
1133 if (mask2)
1134 gpio_inout(mask2,mask2);
1135
1136 if (input == btv->svhs) {
1137 btor(BT848_CONTROL_COMP, BT848_E_CONTROL);
1138 btor(BT848_CONTROL_COMP, BT848_O_CONTROL);
1139 } else {
1140 btand(~BT848_CONTROL_COMP, BT848_E_CONTROL);
1141 btand(~BT848_CONTROL_COMP, BT848_O_CONTROL);
1142 }
Trent Piepho6f987002009-01-28 21:32:59 -03001143 mux = bttv_muxsel(btv, input);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 btaor(mux<<5, ~(3<<5), BT848_IFORM);
1145 dprintk(KERN_DEBUG "bttv%d: video mux: input=%d mux=%d\n",
1146 btv->c.nr,input,mux);
1147
1148 /* card specific hook */
1149 if(bttv_tvcards[btv->c.type].muxsel_hook)
1150 bttv_tvcards[btv->c.type].muxsel_hook (btv, input);
1151 return 0;
1152}
1153
1154static char *audio_modes[] = {
1155 "audio: tuner", "audio: radio", "audio: extern",
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001156 "audio: intern", "audio: mute"
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157};
1158
1159static int
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001160audio_mux(struct bttv *btv, int input, int mute)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161{
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001162 int gpio_val, signal;
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001163 struct v4l2_control ctrl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164
1165 gpio_inout(bttv_tvcards[btv->c.type].gpiomask,
1166 bttv_tvcards[btv->c.type].gpiomask);
1167 signal = btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC;
1168
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001169 btv->mute = mute;
1170 btv->audio = input;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001172 /* automute */
1173 mute = mute || (btv->opt_automute && !signal && !btv->radio_user);
1174
1175 if (mute)
1176 gpio_val = bttv_tvcards[btv->c.type].gpiomute;
1177 else
1178 gpio_val = bttv_tvcards[btv->c.type].gpiomux[input];
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001179
Trent Piepho72134a62009-01-28 21:32:59 -03001180 switch (btv->c.type) {
1181 case BTTV_BOARD_VOODOOTV_FM:
1182 case BTTV_BOARD_VOODOOTV_200:
1183 gpio_val = bttv_tda9880_setnorm(btv, gpio_val);
1184 break;
1185
1186 default:
1187 gpio_bits(bttv_tvcards[btv->c.type].gpiomask, gpio_val);
1188 }
1189
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190 if (bttv_gpio)
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001191 bttv_gpio_tracking(btv, audio_modes[mute ? 4 : input]);
1192 if (in_interrupt())
1193 return 0;
1194
1195 ctrl.id = V4L2_CID_AUDIO_MUTE;
Hans Verkuil2474ed42006-03-19 12:35:57 -03001196 ctrl.value = btv->mute;
Hans Verkuil859f0272009-03-28 08:29:00 -03001197 bttv_call_all(btv, core, s_ctrl, &ctrl);
1198 if (btv->sd_msp34xx) {
Hans Verkuil5325b422009-04-02 11:26:22 -03001199 u32 in;
Hans Verkuil2474ed42006-03-19 12:35:57 -03001200
1201 /* Note: the inputs tuner/radio/extern/intern are translated
1202 to msp routings. This assumes common behavior for all msp3400
1203 based TV cards. When this assumption fails, then the
1204 specific MSP routing must be added to the card table.
1205 For now this is sufficient. */
1206 switch (input) {
1207 case TVAUDIO_INPUT_RADIO:
Hans Verkuil5325b422009-04-02 11:26:22 -03001208 in = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1,
Hans Verkuil07151722006-04-01 18:03:23 -03001209 MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001210 break;
1211 case TVAUDIO_INPUT_EXTERN:
Hans Verkuil5325b422009-04-02 11:26:22 -03001212 in = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1,
Hans Verkuil07151722006-04-01 18:03:23 -03001213 MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001214 break;
1215 case TVAUDIO_INPUT_INTERN:
1216 /* Yes, this is the same input as for RADIO. I doubt
1217 if this is ever used. The only board with an INTERN
1218 input is the BTTV_BOARD_AVERMEDIA98. I wonder how
1219 that was tested. My guess is that the whole INTERN
1220 input does not work. */
Hans Verkuil5325b422009-04-02 11:26:22 -03001221 in = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1,
Hans Verkuil07151722006-04-01 18:03:23 -03001222 MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001223 break;
1224 case TVAUDIO_INPUT_TUNER:
1225 default:
Wade Berrier434b2522007-06-25 13:02:16 -03001226 /* This is the only card that uses TUNER2, and afaik,
1227 is the only difference between the VOODOOTV_FM
1228 and VOODOOTV_200 */
1229 if (btv->c.type == BTTV_BOARD_VOODOOTV_200)
Hans Verkuil5325b422009-04-02 11:26:22 -03001230 in = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER2, \
Wade Berrier434b2522007-06-25 13:02:16 -03001231 MSP_DSP_IN_TUNER, MSP_DSP_IN_TUNER);
1232 else
Hans Verkuil5325b422009-04-02 11:26:22 -03001233 in = MSP_INPUT_DEFAULT;
Hans Verkuil2474ed42006-03-19 12:35:57 -03001234 break;
1235 }
Hans Verkuil5325b422009-04-02 11:26:22 -03001236 v4l2_subdev_call(btv->sd_msp34xx, audio, s_routing,
1237 in, MSP_OUTPUT_DEFAULT, 0);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001238 }
Hans Verkuil859f0272009-03-28 08:29:00 -03001239 if (btv->sd_tvaudio) {
Hans Verkuil5325b422009-04-02 11:26:22 -03001240 v4l2_subdev_call(btv->sd_tvaudio, audio, s_routing,
1241 input, 0, 0);
Hans Verkuil2474ed42006-03-19 12:35:57 -03001242 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243 return 0;
1244}
1245
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03001246static inline int
1247audio_mute(struct bttv *btv, int mute)
1248{
1249 return audio_mux(btv, btv->audio, mute);
1250}
1251
1252static inline int
1253audio_input(struct bttv *btv, int input)
1254{
1255 return audio_mux(btv, input, btv->mute);
1256}
1257
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258static void
Michael Schimeke5bd0262007-01-18 16:17:39 -03001259bttv_crop_calc_limits(struct bttv_crop *c)
1260{
1261 /* Scale factor min. 1:1, max. 16:1. Min. image size
1262 48 x 32. Scaled width must be a multiple of 4. */
1263
1264 if (1) {
1265 /* For bug compatibility with VIDIOCGCAP and image
1266 size checks in earlier driver versions. */
1267 c->min_scaled_width = 48;
1268 c->min_scaled_height = 32;
1269 } else {
1270 c->min_scaled_width =
1271 (max(48, c->rect.width >> 4) + 3) & ~3;
1272 c->min_scaled_height =
1273 max(32, c->rect.height >> 4);
1274 }
1275
1276 c->max_scaled_width = c->rect.width & ~3;
1277 c->max_scaled_height = c->rect.height;
1278}
1279
1280static void
Trent Piepho4ef2ccc2009-01-28 21:32:58 -03001281bttv_crop_reset(struct bttv_crop *c, unsigned int norm)
Michael Schimeke5bd0262007-01-18 16:17:39 -03001282{
1283 c->rect = bttv_tvnorms[norm].cropcap.defrect;
1284 bttv_crop_calc_limits(c);
1285}
1286
1287/* Call with btv->lock down. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288static int
1289set_tvnorm(struct bttv *btv, unsigned int norm)
1290{
1291 const struct bttv_tvnorm *tvnorm;
Nickolay V. Shmyrev302f61a2007-10-26 10:53:21 -03001292 v4l2_std_id id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293
Trent Piepho4ef2ccc2009-01-28 21:32:58 -03001294 BUG_ON(norm >= BTTV_TVNORMS);
1295 BUG_ON(btv->tvnorm >= BTTV_TVNORMS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297 tvnorm = &bttv_tvnorms[norm];
1298
Mike Isely2de26c02009-09-21 12:42:22 -03001299 if (memcmp(&bttv_tvnorms[btv->tvnorm].cropcap, &tvnorm->cropcap,
Trent Piepho4ef2ccc2009-01-28 21:32:58 -03001300 sizeof (tvnorm->cropcap))) {
Michael Schimeke5bd0262007-01-18 16:17:39 -03001301 bttv_crop_reset(&btv->crop[0], norm);
1302 btv->crop[1] = btv->crop[0]; /* current = default */
1303
1304 if (0 == (btv->resources & VIDEO_RESOURCES)) {
1305 btv->crop_start = tvnorm->cropcap.bounds.top
1306 + tvnorm->cropcap.bounds.height;
1307 }
1308 }
1309
1310 btv->tvnorm = norm;
1311
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312 btwrite(tvnorm->adelay, BT848_ADELAY);
1313 btwrite(tvnorm->bdelay, BT848_BDELAY);
1314 btaor(tvnorm->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH),
1315 BT848_IFORM);
1316 btwrite(tvnorm->vbipack, BT848_VBI_PACK_SIZE);
1317 btwrite(1, BT848_VBI_PACK_DEL);
1318 bt848A_set_timing(btv);
1319
1320 switch (btv->c.type) {
Mauro Carvalho Chehab5a25e842005-11-08 21:36:52 -08001321 case BTTV_BOARD_VOODOOTV_FM:
Wade Berrier434b2522007-06-25 13:02:16 -03001322 case BTTV_BOARD_VOODOOTV_200:
Trent Piepho72134a62009-01-28 21:32:59 -03001323 bttv_tda9880_setnorm(btv, gpio_read());
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 }
Nickolay V. Shmyrev302f61a2007-10-26 10:53:21 -03001326 id = tvnorm->v4l2_id;
Hans Verkuilf41737e2009-04-01 03:52:39 -03001327 bttv_call_all(btv, core, s_std, id);
Nickolay V. Shmyrev302f61a2007-10-26 10:53:21 -03001328
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329 return 0;
1330}
1331
Michael Schimeke5bd0262007-01-18 16:17:39 -03001332/* Call with btv->lock down. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333static void
Trent Piepho333408f2007-07-03 15:08:10 -03001334set_input(struct bttv *btv, unsigned int input, unsigned int norm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335{
1336 unsigned long flags;
1337
1338 btv->input = input;
1339 if (irq_iswitch) {
1340 spin_lock_irqsave(&btv->s_lock,flags);
1341 if (btv->curr.frame_irq) {
1342 /* active capture -> delayed input switch */
1343 btv->new_input = input;
1344 } else {
1345 video_mux(btv,input);
1346 }
1347 spin_unlock_irqrestore(&btv->s_lock,flags);
1348 } else {
1349 video_mux(btv,input);
1350 }
Trent Piephoabb03622009-01-28 21:32:59 -03001351 audio_input(btv, (btv->tuner_type != TUNER_ABSENT && input == 0) ?
1352 TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN);
Trent Piepho333408f2007-07-03 15:08:10 -03001353 set_tvnorm(btv, norm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354}
1355
1356static void init_irqreg(struct bttv *btv)
1357{
1358 /* clear status */
1359 btwrite(0xfffffUL, BT848_INT_STAT);
1360
1361 if (bttv_tvcards[btv->c.type].no_video) {
1362 /* i2c only */
1363 btwrite(BT848_INT_I2CDONE,
1364 BT848_INT_MASK);
1365 } else {
1366 /* full video */
1367 btwrite((btv->triton1) |
1368 (btv->gpioirq ? BT848_INT_GPINT : 0) |
1369 BT848_INT_SCERR |
1370 (fdsr ? BT848_INT_FDSR : 0) |
Jean Delvareeb1b27b2008-08-30 10:18:21 -03001371 BT848_INT_RISCI | BT848_INT_OCERR |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372 BT848_INT_FMTCHG|BT848_INT_HLOCK|
1373 BT848_INT_I2CDONE,
1374 BT848_INT_MASK);
1375 }
1376}
1377
1378static void init_bt848(struct bttv *btv)
1379{
1380 int val;
1381
1382 if (bttv_tvcards[btv->c.type].no_video) {
1383 /* very basic init only */
1384 init_irqreg(btv);
1385 return;
1386 }
1387
1388 btwrite(0x00, BT848_CAP_CTL);
1389 btwrite(BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL);
1390 btwrite(BT848_IFORM_XTAUTO | BT848_IFORM_AUTO, BT848_IFORM);
1391
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001392 /* set planar and packed mode trigger points and */
1393 /* set rising edge of inverted GPINTR pin as irq trigger */
1394 btwrite(BT848_GPIO_DMA_CTL_PKTP_32|
1395 BT848_GPIO_DMA_CTL_PLTP1_16|
1396 BT848_GPIO_DMA_CTL_PLTP23_16|
1397 BT848_GPIO_DMA_CTL_GPINTC|
1398 BT848_GPIO_DMA_CTL_GPINTI,
1399 BT848_GPIO_DMA_CTL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400
1401 val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001402 btwrite(val, BT848_E_SCLOOP);
1403 btwrite(val, BT848_O_SCLOOP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001405 btwrite(0x20, BT848_E_VSCALE_HI);
1406 btwrite(0x20, BT848_O_VSCALE_HI);
1407 btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 BT848_ADC);
1409
1410 btwrite(whitecrush_upper, BT848_WC_UP);
1411 btwrite(whitecrush_lower, BT848_WC_DOWN);
1412
1413 if (btv->opt_lumafilter) {
1414 btwrite(0, BT848_E_CONTROL);
1415 btwrite(0, BT848_O_CONTROL);
1416 } else {
1417 btwrite(BT848_CONTROL_LDEC, BT848_E_CONTROL);
1418 btwrite(BT848_CONTROL_LDEC, BT848_O_CONTROL);
1419 }
1420
1421 bt848_bright(btv, btv->bright);
1422 bt848_hue(btv, btv->hue);
1423 bt848_contrast(btv, btv->contrast);
1424 bt848_sat(btv, btv->saturation);
1425
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001426 /* interrupt */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427 init_irqreg(btv);
1428}
1429
1430static void bttv_reinit_bt848(struct bttv *btv)
1431{
1432 unsigned long flags;
1433
1434 if (bttv_verbose)
1435 printk(KERN_INFO "bttv%d: reset, reinitialize\n",btv->c.nr);
1436 spin_lock_irqsave(&btv->s_lock,flags);
1437 btv->errors=0;
1438 bttv_set_dma(btv,0);
1439 spin_unlock_irqrestore(&btv->s_lock,flags);
1440
1441 init_bt848(btv);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001442 btv->pll.pll_current = -1;
Trent Piepho333408f2007-07-03 15:08:10 -03001443 set_input(btv, btv->input, btv->tvnorm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444}
1445
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001446static int bttv_g_ctrl(struct file *file, void *priv,
1447 struct v4l2_control *c)
1448{
1449 struct bttv_fh *fh = priv;
1450 struct bttv *btv = fh->btv;
1451
1452 switch (c->id) {
1453 case V4L2_CID_BRIGHTNESS:
1454 c->value = btv->bright;
1455 break;
1456 case V4L2_CID_HUE:
1457 c->value = btv->hue;
1458 break;
1459 case V4L2_CID_CONTRAST:
1460 c->value = btv->contrast;
1461 break;
1462 case V4L2_CID_SATURATION:
1463 c->value = btv->saturation;
1464 break;
1465
1466 case V4L2_CID_AUDIO_MUTE:
1467 case V4L2_CID_AUDIO_VOLUME:
1468 case V4L2_CID_AUDIO_BALANCE:
1469 case V4L2_CID_AUDIO_BASS:
1470 case V4L2_CID_AUDIO_TREBLE:
Hans Verkuil859f0272009-03-28 08:29:00 -03001471 bttv_call_all(btv, core, g_ctrl, c);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001472 break;
1473
1474 case V4L2_CID_PRIVATE_CHROMA_AGC:
1475 c->value = btv->opt_chroma_agc;
1476 break;
1477 case V4L2_CID_PRIVATE_COMBFILTER:
1478 c->value = btv->opt_combfilter;
1479 break;
1480 case V4L2_CID_PRIVATE_LUMAFILTER:
1481 c->value = btv->opt_lumafilter;
1482 break;
1483 case V4L2_CID_PRIVATE_AUTOMUTE:
1484 c->value = btv->opt_automute;
1485 break;
1486 case V4L2_CID_PRIVATE_AGC_CRUSH:
1487 c->value = btv->opt_adc_crush;
1488 break;
1489 case V4L2_CID_PRIVATE_VCR_HACK:
1490 c->value = btv->opt_vcr_hack;
1491 break;
1492 case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
1493 c->value = btv->opt_whitecrush_upper;
1494 break;
1495 case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
1496 c->value = btv->opt_whitecrush_lower;
1497 break;
1498 case V4L2_CID_PRIVATE_UV_RATIO:
1499 c->value = btv->opt_uv_ratio;
1500 break;
1501 case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
1502 c->value = btv->opt_full_luma_range;
1503 break;
1504 case V4L2_CID_PRIVATE_CORING:
1505 c->value = btv->opt_coring;
1506 break;
1507 default:
1508 return -EINVAL;
1509 }
1510 return 0;
1511}
1512
1513static int bttv_s_ctrl(struct file *file, void *f,
1514 struct v4l2_control *c)
1515{
1516 int err;
1517 int val;
1518 struct bttv_fh *fh = f;
1519 struct bttv *btv = fh->btv;
1520
Hans Verkuilffb48772010-05-01 08:03:24 -03001521 err = v4l2_prio_check(&btv->prio, fh->prio);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001522 if (0 != err)
1523 return err;
1524
1525 switch (c->id) {
1526 case V4L2_CID_BRIGHTNESS:
1527 bt848_bright(btv, c->value);
1528 break;
1529 case V4L2_CID_HUE:
1530 bt848_hue(btv, c->value);
1531 break;
1532 case V4L2_CID_CONTRAST:
1533 bt848_contrast(btv, c->value);
1534 break;
1535 case V4L2_CID_SATURATION:
1536 bt848_sat(btv, c->value);
1537 break;
1538 case V4L2_CID_AUDIO_MUTE:
1539 audio_mute(btv, c->value);
1540 /* fall through */
1541 case V4L2_CID_AUDIO_VOLUME:
1542 if (btv->volume_gpio)
1543 btv->volume_gpio(btv, c->value);
1544
Hans Verkuil859f0272009-03-28 08:29:00 -03001545 bttv_call_all(btv, core, s_ctrl, c);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001546 break;
1547 case V4L2_CID_AUDIO_BALANCE:
1548 case V4L2_CID_AUDIO_BASS:
1549 case V4L2_CID_AUDIO_TREBLE:
Hans Verkuil859f0272009-03-28 08:29:00 -03001550 bttv_call_all(btv, core, s_ctrl, c);
Mauro Carvalho Chehab04a94d32007-12-27 22:23:34 -03001551 break;
1552
1553 case V4L2_CID_PRIVATE_CHROMA_AGC:
1554 btv->opt_chroma_agc = c->value;
1555 val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
1556 btwrite(val, BT848_E_SCLOOP);
1557 btwrite(val, BT848_O_SCLOOP);
1558 break;
1559 case V4L2_CID_PRIVATE_COMBFILTER:
1560 btv->opt_combfilter = c->value;
1561 break;
1562 case V4L2_CID_PRIVATE_LUMAFILTER:
1563 btv->opt_lumafilter = c->value;
1564 if (btv->opt_lumafilter) {
1565 btand(~BT848_CONTROL_LDEC, BT848_E_CONTROL);
1566 btand(~BT848_CONTROL_LDEC, BT848_O_CONTROL);
1567 } else {
1568 btor(BT848_CONTROL_LDEC, BT848_E_CONTROL);
1569 btor(BT848_CONTROL_LDEC, BT848_O_CONTROL);
1570 }
1571 break;
1572 case V4L2_CID_PRIVATE_AUTOMUTE:
1573 btv->opt_automute = c->value;
1574 break;
1575 case V4L2_CID_PRIVATE_AGC_CRUSH:
1576 btv->opt_adc_crush = c->value;
1577 btwrite(BT848_ADC_RESERVED |
1578 (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
1579 BT848_ADC);
1580 break;
1581 case V4L2_CID_PRIVATE_VCR_HACK:
1582 btv->opt_vcr_hack = c->value;
1583 break;
1584 case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
1585 btv->opt_whitecrush_upper = c->value;
1586 btwrite(c->value, BT848_WC_UP);
1587 break;
1588 case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
1589 btv->opt_whitecrush_lower = c->value;
1590 btwrite(c->value, BT848_WC_DOWN);
1591 break;
1592 case V4L2_CID_PRIVATE_UV_RATIO:
1593 btv->opt_uv_ratio = c->value;
1594 bt848_sat(btv, btv->saturation);
1595 break;
1596 case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
1597 btv->opt_full_luma_range = c->value;
1598 btaor((c->value<<7), ~BT848_OFORM_RANGE, BT848_OFORM);
1599 break;
1600 case V4L2_CID_PRIVATE_CORING:
1601 btv->opt_coring = c->value;
1602 btaor((c->value<<5), ~BT848_OFORM_CORE32, BT848_OFORM);
1603 break;
1604 default:
1605 return -EINVAL;
1606 }
1607 return 0;
1608}
1609
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610/* ----------------------------------------------------------------------- */
1611
1612void bttv_gpio_tracking(struct bttv *btv, char *comment)
1613{
1614 unsigned int outbits, data;
1615 outbits = btread(BT848_GPIO_OUT_EN);
1616 data = btread(BT848_GPIO_DATA);
1617 printk(KERN_DEBUG "bttv%d: gpio: en=%08x, out=%08x in=%08x [%s]\n",
1618 btv->c.nr,outbits,data & outbits, data & ~outbits, comment);
1619}
1620
1621static void bttv_field_count(struct bttv *btv)
1622{
1623 int need_count = 0;
1624
1625 if (btv->users)
1626 need_count++;
1627
1628 if (need_count) {
1629 /* start field counter */
1630 btor(BT848_INT_VSYNC,BT848_INT_MASK);
1631 } else {
1632 /* stop field counter */
1633 btand(~BT848_INT_VSYNC,BT848_INT_MASK);
1634 btv->field_count = 0;
1635 }
1636}
1637
1638static const struct bttv_format*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639format_by_fourcc(int fourcc)
1640{
1641 unsigned int i;
1642
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001643 for (i = 0; i < FORMATS; i++) {
1644 if (-1 == formats[i].fourcc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645 continue;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001646 if (formats[i].fourcc == fourcc)
1647 return formats+i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648 }
1649 return NULL;
1650}
1651
1652/* ----------------------------------------------------------------------- */
1653/* misc helpers */
1654
1655static int
1656bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh,
1657 struct bttv_buffer *new)
1658{
1659 struct bttv_buffer *old;
1660 unsigned long flags;
1661 int retval = 0;
1662
1663 dprintk("switch_overlay: enter [new=%p]\n",new);
1664 if (new)
Brandon Philips0fc06862007-11-06 20:02:36 -03001665 new->vb.state = VIDEOBUF_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666 spin_lock_irqsave(&btv->s_lock,flags);
1667 old = btv->screen;
1668 btv->screen = new;
1669 btv->loop_irq |= 1;
1670 bttv_set_dma(btv, 0x03);
1671 spin_unlock_irqrestore(&btv->s_lock,flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672 if (NULL != old) {
1673 dprintk("switch_overlay: old=%p state is %d\n",old,old->vb.state);
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001674 bttv_dma_free(&fh->cap,btv, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675 kfree(old);
1676 }
Michael Schimeke5bd0262007-01-18 16:17:39 -03001677 if (NULL == new)
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03001678 free_btres_lock(btv,fh,RESOURCE_OVERLAY);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679 dprintk("switch_overlay: done\n");
1680 return retval;
1681}
1682
1683/* ----------------------------------------------------------------------- */
1684/* video4linux (1) interface */
1685
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001686static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv,
1687 struct bttv_buffer *buf,
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001688 const struct bttv_format *fmt,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689 unsigned int width, unsigned int height,
1690 enum v4l2_field field)
1691{
Michael Schimeke5bd0262007-01-18 16:17:39 -03001692 struct bttv_fh *fh = q->priv_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693 int redo_dma_risc = 0;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001694 struct bttv_crop c;
1695 int norm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 int rc;
1697
1698 /* check settings */
1699 if (NULL == fmt)
1700 return -EINVAL;
1701 if (fmt->btformat == BT848_COLOR_FMT_RAW) {
1702 width = RAW_BPL;
1703 height = RAW_LINES*2;
1704 if (width*height > buf->vb.bsize)
1705 return -EINVAL;
1706 buf->vb.size = buf->vb.bsize;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001707
1708 /* Make sure tvnorm and vbi_end remain consistent
1709 until we're done. */
Michael Schimeke5bd0262007-01-18 16:17:39 -03001710
1711 norm = btv->tvnorm;
1712
1713 /* In this mode capturing always starts at defrect.top
1714 (default VDELAY), ignoring cropping parameters. */
1715 if (btv->vbi_end > bttv_tvnorms[norm].cropcap.defrect.top) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 return -EINVAL;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001717 }
1718
Michael Schimeke5bd0262007-01-18 16:17:39 -03001719 c.rect = bttv_tvnorms[norm].cropcap.defrect;
1720 } else {
Michael Schimeke5bd0262007-01-18 16:17:39 -03001721 norm = btv->tvnorm;
1722 c = btv->crop[!!fh->do_crop];
1723
Michael Schimeke5bd0262007-01-18 16:17:39 -03001724 if (width < c.min_scaled_width ||
1725 width > c.max_scaled_width ||
1726 height < c.min_scaled_height)
1727 return -EINVAL;
1728
1729 switch (field) {
1730 case V4L2_FIELD_TOP:
1731 case V4L2_FIELD_BOTTOM:
1732 case V4L2_FIELD_ALTERNATE:
1733 /* btv->crop counts frame lines. Max. scale
1734 factor is 16:1 for frames, 8:1 for fields. */
1735 if (height * 2 > c.max_scaled_height)
1736 return -EINVAL;
1737 break;
1738
1739 default:
1740 if (height > c.max_scaled_height)
1741 return -EINVAL;
1742 break;
1743 }
1744
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745 buf->vb.size = (width * height * fmt->depth) >> 3;
1746 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
1747 return -EINVAL;
1748 }
1749
1750 /* alloc + fill struct bttv_buffer (if changed) */
1751 if (buf->vb.width != width || buf->vb.height != height ||
1752 buf->vb.field != field ||
Michael Schimeke5bd0262007-01-18 16:17:39 -03001753 buf->tvnorm != norm || buf->fmt != fmt ||
1754 buf->crop.top != c.rect.top ||
1755 buf->crop.left != c.rect.left ||
1756 buf->crop.width != c.rect.width ||
1757 buf->crop.height != c.rect.height) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758 buf->vb.width = width;
1759 buf->vb.height = height;
1760 buf->vb.field = field;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001761 buf->tvnorm = norm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762 buf->fmt = fmt;
Michael Schimeke5bd0262007-01-18 16:17:39 -03001763 buf->crop = c.rect;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764 redo_dma_risc = 1;
1765 }
1766
1767 /* alloc risc memory */
Brandon Philips0fc06862007-11-06 20:02:36 -03001768 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769 redo_dma_risc = 1;
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001770 if (0 != (rc = videobuf_iolock(q,&buf->vb,&btv->fbuf)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771 goto fail;
1772 }
1773
1774 if (redo_dma_risc)
1775 if (0 != (rc = bttv_buffer_risc(btv,buf)))
1776 goto fail;
1777
Brandon Philips0fc06862007-11-06 20:02:36 -03001778 buf->vb.state = VIDEOBUF_PREPARED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001779 return 0;
1780
1781 fail:
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001782 bttv_dma_free(q,btv,buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783 return rc;
1784}
1785
1786static int
1787buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
1788{
1789 struct bttv_fh *fh = q->priv_data;
1790
1791 *size = fh->fmt->depth*fh->width*fh->height >> 3;
1792 if (0 == *count)
1793 *count = gbuffers;
Andreas Bombedab7e312010-03-21 16:02:45 -03001794 if (*size * *count > gbuffers * gbufsize)
1795 *count = (gbuffers * gbufsize) / *size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796 return 0;
1797}
1798
1799static int
1800buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
1801 enum v4l2_field field)
1802{
1803 struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
1804 struct bttv_fh *fh = q->priv_data;
1805
Mauro Carvalho Chehabc7b0ac02006-03-10 12:29:15 -03001806 return bttv_prepare_buffer(q,fh->btv, buf, fh->fmt,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807 fh->width, fh->height, field);
1808}
1809
1810static void
1811buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
1812{
1813 struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
1814 struct bttv_fh *fh = q->priv_data;
1815 struct bttv *btv = fh->btv;
1816
Brandon Philips0fc06862007-11-06 20:02:36 -03001817 buf->vb.state = VIDEOBUF_QUEUED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818 list_add_tail(&buf->vb.queue,&btv->capture);
1819 if (!btv->curr.frame_irq) {
1820 btv->loop_irq |= 1;
1821 bttv_set_dma(btv, 0x03);
1822 }
1823}
1824
1825static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
1826{
1827 struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
1828 struct bttv_fh *fh = q->priv_data;
1829
Michael Schimekfeaba7a2007-01-26 08:30:05 -03001830 bttv_dma_free(q,fh->btv,buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831}
1832
1833static struct videobuf_queue_ops bttv_video_qops = {
1834 .buf_setup = buffer_setup,
1835 .buf_prepare = buffer_prepare,
1836 .buf_queue = buffer_queue,
1837 .buf_release = buffer_release,
1838};
1839
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001840static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001842 struct bttv_fh *fh = priv;
1843 struct bttv *btv = fh->btv;
1844 unsigned int i;
1845 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846
Hans Verkuilffb48772010-05-01 08:03:24 -03001847 err = v4l2_prio_check(&btv->prio, fh->prio);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001848 if (err)
1849 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001851 for (i = 0; i < BTTV_TVNORMS; i++)
1852 if (*id & bttv_tvnorms[i].v4l2_id)
1853 break;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001854 if (i == BTTV_TVNORMS) {
1855 err = -EINVAL;
1856 goto err;
1857 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001859 set_tvnorm(btv, i);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001860
1861err:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001863 return err;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001864}
1865
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001866static int bttv_querystd(struct file *file, void *f, v4l2_std_id *id)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001867{
1868 struct bttv_fh *fh = f;
1869 struct bttv *btv = fh->btv;
1870
1871 if (btread(BT848_DSTATUS) & BT848_DSTATUS_NUML)
1872 *id = V4L2_STD_625_50;
1873 else
1874 *id = V4L2_STD_525_60;
1875 return 0;
1876}
1877
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001878static int bttv_enum_input(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001879 struct v4l2_input *i)
1880{
1881 struct bttv_fh *fh = priv;
1882 struct bttv *btv = fh->btv;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001883 int rc = 0;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001884
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001885 if (i->index >= bttv_tvcards[btv->c.type].video_inputs) {
1886 rc = -EINVAL;
1887 goto err;
1888 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001889
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001890 i->type = V4L2_INPUT_TYPE_CAMERA;
1891 i->audioset = 1;
1892
Trent Piephoabb03622009-01-28 21:32:59 -03001893 if (btv->tuner_type != TUNER_ABSENT && i->index == 0) {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001894 sprintf(i->name, "Television");
1895 i->type = V4L2_INPUT_TYPE_TUNER;
1896 i->tuner = 0;
1897 } else if (i->index == btv->svhs) {
1898 sprintf(i->name, "S-Video");
1899 } else {
1900 sprintf(i->name, "Composite%d", i->index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901 }
1902
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001903 if (i->index == btv->input) {
1904 __u32 dstatus = btread(BT848_DSTATUS);
1905 if (0 == (dstatus & BT848_DSTATUS_PRES))
1906 i->status |= V4L2_IN_ST_NO_SIGNAL;
1907 if (0 == (dstatus & BT848_DSTATUS_HLOC))
1908 i->status |= V4L2_IN_ST_NO_H_LOCK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909 }
1910
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001911 i->std = BTTV_NORMS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001913err:
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001914
1915 return rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001916}
Nickolay V. Shmyrev4b9b9362006-08-25 16:53:04 -03001917
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001918static int bttv_g_input(struct file *file, void *priv, unsigned int *i)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001919{
1920 struct bttv_fh *fh = priv;
1921 struct bttv *btv = fh->btv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001923 *i = btv->input;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001924
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001925 return 0;
1926}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001928static int bttv_s_input(struct file *file, void *priv, unsigned int i)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001929{
1930 struct bttv_fh *fh = priv;
1931 struct bttv *btv = fh->btv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001933 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001935 err = v4l2_prio_check(&btv->prio, fh->prio);
1936 if (unlikely(err))
1937 goto err;
1938
1939 if (i > bttv_tvcards[btv->c.type].video_inputs) {
1940 err = -EINVAL;
1941 goto err;
1942 }
1943
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001944 set_input(btv, i, btv->tvnorm);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001945
1946err:
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001947 return 0;
1948}
1949
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001950static int bttv_s_tuner(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001951 struct v4l2_tuner *t)
1952{
1953 struct bttv_fh *fh = priv;
1954 struct bttv *btv = fh->btv;
1955 int err;
1956
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001957 if (unlikely(0 != t->index))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001958 return -EINVAL;
1959
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001960 if (unlikely(btv->tuner_type == TUNER_ABSENT)) {
1961 err = -EINVAL;
1962 goto err;
1963 }
1964
1965 err = v4l2_prio_check(&btv->prio, fh->prio);
1966 if (unlikely(err))
1967 goto err;
1968
Hans Verkuil859f0272009-03-28 08:29:00 -03001969 bttv_call_all(btv, tuner, s_tuner, t);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001970
1971 if (btv->audio_mode_gpio)
1972 btv->audio_mode_gpio(btv, t, 1);
1973
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03001974err:
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001975
1976 return 0;
1977}
1978
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001979static int bttv_g_frequency(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001980 struct v4l2_frequency *f)
1981{
1982 struct bttv_fh *fh = priv;
1983 struct bttv *btv = fh->btv;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001984
Robert Fitzsimons1b069012008-04-01 11:41:54 -03001985 f->type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001986 f->frequency = btv->freq;
1987
1988 return 0;
1989}
1990
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03001991static int bttv_s_frequency(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001992 struct v4l2_frequency *f)
1993{
1994 struct bttv_fh *fh = priv;
1995 struct bttv *btv = fh->btv;
1996 int err;
1997
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03001998 if (unlikely(f->tuner != 0))
1999 return -EINVAL;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002000
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002001 err = v4l2_prio_check(&btv->prio, fh->prio);
2002 if (unlikely(err))
2003 goto err;
2004
2005 if (unlikely(f->type != (btv->radio_user
2006 ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV))) {
2007 err = -EINVAL;
2008 goto err;
2009 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002010 btv->freq = f->frequency;
Hans Verkuil859f0272009-03-28 08:29:00 -03002011 bttv_call_all(btv, tuner, s_frequency, f);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002012 if (btv->has_matchbox && btv->radio_user)
2013 tea5757_set_freq(btv, btv->freq);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002014err:
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002015
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002016 return 0;
2017}
2018
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002019static int bttv_log_status(struct file *file, void *f)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002020{
2021 struct bttv_fh *fh = f;
2022 struct bttv *btv = fh->btv;
2023
2024 printk(KERN_INFO "bttv%d: ======== START STATUS CARD #%d ========\n",
2025 btv->c.nr, btv->c.nr);
Hans Verkuil859f0272009-03-28 08:29:00 -03002026 bttv_call_all(btv, core, log_status);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002027 printk(KERN_INFO "bttv%d: ======== END STATUS CARD #%d ========\n",
2028 btv->c.nr, btv->c.nr);
2029 return 0;
2030}
2031
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002032#ifdef CONFIG_VIDEO_ADV_DEBUG
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002033static int bttv_g_register(struct file *file, void *f,
Hans Verkuilaecde8b2008-12-30 07:14:19 -03002034 struct v4l2_dbg_register *reg)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002035{
2036 struct bttv_fh *fh = f;
2037 struct bttv *btv = fh->btv;
2038
2039 if (!capable(CAP_SYS_ADMIN))
2040 return -EPERM;
2041
Hans Verkuilaecde8b2008-12-30 07:14:19 -03002042 if (!v4l2_chip_match_host(&reg->match))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002043 return -EINVAL;
2044
2045 /* bt848 has a 12-bit register space */
2046 reg->reg &= 0xfff;
2047 reg->val = btread(reg->reg);
Hans Verkuilaecde8b2008-12-30 07:14:19 -03002048 reg->size = 1;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002049
2050 return 0;
2051}
2052
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002053static int bttv_s_register(struct file *file, void *f,
Hans Verkuilaecde8b2008-12-30 07:14:19 -03002054 struct v4l2_dbg_register *reg)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002055{
2056 struct bttv_fh *fh = f;
2057 struct bttv *btv = fh->btv;
2058
2059 if (!capable(CAP_SYS_ADMIN))
2060 return -EPERM;
2061
Hans Verkuilaecde8b2008-12-30 07:14:19 -03002062 if (!v4l2_chip_match_host(&reg->match))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002063 return -EINVAL;
2064
2065 /* bt848 has a 12-bit register space */
2066 reg->reg &= 0xfff;
2067 btwrite(reg->val, reg->reg);
2068
2069 return 0;
2070}
2071#endif
2072
Michael Schimeke5bd0262007-01-18 16:17:39 -03002073/* Given cropping boundaries b and the scaled width and height of a
2074 single field or frame, which must not exceed hardware limits, this
2075 function adjusts the cropping parameters c. */
2076static void
2077bttv_crop_adjust (struct bttv_crop * c,
2078 const struct v4l2_rect * b,
2079 __s32 width,
2080 __s32 height,
2081 enum v4l2_field field)
2082{
2083 __s32 frame_height = height << !V4L2_FIELD_HAS_BOTH(field);
2084 __s32 max_left;
2085 __s32 max_top;
2086
2087 if (width < c->min_scaled_width) {
2088 /* Max. hor. scale factor 16:1. */
2089 c->rect.width = width * 16;
2090 } else if (width > c->max_scaled_width) {
2091 /* Min. hor. scale factor 1:1. */
2092 c->rect.width = width;
2093
2094 max_left = b->left + b->width - width;
2095 max_left = min(max_left, (__s32) MAX_HDELAY);
2096 if (c->rect.left > max_left)
2097 c->rect.left = max_left;
2098 }
2099
2100 if (height < c->min_scaled_height) {
2101 /* Max. vert. scale factor 16:1, single fields 8:1. */
2102 c->rect.height = height * 16;
2103 } else if (frame_height > c->max_scaled_height) {
2104 /* Min. vert. scale factor 1:1.
2105 Top and height count field lines times two. */
2106 c->rect.height = (frame_height + 1) & ~1;
2107
2108 max_top = b->top + b->height - c->rect.height;
2109 if (c->rect.top > max_top)
2110 c->rect.top = max_top;
2111 }
2112
2113 bttv_crop_calc_limits(c);
2114}
2115
2116/* Returns an error if scaling to a frame or single field with the given
2117 width and height is not possible with the current cropping parameters
2118 and width aligned according to width_mask. If adjust_size is TRUE the
2119 function may adjust the width and/or height instead, rounding width
2120 to (width + width_bias) & width_mask. If adjust_crop is TRUE it may
2121 also adjust the current cropping parameters to get closer to the
2122 desired image size. */
2123static int
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002124limit_scaled_size_lock (struct bttv_fh * fh,
Michael Schimeke5bd0262007-01-18 16:17:39 -03002125 __s32 * width,
2126 __s32 * height,
2127 enum v4l2_field field,
2128 unsigned int width_mask,
2129 unsigned int width_bias,
2130 int adjust_size,
2131 int adjust_crop)
2132{
2133 struct bttv *btv = fh->btv;
2134 const struct v4l2_rect *b;
2135 struct bttv_crop *c;
2136 __s32 min_width;
2137 __s32 min_height;
2138 __s32 max_width;
2139 __s32 max_height;
2140 int rc;
2141
2142 BUG_ON((int) width_mask >= 0 ||
2143 width_bias >= (unsigned int) -width_mask);
2144
2145 /* Make sure tvnorm, vbi_end and the current cropping parameters
2146 remain consistent until we're done. */
Michael Schimeke5bd0262007-01-18 16:17:39 -03002147
2148 b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
2149
2150 /* Do crop - use current, don't - use default parameters. */
2151 c = &btv->crop[!!fh->do_crop];
2152
2153 if (fh->do_crop
2154 && adjust_size
2155 && adjust_crop
2156 && !locked_btres(btv, VIDEO_RESOURCES)) {
2157 min_width = 48;
2158 min_height = 32;
2159
2160 /* We cannot scale up. When the scaled image is larger
2161 than crop.rect we adjust the crop.rect as required
2162 by the V4L2 spec, hence cropcap.bounds are our limit. */
2163 max_width = min(b->width, (__s32) MAX_HACTIVE);
2164 max_height = b->height;
2165
2166 /* We cannot capture the same line as video and VBI data.
2167 Note btv->vbi_end is really a minimum, see
2168 bttv_vbi_try_fmt(). */
2169 if (btv->vbi_end > b->top) {
2170 max_height -= btv->vbi_end - b->top;
2171 rc = -EBUSY;
2172 if (min_height > max_height)
2173 goto fail;
2174 }
2175 } else {
2176 rc = -EBUSY;
2177 if (btv->vbi_end > c->rect.top)
2178 goto fail;
2179
2180 min_width = c->min_scaled_width;
2181 min_height = c->min_scaled_height;
2182 max_width = c->max_scaled_width;
2183 max_height = c->max_scaled_height;
2184
2185 adjust_crop = 0;
2186 }
2187
2188 min_width = (min_width - width_mask - 1) & width_mask;
2189 max_width = max_width & width_mask;
2190
2191 /* Max. scale factor is 16:1 for frames, 8:1 for fields. */
2192 min_height = min_height;
2193 /* Min. scale factor is 1:1. */
2194 max_height >>= !V4L2_FIELD_HAS_BOTH(field);
2195
2196 if (adjust_size) {
2197 *width = clamp(*width, min_width, max_width);
2198 *height = clamp(*height, min_height, max_height);
2199
2200 /* Round after clamping to avoid overflow. */
2201 *width = (*width + width_bias) & width_mask;
2202
2203 if (adjust_crop) {
2204 bttv_crop_adjust(c, b, *width, *height, field);
2205
2206 if (btv->vbi_end > c->rect.top) {
2207 /* Move the crop window out of the way. */
2208 c->rect.top = btv->vbi_end;
2209 }
2210 }
2211 } else {
2212 rc = -EINVAL;
2213 if (*width < min_width ||
2214 *height < min_height ||
2215 *width > max_width ||
2216 *height > max_height ||
2217 0 != (*width & ~width_mask))
2218 goto fail;
2219 }
2220
2221 rc = 0; /* success */
2222
2223 fail:
Michael Schimeke5bd0262007-01-18 16:17:39 -03002224
2225 return rc;
2226}
2227
2228/* Returns an error if the given overlay window dimensions are not
2229 possible with the current cropping parameters. If adjust_size is
2230 TRUE the function may adjust the window width and/or height
2231 instead, however it always rounds the horizontal position and
2232 width as btcx_align() does. If adjust_crop is TRUE the function
2233 may also adjust the current cropping parameters to get closer
2234 to the desired window size. */
2235static int
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002236verify_window_lock (struct bttv_fh * fh,
Michael Schimeke5bd0262007-01-18 16:17:39 -03002237 struct v4l2_window * win,
2238 int adjust_size,
2239 int adjust_crop)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240{
2241 enum v4l2_field field;
Michael Schimeke5bd0262007-01-18 16:17:39 -03002242 unsigned int width_mask;
2243 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244
2245 if (win->w.width < 48 || win->w.height < 32)
2246 return -EINVAL;
2247 if (win->clipcount > 2048)
2248 return -EINVAL;
2249
2250 field = win->field;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251
2252 if (V4L2_FIELD_ANY == field) {
Michael Schimeke5bd0262007-01-18 16:17:39 -03002253 __s32 height2;
2254
2255 height2 = fh->btv->crop[!!fh->do_crop].rect.height >> 1;
2256 field = (win->w.height > height2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257 ? V4L2_FIELD_INTERLACED
2258 : V4L2_FIELD_TOP;
2259 }
2260 switch (field) {
2261 case V4L2_FIELD_TOP:
2262 case V4L2_FIELD_BOTTOM:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263 case V4L2_FIELD_INTERLACED:
2264 break;
2265 default:
2266 return -EINVAL;
2267 }
2268
Michael Schimeke5bd0262007-01-18 16:17:39 -03002269 /* 4-byte alignment. */
2270 if (NULL == fh->ovfmt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002271 return -EINVAL;
Michael Schimeke5bd0262007-01-18 16:17:39 -03002272 width_mask = ~0;
2273 switch (fh->ovfmt->depth) {
2274 case 8:
2275 case 24:
2276 width_mask = ~3;
2277 break;
2278 case 16:
2279 width_mask = ~1;
2280 break;
2281 case 32:
2282 break;
2283 default:
2284 BUG();
2285 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286
Michael Schimeke5bd0262007-01-18 16:17:39 -03002287 win->w.width -= win->w.left & ~width_mask;
2288 win->w.left = (win->w.left - width_mask - 1) & width_mask;
2289
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002290 rc = limit_scaled_size_lock(fh, &win->w.width, &win->w.height,
Michael Schimeke5bd0262007-01-18 16:17:39 -03002291 field, width_mask,
2292 /* width_bias: round down */ 0,
2293 adjust_size, adjust_crop);
2294 if (0 != rc)
2295 return rc;
2296
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297 win->field = field;
2298 return 0;
2299}
2300
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002301static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302 struct v4l2_window *win, int fixup)
2303{
2304 struct v4l2_clip *clips = NULL;
2305 int n,size,retval = 0;
2306
2307 if (NULL == fh->ovfmt)
2308 return -EINVAL;
2309 if (!(fh->ovfmt->flags & FORMAT_FLAGS_PACKED))
2310 return -EINVAL;
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002311 retval = verify_window_lock(fh, win,
Michael Schimeke5bd0262007-01-18 16:17:39 -03002312 /* adjust_size */ fixup,
2313 /* adjust_crop */ fixup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314 if (0 != retval)
2315 return retval;
2316
2317 /* copy clips -- luckily v4l1 + v4l2 are binary
2318 compatible here ...*/
2319 n = win->clipcount;
2320 size = sizeof(*clips)*(n+4);
2321 clips = kmalloc(size,GFP_KERNEL);
2322 if (NULL == clips)
2323 return -ENOMEM;
2324 if (n > 0) {
2325 if (copy_from_user(clips,win->clips,sizeof(struct v4l2_clip)*n)) {
2326 kfree(clips);
2327 return -EFAULT;
2328 }
2329 }
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002330
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331 /* clip against screen */
2332 if (NULL != btv->fbuf.base)
2333 n = btcx_screen_clips(btv->fbuf.fmt.width, btv->fbuf.fmt.height,
2334 &win->w, clips, n);
2335 btcx_sort_clips(clips,n);
2336
2337 /* 4-byte alignments */
2338 switch (fh->ovfmt->depth) {
2339 case 8:
2340 case 24:
2341 btcx_align(&win->w, clips, n, 3);
2342 break;
2343 case 16:
2344 btcx_align(&win->w, clips, n, 1);
2345 break;
2346 case 32:
2347 /* no alignment fixups needed */
2348 break;
2349 default:
2350 BUG();
2351 }
2352
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03002353 kfree(fh->ov.clips);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354 fh->ov.clips = clips;
2355 fh->ov.nclips = n;
2356
2357 fh->ov.w = win->w;
2358 fh->ov.field = win->field;
2359 fh->ov.setup_ok = 1;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002360
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361 btv->init.ov.w.width = win->w.width;
2362 btv->init.ov.w.height = win->w.height;
2363 btv->init.ov.field = win->field;
2364
2365 /* update overlay if needed */
2366 retval = 0;
2367 if (check_btres(fh, RESOURCE_OVERLAY)) {
2368 struct bttv_buffer *new;
2369
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03002370 new = videobuf_sg_alloc(sizeof(*new));
Michael Schimeke5bd0262007-01-18 16:17:39 -03002371 new->crop = btv->crop[!!fh->do_crop].rect;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372 bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
2373 retval = bttv_switch_overlay(btv,fh,new);
2374 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375 return retval;
2376}
2377
2378/* ----------------------------------------------------------------------- */
2379
2380static struct videobuf_queue* bttv_queue(struct bttv_fh *fh)
2381{
2382 struct videobuf_queue* q = NULL;
2383
2384 switch (fh->type) {
2385 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2386 q = &fh->cap;
2387 break;
2388 case V4L2_BUF_TYPE_VBI_CAPTURE:
2389 q = &fh->vbi;
2390 break;
2391 default:
2392 BUG();
2393 }
2394 return q;
2395}
2396
2397static int bttv_resource(struct bttv_fh *fh)
2398{
2399 int res = 0;
2400
2401 switch (fh->type) {
2402 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Michael Schimeke5bd0262007-01-18 16:17:39 -03002403 res = RESOURCE_VIDEO_STREAM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404 break;
2405 case V4L2_BUF_TYPE_VBI_CAPTURE:
2406 res = RESOURCE_VBI;
2407 break;
2408 default:
2409 BUG();
2410 }
2411 return res;
2412}
2413
2414static int bttv_switch_type(struct bttv_fh *fh, enum v4l2_buf_type type)
2415{
2416 struct videobuf_queue *q = bttv_queue(fh);
2417 int res = bttv_resource(fh);
2418
2419 if (check_btres(fh,res))
2420 return -EBUSY;
2421 if (videobuf_queue_is_busy(q))
2422 return -EBUSY;
2423 fh->type = type;
2424 return 0;
2425}
2426
Michael H. Schimekc87c9482005-12-01 00:51:33 -08002427static void
2428pix_format_set_size (struct v4l2_pix_format * f,
2429 const struct bttv_format * fmt,
2430 unsigned int width,
2431 unsigned int height)
2432{
2433 f->width = width;
2434 f->height = height;
2435
2436 if (fmt->flags & FORMAT_FLAGS_PLANAR) {
2437 f->bytesperline = width; /* Y plane */
2438 f->sizeimage = (width * height * fmt->depth) >> 3;
2439 } else {
2440 f->bytesperline = (width * fmt->depth) >> 3;
2441 f->sizeimage = height * f->bytesperline;
2442 }
2443}
2444
Hans Verkuil78b526a2008-05-28 12:16:41 -03002445static int bttv_g_fmt_vid_cap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002446 struct v4l2_format *f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002448 struct bttv_fh *fh = priv;
2449
2450 pix_format_set_size(&f->fmt.pix, fh->fmt,
2451 fh->width, fh->height);
2452 f->fmt.pix.field = fh->cap.field;
2453 f->fmt.pix.pixelformat = fh->fmt->fourcc;
2454
2455 return 0;
2456}
2457
Hans Verkuil78b526a2008-05-28 12:16:41 -03002458static int bttv_g_fmt_vid_overlay(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002459 struct v4l2_format *f)
2460{
2461 struct bttv_fh *fh = priv;
2462
2463 f->fmt.win.w = fh->ov.w;
2464 f->fmt.win.field = fh->ov.field;
2465
2466 return 0;
2467}
2468
Hans Verkuil78b526a2008-05-28 12:16:41 -03002469static int bttv_try_fmt_vid_cap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002470 struct v4l2_format *f)
2471{
2472 const struct bttv_format *fmt;
2473 struct bttv_fh *fh = priv;
2474 struct bttv *btv = fh->btv;
2475 enum v4l2_field field;
2476 __s32 width, height;
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002477 int rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002478
2479 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
2480 if (NULL == fmt)
2481 return -EINVAL;
2482
2483 field = f->fmt.pix.field;
2484
2485 if (V4L2_FIELD_ANY == field) {
2486 __s32 height2;
2487
2488 height2 = btv->crop[!!fh->do_crop].rect.height >> 1;
2489 field = (f->fmt.pix.height > height2)
2490 ? V4L2_FIELD_INTERLACED
2491 : V4L2_FIELD_BOTTOM;
2492 }
2493
2494 if (V4L2_FIELD_SEQ_BT == field)
2495 field = V4L2_FIELD_SEQ_TB;
2496
2497 switch (field) {
2498 case V4L2_FIELD_TOP:
2499 case V4L2_FIELD_BOTTOM:
2500 case V4L2_FIELD_ALTERNATE:
2501 case V4L2_FIELD_INTERLACED:
2502 break;
2503 case V4L2_FIELD_SEQ_TB:
2504 if (fmt->flags & FORMAT_FLAGS_PLANAR)
2505 return -EINVAL;
2506 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002507 default:
2508 return -EINVAL;
2509 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002510
2511 width = f->fmt.pix.width;
2512 height = f->fmt.pix.height;
2513
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002514 rc = limit_scaled_size_lock(fh, &width, &height, field,
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002515 /* width_mask: 4 pixels */ ~3,
2516 /* width_bias: nearest */ 2,
2517 /* adjust_size */ 1,
2518 /* adjust_crop */ 0);
2519 if (0 != rc)
2520 return rc;
2521
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002522 /* update data for the application */
2523 f->fmt.pix.field = field;
2524 pix_format_set_size(&f->fmt.pix, fmt, width, height);
2525
2526 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002527}
2528
Hans Verkuil78b526a2008-05-28 12:16:41 -03002529static int bttv_try_fmt_vid_overlay(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002530 struct v4l2_format *f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002531{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002532 struct bttv_fh *fh = priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002533
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002534 return verify_window_lock(fh, &f->fmt.win,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002535 /* adjust_size */ 1,
2536 /* adjust_crop */ 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002537}
2538
Hans Verkuil78b526a2008-05-28 12:16:41 -03002539static int bttv_s_fmt_vid_cap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002540 struct v4l2_format *f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541{
2542 int retval;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002543 const struct bttv_format *fmt;
2544 struct bttv_fh *fh = priv;
2545 struct bttv *btv = fh->btv;
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002546 __s32 width, height;
2547 enum v4l2_field field;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002549 retval = bttv_switch_type(fh, f->type);
2550 if (0 != retval)
2551 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002552
Hans Verkuil78b526a2008-05-28 12:16:41 -03002553 retval = bttv_try_fmt_vid_cap(file, priv, f);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002554 if (0 != retval)
2555 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002556
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002557 width = f->fmt.pix.width;
2558 height = f->fmt.pix.height;
2559 field = f->fmt.pix.field;
2560
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002561 retval = limit_scaled_size_lock(fh, &width, &height, f->fmt.pix.field,
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002562 /* width_mask: 4 pixels */ ~3,
2563 /* width_bias: nearest */ 2,
2564 /* adjust_size */ 1,
2565 /* adjust_crop */ 1);
2566 if (0 != retval)
2567 return retval;
2568
2569 f->fmt.pix.field = field;
2570
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002571 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002572
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002573 /* update our state informations */
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002574 fh->fmt = fmt;
2575 fh->cap.field = f->fmt.pix.field;
2576 fh->cap.last = V4L2_FIELD_NONE;
2577 fh->width = f->fmt.pix.width;
2578 fh->height = f->fmt.pix.height;
2579 btv->init.fmt = fmt;
2580 btv->init.width = f->fmt.pix.width;
2581 btv->init.height = f->fmt.pix.height;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002582
2583 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584}
2585
Hans Verkuil78b526a2008-05-28 12:16:41 -03002586static int bttv_s_fmt_vid_overlay(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002587 struct v4l2_format *f)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002588{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002589 struct bttv_fh *fh = priv;
2590 struct bttv *btv = fh->btv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002591
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002592 if (no_overlay > 0) {
2593 printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002594 return -EINVAL;
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002595 }
Michael Krufky5e453dc2006-01-09 15:32:31 -02002596
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002597 return setup_window_lock(fh, btv, &f->fmt.win, 1);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002598}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002599
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002600static int bttv_querycap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002601 struct v4l2_capability *cap)
2602{
2603 struct bttv_fh *fh = priv;
2604 struct bttv *btv = fh->btv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002605
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002606 if (0 == v4l2)
2607 return -EINVAL;
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07002608
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002609 strlcpy(cap->driver, "bttv", sizeof(cap->driver));
2610 strlcpy(cap->card, btv->video_dev->name, sizeof(cap->card));
2611 snprintf(cap->bus_info, sizeof(cap->bus_info),
2612 "PCI:%s", pci_name(btv->c.pci));
2613 cap->version = BTTV_VERSION_CODE;
2614 cap->capabilities =
2615 V4L2_CAP_VIDEO_CAPTURE |
2616 V4L2_CAP_VBI_CAPTURE |
2617 V4L2_CAP_READWRITE |
2618 V4L2_CAP_STREAMING;
2619 if (no_overlay <= 0)
2620 cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002622 /*
2623 * No need to lock here: those vars are initialized during board
2624 * probe and remains untouched during the rest of the driver lifecycle
2625 */
2626 if (btv->has_saa6588)
2627 cap->capabilities |= V4L2_CAP_RDS_CAPTURE;
Trent Piephoabb03622009-01-28 21:32:59 -03002628 if (btv->tuner_type != TUNER_ABSENT)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002629 cap->capabilities |= V4L2_CAP_TUNER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630 return 0;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002631}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002633static int bttv_enum_fmt_cap_ovr(struct v4l2_fmtdesc *f)
2634{
2635 int index = -1, i;
2636
2637 for (i = 0; i < FORMATS; i++) {
2638 if (formats[i].fourcc != -1)
2639 index++;
2640 if ((unsigned int)index == f->index)
2641 break;
2642 }
2643 if (FORMATS == i)
2644 return -EINVAL;
2645
2646 f->pixelformat = formats[i].fourcc;
2647 strlcpy(f->description, formats[i].name, sizeof(f->description));
2648
2649 return i;
2650}
2651
Hans Verkuil78b526a2008-05-28 12:16:41 -03002652static int bttv_enum_fmt_vid_cap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002653 struct v4l2_fmtdesc *f)
2654{
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002655 int rc = bttv_enum_fmt_cap_ovr(f);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002656
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002657 if (rc < 0)
2658 return rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002659
2660 return 0;
2661}
2662
Hans Verkuil78b526a2008-05-28 12:16:41 -03002663static int bttv_enum_fmt_vid_overlay(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002664 struct v4l2_fmtdesc *f)
2665{
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002666 int rc;
2667
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002668 if (no_overlay > 0) {
2669 printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
2670 return -EINVAL;
2671 }
2672
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002673 rc = bttv_enum_fmt_cap_ovr(f);
2674
2675 if (rc < 0)
2676 return rc;
2677
2678 if (!(formats[rc].flags & FORMAT_FLAGS_PACKED))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002679 return -EINVAL;
2680
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002681 return 0;
2682}
2683
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002684static int bttv_g_fbuf(struct file *file, void *f,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002685 struct v4l2_framebuffer *fb)
2686{
2687 struct bttv_fh *fh = f;
2688 struct bttv *btv = fh->btv;
2689
2690 *fb = btv->fbuf;
2691 fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
2692 if (fh->ovfmt)
2693 fb->fmt.pixelformat = fh->ovfmt->fourcc;
2694 return 0;
2695}
2696
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002697static int bttv_overlay(struct file *file, void *f, unsigned int on)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002698{
2699 struct bttv_fh *fh = f;
2700 struct bttv *btv = fh->btv;
2701 struct bttv_buffer *new;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002702 int retval = 0;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002703
2704 if (on) {
2705 /* verify args */
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002706 if (unlikely(!btv->fbuf.base)) {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002707 return -EINVAL;
2708 }
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002709 if (unlikely(!fh->ov.setup_ok)) {
2710 dprintk("bttv%d: overlay: !setup_ok\n", btv->c.nr);
2711 retval = -EINVAL;
2712 }
2713 if (retval)
2714 return retval;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002715 }
2716
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002717 if (!check_alloc_btres_lock(btv, fh, RESOURCE_OVERLAY))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002718 return -EBUSY;
2719
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002720 if (on) {
2721 fh->ov.tvnorm = btv->tvnorm;
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03002722 new = videobuf_sg_alloc(sizeof(*new));
Robert Fitzsimons7c018802008-02-13 16:38:11 -03002723 new->crop = btv->crop[!!fh->do_crop].rect;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002724 bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
2725 } else {
2726 new = NULL;
2727 }
2728
2729 /* switch over */
2730 retval = bttv_switch_overlay(btv, fh, new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731 return retval;
2732}
2733
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002734static int bttv_s_fbuf(struct file *file, void *f,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002735 struct v4l2_framebuffer *fb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002737 struct bttv_fh *fh = f;
2738 struct bttv *btv = fh->btv;
2739 const struct bttv_format *fmt;
2740 int retval;
2741
2742 if (!capable(CAP_SYS_ADMIN) &&
2743 !capable(CAP_SYS_RAWIO))
2744 return -EPERM;
2745
2746 /* check args */
2747 fmt = format_by_fourcc(fb->fmt.pixelformat);
2748 if (NULL == fmt)
2749 return -EINVAL;
2750 if (0 == (fmt->flags & FORMAT_FLAGS_PACKED))
2751 return -EINVAL;
2752
2753 retval = -EINVAL;
2754 if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
2755 __s32 width = fb->fmt.width;
2756 __s32 height = fb->fmt.height;
2757
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002758 retval = limit_scaled_size_lock(fh, &width, &height,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002759 V4L2_FIELD_INTERLACED,
2760 /* width_mask */ ~3,
2761 /* width_bias */ 2,
2762 /* adjust_size */ 0,
2763 /* adjust_crop */ 0);
2764 if (0 != retval)
2765 return retval;
2766 }
2767
2768 /* ok, accept it */
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002769 btv->fbuf.base = fb->base;
2770 btv->fbuf.fmt.width = fb->fmt.width;
2771 btv->fbuf.fmt.height = fb->fmt.height;
2772 if (0 != fb->fmt.bytesperline)
2773 btv->fbuf.fmt.bytesperline = fb->fmt.bytesperline;
2774 else
2775 btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fmt->depth/8;
2776
2777 retval = 0;
2778 fh->ovfmt = fmt;
2779 btv->init.ovfmt = fmt;
2780 if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
2781 fh->ov.w.left = 0;
2782 fh->ov.w.top = 0;
2783 fh->ov.w.width = fb->fmt.width;
2784 fh->ov.w.height = fb->fmt.height;
2785 btv->init.ov.w.width = fb->fmt.width;
2786 btv->init.ov.w.height = fb->fmt.height;
2787 kfree(fh->ov.clips);
2788 fh->ov.clips = NULL;
2789 fh->ov.nclips = 0;
2790
2791 if (check_btres(fh, RESOURCE_OVERLAY)) {
2792 struct bttv_buffer *new;
2793
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03002794 new = videobuf_sg_alloc(sizeof(*new));
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002795 new->crop = btv->crop[!!fh->do_crop].rect;
2796 bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
2797 retval = bttv_switch_overlay(btv, fh, new);
2798 }
2799 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002800 return retval;
2801}
2802
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002803static int bttv_reqbufs(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002804 struct v4l2_requestbuffers *p)
2805{
2806 struct bttv_fh *fh = priv;
2807 return videobuf_reqbufs(bttv_queue(fh), p);
2808}
2809
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002810static int bttv_querybuf(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002811 struct v4l2_buffer *b)
2812{
2813 struct bttv_fh *fh = priv;
2814 return videobuf_querybuf(bttv_queue(fh), b);
2815}
2816
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002817static int bttv_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002818{
2819 struct bttv_fh *fh = priv;
2820 struct bttv *btv = fh->btv;
2821 int res = bttv_resource(fh);
2822
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002823 if (!check_alloc_btres_lock(btv, fh, res))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002824 return -EBUSY;
2825
2826 return videobuf_qbuf(bttv_queue(fh), b);
2827}
2828
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002829static int bttv_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002830{
2831 struct bttv_fh *fh = priv;
2832 return videobuf_dqbuf(bttv_queue(fh), b,
2833 file->f_flags & O_NONBLOCK);
2834}
2835
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002836static int bttv_streamon(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002837 enum v4l2_buf_type type)
2838{
2839 struct bttv_fh *fh = priv;
2840 struct bttv *btv = fh->btv;
2841 int res = bttv_resource(fh);
2842
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002843 if (!check_alloc_btres_lock(btv, fh, res))
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002844 return -EBUSY;
2845 return videobuf_streamon(bttv_queue(fh));
2846}
2847
2848
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002849static int bttv_streamoff(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002850 enum v4l2_buf_type type)
2851{
2852 struct bttv_fh *fh = priv;
2853 struct bttv *btv = fh->btv;
2854 int retval;
2855 int res = bttv_resource(fh);
2856
2857
2858 retval = videobuf_streamoff(bttv_queue(fh));
2859 if (retval < 0)
2860 return retval;
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002861 free_btres_lock(btv, fh, res);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002862 return 0;
2863}
2864
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002865static int bttv_queryctrl(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002866 struct v4l2_queryctrl *c)
2867{
2868 struct bttv_fh *fh = priv;
2869 struct bttv *btv = fh->btv;
2870 const struct v4l2_queryctrl *ctrl;
2871
2872 if ((c->id < V4L2_CID_BASE ||
2873 c->id >= V4L2_CID_LASTP1) &&
2874 (c->id < V4L2_CID_PRIVATE_BASE ||
2875 c->id >= V4L2_CID_PRIVATE_LASTP1))
2876 return -EINVAL;
2877
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002878 if (!btv->volume_gpio && (c->id == V4L2_CID_AUDIO_VOLUME))
2879 *c = no_ctl;
2880 else {
2881 ctrl = ctrl_by_id(c->id);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002882
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03002883 *c = (NULL != ctrl) ? *ctrl : no_ctl;
2884 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002885
2886 return 0;
2887}
2888
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002889static int bttv_g_parm(struct file *file, void *f,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002890 struct v4l2_streamparm *parm)
2891{
2892 struct bttv_fh *fh = f;
2893 struct bttv *btv = fh->btv;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002894
Trent Piepho51f0b8d2009-03-04 01:21:02 -03002895 v4l2_video_std_frame_period(bttv_tvnorms[btv->tvnorm].v4l2_id,
2896 &parm->parm.capture.timeperframe);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002897
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002898 return 0;
2899}
2900
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002901static int bttv_g_tuner(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002902 struct v4l2_tuner *t)
2903{
2904 struct bttv_fh *fh = priv;
2905 struct bttv *btv = fh->btv;
2906
Trent Piephoabb03622009-01-28 21:32:59 -03002907 if (btv->tuner_type == TUNER_ABSENT)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002908 return -EINVAL;
2909 if (0 != t->index)
2910 return -EINVAL;
2911
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002912 t->rxsubchans = V4L2_TUNER_SUB_MONO;
Hans Verkuil859f0272009-03-28 08:29:00 -03002913 bttv_call_all(btv, tuner, g_tuner, t);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002914 strcpy(t->name, "Television");
2915 t->capability = V4L2_TUNER_CAP_NORM;
2916 t->type = V4L2_TUNER_ANALOG_TV;
2917 if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)
2918 t->signal = 0xffff;
2919
2920 if (btv->audio_mode_gpio)
2921 btv->audio_mode_gpio(btv, t, 0);
2922
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002923 return 0;
2924}
2925
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002926static int bttv_g_priority(struct file *file, void *f, enum v4l2_priority *p)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002927{
2928 struct bttv_fh *fh = f;
2929 struct bttv *btv = fh->btv;
2930
2931 *p = v4l2_prio_max(&btv->prio);
2932
2933 return 0;
2934}
2935
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002936static int bttv_s_priority(struct file *file, void *f,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002937 enum v4l2_priority prio)
2938{
2939 struct bttv_fh *fh = f;
2940 struct bttv *btv = fh->btv;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002941 int rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002942
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002943 rc = v4l2_prio_change(&btv->prio, &fh->prio, prio);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03002944
2945 return rc;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002946}
2947
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002948static int bttv_cropcap(struct file *file, void *priv,
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002949 struct v4l2_cropcap *cap)
2950{
2951 struct bttv_fh *fh = priv;
2952 struct bttv *btv = fh->btv;
2953
2954 if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
2955 cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
2956 return -EINVAL;
2957
2958 *cap = bttv_tvnorms[btv->tvnorm].cropcap;
2959
2960 return 0;
2961}
2962
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002963static int bttv_g_crop(struct file *file, void *f, struct v4l2_crop *crop)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002964{
2965 struct bttv_fh *fh = f;
2966 struct bttv *btv = fh->btv;
2967
2968 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
2969 crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
2970 return -EINVAL;
2971
2972 /* No fh->do_crop = 1; because btv->crop[1] may be
2973 inconsistent with fh->width or fh->height and apps
2974 do not expect a change here. */
2975
2976 crop->c = btv->crop[!!fh->do_crop].rect;
2977
2978 return 0;
2979}
2980
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03002981static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002982{
2983 struct bttv_fh *fh = f;
2984 struct bttv *btv = fh->btv;
2985 const struct v4l2_rect *b;
2986 int retval;
2987 struct bttv_crop c;
2988 __s32 b_left;
2989 __s32 b_top;
2990 __s32 b_right;
2991 __s32 b_bottom;
2992
2993 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
2994 crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
2995 return -EINVAL;
2996
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03002997 /* Make sure tvnorm, vbi_end and the current cropping
2998 parameters remain consistent until we're done. Note
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03002999 read() may change vbi_end in check_alloc_btres_lock(). */
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003000 retval = v4l2_prio_check(&btv->prio, fh->prio);
3001 if (0 != retval) {
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003002 return retval;
3003 }
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003004
3005 retval = -EBUSY;
3006
3007 if (locked_btres(fh->btv, VIDEO_RESOURCES)) {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003008 return retval;
3009 }
3010
3011 b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
3012
3013 b_left = b->left;
3014 b_right = b_left + b->width;
3015 b_bottom = b->top + b->height;
3016
3017 b_top = max(b->top, btv->vbi_end);
3018 if (b_top + 32 >= b_bottom) {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003019 return retval;
3020 }
3021
3022 /* Min. scaled size 48 x 32. */
3023 c.rect.left = clamp(crop->c.left, b_left, b_right - 48);
3024 c.rect.left = min(c.rect.left, (__s32) MAX_HDELAY);
3025
3026 c.rect.width = clamp(crop->c.width,
3027 48, b_right - c.rect.left);
3028
3029 c.rect.top = clamp(crop->c.top, b_top, b_bottom - 32);
3030 /* Top and height must be a multiple of two. */
3031 c.rect.top = (c.rect.top + 1) & ~1;
3032
3033 c.rect.height = clamp(crop->c.height,
3034 32, b_bottom - c.rect.top);
3035 c.rect.height = (c.rect.height + 1) & ~1;
3036
3037 bttv_crop_calc_limits(&c);
3038
3039 btv->crop[1] = c;
3040
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003041 fh->do_crop = 1;
3042
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003043 if (fh->width < c.min_scaled_width) {
3044 fh->width = c.min_scaled_width;
3045 btv->init.width = c.min_scaled_width;
3046 } else if (fh->width > c.max_scaled_width) {
3047 fh->width = c.max_scaled_width;
3048 btv->init.width = c.max_scaled_width;
3049 }
3050
3051 if (fh->height < c.min_scaled_height) {
3052 fh->height = c.min_scaled_height;
3053 btv->init.height = c.min_scaled_height;
3054 } else if (fh->height > c.max_scaled_height) {
3055 fh->height = c.max_scaled_height;
3056 btv->init.height = c.max_scaled_height;
3057 }
3058
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003059 return 0;
3060}
3061
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003062static int bttv_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003063{
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03003064 if (unlikely(a->index))
3065 return -EINVAL;
3066
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003067 strcpy(a->name, "audio");
3068 return 0;
3069}
3070
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003071static int bttv_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003072{
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03003073 if (unlikely(a->index))
3074 return -EINVAL;
3075
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003076 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003077}
3078
3079static ssize_t bttv_read(struct file *file, char __user *data,
3080 size_t count, loff_t *ppos)
3081{
3082 struct bttv_fh *fh = file->private_data;
3083 int retval = 0;
3084
3085 if (fh->btv->errors)
3086 bttv_reinit_bt848(fh->btv);
3087 dprintk("bttv%d: read count=%d type=%s\n",
3088 fh->btv->c.nr,(int)count,v4l2_type_names[fh->type]);
3089
3090 switch (fh->type) {
3091 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003092 if (!check_alloc_btres_lock(fh->btv, fh, RESOURCE_VIDEO_READ)) {
Michael Schimeke5bd0262007-01-18 16:17:39 -03003093 /* VIDEO_READ in use by another fh,
3094 or VIDEO_STREAM by any fh. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003095 return -EBUSY;
Michael Schimeke5bd0262007-01-18 16:17:39 -03003096 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003097 retval = videobuf_read_one(&fh->cap, data, count, ppos,
3098 file->f_flags & O_NONBLOCK);
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003099 free_btres_lock(fh->btv, fh, RESOURCE_VIDEO_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003100 break;
3101 case V4L2_BUF_TYPE_VBI_CAPTURE:
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003102 if (!check_alloc_btres_lock(fh->btv,fh,RESOURCE_VBI))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003103 return -EBUSY;
3104 retval = videobuf_read_stream(&fh->vbi, data, count, ppos, 1,
3105 file->f_flags & O_NONBLOCK);
3106 break;
3107 default:
3108 BUG();
3109 }
3110 return retval;
3111}
3112
3113static unsigned int bttv_poll(struct file *file, poll_table *wait)
3114{
3115 struct bttv_fh *fh = file->private_data;
3116 struct bttv_buffer *buf;
3117 enum v4l2_field field;
Figo.zhang9fd64182009-06-16 13:31:29 -03003118 unsigned int rc = POLLERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003119
3120 if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003121 if (!check_alloc_btres_lock(fh->btv,fh,RESOURCE_VBI))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003122 return POLLERR;
3123 return videobuf_poll_stream(file, &fh->vbi, wait);
3124 }
3125
Michael Schimeke5bd0262007-01-18 16:17:39 -03003126 if (check_btres(fh,RESOURCE_VIDEO_STREAM)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003127 /* streaming capture */
3128 if (list_empty(&fh->cap.stream))
Figo.zhang9fd64182009-06-16 13:31:29 -03003129 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003130 buf = list_entry(fh->cap.stream.next,struct bttv_buffer,vb.stream);
3131 } else {
3132 /* read() capture */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003133 if (NULL == fh->cap.read_buf) {
3134 /* need to capture a new frame */
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03003135 if (locked_btres(fh->btv,RESOURCE_VIDEO_STREAM))
3136 goto err;
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03003137 fh->cap.read_buf = videobuf_sg_alloc(fh->cap.msize);
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03003138 if (NULL == fh->cap.read_buf)
3139 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003140 fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR;
3141 field = videobuf_next_field(&fh->cap);
3142 if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,field)) {
Nickolay V. Shmyrev50ab5ed2005-12-01 00:51:32 -08003143 kfree (fh->cap.read_buf);
3144 fh->cap.read_buf = NULL;
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03003145 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003146 }
3147 fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf);
3148 fh->cap.read_off = 0;
3149 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003150 buf = (struct bttv_buffer*)fh->cap.read_buf;
3151 }
3152
3153 poll_wait(file, &buf->vb.done, wait);
Brandon Philips0fc06862007-11-06 20:02:36 -03003154 if (buf->vb.state == VIDEOBUF_DONE ||
3155 buf->vb.state == VIDEOBUF_ERROR)
Figo.zhang9fd64182009-06-16 13:31:29 -03003156 rc = POLLIN|POLLRDNORM;
3157 else
3158 rc = 0;
Mauro Carvalho Chehab64f94772008-01-31 13:57:53 -03003159err:
Figo.zhang9fd64182009-06-16 13:31:29 -03003160 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003161}
3162
Hans Verkuilbec43662008-12-30 06:58:20 -03003163static int bttv_open(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003164{
Laurent Pinchart50462eb2009-12-10 11:47:13 -02003165 struct video_device *vdev = video_devdata(file);
Trent Piepho4b10d3b2009-01-28 21:32:59 -03003166 struct bttv *btv = video_drvdata(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003167 struct bttv_fh *fh;
3168 enum v4l2_buf_type type = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003169
Laurent Pinchart50462eb2009-12-10 11:47:13 -02003170 dprintk(KERN_DEBUG "bttv: open dev=%s\n", video_device_node_name(vdev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003171
Laurent Pinchart327ae592009-11-27 13:57:55 -03003172 if (vdev->vfl_type == VFL_TYPE_GRABBER) {
Trent Piepho4b10d3b2009-01-28 21:32:59 -03003173 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Laurent Pinchart327ae592009-11-27 13:57:55 -03003174 } else if (vdev->vfl_type == VFL_TYPE_VBI) {
Trent Piepho4b10d3b2009-01-28 21:32:59 -03003175 type = V4L2_BUF_TYPE_VBI_CAPTURE;
3176 } else {
3177 WARN_ON(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003178 return -ENODEV;
Hans Verkuild56dc612008-07-30 08:43:36 -03003179 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003180
3181 dprintk(KERN_DEBUG "bttv%d: open called (type=%s)\n",
3182 btv->c.nr,v4l2_type_names[type]);
3183
3184 /* allocate per filehandle data */
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003185 fh = kmalloc(sizeof(*fh), GFP_KERNEL);
3186 if (unlikely(!fh))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187 return -ENOMEM;
3188 file->private_data = fh;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003189
Linus Torvalds1da177e2005-04-16 15:20:36 -07003190 *fh = btv->init;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003191
Linus Torvalds1da177e2005-04-16 15:20:36 -07003192 fh->type = type;
3193 fh->ov.setup_ok = 0;
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003194
Hans Verkuilffb48772010-05-01 08:03:24 -03003195 v4l2_prio_open(&btv->prio, &fh->prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003196
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03003197 videobuf_queue_sg_init(&fh->cap, &bttv_video_qops,
3198 &btv->c.pci->dev, &btv->s_lock,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003199 V4L2_BUF_TYPE_VIDEO_CAPTURE,
3200 V4L2_FIELD_INTERLACED,
3201 sizeof(struct bttv_buffer),
Mauro Carvalho Chehab587f0d52010-12-15 18:45:42 -03003202 fh, &btv->lock);
Guennadi Liakhovetski07051352008-04-22 14:42:13 -03003203 videobuf_queue_sg_init(&fh->vbi, &bttv_vbi_qops,
3204 &btv->c.pci->dev, &btv->s_lock,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003205 V4L2_BUF_TYPE_VBI_CAPTURE,
3206 V4L2_FIELD_SEQ_TB,
3207 sizeof(struct bttv_buffer),
Mauro Carvalho Chehab587f0d52010-12-15 18:45:42 -03003208 fh, &btv->lock);
Nickolay V. Shmyrev302f61a2007-10-26 10:53:21 -03003209 set_tvnorm(btv,btv->tvnorm);
Mauro Carvalho Chehabb46a9c82008-08-05 10:12:35 -03003210 set_input(btv, btv->input, btv->tvnorm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003211
3212 btv->users++;
Michael Schimeke5bd0262007-01-18 16:17:39 -03003213
3214 /* The V4L2 spec requires one global set of cropping parameters
3215 which only change on request. These are stored in btv->crop[1].
3216 However for compatibility with V4L apps and cropping unaware
3217 V4L2 apps we now reset the cropping parameters as seen through
3218 this fh, which is to say VIDIOC_G_CROP and scaling limit checks
3219 will use btv->crop[0], the default cropping parameters for the
3220 current video standard, and VIDIOC_S_FMT will not implicitely
3221 change the cropping parameters until VIDIOC_S_CROP has been
3222 called. */
3223 fh->do_crop = !reset_crop; /* module parameter */
3224
3225 /* Likewise there should be one global set of VBI capture
3226 parameters, but for compatibility with V4L apps and earlier
3227 driver versions each fh has its own parameters. */
3228 bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm);
3229
Linus Torvalds1da177e2005-04-16 15:20:36 -07003230 bttv_field_count(btv);
3231 return 0;
3232}
3233
Hans Verkuilbec43662008-12-30 06:58:20 -03003234static int bttv_release(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003235{
3236 struct bttv_fh *fh = file->private_data;
3237 struct bttv *btv = fh->btv;
3238
3239 /* turn off overlay */
3240 if (check_btres(fh, RESOURCE_OVERLAY))
3241 bttv_switch_overlay(btv,fh,NULL);
3242
3243 /* stop video capture */
Michael Schimeke5bd0262007-01-18 16:17:39 -03003244 if (check_btres(fh, RESOURCE_VIDEO_STREAM)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003245 videobuf_streamoff(&fh->cap);
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003246 free_btres_lock(btv,fh,RESOURCE_VIDEO_STREAM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003247 }
3248 if (fh->cap.read_buf) {
3249 buffer_release(&fh->cap,fh->cap.read_buf);
3250 kfree(fh->cap.read_buf);
3251 }
Michael Schimeke5bd0262007-01-18 16:17:39 -03003252 if (check_btres(fh, RESOURCE_VIDEO_READ)) {
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003253 free_btres_lock(btv, fh, RESOURCE_VIDEO_READ);
Michael Schimeke5bd0262007-01-18 16:17:39 -03003254 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003255
3256 /* stop vbi capture */
3257 if (check_btres(fh, RESOURCE_VBI)) {
Brandon Philips053fcb62007-11-13 20:11:26 -03003258 videobuf_stop(&fh->vbi);
Mauro Carvalho Chehab8822f0d2010-09-14 12:19:51 -03003259 free_btres_lock(btv,fh,RESOURCE_VBI);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003260 }
3261
3262 /* free stuff */
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003263
Linus Torvalds1da177e2005-04-16 15:20:36 -07003264 videobuf_mmap_free(&fh->cap);
3265 videobuf_mmap_free(&fh->vbi);
Hans Verkuilffb48772010-05-01 08:03:24 -03003266 v4l2_prio_close(&btv->prio, fh->prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003267 file->private_data = NULL;
3268 kfree(fh);
3269
3270 btv->users--;
3271 bttv_field_count(btv);
Mauro Carvalho Chehabb46a9c82008-08-05 10:12:35 -03003272
3273 if (!btv->users)
3274 audio_mute(btv, 1);
3275
Linus Torvalds1da177e2005-04-16 15:20:36 -07003276 return 0;
3277}
3278
3279static int
3280bttv_mmap(struct file *file, struct vm_area_struct *vma)
3281{
3282 struct bttv_fh *fh = file->private_data;
3283
3284 dprintk("bttv%d: mmap type=%s 0x%lx+%ld\n",
3285 fh->btv->c.nr, v4l2_type_names[fh->type],
3286 vma->vm_start, vma->vm_end - vma->vm_start);
3287 return videobuf_mmap_mapper(bttv_queue(fh),vma);
3288}
3289
Hans Verkuilbec43662008-12-30 06:58:20 -03003290static const struct v4l2_file_operations bttv_fops =
Linus Torvalds1da177e2005-04-16 15:20:36 -07003291{
Mauro Carvalho Chehab8979e9d2010-09-15 08:22:09 -03003292 .owner = THIS_MODULE,
3293 .open = bttv_open,
3294 .release = bttv_release,
3295 .unlocked_ioctl = video_ioctl2,
3296 .read = bttv_read,
3297 .mmap = bttv_mmap,
3298 .poll = bttv_poll,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003299};
3300
Hans Verkuila3998102008-07-21 02:57:38 -03003301static const struct v4l2_ioctl_ops bttv_ioctl_ops = {
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003302 .vidioc_querycap = bttv_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03003303 .vidioc_enum_fmt_vid_cap = bttv_enum_fmt_vid_cap,
3304 .vidioc_g_fmt_vid_cap = bttv_g_fmt_vid_cap,
3305 .vidioc_try_fmt_vid_cap = bttv_try_fmt_vid_cap,
3306 .vidioc_s_fmt_vid_cap = bttv_s_fmt_vid_cap,
3307 .vidioc_enum_fmt_vid_overlay = bttv_enum_fmt_vid_overlay,
3308 .vidioc_g_fmt_vid_overlay = bttv_g_fmt_vid_overlay,
3309 .vidioc_try_fmt_vid_overlay = bttv_try_fmt_vid_overlay,
3310 .vidioc_s_fmt_vid_overlay = bttv_s_fmt_vid_overlay,
Hans Verkuil78b526a2008-05-28 12:16:41 -03003311 .vidioc_g_fmt_vbi_cap = bttv_g_fmt_vbi_cap,
3312 .vidioc_try_fmt_vbi_cap = bttv_try_fmt_vbi_cap,
3313 .vidioc_s_fmt_vbi_cap = bttv_s_fmt_vbi_cap,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003314 .vidioc_g_audio = bttv_g_audio,
3315 .vidioc_s_audio = bttv_s_audio,
3316 .vidioc_cropcap = bttv_cropcap,
3317 .vidioc_reqbufs = bttv_reqbufs,
3318 .vidioc_querybuf = bttv_querybuf,
3319 .vidioc_qbuf = bttv_qbuf,
3320 .vidioc_dqbuf = bttv_dqbuf,
3321 .vidioc_s_std = bttv_s_std,
3322 .vidioc_enum_input = bttv_enum_input,
3323 .vidioc_g_input = bttv_g_input,
3324 .vidioc_s_input = bttv_s_input,
3325 .vidioc_queryctrl = bttv_queryctrl,
3326 .vidioc_g_ctrl = bttv_g_ctrl,
3327 .vidioc_s_ctrl = bttv_s_ctrl,
3328 .vidioc_streamon = bttv_streamon,
3329 .vidioc_streamoff = bttv_streamoff,
3330 .vidioc_g_tuner = bttv_g_tuner,
3331 .vidioc_s_tuner = bttv_s_tuner,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003332 .vidioc_g_crop = bttv_g_crop,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003333 .vidioc_s_crop = bttv_s_crop,
3334 .vidioc_g_fbuf = bttv_g_fbuf,
3335 .vidioc_s_fbuf = bttv_s_fbuf,
3336 .vidioc_overlay = bttv_overlay,
3337 .vidioc_g_priority = bttv_g_priority,
3338 .vidioc_s_priority = bttv_s_priority,
3339 .vidioc_g_parm = bttv_g_parm,
3340 .vidioc_g_frequency = bttv_g_frequency,
3341 .vidioc_s_frequency = bttv_s_frequency,
3342 .vidioc_log_status = bttv_log_status,
3343 .vidioc_querystd = bttv_querystd,
Zoltan Devai43846832008-01-14 13:24:38 -03003344#ifdef CONFIG_VIDEO_ADV_DEBUG
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003345 .vidioc_g_register = bttv_g_register,
3346 .vidioc_s_register = bttv_s_register,
Zoltan Devai43846832008-01-14 13:24:38 -03003347#endif
Hans Verkuila3998102008-07-21 02:57:38 -03003348};
3349
3350static struct video_device bttv_video_template = {
3351 .fops = &bttv_fops,
Hans Verkuila3998102008-07-21 02:57:38 -03003352 .ioctl_ops = &bttv_ioctl_ops,
3353 .tvnorms = BTTV_NORMS,
3354 .current_norm = V4L2_STD_PAL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003355};
3356
Linus Torvalds1da177e2005-04-16 15:20:36 -07003357/* ----------------------------------------------------------------------- */
3358/* radio interface */
3359
Hans Verkuilbec43662008-12-30 06:58:20 -03003360static int radio_open(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003361{
Laurent Pinchart50462eb2009-12-10 11:47:13 -02003362 struct video_device *vdev = video_devdata(file);
Trent Piepho4b10d3b2009-01-28 21:32:59 -03003363 struct bttv *btv = video_drvdata(file);
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003364 struct bttv_fh *fh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003365
Laurent Pinchart50462eb2009-12-10 11:47:13 -02003366 dprintk("bttv: open dev=%s\n", video_device_node_name(vdev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003367
Linus Torvalds1da177e2005-04-16 15:20:36 -07003368 dprintk("bttv%d: open called (radio)\n",btv->c.nr);
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003369
3370 /* allocate per filehandle data */
3371 fh = kmalloc(sizeof(*fh), GFP_KERNEL);
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003372 if (unlikely(!fh))
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003373 return -ENOMEM;
3374 file->private_data = fh;
3375 *fh = btv->init;
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003376
Mauro Carvalho Chehabc37db912010-09-15 08:18:31 -03003377 v4l2_prio_open(&btv->prio, &fh->prio);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003378
Linus Torvalds1da177e2005-04-16 15:20:36 -07003379 btv->radio_user++;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003380
Hans Verkuil859f0272009-03-28 08:29:00 -03003381 bttv_call_all(btv, tuner, s_radio);
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03003382 audio_input(btv,TVAUDIO_INPUT_RADIO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003383
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003384 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003385}
3386
Hans Verkuilbec43662008-12-30 06:58:20 -03003387static int radio_release(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003388{
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003389 struct bttv_fh *fh = file->private_data;
3390 struct bttv *btv = fh->btv;
Hans Verkuilb9218f22010-12-27 12:22:46 -03003391 struct saa6588_command cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003392
Hans Verkuilffb48772010-05-01 08:03:24 -03003393 v4l2_prio_close(&btv->prio, fh->prio);
Robert Fitzsimonsb9bc07a2008-04-10 09:40:31 -03003394 file->private_data = NULL;
3395 kfree(fh);
3396
Linus Torvalds1da177e2005-04-16 15:20:36 -07003397 btv->radio_user--;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003398
Hans Verkuilb9218f22010-12-27 12:22:46 -03003399 bttv_call_all(btv, core, ioctl, SAA6588_CMD_CLOSE, &cmd);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003400
Linus Torvalds1da177e2005-04-16 15:20:36 -07003401 return 0;
3402}
3403
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003404static int radio_querycap(struct file *file, void *priv,
3405 struct v4l2_capability *cap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003406{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003407 struct bttv_fh *fh = priv;
3408 struct bttv *btv = fh->btv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003409
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003410 strcpy(cap->driver, "bttv");
3411 strlcpy(cap->card, btv->radio_dev->name, sizeof(cap->card));
3412 sprintf(cap->bus_info, "PCI:%s", pci_name(btv->c.pci));
3413 cap->version = BTTV_VERSION_CODE;
3414 cap->capabilities = V4L2_CAP_TUNER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003415
Linus Torvalds1da177e2005-04-16 15:20:36 -07003416 return 0;
3417}
3418
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003419static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003420{
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003421 struct bttv_fh *fh = priv;
3422 struct bttv *btv = fh->btv;
3423
Trent Piephoabb03622009-01-28 21:32:59 -03003424 if (btv->tuner_type == TUNER_ABSENT)
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003425 return -EINVAL;
3426 if (0 != t->index)
3427 return -EINVAL;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003428 strcpy(t->name, "Radio");
3429 t->type = V4L2_TUNER_RADIO;
3430
Hans Verkuil859f0272009-03-28 08:29:00 -03003431 bttv_call_all(btv, tuner, g_tuner, t);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003432
3433 if (btv->audio_mode_gpio)
3434 btv->audio_mode_gpio(btv, t, 0);
3435
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003436 return 0;
3437}
3438
3439static int radio_enum_input(struct file *file, void *priv,
3440 struct v4l2_input *i)
3441{
3442 if (i->index != 0)
3443 return -EINVAL;
3444
3445 strcpy(i->name, "Radio");
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03003446 i->type = V4L2_INPUT_TYPE_TUNER;
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003447
3448 return 0;
3449}
3450
3451static int radio_g_audio(struct file *file, void *priv,
3452 struct v4l2_audio *a)
3453{
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03003454 if (unlikely(a->index))
Cyrill Gorcunov1a002eb2008-04-01 17:49:13 -03003455 return -EINVAL;
3456
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003457 strcpy(a->name, "Radio");
Cyrill Gorcunov1a002eb2008-04-01 17:49:13 -03003458
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003459 return 0;
3460}
3461
3462static int radio_s_tuner(struct file *file, void *priv,
3463 struct v4l2_tuner *t)
3464{
3465 struct bttv_fh *fh = priv;
3466 struct bttv *btv = fh->btv;
3467
3468 if (0 != t->index)
3469 return -EINVAL;
3470
Hans Verkuil859f0272009-03-28 08:29:00 -03003471 bttv_call_all(btv, tuner, g_tuner, t);
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003472 return 0;
3473}
3474
3475static int radio_s_audio(struct file *file, void *priv,
3476 struct v4l2_audio *a)
3477{
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03003478 if (unlikely(a->index))
3479 return -EINVAL;
3480
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003481 return 0;
3482}
3483
3484static int radio_s_input(struct file *filp, void *priv, unsigned int i)
3485{
Mauro Carvalho Chehabd69b2e42008-04-01 20:30:24 -03003486 if (unlikely(i))
3487 return -EINVAL;
3488
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003489 return 0;
3490}
3491
3492static int radio_s_std(struct file *file, void *fh, v4l2_std_id *norm)
3493{
3494 return 0;
3495}
3496
3497static int radio_queryctrl(struct file *file, void *priv,
3498 struct v4l2_queryctrl *c)
3499{
3500 const struct v4l2_queryctrl *ctrl;
3501
3502 if (c->id < V4L2_CID_BASE ||
3503 c->id >= V4L2_CID_LASTP1)
3504 return -EINVAL;
3505
3506 if (c->id == V4L2_CID_AUDIO_MUTE) {
3507 ctrl = ctrl_by_id(c->id);
3508 *c = *ctrl;
3509 } else
3510 *c = no_ctl;
3511
3512 return 0;
3513}
3514
3515static int radio_g_input(struct file *filp, void *priv, unsigned int *i)
3516{
3517 *i = 0;
3518 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003519}
3520
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003521static ssize_t radio_read(struct file *file, char __user *data,
3522 size_t count, loff_t *ppos)
3523{
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003524 struct bttv_fh *fh = file->private_data;
3525 struct bttv *btv = fh->btv;
Hans Verkuilb9218f22010-12-27 12:22:46 -03003526 struct saa6588_command cmd;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003527 cmd.block_count = count/3;
3528 cmd.buffer = data;
3529 cmd.instance = file;
3530 cmd.result = -ENODEV;
3531
Hans Verkuilb9218f22010-12-27 12:22:46 -03003532 bttv_call_all(btv, core, ioctl, SAA6588_CMD_READ, &cmd);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003533
3534 return cmd.result;
3535}
3536
3537static unsigned int radio_poll(struct file *file, poll_table *wait)
3538{
Robert Fitzsimons5cd39552008-04-01 11:41:54 -03003539 struct bttv_fh *fh = file->private_data;
3540 struct bttv *btv = fh->btv;
Hans Verkuilb9218f22010-12-27 12:22:46 -03003541 struct saa6588_command cmd;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003542 cmd.instance = file;
3543 cmd.event_list = wait;
3544 cmd.result = -ENODEV;
Hans Verkuilb9218f22010-12-27 12:22:46 -03003545 bttv_call_all(btv, core, ioctl, SAA6588_CMD_POLL, &cmd);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003546
3547 return cmd.result;
3548}
3549
Hans Verkuilbec43662008-12-30 06:58:20 -03003550static const struct v4l2_file_operations radio_fops =
Linus Torvalds1da177e2005-04-16 15:20:36 -07003551{
3552 .owner = THIS_MODULE,
3553 .open = radio_open,
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003554 .read = radio_read,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003555 .release = radio_release,
Mauro Carvalho Chehab587f0d52010-12-15 18:45:42 -03003556 .unlocked_ioctl = video_ioctl2,
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003557 .poll = radio_poll,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003558};
3559
Hans Verkuila3998102008-07-21 02:57:38 -03003560static const struct v4l2_ioctl_ops radio_ioctl_ops = {
Douglas Schilling Landgraf402aa762007-12-27 22:20:58 -03003561 .vidioc_querycap = radio_querycap,
3562 .vidioc_g_tuner = radio_g_tuner,
3563 .vidioc_enum_input = radio_enum_input,
3564 .vidioc_g_audio = radio_g_audio,
3565 .vidioc_s_tuner = radio_s_tuner,
3566 .vidioc_s_audio = radio_s_audio,
3567 .vidioc_s_input = radio_s_input,
3568 .vidioc_s_std = radio_s_std,
3569 .vidioc_queryctrl = radio_queryctrl,
3570 .vidioc_g_input = radio_g_input,
Mauro Carvalho Chehabe5ae3db2007-12-27 22:22:59 -03003571 .vidioc_g_ctrl = bttv_g_ctrl,
3572 .vidioc_s_ctrl = bttv_s_ctrl,
3573 .vidioc_g_frequency = bttv_g_frequency,
3574 .vidioc_s_frequency = bttv_s_frequency,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003575};
3576
Hans Verkuila3998102008-07-21 02:57:38 -03003577static struct video_device radio_template = {
3578 .fops = &radio_fops,
Hans Verkuila3998102008-07-21 02:57:38 -03003579 .ioctl_ops = &radio_ioctl_ops,
3580};
3581
Linus Torvalds1da177e2005-04-16 15:20:36 -07003582/* ----------------------------------------------------------------------- */
3583/* some debug code */
3584
Adrian Bunk408b6642005-05-01 08:59:29 -07003585static int bttv_risc_decode(u32 risc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003586{
3587 static char *instr[16] = {
3588 [ BT848_RISC_WRITE >> 28 ] = "write",
3589 [ BT848_RISC_SKIP >> 28 ] = "skip",
3590 [ BT848_RISC_WRITEC >> 28 ] = "writec",
3591 [ BT848_RISC_JUMP >> 28 ] = "jump",
3592 [ BT848_RISC_SYNC >> 28 ] = "sync",
3593 [ BT848_RISC_WRITE123 >> 28 ] = "write123",
3594 [ BT848_RISC_SKIP123 >> 28 ] = "skip123",
3595 [ BT848_RISC_WRITE1S23 >> 28 ] = "write1s23",
3596 };
3597 static int incr[16] = {
3598 [ BT848_RISC_WRITE >> 28 ] = 2,
3599 [ BT848_RISC_JUMP >> 28 ] = 2,
3600 [ BT848_RISC_SYNC >> 28 ] = 2,
3601 [ BT848_RISC_WRITE123 >> 28 ] = 5,
3602 [ BT848_RISC_SKIP123 >> 28 ] = 2,
3603 [ BT848_RISC_WRITE1S23 >> 28 ] = 3,
3604 };
3605 static char *bits[] = {
3606 "be0", "be1", "be2", "be3/resync",
3607 "set0", "set1", "set2", "set3",
3608 "clr0", "clr1", "clr2", "clr3",
3609 "irq", "res", "eol", "sol",
3610 };
3611 int i;
3612
3613 printk("0x%08x [ %s", risc,
3614 instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
3615 for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
3616 if (risc & (1 << (i + 12)))
3617 printk(" %s",bits[i]);
3618 printk(" count=%d ]\n", risc & 0xfff);
3619 return incr[risc >> 28] ? incr[risc >> 28] : 1;
3620}
3621
Adrian Bunk408b6642005-05-01 08:59:29 -07003622static void bttv_risc_disasm(struct bttv *btv,
3623 struct btcx_riscmem *risc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003624{
3625 unsigned int i,j,n;
3626
3627 printk("%s: risc disasm: %p [dma=0x%08lx]\n",
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03003628 btv->c.v4l2_dev.name, risc->cpu, (unsigned long)risc->dma);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003629 for (i = 0; i < (risc->size >> 2); i += n) {
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03003630 printk("%s: 0x%lx: ", btv->c.v4l2_dev.name,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631 (unsigned long)(risc->dma + (i<<2)));
Al Viro3aa71102008-06-22 14:20:09 -03003632 n = bttv_risc_decode(le32_to_cpu(risc->cpu[i]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003633 for (j = 1; j < n; j++)
3634 printk("%s: 0x%lx: 0x%08x [ arg #%d ]\n",
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03003635 btv->c.v4l2_dev.name, (unsigned long)(risc->dma + ((i+j)<<2)),
Linus Torvalds1da177e2005-04-16 15:20:36 -07003636 risc->cpu[i+j], j);
3637 if (0 == risc->cpu[i])
3638 break;
3639 }
3640}
3641
3642static void bttv_print_riscaddr(struct bttv *btv)
3643{
3644 printk(" main: %08Lx\n",
3645 (unsigned long long)btv->main.dma);
3646 printk(" vbi : o=%08Lx e=%08Lx\n",
3647 btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
3648 btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0);
3649 printk(" cap : o=%08Lx e=%08Lx\n",
3650 btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0,
3651 btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
3652 printk(" scr : o=%08Lx e=%08Lx\n",
3653 btv->screen ? (unsigned long long)btv->screen->top.dma : 0,
3654 btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0);
3655 bttv_risc_disasm(btv, &btv->main);
3656}
3657
3658/* ----------------------------------------------------------------------- */
3659/* irq handler */
3660
3661static char *irq_name[] = {
3662 "FMTCHG", // format change detected (525 vs. 625)
3663 "VSYNC", // vertical sync (new field)
3664 "HSYNC", // horizontal sync
3665 "OFLOW", // chroma/luma AGC overflow
3666 "HLOCK", // horizontal lock changed
3667 "VPRES", // video presence changed
3668 "6", "7",
3669 "I2CDONE", // hw irc operation finished
3670 "GPINT", // gpio port triggered irq
3671 "10",
3672 "RISCI", // risc instruction triggered irq
3673 "FBUS", // pixel data fifo dropped data (high pci bus latencies)
3674 "FTRGT", // pixel data fifo overrun
3675 "FDSR", // fifo data stream resyncronisation
3676 "PPERR", // parity error (data transfer)
3677 "RIPERR", // parity error (read risc instructions)
3678 "PABORT", // pci abort
3679 "OCERR", // risc instruction error
3680 "SCERR", // syncronisation error
3681};
3682
3683static void bttv_print_irqbits(u32 print, u32 mark)
3684{
3685 unsigned int i;
3686
3687 printk("bits:");
3688 for (i = 0; i < ARRAY_SIZE(irq_name); i++) {
3689 if (print & (1 << i))
3690 printk(" %s",irq_name[i]);
3691 if (mark & (1 << i))
3692 printk("*");
3693 }
3694}
3695
3696static void bttv_irq_debug_low_latency(struct bttv *btv, u32 rc)
3697{
3698 printk("bttv%d: irq: skipped frame [main=%lx,o_vbi=%lx,o_field=%lx,rc=%lx]\n",
3699 btv->c.nr,
3700 (unsigned long)btv->main.dma,
Al Viro3aa71102008-06-22 14:20:09 -03003701 (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_VBI+1]),
3702 (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_FIELD+1]),
Linus Torvalds1da177e2005-04-16 15:20:36 -07003703 (unsigned long)rc);
3704
3705 if (0 == (btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC)) {
3706 printk("bttv%d: Oh, there (temporarely?) is no input signal. "
3707 "Ok, then this is harmless, don't worry ;)\n",
3708 btv->c.nr);
3709 return;
3710 }
3711 printk("bttv%d: Uhm. Looks like we have unusual high IRQ latencies.\n",
3712 btv->c.nr);
3713 printk("bttv%d: Lets try to catch the culpit red-handed ...\n",
3714 btv->c.nr);
3715 dump_stack();
3716}
3717
3718static int
3719bttv_irq_next_video(struct bttv *btv, struct bttv_buffer_set *set)
3720{
3721 struct bttv_buffer *item;
3722
3723 memset(set,0,sizeof(*set));
3724
3725 /* capture request ? */
3726 if (!list_empty(&btv->capture)) {
3727 set->frame_irq = 1;
3728 item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
3729 if (V4L2_FIELD_HAS_TOP(item->vb.field))
3730 set->top = item;
3731 if (V4L2_FIELD_HAS_BOTTOM(item->vb.field))
3732 set->bottom = item;
3733
3734 /* capture request for other field ? */
3735 if (!V4L2_FIELD_HAS_BOTH(item->vb.field) &&
3736 (item->vb.queue.next != &btv->capture)) {
3737 item = list_entry(item->vb.queue.next, struct bttv_buffer, vb.queue);
Mike Isely66349b42009-09-21 12:09:08 -03003738 /* Mike Isely <isely@pobox.com> - Only check
3739 * and set up the bottom field in the logic
3740 * below. Don't ever do the top field. This
3741 * of course means that if we set up the
3742 * bottom field in the above code that we'll
3743 * actually skip a field. But that's OK.
3744 * Having processed only a single buffer this
3745 * time, then the next time around the first
3746 * available buffer should be for a top field.
3747 * That will then cause us here to set up a
3748 * top then a bottom field in the normal way.
3749 * The alternative to this understanding is
3750 * that we set up the second available buffer
3751 * as a top field, but that's out of order
3752 * since this driver always processes the top
3753 * field first - the effect will be the two
3754 * buffers being returned in the wrong order,
3755 * with the second buffer also being delayed
3756 * by one field time (owing to the fifo nature
3757 * of videobuf). Worse still, we'll be stuck
3758 * doing fields out of order now every time
3759 * until something else causes a field to be
3760 * dropped. By effectively forcing a field to
3761 * drop this way then we always get back into
3762 * sync within a single frame time. (Out of
3763 * order fields can screw up deinterlacing
3764 * algorithms.) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003765 if (!V4L2_FIELD_HAS_BOTH(item->vb.field)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003766 if (NULL == set->bottom &&
3767 V4L2_FIELD_BOTTOM == item->vb.field) {
3768 set->bottom = item;
3769 }
3770 if (NULL != set->top && NULL != set->bottom)
3771 set->top_irq = 2;
3772 }
3773 }
3774 }
3775
3776 /* screen overlay ? */
3777 if (NULL != btv->screen) {
3778 if (V4L2_FIELD_HAS_BOTH(btv->screen->vb.field)) {
3779 if (NULL == set->top && NULL == set->bottom) {
3780 set->top = btv->screen;
3781 set->bottom = btv->screen;
3782 }
3783 } else {
3784 if (V4L2_FIELD_TOP == btv->screen->vb.field &&
3785 NULL == set->top) {
3786 set->top = btv->screen;
3787 }
3788 if (V4L2_FIELD_BOTTOM == btv->screen->vb.field &&
3789 NULL == set->bottom) {
3790 set->bottom = btv->screen;
3791 }
3792 }
3793 }
3794
3795 dprintk("bttv%d: next set: top=%p bottom=%p [screen=%p,irq=%d,%d]\n",
3796 btv->c.nr,set->top, set->bottom,
3797 btv->screen,set->frame_irq,set->top_irq);
3798 return 0;
3799}
3800
3801static void
3802bttv_irq_wakeup_video(struct bttv *btv, struct bttv_buffer_set *wakeup,
3803 struct bttv_buffer_set *curr, unsigned int state)
3804{
3805 struct timeval ts;
3806
3807 do_gettimeofday(&ts);
3808
3809 if (wakeup->top == wakeup->bottom) {
3810 if (NULL != wakeup->top && curr->top != wakeup->top) {
3811 if (irq_debug > 1)
3812 printk("bttv%d: wakeup: both=%p\n",btv->c.nr,wakeup->top);
3813 wakeup->top->vb.ts = ts;
3814 wakeup->top->vb.field_count = btv->field_count;
3815 wakeup->top->vb.state = state;
3816 wake_up(&wakeup->top->vb.done);
3817 }
3818 } else {
3819 if (NULL != wakeup->top && curr->top != wakeup->top) {
3820 if (irq_debug > 1)
3821 printk("bttv%d: wakeup: top=%p\n",btv->c.nr,wakeup->top);
3822 wakeup->top->vb.ts = ts;
3823 wakeup->top->vb.field_count = btv->field_count;
3824 wakeup->top->vb.state = state;
3825 wake_up(&wakeup->top->vb.done);
3826 }
3827 if (NULL != wakeup->bottom && curr->bottom != wakeup->bottom) {
3828 if (irq_debug > 1)
3829 printk("bttv%d: wakeup: bottom=%p\n",btv->c.nr,wakeup->bottom);
3830 wakeup->bottom->vb.ts = ts;
3831 wakeup->bottom->vb.field_count = btv->field_count;
3832 wakeup->bottom->vb.state = state;
3833 wake_up(&wakeup->bottom->vb.done);
3834 }
3835 }
3836}
3837
3838static void
3839bttv_irq_wakeup_vbi(struct bttv *btv, struct bttv_buffer *wakeup,
3840 unsigned int state)
3841{
3842 struct timeval ts;
3843
3844 if (NULL == wakeup)
3845 return;
3846
3847 do_gettimeofday(&ts);
3848 wakeup->vb.ts = ts;
3849 wakeup->vb.field_count = btv->field_count;
3850 wakeup->vb.state = state;
3851 wake_up(&wakeup->vb.done);
3852}
3853
3854static void bttv_irq_timeout(unsigned long data)
3855{
3856 struct bttv *btv = (struct bttv *)data;
3857 struct bttv_buffer_set old,new;
3858 struct bttv_buffer *ovbi;
3859 struct bttv_buffer *item;
3860 unsigned long flags;
3861
3862 if (bttv_verbose) {
3863 printk(KERN_INFO "bttv%d: timeout: drop=%d irq=%d/%d, risc=%08x, ",
3864 btv->c.nr, btv->framedrop, btv->irq_me, btv->irq_total,
3865 btread(BT848_RISC_COUNT));
3866 bttv_print_irqbits(btread(BT848_INT_STAT),0);
3867 printk("\n");
3868 }
3869
3870 spin_lock_irqsave(&btv->s_lock,flags);
3871
3872 /* deactivate stuff */
3873 memset(&new,0,sizeof(new));
3874 old = btv->curr;
3875 ovbi = btv->cvbi;
3876 btv->curr = new;
3877 btv->cvbi = NULL;
3878 btv->loop_irq = 0;
3879 bttv_buffer_activate_video(btv, &new);
3880 bttv_buffer_activate_vbi(btv, NULL);
3881 bttv_set_dma(btv, 0);
3882
3883 /* wake up */
Brandon Philips0fc06862007-11-06 20:02:36 -03003884 bttv_irq_wakeup_video(btv, &old, &new, VIDEOBUF_ERROR);
3885 bttv_irq_wakeup_vbi(btv, ovbi, VIDEOBUF_ERROR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003886
3887 /* cancel all outstanding capture / vbi requests */
3888 while (!list_empty(&btv->capture)) {
3889 item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
3890 list_del(&item->vb.queue);
Brandon Philips0fc06862007-11-06 20:02:36 -03003891 item->vb.state = VIDEOBUF_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892 wake_up(&item->vb.done);
3893 }
3894 while (!list_empty(&btv->vcapture)) {
3895 item = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
3896 list_del(&item->vb.queue);
Brandon Philips0fc06862007-11-06 20:02:36 -03003897 item->vb.state = VIDEOBUF_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003898 wake_up(&item->vb.done);
3899 }
3900
3901 btv->errors++;
3902 spin_unlock_irqrestore(&btv->s_lock,flags);
3903}
3904
3905static void
3906bttv_irq_wakeup_top(struct bttv *btv)
3907{
3908 struct bttv_buffer *wakeup = btv->curr.top;
3909
3910 if (NULL == wakeup)
3911 return;
3912
3913 spin_lock(&btv->s_lock);
3914 btv->curr.top_irq = 0;
3915 btv->curr.top = NULL;
3916 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
3917
3918 do_gettimeofday(&wakeup->vb.ts);
3919 wakeup->vb.field_count = btv->field_count;
Brandon Philips0fc06862007-11-06 20:02:36 -03003920 wakeup->vb.state = VIDEOBUF_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003921 wake_up(&wakeup->vb.done);
3922 spin_unlock(&btv->s_lock);
3923}
3924
3925static inline int is_active(struct btcx_riscmem *risc, u32 rc)
3926{
3927 if (rc < risc->dma)
3928 return 0;
3929 if (rc > risc->dma + risc->size)
3930 return 0;
3931 return 1;
3932}
3933
3934static void
3935bttv_irq_switch_video(struct bttv *btv)
3936{
3937 struct bttv_buffer_set new;
3938 struct bttv_buffer_set old;
3939 dma_addr_t rc;
3940
3941 spin_lock(&btv->s_lock);
3942
3943 /* new buffer set */
3944 bttv_irq_next_video(btv, &new);
3945 rc = btread(BT848_RISC_COUNT);
3946 if ((btv->curr.top && is_active(&btv->curr.top->top, rc)) ||
3947 (btv->curr.bottom && is_active(&btv->curr.bottom->bottom, rc))) {
3948 btv->framedrop++;
3949 if (debug_latency)
3950 bttv_irq_debug_low_latency(btv, rc);
3951 spin_unlock(&btv->s_lock);
3952 return;
3953 }
3954
3955 /* switch over */
3956 old = btv->curr;
3957 btv->curr = new;
3958 btv->loop_irq &= ~1;
3959 bttv_buffer_activate_video(btv, &new);
3960 bttv_set_dma(btv, 0);
3961
3962 /* switch input */
3963 if (UNSET != btv->new_input) {
3964 video_mux(btv,btv->new_input);
3965 btv->new_input = UNSET;
3966 }
3967
3968 /* wake up finished buffers */
Brandon Philips0fc06862007-11-06 20:02:36 -03003969 bttv_irq_wakeup_video(btv, &old, &new, VIDEOBUF_DONE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003970 spin_unlock(&btv->s_lock);
3971}
3972
3973static void
3974bttv_irq_switch_vbi(struct bttv *btv)
3975{
3976 struct bttv_buffer *new = NULL;
3977 struct bttv_buffer *old;
3978 u32 rc;
3979
3980 spin_lock(&btv->s_lock);
3981
3982 if (!list_empty(&btv->vcapture))
3983 new = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
3984 old = btv->cvbi;
3985
3986 rc = btread(BT848_RISC_COUNT);
3987 if (NULL != old && (is_active(&old->top, rc) ||
3988 is_active(&old->bottom, rc))) {
3989 btv->framedrop++;
3990 if (debug_latency)
3991 bttv_irq_debug_low_latency(btv, rc);
3992 spin_unlock(&btv->s_lock);
3993 return;
3994 }
3995
3996 /* switch */
3997 btv->cvbi = new;
3998 btv->loop_irq &= ~4;
3999 bttv_buffer_activate_vbi(btv, new);
4000 bttv_set_dma(btv, 0);
4001
Brandon Philips0fc06862007-11-06 20:02:36 -03004002 bttv_irq_wakeup_vbi(btv, old, VIDEOBUF_DONE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004003 spin_unlock(&btv->s_lock);
4004}
4005
David Howells7d12e782006-10-05 14:55:46 +01004006static irqreturn_t bttv_irq(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004007{
4008 u32 stat,astat;
4009 u32 dstat;
4010 int count;
4011 struct bttv *btv;
4012 int handled = 0;
4013
4014 btv=(struct bttv *)dev_id;
Mark Weaver6c6c0b22005-11-13 16:07:52 -08004015
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016 count=0;
4017 while (1) {
4018 /* get/clear interrupt status bits */
4019 stat=btread(BT848_INT_STAT);
4020 astat=stat&btread(BT848_INT_MASK);
4021 if (!astat)
4022 break;
4023 handled = 1;
4024 btwrite(stat,BT848_INT_STAT);
4025
4026 /* get device status bits */
4027 dstat=btread(BT848_DSTATUS);
4028
4029 if (irq_debug) {
4030 printk(KERN_DEBUG "bttv%d: irq loop=%d fc=%d "
4031 "riscs=%x, riscc=%08x, ",
4032 btv->c.nr, count, btv->field_count,
4033 stat>>28, btread(BT848_RISC_COUNT));
4034 bttv_print_irqbits(stat,astat);
4035 if (stat & BT848_INT_HLOCK)
4036 printk(" HLOC => %s", (dstat & BT848_DSTATUS_HLOC)
4037 ? "yes" : "no");
4038 if (stat & BT848_INT_VPRES)
4039 printk(" PRES => %s", (dstat & BT848_DSTATUS_PRES)
4040 ? "yes" : "no");
4041 if (stat & BT848_INT_FMTCHG)
4042 printk(" NUML => %s", (dstat & BT848_DSTATUS_NUML)
4043 ? "625" : "525");
4044 printk("\n");
4045 }
4046
4047 if (astat&BT848_INT_VSYNC)
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004048 btv->field_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004049
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02004050 if ((astat & BT848_INT_GPINT) && btv->remote) {
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02004051 bttv_input_irq(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004052 }
4053
4054 if (astat & BT848_INT_I2CDONE) {
4055 btv->i2c_done = stat;
4056 wake_up(&btv->i2c_queue);
4057 }
4058
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004059 if ((astat & BT848_INT_RISCI) && (stat & (4<<28)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060 bttv_irq_switch_vbi(btv);
4061
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004062 if ((astat & BT848_INT_RISCI) && (stat & (2<<28)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004063 bttv_irq_wakeup_top(btv);
4064
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004065 if ((astat & BT848_INT_RISCI) && (stat & (1<<28)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004066 bttv_irq_switch_video(btv);
4067
4068 if ((astat & BT848_INT_HLOCK) && btv->opt_automute)
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03004069 audio_mute(btv, btv->mute); /* trigger automute */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004070
4071 if (astat & (BT848_INT_SCERR|BT848_INT_OCERR)) {
4072 printk(KERN_INFO "bttv%d: %s%s @ %08x,",btv->c.nr,
4073 (astat & BT848_INT_SCERR) ? "SCERR" : "",
4074 (astat & BT848_INT_OCERR) ? "OCERR" : "",
4075 btread(BT848_RISC_COUNT));
4076 bttv_print_irqbits(stat,astat);
4077 printk("\n");
4078 if (bttv_debug)
4079 bttv_print_riscaddr(btv);
4080 }
4081 if (fdsr && astat & BT848_INT_FDSR) {
4082 printk(KERN_INFO "bttv%d: FDSR @ %08x\n",
4083 btv->c.nr,btread(BT848_RISC_COUNT));
4084 if (bttv_debug)
4085 bttv_print_riscaddr(btv);
4086 }
4087
4088 count++;
4089 if (count > 4) {
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08004090
4091 if (count > 8 || !(astat & BT848_INT_GPINT)) {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004092 btwrite(0, BT848_INT_MASK);
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08004093
4094 printk(KERN_ERR
4095 "bttv%d: IRQ lockup, cleared int mask [", btv->c.nr);
4096 } else {
4097 printk(KERN_ERR
4098 "bttv%d: IRQ lockup, clearing GPINT from int mask [", btv->c.nr);
4099
4100 btwrite(btread(BT848_INT_MASK) & (-1 ^ BT848_INT_GPINT),
4101 BT848_INT_MASK);
4102 };
4103
Linus Torvalds1da177e2005-04-16 15:20:36 -07004104 bttv_print_irqbits(stat,astat);
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08004105
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106 printk("]\n");
4107 }
4108 }
4109 btv->irq_total++;
4110 if (handled)
4111 btv->irq_me++;
4112 return IRQ_RETVAL(handled);
4113}
4114
4115
4116/* ----------------------------------------------------------------------- */
4117/* initialitation */
4118
4119static struct video_device *vdev_init(struct bttv *btv,
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03004120 const struct video_device *template,
Hans Verkuil0ea6bc82008-07-26 08:26:43 -03004121 const char *type_name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004122{
4123 struct video_device *vfd;
4124
4125 vfd = video_device_alloc();
4126 if (NULL == vfd)
4127 return NULL;
4128 *vfd = *template;
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004129 vfd->v4l2_dev = &btv->c.v4l2_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004130 vfd->release = video_device_release;
Mauro Carvalho Chehab1d0a4362008-06-23 12:31:29 -03004131 vfd->debug = bttv_debug;
Trent Piepho4b10d3b2009-01-28 21:32:59 -03004132 video_set_drvdata(vfd, btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004133 snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
4134 btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "",
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03004135 type_name, bttv_tvcards[btv->c.type].name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004136 return vfd;
4137}
4138
4139static void bttv_unregister_video(struct bttv *btv)
4140{
4141 if (btv->video_dev) {
Laurent Pinchartf0813b42009-11-27 13:57:30 -03004142 if (video_is_registered(btv->video_dev))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004143 video_unregister_device(btv->video_dev);
4144 else
4145 video_device_release(btv->video_dev);
4146 btv->video_dev = NULL;
4147 }
4148 if (btv->vbi_dev) {
Laurent Pinchartf0813b42009-11-27 13:57:30 -03004149 if (video_is_registered(btv->vbi_dev))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004150 video_unregister_device(btv->vbi_dev);
4151 else
4152 video_device_release(btv->vbi_dev);
4153 btv->vbi_dev = NULL;
4154 }
4155 if (btv->radio_dev) {
Laurent Pinchartf0813b42009-11-27 13:57:30 -03004156 if (video_is_registered(btv->radio_dev))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004157 video_unregister_device(btv->radio_dev);
4158 else
4159 video_device_release(btv->radio_dev);
4160 btv->radio_dev = NULL;
4161 }
4162}
4163
4164/* register video4linux devices */
4165static int __devinit bttv_register_video(struct bttv *btv)
4166{
Hans Verkuil0ea6bc82008-07-26 08:26:43 -03004167 if (no_overlay > 0)
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07004168 printk("bttv: Overlay support disabled.\n");
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07004169
Linus Torvalds1da177e2005-04-16 15:20:36 -07004170 /* video */
Hans Verkuil0ea6bc82008-07-26 08:26:43 -03004171 btv->video_dev = vdev_init(btv, &bttv_video_template, "video");
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03004172
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004173 if (NULL == btv->video_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004174 goto err;
Jean Delvare176c2f32008-09-07 12:49:59 -03004175 if (video_register_device(btv->video_dev, VFL_TYPE_GRABBER,
4176 video_nr[btv->c.nr]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004177 goto err;
Laurent Pinchart38c7c032009-11-27 13:57:15 -03004178 printk(KERN_INFO "bttv%d: registered device %s\n",
4179 btv->c.nr, video_device_node_name(btv->video_dev));
Hans Verkuil22a04f12008-07-20 06:35:02 -03004180 if (device_create_file(&btv->video_dev->dev,
Kay Sievers54bd5b62007-10-08 16:26:13 -03004181 &dev_attr_card)<0) {
4182 printk(KERN_ERR "bttv%d: device_create_file 'card' "
Trent Piephod94fc9a2006-07-29 17:18:06 -03004183 "failed\n", btv->c.nr);
4184 goto err;
4185 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004186
4187 /* vbi */
Hans Verkuil0ea6bc82008-07-26 08:26:43 -03004188 btv->vbi_dev = vdev_init(btv, &bttv_video_template, "vbi");
Mauro Carvalho Chehab9134be02007-12-27 22:28:31 -03004189
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004190 if (NULL == btv->vbi_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004191 goto err;
Jean Delvare176c2f32008-09-07 12:49:59 -03004192 if (video_register_device(btv->vbi_dev, VFL_TYPE_VBI,
4193 vbi_nr[btv->c.nr]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004194 goto err;
Laurent Pinchart38c7c032009-11-27 13:57:15 -03004195 printk(KERN_INFO "bttv%d: registered device %s\n",
4196 btv->c.nr, video_device_node_name(btv->vbi_dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004197
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004198 if (!btv->has_radio)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004199 return 0;
4200 /* radio */
Hans Verkuil0ea6bc82008-07-26 08:26:43 -03004201 btv->radio_dev = vdev_init(btv, &radio_template, "radio");
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004202 if (NULL == btv->radio_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004203 goto err;
Jean Delvare176c2f32008-09-07 12:49:59 -03004204 if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,
4205 radio_nr[btv->c.nr]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004206 goto err;
Laurent Pinchart38c7c032009-11-27 13:57:15 -03004207 printk(KERN_INFO "bttv%d: registered device %s\n",
4208 btv->c.nr, video_device_node_name(btv->radio_dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004209
4210 /* all done */
4211 return 0;
4212
4213 err:
4214 bttv_unregister_video(btv);
4215 return -1;
4216}
4217
4218
4219/* on OpenFirmware machines (PowerMac at least), PCI memory cycle */
4220/* response on cards with no firmware is not enabled by OF */
4221static void pci_set_command(struct pci_dev *dev)
4222{
4223#if defined(__powerpc__)
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004224 unsigned int cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004225
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004226 pci_read_config_dword(dev, PCI_COMMAND, &cmd);
4227 cmd = (cmd | PCI_COMMAND_MEMORY );
4228 pci_write_config_dword(dev, PCI_COMMAND, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004229#endif
4230}
4231
4232static int __devinit bttv_probe(struct pci_dev *dev,
4233 const struct pci_device_id *pci_id)
4234{
4235 int result;
4236 unsigned char lat;
4237 struct bttv *btv;
4238
4239 if (bttv_num == BTTV_MAX)
4240 return -ENOMEM;
4241 printk(KERN_INFO "bttv: Bt8xx card found (%d).\n", bttv_num);
Trent Piepho4b10d3b2009-01-28 21:32:59 -03004242 bttvs[bttv_num] = btv = kzalloc(sizeof(*btv), GFP_KERNEL);
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004243 if (btv == NULL) {
4244 printk(KERN_ERR "bttv: out of memory.\n");
4245 return -ENOMEM;
4246 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004247 btv->c.nr = bttv_num;
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004248 snprintf(btv->c.v4l2_dev.name, sizeof(btv->c.v4l2_dev.name),
4249 "bttv%d", btv->c.nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004250
4251 /* initialize structs / fill in defaults */
Ingo Molnarbd5f0ac2006-01-13 14:10:24 -02004252 mutex_init(&btv->lock);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004253 spin_lock_init(&btv->s_lock);
4254 spin_lock_init(&btv->gpio_lock);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004255 init_waitqueue_head(&btv->i2c_queue);
4256 INIT_LIST_HEAD(&btv->c.subs);
4257 INIT_LIST_HEAD(&btv->capture);
4258 INIT_LIST_HEAD(&btv->vcapture);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004259 v4l2_prio_init(&btv->prio);
4260
4261 init_timer(&btv->timeout);
4262 btv->timeout.function = bttv_irq_timeout;
4263 btv->timeout.data = (unsigned long)btv;
4264
Michael Krufky7c08fb02005-11-08 21:36:21 -08004265 btv->i2c_rc = -1;
4266 btv->tuner_type = UNSET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004267 btv->new_input = UNSET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004268 btv->has_radio=radio[btv->c.nr];
4269
4270 /* pci stuff (init, get irq/mmio, ... */
4271 btv->c.pci = dev;
Michael Krufky7c08fb02005-11-08 21:36:21 -08004272 btv->id = dev->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004273 if (pci_enable_device(dev)) {
Michael Krufky7c08fb02005-11-08 21:36:21 -08004274 printk(KERN_WARNING "bttv%d: Can't enable device.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004275 btv->c.nr);
4276 return -EIO;
4277 }
Yang Hongyang284901a2009-04-06 19:01:15 -07004278 if (pci_set_dma_mask(dev, DMA_BIT_MASK(32))) {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004279 printk(KERN_WARNING "bttv%d: No suitable DMA available.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004280 btv->c.nr);
4281 return -EIO;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004282 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004283 if (!request_mem_region(pci_resource_start(dev,0),
4284 pci_resource_len(dev,0),
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004285 btv->c.v4l2_dev.name)) {
Greg Kroah-Hartman228aef62006-06-12 15:16:52 -07004286 printk(KERN_WARNING "bttv%d: can't request iomem (0x%llx).\n",
4287 btv->c.nr,
4288 (unsigned long long)pci_resource_start(dev,0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004289 return -EBUSY;
4290 }
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004291 pci_set_master(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004292 pci_set_command(dev);
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004293
4294 result = v4l2_device_register(&dev->dev, &btv->c.v4l2_dev);
4295 if (result < 0) {
4296 printk(KERN_WARNING "bttv%d: v4l2_device_register() failed\n", btv->c.nr);
4297 goto fail0;
4298 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004299
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004300 pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision);
4301 pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
4302 printk(KERN_INFO "bttv%d: Bt%d (rev %d) at %s, ",
4303 bttv_num,btv->id, btv->revision, pci_name(dev));
Greg Kroah-Hartman228aef62006-06-12 15:16:52 -07004304 printk("irq: %d, latency: %d, mmio: 0x%llx\n",
4305 btv->c.pci->irq, lat,
4306 (unsigned long long)pci_resource_start(dev,0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004307 schedule();
4308
Akinobu Mita5f1693f2006-12-20 10:08:56 -03004309 btv->bt848_mmio = ioremap(pci_resource_start(dev, 0), 0x1000);
4310 if (NULL == btv->bt848_mmio) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004311 printk("bttv%d: ioremap() failed\n", btv->c.nr);
4312 result = -EIO;
4313 goto fail1;
4314 }
4315
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004316 /* identify card */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004317 bttv_idcard(btv);
4318
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004319 /* disable irqs, register irq handler */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004320 btwrite(0, BT848_INT_MASK);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004321 result = request_irq(btv->c.pci->irq, bttv_irq,
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004322 IRQF_SHARED | IRQF_DISABLED, btv->c.v4l2_dev.name, (void *)btv);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004323 if (result < 0) {
4324 printk(KERN_ERR "bttv%d: can't get IRQ %d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004325 bttv_num,btv->c.pci->irq);
4326 goto fail1;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004327 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004328
4329 if (0 != bttv_handle_chipset(btv)) {
4330 result = -EIO;
4331 goto fail2;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004332 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004333
4334 /* init options from insmod args */
4335 btv->opt_combfilter = combfilter;
4336 btv->opt_lumafilter = lumafilter;
4337 btv->opt_automute = automute;
4338 btv->opt_chroma_agc = chroma_agc;
4339 btv->opt_adc_crush = adc_crush;
4340 btv->opt_vcr_hack = vcr_hack;
4341 btv->opt_whitecrush_upper = whitecrush_upper;
4342 btv->opt_whitecrush_lower = whitecrush_lower;
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -07004343 btv->opt_uv_ratio = uv_ratio;
4344 btv->opt_full_luma_range = full_luma_range;
4345 btv->opt_coring = coring;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004346
4347 /* fill struct bttv with some useful defaults */
4348 btv->init.btv = btv;
4349 btv->init.ov.w.width = 320;
4350 btv->init.ov.w.height = 240;
Mauro Carvalho Chehabc96dd072007-10-26 16:51:47 -03004351 btv->init.fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004352 btv->init.width = 320;
4353 btv->init.height = 240;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004354 btv->input = 0;
4355
4356 /* initialize hardware */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004357 if (bttv_gpio)
4358 bttv_gpio_tracking(btv,"pre-init");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004359
4360 bttv_risc_init_main(btv);
4361 init_bt848(btv);
4362
4363 /* gpio */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004364 btwrite(0x00, BT848_GPIO_REG_INP);
4365 btwrite(0x00, BT848_GPIO_OUT_EN);
4366 if (bttv_verbose)
4367 bttv_gpio_tracking(btv,"init");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004368
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004369 /* needs to be done before i2c is registered */
4370 bttv_init_card1(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004371
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004372 /* register i2c + gpio */
4373 init_bttv_i2c(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004374
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004375 /* some card-specific stuff (needs working i2c) */
4376 bttv_init_card2(btv);
Hans Verkuil2c905772009-07-20 08:14:17 -03004377 bttv_init_tuner(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004378 init_irqreg(btv);
4379
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004380 /* register video4linux + input */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004381 if (!bttv_tvcards[btv->c.type].no_video) {
4382 bttv_register_video(btv);
4383 bt848_bright(btv,32768);
4384 bt848_contrast(btv,32768);
4385 bt848_hue(btv,32768);
4386 bt848_sat(btv,32768);
Hans Verkuil8bf2f8e2006-03-18 21:31:00 -03004387 audio_mute(btv, 1);
Trent Piepho333408f2007-07-03 15:08:10 -03004388 set_input(btv, 0, btv->tvnorm);
Michael Schimeke5bd0262007-01-18 16:17:39 -03004389 bttv_crop_reset(&btv->crop[0], btv->tvnorm);
4390 btv->crop[1] = btv->crop[0]; /* current = default */
4391 disclaim_vbi_lines(btv);
4392 disclaim_video_lines(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004393 }
4394
Jarod Wilsonf992a492007-03-24 15:23:50 -03004395 /* add subdevices and autoload dvb-bt8xx if needed */
4396 if (bttv_tvcards[btv->c.type].has_dvb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004397 bttv_sub_add_device(&btv->c, "dvb");
Jarod Wilsonf992a492007-03-24 15:23:50 -03004398 request_modules(btv);
4399 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004400
Jean Delvared90a4ae2010-02-16 14:22:37 -03004401 if (!disable_ir) {
4402 init_bttv_i2c_ir(btv);
4403 bttv_input_init(btv);
4404 }
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02004405
Linus Torvalds1da177e2005-04-16 15:20:36 -07004406 /* everything is fine */
4407 bttv_num++;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004408 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004409
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004410fail2:
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004411 free_irq(btv->c.pci->irq,btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004412
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004413fail1:
4414 v4l2_device_unregister(&btv->c.v4l2_dev);
4415
4416fail0:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004417 if (btv->bt848_mmio)
4418 iounmap(btv->bt848_mmio);
4419 release_mem_region(pci_resource_start(btv->c.pci,0),
4420 pci_resource_len(btv->c.pci,0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004421 return result;
4422}
4423
4424static void __devexit bttv_remove(struct pci_dev *pci_dev)
4425{
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004426 struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
4427 struct bttv *btv = to_bttv(v4l2_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004428
4429 if (bttv_verbose)
4430 printk("bttv%d: unloading\n",btv->c.nr);
4431
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004432 /* shutdown everything (DMA+IRQs) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004433 btand(~15, BT848_GPIO_DMA_CTL);
4434 btwrite(0, BT848_INT_MASK);
4435 btwrite(~0x0, BT848_INT_STAT);
4436 btwrite(0x0, BT848_GPIO_OUT_EN);
4437 if (bttv_gpio)
4438 bttv_gpio_tracking(btv,"cleanup");
4439
4440 /* tell gpio modules we are leaving ... */
4441 btv->shutdown=1;
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02004442 bttv_input_fini(btv);
Christopher Pascoe889aee82006-01-09 15:25:28 -02004443 bttv_sub_del_devices(&btv->c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004444
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004445 /* unregister i2c_bus + input */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004446 fini_bttv_i2c(btv);
4447
4448 /* unregister video4linux */
4449 bttv_unregister_video(btv);
4450
4451 /* free allocated memory */
4452 btcx_riscmem_free(btv->c.pci,&btv->main);
4453
4454 /* free ressources */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004455 free_irq(btv->c.pci->irq,btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004456 iounmap(btv->bt848_mmio);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004457 release_mem_region(pci_resource_start(btv->c.pci,0),
4458 pci_resource_len(btv->c.pci,0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004459
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004460 v4l2_device_unregister(&btv->c.v4l2_dev);
Trent Piepho4b10d3b2009-01-28 21:32:59 -03004461 bttvs[btv->c.nr] = NULL;
4462 kfree(btv);
4463
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004464 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004465}
4466
Alexey Dobriyan17bc98a2006-08-12 22:01:27 -03004467#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -07004468static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state)
4469{
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004470 struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
4471 struct bttv *btv = to_bttv(v4l2_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004472 struct bttv_buffer_set idle;
4473 unsigned long flags;
4474
Mauro Carvalho Chehab0f97a932005-09-09 13:04:05 -07004475 dprintk("bttv%d: suspend %d\n", btv->c.nr, state.event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004476
4477 /* stop dma + irqs */
4478 spin_lock_irqsave(&btv->s_lock,flags);
4479 memset(&idle, 0, sizeof(idle));
4480 btv->state.video = btv->curr;
4481 btv->state.vbi = btv->cvbi;
4482 btv->state.loop_irq = btv->loop_irq;
4483 btv->curr = idle;
4484 btv->loop_irq = 0;
4485 bttv_buffer_activate_video(btv, &idle);
4486 bttv_buffer_activate_vbi(btv, NULL);
4487 bttv_set_dma(btv, 0);
4488 btwrite(0, BT848_INT_MASK);
4489 spin_unlock_irqrestore(&btv->s_lock,flags);
4490
4491 /* save bt878 state */
4492 btv->state.gpio_enable = btread(BT848_GPIO_OUT_EN);
4493 btv->state.gpio_data = gpio_read();
4494
4495 /* save pci state */
4496 pci_save_state(pci_dev);
4497 if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
4498 pci_disable_device(pci_dev);
4499 btv->state.disabled = 1;
4500 }
4501 return 0;
4502}
4503
4504static int bttv_resume(struct pci_dev *pci_dev)
4505{
Hans Verkuil74fc7bd2009-03-14 12:36:54 -03004506 struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
4507 struct bttv *btv = to_bttv(v4l2_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004508 unsigned long flags;
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004509 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004510
4511 dprintk("bttv%d: resume\n", btv->c.nr);
4512
4513 /* restore pci state */
4514 if (btv->state.disabled) {
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004515 err=pci_enable_device(pci_dev);
4516 if (err) {
4517 printk(KERN_WARNING "bttv%d: Can't enable device.\n",
4518 btv->c.nr);
4519 return err;
4520 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004521 btv->state.disabled = 0;
4522 }
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004523 err=pci_set_power_state(pci_dev, PCI_D0);
4524 if (err) {
4525 pci_disable_device(pci_dev);
4526 printk(KERN_WARNING "bttv%d: Can't enable device.\n",
4527 btv->c.nr);
4528 btv->state.disabled = 1;
4529 return err;
4530 }
4531
Linus Torvalds1da177e2005-04-16 15:20:36 -07004532 pci_restore_state(pci_dev);
4533
4534 /* restore bt878 state */
4535 bttv_reinit_bt848(btv);
4536 gpio_inout(0xffffff, btv->state.gpio_enable);
4537 gpio_write(btv->state.gpio_data);
4538
4539 /* restart dma */
4540 spin_lock_irqsave(&btv->s_lock,flags);
4541 btv->curr = btv->state.video;
4542 btv->cvbi = btv->state.vbi;
4543 btv->loop_irq = btv->state.loop_irq;
4544 bttv_buffer_activate_video(btv, &btv->curr);
4545 bttv_buffer_activate_vbi(btv, btv->cvbi);
4546 bttv_set_dma(btv, 0);
4547 spin_unlock_irqrestore(&btv->s_lock,flags);
4548 return 0;
4549}
Alexey Dobriyan17bc98a2006-08-12 22:01:27 -03004550#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07004551
4552static struct pci_device_id bttv_pci_tbl[] = {
Joe Perches76e97412009-07-05 15:59:21 -03004553 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT848), 0},
4554 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT849), 0},
4555 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT878), 0},
4556 {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT879), 0},
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004557 {0,}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004558};
4559
4560MODULE_DEVICE_TABLE(pci, bttv_pci_tbl);
4561
4562static struct pci_driver bttv_pci_driver = {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004563 .name = "bttv",
4564 .id_table = bttv_pci_tbl,
4565 .probe = bttv_probe,
4566 .remove = __devexit_p(bttv_remove),
Alexey Dobriyan17bc98a2006-08-12 22:01:27 -03004567#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -07004568 .suspend = bttv_suspend,
4569 .resume = bttv_resume,
Alexey Dobriyan17bc98a2006-08-12 22:01:27 -03004570#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07004571};
4572
Adrian Bunk7d44e892007-12-11 19:23:43 -03004573static int __init bttv_init_module(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004574{
Randy Dunlapc526e222006-07-15 09:08:26 -03004575 int ret;
4576
Linus Torvalds1da177e2005-04-16 15:20:36 -07004577 bttv_num = 0;
4578
4579 printk(KERN_INFO "bttv: driver version %d.%d.%d loaded\n",
4580 (BTTV_VERSION_CODE >> 16) & 0xff,
4581 (BTTV_VERSION_CODE >> 8) & 0xff,
4582 BTTV_VERSION_CODE & 0xff);
4583#ifdef SNAPSHOT
4584 printk(KERN_INFO "bttv: snapshot date %04d-%02d-%02d\n",
4585 SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
4586#endif
4587 if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME)
4588 gbuffers = 2;
Filipe Rossetf41b6962009-05-28 11:11:53 -03004589 if (gbufsize > BTTV_MAX_FBUF)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004590 gbufsize = BTTV_MAX_FBUF;
4591 gbufsize = (gbufsize + PAGE_SIZE - 1) & PAGE_MASK;
4592 if (bttv_verbose)
4593 printk(KERN_INFO "bttv: using %d buffers with %dk (%d pages) each for capture\n",
4594 gbuffers, gbufsize >> 10, gbufsize >> PAGE_SHIFT);
4595
4596 bttv_check_chipset();
4597
Randy Dunlapc526e222006-07-15 09:08:26 -03004598 ret = bus_register(&bttv_sub_bus_type);
4599 if (ret < 0) {
4600 printk(KERN_WARNING "bttv: bus_register error: %d\n", ret);
4601 return ret;
4602 }
Akinobu Mita9e7e85e2007-12-17 14:26:29 -03004603 ret = pci_register_driver(&bttv_pci_driver);
4604 if (ret < 0)
4605 bus_unregister(&bttv_sub_bus_type);
4606
4607 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004608}
4609
Adrian Bunk7d44e892007-12-11 19:23:43 -03004610static void __exit bttv_cleanup_module(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004611{
4612 pci_unregister_driver(&bttv_pci_driver);
4613 bus_unregister(&bttv_sub_bus_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004614}
4615
4616module_init(bttv_init_module);
4617module_exit(bttv_cleanup_module);
4618
4619/*
4620 * Local variables:
4621 * c-basic-offset: 8
4622 * End:
4623 */