blob: 0005741d55141c0b1471cf8932845ac2e44990e9 [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 {
1856 bttv_call_i2c_clients(btv, VIDIOC_LOG_STATUS, 0);
1857 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
2032static int bttv_g_fmt(struct bttv_fh *fh, struct v4l2_format *f)
2033{
2034 switch (f->type) {
2035 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2036 memset(&f->fmt.pix,0,sizeof(struct v4l2_pix_format));
2037 f->fmt.pix.width = fh->width;
2038 f->fmt.pix.height = fh->height;
2039 f->fmt.pix.field = fh->cap.field;
2040 f->fmt.pix.pixelformat = fh->fmt->fourcc;
2041 f->fmt.pix.bytesperline =
2042 (f->fmt.pix.width * fh->fmt->depth) >> 3;
2043 f->fmt.pix.sizeimage =
2044 f->fmt.pix.height * f->fmt.pix.bytesperline;
2045 return 0;
2046 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
2047 memset(&f->fmt.win,0,sizeof(struct v4l2_window));
2048 f->fmt.win.w = fh->ov.w;
2049 f->fmt.win.field = fh->ov.field;
2050 return 0;
2051 case V4L2_BUF_TYPE_VBI_CAPTURE:
2052 bttv_vbi_get_fmt(fh,f);
2053 return 0;
2054 default:
2055 return -EINVAL;
2056 }
2057}
2058
2059static int bttv_try_fmt(struct bttv_fh *fh, struct bttv *btv,
2060 struct v4l2_format *f)
2061{
2062 switch (f->type) {
2063 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2064 {
2065 const struct bttv_format *fmt;
2066 enum v4l2_field field;
2067 unsigned int maxw,maxh;
2068
2069 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
2070 if (NULL == fmt)
2071 return -EINVAL;
2072
2073 /* fixup format */
2074 maxw = bttv_tvnorms[btv->tvnorm].swidth;
2075 maxh = bttv_tvnorms[btv->tvnorm].sheight;
2076 field = f->fmt.pix.field;
2077 if (V4L2_FIELD_ANY == field)
2078 field = (f->fmt.pix.height > maxh/2)
2079 ? V4L2_FIELD_INTERLACED
2080 : V4L2_FIELD_BOTTOM;
2081 if (V4L2_FIELD_SEQ_BT == field)
2082 field = V4L2_FIELD_SEQ_TB;
2083 switch (field) {
2084 case V4L2_FIELD_TOP:
2085 case V4L2_FIELD_BOTTOM:
2086 case V4L2_FIELD_ALTERNATE:
2087 maxh = maxh/2;
2088 break;
2089 case V4L2_FIELD_INTERLACED:
2090 break;
2091 case V4L2_FIELD_SEQ_TB:
2092 if (fmt->flags & FORMAT_FLAGS_PLANAR)
2093 return -EINVAL;
2094 break;
2095 default:
2096 return -EINVAL;
2097 }
2098
2099 /* update data for the application */
2100 f->fmt.pix.field = field;
2101 if (f->fmt.pix.width < 48)
2102 f->fmt.pix.width = 48;
2103 if (f->fmt.pix.height < 32)
2104 f->fmt.pix.height = 32;
2105 if (f->fmt.pix.width > maxw)
2106 f->fmt.pix.width = maxw;
2107 if (f->fmt.pix.height > maxh)
2108 f->fmt.pix.height = maxh;
2109 f->fmt.pix.width &= ~0x03;
2110 f->fmt.pix.bytesperline =
2111 (f->fmt.pix.width * fmt->depth) >> 3;
2112 f->fmt.pix.sizeimage =
2113 f->fmt.pix.height * f->fmt.pix.bytesperline;
2114
2115 return 0;
2116 }
2117 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
2118 return verify_window(&bttv_tvnorms[btv->tvnorm],
2119 &f->fmt.win, 1);
2120 case V4L2_BUF_TYPE_VBI_CAPTURE:
2121 bttv_vbi_try_fmt(fh,f);
2122 return 0;
2123 default:
2124 return -EINVAL;
2125 }
2126}
2127
2128static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv,
2129 struct v4l2_format *f)
2130{
2131 int retval;
2132
2133 switch (f->type) {
2134 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2135 {
2136 const struct bttv_format *fmt;
2137
2138 retval = bttv_switch_type(fh,f->type);
2139 if (0 != retval)
2140 return retval;
2141 retval = bttv_try_fmt(fh,btv,f);
2142 if (0 != retval)
2143 return retval;
2144 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
2145
2146 /* update our state informations */
2147 down(&fh->cap.lock);
2148 fh->fmt = fmt;
2149 fh->cap.field = f->fmt.pix.field;
2150 fh->cap.last = V4L2_FIELD_NONE;
2151 fh->width = f->fmt.pix.width;
2152 fh->height = f->fmt.pix.height;
2153 btv->init.fmt = fmt;
2154 btv->init.width = f->fmt.pix.width;
2155 btv->init.height = f->fmt.pix.height;
2156 up(&fh->cap.lock);
2157
2158 return 0;
2159 }
2160 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07002161 if (no_overlay > 0) {
2162 printk ("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
2163 return -EINVAL;
2164 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002165 return setup_window(fh, btv, &f->fmt.win, 1);
2166 case V4L2_BUF_TYPE_VBI_CAPTURE:
2167 retval = bttv_switch_type(fh,f->type);
2168 if (0 != retval)
2169 return retval;
2170 if (locked_btres(fh->btv, RESOURCE_VBI))
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08002171 return -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172 bttv_vbi_try_fmt(fh,f);
2173 bttv_vbi_setlines(fh,btv,f->fmt.vbi.count[0]);
2174 bttv_vbi_get_fmt(fh,f);
2175 return 0;
2176 default:
2177 return -EINVAL;
2178 }
2179}
2180
2181static int bttv_do_ioctl(struct inode *inode, struct file *file,
2182 unsigned int cmd, void *arg)
2183{
2184 struct bttv_fh *fh = file->private_data;
2185 struct bttv *btv = fh->btv;
2186 unsigned long flags;
2187 int retval = 0;
2188
2189 if (bttv_debug > 1) {
2190 switch (_IOC_TYPE(cmd)) {
2191 case 'v':
2192 printk("bttv%d: ioctl 0x%x (v4l1, VIDIOC%s)\n",
2193 btv->c.nr, cmd, (_IOC_NR(cmd) < V4L1_IOCTLS) ?
2194 v4l1_ioctls[_IOC_NR(cmd)] : "???");
2195 break;
2196 case 'V':
2197 printk("bttv%d: ioctl 0x%x (v4l2, %s)\n",
2198 btv->c.nr, cmd, v4l2_ioctl_names[_IOC_NR(cmd)]);
2199 break;
2200 default:
2201 printk("bttv%d: ioctl 0x%x (???)\n",
2202 btv->c.nr, cmd);
2203 }
2204 }
2205 if (btv->errors)
2206 bttv_reinit_bt848(btv);
2207
2208 switch (cmd) {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08002209 case VIDIOCSFREQ:
2210 case VIDIOCSTUNER:
2211 case VIDIOCSCHAN:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002212 case VIDIOC_S_CTRL:
2213 case VIDIOC_S_STD:
2214 case VIDIOC_S_INPUT:
2215 case VIDIOC_S_TUNER:
2216 case VIDIOC_S_FREQUENCY:
2217 retval = v4l2_prio_check(&btv->prio,&fh->prio);
2218 if (0 != retval)
2219 return retval;
2220 };
2221
2222 switch (cmd) {
2223
2224 /* *** v4l1 *** ************************************************ */
2225 case VIDIOCGCAP:
2226 {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08002227 struct video_capability *cap = arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002228
2229 memset(cap,0,sizeof(*cap));
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08002230 strcpy(cap->name,btv->video_dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002231 if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
2232 /* vbi */
2233 cap->type = VID_TYPE_TUNER|VID_TYPE_TELETEXT;
2234 } else {
2235 /* others */
2236 cap->type = VID_TYPE_CAPTURE|
2237 VID_TYPE_TUNER|
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238 VID_TYPE_CLIPPING|
2239 VID_TYPE_SCALES;
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07002240 if (no_overlay <= 0)
2241 cap->type |= VID_TYPE_OVERLAY;
2242
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243 cap->maxwidth = bttv_tvnorms[btv->tvnorm].swidth;
2244 cap->maxheight = bttv_tvnorms[btv->tvnorm].sheight;
2245 cap->minwidth = 48;
2246 cap->minheight = 32;
2247 }
2248 cap->channels = bttv_tvcards[btv->c.type].video_inputs;
2249 cap->audios = bttv_tvcards[btv->c.type].audio_inputs;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08002250 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251 }
2252
2253 case VIDIOCGPICT:
2254 {
2255 struct video_picture *pic = arg;
2256
2257 memset(pic,0,sizeof(*pic));
2258 pic->brightness = btv->bright;
2259 pic->contrast = btv->contrast;
2260 pic->hue = btv->hue;
2261 pic->colour = btv->saturation;
2262 if (fh->fmt) {
2263 pic->depth = fh->fmt->depth;
2264 pic->palette = fh->fmt->palette;
2265 }
2266 return 0;
2267 }
2268 case VIDIOCSPICT:
2269 {
2270 struct video_picture *pic = arg;
2271 const struct bttv_format *fmt;
2272
2273 fmt = format_by_palette(pic->palette);
2274 if (NULL == fmt)
2275 return -EINVAL;
2276 down(&fh->cap.lock);
2277 if (fmt->depth != pic->depth) {
2278 retval = -EINVAL;
2279 goto fh_unlock_and_return;
2280 }
2281 fh->ovfmt = fmt;
2282 fh->fmt = fmt;
2283 btv->init.ovfmt = fmt;
2284 btv->init.fmt = fmt;
2285 if (bigendian) {
2286 /* dirty hack time: swap bytes for overlay if the
2287 display adaptor is big endian (insmod option) */
2288 if (fmt->palette == VIDEO_PALETTE_RGB555 ||
2289 fmt->palette == VIDEO_PALETTE_RGB565 ||
2290 fmt->palette == VIDEO_PALETTE_RGB32) {
2291 fh->ovfmt = fmt+1;
2292 }
2293 }
2294 bt848_bright(btv,pic->brightness);
2295 bt848_contrast(btv,pic->contrast);
2296 bt848_hue(btv,pic->hue);
2297 bt848_sat(btv,pic->colour);
2298 up(&fh->cap.lock);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08002299 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300 }
2301
2302 case VIDIOCGWIN:
2303 {
2304 struct video_window *win = arg;
2305
2306 memset(win,0,sizeof(*win));
2307 win->x = fh->ov.w.left;
2308 win->y = fh->ov.w.top;
2309 win->width = fh->ov.w.width;
2310 win->height = fh->ov.w.height;
2311 return 0;
2312 }
2313 case VIDIOCSWIN:
2314 {
2315 struct video_window *win = arg;
2316 struct v4l2_window w2;
2317
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07002318 if (no_overlay > 0) {
2319 printk ("VIDIOCSWIN: no_overlay\n");
2320 return -EINVAL;
2321 }
2322
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323 w2.field = V4L2_FIELD_ANY;
2324 w2.w.left = win->x;
2325 w2.w.top = win->y;
2326 w2.w.width = win->width;
2327 w2.w.height = win->height;
2328 w2.clipcount = win->clipcount;
2329 w2.clips = (struct v4l2_clip __user *)win->clips;
2330 retval = setup_window(fh, btv, &w2, 0);
2331 if (0 == retval) {
2332 /* on v4l1 this ioctl affects the read() size too */
2333 fh->width = fh->ov.w.width;
2334 fh->height = fh->ov.w.height;
2335 btv->init.width = fh->ov.w.width;
2336 btv->init.height = fh->ov.w.height;
2337 }
2338 return retval;
2339 }
2340
2341 case VIDIOCGFBUF:
2342 {
2343 struct video_buffer *fbuf = arg;
2344
2345 fbuf->base = btv->fbuf.base;
2346 fbuf->width = btv->fbuf.fmt.width;
2347 fbuf->height = btv->fbuf.fmt.height;
2348 fbuf->bytesperline = btv->fbuf.fmt.bytesperline;
2349 if (fh->ovfmt)
2350 fbuf->depth = fh->ovfmt->depth;
2351 return 0;
2352 }
2353 case VIDIOCSFBUF:
2354 {
2355 struct video_buffer *fbuf = arg;
2356 const struct bttv_format *fmt;
2357 unsigned long end;
2358
2359 if(!capable(CAP_SYS_ADMIN) &&
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08002360 !capable(CAP_SYS_RAWIO))
2361 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362 end = (unsigned long)fbuf->base +
2363 fbuf->height * fbuf->bytesperline;
2364 down(&fh->cap.lock);
2365 retval = -EINVAL;
2366
2367 switch (fbuf->depth) {
2368 case 8:
2369 fmt = format_by_palette(VIDEO_PALETTE_HI240);
2370 break;
2371 case 16:
2372 fmt = format_by_palette(VIDEO_PALETTE_RGB565);
2373 break;
2374 case 24:
2375 fmt = format_by_palette(VIDEO_PALETTE_RGB24);
2376 break;
2377 case 32:
2378 fmt = format_by_palette(VIDEO_PALETTE_RGB32);
2379 break;
2380 case 15:
2381 fbuf->depth = 16;
2382 fmt = format_by_palette(VIDEO_PALETTE_RGB555);
2383 break;
2384 default:
2385 fmt = NULL;
2386 break;
2387 }
2388 if (NULL == fmt)
2389 goto fh_unlock_and_return;
2390
2391 fh->ovfmt = fmt;
2392 fh->fmt = fmt;
2393 btv->init.ovfmt = fmt;
2394 btv->init.fmt = fmt;
2395 btv->fbuf.base = fbuf->base;
2396 btv->fbuf.fmt.width = fbuf->width;
2397 btv->fbuf.fmt.height = fbuf->height;
2398 if (fbuf->bytesperline)
2399 btv->fbuf.fmt.bytesperline = fbuf->bytesperline;
2400 else
2401 btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fbuf->depth/8;
2402 up(&fh->cap.lock);
2403 return 0;
2404 }
2405
2406 case VIDIOCCAPTURE:
2407 case VIDIOC_OVERLAY:
2408 {
2409 struct bttv_buffer *new;
2410 int *on = arg;
2411
2412 if (*on) {
2413 /* verify args */
2414 if (NULL == btv->fbuf.base)
2415 return -EINVAL;
2416 if (!fh->ov.setup_ok) {
2417 dprintk("bttv%d: overlay: !setup_ok\n",btv->c.nr);
2418 return -EINVAL;
2419 }
2420 }
2421
2422 if (!check_alloc_btres(btv,fh,RESOURCE_OVERLAY))
2423 return -EBUSY;
2424
2425 down(&fh->cap.lock);
2426 if (*on) {
2427 fh->ov.tvnorm = btv->tvnorm;
2428 new = videobuf_alloc(sizeof(*new));
2429 bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
2430 } else {
2431 new = NULL;
2432 }
2433
2434 /* switch over */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08002435 retval = bttv_switch_overlay(btv,fh,new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436 up(&fh->cap.lock);
2437 return retval;
2438 }
2439
2440 case VIDIOCGMBUF:
2441 {
2442 struct video_mbuf *mbuf = arg;
2443 unsigned int i;
2444
2445 down(&fh->cap.lock);
2446 retval = videobuf_mmap_setup(&fh->cap,gbuffers,gbufsize,
2447 V4L2_MEMORY_MMAP);
2448 if (retval < 0)
2449 goto fh_unlock_and_return;
2450 memset(mbuf,0,sizeof(*mbuf));
2451 mbuf->frames = gbuffers;
2452 mbuf->size = gbuffers * gbufsize;
2453 for (i = 0; i < gbuffers; i++)
2454 mbuf->offsets[i] = i * gbufsize;
2455 up(&fh->cap.lock);
2456 return 0;
2457 }
2458 case VIDIOCMCAPTURE:
2459 {
2460 struct video_mmap *vm = arg;
2461 struct bttv_buffer *buf;
2462 enum v4l2_field field;
2463
2464 if (vm->frame >= VIDEO_MAX_FRAME)
2465 return -EINVAL;
2466
2467 down(&fh->cap.lock);
2468 retval = -EINVAL;
2469 buf = (struct bttv_buffer *)fh->cap.bufs[vm->frame];
2470 if (NULL == buf)
2471 goto fh_unlock_and_return;
2472 if (0 == buf->vb.baddr)
2473 goto fh_unlock_and_return;
2474 if (buf->vb.state == STATE_QUEUED ||
2475 buf->vb.state == STATE_ACTIVE)
2476 goto fh_unlock_and_return;
2477
2478 field = (vm->height > bttv_tvnorms[btv->tvnorm].sheight/2)
2479 ? V4L2_FIELD_INTERLACED
2480 : V4L2_FIELD_BOTTOM;
2481 retval = bttv_prepare_buffer(btv,buf,
2482 format_by_palette(vm->format),
2483 vm->width,vm->height,field);
2484 if (0 != retval)
2485 goto fh_unlock_and_return;
2486 spin_lock_irqsave(&btv->s_lock,flags);
2487 buffer_queue(&fh->cap,&buf->vb);
2488 spin_unlock_irqrestore(&btv->s_lock,flags);
2489 up(&fh->cap.lock);
2490 return 0;
2491 }
2492 case VIDIOCSYNC:
2493 {
2494 int *frame = arg;
2495 struct bttv_buffer *buf;
2496
2497 if (*frame >= VIDEO_MAX_FRAME)
2498 return -EINVAL;
2499
2500 down(&fh->cap.lock);
2501 retval = -EINVAL;
2502 buf = (struct bttv_buffer *)fh->cap.bufs[*frame];
2503 if (NULL == buf)
2504 goto fh_unlock_and_return;
2505 retval = videobuf_waiton(&buf->vb,0,1);
2506 if (0 != retval)
2507 goto fh_unlock_and_return;
2508 switch (buf->vb.state) {
2509 case STATE_ERROR:
2510 retval = -EIO;
2511 /* fall through */
2512 case STATE_DONE:
2513 videobuf_dma_pci_sync(btv->c.pci,&buf->vb.dma);
2514 bttv_dma_free(btv,buf);
2515 break;
2516 default:
2517 retval = -EINVAL;
2518 break;
2519 }
2520 up(&fh->cap.lock);
2521 return retval;
2522 }
2523
2524 case VIDIOCGVBIFMT:
2525 {
2526 struct vbi_format *fmt = (void *) arg;
2527 struct v4l2_format fmt2;
2528
2529 if (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE) {
2530 retval = bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE);
2531 if (0 != retval)
2532 return retval;
2533 }
2534 bttv_vbi_get_fmt(fh, &fmt2);
2535
2536 memset(fmt,0,sizeof(*fmt));
2537 fmt->sampling_rate = fmt2.fmt.vbi.sampling_rate;
2538 fmt->samples_per_line = fmt2.fmt.vbi.samples_per_line;
2539 fmt->sample_format = VIDEO_PALETTE_RAW;
2540 fmt->start[0] = fmt2.fmt.vbi.start[0];
2541 fmt->count[0] = fmt2.fmt.vbi.count[0];
2542 fmt->start[1] = fmt2.fmt.vbi.start[1];
2543 fmt->count[1] = fmt2.fmt.vbi.count[1];
2544 if (fmt2.fmt.vbi.flags & VBI_UNSYNC)
2545 fmt->flags |= V4L2_VBI_UNSYNC;
2546 if (fmt2.fmt.vbi.flags & VBI_INTERLACED)
2547 fmt->flags |= V4L2_VBI_INTERLACED;
2548 return 0;
2549 }
2550 case VIDIOCSVBIFMT:
2551 {
2552 struct vbi_format *fmt = (void *) arg;
2553 struct v4l2_format fmt2;
2554
2555 retval = bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE);
2556 if (0 != retval)
2557 return retval;
2558 bttv_vbi_get_fmt(fh, &fmt2);
2559
2560 if (fmt->sampling_rate != fmt2.fmt.vbi.sampling_rate ||
2561 fmt->samples_per_line != fmt2.fmt.vbi.samples_per_line ||
2562 fmt->sample_format != VIDEO_PALETTE_RAW ||
2563 fmt->start[0] != fmt2.fmt.vbi.start[0] ||
2564 fmt->start[1] != fmt2.fmt.vbi.start[1] ||
2565 fmt->count[0] != fmt->count[1] ||
2566 fmt->count[0] < 1 ||
2567 fmt->count[0] > 32 /* VBI_MAXLINES */)
2568 return -EINVAL;
2569
2570 bttv_vbi_setlines(fh,btv,fmt->count[0]);
2571 return 0;
2572 }
2573
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08002574 case BTTV_VERSION:
2575 case VIDIOCGFREQ:
2576 case VIDIOCSFREQ:
2577 case VIDIOCGTUNER:
2578 case VIDIOCSTUNER:
2579 case VIDIOCGCHAN:
2580 case VIDIOCSCHAN:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002581 case VIDIOCGAUDIO:
2582 case VIDIOCSAUDIO:
2583 return bttv_common_ioctls(btv,cmd,arg);
2584
2585 /* *** v4l2 *** ************************************************ */
2586 case VIDIOC_QUERYCAP:
2587 {
2588 struct v4l2_capability *cap = arg;
2589
2590 if (0 == v4l2)
2591 return -EINVAL;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08002592 strcpy(cap->driver,"bttv");
2593 strlcpy(cap->card,btv->video_dev->name,sizeof(cap->card));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594 sprintf(cap->bus_info,"PCI:%s",pci_name(btv->c.pci));
2595 cap->version = BTTV_VERSION_CODE;
2596 cap->capabilities =
2597 V4L2_CAP_VIDEO_CAPTURE |
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598 V4L2_CAP_VBI_CAPTURE |
2599 V4L2_CAP_READWRITE |
2600 V4L2_CAP_STREAMING;
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07002601 if (no_overlay <= 0)
2602 cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
2603
Linus Torvalds1da177e2005-04-16 15:20:36 -07002604 if (bttv_tvcards[btv->c.type].tuner != UNSET &&
2605 bttv_tvcards[btv->c.type].tuner != TUNER_ABSENT)
2606 cap->capabilities |= V4L2_CAP_TUNER;
2607 return 0;
2608 }
2609
2610 case VIDIOC_ENUM_FMT:
2611 {
2612 struct v4l2_fmtdesc *f = arg;
2613 enum v4l2_buf_type type;
2614 unsigned int i;
2615 int index;
2616
2617 type = f->type;
2618 if (V4L2_BUF_TYPE_VBI_CAPTURE == type) {
2619 /* vbi */
2620 index = f->index;
2621 if (0 != index)
2622 return -EINVAL;
2623 memset(f,0,sizeof(*f));
2624 f->index = index;
2625 f->type = type;
2626 f->pixelformat = V4L2_PIX_FMT_GREY;
2627 strcpy(f->description,"vbi data");
2628 return 0;
2629 }
2630
2631 /* video capture + overlay */
2632 index = -1;
2633 for (i = 0; i < BTTV_FORMATS; i++) {
2634 if (bttv_formats[i].fourcc != -1)
2635 index++;
2636 if ((unsigned int)index == f->index)
2637 break;
2638 }
2639 if (BTTV_FORMATS == i)
2640 return -EINVAL;
2641
2642 switch (f->type) {
2643 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2644 break;
2645 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
2646 if (!(bttv_formats[i].flags & FORMAT_FLAGS_PACKED))
2647 return -EINVAL;
2648 break;
2649 default:
2650 return -EINVAL;
2651 }
2652 memset(f,0,sizeof(*f));
2653 f->index = index;
2654 f->type = type;
2655 f->pixelformat = bttv_formats[i].fourcc;
2656 strlcpy(f->description,bttv_formats[i].name,sizeof(f->description));
2657 return 0;
2658 }
2659
2660 case VIDIOC_TRY_FMT:
2661 {
2662 struct v4l2_format *f = arg;
2663 return bttv_try_fmt(fh,btv,f);
2664 }
2665 case VIDIOC_G_FMT:
2666 {
2667 struct v4l2_format *f = arg;
2668 return bttv_g_fmt(fh,f);
2669 }
2670 case VIDIOC_S_FMT:
2671 {
2672 struct v4l2_format *f = arg;
2673 return bttv_s_fmt(fh,btv,f);
2674 }
2675
2676 case VIDIOC_G_FBUF:
2677 {
2678 struct v4l2_framebuffer *fb = arg;
2679
2680 *fb = btv->fbuf;
2681 fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
2682 if (fh->ovfmt)
2683 fb->fmt.pixelformat = fh->ovfmt->fourcc;
2684 return 0;
2685 }
2686 case VIDIOC_S_FBUF:
2687 {
2688 struct v4l2_framebuffer *fb = arg;
2689 const struct bttv_format *fmt;
2690
2691 if(!capable(CAP_SYS_ADMIN) &&
2692 !capable(CAP_SYS_RAWIO))
2693 return -EPERM;
2694
2695 /* check args */
2696 fmt = format_by_fourcc(fb->fmt.pixelformat);
2697 if (NULL == fmt)
2698 return -EINVAL;
2699 if (0 == (fmt->flags & FORMAT_FLAGS_PACKED))
2700 return -EINVAL;
2701
2702 down(&fh->cap.lock);
2703 retval = -EINVAL;
2704 if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
2705 if (fb->fmt.width > bttv_tvnorms[btv->tvnorm].swidth)
2706 goto fh_unlock_and_return;
2707 if (fb->fmt.height > bttv_tvnorms[btv->tvnorm].sheight)
2708 goto fh_unlock_and_return;
2709 }
2710
2711 /* ok, accept it */
2712 btv->fbuf.base = fb->base;
2713 btv->fbuf.fmt.width = fb->fmt.width;
2714 btv->fbuf.fmt.height = fb->fmt.height;
2715 if (0 != fb->fmt.bytesperline)
2716 btv->fbuf.fmt.bytesperline = fb->fmt.bytesperline;
2717 else
2718 btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fmt->depth/8;
2719
2720 retval = 0;
2721 fh->ovfmt = fmt;
2722 btv->init.ovfmt = fmt;
2723 if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
2724 fh->ov.w.left = 0;
2725 fh->ov.w.top = 0;
2726 fh->ov.w.width = fb->fmt.width;
2727 fh->ov.w.height = fb->fmt.height;
2728 btv->init.ov.w.width = fb->fmt.width;
2729 btv->init.ov.w.height = fb->fmt.height;
Jesper Juhl2ea75332005-11-07 01:01:31 -08002730 kfree(fh->ov.clips);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731 fh->ov.clips = NULL;
2732 fh->ov.nclips = 0;
2733
2734 if (check_btres(fh, RESOURCE_OVERLAY)) {
2735 struct bttv_buffer *new;
2736
2737 new = videobuf_alloc(sizeof(*new));
2738 bttv_overlay_risc(btv,&fh->ov,fh->ovfmt,new);
2739 retval = bttv_switch_overlay(btv,fh,new);
2740 }
2741 }
2742 up(&fh->cap.lock);
2743 return retval;
2744 }
2745
2746 case VIDIOC_REQBUFS:
2747 return videobuf_reqbufs(bttv_queue(fh),arg);
2748
2749 case VIDIOC_QUERYBUF:
2750 return videobuf_querybuf(bttv_queue(fh),arg);
2751
2752 case VIDIOC_QBUF:
2753 return videobuf_qbuf(bttv_queue(fh),arg);
2754
2755 case VIDIOC_DQBUF:
2756 return videobuf_dqbuf(bttv_queue(fh),arg,
2757 file->f_flags & O_NONBLOCK);
2758
2759 case VIDIOC_STREAMON:
2760 {
2761 int res = bttv_resource(fh);
2762
2763 if (!check_alloc_btres(btv,fh,res))
2764 return -EBUSY;
2765 return videobuf_streamon(bttv_queue(fh));
2766 }
2767 case VIDIOC_STREAMOFF:
2768 {
2769 int res = bttv_resource(fh);
2770
2771 retval = videobuf_streamoff(bttv_queue(fh));
2772 if (retval < 0)
2773 return retval;
2774 free_btres(btv,fh,res);
2775 return 0;
2776 }
2777
2778 case VIDIOC_QUERYCTRL:
2779 {
2780 struct v4l2_queryctrl *c = arg;
2781 int i;
2782
2783 if ((c->id < V4L2_CID_BASE ||
2784 c->id >= V4L2_CID_LASTP1) &&
2785 (c->id < V4L2_CID_PRIVATE_BASE ||
2786 c->id >= V4L2_CID_PRIVATE_LASTP1))
2787 return -EINVAL;
2788 for (i = 0; i < BTTV_CTLS; i++)
2789 if (bttv_ctls[i].id == c->id)
2790 break;
2791 if (i == BTTV_CTLS) {
2792 *c = no_ctl;
2793 return 0;
2794 }
2795 *c = bttv_ctls[i];
2796 if (i >= 4 && i <= 8) {
2797 struct video_audio va;
2798 memset(&va,0,sizeof(va));
2799 bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
2800 if (btv->audio_hook)
2801 btv->audio_hook(btv,&va,0);
2802 switch (bttv_ctls[i].id) {
2803 case V4L2_CID_AUDIO_VOLUME:
2804 if (!(va.flags & VIDEO_AUDIO_VOLUME))
2805 *c = no_ctl;
2806 break;
2807 case V4L2_CID_AUDIO_BALANCE:
2808 if (!(va.flags & VIDEO_AUDIO_BALANCE))
2809 *c = no_ctl;
2810 break;
2811 case V4L2_CID_AUDIO_BASS:
2812 if (!(va.flags & VIDEO_AUDIO_BASS))
2813 *c = no_ctl;
2814 break;
2815 case V4L2_CID_AUDIO_TREBLE:
2816 if (!(va.flags & VIDEO_AUDIO_TREBLE))
2817 *c = no_ctl;
2818 break;
2819 }
2820 }
2821 return 0;
2822 }
2823 case VIDIOC_G_CTRL:
2824 return get_control(btv,arg);
2825 case VIDIOC_S_CTRL:
2826 return set_control(btv,arg);
2827 case VIDIOC_G_PARM:
2828 {
2829 struct v4l2_streamparm *parm = arg;
2830 struct v4l2_standard s;
2831 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
2832 return -EINVAL;
2833 memset(parm,0,sizeof(*parm));
2834 v4l2_video_std_construct(&s, bttv_tvnorms[btv->tvnorm].v4l2_id,
2835 bttv_tvnorms[btv->tvnorm].name);
2836 parm->parm.capture.timeperframe = s.frameperiod;
2837 return 0;
2838 }
2839
2840 case VIDIOC_G_PRIORITY:
2841 {
2842 enum v4l2_priority *p = arg;
2843
2844 *p = v4l2_prio_max(&btv->prio);
2845 return 0;
2846 }
2847 case VIDIOC_S_PRIORITY:
2848 {
2849 enum v4l2_priority *prio = arg;
2850
2851 return v4l2_prio_change(&btv->prio, &fh->prio, *prio);
2852 }
2853
2854 case VIDIOC_ENUMSTD:
2855 case VIDIOC_G_STD:
2856 case VIDIOC_S_STD:
2857 case VIDIOC_ENUMINPUT:
2858 case VIDIOC_G_INPUT:
2859 case VIDIOC_S_INPUT:
2860 case VIDIOC_G_TUNER:
2861 case VIDIOC_S_TUNER:
2862 case VIDIOC_G_FREQUENCY:
2863 case VIDIOC_S_FREQUENCY:
Hans Verkuil299392b2005-11-08 21:37:42 -08002864 case VIDIOC_LOG_STATUS:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002865 return bttv_common_ioctls(btv,cmd,arg);
2866
2867 default:
2868 return -ENOIOCTLCMD;
2869 }
2870 return 0;
2871
2872 fh_unlock_and_return:
2873 up(&fh->cap.lock);
2874 return retval;
2875}
2876
2877static int bttv_ioctl(struct inode *inode, struct file *file,
2878 unsigned int cmd, unsigned long arg)
2879{
2880 struct bttv_fh *fh = file->private_data;
2881
2882 switch (cmd) {
2883 case BTTV_VBISIZE:
2884 bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE);
2885 return fh->lines * 2 * 2048;
2886 default:
2887 return video_usercopy(inode, file, cmd, arg, bttv_do_ioctl);
2888 }
2889}
2890
2891static ssize_t bttv_read(struct file *file, char __user *data,
2892 size_t count, loff_t *ppos)
2893{
2894 struct bttv_fh *fh = file->private_data;
2895 int retval = 0;
2896
2897 if (fh->btv->errors)
2898 bttv_reinit_bt848(fh->btv);
2899 dprintk("bttv%d: read count=%d type=%s\n",
2900 fh->btv->c.nr,(int)count,v4l2_type_names[fh->type]);
2901
2902 switch (fh->type) {
2903 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2904 if (locked_btres(fh->btv,RESOURCE_VIDEO))
2905 return -EBUSY;
2906 retval = videobuf_read_one(&fh->cap, data, count, ppos,
2907 file->f_flags & O_NONBLOCK);
2908 break;
2909 case V4L2_BUF_TYPE_VBI_CAPTURE:
2910 if (!check_alloc_btres(fh->btv,fh,RESOURCE_VBI))
2911 return -EBUSY;
2912 retval = videobuf_read_stream(&fh->vbi, data, count, ppos, 1,
2913 file->f_flags & O_NONBLOCK);
2914 break;
2915 default:
2916 BUG();
2917 }
2918 return retval;
2919}
2920
2921static unsigned int bttv_poll(struct file *file, poll_table *wait)
2922{
2923 struct bttv_fh *fh = file->private_data;
2924 struct bttv_buffer *buf;
2925 enum v4l2_field field;
2926
2927 if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
2928 if (!check_alloc_btres(fh->btv,fh,RESOURCE_VBI))
2929 return POLLERR;
2930 return videobuf_poll_stream(file, &fh->vbi, wait);
2931 }
2932
2933 if (check_btres(fh,RESOURCE_VIDEO)) {
2934 /* streaming capture */
2935 if (list_empty(&fh->cap.stream))
2936 return POLLERR;
2937 buf = list_entry(fh->cap.stream.next,struct bttv_buffer,vb.stream);
2938 } else {
2939 /* read() capture */
2940 down(&fh->cap.lock);
2941 if (NULL == fh->cap.read_buf) {
2942 /* need to capture a new frame */
2943 if (locked_btres(fh->btv,RESOURCE_VIDEO)) {
2944 up(&fh->cap.lock);
2945 return POLLERR;
2946 }
2947 fh->cap.read_buf = videobuf_alloc(fh->cap.msize);
2948 if (NULL == fh->cap.read_buf) {
2949 up(&fh->cap.lock);
2950 return POLLERR;
2951 }
2952 fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR;
2953 field = videobuf_next_field(&fh->cap);
2954 if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,field)) {
2955 up(&fh->cap.lock);
2956 return POLLERR;
2957 }
2958 fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf);
2959 fh->cap.read_off = 0;
2960 }
2961 up(&fh->cap.lock);
2962 buf = (struct bttv_buffer*)fh->cap.read_buf;
2963 }
2964
2965 poll_wait(file, &buf->vb.done, wait);
2966 if (buf->vb.state == STATE_DONE ||
2967 buf->vb.state == STATE_ERROR)
2968 return POLLIN|POLLRDNORM;
2969 return 0;
2970}
2971
2972static int bttv_open(struct inode *inode, struct file *file)
2973{
2974 int minor = iminor(inode);
2975 struct bttv *btv = NULL;
2976 struct bttv_fh *fh;
2977 enum v4l2_buf_type type = 0;
2978 unsigned int i;
2979
2980 dprintk(KERN_DEBUG "bttv: open minor=%d\n",minor);
2981
2982 for (i = 0; i < bttv_num; i++) {
2983 if (bttvs[i].video_dev &&
2984 bttvs[i].video_dev->minor == minor) {
2985 btv = &bttvs[i];
2986 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2987 break;
2988 }
2989 if (bttvs[i].vbi_dev &&
2990 bttvs[i].vbi_dev->minor == minor) {
2991 btv = &bttvs[i];
2992 type = V4L2_BUF_TYPE_VBI_CAPTURE;
2993 break;
2994 }
2995 }
2996 if (NULL == btv)
2997 return -ENODEV;
2998
2999 dprintk(KERN_DEBUG "bttv%d: open called (type=%s)\n",
3000 btv->c.nr,v4l2_type_names[type]);
3001
3002 /* allocate per filehandle data */
3003 fh = kmalloc(sizeof(*fh),GFP_KERNEL);
3004 if (NULL == fh)
3005 return -ENOMEM;
3006 file->private_data = fh;
3007 *fh = btv->init;
3008 fh->type = type;
3009 fh->ov.setup_ok = 0;
3010 v4l2_prio_open(&btv->prio,&fh->prio);
3011
3012 videobuf_queue_init(&fh->cap, &bttv_video_qops,
3013 btv->c.pci, &btv->s_lock,
3014 V4L2_BUF_TYPE_VIDEO_CAPTURE,
3015 V4L2_FIELD_INTERLACED,
3016 sizeof(struct bttv_buffer),
3017 fh);
3018 videobuf_queue_init(&fh->vbi, &bttv_vbi_qops,
3019 btv->c.pci, &btv->s_lock,
3020 V4L2_BUF_TYPE_VBI_CAPTURE,
3021 V4L2_FIELD_SEQ_TB,
3022 sizeof(struct bttv_buffer),
3023 fh);
3024 i2c_vidiocschan(btv);
3025
3026 btv->users++;
3027 if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type)
3028 bttv_vbi_setlines(fh,btv,16);
3029 bttv_field_count(btv);
3030 return 0;
3031}
3032
3033static int bttv_release(struct inode *inode, struct file *file)
3034{
3035 struct bttv_fh *fh = file->private_data;
3036 struct bttv *btv = fh->btv;
3037
3038 /* turn off overlay */
3039 if (check_btres(fh, RESOURCE_OVERLAY))
3040 bttv_switch_overlay(btv,fh,NULL);
3041
3042 /* stop video capture */
3043 if (check_btres(fh, RESOURCE_VIDEO)) {
3044 videobuf_streamoff(&fh->cap);
3045 free_btres(btv,fh,RESOURCE_VIDEO);
3046 }
3047 if (fh->cap.read_buf) {
3048 buffer_release(&fh->cap,fh->cap.read_buf);
3049 kfree(fh->cap.read_buf);
3050 }
3051
3052 /* stop vbi capture */
3053 if (check_btres(fh, RESOURCE_VBI)) {
3054 if (fh->vbi.streaming)
3055 videobuf_streamoff(&fh->vbi);
3056 if (fh->vbi.reading)
3057 videobuf_read_stop(&fh->vbi);
3058 free_btres(btv,fh,RESOURCE_VBI);
3059 }
3060
3061 /* free stuff */
3062 videobuf_mmap_free(&fh->cap);
3063 videobuf_mmap_free(&fh->vbi);
3064 v4l2_prio_close(&btv->prio,&fh->prio);
3065 file->private_data = NULL;
3066 kfree(fh);
3067
3068 btv->users--;
3069 bttv_field_count(btv);
3070 return 0;
3071}
3072
3073static int
3074bttv_mmap(struct file *file, struct vm_area_struct *vma)
3075{
3076 struct bttv_fh *fh = file->private_data;
3077
3078 dprintk("bttv%d: mmap type=%s 0x%lx+%ld\n",
3079 fh->btv->c.nr, v4l2_type_names[fh->type],
3080 vma->vm_start, vma->vm_end - vma->vm_start);
3081 return videobuf_mmap_mapper(bttv_queue(fh),vma);
3082}
3083
3084static struct file_operations bttv_fops =
3085{
3086 .owner = THIS_MODULE,
3087 .open = bttv_open,
3088 .release = bttv_release,
3089 .ioctl = bttv_ioctl,
3090 .llseek = no_llseek,
3091 .read = bttv_read,
3092 .mmap = bttv_mmap,
3093 .poll = bttv_poll,
3094};
3095
3096static struct video_device bttv_video_template =
3097{
3098 .name = "UNSET",
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07003099 .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003100 VID_TYPE_CLIPPING|VID_TYPE_SCALES,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003101 .hardware = VID_HARDWARE_BT848,
3102 .fops = &bttv_fops,
3103 .minor = -1,
3104};
3105
3106static struct video_device bttv_vbi_template =
3107{
3108 .name = "bt848/878 vbi",
3109 .type = VID_TYPE_TUNER|VID_TYPE_TELETEXT,
3110 .hardware = VID_HARDWARE_BT848,
3111 .fops = &bttv_fops,
3112 .minor = -1,
3113};
3114
3115/* ----------------------------------------------------------------------- */
3116/* radio interface */
3117
3118static int radio_open(struct inode *inode, struct file *file)
3119{
3120 int minor = iminor(inode);
3121 struct bttv *btv = NULL;
3122 unsigned int i;
3123
3124 dprintk("bttv: open minor=%d\n",minor);
3125
3126 for (i = 0; i < bttv_num; i++) {
3127 if (bttvs[i].radio_dev->minor == minor) {
3128 btv = &bttvs[i];
3129 break;
3130 }
3131 }
3132 if (NULL == btv)
3133 return -ENODEV;
3134
3135 dprintk("bttv%d: open called (radio)\n",btv->c.nr);
3136 down(&btv->lock);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003137
Linus Torvalds1da177e2005-04-16 15:20:36 -07003138 btv->radio_user++;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003139
Linus Torvalds1da177e2005-04-16 15:20:36 -07003140 file->private_data = btv;
3141
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003142 bttv_call_i2c_clients(btv,AUDC_SET_RADIO,&btv->tuner_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003143 audio_mux(btv,AUDIO_RADIO);
3144
3145 up(&btv->lock);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003146 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003147}
3148
3149static int radio_release(struct inode *inode, struct file *file)
3150{
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003151 struct bttv *btv = file->private_data;
3152 struct rds_command cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003153
3154 btv->radio_user--;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003155
3156 bttv_call_i2c_clients(btv, RDS_CMD_CLOSE, &cmd);
3157
Linus Torvalds1da177e2005-04-16 15:20:36 -07003158 return 0;
3159}
3160
3161static int radio_do_ioctl(struct inode *inode, struct file *file,
3162 unsigned int cmd, void *arg)
3163{
3164 struct bttv *btv = file->private_data;
3165
3166 switch (cmd) {
3167 case VIDIOCGCAP:
3168 {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003169 struct video_capability *cap = arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003170
3171 memset(cap,0,sizeof(*cap));
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003172 strcpy(cap->name,btv->radio_dev->name);
3173 cap->type = VID_TYPE_TUNER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003174 cap->channels = 1;
3175 cap->audios = 1;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003176 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003177 }
3178
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003179 case VIDIOCGTUNER:
3180 {
3181 struct video_tuner *v = arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003182
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003183 if(v->tuner)
3184 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003185 memset(v,0,sizeof(*v));
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003186 strcpy(v->name, "Radio");
3187 bttv_call_i2c_clients(btv,cmd,v);
3188 return 0;
3189 }
3190 case VIDIOCSTUNER:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003191 /* nothing to do */
3192 return 0;
3193
3194 case BTTV_VERSION:
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003195 case VIDIOCGFREQ:
3196 case VIDIOCSFREQ:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197 case VIDIOCGAUDIO:
3198 case VIDIOCSAUDIO:
3199 return bttv_common_ioctls(btv,cmd,arg);
3200
3201 default:
3202 return -ENOIOCTLCMD;
3203 }
3204 return 0;
3205}
3206
3207static int radio_ioctl(struct inode *inode, struct file *file,
3208 unsigned int cmd, unsigned long arg)
3209{
3210 return video_usercopy(inode, file, cmd, arg, radio_do_ioctl);
3211}
3212
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003213static ssize_t radio_read(struct file *file, char __user *data,
3214 size_t count, loff_t *ppos)
3215{
3216 struct bttv *btv = file->private_data;
3217 struct rds_command cmd;
3218 cmd.block_count = count/3;
3219 cmd.buffer = data;
3220 cmd.instance = file;
3221 cmd.result = -ENODEV;
3222
3223 bttv_call_i2c_clients(btv, RDS_CMD_READ, &cmd);
3224
3225 return cmd.result;
3226}
3227
3228static unsigned int radio_poll(struct file *file, poll_table *wait)
3229{
3230 struct bttv *btv = file->private_data;
3231 struct rds_command cmd;
3232 cmd.instance = file;
3233 cmd.event_list = wait;
3234 cmd.result = -ENODEV;
3235 bttv_call_i2c_clients(btv, RDS_CMD_POLL, &cmd);
3236
3237 return cmd.result;
3238}
3239
Linus Torvalds1da177e2005-04-16 15:20:36 -07003240static struct file_operations radio_fops =
3241{
3242 .owner = THIS_MODULE,
3243 .open = radio_open,
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003244 .read = radio_read,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003245 .release = radio_release,
3246 .ioctl = radio_ioctl,
3247 .llseek = no_llseek,
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003248 .poll = radio_poll,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003249};
3250
3251static struct video_device radio_template =
3252{
3253 .name = "bt848/878 radio",
3254 .type = VID_TYPE_TUNER,
3255 .hardware = VID_HARDWARE_BT848,
3256 .fops = &radio_fops,
3257 .minor = -1,
3258};
3259
3260/* ----------------------------------------------------------------------- */
3261/* some debug code */
3262
Adrian Bunk408b6642005-05-01 08:59:29 -07003263static int bttv_risc_decode(u32 risc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003264{
3265 static char *instr[16] = {
3266 [ BT848_RISC_WRITE >> 28 ] = "write",
3267 [ BT848_RISC_SKIP >> 28 ] = "skip",
3268 [ BT848_RISC_WRITEC >> 28 ] = "writec",
3269 [ BT848_RISC_JUMP >> 28 ] = "jump",
3270 [ BT848_RISC_SYNC >> 28 ] = "sync",
3271 [ BT848_RISC_WRITE123 >> 28 ] = "write123",
3272 [ BT848_RISC_SKIP123 >> 28 ] = "skip123",
3273 [ BT848_RISC_WRITE1S23 >> 28 ] = "write1s23",
3274 };
3275 static int incr[16] = {
3276 [ BT848_RISC_WRITE >> 28 ] = 2,
3277 [ BT848_RISC_JUMP >> 28 ] = 2,
3278 [ BT848_RISC_SYNC >> 28 ] = 2,
3279 [ BT848_RISC_WRITE123 >> 28 ] = 5,
3280 [ BT848_RISC_SKIP123 >> 28 ] = 2,
3281 [ BT848_RISC_WRITE1S23 >> 28 ] = 3,
3282 };
3283 static char *bits[] = {
3284 "be0", "be1", "be2", "be3/resync",
3285 "set0", "set1", "set2", "set3",
3286 "clr0", "clr1", "clr2", "clr3",
3287 "irq", "res", "eol", "sol",
3288 };
3289 int i;
3290
3291 printk("0x%08x [ %s", risc,
3292 instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
3293 for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
3294 if (risc & (1 << (i + 12)))
3295 printk(" %s",bits[i]);
3296 printk(" count=%d ]\n", risc & 0xfff);
3297 return incr[risc >> 28] ? incr[risc >> 28] : 1;
3298}
3299
Adrian Bunk408b6642005-05-01 08:59:29 -07003300static void bttv_risc_disasm(struct bttv *btv,
3301 struct btcx_riscmem *risc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003302{
3303 unsigned int i,j,n;
3304
3305 printk("%s: risc disasm: %p [dma=0x%08lx]\n",
3306 btv->c.name, risc->cpu, (unsigned long)risc->dma);
3307 for (i = 0; i < (risc->size >> 2); i += n) {
3308 printk("%s: 0x%lx: ", btv->c.name,
3309 (unsigned long)(risc->dma + (i<<2)));
3310 n = bttv_risc_decode(risc->cpu[i]);
3311 for (j = 1; j < n; j++)
3312 printk("%s: 0x%lx: 0x%08x [ arg #%d ]\n",
3313 btv->c.name, (unsigned long)(risc->dma + ((i+j)<<2)),
3314 risc->cpu[i+j], j);
3315 if (0 == risc->cpu[i])
3316 break;
3317 }
3318}
3319
3320static void bttv_print_riscaddr(struct bttv *btv)
3321{
3322 printk(" main: %08Lx\n",
3323 (unsigned long long)btv->main.dma);
3324 printk(" vbi : o=%08Lx e=%08Lx\n",
3325 btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
3326 btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0);
3327 printk(" cap : o=%08Lx e=%08Lx\n",
3328 btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0,
3329 btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
3330 printk(" scr : o=%08Lx e=%08Lx\n",
3331 btv->screen ? (unsigned long long)btv->screen->top.dma : 0,
3332 btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0);
3333 bttv_risc_disasm(btv, &btv->main);
3334}
3335
3336/* ----------------------------------------------------------------------- */
3337/* irq handler */
3338
3339static char *irq_name[] = {
3340 "FMTCHG", // format change detected (525 vs. 625)
3341 "VSYNC", // vertical sync (new field)
3342 "HSYNC", // horizontal sync
3343 "OFLOW", // chroma/luma AGC overflow
3344 "HLOCK", // horizontal lock changed
3345 "VPRES", // video presence changed
3346 "6", "7",
3347 "I2CDONE", // hw irc operation finished
3348 "GPINT", // gpio port triggered irq
3349 "10",
3350 "RISCI", // risc instruction triggered irq
3351 "FBUS", // pixel data fifo dropped data (high pci bus latencies)
3352 "FTRGT", // pixel data fifo overrun
3353 "FDSR", // fifo data stream resyncronisation
3354 "PPERR", // parity error (data transfer)
3355 "RIPERR", // parity error (read risc instructions)
3356 "PABORT", // pci abort
3357 "OCERR", // risc instruction error
3358 "SCERR", // syncronisation error
3359};
3360
3361static void bttv_print_irqbits(u32 print, u32 mark)
3362{
3363 unsigned int i;
3364
3365 printk("bits:");
3366 for (i = 0; i < ARRAY_SIZE(irq_name); i++) {
3367 if (print & (1 << i))
3368 printk(" %s",irq_name[i]);
3369 if (mark & (1 << i))
3370 printk("*");
3371 }
3372}
3373
3374static void bttv_irq_debug_low_latency(struct bttv *btv, u32 rc)
3375{
3376 printk("bttv%d: irq: skipped frame [main=%lx,o_vbi=%lx,o_field=%lx,rc=%lx]\n",
3377 btv->c.nr,
3378 (unsigned long)btv->main.dma,
3379 (unsigned long)btv->main.cpu[RISC_SLOT_O_VBI+1],
3380 (unsigned long)btv->main.cpu[RISC_SLOT_O_FIELD+1],
3381 (unsigned long)rc);
3382
3383 if (0 == (btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC)) {
3384 printk("bttv%d: Oh, there (temporarely?) is no input signal. "
3385 "Ok, then this is harmless, don't worry ;)\n",
3386 btv->c.nr);
3387 return;
3388 }
3389 printk("bttv%d: Uhm. Looks like we have unusual high IRQ latencies.\n",
3390 btv->c.nr);
3391 printk("bttv%d: Lets try to catch the culpit red-handed ...\n",
3392 btv->c.nr);
3393 dump_stack();
3394}
3395
3396static int
3397bttv_irq_next_video(struct bttv *btv, struct bttv_buffer_set *set)
3398{
3399 struct bttv_buffer *item;
3400
3401 memset(set,0,sizeof(*set));
3402
3403 /* capture request ? */
3404 if (!list_empty(&btv->capture)) {
3405 set->frame_irq = 1;
3406 item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
3407 if (V4L2_FIELD_HAS_TOP(item->vb.field))
3408 set->top = item;
3409 if (V4L2_FIELD_HAS_BOTTOM(item->vb.field))
3410 set->bottom = item;
3411
3412 /* capture request for other field ? */
3413 if (!V4L2_FIELD_HAS_BOTH(item->vb.field) &&
3414 (item->vb.queue.next != &btv->capture)) {
3415 item = list_entry(item->vb.queue.next, struct bttv_buffer, vb.queue);
3416 if (!V4L2_FIELD_HAS_BOTH(item->vb.field)) {
3417 if (NULL == set->top &&
3418 V4L2_FIELD_TOP == item->vb.field) {
3419 set->top = item;
3420 }
3421 if (NULL == set->bottom &&
3422 V4L2_FIELD_BOTTOM == item->vb.field) {
3423 set->bottom = item;
3424 }
3425 if (NULL != set->top && NULL != set->bottom)
3426 set->top_irq = 2;
3427 }
3428 }
3429 }
3430
3431 /* screen overlay ? */
3432 if (NULL != btv->screen) {
3433 if (V4L2_FIELD_HAS_BOTH(btv->screen->vb.field)) {
3434 if (NULL == set->top && NULL == set->bottom) {
3435 set->top = btv->screen;
3436 set->bottom = btv->screen;
3437 }
3438 } else {
3439 if (V4L2_FIELD_TOP == btv->screen->vb.field &&
3440 NULL == set->top) {
3441 set->top = btv->screen;
3442 }
3443 if (V4L2_FIELD_BOTTOM == btv->screen->vb.field &&
3444 NULL == set->bottom) {
3445 set->bottom = btv->screen;
3446 }
3447 }
3448 }
3449
3450 dprintk("bttv%d: next set: top=%p bottom=%p [screen=%p,irq=%d,%d]\n",
3451 btv->c.nr,set->top, set->bottom,
3452 btv->screen,set->frame_irq,set->top_irq);
3453 return 0;
3454}
3455
3456static void
3457bttv_irq_wakeup_video(struct bttv *btv, struct bttv_buffer_set *wakeup,
3458 struct bttv_buffer_set *curr, unsigned int state)
3459{
3460 struct timeval ts;
3461
3462 do_gettimeofday(&ts);
3463
3464 if (wakeup->top == wakeup->bottom) {
3465 if (NULL != wakeup->top && curr->top != wakeup->top) {
3466 if (irq_debug > 1)
3467 printk("bttv%d: wakeup: both=%p\n",btv->c.nr,wakeup->top);
3468 wakeup->top->vb.ts = ts;
3469 wakeup->top->vb.field_count = btv->field_count;
3470 wakeup->top->vb.state = state;
3471 wake_up(&wakeup->top->vb.done);
3472 }
3473 } else {
3474 if (NULL != wakeup->top && curr->top != wakeup->top) {
3475 if (irq_debug > 1)
3476 printk("bttv%d: wakeup: top=%p\n",btv->c.nr,wakeup->top);
3477 wakeup->top->vb.ts = ts;
3478 wakeup->top->vb.field_count = btv->field_count;
3479 wakeup->top->vb.state = state;
3480 wake_up(&wakeup->top->vb.done);
3481 }
3482 if (NULL != wakeup->bottom && curr->bottom != wakeup->bottom) {
3483 if (irq_debug > 1)
3484 printk("bttv%d: wakeup: bottom=%p\n",btv->c.nr,wakeup->bottom);
3485 wakeup->bottom->vb.ts = ts;
3486 wakeup->bottom->vb.field_count = btv->field_count;
3487 wakeup->bottom->vb.state = state;
3488 wake_up(&wakeup->bottom->vb.done);
3489 }
3490 }
3491}
3492
3493static void
3494bttv_irq_wakeup_vbi(struct bttv *btv, struct bttv_buffer *wakeup,
3495 unsigned int state)
3496{
3497 struct timeval ts;
3498
3499 if (NULL == wakeup)
3500 return;
3501
3502 do_gettimeofday(&ts);
3503 wakeup->vb.ts = ts;
3504 wakeup->vb.field_count = btv->field_count;
3505 wakeup->vb.state = state;
3506 wake_up(&wakeup->vb.done);
3507}
3508
3509static void bttv_irq_timeout(unsigned long data)
3510{
3511 struct bttv *btv = (struct bttv *)data;
3512 struct bttv_buffer_set old,new;
3513 struct bttv_buffer *ovbi;
3514 struct bttv_buffer *item;
3515 unsigned long flags;
3516
3517 if (bttv_verbose) {
3518 printk(KERN_INFO "bttv%d: timeout: drop=%d irq=%d/%d, risc=%08x, ",
3519 btv->c.nr, btv->framedrop, btv->irq_me, btv->irq_total,
3520 btread(BT848_RISC_COUNT));
3521 bttv_print_irqbits(btread(BT848_INT_STAT),0);
3522 printk("\n");
3523 }
3524
3525 spin_lock_irqsave(&btv->s_lock,flags);
3526
3527 /* deactivate stuff */
3528 memset(&new,0,sizeof(new));
3529 old = btv->curr;
3530 ovbi = btv->cvbi;
3531 btv->curr = new;
3532 btv->cvbi = NULL;
3533 btv->loop_irq = 0;
3534 bttv_buffer_activate_video(btv, &new);
3535 bttv_buffer_activate_vbi(btv, NULL);
3536 bttv_set_dma(btv, 0);
3537
3538 /* wake up */
3539 bttv_irq_wakeup_video(btv, &old, &new, STATE_ERROR);
3540 bttv_irq_wakeup_vbi(btv, ovbi, STATE_ERROR);
3541
3542 /* cancel all outstanding capture / vbi requests */
3543 while (!list_empty(&btv->capture)) {
3544 item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
3545 list_del(&item->vb.queue);
3546 item->vb.state = STATE_ERROR;
3547 wake_up(&item->vb.done);
3548 }
3549 while (!list_empty(&btv->vcapture)) {
3550 item = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
3551 list_del(&item->vb.queue);
3552 item->vb.state = STATE_ERROR;
3553 wake_up(&item->vb.done);
3554 }
3555
3556 btv->errors++;
3557 spin_unlock_irqrestore(&btv->s_lock,flags);
3558}
3559
3560static void
3561bttv_irq_wakeup_top(struct bttv *btv)
3562{
3563 struct bttv_buffer *wakeup = btv->curr.top;
3564
3565 if (NULL == wakeup)
3566 return;
3567
3568 spin_lock(&btv->s_lock);
3569 btv->curr.top_irq = 0;
3570 btv->curr.top = NULL;
3571 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
3572
3573 do_gettimeofday(&wakeup->vb.ts);
3574 wakeup->vb.field_count = btv->field_count;
3575 wakeup->vb.state = STATE_DONE;
3576 wake_up(&wakeup->vb.done);
3577 spin_unlock(&btv->s_lock);
3578}
3579
3580static inline int is_active(struct btcx_riscmem *risc, u32 rc)
3581{
3582 if (rc < risc->dma)
3583 return 0;
3584 if (rc > risc->dma + risc->size)
3585 return 0;
3586 return 1;
3587}
3588
3589static void
3590bttv_irq_switch_video(struct bttv *btv)
3591{
3592 struct bttv_buffer_set new;
3593 struct bttv_buffer_set old;
3594 dma_addr_t rc;
3595
3596 spin_lock(&btv->s_lock);
3597
3598 /* new buffer set */
3599 bttv_irq_next_video(btv, &new);
3600 rc = btread(BT848_RISC_COUNT);
3601 if ((btv->curr.top && is_active(&btv->curr.top->top, rc)) ||
3602 (btv->curr.bottom && is_active(&btv->curr.bottom->bottom, rc))) {
3603 btv->framedrop++;
3604 if (debug_latency)
3605 bttv_irq_debug_low_latency(btv, rc);
3606 spin_unlock(&btv->s_lock);
3607 return;
3608 }
3609
3610 /* switch over */
3611 old = btv->curr;
3612 btv->curr = new;
3613 btv->loop_irq &= ~1;
3614 bttv_buffer_activate_video(btv, &new);
3615 bttv_set_dma(btv, 0);
3616
3617 /* switch input */
3618 if (UNSET != btv->new_input) {
3619 video_mux(btv,btv->new_input);
3620 btv->new_input = UNSET;
3621 }
3622
3623 /* wake up finished buffers */
3624 bttv_irq_wakeup_video(btv, &old, &new, STATE_DONE);
3625 spin_unlock(&btv->s_lock);
3626}
3627
3628static void
3629bttv_irq_switch_vbi(struct bttv *btv)
3630{
3631 struct bttv_buffer *new = NULL;
3632 struct bttv_buffer *old;
3633 u32 rc;
3634
3635 spin_lock(&btv->s_lock);
3636
3637 if (!list_empty(&btv->vcapture))
3638 new = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
3639 old = btv->cvbi;
3640
3641 rc = btread(BT848_RISC_COUNT);
3642 if (NULL != old && (is_active(&old->top, rc) ||
3643 is_active(&old->bottom, rc))) {
3644 btv->framedrop++;
3645 if (debug_latency)
3646 bttv_irq_debug_low_latency(btv, rc);
3647 spin_unlock(&btv->s_lock);
3648 return;
3649 }
3650
3651 /* switch */
3652 btv->cvbi = new;
3653 btv->loop_irq &= ~4;
3654 bttv_buffer_activate_vbi(btv, new);
3655 bttv_set_dma(btv, 0);
3656
3657 bttv_irq_wakeup_vbi(btv, old, STATE_DONE);
3658 spin_unlock(&btv->s_lock);
3659}
3660
3661static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
3662{
3663 u32 stat,astat;
3664 u32 dstat;
3665 int count;
3666 struct bttv *btv;
3667 int handled = 0;
3668
3669 btv=(struct bttv *)dev_id;
3670 count=0;
3671 while (1) {
3672 /* get/clear interrupt status bits */
3673 stat=btread(BT848_INT_STAT);
3674 astat=stat&btread(BT848_INT_MASK);
3675 if (!astat)
3676 break;
3677 handled = 1;
3678 btwrite(stat,BT848_INT_STAT);
3679
3680 /* get device status bits */
3681 dstat=btread(BT848_DSTATUS);
3682
3683 if (irq_debug) {
3684 printk(KERN_DEBUG "bttv%d: irq loop=%d fc=%d "
3685 "riscs=%x, riscc=%08x, ",
3686 btv->c.nr, count, btv->field_count,
3687 stat>>28, btread(BT848_RISC_COUNT));
3688 bttv_print_irqbits(stat,astat);
3689 if (stat & BT848_INT_HLOCK)
3690 printk(" HLOC => %s", (dstat & BT848_DSTATUS_HLOC)
3691 ? "yes" : "no");
3692 if (stat & BT848_INT_VPRES)
3693 printk(" PRES => %s", (dstat & BT848_DSTATUS_PRES)
3694 ? "yes" : "no");
3695 if (stat & BT848_INT_FMTCHG)
3696 printk(" NUML => %s", (dstat & BT848_DSTATUS_NUML)
3697 ? "625" : "525");
3698 printk("\n");
3699 }
3700
3701 if (astat&BT848_INT_VSYNC)
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003702 btv->field_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003703
3704 if (astat & BT848_INT_GPINT) {
3705 wake_up(&btv->gpioq);
3706 bttv_gpio_irq(&btv->c);
3707 }
3708
3709 if (astat & BT848_INT_I2CDONE) {
3710 btv->i2c_done = stat;
3711 wake_up(&btv->i2c_queue);
3712 }
3713
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003714 if ((astat & BT848_INT_RISCI) && (stat & (4<<28)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003715 bttv_irq_switch_vbi(btv);
3716
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003717 if ((astat & BT848_INT_RISCI) && (stat & (2<<28)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003718 bttv_irq_wakeup_top(btv);
3719
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003720 if ((astat & BT848_INT_RISCI) && (stat & (1<<28)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003721 bttv_irq_switch_video(btv);
3722
3723 if ((astat & BT848_INT_HLOCK) && btv->opt_automute)
3724 audio_mux(btv, -1);
3725
3726 if (astat & (BT848_INT_SCERR|BT848_INT_OCERR)) {
3727 printk(KERN_INFO "bttv%d: %s%s @ %08x,",btv->c.nr,
3728 (astat & BT848_INT_SCERR) ? "SCERR" : "",
3729 (astat & BT848_INT_OCERR) ? "OCERR" : "",
3730 btread(BT848_RISC_COUNT));
3731 bttv_print_irqbits(stat,astat);
3732 printk("\n");
3733 if (bttv_debug)
3734 bttv_print_riscaddr(btv);
3735 }
3736 if (fdsr && astat & BT848_INT_FDSR) {
3737 printk(KERN_INFO "bttv%d: FDSR @ %08x\n",
3738 btv->c.nr,btread(BT848_RISC_COUNT));
3739 if (bttv_debug)
3740 bttv_print_riscaddr(btv);
3741 }
3742
3743 count++;
3744 if (count > 4) {
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08003745
3746 if (count > 8 || !(astat & BT848_INT_GPINT)) {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003747 btwrite(0, BT848_INT_MASK);
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08003748
3749 printk(KERN_ERR
3750 "bttv%d: IRQ lockup, cleared int mask [", btv->c.nr);
3751 } else {
3752 printk(KERN_ERR
3753 "bttv%d: IRQ lockup, clearing GPINT from int mask [", btv->c.nr);
3754
3755 btwrite(btread(BT848_INT_MASK) & (-1 ^ BT848_INT_GPINT),
3756 BT848_INT_MASK);
3757 };
3758
Linus Torvalds1da177e2005-04-16 15:20:36 -07003759 bttv_print_irqbits(stat,astat);
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08003760
Linus Torvalds1da177e2005-04-16 15:20:36 -07003761 printk("]\n");
3762 }
3763 }
3764 btv->irq_total++;
3765 if (handled)
3766 btv->irq_me++;
3767 return IRQ_RETVAL(handled);
3768}
3769
3770
3771/* ----------------------------------------------------------------------- */
3772/* initialitation */
3773
3774static struct video_device *vdev_init(struct bttv *btv,
3775 struct video_device *template,
3776 char *type)
3777{
3778 struct video_device *vfd;
3779
3780 vfd = video_device_alloc();
3781 if (NULL == vfd)
3782 return NULL;
3783 *vfd = *template;
3784 vfd->minor = -1;
3785 vfd->dev = &btv->c.pci->dev;
3786 vfd->release = video_device_release;
3787 snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
3788 btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "",
3789 type, bttv_tvcards[btv->c.type].name);
3790 return vfd;
3791}
3792
3793static void bttv_unregister_video(struct bttv *btv)
3794{
3795 if (btv->video_dev) {
3796 if (-1 != btv->video_dev->minor)
3797 video_unregister_device(btv->video_dev);
3798 else
3799 video_device_release(btv->video_dev);
3800 btv->video_dev = NULL;
3801 }
3802 if (btv->vbi_dev) {
3803 if (-1 != btv->vbi_dev->minor)
3804 video_unregister_device(btv->vbi_dev);
3805 else
3806 video_device_release(btv->vbi_dev);
3807 btv->vbi_dev = NULL;
3808 }
3809 if (btv->radio_dev) {
3810 if (-1 != btv->radio_dev->minor)
3811 video_unregister_device(btv->radio_dev);
3812 else
3813 video_device_release(btv->radio_dev);
3814 btv->radio_dev = NULL;
3815 }
3816}
3817
3818/* register video4linux devices */
3819static int __devinit bttv_register_video(struct bttv *btv)
3820{
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07003821 if (no_overlay <= 0) {
3822 bttv_video_template.type |= VID_TYPE_OVERLAY;
3823 } else {
3824 printk("bttv: Overlay support disabled.\n");
3825 }
3826
Linus Torvalds1da177e2005-04-16 15:20:36 -07003827 /* video */
3828 btv->video_dev = vdev_init(btv, &bttv_video_template, "video");
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003829 if (NULL == btv->video_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003830 goto err;
3831 if (video_register_device(btv->video_dev,VFL_TYPE_GRABBER,video_nr)<0)
3832 goto err;
3833 printk(KERN_INFO "bttv%d: registered device video%d\n",
3834 btv->c.nr,btv->video_dev->minor & 0x1f);
3835 video_device_create_file(btv->video_dev, &class_device_attr_card);
3836
3837 /* vbi */
3838 btv->vbi_dev = vdev_init(btv, &bttv_vbi_template, "vbi");
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003839 if (NULL == btv->vbi_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003840 goto err;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003841 if (video_register_device(btv->vbi_dev,VFL_TYPE_VBI,vbi_nr)<0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003842 goto err;
3843 printk(KERN_INFO "bttv%d: registered device vbi%d\n",
3844 btv->c.nr,btv->vbi_dev->minor & 0x1f);
3845
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003846 if (!btv->has_radio)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003847 return 0;
3848 /* radio */
3849 btv->radio_dev = vdev_init(btv, &radio_template, "radio");
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003850 if (NULL == btv->radio_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003851 goto err;
3852 if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,radio_nr)<0)
3853 goto err;
3854 printk(KERN_INFO "bttv%d: registered device radio%d\n",
3855 btv->c.nr,btv->radio_dev->minor & 0x1f);
3856
3857 /* all done */
3858 return 0;
3859
3860 err:
3861 bttv_unregister_video(btv);
3862 return -1;
3863}
3864
3865
3866/* on OpenFirmware machines (PowerMac at least), PCI memory cycle */
3867/* response on cards with no firmware is not enabled by OF */
3868static void pci_set_command(struct pci_dev *dev)
3869{
3870#if defined(__powerpc__)
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003871 unsigned int cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003872
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003873 pci_read_config_dword(dev, PCI_COMMAND, &cmd);
3874 cmd = (cmd | PCI_COMMAND_MEMORY );
3875 pci_write_config_dword(dev, PCI_COMMAND, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003876#endif
3877}
3878
3879static int __devinit bttv_probe(struct pci_dev *dev,
3880 const struct pci_device_id *pci_id)
3881{
3882 int result;
3883 unsigned char lat;
3884 struct bttv *btv;
3885
3886 if (bttv_num == BTTV_MAX)
3887 return -ENOMEM;
3888 printk(KERN_INFO "bttv: Bt8xx card found (%d).\n", bttv_num);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003889 btv=&bttvs[bttv_num];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003890 memset(btv,0,sizeof(*btv));
3891 btv->c.nr = bttv_num;
3892 sprintf(btv->c.name,"bttv%d",btv->c.nr);
3893
3894 /* initialize structs / fill in defaults */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003895 init_MUTEX(&btv->lock);
3896 init_MUTEX(&btv->reslock);
3897 spin_lock_init(&btv->s_lock);
3898 spin_lock_init(&btv->gpio_lock);
3899 init_waitqueue_head(&btv->gpioq);
3900 init_waitqueue_head(&btv->i2c_queue);
3901 INIT_LIST_HEAD(&btv->c.subs);
3902 INIT_LIST_HEAD(&btv->capture);
3903 INIT_LIST_HEAD(&btv->vcapture);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003904 v4l2_prio_init(&btv->prio);
3905
3906 init_timer(&btv->timeout);
3907 btv->timeout.function = bttv_irq_timeout;
3908 btv->timeout.data = (unsigned long)btv;
3909
Michael Krufky7c08fb02005-11-08 21:36:21 -08003910 btv->i2c_rc = -1;
3911 btv->tuner_type = UNSET;
3912 btv->pinnacle_id = UNSET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003913 btv->new_input = UNSET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003914 btv->has_radio=radio[btv->c.nr];
3915
3916 /* pci stuff (init, get irq/mmio, ... */
3917 btv->c.pci = dev;
Michael Krufky7c08fb02005-11-08 21:36:21 -08003918 btv->id = dev->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003919 if (pci_enable_device(dev)) {
Michael Krufky7c08fb02005-11-08 21:36:21 -08003920 printk(KERN_WARNING "bttv%d: Can't enable device.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003921 btv->c.nr);
3922 return -EIO;
3923 }
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003924 if (pci_set_dma_mask(dev, DMA_32BIT_MASK)) {
3925 printk(KERN_WARNING "bttv%d: No suitable DMA available.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003926 btv->c.nr);
3927 return -EIO;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003928 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003929 if (!request_mem_region(pci_resource_start(dev,0),
3930 pci_resource_len(dev,0),
3931 btv->c.name)) {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003932 printk(KERN_WARNING "bttv%d: can't request iomem (0x%lx).\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003933 btv->c.nr, pci_resource_start(dev,0));
3934 return -EBUSY;
3935 }
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003936 pci_set_master(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003937 pci_set_command(dev);
3938 pci_set_drvdata(dev,btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003939
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003940 pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision);
3941 pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
3942 printk(KERN_INFO "bttv%d: Bt%d (rev %d) at %s, ",
3943 bttv_num,btv->id, btv->revision, pci_name(dev));
3944 printk("irq: %d, latency: %d, mmio: 0x%lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003945 btv->c.pci->irq, lat, pci_resource_start(dev,0));
3946 schedule();
3947
3948 btv->bt848_mmio=ioremap(pci_resource_start(dev,0), 0x1000);
3949 if (NULL == ioremap(pci_resource_start(dev,0), 0x1000)) {
3950 printk("bttv%d: ioremap() failed\n", btv->c.nr);
3951 result = -EIO;
3952 goto fail1;
3953 }
3954
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003955 /* identify card */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003956 bttv_idcard(btv);
3957
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003958 /* disable irqs, register irq handler */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003959 btwrite(0, BT848_INT_MASK);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003960 result = request_irq(btv->c.pci->irq, bttv_irq,
3961 SA_SHIRQ | SA_INTERRUPT,btv->c.name,(void *)btv);
3962 if (result < 0) {
3963 printk(KERN_ERR "bttv%d: can't get IRQ %d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003964 bttv_num,btv->c.pci->irq);
3965 goto fail1;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003966 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003967
3968 if (0 != bttv_handle_chipset(btv)) {
3969 result = -EIO;
3970 goto fail2;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003971 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003972
3973 /* init options from insmod args */
3974 btv->opt_combfilter = combfilter;
3975 btv->opt_lumafilter = lumafilter;
3976 btv->opt_automute = automute;
3977 btv->opt_chroma_agc = chroma_agc;
3978 btv->opt_adc_crush = adc_crush;
3979 btv->opt_vcr_hack = vcr_hack;
3980 btv->opt_whitecrush_upper = whitecrush_upper;
3981 btv->opt_whitecrush_lower = whitecrush_lower;
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -07003982 btv->opt_uv_ratio = uv_ratio;
3983 btv->opt_full_luma_range = full_luma_range;
3984 btv->opt_coring = coring;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003985
3986 /* fill struct bttv with some useful defaults */
3987 btv->init.btv = btv;
3988 btv->init.ov.w.width = 320;
3989 btv->init.ov.w.height = 240;
3990 btv->init.fmt = format_by_palette(VIDEO_PALETTE_RGB24);
3991 btv->init.width = 320;
3992 btv->init.height = 240;
3993 btv->init.lines = 16;
3994 btv->input = 0;
3995
3996 /* initialize hardware */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003997 if (bttv_gpio)
3998 bttv_gpio_tracking(btv,"pre-init");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003999
4000 bttv_risc_init_main(btv);
4001 init_bt848(btv);
4002
4003 /* gpio */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004004 btwrite(0x00, BT848_GPIO_REG_INP);
4005 btwrite(0x00, BT848_GPIO_OUT_EN);
4006 if (bttv_verbose)
4007 bttv_gpio_tracking(btv,"init");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004008
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004009 /* needs to be done before i2c is registered */
4010 bttv_init_card1(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004011
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004012 /* register i2c + gpio */
4013 init_bttv_i2c(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004014
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004015 /* some card-specific stuff (needs working i2c) */
4016 bttv_init_card2(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004017 init_irqreg(btv);
4018
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004019 /* register video4linux + input */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004020 if (!bttv_tvcards[btv->c.type].no_video) {
4021 bttv_register_video(btv);
4022 bt848_bright(btv,32768);
4023 bt848_contrast(btv,32768);
4024 bt848_hue(btv,32768);
4025 bt848_sat(btv,32768);
4026 audio_mux(btv,AUDIO_MUTE);
4027 set_input(btv,0);
4028 }
4029
4030 /* add subdevices */
4031 if (btv->has_remote)
4032 bttv_sub_add_device(&btv->c, "remote");
4033 if (bttv_tvcards[btv->c.type].has_dvb)
4034 bttv_sub_add_device(&btv->c, "dvb");
4035
4036 /* everything is fine */
4037 bttv_num++;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004038 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004039
4040 fail2:
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004041 free_irq(btv->c.pci->irq,btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042
4043 fail1:
4044 if (btv->bt848_mmio)
4045 iounmap(btv->bt848_mmio);
4046 release_mem_region(pci_resource_start(btv->c.pci,0),
4047 pci_resource_len(btv->c.pci,0));
4048 pci_set_drvdata(dev,NULL);
4049 return result;
4050}
4051
4052static void __devexit bttv_remove(struct pci_dev *pci_dev)
4053{
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004054 struct bttv *btv = pci_get_drvdata(pci_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004055
4056 if (bttv_verbose)
4057 printk("bttv%d: unloading\n",btv->c.nr);
4058
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004059 /* shutdown everything (DMA+IRQs) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060 btand(~15, BT848_GPIO_DMA_CTL);
4061 btwrite(0, BT848_INT_MASK);
4062 btwrite(~0x0, BT848_INT_STAT);
4063 btwrite(0x0, BT848_GPIO_OUT_EN);
4064 if (bttv_gpio)
4065 bttv_gpio_tracking(btv,"cleanup");
4066
4067 /* tell gpio modules we are leaving ... */
4068 btv->shutdown=1;
4069 wake_up(&btv->gpioq);
4070 bttv_sub_del_devices(&btv->c);
4071
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004072 /* unregister i2c_bus + input */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004073 fini_bttv_i2c(btv);
4074
4075 /* unregister video4linux */
4076 bttv_unregister_video(btv);
4077
4078 /* free allocated memory */
4079 btcx_riscmem_free(btv->c.pci,&btv->main);
4080
4081 /* free ressources */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004082 free_irq(btv->c.pci->irq,btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004083 iounmap(btv->bt848_mmio);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004084 release_mem_region(pci_resource_start(btv->c.pci,0),
4085 pci_resource_len(btv->c.pci,0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004086
4087 pci_set_drvdata(pci_dev, NULL);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004088 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004089}
4090
4091static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state)
4092{
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004093 struct bttv *btv = pci_get_drvdata(pci_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004094 struct bttv_buffer_set idle;
4095 unsigned long flags;
4096
Mauro Carvalho Chehab0f97a932005-09-09 13:04:05 -07004097 dprintk("bttv%d: suspend %d\n", btv->c.nr, state.event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004098
4099 /* stop dma + irqs */
4100 spin_lock_irqsave(&btv->s_lock,flags);
4101 memset(&idle, 0, sizeof(idle));
4102 btv->state.video = btv->curr;
4103 btv->state.vbi = btv->cvbi;
4104 btv->state.loop_irq = btv->loop_irq;
4105 btv->curr = idle;
4106 btv->loop_irq = 0;
4107 bttv_buffer_activate_video(btv, &idle);
4108 bttv_buffer_activate_vbi(btv, NULL);
4109 bttv_set_dma(btv, 0);
4110 btwrite(0, BT848_INT_MASK);
4111 spin_unlock_irqrestore(&btv->s_lock,flags);
4112
4113 /* save bt878 state */
4114 btv->state.gpio_enable = btread(BT848_GPIO_OUT_EN);
4115 btv->state.gpio_data = gpio_read();
4116
4117 /* save pci state */
4118 pci_save_state(pci_dev);
4119 if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
4120 pci_disable_device(pci_dev);
4121 btv->state.disabled = 1;
4122 }
4123 return 0;
4124}
4125
4126static int bttv_resume(struct pci_dev *pci_dev)
4127{
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004128 struct bttv *btv = pci_get_drvdata(pci_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004129 unsigned long flags;
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004130 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004131
4132 dprintk("bttv%d: resume\n", btv->c.nr);
4133
4134 /* restore pci state */
4135 if (btv->state.disabled) {
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004136 err=pci_enable_device(pci_dev);
4137 if (err) {
4138 printk(KERN_WARNING "bttv%d: Can't enable device.\n",
4139 btv->c.nr);
4140 return err;
4141 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004142 btv->state.disabled = 0;
4143 }
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004144 err=pci_set_power_state(pci_dev, PCI_D0);
4145 if (err) {
4146 pci_disable_device(pci_dev);
4147 printk(KERN_WARNING "bttv%d: Can't enable device.\n",
4148 btv->c.nr);
4149 btv->state.disabled = 1;
4150 return err;
4151 }
4152
Linus Torvalds1da177e2005-04-16 15:20:36 -07004153 pci_restore_state(pci_dev);
4154
4155 /* restore bt878 state */
4156 bttv_reinit_bt848(btv);
4157 gpio_inout(0xffffff, btv->state.gpio_enable);
4158 gpio_write(btv->state.gpio_data);
4159
4160 /* restart dma */
4161 spin_lock_irqsave(&btv->s_lock,flags);
4162 btv->curr = btv->state.video;
4163 btv->cvbi = btv->state.vbi;
4164 btv->loop_irq = btv->state.loop_irq;
4165 bttv_buffer_activate_video(btv, &btv->curr);
4166 bttv_buffer_activate_vbi(btv, btv->cvbi);
4167 bttv_set_dma(btv, 0);
4168 spin_unlock_irqrestore(&btv->s_lock,flags);
4169 return 0;
4170}
4171
4172static struct pci_device_id bttv_pci_tbl[] = {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004173 {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848,
4174 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
Linus Torvalds1da177e2005-04-16 15:20:36 -07004175 {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849,
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004176 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
Linus Torvalds1da177e2005-04-16 15:20:36 -07004177 {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878,
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004178 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
Linus Torvalds1da177e2005-04-16 15:20:36 -07004179 {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879,
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004180 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
4181 {0,}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004182};
4183
4184MODULE_DEVICE_TABLE(pci, bttv_pci_tbl);
4185
4186static struct pci_driver bttv_pci_driver = {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004187 .name = "bttv",
4188 .id_table = bttv_pci_tbl,
4189 .probe = bttv_probe,
4190 .remove = __devexit_p(bttv_remove),
Linus Torvalds1da177e2005-04-16 15:20:36 -07004191 .suspend = bttv_suspend,
4192 .resume = bttv_resume,
4193};
4194
4195static int bttv_init_module(void)
4196{
4197 bttv_num = 0;
4198
4199 printk(KERN_INFO "bttv: driver version %d.%d.%d loaded\n",
4200 (BTTV_VERSION_CODE >> 16) & 0xff,
4201 (BTTV_VERSION_CODE >> 8) & 0xff,
4202 BTTV_VERSION_CODE & 0xff);
4203#ifdef SNAPSHOT
4204 printk(KERN_INFO "bttv: snapshot date %04d-%02d-%02d\n",
4205 SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
4206#endif
4207 if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME)
4208 gbuffers = 2;
4209 if (gbufsize < 0 || gbufsize > BTTV_MAX_FBUF)
4210 gbufsize = BTTV_MAX_FBUF;
4211 gbufsize = (gbufsize + PAGE_SIZE - 1) & PAGE_MASK;
4212 if (bttv_verbose)
4213 printk(KERN_INFO "bttv: using %d buffers with %dk (%d pages) each for capture\n",
4214 gbuffers, gbufsize >> 10, gbufsize >> PAGE_SHIFT);
4215
4216 bttv_check_chipset();
4217
4218 bus_register(&bttv_sub_bus_type);
4219 return pci_module_init(&bttv_pci_driver);
4220}
4221
4222static void bttv_cleanup_module(void)
4223{
4224 pci_unregister_driver(&bttv_pci_driver);
4225 bus_unregister(&bttv_sub_bus_type);
4226 return;
4227}
4228
4229module_init(bttv_init_module);
4230module_exit(bttv_cleanup_module);
4231
4232/*
4233 * Local variables:
4234 * c-basic-offset: 8
4235 * End:
4236 */