blob: 6fcc20de48d37d83044564f2a5964749181b983e [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
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25*/
26
27#include <linux/init.h>
28#include <linux/module.h>
29#include <linux/moduleparam.h>
30#include <linux/delay.h>
31#include <linux/errno.h>
32#include <linux/fs.h>
33#include <linux/kernel.h>
34#include <linux/sched.h>
35#include <linux/interrupt.h>
36#include <linux/kdev_t.h>
Mauro Carvalho Chehabfa9846a2005-07-12 13:58:42 -070037#include <linux/dma-mapping.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070038
39#include <asm/io.h>
40#include <asm/byteorder.h>
41
42#include "bttvp.h"
43
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -070044#include "rds.h"
45
46
Linus Torvalds1da177e2005-04-16 15:20:36 -070047unsigned int bttv_num; /* number of Bt848s in use */
48struct bttv bttvs[BTTV_MAX];
49
50unsigned int bttv_debug = 0;
51unsigned int bttv_verbose = 1;
52unsigned int bttv_gpio = 0;
53
54/* config variables */
55#ifdef __BIG_ENDIAN
56static unsigned int bigendian=1;
57#else
58static unsigned int bigendian=0;
59#endif
60static unsigned int radio[BTTV_MAX];
61static unsigned int irq_debug = 0;
62static unsigned int gbuffers = 8;
63static unsigned int gbufsize = 0x208000;
64
65static int video_nr = -1;
66static int radio_nr = -1;
67static int vbi_nr = -1;
68static int debug_latency = 0;
69
70static unsigned int fdsr = 0;
71
72/* options */
73static unsigned int combfilter = 0;
74static unsigned int lumafilter = 0;
75static unsigned int automute = 1;
76static unsigned int chroma_agc = 0;
77static unsigned int adc_crush = 1;
78static unsigned int whitecrush_upper = 0xCF;
79static unsigned int whitecrush_lower = 0x7F;
80static unsigned int vcr_hack = 0;
81static unsigned int irq_iswitch = 0;
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -070082static unsigned int uv_ratio = 50;
83static unsigned int full_luma_range = 0;
84static unsigned int coring = 0;
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -070085extern int no_overlay;
Linus Torvalds1da177e2005-04-16 15:20:36 -070086
87/* API features (turn on/off stuff for testing) */
88static unsigned int v4l2 = 1;
89
90
91/* insmod args */
92module_param(bttv_verbose, int, 0644);
93module_param(bttv_gpio, int, 0644);
94module_param(bttv_debug, int, 0644);
95module_param(irq_debug, int, 0644);
96module_param(debug_latency, int, 0644);
97
98module_param(fdsr, int, 0444);
99module_param(video_nr, int, 0444);
100module_param(radio_nr, int, 0444);
101module_param(vbi_nr, int, 0444);
102module_param(gbuffers, int, 0444);
103module_param(gbufsize, int, 0444);
104
105module_param(v4l2, int, 0644);
106module_param(bigendian, int, 0644);
107module_param(irq_iswitch, int, 0644);
108module_param(combfilter, int, 0444);
109module_param(lumafilter, int, 0444);
110module_param(automute, int, 0444);
111module_param(chroma_agc, int, 0444);
112module_param(adc_crush, int, 0444);
113module_param(whitecrush_upper, int, 0444);
114module_param(whitecrush_lower, int, 0444);
115module_param(vcr_hack, int, 0444);
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700116module_param(uv_ratio, int, 0444);
117module_param(full_luma_range, int, 0444);
118module_param(coring, int, 0444);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119
120module_param_array(radio, int, NULL, 0444);
121
122MODULE_PARM_DESC(radio,"The TV card supports radio, default is 0 (no)");
123MODULE_PARM_DESC(bigendian,"byte order of the framebuffer, default is native endian");
124MODULE_PARM_DESC(bttv_verbose,"verbose startup messages, default is 1 (yes)");
125MODULE_PARM_DESC(bttv_gpio,"log gpio changes, default is 0 (no)");
126MODULE_PARM_DESC(bttv_debug,"debug messages, default is 0 (no)");
127MODULE_PARM_DESC(irq_debug,"irq handler debug messages, default is 0 (no)");
128MODULE_PARM_DESC(gbuffers,"number of capture buffers. range 2-32, default 8");
129MODULE_PARM_DESC(gbufsize,"size of the capture buffers, default is 0x208000");
130MODULE_PARM_DESC(automute,"mute audio on bad/missing video signal, default is 1 (yes)");
131MODULE_PARM_DESC(chroma_agc,"enables the AGC of chroma signal, default is 0 (no)");
132MODULE_PARM_DESC(adc_crush,"enables the luminance ADC crush, default is 1 (yes)");
133MODULE_PARM_DESC(whitecrush_upper,"sets the white crush upper value, default is 207");
134MODULE_PARM_DESC(whitecrush_lower,"sets the white crush lower value, default is 127");
135MODULE_PARM_DESC(vcr_hack,"enables the VCR hack (improves synch on poor VCR tapes), default is 0 (no)");
136MODULE_PARM_DESC(irq_iswitch,"switch inputs in irq handler");
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700137MODULE_PARM_DESC(uv_ratio,"ratio between u and v gains, default is 50");
138MODULE_PARM_DESC(full_luma_range,"use the full luma range, default is 0 (no)");
139MODULE_PARM_DESC(coring,"set the luma coring level, default is 0 (no)");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140
141MODULE_DESCRIPTION("bttv - v4l/v4l2 driver module for bt848/878 based cards");
142MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr");
143MODULE_LICENSE("GPL");
144
145/* ----------------------------------------------------------------------- */
146/* sysfs */
147
148static ssize_t show_card(struct class_device *cd, char *buf)
149{
150 struct video_device *vfd = to_video_device(cd);
151 struct bttv *btv = dev_get_drvdata(vfd->dev);
152 return sprintf(buf, "%d\n", btv ? btv->c.type : UNSET);
153}
154static CLASS_DEVICE_ATTR(card, S_IRUGO, show_card, NULL);
155
156/* ----------------------------------------------------------------------- */
157/* static data */
158
159/* special timing tables from conexant... */
160static u8 SRAM_Table[][60] =
161{
162 /* PAL digital input over GPIO[7:0] */
163 {
164 45, // 45 bytes following
165 0x36,0x11,0x01,0x00,0x90,0x02,0x05,0x10,0x04,0x16,
166 0x12,0x05,0x11,0x00,0x04,0x12,0xC0,0x00,0x31,0x00,
167 0x06,0x51,0x08,0x03,0x89,0x08,0x07,0xC0,0x44,0x00,
168 0x81,0x01,0x01,0xA9,0x0D,0x02,0x02,0x50,0x03,0x37,
169 0x37,0x00,0xAF,0x21,0x00
170 },
171 /* NTSC digital input over GPIO[7:0] */
172 {
173 51, // 51 bytes following
174 0x0C,0xC0,0x00,0x00,0x90,0x02,0x03,0x10,0x03,0x06,
175 0x10,0x04,0x12,0x12,0x05,0x02,0x13,0x04,0x19,0x00,
176 0x04,0x39,0x00,0x06,0x59,0x08,0x03,0x83,0x08,0x07,
177 0x03,0x50,0x00,0xC0,0x40,0x00,0x86,0x01,0x01,0xA6,
178 0x0D,0x02,0x03,0x11,0x01,0x05,0x37,0x00,0xAC,0x21,
179 0x00,
180 },
181 // TGB_NTSC392 // quartzsight
182 // This table has been modified to be used for Fusion Rev D
183 {
184 0x2A, // size of table = 42
185 0x06, 0x08, 0x04, 0x0a, 0xc0, 0x00, 0x18, 0x08, 0x03, 0x24,
186 0x08, 0x07, 0x02, 0x90, 0x02, 0x08, 0x10, 0x04, 0x0c, 0x10,
187 0x05, 0x2c, 0x11, 0x04, 0x55, 0x48, 0x00, 0x05, 0x50, 0x00,
188 0xbf, 0x0c, 0x02, 0x2f, 0x3d, 0x00, 0x2f, 0x3f, 0x00, 0xc3,
189 0x20, 0x00
190 }
191};
192
193const struct bttv_tvnorm bttv_tvnorms[] = {
194 /* PAL-BDGHI */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800195 /* max. active video is actually 922, but 924 is divisible by 4 and 3! */
196 /* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 {
198 .v4l2_id = V4L2_STD_PAL,
199 .name = "PAL",
200 .Fsc = 35468950,
201 .swidth = 924,
202 .sheight = 576,
203 .totalwidth = 1135,
204 .adelay = 0x7f,
205 .bdelay = 0x72,
206 .iform = (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
207 .scaledtwidth = 1135,
208 .hdelayx1 = 186,
209 .hactivex1 = 924,
210 .vdelay = 0x20,
211 .vbipack = 255,
212 .sram = 0,
213 },{
214 .v4l2_id = V4L2_STD_NTSC_M,
215 .name = "NTSC",
216 .Fsc = 28636363,
217 .swidth = 768,
218 .sheight = 480,
219 .totalwidth = 910,
220 .adelay = 0x68,
221 .bdelay = 0x5d,
222 .iform = (BT848_IFORM_NTSC|BT848_IFORM_XT0),
223 .scaledtwidth = 910,
224 .hdelayx1 = 128,
225 .hactivex1 = 910,
226 .vdelay = 0x1a,
227 .vbipack = 144,
228 .sram = 1,
229 },{
230 .v4l2_id = V4L2_STD_SECAM,
231 .name = "SECAM",
232 .Fsc = 35468950,
233 .swidth = 924,
234 .sheight = 576,
235 .totalwidth = 1135,
236 .adelay = 0x7f,
237 .bdelay = 0xb0,
238 .iform = (BT848_IFORM_SECAM|BT848_IFORM_XT1),
239 .scaledtwidth = 1135,
240 .hdelayx1 = 186,
241 .hactivex1 = 922,
242 .vdelay = 0x20,
243 .vbipack = 255,
244 .sram = 0, /* like PAL, correct? */
245 },{
246 .v4l2_id = V4L2_STD_PAL_Nc,
247 .name = "PAL-Nc",
248 .Fsc = 28636363,
249 .swidth = 640,
250 .sheight = 576,
251 .totalwidth = 910,
252 .adelay = 0x68,
253 .bdelay = 0x5d,
254 .iform = (BT848_IFORM_PAL_NC|BT848_IFORM_XT0),
255 .scaledtwidth = 780,
256 .hdelayx1 = 130,
257 .hactivex1 = 734,
258 .vdelay = 0x1a,
259 .vbipack = 144,
260 .sram = -1,
261 },{
262 .v4l2_id = V4L2_STD_PAL_M,
263 .name = "PAL-M",
264 .Fsc = 28636363,
265 .swidth = 640,
266 .sheight = 480,
267 .totalwidth = 910,
268 .adelay = 0x68,
269 .bdelay = 0x5d,
270 .iform = (BT848_IFORM_PAL_M|BT848_IFORM_XT0),
271 .scaledtwidth = 780,
272 .hdelayx1 = 135,
273 .hactivex1 = 754,
274 .vdelay = 0x1a,
275 .vbipack = 144,
276 .sram = -1,
277 },{
278 .v4l2_id = V4L2_STD_PAL_N,
279 .name = "PAL-N",
280 .Fsc = 35468950,
281 .swidth = 768,
282 .sheight = 576,
283 .totalwidth = 1135,
284 .adelay = 0x7f,
285 .bdelay = 0x72,
286 .iform = (BT848_IFORM_PAL_N|BT848_IFORM_XT1),
287 .scaledtwidth = 944,
288 .hdelayx1 = 186,
289 .hactivex1 = 922,
290 .vdelay = 0x20,
291 .vbipack = 144,
292 .sram = -1,
293 },{
294 .v4l2_id = V4L2_STD_NTSC_M_JP,
295 .name = "NTSC-JP",
296 .Fsc = 28636363,
297 .swidth = 640,
298 .sheight = 480,
299 .totalwidth = 910,
300 .adelay = 0x68,
301 .bdelay = 0x5d,
302 .iform = (BT848_IFORM_NTSC_J|BT848_IFORM_XT0),
303 .scaledtwidth = 780,
304 .hdelayx1 = 135,
305 .hactivex1 = 754,
306 .vdelay = 0x16,
307 .vbipack = 144,
308 .sram = -1,
309 },{
310 /* that one hopefully works with the strange timing
311 * which video recorders produce when playing a NTSC
312 * tape on a PAL TV ... */
313 .v4l2_id = V4L2_STD_PAL_60,
314 .name = "PAL-60",
315 .Fsc = 35468950,
316 .swidth = 924,
317 .sheight = 480,
318 .totalwidth = 1135,
319 .adelay = 0x7f,
320 .bdelay = 0x72,
321 .iform = (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
322 .scaledtwidth = 1135,
323 .hdelayx1 = 186,
324 .hactivex1 = 924,
325 .vdelay = 0x1a,
326 .vbipack = 255,
327 .vtotal = 524,
328 .sram = -1,
329 }
330};
331static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms);
332
333/* ----------------------------------------------------------------------- */
334/* bttv format list
335 packed pixel formats must come first */
336static const struct bttv_format bttv_formats[] = {
337 {
338 .name = "8 bpp, gray",
339 .palette = VIDEO_PALETTE_GREY,
340 .fourcc = V4L2_PIX_FMT_GREY,
341 .btformat = BT848_COLOR_FMT_Y8,
342 .depth = 8,
343 .flags = FORMAT_FLAGS_PACKED,
344 },{
345 .name = "8 bpp, dithered color",
346 .palette = VIDEO_PALETTE_HI240,
347 .fourcc = V4L2_PIX_FMT_HI240,
348 .btformat = BT848_COLOR_FMT_RGB8,
349 .depth = 8,
350 .flags = FORMAT_FLAGS_PACKED | FORMAT_FLAGS_DITHER,
351 },{
352 .name = "15 bpp RGB, le",
353 .palette = VIDEO_PALETTE_RGB555,
354 .fourcc = V4L2_PIX_FMT_RGB555,
355 .btformat = BT848_COLOR_FMT_RGB15,
356 .depth = 16,
357 .flags = FORMAT_FLAGS_PACKED,
358 },{
359 .name = "15 bpp RGB, be",
360 .palette = -1,
361 .fourcc = V4L2_PIX_FMT_RGB555X,
362 .btformat = BT848_COLOR_FMT_RGB15,
363 .btswap = 0x03, /* byteswap */
364 .depth = 16,
365 .flags = FORMAT_FLAGS_PACKED,
366 },{
367 .name = "16 bpp RGB, le",
368 .palette = VIDEO_PALETTE_RGB565,
369 .fourcc = V4L2_PIX_FMT_RGB565,
370 .btformat = BT848_COLOR_FMT_RGB16,
371 .depth = 16,
372 .flags = FORMAT_FLAGS_PACKED,
373 },{
374 .name = "16 bpp RGB, be",
375 .palette = -1,
376 .fourcc = V4L2_PIX_FMT_RGB565X,
377 .btformat = BT848_COLOR_FMT_RGB16,
378 .btswap = 0x03, /* byteswap */
379 .depth = 16,
380 .flags = FORMAT_FLAGS_PACKED,
381 },{
382 .name = "24 bpp RGB, le",
383 .palette = VIDEO_PALETTE_RGB24,
384 .fourcc = V4L2_PIX_FMT_BGR24,
385 .btformat = BT848_COLOR_FMT_RGB24,
386 .depth = 24,
387 .flags = FORMAT_FLAGS_PACKED,
388 },{
389 .name = "32 bpp RGB, le",
390 .palette = VIDEO_PALETTE_RGB32,
391 .fourcc = V4L2_PIX_FMT_BGR32,
392 .btformat = BT848_COLOR_FMT_RGB32,
393 .depth = 32,
394 .flags = FORMAT_FLAGS_PACKED,
395 },{
396 .name = "32 bpp RGB, be",
397 .palette = -1,
398 .fourcc = V4L2_PIX_FMT_RGB32,
399 .btformat = BT848_COLOR_FMT_RGB32,
400 .btswap = 0x0f, /* byte+word swap */
401 .depth = 32,
402 .flags = FORMAT_FLAGS_PACKED,
403 },{
404 .name = "4:2:2, packed, YUYV",
405 .palette = VIDEO_PALETTE_YUV422,
406 .fourcc = V4L2_PIX_FMT_YUYV,
407 .btformat = BT848_COLOR_FMT_YUY2,
408 .depth = 16,
409 .flags = FORMAT_FLAGS_PACKED,
410 },{
411 .name = "4:2:2, packed, YUYV",
412 .palette = VIDEO_PALETTE_YUYV,
413 .fourcc = V4L2_PIX_FMT_YUYV,
414 .btformat = BT848_COLOR_FMT_YUY2,
415 .depth = 16,
416 .flags = FORMAT_FLAGS_PACKED,
417 },{
418 .name = "4:2:2, packed, UYVY",
419 .palette = VIDEO_PALETTE_UYVY,
420 .fourcc = V4L2_PIX_FMT_UYVY,
421 .btformat = BT848_COLOR_FMT_YUY2,
422 .btswap = 0x03, /* byteswap */
423 .depth = 16,
424 .flags = FORMAT_FLAGS_PACKED,
425 },{
426 .name = "4:2:2, planar, Y-Cb-Cr",
427 .palette = VIDEO_PALETTE_YUV422P,
428 .fourcc = V4L2_PIX_FMT_YUV422P,
429 .btformat = BT848_COLOR_FMT_YCrCb422,
430 .depth = 16,
431 .flags = FORMAT_FLAGS_PLANAR,
432 .hshift = 1,
433 .vshift = 0,
434 },{
435 .name = "4:2:0, planar, Y-Cb-Cr",
436 .palette = VIDEO_PALETTE_YUV420P,
437 .fourcc = V4L2_PIX_FMT_YUV420,
438 .btformat = BT848_COLOR_FMT_YCrCb422,
439 .depth = 12,
440 .flags = FORMAT_FLAGS_PLANAR,
441 .hshift = 1,
442 .vshift = 1,
443 },{
444 .name = "4:2:0, planar, Y-Cr-Cb",
445 .palette = -1,
446 .fourcc = V4L2_PIX_FMT_YVU420,
447 .btformat = BT848_COLOR_FMT_YCrCb422,
448 .depth = 12,
449 .flags = FORMAT_FLAGS_PLANAR | FORMAT_FLAGS_CrCb,
450 .hshift = 1,
451 .vshift = 1,
452 },{
453 .name = "4:1:1, planar, Y-Cb-Cr",
454 .palette = VIDEO_PALETTE_YUV411P,
455 .fourcc = V4L2_PIX_FMT_YUV411P,
456 .btformat = BT848_COLOR_FMT_YCrCb411,
457 .depth = 12,
458 .flags = FORMAT_FLAGS_PLANAR,
459 .hshift = 2,
460 .vshift = 0,
461 },{
462 .name = "4:1:0, planar, Y-Cb-Cr",
463 .palette = VIDEO_PALETTE_YUV410P,
464 .fourcc = V4L2_PIX_FMT_YUV410,
465 .btformat = BT848_COLOR_FMT_YCrCb411,
466 .depth = 9,
467 .flags = FORMAT_FLAGS_PLANAR,
468 .hshift = 2,
469 .vshift = 2,
470 },{
471 .name = "4:1:0, planar, Y-Cr-Cb",
472 .palette = -1,
473 .fourcc = V4L2_PIX_FMT_YVU410,
474 .btformat = BT848_COLOR_FMT_YCrCb411,
475 .depth = 9,
476 .flags = FORMAT_FLAGS_PLANAR | FORMAT_FLAGS_CrCb,
477 .hshift = 2,
478 .vshift = 2,
479 },{
480 .name = "raw scanlines",
481 .palette = VIDEO_PALETTE_RAW,
482 .fourcc = -1,
483 .btformat = BT848_COLOR_FMT_RAW,
484 .depth = 8,
485 .flags = FORMAT_FLAGS_RAW,
486 }
487};
488static const unsigned int BTTV_FORMATS = ARRAY_SIZE(bttv_formats);
489
490/* ----------------------------------------------------------------------- */
491
492#define V4L2_CID_PRIVATE_CHROMA_AGC (V4L2_CID_PRIVATE_BASE + 0)
493#define V4L2_CID_PRIVATE_COMBFILTER (V4L2_CID_PRIVATE_BASE + 1)
494#define V4L2_CID_PRIVATE_AUTOMUTE (V4L2_CID_PRIVATE_BASE + 2)
495#define V4L2_CID_PRIVATE_LUMAFILTER (V4L2_CID_PRIVATE_BASE + 3)
496#define V4L2_CID_PRIVATE_AGC_CRUSH (V4L2_CID_PRIVATE_BASE + 4)
497#define V4L2_CID_PRIVATE_VCR_HACK (V4L2_CID_PRIVATE_BASE + 5)
498#define V4L2_CID_PRIVATE_WHITECRUSH_UPPER (V4L2_CID_PRIVATE_BASE + 6)
499#define V4L2_CID_PRIVATE_WHITECRUSH_LOWER (V4L2_CID_PRIVATE_BASE + 7)
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700500#define V4L2_CID_PRIVATE_UV_RATIO (V4L2_CID_PRIVATE_BASE + 8)
501#define V4L2_CID_PRIVATE_FULL_LUMA_RANGE (V4L2_CID_PRIVATE_BASE + 9)
502#define V4L2_CID_PRIVATE_CORING (V4L2_CID_PRIVATE_BASE + 10)
503#define V4L2_CID_PRIVATE_LASTP1 (V4L2_CID_PRIVATE_BASE + 11)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504
505static const struct v4l2_queryctrl no_ctl = {
506 .name = "42",
507 .flags = V4L2_CTRL_FLAG_DISABLED,
508};
509static const struct v4l2_queryctrl bttv_ctls[] = {
510 /* --- video --- */
511 {
512 .id = V4L2_CID_BRIGHTNESS,
513 .name = "Brightness",
514 .minimum = 0,
515 .maximum = 65535,
516 .step = 256,
517 .default_value = 32768,
518 .type = V4L2_CTRL_TYPE_INTEGER,
519 },{
520 .id = V4L2_CID_CONTRAST,
521 .name = "Contrast",
522 .minimum = 0,
523 .maximum = 65535,
524 .step = 128,
525 .default_value = 32768,
526 .type = V4L2_CTRL_TYPE_INTEGER,
527 },{
528 .id = V4L2_CID_SATURATION,
529 .name = "Saturation",
530 .minimum = 0,
531 .maximum = 65535,
532 .step = 128,
533 .default_value = 32768,
534 .type = V4L2_CTRL_TYPE_INTEGER,
535 },{
536 .id = V4L2_CID_HUE,
537 .name = "Hue",
538 .minimum = 0,
539 .maximum = 65535,
540 .step = 256,
541 .default_value = 32768,
542 .type = V4L2_CTRL_TYPE_INTEGER,
543 },
544 /* --- audio --- */
545 {
546 .id = V4L2_CID_AUDIO_MUTE,
547 .name = "Mute",
548 .minimum = 0,
549 .maximum = 1,
550 .type = V4L2_CTRL_TYPE_BOOLEAN,
551 },{
552 .id = V4L2_CID_AUDIO_VOLUME,
553 .name = "Volume",
554 .minimum = 0,
555 .maximum = 65535,
556 .step = 65535/100,
557 .default_value = 65535,
558 .type = V4L2_CTRL_TYPE_INTEGER,
559 },{
560 .id = V4L2_CID_AUDIO_BALANCE,
561 .name = "Balance",
562 .minimum = 0,
563 .maximum = 65535,
564 .step = 65535/100,
565 .default_value = 32768,
566 .type = V4L2_CTRL_TYPE_INTEGER,
567 },{
568 .id = V4L2_CID_AUDIO_BASS,
569 .name = "Bass",
570 .minimum = 0,
571 .maximum = 65535,
572 .step = 65535/100,
573 .default_value = 32768,
574 .type = V4L2_CTRL_TYPE_INTEGER,
575 },{
576 .id = V4L2_CID_AUDIO_TREBLE,
577 .name = "Treble",
578 .minimum = 0,
579 .maximum = 65535,
580 .step = 65535/100,
581 .default_value = 32768,
582 .type = V4L2_CTRL_TYPE_INTEGER,
583 },
584 /* --- private --- */
585 {
586 .id = V4L2_CID_PRIVATE_CHROMA_AGC,
587 .name = "chroma agc",
588 .minimum = 0,
589 .maximum = 1,
590 .type = V4L2_CTRL_TYPE_BOOLEAN,
591 },{
592 .id = V4L2_CID_PRIVATE_COMBFILTER,
593 .name = "combfilter",
594 .minimum = 0,
595 .maximum = 1,
596 .type = V4L2_CTRL_TYPE_BOOLEAN,
597 },{
598 .id = V4L2_CID_PRIVATE_AUTOMUTE,
599 .name = "automute",
600 .minimum = 0,
601 .maximum = 1,
602 .type = V4L2_CTRL_TYPE_BOOLEAN,
603 },{
604 .id = V4L2_CID_PRIVATE_LUMAFILTER,
605 .name = "luma decimation filter",
606 .minimum = 0,
607 .maximum = 1,
608 .type = V4L2_CTRL_TYPE_BOOLEAN,
609 },{
610 .id = V4L2_CID_PRIVATE_AGC_CRUSH,
611 .name = "agc crush",
612 .minimum = 0,
613 .maximum = 1,
614 .type = V4L2_CTRL_TYPE_BOOLEAN,
615 },{
616 .id = V4L2_CID_PRIVATE_VCR_HACK,
617 .name = "vcr hack",
618 .minimum = 0,
619 .maximum = 1,
620 .type = V4L2_CTRL_TYPE_BOOLEAN,
621 },{
622 .id = V4L2_CID_PRIVATE_WHITECRUSH_UPPER,
623 .name = "whitecrush upper",
624 .minimum = 0,
625 .maximum = 255,
626 .step = 1,
627 .default_value = 0xCF,
628 .type = V4L2_CTRL_TYPE_INTEGER,
629 },{
630 .id = V4L2_CID_PRIVATE_WHITECRUSH_LOWER,
631 .name = "whitecrush lower",
632 .minimum = 0,
633 .maximum = 255,
634 .step = 1,
635 .default_value = 0x7F,
636 .type = V4L2_CTRL_TYPE_INTEGER,
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700637 },{
638 .id = V4L2_CID_PRIVATE_UV_RATIO,
639 .name = "uv ratio",
640 .minimum = 0,
641 .maximum = 100,
642 .step = 1,
643 .default_value = 50,
644 .type = V4L2_CTRL_TYPE_INTEGER,
645 },{
646 .id = V4L2_CID_PRIVATE_FULL_LUMA_RANGE,
647 .name = "full luma range",
648 .minimum = 0,
649 .maximum = 1,
650 .type = V4L2_CTRL_TYPE_BOOLEAN,
651 },{
652 .id = V4L2_CID_PRIVATE_CORING,
653 .name = "coring",
654 .minimum = 0,
655 .maximum = 3,
656 .step = 1,
657 .default_value = 0,
658 .type = V4L2_CTRL_TYPE_INTEGER,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 }
660
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700661
662
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663};
664static const int BTTV_CTLS = ARRAY_SIZE(bttv_ctls);
665
666/* ----------------------------------------------------------------------- */
667/* resource management */
668
669static
670int check_alloc_btres(struct bttv *btv, struct bttv_fh *fh, int bit)
671{
672 if (fh->resources & bit)
673 /* have it already allocated */
674 return 1;
675
676 /* is it free? */
677 down(&btv->reslock);
678 if (btv->resources & bit) {
679 /* no, someone else uses it */
680 up(&btv->reslock);
681 return 0;
682 }
683 /* it's free, grab it */
684 fh->resources |= bit;
685 btv->resources |= bit;
686 up(&btv->reslock);
687 return 1;
688}
689
690static
691int check_btres(struct bttv_fh *fh, int bit)
692{
693 return (fh->resources & bit);
694}
695
696static
697int locked_btres(struct bttv *btv, int bit)
698{
699 return (btv->resources & bit);
700}
701
702static
703void free_btres(struct bttv *btv, struct bttv_fh *fh, int bits)
704{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 if ((fh->resources & bits) != bits) {
706 /* trying to free ressources not allocated by us ... */
707 printk("bttv: BUG! (btres)\n");
708 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709 down(&btv->reslock);
710 fh->resources &= ~bits;
711 btv->resources &= ~bits;
712 up(&btv->reslock);
713}
714
715/* ----------------------------------------------------------------------- */
716/* If Bt848a or Bt849, use PLL for PAL/SECAM and crystal for NTSC */
717
718/* Frequency = (F_input / PLL_X) * PLL_I.PLL_F/PLL_C
719 PLL_X = Reference pre-divider (0=1, 1=2)
720 PLL_C = Post divider (0=6, 1=4)
721 PLL_I = Integer input
722 PLL_F = Fractional input
723
724 F_input = 28.636363 MHz:
725 PAL (CLKx2 = 35.46895 MHz): PLL_X = 1, PLL_I = 0x0E, PLL_F = 0xDCF9, PLL_C = 0
726*/
727
728static void set_pll_freq(struct bttv *btv, unsigned int fin, unsigned int fout)
729{
730 unsigned char fl, fh, fi;
731
732 /* prevent overflows */
733 fin/=4;
734 fout/=4;
735
736 fout*=12;
737 fi=fout/fin;
738
739 fout=(fout%fin)*256;
740 fh=fout/fin;
741
742 fout=(fout%fin)*256;
743 fl=fout/fin;
744
745 btwrite(fl, BT848_PLL_F_LO);
746 btwrite(fh, BT848_PLL_F_HI);
747 btwrite(fi|BT848_PLL_X, BT848_PLL_XCI);
748}
749
750static void set_pll(struct bttv *btv)
751{
752 int i;
753
754 if (!btv->pll.pll_crystal)
755 return;
756
757 if (btv->pll.pll_ofreq == btv->pll.pll_current) {
758 dprintk("bttv%d: PLL: no change required\n",btv->c.nr);
759 return;
760 }
761
762 if (btv->pll.pll_ifreq == btv->pll.pll_ofreq) {
763 /* no PLL needed */
764 if (btv->pll.pll_current == 0)
765 return;
Bernd Petrovitsche1e70a22005-09-22 21:43:53 -0700766 bttv_printk(KERN_INFO "bttv%d: PLL can sleep, using XTAL (%d).\n",
767 btv->c.nr,btv->pll.pll_ifreq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 btwrite(0x00,BT848_TGCTRL);
769 btwrite(0x00,BT848_PLL_XCI);
770 btv->pll.pll_current = 0;
771 return;
772 }
773
Bernd Petrovitsche1e70a22005-09-22 21:43:53 -0700774 bttv_printk(KERN_INFO "bttv%d: PLL: %d => %d ",btv->c.nr,
775 btv->pll.pll_ifreq, btv->pll.pll_ofreq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 set_pll_freq(btv, btv->pll.pll_ifreq, btv->pll.pll_ofreq);
777
778 for (i=0; i<10; i++) {
779 /* Let other people run while the PLL stabilizes */
Bernd Petrovitsche1e70a22005-09-22 21:43:53 -0700780 bttv_printk(".");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 msleep(10);
782
783 if (btread(BT848_DSTATUS) & BT848_DSTATUS_PLOCK) {
784 btwrite(0,BT848_DSTATUS);
785 } else {
786 btwrite(0x08,BT848_TGCTRL);
787 btv->pll.pll_current = btv->pll.pll_ofreq;
Bernd Petrovitsche1e70a22005-09-22 21:43:53 -0700788 bttv_printk(" ok\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 return;
790 }
791 }
792 btv->pll.pll_current = -1;
Bernd Petrovitsche1e70a22005-09-22 21:43:53 -0700793 bttv_printk("failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 return;
795}
796
797/* used to switch between the bt848's analog/digital video capture modes */
798static void bt848A_set_timing(struct bttv *btv)
799{
800 int i, len;
801 int table_idx = bttv_tvnorms[btv->tvnorm].sram;
802 int fsc = bttv_tvnorms[btv->tvnorm].Fsc;
803
804 if (UNSET == bttv_tvcards[btv->c.type].muxsel[btv->input]) {
805 dprintk("bttv%d: load digital timing table (table_idx=%d)\n",
806 btv->c.nr,table_idx);
807
808 /* timing change...reset timing generator address */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800809 btwrite(0x00, BT848_TGCTRL);
810 btwrite(0x02, BT848_TGCTRL);
811 btwrite(0x00, BT848_TGCTRL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812
813 len=SRAM_Table[table_idx][0];
814 for(i = 1; i <= len; i++)
815 btwrite(SRAM_Table[table_idx][i],BT848_TGLB);
816 btv->pll.pll_ofreq = 27000000;
817
818 set_pll(btv);
819 btwrite(0x11, BT848_TGCTRL);
820 btwrite(0x41, BT848_DVSIF);
821 } else {
822 btv->pll.pll_ofreq = fsc;
823 set_pll(btv);
824 btwrite(0x0, BT848_DVSIF);
825 }
826}
827
828/* ----------------------------------------------------------------------- */
829
830static void bt848_bright(struct bttv *btv, int bright)
831{
832 int value;
833
834 // printk("bttv: set bright: %d\n",bright); // DEBUG
835 btv->bright = bright;
836
837 /* We want -128 to 127 we get 0-65535 */
838 value = (bright >> 8) - 128;
839 btwrite(value & 0xff, BT848_BRIGHT);
840}
841
842static void bt848_hue(struct bttv *btv, int hue)
843{
844 int value;
845
846 btv->hue = hue;
847
848 /* -128 to 127 */
849 value = (hue >> 8) - 128;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800850 btwrite(value & 0xff, BT848_HUE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851}
852
853static void bt848_contrast(struct bttv *btv, int cont)
854{
855 int value,hibit;
856
857 btv->contrast = cont;
858
859 /* 0-511 */
860 value = (cont >> 7);
861 hibit = (value >> 6) & 4;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800862 btwrite(value & 0xff, BT848_CONTRAST_LO);
863 btaor(hibit, ~4, BT848_E_CONTROL);
864 btaor(hibit, ~4, BT848_O_CONTROL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865}
866
867static void bt848_sat(struct bttv *btv, int color)
868{
869 int val_u,val_v,hibits;
870
871 btv->saturation = color;
872
873 /* 0-511 for the color */
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700874 val_u = ((color * btv->opt_uv_ratio) / 50) >> 7;
875 val_v = (((color * (100 - btv->opt_uv_ratio) / 50) >>7)*180L)/254;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800876 hibits = (val_u >> 7) & 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 hibits |= (val_v >> 8) & 1;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800878 btwrite(val_u & 0xff, BT848_SAT_U_LO);
879 btwrite(val_v & 0xff, BT848_SAT_V_LO);
880 btaor(hibits, ~3, BT848_E_CONTROL);
881 btaor(hibits, ~3, BT848_O_CONTROL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882}
883
884/* ----------------------------------------------------------------------- */
885
886static int
887video_mux(struct bttv *btv, unsigned int input)
888{
889 int mux,mask2;
890
891 if (input >= bttv_tvcards[btv->c.type].video_inputs)
892 return -EINVAL;
893
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800894 /* needed by RemoteVideo MX */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 mask2 = bttv_tvcards[btv->c.type].gpiomask2;
896 if (mask2)
897 gpio_inout(mask2,mask2);
898
899 if (input == btv->svhs) {
900 btor(BT848_CONTROL_COMP, BT848_E_CONTROL);
901 btor(BT848_CONTROL_COMP, BT848_O_CONTROL);
902 } else {
903 btand(~BT848_CONTROL_COMP, BT848_E_CONTROL);
904 btand(~BT848_CONTROL_COMP, BT848_O_CONTROL);
905 }
906 mux = bttv_tvcards[btv->c.type].muxsel[input] & 3;
907 btaor(mux<<5, ~(3<<5), BT848_IFORM);
908 dprintk(KERN_DEBUG "bttv%d: video mux: input=%d mux=%d\n",
909 btv->c.nr,input,mux);
910
911 /* card specific hook */
912 if(bttv_tvcards[btv->c.type].muxsel_hook)
913 bttv_tvcards[btv->c.type].muxsel_hook (btv, input);
914 return 0;
915}
916
917static char *audio_modes[] = {
918 "audio: tuner", "audio: radio", "audio: extern",
919 "audio: intern", "audio: off"
920};
921
922static int
923audio_mux(struct bttv *btv, int mode)
924{
925 int val,mux,i2c_mux,signal;
926
927 gpio_inout(bttv_tvcards[btv->c.type].gpiomask,
928 bttv_tvcards[btv->c.type].gpiomask);
929 signal = btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC;
930
931 switch (mode) {
932 case AUDIO_MUTE:
933 btv->audio |= AUDIO_MUTE;
934 break;
935 case AUDIO_UNMUTE:
936 btv->audio &= ~AUDIO_MUTE;
937 break;
938 case AUDIO_TUNER:
939 case AUDIO_RADIO:
940 case AUDIO_EXTERN:
941 case AUDIO_INTERN:
942 btv->audio &= AUDIO_MUTE;
943 btv->audio |= mode;
944 }
945 i2c_mux = mux = (btv->audio & AUDIO_MUTE) ? AUDIO_OFF : btv->audio;
946 if (btv->opt_automute && !signal && !btv->radio_user)
947 mux = AUDIO_OFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948
949 val = bttv_tvcards[btv->c.type].audiomux[mux];
950 gpio_bits(bttv_tvcards[btv->c.type].gpiomask,val);
951 if (bttv_gpio)
952 bttv_gpio_tracking(btv,audio_modes[mux]);
953 if (!in_interrupt())
954 bttv_call_i2c_clients(btv,AUDC_SET_INPUT,&(i2c_mux));
955 return 0;
956}
957
958static void
959i2c_vidiocschan(struct bttv *btv)
960{
961 struct video_channel c;
962
963 memset(&c,0,sizeof(c));
964 c.norm = btv->tvnorm;
965 c.channel = btv->input;
966 bttv_call_i2c_clients(btv,VIDIOCSCHAN,&c);
Mauro Carvalho Chehab5a25e842005-11-08 21:36:52 -0800967 if (btv->c.type == BTTV_BOARD_VOODOOTV_FM)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 bttv_tda9880_setnorm(btv,c.norm);
969}
970
971static int
972set_tvnorm(struct bttv *btv, unsigned int norm)
973{
974 const struct bttv_tvnorm *tvnorm;
975
976 if (norm < 0 || norm >= BTTV_TVNORMS)
977 return -EINVAL;
978
979 btv->tvnorm = norm;
980 tvnorm = &bttv_tvnorms[norm];
981
982 btwrite(tvnorm->adelay, BT848_ADELAY);
983 btwrite(tvnorm->bdelay, BT848_BDELAY);
984 btaor(tvnorm->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH),
985 BT848_IFORM);
986 btwrite(tvnorm->vbipack, BT848_VBI_PACK_SIZE);
987 btwrite(1, BT848_VBI_PACK_DEL);
988 bt848A_set_timing(btv);
989
990 switch (btv->c.type) {
Mauro Carvalho Chehab5a25e842005-11-08 21:36:52 -0800991 case BTTV_BOARD_VOODOOTV_FM:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 bttv_tda9880_setnorm(btv,norm);
993 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 }
995 return 0;
996}
997
998static void
999set_input(struct bttv *btv, unsigned int input)
1000{
1001 unsigned long flags;
1002
1003 btv->input = input;
1004 if (irq_iswitch) {
1005 spin_lock_irqsave(&btv->s_lock,flags);
1006 if (btv->curr.frame_irq) {
1007 /* active capture -> delayed input switch */
1008 btv->new_input = input;
1009 } else {
1010 video_mux(btv,input);
1011 }
1012 spin_unlock_irqrestore(&btv->s_lock,flags);
1013 } else {
1014 video_mux(btv,input);
1015 }
1016 audio_mux(btv,(input == bttv_tvcards[btv->c.type].tuner ?
1017 AUDIO_TUNER : AUDIO_EXTERN));
1018 set_tvnorm(btv,btv->tvnorm);
1019 i2c_vidiocschan(btv);
1020}
1021
1022static void init_irqreg(struct bttv *btv)
1023{
1024 /* clear status */
1025 btwrite(0xfffffUL, BT848_INT_STAT);
1026
1027 if (bttv_tvcards[btv->c.type].no_video) {
1028 /* i2c only */
1029 btwrite(BT848_INT_I2CDONE,
1030 BT848_INT_MASK);
1031 } else {
1032 /* full video */
1033 btwrite((btv->triton1) |
1034 (btv->gpioirq ? BT848_INT_GPINT : 0) |
1035 BT848_INT_SCERR |
1036 (fdsr ? BT848_INT_FDSR : 0) |
1037 BT848_INT_RISCI|BT848_INT_OCERR|BT848_INT_VPRES|
1038 BT848_INT_FMTCHG|BT848_INT_HLOCK|
1039 BT848_INT_I2CDONE,
1040 BT848_INT_MASK);
1041 }
1042}
1043
1044static void init_bt848(struct bttv *btv)
1045{
1046 int val;
1047
1048 if (bttv_tvcards[btv->c.type].no_video) {
1049 /* very basic init only */
1050 init_irqreg(btv);
1051 return;
1052 }
1053
1054 btwrite(0x00, BT848_CAP_CTL);
1055 btwrite(BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL);
1056 btwrite(BT848_IFORM_XTAUTO | BT848_IFORM_AUTO, BT848_IFORM);
1057
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001058 /* set planar and packed mode trigger points and */
1059 /* set rising edge of inverted GPINTR pin as irq trigger */
1060 btwrite(BT848_GPIO_DMA_CTL_PKTP_32|
1061 BT848_GPIO_DMA_CTL_PLTP1_16|
1062 BT848_GPIO_DMA_CTL_PLTP23_16|
1063 BT848_GPIO_DMA_CTL_GPINTC|
1064 BT848_GPIO_DMA_CTL_GPINTI,
1065 BT848_GPIO_DMA_CTL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066
1067 val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001068 btwrite(val, BT848_E_SCLOOP);
1069 btwrite(val, BT848_O_SCLOOP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001071 btwrite(0x20, BT848_E_VSCALE_HI);
1072 btwrite(0x20, BT848_O_VSCALE_HI);
1073 btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 BT848_ADC);
1075
1076 btwrite(whitecrush_upper, BT848_WC_UP);
1077 btwrite(whitecrush_lower, BT848_WC_DOWN);
1078
1079 if (btv->opt_lumafilter) {
1080 btwrite(0, BT848_E_CONTROL);
1081 btwrite(0, BT848_O_CONTROL);
1082 } else {
1083 btwrite(BT848_CONTROL_LDEC, BT848_E_CONTROL);
1084 btwrite(BT848_CONTROL_LDEC, BT848_O_CONTROL);
1085 }
1086
1087 bt848_bright(btv, btv->bright);
1088 bt848_hue(btv, btv->hue);
1089 bt848_contrast(btv, btv->contrast);
1090 bt848_sat(btv, btv->saturation);
1091
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001092 /* interrupt */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 init_irqreg(btv);
1094}
1095
1096static void bttv_reinit_bt848(struct bttv *btv)
1097{
1098 unsigned long flags;
1099
1100 if (bttv_verbose)
1101 printk(KERN_INFO "bttv%d: reset, reinitialize\n",btv->c.nr);
1102 spin_lock_irqsave(&btv->s_lock,flags);
1103 btv->errors=0;
1104 bttv_set_dma(btv,0);
1105 spin_unlock_irqrestore(&btv->s_lock,flags);
1106
1107 init_bt848(btv);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001108 btv->pll.pll_current = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 set_input(btv,btv->input);
1110}
1111
1112static int get_control(struct bttv *btv, struct v4l2_control *c)
1113{
1114 struct video_audio va;
1115 int i;
1116
1117 for (i = 0; i < BTTV_CTLS; i++)
1118 if (bttv_ctls[i].id == c->id)
1119 break;
1120 if (i == BTTV_CTLS)
1121 return -EINVAL;
1122 if (i >= 4 && i <= 8) {
1123 memset(&va,0,sizeof(va));
1124 bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
1125 if (btv->audio_hook)
1126 btv->audio_hook(btv,&va,0);
1127 }
1128 switch (c->id) {
1129 case V4L2_CID_BRIGHTNESS:
1130 c->value = btv->bright;
1131 break;
1132 case V4L2_CID_HUE:
1133 c->value = btv->hue;
1134 break;
1135 case V4L2_CID_CONTRAST:
1136 c->value = btv->contrast;
1137 break;
1138 case V4L2_CID_SATURATION:
1139 c->value = btv->saturation;
1140 break;
1141
1142 case V4L2_CID_AUDIO_MUTE:
1143 c->value = (VIDEO_AUDIO_MUTE & va.flags) ? 1 : 0;
1144 break;
1145 case V4L2_CID_AUDIO_VOLUME:
1146 c->value = va.volume;
1147 break;
1148 case V4L2_CID_AUDIO_BALANCE:
1149 c->value = va.balance;
1150 break;
1151 case V4L2_CID_AUDIO_BASS:
1152 c->value = va.bass;
1153 break;
1154 case V4L2_CID_AUDIO_TREBLE:
1155 c->value = va.treble;
1156 break;
1157
1158 case V4L2_CID_PRIVATE_CHROMA_AGC:
1159 c->value = btv->opt_chroma_agc;
1160 break;
1161 case V4L2_CID_PRIVATE_COMBFILTER:
1162 c->value = btv->opt_combfilter;
1163 break;
1164 case V4L2_CID_PRIVATE_LUMAFILTER:
1165 c->value = btv->opt_lumafilter;
1166 break;
1167 case V4L2_CID_PRIVATE_AUTOMUTE:
1168 c->value = btv->opt_automute;
1169 break;
1170 case V4L2_CID_PRIVATE_AGC_CRUSH:
1171 c->value = btv->opt_adc_crush;
1172 break;
1173 case V4L2_CID_PRIVATE_VCR_HACK:
1174 c->value = btv->opt_vcr_hack;
1175 break;
1176 case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
1177 c->value = btv->opt_whitecrush_upper;
1178 break;
1179 case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
1180 c->value = btv->opt_whitecrush_lower;
1181 break;
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -07001182 case V4L2_CID_PRIVATE_UV_RATIO:
1183 c->value = btv->opt_uv_ratio;
1184 break;
1185 case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
1186 c->value = btv->opt_full_luma_range;
1187 break;
1188 case V4L2_CID_PRIVATE_CORING:
1189 c->value = btv->opt_coring;
1190 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191 default:
1192 return -EINVAL;
1193 }
1194 return 0;
1195}
1196
1197static int set_control(struct bttv *btv, struct v4l2_control *c)
1198{
1199 struct video_audio va;
1200 int i,val;
1201
1202 for (i = 0; i < BTTV_CTLS; i++)
1203 if (bttv_ctls[i].id == c->id)
1204 break;
1205 if (i == BTTV_CTLS)
1206 return -EINVAL;
1207 if (i >= 4 && i <= 8) {
1208 memset(&va,0,sizeof(va));
1209 bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
1210 if (btv->audio_hook)
1211 btv->audio_hook(btv,&va,0);
1212 }
1213 switch (c->id) {
1214 case V4L2_CID_BRIGHTNESS:
1215 bt848_bright(btv,c->value);
1216 break;
1217 case V4L2_CID_HUE:
1218 bt848_hue(btv,c->value);
1219 break;
1220 case V4L2_CID_CONTRAST:
1221 bt848_contrast(btv,c->value);
1222 break;
1223 case V4L2_CID_SATURATION:
1224 bt848_sat(btv,c->value);
1225 break;
1226 case V4L2_CID_AUDIO_MUTE:
1227 if (c->value) {
1228 va.flags |= VIDEO_AUDIO_MUTE;
1229 audio_mux(btv, AUDIO_MUTE);
1230 } else {
1231 va.flags &= ~VIDEO_AUDIO_MUTE;
1232 audio_mux(btv, AUDIO_UNMUTE);
1233 }
1234 break;
1235
1236 case V4L2_CID_AUDIO_VOLUME:
1237 va.volume = c->value;
1238 break;
1239 case V4L2_CID_AUDIO_BALANCE:
1240 va.balance = c->value;
1241 break;
1242 case V4L2_CID_AUDIO_BASS:
1243 va.bass = c->value;
1244 break;
1245 case V4L2_CID_AUDIO_TREBLE:
1246 va.treble = c->value;
1247 break;
1248
1249 case V4L2_CID_PRIVATE_CHROMA_AGC:
1250 btv->opt_chroma_agc = c->value;
1251 val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
1252 btwrite(val, BT848_E_SCLOOP);
1253 btwrite(val, BT848_O_SCLOOP);
1254 break;
1255 case V4L2_CID_PRIVATE_COMBFILTER:
1256 btv->opt_combfilter = c->value;
1257 break;
1258 case V4L2_CID_PRIVATE_LUMAFILTER:
1259 btv->opt_lumafilter = c->value;
1260 if (btv->opt_lumafilter) {
1261 btand(~BT848_CONTROL_LDEC, BT848_E_CONTROL);
1262 btand(~BT848_CONTROL_LDEC, BT848_O_CONTROL);
1263 } else {
1264 btor(BT848_CONTROL_LDEC, BT848_E_CONTROL);
1265 btor(BT848_CONTROL_LDEC, BT848_O_CONTROL);
1266 }
1267 break;
1268 case V4L2_CID_PRIVATE_AUTOMUTE:
1269 btv->opt_automute = c->value;
1270 break;
1271 case V4L2_CID_PRIVATE_AGC_CRUSH:
1272 btv->opt_adc_crush = c->value;
1273 btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
1274 BT848_ADC);
1275 break;
1276 case V4L2_CID_PRIVATE_VCR_HACK:
1277 btv->opt_vcr_hack = c->value;
1278 break;
1279 case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
1280 btv->opt_whitecrush_upper = c->value;
1281 btwrite(c->value, BT848_WC_UP);
1282 break;
1283 case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
1284 btv->opt_whitecrush_lower = c->value;
1285 btwrite(c->value, BT848_WC_DOWN);
1286 break;
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -07001287 case V4L2_CID_PRIVATE_UV_RATIO:
1288 btv->opt_uv_ratio = c->value;
1289 bt848_sat(btv, btv->saturation);
1290 break;
1291 case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
1292 btv->opt_full_luma_range = c->value;
1293 btaor((c->value<<7), ~BT848_OFORM_RANGE, BT848_OFORM);
1294 break;
1295 case V4L2_CID_PRIVATE_CORING:
1296 btv->opt_coring = c->value;
1297 btaor((c->value<<5), ~BT848_OFORM_CORE32, BT848_OFORM);
1298 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 default:
1300 return -EINVAL;
1301 }
1302 if (i >= 4 && i <= 8) {
1303 bttv_call_i2c_clients(btv, VIDIOCSAUDIO, &va);
1304 if (btv->audio_hook)
1305 btv->audio_hook(btv,&va,1);
1306 }
1307 return 0;
1308}
1309
1310/* ----------------------------------------------------------------------- */
1311
1312void bttv_gpio_tracking(struct bttv *btv, char *comment)
1313{
1314 unsigned int outbits, data;
1315 outbits = btread(BT848_GPIO_OUT_EN);
1316 data = btread(BT848_GPIO_DATA);
1317 printk(KERN_DEBUG "bttv%d: gpio: en=%08x, out=%08x in=%08x [%s]\n",
1318 btv->c.nr,outbits,data & outbits, data & ~outbits, comment);
1319}
1320
1321static void bttv_field_count(struct bttv *btv)
1322{
1323 int need_count = 0;
1324
1325 if (btv->users)
1326 need_count++;
1327
1328 if (need_count) {
1329 /* start field counter */
1330 btor(BT848_INT_VSYNC,BT848_INT_MASK);
1331 } else {
1332 /* stop field counter */
1333 btand(~BT848_INT_VSYNC,BT848_INT_MASK);
1334 btv->field_count = 0;
1335 }
1336}
1337
1338static const struct bttv_format*
1339format_by_palette(int palette)
1340{
1341 unsigned int i;
1342
1343 for (i = 0; i < BTTV_FORMATS; i++) {
1344 if (-1 == bttv_formats[i].palette)
1345 continue;
1346 if (bttv_formats[i].palette == palette)
1347 return bttv_formats+i;
1348 }
1349 return NULL;
1350}
1351
1352static const struct bttv_format*
1353format_by_fourcc(int fourcc)
1354{
1355 unsigned int i;
1356
1357 for (i = 0; i < BTTV_FORMATS; i++) {
1358 if (-1 == bttv_formats[i].fourcc)
1359 continue;
1360 if (bttv_formats[i].fourcc == fourcc)
1361 return bttv_formats+i;
1362 }
1363 return NULL;
1364}
1365
1366/* ----------------------------------------------------------------------- */
1367/* misc helpers */
1368
1369static int
1370bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh,
1371 struct bttv_buffer *new)
1372{
1373 struct bttv_buffer *old;
1374 unsigned long flags;
1375 int retval = 0;
1376
1377 dprintk("switch_overlay: enter [new=%p]\n",new);
1378 if (new)
1379 new->vb.state = STATE_DONE;
1380 spin_lock_irqsave(&btv->s_lock,flags);
1381 old = btv->screen;
1382 btv->screen = new;
1383 btv->loop_irq |= 1;
1384 bttv_set_dma(btv, 0x03);
1385 spin_unlock_irqrestore(&btv->s_lock,flags);
1386 if (NULL == new)
1387 free_btres(btv,fh,RESOURCE_OVERLAY);
1388 if (NULL != old) {
1389 dprintk("switch_overlay: old=%p state is %d\n",old,old->vb.state);
1390 bttv_dma_free(btv, old);
1391 kfree(old);
1392 }
1393 dprintk("switch_overlay: done\n");
1394 return retval;
1395}
1396
1397/* ----------------------------------------------------------------------- */
1398/* video4linux (1) interface */
1399
1400static int bttv_prepare_buffer(struct bttv *btv, struct bttv_buffer *buf,
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001401 const struct bttv_format *fmt,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402 unsigned int width, unsigned int height,
1403 enum v4l2_field field)
1404{
1405 int redo_dma_risc = 0;
1406 int rc;
1407
1408 /* check settings */
1409 if (NULL == fmt)
1410 return -EINVAL;
1411 if (fmt->btformat == BT848_COLOR_FMT_RAW) {
1412 width = RAW_BPL;
1413 height = RAW_LINES*2;
1414 if (width*height > buf->vb.bsize)
1415 return -EINVAL;
1416 buf->vb.size = buf->vb.bsize;
1417 } else {
1418 if (width < 48 ||
1419 height < 32 ||
1420 width > bttv_tvnorms[btv->tvnorm].swidth ||
1421 height > bttv_tvnorms[btv->tvnorm].sheight)
1422 return -EINVAL;
1423 buf->vb.size = (width * height * fmt->depth) >> 3;
1424 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
1425 return -EINVAL;
1426 }
1427
1428 /* alloc + fill struct bttv_buffer (if changed) */
1429 if (buf->vb.width != width || buf->vb.height != height ||
1430 buf->vb.field != field ||
1431 buf->tvnorm != btv->tvnorm || buf->fmt != fmt) {
1432 buf->vb.width = width;
1433 buf->vb.height = height;
1434 buf->vb.field = field;
1435 buf->tvnorm = btv->tvnorm;
1436 buf->fmt = fmt;
1437 redo_dma_risc = 1;
1438 }
1439
1440 /* alloc risc memory */
1441 if (STATE_NEEDS_INIT == buf->vb.state) {
1442 redo_dma_risc = 1;
1443 if (0 != (rc = videobuf_iolock(btv->c.pci,&buf->vb,&btv->fbuf)))
1444 goto fail;
1445 }
1446
1447 if (redo_dma_risc)
1448 if (0 != (rc = bttv_buffer_risc(btv,buf)))
1449 goto fail;
1450
1451 buf->vb.state = STATE_PREPARED;
1452 return 0;
1453
1454 fail:
1455 bttv_dma_free(btv,buf);
1456 return rc;
1457}
1458
1459static int
1460buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
1461{
1462 struct bttv_fh *fh = q->priv_data;
1463
1464 *size = fh->fmt->depth*fh->width*fh->height >> 3;
1465 if (0 == *count)
1466 *count = gbuffers;
1467 while (*size * *count > gbuffers * gbufsize)
1468 (*count)--;
1469 return 0;
1470}
1471
1472static int
1473buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
1474 enum v4l2_field field)
1475{
1476 struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
1477 struct bttv_fh *fh = q->priv_data;
1478
1479 return bttv_prepare_buffer(fh->btv, buf, fh->fmt,
1480 fh->width, fh->height, field);
1481}
1482
1483static void
1484buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
1485{
1486 struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
1487 struct bttv_fh *fh = q->priv_data;
1488 struct bttv *btv = fh->btv;
1489
1490 buf->vb.state = STATE_QUEUED;
1491 list_add_tail(&buf->vb.queue,&btv->capture);
1492 if (!btv->curr.frame_irq) {
1493 btv->loop_irq |= 1;
1494 bttv_set_dma(btv, 0x03);
1495 }
1496}
1497
1498static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
1499{
1500 struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
1501 struct bttv_fh *fh = q->priv_data;
1502
1503 bttv_dma_free(fh->btv,buf);
1504}
1505
1506static struct videobuf_queue_ops bttv_video_qops = {
1507 .buf_setup = buffer_setup,
1508 .buf_prepare = buffer_prepare,
1509 .buf_queue = buffer_queue,
1510 .buf_release = buffer_release,
1511};
1512
1513static const char *v4l1_ioctls[] = {
1514 "?", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT", "SPICT",
1515 "CCAPTURE", "GWIN", "SWIN", "GFBUF", "SFBUF", "KEY", "GFREQ",
1516 "SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT",
1517 "GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO",
1518 "SMICROCODE", "GVBIFMT", "SVBIFMT" };
1519#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
1520
1521static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
1522{
1523 switch (cmd) {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001524 case BTTV_VERSION:
1525 return BTTV_VERSION_CODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526
1527 /* *** v4l1 *** ************************************************ */
1528 case VIDIOCGFREQ:
1529 {
1530 unsigned long *freq = arg;
1531 *freq = btv->freq;
1532 return 0;
1533 }
1534 case VIDIOCSFREQ:
1535 {
1536 unsigned long *freq = arg;
1537 down(&btv->lock);
1538 btv->freq=*freq;
1539 bttv_call_i2c_clients(btv,VIDIOCSFREQ,freq);
1540 if (btv->has_matchbox && btv->radio_user)
1541 tea5757_set_freq(btv,*freq);
1542 up(&btv->lock);
1543 return 0;
1544 }
1545
1546 case VIDIOCGTUNER:
1547 {
1548 struct video_tuner *v = arg;
1549
1550 if (UNSET == bttv_tvcards[btv->c.type].tuner)
1551 return -EINVAL;
1552 if (v->tuner) /* Only tuner 0 */
1553 return -EINVAL;
1554 strcpy(v->name, "Television");
1555 v->rangelow = 0;
1556 v->rangehigh = 0x7FFFFFFF;
1557 v->flags = VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM;
1558 v->mode = btv->tvnorm;
1559 v->signal = (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC) ? 0xFFFF : 0;
1560 bttv_call_i2c_clients(btv,cmd,v);
1561 return 0;
1562 }
1563 case VIDIOCSTUNER:
1564 {
1565 struct video_tuner *v = arg;
1566
1567 if (v->tuner) /* Only tuner 0 */
1568 return -EINVAL;
1569 if (v->mode >= BTTV_TVNORMS)
1570 return -EINVAL;
1571
1572 down(&btv->lock);
1573 set_tvnorm(btv,v->mode);
1574 bttv_call_i2c_clients(btv,cmd,v);
1575 up(&btv->lock);
1576 return 0;
1577 }
1578
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001579 case VIDIOCGCHAN:
1580 {
1581 struct video_channel *v = arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582 unsigned int channel = v->channel;
1583
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001584 if (channel >= bttv_tvcards[btv->c.type].video_inputs)
1585 return -EINVAL;
1586 v->tuners=0;
1587 v->flags = VIDEO_VC_AUDIO;
1588 v->type = VIDEO_TYPE_CAMERA;
1589 v->norm = btv->tvnorm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590 if (channel == bttv_tvcards[btv->c.type].tuner) {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001591 strcpy(v->name,"Television");
1592 v->flags|=VIDEO_VC_TUNER;
1593 v->type=VIDEO_TYPE_TV;
1594 v->tuners=1;
1595 } else if (channel == btv->svhs) {
1596 strcpy(v->name,"S-Video");
1597 } else {
1598 sprintf(v->name,"Composite%d",channel);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599 }
1600 return 0;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001601 }
1602 case VIDIOCSCHAN:
1603 {
1604 struct video_channel *v = arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605 unsigned int channel = v->channel;
1606
1607 if (channel >= bttv_tvcards[btv->c.type].video_inputs)
1608 return -EINVAL;
1609 if (v->norm >= BTTV_TVNORMS)
1610 return -EINVAL;
1611
1612 down(&btv->lock);
1613 if (channel == btv->input &&
1614 v->norm == btv->tvnorm) {
1615 /* nothing to do */
1616 up(&btv->lock);
1617 return 0;
1618 }
1619
1620 btv->tvnorm = v->norm;
1621 set_input(btv,v->channel);
1622 up(&btv->lock);
1623 return 0;
1624 }
1625
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001626 case VIDIOCGAUDIO:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627 {
1628 struct video_audio *v = arg;
1629
1630 memset(v,0,sizeof(*v));
1631 strcpy(v->name,"Television");
1632 v->flags |= VIDEO_AUDIO_MUTABLE;
1633 v->mode = VIDEO_SOUND_MONO;
1634
1635 down(&btv->lock);
1636 bttv_call_i2c_clients(btv,cmd,v);
1637
1638 /* card specific hooks */
1639 if (btv->audio_hook)
1640 btv->audio_hook(btv,v,0);
1641
1642 up(&btv->lock);
1643 return 0;
1644 }
1645 case VIDIOCSAUDIO:
1646 {
1647 struct video_audio *v = arg;
1648 unsigned int audio = v->audio;
1649
1650 if (audio >= bttv_tvcards[btv->c.type].audio_inputs)
1651 return -EINVAL;
1652
1653 down(&btv->lock);
1654 audio_mux(btv, (v->flags&VIDEO_AUDIO_MUTE) ? AUDIO_MUTE : AUDIO_UNMUTE);
1655 bttv_call_i2c_clients(btv,cmd,v);
1656
1657 /* card specific hooks */
1658 if (btv->audio_hook)
1659 btv->audio_hook(btv,v,1);
1660
1661 up(&btv->lock);
1662 return 0;
1663 }
1664
1665 /* *** v4l2 *** ************************************************ */
1666 case VIDIOC_ENUMSTD:
1667 {
1668 struct v4l2_standard *e = arg;
1669 unsigned int index = e->index;
1670
1671 if (index >= BTTV_TVNORMS)
1672 return -EINVAL;
1673 v4l2_video_std_construct(e, bttv_tvnorms[e->index].v4l2_id,
1674 bttv_tvnorms[e->index].name);
1675 e->index = index;
1676 return 0;
1677 }
1678 case VIDIOC_G_STD:
1679 {
1680 v4l2_std_id *id = arg;
1681 *id = bttv_tvnorms[btv->tvnorm].v4l2_id;
1682 return 0;
1683 }
1684 case VIDIOC_S_STD:
1685 {
1686 v4l2_std_id *id = arg;
1687 unsigned int i;
1688
1689 for (i = 0; i < BTTV_TVNORMS; i++)
1690 if (*id & bttv_tvnorms[i].v4l2_id)
1691 break;
1692 if (i == BTTV_TVNORMS)
1693 return -EINVAL;
1694
1695 down(&btv->lock);
1696 set_tvnorm(btv,i);
1697 i2c_vidiocschan(btv);
1698 up(&btv->lock);
1699 return 0;
1700 }
1701 case VIDIOC_QUERYSTD:
1702 {
1703 v4l2_std_id *id = arg;
1704
1705 if (btread(BT848_DSTATUS) & BT848_DSTATUS_NUML)
1706 *id = V4L2_STD_625_50;
1707 else
1708 *id = V4L2_STD_525_60;
1709 return 0;
1710 }
1711
1712 case VIDIOC_ENUMINPUT:
1713 {
1714 struct v4l2_input *i = arg;
1715 unsigned int n;
1716
1717 n = i->index;
1718 if (n >= bttv_tvcards[btv->c.type].video_inputs)
1719 return -EINVAL;
1720 memset(i,0,sizeof(*i));
1721 i->index = n;
1722 i->type = V4L2_INPUT_TYPE_CAMERA;
1723 i->audioset = 1;
1724 if (i->index == bttv_tvcards[btv->c.type].tuner) {
1725 sprintf(i->name, "Television");
1726 i->type = V4L2_INPUT_TYPE_TUNER;
1727 i->tuner = 0;
1728 } else if (i->index == btv->svhs) {
1729 sprintf(i->name, "S-Video");
1730 } else {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001731 sprintf(i->name,"Composite%d",i->index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732 }
1733 if (i->index == btv->input) {
1734 __u32 dstatus = btread(BT848_DSTATUS);
1735 if (0 == (dstatus & BT848_DSTATUS_PRES))
1736 i->status |= V4L2_IN_ST_NO_SIGNAL;
1737 if (0 == (dstatus & BT848_DSTATUS_HLOC))
1738 i->status |= V4L2_IN_ST_NO_H_LOCK;
1739 }
1740 for (n = 0; n < BTTV_TVNORMS; n++)
1741 i->std |= bttv_tvnorms[n].v4l2_id;
1742 return 0;
1743 }
1744 case VIDIOC_G_INPUT:
1745 {
1746 int *i = arg;
1747 *i = btv->input;
1748 return 0;
1749 }
1750 case VIDIOC_S_INPUT:
1751 {
1752 unsigned int *i = arg;
1753
1754 if (*i > bttv_tvcards[btv->c.type].video_inputs)
1755 return -EINVAL;
1756 down(&btv->lock);
1757 set_input(btv,*i);
1758 up(&btv->lock);
1759 return 0;
1760 }
1761
1762 case VIDIOC_G_TUNER:
1763 {
1764 struct v4l2_tuner *t = arg;
1765
1766 if (UNSET == bttv_tvcards[btv->c.type].tuner)
1767 return -EINVAL;
1768 if (0 != t->index)
1769 return -EINVAL;
1770 down(&btv->lock);
1771 memset(t,0,sizeof(*t));
1772 strcpy(t->name, "Television");
1773 t->type = V4L2_TUNER_ANALOG_TV;
1774 t->rangehigh = 0xffffffffUL;
1775 t->capability = V4L2_TUNER_CAP_NORM;
1776 t->rxsubchans = V4L2_TUNER_SUB_MONO;
1777 if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)
1778 t->signal = 0xffff;
1779 {
1780 /* Hmmm ... */
1781 struct video_audio va;
1782 memset(&va, 0, sizeof(struct video_audio));
1783 bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
1784 if (btv->audio_hook)
1785 btv->audio_hook(btv,&va,0);
1786 if(va.mode & VIDEO_SOUND_STEREO) {
1787 t->audmode = V4L2_TUNER_MODE_STEREO;
1788 t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
1789 }
1790 if(va.mode & VIDEO_SOUND_LANG1) {
1791 t->audmode = V4L2_TUNER_MODE_LANG1;
1792 t->rxsubchans = V4L2_TUNER_SUB_LANG1
1793 | V4L2_TUNER_SUB_LANG2;
1794 }
1795 }
1796 /* FIXME: fill capability+audmode */
1797 up(&btv->lock);
1798 return 0;
1799 }
1800 case VIDIOC_S_TUNER:
1801 {
1802 struct v4l2_tuner *t = arg;
1803
1804 if (UNSET == bttv_tvcards[btv->c.type].tuner)
1805 return -EINVAL;
1806 if (0 != t->index)
1807 return -EINVAL;
1808 down(&btv->lock);
1809 {
1810 struct video_audio va;
1811 memset(&va, 0, sizeof(struct video_audio));
1812 bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
1813 if (t->audmode == V4L2_TUNER_MODE_MONO)
1814 va.mode = VIDEO_SOUND_MONO;
1815 else if (t->audmode == V4L2_TUNER_MODE_STEREO)
1816 va.mode = VIDEO_SOUND_STEREO;
1817 else if (t->audmode == V4L2_TUNER_MODE_LANG1)
1818 va.mode = VIDEO_SOUND_LANG1;
1819 else if (t->audmode == V4L2_TUNER_MODE_LANG2)
1820 va.mode = VIDEO_SOUND_LANG2;
1821 bttv_call_i2c_clients(btv, VIDIOCSAUDIO, &va);
1822 if (btv->audio_hook)
1823 btv->audio_hook(btv,&va,1);
1824 }
1825 up(&btv->lock);
1826 return 0;
1827 }
1828
1829 case VIDIOC_G_FREQUENCY:
1830 {
1831 struct v4l2_frequency *f = arg;
1832
1833 memset(f,0,sizeof(*f));
1834 f->type = V4L2_TUNER_ANALOG_TV;
1835 f->frequency = btv->freq;
1836 return 0;
1837 }
1838 case VIDIOC_S_FREQUENCY:
1839 {
1840 struct v4l2_frequency *f = arg;
1841
1842 if (unlikely(f->tuner != 0))
1843 return -EINVAL;
Mauro Carvalho Chehabfa9846a2005-07-12 13:58:42 -07001844 if (unlikely (f->type != V4L2_TUNER_ANALOG_TV))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845 return -EINVAL;
1846 down(&btv->lock);
1847 btv->freq = f->frequency;
1848 bttv_call_i2c_clients(btv,VIDIOCSFREQ,&btv->freq);
1849 if (btv->has_matchbox && btv->radio_user)
1850 tea5757_set_freq(btv,btv->freq);
1851 up(&btv->lock);
1852 return 0;
1853 }
Hans Verkuil299392b2005-11-08 21:37:42 -08001854 case VIDIOC_LOG_STATUS:
1855 {
Luiz Capitulino97cb4452005-12-01 00:51:24 -08001856 bttv_call_i2c_clients(btv, VIDIOC_LOG_STATUS, NULL);
Hans Verkuil299392b2005-11-08 21:37:42 -08001857 return 0;
1858 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859
1860 default:
1861 return -ENOIOCTLCMD;
1862
1863 }
1864 return 0;
1865}
1866
1867static int verify_window(const struct bttv_tvnorm *tvn,
1868 struct v4l2_window *win, int fixup)
1869{
1870 enum v4l2_field field;
1871 int maxw, maxh;
1872
1873 if (win->w.width < 48 || win->w.height < 32)
1874 return -EINVAL;
1875 if (win->clipcount > 2048)
1876 return -EINVAL;
1877
1878 field = win->field;
1879 maxw = tvn->swidth;
1880 maxh = tvn->sheight;
1881
1882 if (V4L2_FIELD_ANY == field) {
1883 field = (win->w.height > maxh/2)
1884 ? V4L2_FIELD_INTERLACED
1885 : V4L2_FIELD_TOP;
1886 }
1887 switch (field) {
1888 case V4L2_FIELD_TOP:
1889 case V4L2_FIELD_BOTTOM:
1890 maxh = maxh / 2;
1891 break;
1892 case V4L2_FIELD_INTERLACED:
1893 break;
1894 default:
1895 return -EINVAL;
1896 }
1897
1898 if (!fixup && (win->w.width > maxw || win->w.height > maxh))
1899 return -EINVAL;
1900
1901 if (win->w.width > maxw)
1902 win->w.width = maxw;
1903 if (win->w.height > maxh)
1904 win->w.height = maxh;
1905 win->field = field;
1906 return 0;
1907}
1908
1909static int setup_window(struct bttv_fh *fh, struct bttv *btv,
1910 struct v4l2_window *win, int fixup)
1911{
1912 struct v4l2_clip *clips = NULL;
1913 int n,size,retval = 0;
1914
1915 if (NULL == fh->ovfmt)
1916 return -EINVAL;
1917 if (!(fh->ovfmt->flags & FORMAT_FLAGS_PACKED))
1918 return -EINVAL;
1919 retval = verify_window(&bttv_tvnorms[btv->tvnorm],win,fixup);
1920 if (0 != retval)
1921 return retval;
1922
1923 /* copy clips -- luckily v4l1 + v4l2 are binary
1924 compatible here ...*/
1925 n = win->clipcount;
1926 size = sizeof(*clips)*(n+4);
1927 clips = kmalloc(size,GFP_KERNEL);
1928 if (NULL == clips)
1929 return -ENOMEM;
1930 if (n > 0) {
1931 if (copy_from_user(clips,win->clips,sizeof(struct v4l2_clip)*n)) {
1932 kfree(clips);
1933 return -EFAULT;
1934 }
1935 }
1936 /* clip against screen */
1937 if (NULL != btv->fbuf.base)
1938 n = btcx_screen_clips(btv->fbuf.fmt.width, btv->fbuf.fmt.height,
1939 &win->w, clips, n);
1940 btcx_sort_clips(clips,n);
1941
1942 /* 4-byte alignments */
1943 switch (fh->ovfmt->depth) {
1944 case 8:
1945 case 24:
1946 btcx_align(&win->w, clips, n, 3);
1947 break;
1948 case 16:
1949 btcx_align(&win->w, clips, n, 1);
1950 break;
1951 case 32:
1952 /* no alignment fixups needed */
1953 break;
1954 default:
1955 BUG();
1956 }
1957
1958 down(&fh->cap.lock);
Jesper Juhl2ea75332005-11-07 01:01:31 -08001959 kfree(fh->ov.clips);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960 fh->ov.clips = clips;
1961 fh->ov.nclips = n;
1962
1963 fh->ov.w = win->w;
1964 fh->ov.field = win->field;
1965 fh->ov.setup_ok = 1;
1966 btv->init.ov.w.width = win->w.width;
1967 btv->init.ov.w.height = win->w.height;
1968 btv->init.ov.field = win->field;
1969
1970 /* update overlay if needed */
1971 retval = 0;
1972 if (check_btres(fh, RESOURCE_OVERLAY)) {
1973 struct bttv_buffer *new;
1974
1975 new = videobuf_alloc(sizeof(*new));
1976 bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
1977 retval = bttv_switch_overlay(btv,fh,new);
1978 }
1979 up(&fh->cap.lock);
1980 return retval;
1981}
1982
1983/* ----------------------------------------------------------------------- */
1984
1985static struct videobuf_queue* bttv_queue(struct bttv_fh *fh)
1986{
1987 struct videobuf_queue* q = NULL;
1988
1989 switch (fh->type) {
1990 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1991 q = &fh->cap;
1992 break;
1993 case V4L2_BUF_TYPE_VBI_CAPTURE:
1994 q = &fh->vbi;
1995 break;
1996 default:
1997 BUG();
1998 }
1999 return q;
2000}
2001
2002static int bttv_resource(struct bttv_fh *fh)
2003{
2004 int res = 0;
2005
2006 switch (fh->type) {
2007 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2008 res = RESOURCE_VIDEO;
2009 break;
2010 case V4L2_BUF_TYPE_VBI_CAPTURE:
2011 res = RESOURCE_VBI;
2012 break;
2013 default:
2014 BUG();
2015 }
2016 return res;
2017}
2018
2019static int bttv_switch_type(struct bttv_fh *fh, enum v4l2_buf_type type)
2020{
2021 struct videobuf_queue *q = bttv_queue(fh);
2022 int res = bttv_resource(fh);
2023
2024 if (check_btres(fh,res))
2025 return -EBUSY;
2026 if (videobuf_queue_is_busy(q))
2027 return -EBUSY;
2028 fh->type = type;
2029 return 0;
2030}
2031
Michael H. Schimekc87c9482005-12-01 00:51:33 -08002032static void
2033pix_format_set_size (struct v4l2_pix_format * f,
2034 const struct bttv_format * fmt,
2035 unsigned int width,
2036 unsigned int height)
2037{
2038 f->width = width;
2039 f->height = height;
2040
2041 if (fmt->flags & FORMAT_FLAGS_PLANAR) {
2042 f->bytesperline = width; /* Y plane */
2043 f->sizeimage = (width * height * fmt->depth) >> 3;
2044 } else {
2045 f->bytesperline = (width * fmt->depth) >> 3;
2046 f->sizeimage = height * f->bytesperline;
2047 }
2048}
2049
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050static int bttv_g_fmt(struct bttv_fh *fh, struct v4l2_format *f)
2051{
2052 switch (f->type) {
2053 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2054 memset(&f->fmt.pix,0,sizeof(struct v4l2_pix_format));
Michael H. Schimekc87c9482005-12-01 00:51:33 -08002055 pix_format_set_size (&f->fmt.pix, fh->fmt,
2056 fh->width, fh->height);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057 f->fmt.pix.field = fh->cap.field;
2058 f->fmt.pix.pixelformat = fh->fmt->fourcc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059 return 0;
2060 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
2061 memset(&f->fmt.win,0,sizeof(struct v4l2_window));
2062 f->fmt.win.w = fh->ov.w;
2063 f->fmt.win.field = fh->ov.field;
2064 return 0;
2065 case V4L2_BUF_TYPE_VBI_CAPTURE:
2066 bttv_vbi_get_fmt(fh,f);
2067 return 0;
2068 default:
2069 return -EINVAL;
2070 }
2071}
2072
2073static int bttv_try_fmt(struct bttv_fh *fh, struct bttv *btv,
2074 struct v4l2_format *f)
2075{
2076 switch (f->type) {
2077 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2078 {
2079 const struct bttv_format *fmt;
2080 enum v4l2_field field;
2081 unsigned int maxw,maxh;
2082
2083 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
2084 if (NULL == fmt)
2085 return -EINVAL;
2086
2087 /* fixup format */
2088 maxw = bttv_tvnorms[btv->tvnorm].swidth;
2089 maxh = bttv_tvnorms[btv->tvnorm].sheight;
2090 field = f->fmt.pix.field;
2091 if (V4L2_FIELD_ANY == field)
2092 field = (f->fmt.pix.height > maxh/2)
2093 ? V4L2_FIELD_INTERLACED
2094 : V4L2_FIELD_BOTTOM;
2095 if (V4L2_FIELD_SEQ_BT == field)
2096 field = V4L2_FIELD_SEQ_TB;
2097 switch (field) {
2098 case V4L2_FIELD_TOP:
2099 case V4L2_FIELD_BOTTOM:
2100 case V4L2_FIELD_ALTERNATE:
2101 maxh = maxh/2;
2102 break;
2103 case V4L2_FIELD_INTERLACED:
2104 break;
2105 case V4L2_FIELD_SEQ_TB:
2106 if (fmt->flags & FORMAT_FLAGS_PLANAR)
2107 return -EINVAL;
2108 break;
2109 default:
2110 return -EINVAL;
2111 }
2112
2113 /* update data for the application */
2114 f->fmt.pix.field = field;
2115 if (f->fmt.pix.width < 48)
2116 f->fmt.pix.width = 48;
2117 if (f->fmt.pix.height < 32)
2118 f->fmt.pix.height = 32;
2119 if (f->fmt.pix.width > maxw)
2120 f->fmt.pix.width = maxw;
2121 if (f->fmt.pix.height > maxh)
2122 f->fmt.pix.height = maxh;
Michael H. Schimekc87c9482005-12-01 00:51:33 -08002123 pix_format_set_size (&f->fmt.pix, fmt,
2124 f->fmt.pix.width & ~3,
2125 f->fmt.pix.height);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126
2127 return 0;
2128 }
2129 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
2130 return verify_window(&bttv_tvnorms[btv->tvnorm],
2131 &f->fmt.win, 1);
2132 case V4L2_BUF_TYPE_VBI_CAPTURE:
2133 bttv_vbi_try_fmt(fh,f);
2134 return 0;
2135 default:
2136 return -EINVAL;
2137 }
2138}
2139
2140static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv,
2141 struct v4l2_format *f)
2142{
2143 int retval;
2144
2145 switch (f->type) {
2146 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2147 {
2148 const struct bttv_format *fmt;
2149
2150 retval = bttv_switch_type(fh,f->type);
2151 if (0 != retval)
2152 return retval;
2153 retval = bttv_try_fmt(fh,btv,f);
2154 if (0 != retval)
2155 return retval;
2156 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
2157
2158 /* update our state informations */
2159 down(&fh->cap.lock);
2160 fh->fmt = fmt;
2161 fh->cap.field = f->fmt.pix.field;
2162 fh->cap.last = V4L2_FIELD_NONE;
2163 fh->width = f->fmt.pix.width;
2164 fh->height = f->fmt.pix.height;
2165 btv->init.fmt = fmt;
2166 btv->init.width = f->fmt.pix.width;
2167 btv->init.height = f->fmt.pix.height;
2168 up(&fh->cap.lock);
2169
2170 return 0;
2171 }
2172 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07002173 if (no_overlay > 0) {
2174 printk ("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
2175 return -EINVAL;
2176 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177 return setup_window(fh, btv, &f->fmt.win, 1);
2178 case V4L2_BUF_TYPE_VBI_CAPTURE:
2179 retval = bttv_switch_type(fh,f->type);
2180 if (0 != retval)
2181 return retval;
2182 if (locked_btres(fh->btv, RESOURCE_VBI))
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08002183 return -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184 bttv_vbi_try_fmt(fh,f);
2185 bttv_vbi_setlines(fh,btv,f->fmt.vbi.count[0]);
2186 bttv_vbi_get_fmt(fh,f);
2187 return 0;
2188 default:
2189 return -EINVAL;
2190 }
2191}
2192
2193static int bttv_do_ioctl(struct inode *inode, struct file *file,
2194 unsigned int cmd, void *arg)
2195{
2196 struct bttv_fh *fh = file->private_data;
2197 struct bttv *btv = fh->btv;
2198 unsigned long flags;
2199 int retval = 0;
2200
2201 if (bttv_debug > 1) {
2202 switch (_IOC_TYPE(cmd)) {
2203 case 'v':
2204 printk("bttv%d: ioctl 0x%x (v4l1, VIDIOC%s)\n",
2205 btv->c.nr, cmd, (_IOC_NR(cmd) < V4L1_IOCTLS) ?
2206 v4l1_ioctls[_IOC_NR(cmd)] : "???");
2207 break;
2208 case 'V':
2209 printk("bttv%d: ioctl 0x%x (v4l2, %s)\n",
2210 btv->c.nr, cmd, v4l2_ioctl_names[_IOC_NR(cmd)]);
2211 break;
2212 default:
2213 printk("bttv%d: ioctl 0x%x (???)\n",
2214 btv->c.nr, cmd);
2215 }
2216 }
2217 if (btv->errors)
2218 bttv_reinit_bt848(btv);
2219
2220 switch (cmd) {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08002221 case VIDIOCSFREQ:
2222 case VIDIOCSTUNER:
2223 case VIDIOCSCHAN:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224 case VIDIOC_S_CTRL:
2225 case VIDIOC_S_STD:
2226 case VIDIOC_S_INPUT:
2227 case VIDIOC_S_TUNER:
2228 case VIDIOC_S_FREQUENCY:
2229 retval = v4l2_prio_check(&btv->prio,&fh->prio);
2230 if (0 != retval)
2231 return retval;
2232 };
2233
2234 switch (cmd) {
2235
2236 /* *** v4l1 *** ************************************************ */
2237 case VIDIOCGCAP:
2238 {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08002239 struct video_capability *cap = arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240
2241 memset(cap,0,sizeof(*cap));
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08002242 strcpy(cap->name,btv->video_dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243 if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
2244 /* vbi */
2245 cap->type = VID_TYPE_TUNER|VID_TYPE_TELETEXT;
2246 } else {
2247 /* others */
2248 cap->type = VID_TYPE_CAPTURE|
2249 VID_TYPE_TUNER|
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250 VID_TYPE_CLIPPING|
2251 VID_TYPE_SCALES;
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07002252 if (no_overlay <= 0)
2253 cap->type |= VID_TYPE_OVERLAY;
2254
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255 cap->maxwidth = bttv_tvnorms[btv->tvnorm].swidth;
2256 cap->maxheight = bttv_tvnorms[btv->tvnorm].sheight;
2257 cap->minwidth = 48;
2258 cap->minheight = 32;
2259 }
2260 cap->channels = bttv_tvcards[btv->c.type].video_inputs;
2261 cap->audios = bttv_tvcards[btv->c.type].audio_inputs;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08002262 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263 }
2264
2265 case VIDIOCGPICT:
2266 {
2267 struct video_picture *pic = arg;
2268
2269 memset(pic,0,sizeof(*pic));
2270 pic->brightness = btv->bright;
2271 pic->contrast = btv->contrast;
2272 pic->hue = btv->hue;
2273 pic->colour = btv->saturation;
2274 if (fh->fmt) {
2275 pic->depth = fh->fmt->depth;
2276 pic->palette = fh->fmt->palette;
2277 }
2278 return 0;
2279 }
2280 case VIDIOCSPICT:
2281 {
2282 struct video_picture *pic = arg;
2283 const struct bttv_format *fmt;
2284
2285 fmt = format_by_palette(pic->palette);
2286 if (NULL == fmt)
2287 return -EINVAL;
2288 down(&fh->cap.lock);
2289 if (fmt->depth != pic->depth) {
2290 retval = -EINVAL;
2291 goto fh_unlock_and_return;
2292 }
Michael H. Schimek13c72802005-12-01 00:51:37 -08002293 if (fmt->flags & FORMAT_FLAGS_RAW) {
2294 /* VIDIOCMCAPTURE uses gbufsize, not RAW_BPL *
2295 RAW_LINES * 2. F1 is stored at offset 0, F2
2296 at buffer size / 2. */
2297 fh->width = RAW_BPL;
2298 fh->height = gbufsize / RAW_BPL;
2299 btv->init.width = RAW_BPL;
2300 btv->init.height = gbufsize / RAW_BPL;
2301 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302 fh->ovfmt = fmt;
2303 fh->fmt = fmt;
2304 btv->init.ovfmt = fmt;
2305 btv->init.fmt = fmt;
2306 if (bigendian) {
2307 /* dirty hack time: swap bytes for overlay if the
2308 display adaptor is big endian (insmod option) */
2309 if (fmt->palette == VIDEO_PALETTE_RGB555 ||
2310 fmt->palette == VIDEO_PALETTE_RGB565 ||
2311 fmt->palette == VIDEO_PALETTE_RGB32) {
2312 fh->ovfmt = fmt+1;
2313 }
2314 }
2315 bt848_bright(btv,pic->brightness);
2316 bt848_contrast(btv,pic->contrast);
2317 bt848_hue(btv,pic->hue);
2318 bt848_sat(btv,pic->colour);
2319 up(&fh->cap.lock);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08002320 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321 }
2322
2323 case VIDIOCGWIN:
2324 {
2325 struct video_window *win = arg;
2326
2327 memset(win,0,sizeof(*win));
2328 win->x = fh->ov.w.left;
2329 win->y = fh->ov.w.top;
2330 win->width = fh->ov.w.width;
2331 win->height = fh->ov.w.height;
2332 return 0;
2333 }
2334 case VIDIOCSWIN:
2335 {
2336 struct video_window *win = arg;
2337 struct v4l2_window w2;
2338
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07002339 if (no_overlay > 0) {
2340 printk ("VIDIOCSWIN: no_overlay\n");
2341 return -EINVAL;
2342 }
2343
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344 w2.field = V4L2_FIELD_ANY;
2345 w2.w.left = win->x;
2346 w2.w.top = win->y;
2347 w2.w.width = win->width;
2348 w2.w.height = win->height;
2349 w2.clipcount = win->clipcount;
2350 w2.clips = (struct v4l2_clip __user *)win->clips;
2351 retval = setup_window(fh, btv, &w2, 0);
2352 if (0 == retval) {
2353 /* on v4l1 this ioctl affects the read() size too */
2354 fh->width = fh->ov.w.width;
2355 fh->height = fh->ov.w.height;
2356 btv->init.width = fh->ov.w.width;
2357 btv->init.height = fh->ov.w.height;
2358 }
2359 return retval;
2360 }
2361
2362 case VIDIOCGFBUF:
2363 {
2364 struct video_buffer *fbuf = arg;
2365
2366 fbuf->base = btv->fbuf.base;
2367 fbuf->width = btv->fbuf.fmt.width;
2368 fbuf->height = btv->fbuf.fmt.height;
2369 fbuf->bytesperline = btv->fbuf.fmt.bytesperline;
2370 if (fh->ovfmt)
2371 fbuf->depth = fh->ovfmt->depth;
2372 return 0;
2373 }
2374 case VIDIOCSFBUF:
2375 {
2376 struct video_buffer *fbuf = arg;
2377 const struct bttv_format *fmt;
2378 unsigned long end;
2379
2380 if(!capable(CAP_SYS_ADMIN) &&
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08002381 !capable(CAP_SYS_RAWIO))
2382 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383 end = (unsigned long)fbuf->base +
2384 fbuf->height * fbuf->bytesperline;
2385 down(&fh->cap.lock);
2386 retval = -EINVAL;
2387
2388 switch (fbuf->depth) {
2389 case 8:
2390 fmt = format_by_palette(VIDEO_PALETTE_HI240);
2391 break;
2392 case 16:
2393 fmt = format_by_palette(VIDEO_PALETTE_RGB565);
2394 break;
2395 case 24:
2396 fmt = format_by_palette(VIDEO_PALETTE_RGB24);
2397 break;
2398 case 32:
2399 fmt = format_by_palette(VIDEO_PALETTE_RGB32);
2400 break;
2401 case 15:
2402 fbuf->depth = 16;
2403 fmt = format_by_palette(VIDEO_PALETTE_RGB555);
2404 break;
2405 default:
2406 fmt = NULL;
2407 break;
2408 }
2409 if (NULL == fmt)
2410 goto fh_unlock_and_return;
2411
2412 fh->ovfmt = fmt;
2413 fh->fmt = fmt;
2414 btv->init.ovfmt = fmt;
2415 btv->init.fmt = fmt;
2416 btv->fbuf.base = fbuf->base;
2417 btv->fbuf.fmt.width = fbuf->width;
2418 btv->fbuf.fmt.height = fbuf->height;
2419 if (fbuf->bytesperline)
2420 btv->fbuf.fmt.bytesperline = fbuf->bytesperline;
2421 else
2422 btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fbuf->depth/8;
2423 up(&fh->cap.lock);
2424 return 0;
2425 }
2426
2427 case VIDIOCCAPTURE:
2428 case VIDIOC_OVERLAY:
2429 {
2430 struct bttv_buffer *new;
2431 int *on = arg;
2432
2433 if (*on) {
2434 /* verify args */
2435 if (NULL == btv->fbuf.base)
2436 return -EINVAL;
2437 if (!fh->ov.setup_ok) {
2438 dprintk("bttv%d: overlay: !setup_ok\n",btv->c.nr);
2439 return -EINVAL;
2440 }
2441 }
2442
2443 if (!check_alloc_btres(btv,fh,RESOURCE_OVERLAY))
2444 return -EBUSY;
2445
2446 down(&fh->cap.lock);
2447 if (*on) {
2448 fh->ov.tvnorm = btv->tvnorm;
2449 new = videobuf_alloc(sizeof(*new));
2450 bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
2451 } else {
2452 new = NULL;
2453 }
2454
2455 /* switch over */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08002456 retval = bttv_switch_overlay(btv,fh,new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457 up(&fh->cap.lock);
2458 return retval;
2459 }
2460
2461 case VIDIOCGMBUF:
2462 {
2463 struct video_mbuf *mbuf = arg;
2464 unsigned int i;
2465
2466 down(&fh->cap.lock);
2467 retval = videobuf_mmap_setup(&fh->cap,gbuffers,gbufsize,
2468 V4L2_MEMORY_MMAP);
2469 if (retval < 0)
2470 goto fh_unlock_and_return;
2471 memset(mbuf,0,sizeof(*mbuf));
2472 mbuf->frames = gbuffers;
2473 mbuf->size = gbuffers * gbufsize;
2474 for (i = 0; i < gbuffers; i++)
2475 mbuf->offsets[i] = i * gbufsize;
2476 up(&fh->cap.lock);
2477 return 0;
2478 }
2479 case VIDIOCMCAPTURE:
2480 {
2481 struct video_mmap *vm = arg;
2482 struct bttv_buffer *buf;
2483 enum v4l2_field field;
2484
2485 if (vm->frame >= VIDEO_MAX_FRAME)
2486 return -EINVAL;
2487
2488 down(&fh->cap.lock);
2489 retval = -EINVAL;
2490 buf = (struct bttv_buffer *)fh->cap.bufs[vm->frame];
2491 if (NULL == buf)
2492 goto fh_unlock_and_return;
2493 if (0 == buf->vb.baddr)
2494 goto fh_unlock_and_return;
2495 if (buf->vb.state == STATE_QUEUED ||
2496 buf->vb.state == STATE_ACTIVE)
2497 goto fh_unlock_and_return;
2498
2499 field = (vm->height > bttv_tvnorms[btv->tvnorm].sheight/2)
2500 ? V4L2_FIELD_INTERLACED
2501 : V4L2_FIELD_BOTTOM;
2502 retval = bttv_prepare_buffer(btv,buf,
2503 format_by_palette(vm->format),
2504 vm->width,vm->height,field);
2505 if (0 != retval)
2506 goto fh_unlock_and_return;
2507 spin_lock_irqsave(&btv->s_lock,flags);
2508 buffer_queue(&fh->cap,&buf->vb);
2509 spin_unlock_irqrestore(&btv->s_lock,flags);
2510 up(&fh->cap.lock);
2511 return 0;
2512 }
2513 case VIDIOCSYNC:
2514 {
2515 int *frame = arg;
2516 struct bttv_buffer *buf;
2517
2518 if (*frame >= VIDEO_MAX_FRAME)
2519 return -EINVAL;
2520
2521 down(&fh->cap.lock);
2522 retval = -EINVAL;
2523 buf = (struct bttv_buffer *)fh->cap.bufs[*frame];
2524 if (NULL == buf)
2525 goto fh_unlock_and_return;
2526 retval = videobuf_waiton(&buf->vb,0,1);
2527 if (0 != retval)
2528 goto fh_unlock_and_return;
2529 switch (buf->vb.state) {
2530 case STATE_ERROR:
2531 retval = -EIO;
2532 /* fall through */
2533 case STATE_DONE:
2534 videobuf_dma_pci_sync(btv->c.pci,&buf->vb.dma);
2535 bttv_dma_free(btv,buf);
2536 break;
2537 default:
2538 retval = -EINVAL;
2539 break;
2540 }
2541 up(&fh->cap.lock);
2542 return retval;
2543 }
2544
2545 case VIDIOCGVBIFMT:
2546 {
2547 struct vbi_format *fmt = (void *) arg;
2548 struct v4l2_format fmt2;
2549
2550 if (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE) {
2551 retval = bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE);
2552 if (0 != retval)
2553 return retval;
2554 }
2555 bttv_vbi_get_fmt(fh, &fmt2);
2556
2557 memset(fmt,0,sizeof(*fmt));
2558 fmt->sampling_rate = fmt2.fmt.vbi.sampling_rate;
2559 fmt->samples_per_line = fmt2.fmt.vbi.samples_per_line;
2560 fmt->sample_format = VIDEO_PALETTE_RAW;
2561 fmt->start[0] = fmt2.fmt.vbi.start[0];
2562 fmt->count[0] = fmt2.fmt.vbi.count[0];
2563 fmt->start[1] = fmt2.fmt.vbi.start[1];
2564 fmt->count[1] = fmt2.fmt.vbi.count[1];
2565 if (fmt2.fmt.vbi.flags & VBI_UNSYNC)
2566 fmt->flags |= V4L2_VBI_UNSYNC;
2567 if (fmt2.fmt.vbi.flags & VBI_INTERLACED)
2568 fmt->flags |= V4L2_VBI_INTERLACED;
2569 return 0;
2570 }
2571 case VIDIOCSVBIFMT:
2572 {
2573 struct vbi_format *fmt = (void *) arg;
2574 struct v4l2_format fmt2;
2575
2576 retval = bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE);
2577 if (0 != retval)
2578 return retval;
2579 bttv_vbi_get_fmt(fh, &fmt2);
2580
2581 if (fmt->sampling_rate != fmt2.fmt.vbi.sampling_rate ||
2582 fmt->samples_per_line != fmt2.fmt.vbi.samples_per_line ||
2583 fmt->sample_format != VIDEO_PALETTE_RAW ||
2584 fmt->start[0] != fmt2.fmt.vbi.start[0] ||
2585 fmt->start[1] != fmt2.fmt.vbi.start[1] ||
2586 fmt->count[0] != fmt->count[1] ||
2587 fmt->count[0] < 1 ||
2588 fmt->count[0] > 32 /* VBI_MAXLINES */)
2589 return -EINVAL;
2590
2591 bttv_vbi_setlines(fh,btv,fmt->count[0]);
2592 return 0;
2593 }
2594
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08002595 case BTTV_VERSION:
2596 case VIDIOCGFREQ:
2597 case VIDIOCSFREQ:
2598 case VIDIOCGTUNER:
2599 case VIDIOCSTUNER:
2600 case VIDIOCGCHAN:
2601 case VIDIOCSCHAN:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602 case VIDIOCGAUDIO:
2603 case VIDIOCSAUDIO:
2604 return bttv_common_ioctls(btv,cmd,arg);
2605
2606 /* *** v4l2 *** ************************************************ */
2607 case VIDIOC_QUERYCAP:
2608 {
2609 struct v4l2_capability *cap = arg;
2610
2611 if (0 == v4l2)
2612 return -EINVAL;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08002613 strcpy(cap->driver,"bttv");
2614 strlcpy(cap->card,btv->video_dev->name,sizeof(cap->card));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615 sprintf(cap->bus_info,"PCI:%s",pci_name(btv->c.pci));
2616 cap->version = BTTV_VERSION_CODE;
2617 cap->capabilities =
2618 V4L2_CAP_VIDEO_CAPTURE |
Linus Torvalds1da177e2005-04-16 15:20:36 -07002619 V4L2_CAP_VBI_CAPTURE |
2620 V4L2_CAP_READWRITE |
2621 V4L2_CAP_STREAMING;
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07002622 if (no_overlay <= 0)
2623 cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
2624
Linus Torvalds1da177e2005-04-16 15:20:36 -07002625 if (bttv_tvcards[btv->c.type].tuner != UNSET &&
2626 bttv_tvcards[btv->c.type].tuner != TUNER_ABSENT)
2627 cap->capabilities |= V4L2_CAP_TUNER;
2628 return 0;
2629 }
2630
2631 case VIDIOC_ENUM_FMT:
2632 {
2633 struct v4l2_fmtdesc *f = arg;
2634 enum v4l2_buf_type type;
2635 unsigned int i;
2636 int index;
2637
2638 type = f->type;
2639 if (V4L2_BUF_TYPE_VBI_CAPTURE == type) {
2640 /* vbi */
2641 index = f->index;
2642 if (0 != index)
2643 return -EINVAL;
2644 memset(f,0,sizeof(*f));
2645 f->index = index;
2646 f->type = type;
2647 f->pixelformat = V4L2_PIX_FMT_GREY;
2648 strcpy(f->description,"vbi data");
2649 return 0;
2650 }
2651
2652 /* video capture + overlay */
2653 index = -1;
2654 for (i = 0; i < BTTV_FORMATS; i++) {
2655 if (bttv_formats[i].fourcc != -1)
2656 index++;
2657 if ((unsigned int)index == f->index)
2658 break;
2659 }
2660 if (BTTV_FORMATS == i)
2661 return -EINVAL;
2662
2663 switch (f->type) {
2664 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2665 break;
2666 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
2667 if (!(bttv_formats[i].flags & FORMAT_FLAGS_PACKED))
2668 return -EINVAL;
2669 break;
2670 default:
2671 return -EINVAL;
2672 }
2673 memset(f,0,sizeof(*f));
2674 f->index = index;
2675 f->type = type;
2676 f->pixelformat = bttv_formats[i].fourcc;
2677 strlcpy(f->description,bttv_formats[i].name,sizeof(f->description));
2678 return 0;
2679 }
2680
2681 case VIDIOC_TRY_FMT:
2682 {
2683 struct v4l2_format *f = arg;
2684 return bttv_try_fmt(fh,btv,f);
2685 }
2686 case VIDIOC_G_FMT:
2687 {
2688 struct v4l2_format *f = arg;
2689 return bttv_g_fmt(fh,f);
2690 }
2691 case VIDIOC_S_FMT:
2692 {
2693 struct v4l2_format *f = arg;
2694 return bttv_s_fmt(fh,btv,f);
2695 }
2696
2697 case VIDIOC_G_FBUF:
2698 {
2699 struct v4l2_framebuffer *fb = arg;
2700
2701 *fb = btv->fbuf;
2702 fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
2703 if (fh->ovfmt)
2704 fb->fmt.pixelformat = fh->ovfmt->fourcc;
2705 return 0;
2706 }
2707 case VIDIOC_S_FBUF:
2708 {
2709 struct v4l2_framebuffer *fb = arg;
2710 const struct bttv_format *fmt;
2711
2712 if(!capable(CAP_SYS_ADMIN) &&
2713 !capable(CAP_SYS_RAWIO))
2714 return -EPERM;
2715
2716 /* check args */
2717 fmt = format_by_fourcc(fb->fmt.pixelformat);
2718 if (NULL == fmt)
2719 return -EINVAL;
2720 if (0 == (fmt->flags & FORMAT_FLAGS_PACKED))
2721 return -EINVAL;
2722
2723 down(&fh->cap.lock);
2724 retval = -EINVAL;
2725 if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
2726 if (fb->fmt.width > bttv_tvnorms[btv->tvnorm].swidth)
2727 goto fh_unlock_and_return;
2728 if (fb->fmt.height > bttv_tvnorms[btv->tvnorm].sheight)
2729 goto fh_unlock_and_return;
2730 }
2731
2732 /* ok, accept it */
2733 btv->fbuf.base = fb->base;
2734 btv->fbuf.fmt.width = fb->fmt.width;
2735 btv->fbuf.fmt.height = fb->fmt.height;
2736 if (0 != fb->fmt.bytesperline)
2737 btv->fbuf.fmt.bytesperline = fb->fmt.bytesperline;
2738 else
2739 btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fmt->depth/8;
2740
2741 retval = 0;
2742 fh->ovfmt = fmt;
2743 btv->init.ovfmt = fmt;
2744 if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
2745 fh->ov.w.left = 0;
2746 fh->ov.w.top = 0;
2747 fh->ov.w.width = fb->fmt.width;
2748 fh->ov.w.height = fb->fmt.height;
2749 btv->init.ov.w.width = fb->fmt.width;
2750 btv->init.ov.w.height = fb->fmt.height;
Jesper Juhl2ea75332005-11-07 01:01:31 -08002751 kfree(fh->ov.clips);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002752 fh->ov.clips = NULL;
2753 fh->ov.nclips = 0;
2754
2755 if (check_btres(fh, RESOURCE_OVERLAY)) {
2756 struct bttv_buffer *new;
2757
2758 new = videobuf_alloc(sizeof(*new));
2759 bttv_overlay_risc(btv,&fh->ov,fh->ovfmt,new);
2760 retval = bttv_switch_overlay(btv,fh,new);
2761 }
2762 }
2763 up(&fh->cap.lock);
2764 return retval;
2765 }
2766
2767 case VIDIOC_REQBUFS:
2768 return videobuf_reqbufs(bttv_queue(fh),arg);
2769
2770 case VIDIOC_QUERYBUF:
2771 return videobuf_querybuf(bttv_queue(fh),arg);
2772
2773 case VIDIOC_QBUF:
2774 return videobuf_qbuf(bttv_queue(fh),arg);
2775
2776 case VIDIOC_DQBUF:
2777 return videobuf_dqbuf(bttv_queue(fh),arg,
2778 file->f_flags & O_NONBLOCK);
2779
2780 case VIDIOC_STREAMON:
2781 {
2782 int res = bttv_resource(fh);
2783
2784 if (!check_alloc_btres(btv,fh,res))
2785 return -EBUSY;
2786 return videobuf_streamon(bttv_queue(fh));
2787 }
2788 case VIDIOC_STREAMOFF:
2789 {
2790 int res = bttv_resource(fh);
2791
2792 retval = videobuf_streamoff(bttv_queue(fh));
2793 if (retval < 0)
2794 return retval;
2795 free_btres(btv,fh,res);
2796 return 0;
2797 }
2798
2799 case VIDIOC_QUERYCTRL:
2800 {
2801 struct v4l2_queryctrl *c = arg;
2802 int i;
2803
2804 if ((c->id < V4L2_CID_BASE ||
2805 c->id >= V4L2_CID_LASTP1) &&
2806 (c->id < V4L2_CID_PRIVATE_BASE ||
2807 c->id >= V4L2_CID_PRIVATE_LASTP1))
2808 return -EINVAL;
2809 for (i = 0; i < BTTV_CTLS; i++)
2810 if (bttv_ctls[i].id == c->id)
2811 break;
2812 if (i == BTTV_CTLS) {
2813 *c = no_ctl;
2814 return 0;
2815 }
2816 *c = bttv_ctls[i];
2817 if (i >= 4 && i <= 8) {
2818 struct video_audio va;
2819 memset(&va,0,sizeof(va));
2820 bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
2821 if (btv->audio_hook)
2822 btv->audio_hook(btv,&va,0);
2823 switch (bttv_ctls[i].id) {
2824 case V4L2_CID_AUDIO_VOLUME:
2825 if (!(va.flags & VIDEO_AUDIO_VOLUME))
2826 *c = no_ctl;
2827 break;
2828 case V4L2_CID_AUDIO_BALANCE:
2829 if (!(va.flags & VIDEO_AUDIO_BALANCE))
2830 *c = no_ctl;
2831 break;
2832 case V4L2_CID_AUDIO_BASS:
2833 if (!(va.flags & VIDEO_AUDIO_BASS))
2834 *c = no_ctl;
2835 break;
2836 case V4L2_CID_AUDIO_TREBLE:
2837 if (!(va.flags & VIDEO_AUDIO_TREBLE))
2838 *c = no_ctl;
2839 break;
2840 }
2841 }
2842 return 0;
2843 }
2844 case VIDIOC_G_CTRL:
2845 return get_control(btv,arg);
2846 case VIDIOC_S_CTRL:
2847 return set_control(btv,arg);
2848 case VIDIOC_G_PARM:
2849 {
2850 struct v4l2_streamparm *parm = arg;
2851 struct v4l2_standard s;
2852 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
2853 return -EINVAL;
2854 memset(parm,0,sizeof(*parm));
2855 v4l2_video_std_construct(&s, bttv_tvnorms[btv->tvnorm].v4l2_id,
2856 bttv_tvnorms[btv->tvnorm].name);
2857 parm->parm.capture.timeperframe = s.frameperiod;
2858 return 0;
2859 }
2860
2861 case VIDIOC_G_PRIORITY:
2862 {
2863 enum v4l2_priority *p = arg;
2864
2865 *p = v4l2_prio_max(&btv->prio);
2866 return 0;
2867 }
2868 case VIDIOC_S_PRIORITY:
2869 {
2870 enum v4l2_priority *prio = arg;
2871
2872 return v4l2_prio_change(&btv->prio, &fh->prio, *prio);
2873 }
2874
2875 case VIDIOC_ENUMSTD:
2876 case VIDIOC_G_STD:
2877 case VIDIOC_S_STD:
2878 case VIDIOC_ENUMINPUT:
2879 case VIDIOC_G_INPUT:
2880 case VIDIOC_S_INPUT:
2881 case VIDIOC_G_TUNER:
2882 case VIDIOC_S_TUNER:
2883 case VIDIOC_G_FREQUENCY:
2884 case VIDIOC_S_FREQUENCY:
Hans Verkuil299392b2005-11-08 21:37:42 -08002885 case VIDIOC_LOG_STATUS:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002886 return bttv_common_ioctls(btv,cmd,arg);
2887
2888 default:
2889 return -ENOIOCTLCMD;
2890 }
2891 return 0;
2892
2893 fh_unlock_and_return:
2894 up(&fh->cap.lock);
2895 return retval;
2896}
2897
2898static int bttv_ioctl(struct inode *inode, struct file *file,
2899 unsigned int cmd, unsigned long arg)
2900{
2901 struct bttv_fh *fh = file->private_data;
2902
2903 switch (cmd) {
2904 case BTTV_VBISIZE:
2905 bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE);
2906 return fh->lines * 2 * 2048;
2907 default:
2908 return video_usercopy(inode, file, cmd, arg, bttv_do_ioctl);
2909 }
2910}
2911
2912static ssize_t bttv_read(struct file *file, char __user *data,
2913 size_t count, loff_t *ppos)
2914{
2915 struct bttv_fh *fh = file->private_data;
2916 int retval = 0;
2917
2918 if (fh->btv->errors)
2919 bttv_reinit_bt848(fh->btv);
2920 dprintk("bttv%d: read count=%d type=%s\n",
2921 fh->btv->c.nr,(int)count,v4l2_type_names[fh->type]);
2922
2923 switch (fh->type) {
2924 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2925 if (locked_btres(fh->btv,RESOURCE_VIDEO))
2926 return -EBUSY;
2927 retval = videobuf_read_one(&fh->cap, data, count, ppos,
2928 file->f_flags & O_NONBLOCK);
2929 break;
2930 case V4L2_BUF_TYPE_VBI_CAPTURE:
2931 if (!check_alloc_btres(fh->btv,fh,RESOURCE_VBI))
2932 return -EBUSY;
2933 retval = videobuf_read_stream(&fh->vbi, data, count, ppos, 1,
2934 file->f_flags & O_NONBLOCK);
2935 break;
2936 default:
2937 BUG();
2938 }
2939 return retval;
2940}
2941
2942static unsigned int bttv_poll(struct file *file, poll_table *wait)
2943{
2944 struct bttv_fh *fh = file->private_data;
2945 struct bttv_buffer *buf;
2946 enum v4l2_field field;
2947
2948 if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
2949 if (!check_alloc_btres(fh->btv,fh,RESOURCE_VBI))
2950 return POLLERR;
2951 return videobuf_poll_stream(file, &fh->vbi, wait);
2952 }
2953
2954 if (check_btres(fh,RESOURCE_VIDEO)) {
2955 /* streaming capture */
2956 if (list_empty(&fh->cap.stream))
2957 return POLLERR;
2958 buf = list_entry(fh->cap.stream.next,struct bttv_buffer,vb.stream);
2959 } else {
2960 /* read() capture */
2961 down(&fh->cap.lock);
2962 if (NULL == fh->cap.read_buf) {
2963 /* need to capture a new frame */
2964 if (locked_btres(fh->btv,RESOURCE_VIDEO)) {
2965 up(&fh->cap.lock);
2966 return POLLERR;
2967 }
2968 fh->cap.read_buf = videobuf_alloc(fh->cap.msize);
2969 if (NULL == fh->cap.read_buf) {
2970 up(&fh->cap.lock);
2971 return POLLERR;
2972 }
2973 fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR;
2974 field = videobuf_next_field(&fh->cap);
2975 if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,field)) {
Nickolay V. Shmyrev50ab5ed2005-12-01 00:51:32 -08002976 kfree (fh->cap.read_buf);
2977 fh->cap.read_buf = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002978 up(&fh->cap.lock);
2979 return POLLERR;
2980 }
2981 fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf);
2982 fh->cap.read_off = 0;
2983 }
2984 up(&fh->cap.lock);
2985 buf = (struct bttv_buffer*)fh->cap.read_buf;
2986 }
2987
2988 poll_wait(file, &buf->vb.done, wait);
2989 if (buf->vb.state == STATE_DONE ||
2990 buf->vb.state == STATE_ERROR)
2991 return POLLIN|POLLRDNORM;
2992 return 0;
2993}
2994
2995static int bttv_open(struct inode *inode, struct file *file)
2996{
2997 int minor = iminor(inode);
2998 struct bttv *btv = NULL;
2999 struct bttv_fh *fh;
3000 enum v4l2_buf_type type = 0;
3001 unsigned int i;
3002
3003 dprintk(KERN_DEBUG "bttv: open minor=%d\n",minor);
3004
3005 for (i = 0; i < bttv_num; i++) {
3006 if (bttvs[i].video_dev &&
3007 bttvs[i].video_dev->minor == minor) {
3008 btv = &bttvs[i];
3009 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
3010 break;
3011 }
3012 if (bttvs[i].vbi_dev &&
3013 bttvs[i].vbi_dev->minor == minor) {
3014 btv = &bttvs[i];
3015 type = V4L2_BUF_TYPE_VBI_CAPTURE;
3016 break;
3017 }
3018 }
3019 if (NULL == btv)
3020 return -ENODEV;
3021
3022 dprintk(KERN_DEBUG "bttv%d: open called (type=%s)\n",
3023 btv->c.nr,v4l2_type_names[type]);
3024
3025 /* allocate per filehandle data */
3026 fh = kmalloc(sizeof(*fh),GFP_KERNEL);
3027 if (NULL == fh)
3028 return -ENOMEM;
3029 file->private_data = fh;
3030 *fh = btv->init;
3031 fh->type = type;
3032 fh->ov.setup_ok = 0;
3033 v4l2_prio_open(&btv->prio,&fh->prio);
3034
3035 videobuf_queue_init(&fh->cap, &bttv_video_qops,
3036 btv->c.pci, &btv->s_lock,
3037 V4L2_BUF_TYPE_VIDEO_CAPTURE,
3038 V4L2_FIELD_INTERLACED,
3039 sizeof(struct bttv_buffer),
3040 fh);
3041 videobuf_queue_init(&fh->vbi, &bttv_vbi_qops,
3042 btv->c.pci, &btv->s_lock,
3043 V4L2_BUF_TYPE_VBI_CAPTURE,
3044 V4L2_FIELD_SEQ_TB,
3045 sizeof(struct bttv_buffer),
3046 fh);
3047 i2c_vidiocschan(btv);
3048
3049 btv->users++;
3050 if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type)
3051 bttv_vbi_setlines(fh,btv,16);
3052 bttv_field_count(btv);
3053 return 0;
3054}
3055
3056static int bttv_release(struct inode *inode, struct file *file)
3057{
3058 struct bttv_fh *fh = file->private_data;
3059 struct bttv *btv = fh->btv;
3060
3061 /* turn off overlay */
3062 if (check_btres(fh, RESOURCE_OVERLAY))
3063 bttv_switch_overlay(btv,fh,NULL);
3064
3065 /* stop video capture */
3066 if (check_btres(fh, RESOURCE_VIDEO)) {
3067 videobuf_streamoff(&fh->cap);
3068 free_btres(btv,fh,RESOURCE_VIDEO);
3069 }
3070 if (fh->cap.read_buf) {
3071 buffer_release(&fh->cap,fh->cap.read_buf);
3072 kfree(fh->cap.read_buf);
3073 }
3074
3075 /* stop vbi capture */
3076 if (check_btres(fh, RESOURCE_VBI)) {
3077 if (fh->vbi.streaming)
3078 videobuf_streamoff(&fh->vbi);
3079 if (fh->vbi.reading)
3080 videobuf_read_stop(&fh->vbi);
3081 free_btres(btv,fh,RESOURCE_VBI);
3082 }
3083
3084 /* free stuff */
3085 videobuf_mmap_free(&fh->cap);
3086 videobuf_mmap_free(&fh->vbi);
3087 v4l2_prio_close(&btv->prio,&fh->prio);
3088 file->private_data = NULL;
3089 kfree(fh);
3090
3091 btv->users--;
3092 bttv_field_count(btv);
3093 return 0;
3094}
3095
3096static int
3097bttv_mmap(struct file *file, struct vm_area_struct *vma)
3098{
3099 struct bttv_fh *fh = file->private_data;
3100
3101 dprintk("bttv%d: mmap type=%s 0x%lx+%ld\n",
3102 fh->btv->c.nr, v4l2_type_names[fh->type],
3103 vma->vm_start, vma->vm_end - vma->vm_start);
3104 return videobuf_mmap_mapper(bttv_queue(fh),vma);
3105}
3106
3107static struct file_operations bttv_fops =
3108{
3109 .owner = THIS_MODULE,
3110 .open = bttv_open,
3111 .release = bttv_release,
3112 .ioctl = bttv_ioctl,
3113 .llseek = no_llseek,
3114 .read = bttv_read,
3115 .mmap = bttv_mmap,
3116 .poll = bttv_poll,
3117};
3118
3119static struct video_device bttv_video_template =
3120{
3121 .name = "UNSET",
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07003122 .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003123 VID_TYPE_CLIPPING|VID_TYPE_SCALES,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003124 .hardware = VID_HARDWARE_BT848,
3125 .fops = &bttv_fops,
3126 .minor = -1,
3127};
3128
3129static struct video_device bttv_vbi_template =
3130{
3131 .name = "bt848/878 vbi",
3132 .type = VID_TYPE_TUNER|VID_TYPE_TELETEXT,
3133 .hardware = VID_HARDWARE_BT848,
3134 .fops = &bttv_fops,
3135 .minor = -1,
3136};
3137
3138/* ----------------------------------------------------------------------- */
3139/* radio interface */
3140
3141static int radio_open(struct inode *inode, struct file *file)
3142{
3143 int minor = iminor(inode);
3144 struct bttv *btv = NULL;
3145 unsigned int i;
3146
3147 dprintk("bttv: open minor=%d\n",minor);
3148
3149 for (i = 0; i < bttv_num; i++) {
3150 if (bttvs[i].radio_dev->minor == minor) {
3151 btv = &bttvs[i];
3152 break;
3153 }
3154 }
3155 if (NULL == btv)
3156 return -ENODEV;
3157
3158 dprintk("bttv%d: open called (radio)\n",btv->c.nr);
3159 down(&btv->lock);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003160
Linus Torvalds1da177e2005-04-16 15:20:36 -07003161 btv->radio_user++;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003162
Linus Torvalds1da177e2005-04-16 15:20:36 -07003163 file->private_data = btv;
3164
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003165 bttv_call_i2c_clients(btv,AUDC_SET_RADIO,&btv->tuner_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003166 audio_mux(btv,AUDIO_RADIO);
3167
3168 up(&btv->lock);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003169 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003170}
3171
3172static int radio_release(struct inode *inode, struct file *file)
3173{
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003174 struct bttv *btv = file->private_data;
3175 struct rds_command cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003176
3177 btv->radio_user--;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003178
3179 bttv_call_i2c_clients(btv, RDS_CMD_CLOSE, &cmd);
3180
Linus Torvalds1da177e2005-04-16 15:20:36 -07003181 return 0;
3182}
3183
3184static int radio_do_ioctl(struct inode *inode, struct file *file,
3185 unsigned int cmd, void *arg)
3186{
3187 struct bttv *btv = file->private_data;
3188
3189 switch (cmd) {
3190 case VIDIOCGCAP:
3191 {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003192 struct video_capability *cap = arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003193
3194 memset(cap,0,sizeof(*cap));
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003195 strcpy(cap->name,btv->radio_dev->name);
3196 cap->type = VID_TYPE_TUNER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197 cap->channels = 1;
3198 cap->audios = 1;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003199 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003200 }
3201
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003202 case VIDIOCGTUNER:
3203 {
3204 struct video_tuner *v = arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003205
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003206 if(v->tuner)
3207 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003208 memset(v,0,sizeof(*v));
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003209 strcpy(v->name, "Radio");
3210 bttv_call_i2c_clients(btv,cmd,v);
3211 return 0;
3212 }
3213 case VIDIOCSTUNER:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003214 /* nothing to do */
3215 return 0;
3216
3217 case BTTV_VERSION:
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003218 case VIDIOCGFREQ:
3219 case VIDIOCSFREQ:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003220 case VIDIOCGAUDIO:
3221 case VIDIOCSAUDIO:
3222 return bttv_common_ioctls(btv,cmd,arg);
3223
3224 default:
3225 return -ENOIOCTLCMD;
3226 }
3227 return 0;
3228}
3229
3230static int radio_ioctl(struct inode *inode, struct file *file,
3231 unsigned int cmd, unsigned long arg)
3232{
3233 return video_usercopy(inode, file, cmd, arg, radio_do_ioctl);
3234}
3235
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003236static ssize_t radio_read(struct file *file, char __user *data,
3237 size_t count, loff_t *ppos)
3238{
3239 struct bttv *btv = file->private_data;
3240 struct rds_command cmd;
3241 cmd.block_count = count/3;
3242 cmd.buffer = data;
3243 cmd.instance = file;
3244 cmd.result = -ENODEV;
3245
3246 bttv_call_i2c_clients(btv, RDS_CMD_READ, &cmd);
3247
3248 return cmd.result;
3249}
3250
3251static unsigned int radio_poll(struct file *file, poll_table *wait)
3252{
3253 struct bttv *btv = file->private_data;
3254 struct rds_command cmd;
3255 cmd.instance = file;
3256 cmd.event_list = wait;
3257 cmd.result = -ENODEV;
3258 bttv_call_i2c_clients(btv, RDS_CMD_POLL, &cmd);
3259
3260 return cmd.result;
3261}
3262
Linus Torvalds1da177e2005-04-16 15:20:36 -07003263static struct file_operations radio_fops =
3264{
3265 .owner = THIS_MODULE,
3266 .open = radio_open,
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003267 .read = radio_read,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003268 .release = radio_release,
3269 .ioctl = radio_ioctl,
3270 .llseek = no_llseek,
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003271 .poll = radio_poll,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003272};
3273
3274static struct video_device radio_template =
3275{
3276 .name = "bt848/878 radio",
3277 .type = VID_TYPE_TUNER,
3278 .hardware = VID_HARDWARE_BT848,
3279 .fops = &radio_fops,
3280 .minor = -1,
3281};
3282
3283/* ----------------------------------------------------------------------- */
3284/* some debug code */
3285
Adrian Bunk408b6642005-05-01 08:59:29 -07003286static int bttv_risc_decode(u32 risc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003287{
3288 static char *instr[16] = {
3289 [ BT848_RISC_WRITE >> 28 ] = "write",
3290 [ BT848_RISC_SKIP >> 28 ] = "skip",
3291 [ BT848_RISC_WRITEC >> 28 ] = "writec",
3292 [ BT848_RISC_JUMP >> 28 ] = "jump",
3293 [ BT848_RISC_SYNC >> 28 ] = "sync",
3294 [ BT848_RISC_WRITE123 >> 28 ] = "write123",
3295 [ BT848_RISC_SKIP123 >> 28 ] = "skip123",
3296 [ BT848_RISC_WRITE1S23 >> 28 ] = "write1s23",
3297 };
3298 static int incr[16] = {
3299 [ BT848_RISC_WRITE >> 28 ] = 2,
3300 [ BT848_RISC_JUMP >> 28 ] = 2,
3301 [ BT848_RISC_SYNC >> 28 ] = 2,
3302 [ BT848_RISC_WRITE123 >> 28 ] = 5,
3303 [ BT848_RISC_SKIP123 >> 28 ] = 2,
3304 [ BT848_RISC_WRITE1S23 >> 28 ] = 3,
3305 };
3306 static char *bits[] = {
3307 "be0", "be1", "be2", "be3/resync",
3308 "set0", "set1", "set2", "set3",
3309 "clr0", "clr1", "clr2", "clr3",
3310 "irq", "res", "eol", "sol",
3311 };
3312 int i;
3313
3314 printk("0x%08x [ %s", risc,
3315 instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
3316 for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
3317 if (risc & (1 << (i + 12)))
3318 printk(" %s",bits[i]);
3319 printk(" count=%d ]\n", risc & 0xfff);
3320 return incr[risc >> 28] ? incr[risc >> 28] : 1;
3321}
3322
Adrian Bunk408b6642005-05-01 08:59:29 -07003323static void bttv_risc_disasm(struct bttv *btv,
3324 struct btcx_riscmem *risc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003325{
3326 unsigned int i,j,n;
3327
3328 printk("%s: risc disasm: %p [dma=0x%08lx]\n",
3329 btv->c.name, risc->cpu, (unsigned long)risc->dma);
3330 for (i = 0; i < (risc->size >> 2); i += n) {
3331 printk("%s: 0x%lx: ", btv->c.name,
3332 (unsigned long)(risc->dma + (i<<2)));
3333 n = bttv_risc_decode(risc->cpu[i]);
3334 for (j = 1; j < n; j++)
3335 printk("%s: 0x%lx: 0x%08x [ arg #%d ]\n",
3336 btv->c.name, (unsigned long)(risc->dma + ((i+j)<<2)),
3337 risc->cpu[i+j], j);
3338 if (0 == risc->cpu[i])
3339 break;
3340 }
3341}
3342
3343static void bttv_print_riscaddr(struct bttv *btv)
3344{
3345 printk(" main: %08Lx\n",
3346 (unsigned long long)btv->main.dma);
3347 printk(" vbi : o=%08Lx e=%08Lx\n",
3348 btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
3349 btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0);
3350 printk(" cap : o=%08Lx e=%08Lx\n",
3351 btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0,
3352 btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
3353 printk(" scr : o=%08Lx e=%08Lx\n",
3354 btv->screen ? (unsigned long long)btv->screen->top.dma : 0,
3355 btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0);
3356 bttv_risc_disasm(btv, &btv->main);
3357}
3358
3359/* ----------------------------------------------------------------------- */
3360/* irq handler */
3361
3362static char *irq_name[] = {
3363 "FMTCHG", // format change detected (525 vs. 625)
3364 "VSYNC", // vertical sync (new field)
3365 "HSYNC", // horizontal sync
3366 "OFLOW", // chroma/luma AGC overflow
3367 "HLOCK", // horizontal lock changed
3368 "VPRES", // video presence changed
3369 "6", "7",
3370 "I2CDONE", // hw irc operation finished
3371 "GPINT", // gpio port triggered irq
3372 "10",
3373 "RISCI", // risc instruction triggered irq
3374 "FBUS", // pixel data fifo dropped data (high pci bus latencies)
3375 "FTRGT", // pixel data fifo overrun
3376 "FDSR", // fifo data stream resyncronisation
3377 "PPERR", // parity error (data transfer)
3378 "RIPERR", // parity error (read risc instructions)
3379 "PABORT", // pci abort
3380 "OCERR", // risc instruction error
3381 "SCERR", // syncronisation error
3382};
3383
3384static void bttv_print_irqbits(u32 print, u32 mark)
3385{
3386 unsigned int i;
3387
3388 printk("bits:");
3389 for (i = 0; i < ARRAY_SIZE(irq_name); i++) {
3390 if (print & (1 << i))
3391 printk(" %s",irq_name[i]);
3392 if (mark & (1 << i))
3393 printk("*");
3394 }
3395}
3396
3397static void bttv_irq_debug_low_latency(struct bttv *btv, u32 rc)
3398{
3399 printk("bttv%d: irq: skipped frame [main=%lx,o_vbi=%lx,o_field=%lx,rc=%lx]\n",
3400 btv->c.nr,
3401 (unsigned long)btv->main.dma,
3402 (unsigned long)btv->main.cpu[RISC_SLOT_O_VBI+1],
3403 (unsigned long)btv->main.cpu[RISC_SLOT_O_FIELD+1],
3404 (unsigned long)rc);
3405
3406 if (0 == (btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC)) {
3407 printk("bttv%d: Oh, there (temporarely?) is no input signal. "
3408 "Ok, then this is harmless, don't worry ;)\n",
3409 btv->c.nr);
3410 return;
3411 }
3412 printk("bttv%d: Uhm. Looks like we have unusual high IRQ latencies.\n",
3413 btv->c.nr);
3414 printk("bttv%d: Lets try to catch the culpit red-handed ...\n",
3415 btv->c.nr);
3416 dump_stack();
3417}
3418
3419static int
3420bttv_irq_next_video(struct bttv *btv, struct bttv_buffer_set *set)
3421{
3422 struct bttv_buffer *item;
3423
3424 memset(set,0,sizeof(*set));
3425
3426 /* capture request ? */
3427 if (!list_empty(&btv->capture)) {
3428 set->frame_irq = 1;
3429 item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
3430 if (V4L2_FIELD_HAS_TOP(item->vb.field))
3431 set->top = item;
3432 if (V4L2_FIELD_HAS_BOTTOM(item->vb.field))
3433 set->bottom = item;
3434
3435 /* capture request for other field ? */
3436 if (!V4L2_FIELD_HAS_BOTH(item->vb.field) &&
3437 (item->vb.queue.next != &btv->capture)) {
3438 item = list_entry(item->vb.queue.next, struct bttv_buffer, vb.queue);
3439 if (!V4L2_FIELD_HAS_BOTH(item->vb.field)) {
3440 if (NULL == set->top &&
3441 V4L2_FIELD_TOP == item->vb.field) {
3442 set->top = item;
3443 }
3444 if (NULL == set->bottom &&
3445 V4L2_FIELD_BOTTOM == item->vb.field) {
3446 set->bottom = item;
3447 }
3448 if (NULL != set->top && NULL != set->bottom)
3449 set->top_irq = 2;
3450 }
3451 }
3452 }
3453
3454 /* screen overlay ? */
3455 if (NULL != btv->screen) {
3456 if (V4L2_FIELD_HAS_BOTH(btv->screen->vb.field)) {
3457 if (NULL == set->top && NULL == set->bottom) {
3458 set->top = btv->screen;
3459 set->bottom = btv->screen;
3460 }
3461 } else {
3462 if (V4L2_FIELD_TOP == btv->screen->vb.field &&
3463 NULL == set->top) {
3464 set->top = btv->screen;
3465 }
3466 if (V4L2_FIELD_BOTTOM == btv->screen->vb.field &&
3467 NULL == set->bottom) {
3468 set->bottom = btv->screen;
3469 }
3470 }
3471 }
3472
3473 dprintk("bttv%d: next set: top=%p bottom=%p [screen=%p,irq=%d,%d]\n",
3474 btv->c.nr,set->top, set->bottom,
3475 btv->screen,set->frame_irq,set->top_irq);
3476 return 0;
3477}
3478
3479static void
3480bttv_irq_wakeup_video(struct bttv *btv, struct bttv_buffer_set *wakeup,
3481 struct bttv_buffer_set *curr, unsigned int state)
3482{
3483 struct timeval ts;
3484
3485 do_gettimeofday(&ts);
3486
3487 if (wakeup->top == wakeup->bottom) {
3488 if (NULL != wakeup->top && curr->top != wakeup->top) {
3489 if (irq_debug > 1)
3490 printk("bttv%d: wakeup: both=%p\n",btv->c.nr,wakeup->top);
3491 wakeup->top->vb.ts = ts;
3492 wakeup->top->vb.field_count = btv->field_count;
3493 wakeup->top->vb.state = state;
3494 wake_up(&wakeup->top->vb.done);
3495 }
3496 } else {
3497 if (NULL != wakeup->top && curr->top != wakeup->top) {
3498 if (irq_debug > 1)
3499 printk("bttv%d: wakeup: top=%p\n",btv->c.nr,wakeup->top);
3500 wakeup->top->vb.ts = ts;
3501 wakeup->top->vb.field_count = btv->field_count;
3502 wakeup->top->vb.state = state;
3503 wake_up(&wakeup->top->vb.done);
3504 }
3505 if (NULL != wakeup->bottom && curr->bottom != wakeup->bottom) {
3506 if (irq_debug > 1)
3507 printk("bttv%d: wakeup: bottom=%p\n",btv->c.nr,wakeup->bottom);
3508 wakeup->bottom->vb.ts = ts;
3509 wakeup->bottom->vb.field_count = btv->field_count;
3510 wakeup->bottom->vb.state = state;
3511 wake_up(&wakeup->bottom->vb.done);
3512 }
3513 }
3514}
3515
3516static void
3517bttv_irq_wakeup_vbi(struct bttv *btv, struct bttv_buffer *wakeup,
3518 unsigned int state)
3519{
3520 struct timeval ts;
3521
3522 if (NULL == wakeup)
3523 return;
3524
3525 do_gettimeofday(&ts);
3526 wakeup->vb.ts = ts;
3527 wakeup->vb.field_count = btv->field_count;
3528 wakeup->vb.state = state;
3529 wake_up(&wakeup->vb.done);
3530}
3531
3532static void bttv_irq_timeout(unsigned long data)
3533{
3534 struct bttv *btv = (struct bttv *)data;
3535 struct bttv_buffer_set old,new;
3536 struct bttv_buffer *ovbi;
3537 struct bttv_buffer *item;
3538 unsigned long flags;
3539
3540 if (bttv_verbose) {
3541 printk(KERN_INFO "bttv%d: timeout: drop=%d irq=%d/%d, risc=%08x, ",
3542 btv->c.nr, btv->framedrop, btv->irq_me, btv->irq_total,
3543 btread(BT848_RISC_COUNT));
3544 bttv_print_irqbits(btread(BT848_INT_STAT),0);
3545 printk("\n");
3546 }
3547
3548 spin_lock_irqsave(&btv->s_lock,flags);
3549
3550 /* deactivate stuff */
3551 memset(&new,0,sizeof(new));
3552 old = btv->curr;
3553 ovbi = btv->cvbi;
3554 btv->curr = new;
3555 btv->cvbi = NULL;
3556 btv->loop_irq = 0;
3557 bttv_buffer_activate_video(btv, &new);
3558 bttv_buffer_activate_vbi(btv, NULL);
3559 bttv_set_dma(btv, 0);
3560
3561 /* wake up */
3562 bttv_irq_wakeup_video(btv, &old, &new, STATE_ERROR);
3563 bttv_irq_wakeup_vbi(btv, ovbi, STATE_ERROR);
3564
3565 /* cancel all outstanding capture / vbi requests */
3566 while (!list_empty(&btv->capture)) {
3567 item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
3568 list_del(&item->vb.queue);
3569 item->vb.state = STATE_ERROR;
3570 wake_up(&item->vb.done);
3571 }
3572 while (!list_empty(&btv->vcapture)) {
3573 item = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
3574 list_del(&item->vb.queue);
3575 item->vb.state = STATE_ERROR;
3576 wake_up(&item->vb.done);
3577 }
3578
3579 btv->errors++;
3580 spin_unlock_irqrestore(&btv->s_lock,flags);
3581}
3582
3583static void
3584bttv_irq_wakeup_top(struct bttv *btv)
3585{
3586 struct bttv_buffer *wakeup = btv->curr.top;
3587
3588 if (NULL == wakeup)
3589 return;
3590
3591 spin_lock(&btv->s_lock);
3592 btv->curr.top_irq = 0;
3593 btv->curr.top = NULL;
3594 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
3595
3596 do_gettimeofday(&wakeup->vb.ts);
3597 wakeup->vb.field_count = btv->field_count;
3598 wakeup->vb.state = STATE_DONE;
3599 wake_up(&wakeup->vb.done);
3600 spin_unlock(&btv->s_lock);
3601}
3602
3603static inline int is_active(struct btcx_riscmem *risc, u32 rc)
3604{
3605 if (rc < risc->dma)
3606 return 0;
3607 if (rc > risc->dma + risc->size)
3608 return 0;
3609 return 1;
3610}
3611
3612static void
3613bttv_irq_switch_video(struct bttv *btv)
3614{
3615 struct bttv_buffer_set new;
3616 struct bttv_buffer_set old;
3617 dma_addr_t rc;
3618
3619 spin_lock(&btv->s_lock);
3620
3621 /* new buffer set */
3622 bttv_irq_next_video(btv, &new);
3623 rc = btread(BT848_RISC_COUNT);
3624 if ((btv->curr.top && is_active(&btv->curr.top->top, rc)) ||
3625 (btv->curr.bottom && is_active(&btv->curr.bottom->bottom, rc))) {
3626 btv->framedrop++;
3627 if (debug_latency)
3628 bttv_irq_debug_low_latency(btv, rc);
3629 spin_unlock(&btv->s_lock);
3630 return;
3631 }
3632
3633 /* switch over */
3634 old = btv->curr;
3635 btv->curr = new;
3636 btv->loop_irq &= ~1;
3637 bttv_buffer_activate_video(btv, &new);
3638 bttv_set_dma(btv, 0);
3639
3640 /* switch input */
3641 if (UNSET != btv->new_input) {
3642 video_mux(btv,btv->new_input);
3643 btv->new_input = UNSET;
3644 }
3645
3646 /* wake up finished buffers */
3647 bttv_irq_wakeup_video(btv, &old, &new, STATE_DONE);
3648 spin_unlock(&btv->s_lock);
3649}
3650
3651static void
3652bttv_irq_switch_vbi(struct bttv *btv)
3653{
3654 struct bttv_buffer *new = NULL;
3655 struct bttv_buffer *old;
3656 u32 rc;
3657
3658 spin_lock(&btv->s_lock);
3659
3660 if (!list_empty(&btv->vcapture))
3661 new = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
3662 old = btv->cvbi;
3663
3664 rc = btread(BT848_RISC_COUNT);
3665 if (NULL != old && (is_active(&old->top, rc) ||
3666 is_active(&old->bottom, rc))) {
3667 btv->framedrop++;
3668 if (debug_latency)
3669 bttv_irq_debug_low_latency(btv, rc);
3670 spin_unlock(&btv->s_lock);
3671 return;
3672 }
3673
3674 /* switch */
3675 btv->cvbi = new;
3676 btv->loop_irq &= ~4;
3677 bttv_buffer_activate_vbi(btv, new);
3678 bttv_set_dma(btv, 0);
3679
3680 bttv_irq_wakeup_vbi(btv, old, STATE_DONE);
3681 spin_unlock(&btv->s_lock);
3682}
3683
3684static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
3685{
3686 u32 stat,astat;
3687 u32 dstat;
3688 int count;
3689 struct bttv *btv;
3690 int handled = 0;
3691
3692 btv=(struct bttv *)dev_id;
Mark Weaver6c6c0b22005-11-13 16:07:52 -08003693
3694 if (btv->any_irq)
3695 handled = bttv_any_irq(&btv->c);
3696
Linus Torvalds1da177e2005-04-16 15:20:36 -07003697 count=0;
3698 while (1) {
3699 /* get/clear interrupt status bits */
3700 stat=btread(BT848_INT_STAT);
3701 astat=stat&btread(BT848_INT_MASK);
3702 if (!astat)
3703 break;
3704 handled = 1;
3705 btwrite(stat,BT848_INT_STAT);
3706
3707 /* get device status bits */
3708 dstat=btread(BT848_DSTATUS);
3709
3710 if (irq_debug) {
3711 printk(KERN_DEBUG "bttv%d: irq loop=%d fc=%d "
3712 "riscs=%x, riscc=%08x, ",
3713 btv->c.nr, count, btv->field_count,
3714 stat>>28, btread(BT848_RISC_COUNT));
3715 bttv_print_irqbits(stat,astat);
3716 if (stat & BT848_INT_HLOCK)
3717 printk(" HLOC => %s", (dstat & BT848_DSTATUS_HLOC)
3718 ? "yes" : "no");
3719 if (stat & BT848_INT_VPRES)
3720 printk(" PRES => %s", (dstat & BT848_DSTATUS_PRES)
3721 ? "yes" : "no");
3722 if (stat & BT848_INT_FMTCHG)
3723 printk(" NUML => %s", (dstat & BT848_DSTATUS_NUML)
3724 ? "625" : "525");
3725 printk("\n");
3726 }
3727
3728 if (astat&BT848_INT_VSYNC)
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003729 btv->field_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003730
3731 if (astat & BT848_INT_GPINT) {
3732 wake_up(&btv->gpioq);
3733 bttv_gpio_irq(&btv->c);
3734 }
3735
3736 if (astat & BT848_INT_I2CDONE) {
3737 btv->i2c_done = stat;
3738 wake_up(&btv->i2c_queue);
3739 }
3740
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003741 if ((astat & BT848_INT_RISCI) && (stat & (4<<28)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003742 bttv_irq_switch_vbi(btv);
3743
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003744 if ((astat & BT848_INT_RISCI) && (stat & (2<<28)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003745 bttv_irq_wakeup_top(btv);
3746
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003747 if ((astat & BT848_INT_RISCI) && (stat & (1<<28)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003748 bttv_irq_switch_video(btv);
3749
3750 if ((astat & BT848_INT_HLOCK) && btv->opt_automute)
3751 audio_mux(btv, -1);
3752
3753 if (astat & (BT848_INT_SCERR|BT848_INT_OCERR)) {
3754 printk(KERN_INFO "bttv%d: %s%s @ %08x,",btv->c.nr,
3755 (astat & BT848_INT_SCERR) ? "SCERR" : "",
3756 (astat & BT848_INT_OCERR) ? "OCERR" : "",
3757 btread(BT848_RISC_COUNT));
3758 bttv_print_irqbits(stat,astat);
3759 printk("\n");
3760 if (bttv_debug)
3761 bttv_print_riscaddr(btv);
3762 }
3763 if (fdsr && astat & BT848_INT_FDSR) {
3764 printk(KERN_INFO "bttv%d: FDSR @ %08x\n",
3765 btv->c.nr,btread(BT848_RISC_COUNT));
3766 if (bttv_debug)
3767 bttv_print_riscaddr(btv);
3768 }
3769
3770 count++;
3771 if (count > 4) {
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08003772
3773 if (count > 8 || !(astat & BT848_INT_GPINT)) {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003774 btwrite(0, BT848_INT_MASK);
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08003775
3776 printk(KERN_ERR
3777 "bttv%d: IRQ lockup, cleared int mask [", btv->c.nr);
3778 } else {
3779 printk(KERN_ERR
3780 "bttv%d: IRQ lockup, clearing GPINT from int mask [", btv->c.nr);
3781
3782 btwrite(btread(BT848_INT_MASK) & (-1 ^ BT848_INT_GPINT),
3783 BT848_INT_MASK);
3784 };
3785
Linus Torvalds1da177e2005-04-16 15:20:36 -07003786 bttv_print_irqbits(stat,astat);
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08003787
Linus Torvalds1da177e2005-04-16 15:20:36 -07003788 printk("]\n");
3789 }
3790 }
3791 btv->irq_total++;
3792 if (handled)
3793 btv->irq_me++;
3794 return IRQ_RETVAL(handled);
3795}
3796
3797
3798/* ----------------------------------------------------------------------- */
3799/* initialitation */
3800
3801static struct video_device *vdev_init(struct bttv *btv,
3802 struct video_device *template,
3803 char *type)
3804{
3805 struct video_device *vfd;
3806
3807 vfd = video_device_alloc();
3808 if (NULL == vfd)
3809 return NULL;
3810 *vfd = *template;
3811 vfd->minor = -1;
3812 vfd->dev = &btv->c.pci->dev;
3813 vfd->release = video_device_release;
3814 snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
3815 btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "",
3816 type, bttv_tvcards[btv->c.type].name);
3817 return vfd;
3818}
3819
3820static void bttv_unregister_video(struct bttv *btv)
3821{
3822 if (btv->video_dev) {
3823 if (-1 != btv->video_dev->minor)
3824 video_unregister_device(btv->video_dev);
3825 else
3826 video_device_release(btv->video_dev);
3827 btv->video_dev = NULL;
3828 }
3829 if (btv->vbi_dev) {
3830 if (-1 != btv->vbi_dev->minor)
3831 video_unregister_device(btv->vbi_dev);
3832 else
3833 video_device_release(btv->vbi_dev);
3834 btv->vbi_dev = NULL;
3835 }
3836 if (btv->radio_dev) {
3837 if (-1 != btv->radio_dev->minor)
3838 video_unregister_device(btv->radio_dev);
3839 else
3840 video_device_release(btv->radio_dev);
3841 btv->radio_dev = NULL;
3842 }
3843}
3844
3845/* register video4linux devices */
3846static int __devinit bttv_register_video(struct bttv *btv)
3847{
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07003848 if (no_overlay <= 0) {
3849 bttv_video_template.type |= VID_TYPE_OVERLAY;
3850 } else {
3851 printk("bttv: Overlay support disabled.\n");
3852 }
3853
Linus Torvalds1da177e2005-04-16 15:20:36 -07003854 /* video */
3855 btv->video_dev = vdev_init(btv, &bttv_video_template, "video");
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003856 if (NULL == btv->video_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003857 goto err;
3858 if (video_register_device(btv->video_dev,VFL_TYPE_GRABBER,video_nr)<0)
3859 goto err;
3860 printk(KERN_INFO "bttv%d: registered device video%d\n",
3861 btv->c.nr,btv->video_dev->minor & 0x1f);
3862 video_device_create_file(btv->video_dev, &class_device_attr_card);
3863
3864 /* vbi */
3865 btv->vbi_dev = vdev_init(btv, &bttv_vbi_template, "vbi");
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003866 if (NULL == btv->vbi_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003867 goto err;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003868 if (video_register_device(btv->vbi_dev,VFL_TYPE_VBI,vbi_nr)<0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003869 goto err;
3870 printk(KERN_INFO "bttv%d: registered device vbi%d\n",
3871 btv->c.nr,btv->vbi_dev->minor & 0x1f);
3872
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003873 if (!btv->has_radio)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003874 return 0;
3875 /* radio */
3876 btv->radio_dev = vdev_init(btv, &radio_template, "radio");
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003877 if (NULL == btv->radio_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003878 goto err;
3879 if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,radio_nr)<0)
3880 goto err;
3881 printk(KERN_INFO "bttv%d: registered device radio%d\n",
3882 btv->c.nr,btv->radio_dev->minor & 0x1f);
3883
3884 /* all done */
3885 return 0;
3886
3887 err:
3888 bttv_unregister_video(btv);
3889 return -1;
3890}
3891
3892
3893/* on OpenFirmware machines (PowerMac at least), PCI memory cycle */
3894/* response on cards with no firmware is not enabled by OF */
3895static void pci_set_command(struct pci_dev *dev)
3896{
3897#if defined(__powerpc__)
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003898 unsigned int cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003899
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003900 pci_read_config_dword(dev, PCI_COMMAND, &cmd);
3901 cmd = (cmd | PCI_COMMAND_MEMORY );
3902 pci_write_config_dword(dev, PCI_COMMAND, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003903#endif
3904}
3905
3906static int __devinit bttv_probe(struct pci_dev *dev,
3907 const struct pci_device_id *pci_id)
3908{
3909 int result;
3910 unsigned char lat;
3911 struct bttv *btv;
3912
3913 if (bttv_num == BTTV_MAX)
3914 return -ENOMEM;
3915 printk(KERN_INFO "bttv: Bt8xx card found (%d).\n", bttv_num);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003916 btv=&bttvs[bttv_num];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003917 memset(btv,0,sizeof(*btv));
3918 btv->c.nr = bttv_num;
3919 sprintf(btv->c.name,"bttv%d",btv->c.nr);
3920
3921 /* initialize structs / fill in defaults */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003922 init_MUTEX(&btv->lock);
3923 init_MUTEX(&btv->reslock);
3924 spin_lock_init(&btv->s_lock);
3925 spin_lock_init(&btv->gpio_lock);
3926 init_waitqueue_head(&btv->gpioq);
3927 init_waitqueue_head(&btv->i2c_queue);
3928 INIT_LIST_HEAD(&btv->c.subs);
3929 INIT_LIST_HEAD(&btv->capture);
3930 INIT_LIST_HEAD(&btv->vcapture);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003931 v4l2_prio_init(&btv->prio);
3932
3933 init_timer(&btv->timeout);
3934 btv->timeout.function = bttv_irq_timeout;
3935 btv->timeout.data = (unsigned long)btv;
3936
Michael Krufky7c08fb02005-11-08 21:36:21 -08003937 btv->i2c_rc = -1;
3938 btv->tuner_type = UNSET;
3939 btv->pinnacle_id = UNSET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003940 btv->new_input = UNSET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003941 btv->has_radio=radio[btv->c.nr];
3942
3943 /* pci stuff (init, get irq/mmio, ... */
3944 btv->c.pci = dev;
Michael Krufky7c08fb02005-11-08 21:36:21 -08003945 btv->id = dev->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946 if (pci_enable_device(dev)) {
Michael Krufky7c08fb02005-11-08 21:36:21 -08003947 printk(KERN_WARNING "bttv%d: Can't enable device.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003948 btv->c.nr);
3949 return -EIO;
3950 }
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003951 if (pci_set_dma_mask(dev, DMA_32BIT_MASK)) {
3952 printk(KERN_WARNING "bttv%d: No suitable DMA available.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003953 btv->c.nr);
3954 return -EIO;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003955 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003956 if (!request_mem_region(pci_resource_start(dev,0),
3957 pci_resource_len(dev,0),
3958 btv->c.name)) {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003959 printk(KERN_WARNING "bttv%d: can't request iomem (0x%lx).\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003960 btv->c.nr, pci_resource_start(dev,0));
3961 return -EBUSY;
3962 }
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003963 pci_set_master(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003964 pci_set_command(dev);
3965 pci_set_drvdata(dev,btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003966
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003967 pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision);
3968 pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
3969 printk(KERN_INFO "bttv%d: Bt%d (rev %d) at %s, ",
3970 bttv_num,btv->id, btv->revision, pci_name(dev));
3971 printk("irq: %d, latency: %d, mmio: 0x%lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003972 btv->c.pci->irq, lat, pci_resource_start(dev,0));
3973 schedule();
3974
3975 btv->bt848_mmio=ioremap(pci_resource_start(dev,0), 0x1000);
3976 if (NULL == ioremap(pci_resource_start(dev,0), 0x1000)) {
3977 printk("bttv%d: ioremap() failed\n", btv->c.nr);
3978 result = -EIO;
3979 goto fail1;
3980 }
3981
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003982 /* identify card */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003983 bttv_idcard(btv);
3984
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003985 /* disable irqs, register irq handler */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003986 btwrite(0, BT848_INT_MASK);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003987 result = request_irq(btv->c.pci->irq, bttv_irq,
3988 SA_SHIRQ | SA_INTERRUPT,btv->c.name,(void *)btv);
3989 if (result < 0) {
3990 printk(KERN_ERR "bttv%d: can't get IRQ %d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003991 bttv_num,btv->c.pci->irq);
3992 goto fail1;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003993 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003994
3995 if (0 != bttv_handle_chipset(btv)) {
3996 result = -EIO;
3997 goto fail2;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003998 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003999
4000 /* init options from insmod args */
4001 btv->opt_combfilter = combfilter;
4002 btv->opt_lumafilter = lumafilter;
4003 btv->opt_automute = automute;
4004 btv->opt_chroma_agc = chroma_agc;
4005 btv->opt_adc_crush = adc_crush;
4006 btv->opt_vcr_hack = vcr_hack;
4007 btv->opt_whitecrush_upper = whitecrush_upper;
4008 btv->opt_whitecrush_lower = whitecrush_lower;
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -07004009 btv->opt_uv_ratio = uv_ratio;
4010 btv->opt_full_luma_range = full_luma_range;
4011 btv->opt_coring = coring;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004012
4013 /* fill struct bttv with some useful defaults */
4014 btv->init.btv = btv;
4015 btv->init.ov.w.width = 320;
4016 btv->init.ov.w.height = 240;
4017 btv->init.fmt = format_by_palette(VIDEO_PALETTE_RGB24);
4018 btv->init.width = 320;
4019 btv->init.height = 240;
4020 btv->init.lines = 16;
4021 btv->input = 0;
4022
4023 /* initialize hardware */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004024 if (bttv_gpio)
4025 bttv_gpio_tracking(btv,"pre-init");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004026
4027 bttv_risc_init_main(btv);
4028 init_bt848(btv);
4029
4030 /* gpio */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004031 btwrite(0x00, BT848_GPIO_REG_INP);
4032 btwrite(0x00, BT848_GPIO_OUT_EN);
4033 if (bttv_verbose)
4034 bttv_gpio_tracking(btv,"init");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004035
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004036 /* needs to be done before i2c is registered */
4037 bttv_init_card1(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004038
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004039 /* register i2c + gpio */
4040 init_bttv_i2c(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004041
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004042 /* some card-specific stuff (needs working i2c) */
4043 bttv_init_card2(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004044 init_irqreg(btv);
4045
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004046 /* register video4linux + input */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004047 if (!bttv_tvcards[btv->c.type].no_video) {
4048 bttv_register_video(btv);
4049 bt848_bright(btv,32768);
4050 bt848_contrast(btv,32768);
4051 bt848_hue(btv,32768);
4052 bt848_sat(btv,32768);
4053 audio_mux(btv,AUDIO_MUTE);
4054 set_input(btv,0);
4055 }
4056
4057 /* add subdevices */
4058 if (btv->has_remote)
4059 bttv_sub_add_device(&btv->c, "remote");
4060 if (bttv_tvcards[btv->c.type].has_dvb)
4061 bttv_sub_add_device(&btv->c, "dvb");
4062
4063 /* everything is fine */
4064 bttv_num++;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004065 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004066
4067 fail2:
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004068 free_irq(btv->c.pci->irq,btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069
4070 fail1:
4071 if (btv->bt848_mmio)
4072 iounmap(btv->bt848_mmio);
4073 release_mem_region(pci_resource_start(btv->c.pci,0),
4074 pci_resource_len(btv->c.pci,0));
4075 pci_set_drvdata(dev,NULL);
4076 return result;
4077}
4078
4079static void __devexit bttv_remove(struct pci_dev *pci_dev)
4080{
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004081 struct bttv *btv = pci_get_drvdata(pci_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004082
4083 if (bttv_verbose)
4084 printk("bttv%d: unloading\n",btv->c.nr);
4085
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004086 /* shutdown everything (DMA+IRQs) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087 btand(~15, BT848_GPIO_DMA_CTL);
4088 btwrite(0, BT848_INT_MASK);
4089 btwrite(~0x0, BT848_INT_STAT);
4090 btwrite(0x0, BT848_GPIO_OUT_EN);
4091 if (bttv_gpio)
4092 bttv_gpio_tracking(btv,"cleanup");
4093
4094 /* tell gpio modules we are leaving ... */
4095 btv->shutdown=1;
4096 wake_up(&btv->gpioq);
4097 bttv_sub_del_devices(&btv->c);
4098
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004099 /* unregister i2c_bus + input */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004100 fini_bttv_i2c(btv);
4101
4102 /* unregister video4linux */
4103 bttv_unregister_video(btv);
4104
4105 /* free allocated memory */
4106 btcx_riscmem_free(btv->c.pci,&btv->main);
4107
4108 /* free ressources */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004109 free_irq(btv->c.pci->irq,btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110 iounmap(btv->bt848_mmio);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004111 release_mem_region(pci_resource_start(btv->c.pci,0),
4112 pci_resource_len(btv->c.pci,0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004113
4114 pci_set_drvdata(pci_dev, NULL);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004115 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004116}
4117
4118static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state)
4119{
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004120 struct bttv *btv = pci_get_drvdata(pci_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004121 struct bttv_buffer_set idle;
4122 unsigned long flags;
4123
Mauro Carvalho Chehab0f97a932005-09-09 13:04:05 -07004124 dprintk("bttv%d: suspend %d\n", btv->c.nr, state.event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004125
4126 /* stop dma + irqs */
4127 spin_lock_irqsave(&btv->s_lock,flags);
4128 memset(&idle, 0, sizeof(idle));
4129 btv->state.video = btv->curr;
4130 btv->state.vbi = btv->cvbi;
4131 btv->state.loop_irq = btv->loop_irq;
4132 btv->curr = idle;
4133 btv->loop_irq = 0;
4134 bttv_buffer_activate_video(btv, &idle);
4135 bttv_buffer_activate_vbi(btv, NULL);
4136 bttv_set_dma(btv, 0);
4137 btwrite(0, BT848_INT_MASK);
4138 spin_unlock_irqrestore(&btv->s_lock,flags);
4139
4140 /* save bt878 state */
4141 btv->state.gpio_enable = btread(BT848_GPIO_OUT_EN);
4142 btv->state.gpio_data = gpio_read();
4143
4144 /* save pci state */
4145 pci_save_state(pci_dev);
4146 if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
4147 pci_disable_device(pci_dev);
4148 btv->state.disabled = 1;
4149 }
4150 return 0;
4151}
4152
4153static int bttv_resume(struct pci_dev *pci_dev)
4154{
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004155 struct bttv *btv = pci_get_drvdata(pci_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004156 unsigned long flags;
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004157 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004158
4159 dprintk("bttv%d: resume\n", btv->c.nr);
4160
4161 /* restore pci state */
4162 if (btv->state.disabled) {
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004163 err=pci_enable_device(pci_dev);
4164 if (err) {
4165 printk(KERN_WARNING "bttv%d: Can't enable device.\n",
4166 btv->c.nr);
4167 return err;
4168 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004169 btv->state.disabled = 0;
4170 }
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004171 err=pci_set_power_state(pci_dev, PCI_D0);
4172 if (err) {
4173 pci_disable_device(pci_dev);
4174 printk(KERN_WARNING "bttv%d: Can't enable device.\n",
4175 btv->c.nr);
4176 btv->state.disabled = 1;
4177 return err;
4178 }
4179
Linus Torvalds1da177e2005-04-16 15:20:36 -07004180 pci_restore_state(pci_dev);
4181
4182 /* restore bt878 state */
4183 bttv_reinit_bt848(btv);
4184 gpio_inout(0xffffff, btv->state.gpio_enable);
4185 gpio_write(btv->state.gpio_data);
4186
4187 /* restart dma */
4188 spin_lock_irqsave(&btv->s_lock,flags);
4189 btv->curr = btv->state.video;
4190 btv->cvbi = btv->state.vbi;
4191 btv->loop_irq = btv->state.loop_irq;
4192 bttv_buffer_activate_video(btv, &btv->curr);
4193 bttv_buffer_activate_vbi(btv, btv->cvbi);
4194 bttv_set_dma(btv, 0);
4195 spin_unlock_irqrestore(&btv->s_lock,flags);
4196 return 0;
4197}
4198
4199static struct pci_device_id bttv_pci_tbl[] = {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004200 {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848,
4201 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
Linus Torvalds1da177e2005-04-16 15:20:36 -07004202 {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849,
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004203 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
Linus Torvalds1da177e2005-04-16 15:20:36 -07004204 {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878,
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004205 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
Linus Torvalds1da177e2005-04-16 15:20:36 -07004206 {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879,
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004207 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
4208 {0,}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004209};
4210
4211MODULE_DEVICE_TABLE(pci, bttv_pci_tbl);
4212
4213static struct pci_driver bttv_pci_driver = {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004214 .name = "bttv",
4215 .id_table = bttv_pci_tbl,
4216 .probe = bttv_probe,
4217 .remove = __devexit_p(bttv_remove),
Linus Torvalds1da177e2005-04-16 15:20:36 -07004218 .suspend = bttv_suspend,
4219 .resume = bttv_resume,
4220};
4221
4222static int bttv_init_module(void)
4223{
4224 bttv_num = 0;
4225
4226 printk(KERN_INFO "bttv: driver version %d.%d.%d loaded\n",
4227 (BTTV_VERSION_CODE >> 16) & 0xff,
4228 (BTTV_VERSION_CODE >> 8) & 0xff,
4229 BTTV_VERSION_CODE & 0xff);
4230#ifdef SNAPSHOT
4231 printk(KERN_INFO "bttv: snapshot date %04d-%02d-%02d\n",
4232 SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
4233#endif
4234 if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME)
4235 gbuffers = 2;
4236 if (gbufsize < 0 || gbufsize > BTTV_MAX_FBUF)
4237 gbufsize = BTTV_MAX_FBUF;
4238 gbufsize = (gbufsize + PAGE_SIZE - 1) & PAGE_MASK;
4239 if (bttv_verbose)
4240 printk(KERN_INFO "bttv: using %d buffers with %dk (%d pages) each for capture\n",
4241 gbuffers, gbufsize >> 10, gbufsize >> PAGE_SHIFT);
4242
4243 bttv_check_chipset();
4244
4245 bus_register(&bttv_sub_bus_type);
4246 return pci_module_init(&bttv_pci_driver);
4247}
4248
4249static void bttv_cleanup_module(void)
4250{
4251 pci_unregister_driver(&bttv_pci_driver);
4252 bus_unregister(&bttv_sub_bus_type);
4253 return;
4254}
4255
4256module_init(bttv_init_module);
4257module_exit(bttv_cleanup_module);
4258
4259/*
4260 * Local variables:
4261 * c-basic-offset: 8
4262 * End:
4263 */