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