blob: 69a147b85f1a7bb4ac94779eecbc9f4cfcd2da2c [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 Chehabb5b8ab82006-01-09 15:25:20 -020037#include "bttvp.h"
38
Mauro Carvalho Chehabfa9846a2005-07-12 13:58:42 -070039#include <linux/dma-mapping.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040
41#include <asm/io.h>
42#include <asm/byteorder.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,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200213 /* ITU-R frame line number of the first VBI line
214 we can capture, of the first and second field. */
215 .vbistart = { 7,320 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216 },{
217 .v4l2_id = V4L2_STD_NTSC_M,
218 .name = "NTSC",
219 .Fsc = 28636363,
220 .swidth = 768,
221 .sheight = 480,
222 .totalwidth = 910,
223 .adelay = 0x68,
224 .bdelay = 0x5d,
225 .iform = (BT848_IFORM_NTSC|BT848_IFORM_XT0),
226 .scaledtwidth = 910,
227 .hdelayx1 = 128,
228 .hactivex1 = 910,
229 .vdelay = 0x1a,
230 .vbipack = 144,
231 .sram = 1,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200232 .vbistart = { 10, 273 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 },{
234 .v4l2_id = V4L2_STD_SECAM,
235 .name = "SECAM",
236 .Fsc = 35468950,
237 .swidth = 924,
238 .sheight = 576,
239 .totalwidth = 1135,
240 .adelay = 0x7f,
241 .bdelay = 0xb0,
242 .iform = (BT848_IFORM_SECAM|BT848_IFORM_XT1),
243 .scaledtwidth = 1135,
244 .hdelayx1 = 186,
245 .hactivex1 = 922,
246 .vdelay = 0x20,
247 .vbipack = 255,
248 .sram = 0, /* like PAL, correct? */
Michael H. Schimek67f15702006-01-09 15:25:27 -0200249 .vbistart = { 7, 320 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 },{
251 .v4l2_id = V4L2_STD_PAL_Nc,
252 .name = "PAL-Nc",
253 .Fsc = 28636363,
254 .swidth = 640,
255 .sheight = 576,
256 .totalwidth = 910,
257 .adelay = 0x68,
258 .bdelay = 0x5d,
259 .iform = (BT848_IFORM_PAL_NC|BT848_IFORM_XT0),
260 .scaledtwidth = 780,
261 .hdelayx1 = 130,
262 .hactivex1 = 734,
263 .vdelay = 0x1a,
264 .vbipack = 144,
265 .sram = -1,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200266 .vbistart = { 7, 320 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 },{
268 .v4l2_id = V4L2_STD_PAL_M,
269 .name = "PAL-M",
270 .Fsc = 28636363,
271 .swidth = 640,
272 .sheight = 480,
273 .totalwidth = 910,
274 .adelay = 0x68,
275 .bdelay = 0x5d,
276 .iform = (BT848_IFORM_PAL_M|BT848_IFORM_XT0),
277 .scaledtwidth = 780,
278 .hdelayx1 = 135,
279 .hactivex1 = 754,
280 .vdelay = 0x1a,
281 .vbipack = 144,
282 .sram = -1,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200283 .vbistart = { 10, 273 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 },{
285 .v4l2_id = V4L2_STD_PAL_N,
286 .name = "PAL-N",
287 .Fsc = 35468950,
288 .swidth = 768,
289 .sheight = 576,
290 .totalwidth = 1135,
291 .adelay = 0x7f,
292 .bdelay = 0x72,
293 .iform = (BT848_IFORM_PAL_N|BT848_IFORM_XT1),
294 .scaledtwidth = 944,
295 .hdelayx1 = 186,
296 .hactivex1 = 922,
297 .vdelay = 0x20,
298 .vbipack = 144,
299 .sram = -1,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200300 .vbistart = { 7, 320},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301 },{
302 .v4l2_id = V4L2_STD_NTSC_M_JP,
303 .name = "NTSC-JP",
304 .Fsc = 28636363,
305 .swidth = 640,
306 .sheight = 480,
307 .totalwidth = 910,
308 .adelay = 0x68,
309 .bdelay = 0x5d,
310 .iform = (BT848_IFORM_NTSC_J|BT848_IFORM_XT0),
311 .scaledtwidth = 780,
312 .hdelayx1 = 135,
313 .hactivex1 = 754,
314 .vdelay = 0x16,
315 .vbipack = 144,
316 .sram = -1,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200317 .vbistart = {10, 273},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 },{
319 /* that one hopefully works with the strange timing
320 * which video recorders produce when playing a NTSC
321 * tape on a PAL TV ... */
322 .v4l2_id = V4L2_STD_PAL_60,
323 .name = "PAL-60",
324 .Fsc = 35468950,
325 .swidth = 924,
326 .sheight = 480,
327 .totalwidth = 1135,
328 .adelay = 0x7f,
329 .bdelay = 0x72,
330 .iform = (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
331 .scaledtwidth = 1135,
332 .hdelayx1 = 186,
333 .hactivex1 = 924,
334 .vdelay = 0x1a,
335 .vbipack = 255,
336 .vtotal = 524,
337 .sram = -1,
Michael H. Schimek67f15702006-01-09 15:25:27 -0200338 .vbistart = { 10, 273 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339 }
340};
341static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms);
342
343/* ----------------------------------------------------------------------- */
344/* bttv format list
345 packed pixel formats must come first */
346static const struct bttv_format bttv_formats[] = {
347 {
348 .name = "8 bpp, gray",
349 .palette = VIDEO_PALETTE_GREY,
350 .fourcc = V4L2_PIX_FMT_GREY,
351 .btformat = BT848_COLOR_FMT_Y8,
352 .depth = 8,
353 .flags = FORMAT_FLAGS_PACKED,
354 },{
355 .name = "8 bpp, dithered color",
356 .palette = VIDEO_PALETTE_HI240,
357 .fourcc = V4L2_PIX_FMT_HI240,
358 .btformat = BT848_COLOR_FMT_RGB8,
359 .depth = 8,
360 .flags = FORMAT_FLAGS_PACKED | FORMAT_FLAGS_DITHER,
361 },{
362 .name = "15 bpp RGB, le",
363 .palette = VIDEO_PALETTE_RGB555,
364 .fourcc = V4L2_PIX_FMT_RGB555,
365 .btformat = BT848_COLOR_FMT_RGB15,
366 .depth = 16,
367 .flags = FORMAT_FLAGS_PACKED,
368 },{
369 .name = "15 bpp RGB, be",
370 .palette = -1,
371 .fourcc = V4L2_PIX_FMT_RGB555X,
372 .btformat = BT848_COLOR_FMT_RGB15,
373 .btswap = 0x03, /* byteswap */
374 .depth = 16,
375 .flags = FORMAT_FLAGS_PACKED,
376 },{
377 .name = "16 bpp RGB, le",
378 .palette = VIDEO_PALETTE_RGB565,
379 .fourcc = V4L2_PIX_FMT_RGB565,
380 .btformat = BT848_COLOR_FMT_RGB16,
381 .depth = 16,
382 .flags = FORMAT_FLAGS_PACKED,
383 },{
384 .name = "16 bpp RGB, be",
385 .palette = -1,
386 .fourcc = V4L2_PIX_FMT_RGB565X,
387 .btformat = BT848_COLOR_FMT_RGB16,
388 .btswap = 0x03, /* byteswap */
389 .depth = 16,
390 .flags = FORMAT_FLAGS_PACKED,
391 },{
392 .name = "24 bpp RGB, le",
393 .palette = VIDEO_PALETTE_RGB24,
394 .fourcc = V4L2_PIX_FMT_BGR24,
395 .btformat = BT848_COLOR_FMT_RGB24,
396 .depth = 24,
397 .flags = FORMAT_FLAGS_PACKED,
398 },{
399 .name = "32 bpp RGB, le",
400 .palette = VIDEO_PALETTE_RGB32,
401 .fourcc = V4L2_PIX_FMT_BGR32,
402 .btformat = BT848_COLOR_FMT_RGB32,
403 .depth = 32,
404 .flags = FORMAT_FLAGS_PACKED,
405 },{
406 .name = "32 bpp RGB, be",
407 .palette = -1,
408 .fourcc = V4L2_PIX_FMT_RGB32,
409 .btformat = BT848_COLOR_FMT_RGB32,
410 .btswap = 0x0f, /* byte+word swap */
411 .depth = 32,
412 .flags = FORMAT_FLAGS_PACKED,
413 },{
414 .name = "4:2:2, packed, YUYV",
415 .palette = VIDEO_PALETTE_YUV422,
416 .fourcc = V4L2_PIX_FMT_YUYV,
417 .btformat = BT848_COLOR_FMT_YUY2,
418 .depth = 16,
419 .flags = FORMAT_FLAGS_PACKED,
420 },{
421 .name = "4:2:2, packed, YUYV",
422 .palette = VIDEO_PALETTE_YUYV,
423 .fourcc = V4L2_PIX_FMT_YUYV,
424 .btformat = BT848_COLOR_FMT_YUY2,
425 .depth = 16,
426 .flags = FORMAT_FLAGS_PACKED,
427 },{
428 .name = "4:2:2, packed, UYVY",
429 .palette = VIDEO_PALETTE_UYVY,
430 .fourcc = V4L2_PIX_FMT_UYVY,
431 .btformat = BT848_COLOR_FMT_YUY2,
432 .btswap = 0x03, /* byteswap */
433 .depth = 16,
434 .flags = FORMAT_FLAGS_PACKED,
435 },{
436 .name = "4:2:2, planar, Y-Cb-Cr",
437 .palette = VIDEO_PALETTE_YUV422P,
438 .fourcc = V4L2_PIX_FMT_YUV422P,
439 .btformat = BT848_COLOR_FMT_YCrCb422,
440 .depth = 16,
441 .flags = FORMAT_FLAGS_PLANAR,
442 .hshift = 1,
443 .vshift = 0,
444 },{
445 .name = "4:2:0, planar, Y-Cb-Cr",
446 .palette = VIDEO_PALETTE_YUV420P,
447 .fourcc = V4L2_PIX_FMT_YUV420,
448 .btformat = BT848_COLOR_FMT_YCrCb422,
449 .depth = 12,
450 .flags = FORMAT_FLAGS_PLANAR,
451 .hshift = 1,
452 .vshift = 1,
453 },{
454 .name = "4:2:0, planar, Y-Cr-Cb",
455 .palette = -1,
456 .fourcc = V4L2_PIX_FMT_YVU420,
457 .btformat = BT848_COLOR_FMT_YCrCb422,
458 .depth = 12,
459 .flags = FORMAT_FLAGS_PLANAR | FORMAT_FLAGS_CrCb,
460 .hshift = 1,
461 .vshift = 1,
462 },{
463 .name = "4:1:1, planar, Y-Cb-Cr",
464 .palette = VIDEO_PALETTE_YUV411P,
465 .fourcc = V4L2_PIX_FMT_YUV411P,
466 .btformat = BT848_COLOR_FMT_YCrCb411,
467 .depth = 12,
468 .flags = FORMAT_FLAGS_PLANAR,
469 .hshift = 2,
470 .vshift = 0,
471 },{
472 .name = "4:1:0, planar, Y-Cb-Cr",
473 .palette = VIDEO_PALETTE_YUV410P,
474 .fourcc = V4L2_PIX_FMT_YUV410,
475 .btformat = BT848_COLOR_FMT_YCrCb411,
476 .depth = 9,
477 .flags = FORMAT_FLAGS_PLANAR,
478 .hshift = 2,
479 .vshift = 2,
480 },{
481 .name = "4:1:0, planar, Y-Cr-Cb",
482 .palette = -1,
483 .fourcc = V4L2_PIX_FMT_YVU410,
484 .btformat = BT848_COLOR_FMT_YCrCb411,
485 .depth = 9,
486 .flags = FORMAT_FLAGS_PLANAR | FORMAT_FLAGS_CrCb,
487 .hshift = 2,
488 .vshift = 2,
489 },{
490 .name = "raw scanlines",
491 .palette = VIDEO_PALETTE_RAW,
492 .fourcc = -1,
493 .btformat = BT848_COLOR_FMT_RAW,
494 .depth = 8,
495 .flags = FORMAT_FLAGS_RAW,
496 }
497};
498static const unsigned int BTTV_FORMATS = ARRAY_SIZE(bttv_formats);
499
500/* ----------------------------------------------------------------------- */
501
502#define V4L2_CID_PRIVATE_CHROMA_AGC (V4L2_CID_PRIVATE_BASE + 0)
503#define V4L2_CID_PRIVATE_COMBFILTER (V4L2_CID_PRIVATE_BASE + 1)
504#define V4L2_CID_PRIVATE_AUTOMUTE (V4L2_CID_PRIVATE_BASE + 2)
505#define V4L2_CID_PRIVATE_LUMAFILTER (V4L2_CID_PRIVATE_BASE + 3)
506#define V4L2_CID_PRIVATE_AGC_CRUSH (V4L2_CID_PRIVATE_BASE + 4)
507#define V4L2_CID_PRIVATE_VCR_HACK (V4L2_CID_PRIVATE_BASE + 5)
508#define V4L2_CID_PRIVATE_WHITECRUSH_UPPER (V4L2_CID_PRIVATE_BASE + 6)
509#define V4L2_CID_PRIVATE_WHITECRUSH_LOWER (V4L2_CID_PRIVATE_BASE + 7)
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700510#define V4L2_CID_PRIVATE_UV_RATIO (V4L2_CID_PRIVATE_BASE + 8)
511#define V4L2_CID_PRIVATE_FULL_LUMA_RANGE (V4L2_CID_PRIVATE_BASE + 9)
512#define V4L2_CID_PRIVATE_CORING (V4L2_CID_PRIVATE_BASE + 10)
513#define V4L2_CID_PRIVATE_LASTP1 (V4L2_CID_PRIVATE_BASE + 11)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514
515static const struct v4l2_queryctrl no_ctl = {
516 .name = "42",
517 .flags = V4L2_CTRL_FLAG_DISABLED,
518};
519static const struct v4l2_queryctrl bttv_ctls[] = {
520 /* --- video --- */
521 {
522 .id = V4L2_CID_BRIGHTNESS,
523 .name = "Brightness",
524 .minimum = 0,
525 .maximum = 65535,
526 .step = 256,
527 .default_value = 32768,
528 .type = V4L2_CTRL_TYPE_INTEGER,
529 },{
530 .id = V4L2_CID_CONTRAST,
531 .name = "Contrast",
532 .minimum = 0,
533 .maximum = 65535,
534 .step = 128,
535 .default_value = 32768,
536 .type = V4L2_CTRL_TYPE_INTEGER,
537 },{
538 .id = V4L2_CID_SATURATION,
539 .name = "Saturation",
540 .minimum = 0,
541 .maximum = 65535,
542 .step = 128,
543 .default_value = 32768,
544 .type = V4L2_CTRL_TYPE_INTEGER,
545 },{
546 .id = V4L2_CID_HUE,
547 .name = "Hue",
548 .minimum = 0,
549 .maximum = 65535,
550 .step = 256,
551 .default_value = 32768,
552 .type = V4L2_CTRL_TYPE_INTEGER,
553 },
554 /* --- audio --- */
555 {
556 .id = V4L2_CID_AUDIO_MUTE,
557 .name = "Mute",
558 .minimum = 0,
559 .maximum = 1,
560 .type = V4L2_CTRL_TYPE_BOOLEAN,
561 },{
562 .id = V4L2_CID_AUDIO_VOLUME,
563 .name = "Volume",
564 .minimum = 0,
565 .maximum = 65535,
566 .step = 65535/100,
567 .default_value = 65535,
568 .type = V4L2_CTRL_TYPE_INTEGER,
569 },{
570 .id = V4L2_CID_AUDIO_BALANCE,
571 .name = "Balance",
572 .minimum = 0,
573 .maximum = 65535,
574 .step = 65535/100,
575 .default_value = 32768,
576 .type = V4L2_CTRL_TYPE_INTEGER,
577 },{
578 .id = V4L2_CID_AUDIO_BASS,
579 .name = "Bass",
580 .minimum = 0,
581 .maximum = 65535,
582 .step = 65535/100,
583 .default_value = 32768,
584 .type = V4L2_CTRL_TYPE_INTEGER,
585 },{
586 .id = V4L2_CID_AUDIO_TREBLE,
587 .name = "Treble",
588 .minimum = 0,
589 .maximum = 65535,
590 .step = 65535/100,
591 .default_value = 32768,
592 .type = V4L2_CTRL_TYPE_INTEGER,
593 },
594 /* --- private --- */
595 {
596 .id = V4L2_CID_PRIVATE_CHROMA_AGC,
597 .name = "chroma agc",
598 .minimum = 0,
599 .maximum = 1,
600 .type = V4L2_CTRL_TYPE_BOOLEAN,
601 },{
602 .id = V4L2_CID_PRIVATE_COMBFILTER,
603 .name = "combfilter",
604 .minimum = 0,
605 .maximum = 1,
606 .type = V4L2_CTRL_TYPE_BOOLEAN,
607 },{
608 .id = V4L2_CID_PRIVATE_AUTOMUTE,
609 .name = "automute",
610 .minimum = 0,
611 .maximum = 1,
612 .type = V4L2_CTRL_TYPE_BOOLEAN,
613 },{
614 .id = V4L2_CID_PRIVATE_LUMAFILTER,
615 .name = "luma decimation filter",
616 .minimum = 0,
617 .maximum = 1,
618 .type = V4L2_CTRL_TYPE_BOOLEAN,
619 },{
620 .id = V4L2_CID_PRIVATE_AGC_CRUSH,
621 .name = "agc crush",
622 .minimum = 0,
623 .maximum = 1,
624 .type = V4L2_CTRL_TYPE_BOOLEAN,
625 },{
626 .id = V4L2_CID_PRIVATE_VCR_HACK,
627 .name = "vcr hack",
628 .minimum = 0,
629 .maximum = 1,
630 .type = V4L2_CTRL_TYPE_BOOLEAN,
631 },{
632 .id = V4L2_CID_PRIVATE_WHITECRUSH_UPPER,
633 .name = "whitecrush upper",
634 .minimum = 0,
635 .maximum = 255,
636 .step = 1,
637 .default_value = 0xCF,
638 .type = V4L2_CTRL_TYPE_INTEGER,
639 },{
640 .id = V4L2_CID_PRIVATE_WHITECRUSH_LOWER,
641 .name = "whitecrush lower",
642 .minimum = 0,
643 .maximum = 255,
644 .step = 1,
645 .default_value = 0x7F,
646 .type = V4L2_CTRL_TYPE_INTEGER,
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700647 },{
648 .id = V4L2_CID_PRIVATE_UV_RATIO,
649 .name = "uv ratio",
650 .minimum = 0,
651 .maximum = 100,
652 .step = 1,
653 .default_value = 50,
654 .type = V4L2_CTRL_TYPE_INTEGER,
655 },{
656 .id = V4L2_CID_PRIVATE_FULL_LUMA_RANGE,
657 .name = "full luma range",
658 .minimum = 0,
659 .maximum = 1,
660 .type = V4L2_CTRL_TYPE_BOOLEAN,
661 },{
662 .id = V4L2_CID_PRIVATE_CORING,
663 .name = "coring",
664 .minimum = 0,
665 .maximum = 3,
666 .step = 1,
667 .default_value = 0,
668 .type = V4L2_CTRL_TYPE_INTEGER,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669 }
670
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700671
672
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673};
674static const int BTTV_CTLS = ARRAY_SIZE(bttv_ctls);
675
676/* ----------------------------------------------------------------------- */
677/* resource management */
678
679static
680int check_alloc_btres(struct bttv *btv, struct bttv_fh *fh, int bit)
681{
682 if (fh->resources & bit)
683 /* have it already allocated */
684 return 1;
685
686 /* is it free? */
687 down(&btv->reslock);
688 if (btv->resources & bit) {
689 /* no, someone else uses it */
690 up(&btv->reslock);
691 return 0;
692 }
693 /* it's free, grab it */
694 fh->resources |= bit;
695 btv->resources |= bit;
696 up(&btv->reslock);
697 return 1;
698}
699
700static
701int check_btres(struct bttv_fh *fh, int bit)
702{
703 return (fh->resources & bit);
704}
705
706static
707int locked_btres(struct bttv *btv, int bit)
708{
709 return (btv->resources & bit);
710}
711
712static
713void free_btres(struct bttv *btv, struct bttv_fh *fh, int bits)
714{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715 if ((fh->resources & bits) != bits) {
716 /* trying to free ressources not allocated by us ... */
717 printk("bttv: BUG! (btres)\n");
718 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 down(&btv->reslock);
720 fh->resources &= ~bits;
721 btv->resources &= ~bits;
722 up(&btv->reslock);
723}
724
725/* ----------------------------------------------------------------------- */
726/* If Bt848a or Bt849, use PLL for PAL/SECAM and crystal for NTSC */
727
728/* Frequency = (F_input / PLL_X) * PLL_I.PLL_F/PLL_C
729 PLL_X = Reference pre-divider (0=1, 1=2)
730 PLL_C = Post divider (0=6, 1=4)
731 PLL_I = Integer input
732 PLL_F = Fractional input
733
734 F_input = 28.636363 MHz:
735 PAL (CLKx2 = 35.46895 MHz): PLL_X = 1, PLL_I = 0x0E, PLL_F = 0xDCF9, PLL_C = 0
736*/
737
738static void set_pll_freq(struct bttv *btv, unsigned int fin, unsigned int fout)
739{
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800740 unsigned char fl, fh, fi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800742 /* prevent overflows */
743 fin/=4;
744 fout/=4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800746 fout*=12;
747 fi=fout/fin;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800749 fout=(fout%fin)*256;
750 fh=fout/fin;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800752 fout=(fout%fin)*256;
753 fl=fout/fin;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800755 btwrite(fl, BT848_PLL_F_LO);
756 btwrite(fh, BT848_PLL_F_HI);
757 btwrite(fi|BT848_PLL_X, BT848_PLL_XCI);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758}
759
760static void set_pll(struct bttv *btv)
761{
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800762 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800764 if (!btv->pll.pll_crystal)
765 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766
767 if (btv->pll.pll_ofreq == btv->pll.pll_current) {
768 dprintk("bttv%d: PLL: no change required\n",btv->c.nr);
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800769 return;
770 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800772 if (btv->pll.pll_ifreq == btv->pll.pll_ofreq) {
773 /* no PLL needed */
774 if (btv->pll.pll_current == 0)
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -0800775 return;
Bernd Petrovitsche1e70a22005-09-22 21:43:53 -0700776 bttv_printk(KERN_INFO "bttv%d: PLL can sleep, using XTAL (%d).\n",
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -0800777 btv->c.nr,btv->pll.pll_ifreq);
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800778 btwrite(0x00,BT848_TGCTRL);
779 btwrite(0x00,BT848_PLL_XCI);
780 btv->pll.pll_current = 0;
781 return;
782 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783
Bernd Petrovitsche1e70a22005-09-22 21:43:53 -0700784 bttv_printk(KERN_INFO "bttv%d: PLL: %d => %d ",btv->c.nr,
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -0800785 btv->pll.pll_ifreq, btv->pll.pll_ofreq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786 set_pll_freq(btv, btv->pll.pll_ifreq, btv->pll.pll_ofreq);
787
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800788 for (i=0; i<10; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 /* Let other people run while the PLL stabilizes */
Bernd Petrovitsche1e70a22005-09-22 21:43:53 -0700790 bttv_printk(".");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791 msleep(10);
792
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800793 if (btread(BT848_DSTATUS) & BT848_DSTATUS_PLOCK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 btwrite(0,BT848_DSTATUS);
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800795 } else {
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -0800796 btwrite(0x08,BT848_TGCTRL);
797 btv->pll.pll_current = btv->pll.pll_ofreq;
Bernd Petrovitsche1e70a22005-09-22 21:43:53 -0700798 bttv_printk(" ok\n");
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -0800799 return;
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800800 }
801 }
802 btv->pll.pll_current = -1;
Bernd Petrovitsche1e70a22005-09-22 21:43:53 -0700803 bttv_printk("failed\n");
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800804 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805}
806
807/* used to switch between the bt848's analog/digital video capture modes */
808static void bt848A_set_timing(struct bttv *btv)
809{
810 int i, len;
811 int table_idx = bttv_tvnorms[btv->tvnorm].sram;
812 int fsc = bttv_tvnorms[btv->tvnorm].Fsc;
813
814 if (UNSET == bttv_tvcards[btv->c.type].muxsel[btv->input]) {
815 dprintk("bttv%d: load digital timing table (table_idx=%d)\n",
816 btv->c.nr,table_idx);
817
818 /* timing change...reset timing generator address */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800819 btwrite(0x00, BT848_TGCTRL);
820 btwrite(0x02, BT848_TGCTRL);
821 btwrite(0x00, BT848_TGCTRL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822
823 len=SRAM_Table[table_idx][0];
824 for(i = 1; i <= len; i++)
825 btwrite(SRAM_Table[table_idx][i],BT848_TGLB);
826 btv->pll.pll_ofreq = 27000000;
827
828 set_pll(btv);
829 btwrite(0x11, BT848_TGCTRL);
830 btwrite(0x41, BT848_DVSIF);
831 } else {
832 btv->pll.pll_ofreq = fsc;
833 set_pll(btv);
834 btwrite(0x0, BT848_DVSIF);
835 }
836}
837
838/* ----------------------------------------------------------------------- */
839
840static void bt848_bright(struct bttv *btv, int bright)
841{
842 int value;
843
844 // printk("bttv: set bright: %d\n",bright); // DEBUG
845 btv->bright = bright;
846
847 /* We want -128 to 127 we get 0-65535 */
848 value = (bright >> 8) - 128;
849 btwrite(value & 0xff, BT848_BRIGHT);
850}
851
852static void bt848_hue(struct bttv *btv, int hue)
853{
854 int value;
855
856 btv->hue = hue;
857
858 /* -128 to 127 */
859 value = (hue >> 8) - 128;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800860 btwrite(value & 0xff, BT848_HUE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861}
862
863static void bt848_contrast(struct bttv *btv, int cont)
864{
865 int value,hibit;
866
867 btv->contrast = cont;
868
869 /* 0-511 */
870 value = (cont >> 7);
871 hibit = (value >> 6) & 4;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800872 btwrite(value & 0xff, BT848_CONTRAST_LO);
873 btaor(hibit, ~4, BT848_E_CONTROL);
874 btaor(hibit, ~4, BT848_O_CONTROL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875}
876
877static void bt848_sat(struct bttv *btv, int color)
878{
879 int val_u,val_v,hibits;
880
881 btv->saturation = color;
882
883 /* 0-511 for the color */
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -0700884 val_u = ((color * btv->opt_uv_ratio) / 50) >> 7;
885 val_v = (((color * (100 - btv->opt_uv_ratio) / 50) >>7)*180L)/254;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800886 hibits = (val_u >> 7) & 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887 hibits |= (val_v >> 8) & 1;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800888 btwrite(val_u & 0xff, BT848_SAT_U_LO);
889 btwrite(val_v & 0xff, BT848_SAT_V_LO);
890 btaor(hibits, ~3, BT848_E_CONTROL);
891 btaor(hibits, ~3, BT848_O_CONTROL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892}
893
894/* ----------------------------------------------------------------------- */
895
896static int
897video_mux(struct bttv *btv, unsigned int input)
898{
899 int mux,mask2;
900
901 if (input >= bttv_tvcards[btv->c.type].video_inputs)
902 return -EINVAL;
903
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800904 /* needed by RemoteVideo MX */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 mask2 = bttv_tvcards[btv->c.type].gpiomask2;
906 if (mask2)
907 gpio_inout(mask2,mask2);
908
909 if (input == btv->svhs) {
910 btor(BT848_CONTROL_COMP, BT848_E_CONTROL);
911 btor(BT848_CONTROL_COMP, BT848_O_CONTROL);
912 } else {
913 btand(~BT848_CONTROL_COMP, BT848_E_CONTROL);
914 btand(~BT848_CONTROL_COMP, BT848_O_CONTROL);
915 }
916 mux = bttv_tvcards[btv->c.type].muxsel[input] & 3;
917 btaor(mux<<5, ~(3<<5), BT848_IFORM);
918 dprintk(KERN_DEBUG "bttv%d: video mux: input=%d mux=%d\n",
919 btv->c.nr,input,mux);
920
921 /* card specific hook */
922 if(bttv_tvcards[btv->c.type].muxsel_hook)
923 bttv_tvcards[btv->c.type].muxsel_hook (btv, input);
924 return 0;
925}
926
927static char *audio_modes[] = {
928 "audio: tuner", "audio: radio", "audio: extern",
929 "audio: intern", "audio: off"
930};
931
932static int
933audio_mux(struct bttv *btv, int mode)
934{
935 int val,mux,i2c_mux,signal;
936
937 gpio_inout(bttv_tvcards[btv->c.type].gpiomask,
938 bttv_tvcards[btv->c.type].gpiomask);
939 signal = btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC;
940
941 switch (mode) {
942 case AUDIO_MUTE:
943 btv->audio |= AUDIO_MUTE;
944 break;
945 case AUDIO_UNMUTE:
946 btv->audio &= ~AUDIO_MUTE;
947 break;
948 case AUDIO_TUNER:
949 case AUDIO_RADIO:
950 case AUDIO_EXTERN:
951 case AUDIO_INTERN:
952 btv->audio &= AUDIO_MUTE;
953 btv->audio |= mode;
954 }
955 i2c_mux = mux = (btv->audio & AUDIO_MUTE) ? AUDIO_OFF : btv->audio;
956 if (btv->opt_automute && !signal && !btv->radio_user)
957 mux = AUDIO_OFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958
959 val = bttv_tvcards[btv->c.type].audiomux[mux];
960 gpio_bits(bttv_tvcards[btv->c.type].gpiomask,val);
961 if (bttv_gpio)
962 bttv_gpio_tracking(btv,audio_modes[mux]);
963 if (!in_interrupt())
964 bttv_call_i2c_clients(btv,AUDC_SET_INPUT,&(i2c_mux));
965 return 0;
966}
967
968static void
969i2c_vidiocschan(struct bttv *btv)
970{
971 struct video_channel c;
972
973 memset(&c,0,sizeof(c));
974 c.norm = btv->tvnorm;
975 c.channel = btv->input;
976 bttv_call_i2c_clients(btv,VIDIOCSCHAN,&c);
Mauro Carvalho Chehab5a25e842005-11-08 21:36:52 -0800977 if (btv->c.type == BTTV_BOARD_VOODOOTV_FM)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 bttv_tda9880_setnorm(btv,c.norm);
979}
980
981static int
982set_tvnorm(struct bttv *btv, unsigned int norm)
983{
984 const struct bttv_tvnorm *tvnorm;
985
986 if (norm < 0 || norm >= BTTV_TVNORMS)
987 return -EINVAL;
988
989 btv->tvnorm = norm;
990 tvnorm = &bttv_tvnorms[norm];
991
992 btwrite(tvnorm->adelay, BT848_ADELAY);
993 btwrite(tvnorm->bdelay, BT848_BDELAY);
994 btaor(tvnorm->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH),
995 BT848_IFORM);
996 btwrite(tvnorm->vbipack, BT848_VBI_PACK_SIZE);
997 btwrite(1, BT848_VBI_PACK_DEL);
998 bt848A_set_timing(btv);
999
1000 switch (btv->c.type) {
Mauro Carvalho Chehab5a25e842005-11-08 21:36:52 -08001001 case BTTV_BOARD_VOODOOTV_FM:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 bttv_tda9880_setnorm(btv,norm);
1003 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 }
1005 return 0;
1006}
1007
1008static void
1009set_input(struct bttv *btv, unsigned int input)
1010{
1011 unsigned long flags;
1012
1013 btv->input = input;
1014 if (irq_iswitch) {
1015 spin_lock_irqsave(&btv->s_lock,flags);
1016 if (btv->curr.frame_irq) {
1017 /* active capture -> delayed input switch */
1018 btv->new_input = input;
1019 } else {
1020 video_mux(btv,input);
1021 }
1022 spin_unlock_irqrestore(&btv->s_lock,flags);
1023 } else {
1024 video_mux(btv,input);
1025 }
1026 audio_mux(btv,(input == bttv_tvcards[btv->c.type].tuner ?
1027 AUDIO_TUNER : AUDIO_EXTERN));
1028 set_tvnorm(btv,btv->tvnorm);
1029 i2c_vidiocschan(btv);
1030}
1031
1032static void init_irqreg(struct bttv *btv)
1033{
1034 /* clear status */
1035 btwrite(0xfffffUL, BT848_INT_STAT);
1036
1037 if (bttv_tvcards[btv->c.type].no_video) {
1038 /* i2c only */
1039 btwrite(BT848_INT_I2CDONE,
1040 BT848_INT_MASK);
1041 } else {
1042 /* full video */
1043 btwrite((btv->triton1) |
1044 (btv->gpioirq ? BT848_INT_GPINT : 0) |
1045 BT848_INT_SCERR |
1046 (fdsr ? BT848_INT_FDSR : 0) |
1047 BT848_INT_RISCI|BT848_INT_OCERR|BT848_INT_VPRES|
1048 BT848_INT_FMTCHG|BT848_INT_HLOCK|
1049 BT848_INT_I2CDONE,
1050 BT848_INT_MASK);
1051 }
1052}
1053
1054static void init_bt848(struct bttv *btv)
1055{
1056 int val;
1057
1058 if (bttv_tvcards[btv->c.type].no_video) {
1059 /* very basic init only */
1060 init_irqreg(btv);
1061 return;
1062 }
1063
1064 btwrite(0x00, BT848_CAP_CTL);
1065 btwrite(BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL);
1066 btwrite(BT848_IFORM_XTAUTO | BT848_IFORM_AUTO, BT848_IFORM);
1067
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001068 /* set planar and packed mode trigger points and */
1069 /* set rising edge of inverted GPINTR pin as irq trigger */
1070 btwrite(BT848_GPIO_DMA_CTL_PKTP_32|
1071 BT848_GPIO_DMA_CTL_PLTP1_16|
1072 BT848_GPIO_DMA_CTL_PLTP23_16|
1073 BT848_GPIO_DMA_CTL_GPINTC|
1074 BT848_GPIO_DMA_CTL_GPINTI,
1075 BT848_GPIO_DMA_CTL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076
1077 val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001078 btwrite(val, BT848_E_SCLOOP);
1079 btwrite(val, BT848_O_SCLOOP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001081 btwrite(0x20, BT848_E_VSCALE_HI);
1082 btwrite(0x20, BT848_O_VSCALE_HI);
1083 btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 BT848_ADC);
1085
1086 btwrite(whitecrush_upper, BT848_WC_UP);
1087 btwrite(whitecrush_lower, BT848_WC_DOWN);
1088
1089 if (btv->opt_lumafilter) {
1090 btwrite(0, BT848_E_CONTROL);
1091 btwrite(0, BT848_O_CONTROL);
1092 } else {
1093 btwrite(BT848_CONTROL_LDEC, BT848_E_CONTROL);
1094 btwrite(BT848_CONTROL_LDEC, BT848_O_CONTROL);
1095 }
1096
1097 bt848_bright(btv, btv->bright);
1098 bt848_hue(btv, btv->hue);
1099 bt848_contrast(btv, btv->contrast);
1100 bt848_sat(btv, btv->saturation);
1101
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001102 /* interrupt */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 init_irqreg(btv);
1104}
1105
1106static void bttv_reinit_bt848(struct bttv *btv)
1107{
1108 unsigned long flags;
1109
1110 if (bttv_verbose)
1111 printk(KERN_INFO "bttv%d: reset, reinitialize\n",btv->c.nr);
1112 spin_lock_irqsave(&btv->s_lock,flags);
1113 btv->errors=0;
1114 bttv_set_dma(btv,0);
1115 spin_unlock_irqrestore(&btv->s_lock,flags);
1116
1117 init_bt848(btv);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001118 btv->pll.pll_current = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 set_input(btv,btv->input);
1120}
1121
1122static int get_control(struct bttv *btv, struct v4l2_control *c)
1123{
1124 struct video_audio va;
1125 int i;
1126
1127 for (i = 0; i < BTTV_CTLS; i++)
1128 if (bttv_ctls[i].id == c->id)
1129 break;
1130 if (i == BTTV_CTLS)
1131 return -EINVAL;
1132 if (i >= 4 && i <= 8) {
1133 memset(&va,0,sizeof(va));
1134 bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
1135 if (btv->audio_hook)
1136 btv->audio_hook(btv,&va,0);
1137 }
1138 switch (c->id) {
1139 case V4L2_CID_BRIGHTNESS:
1140 c->value = btv->bright;
1141 break;
1142 case V4L2_CID_HUE:
1143 c->value = btv->hue;
1144 break;
1145 case V4L2_CID_CONTRAST:
1146 c->value = btv->contrast;
1147 break;
1148 case V4L2_CID_SATURATION:
1149 c->value = btv->saturation;
1150 break;
1151
1152 case V4L2_CID_AUDIO_MUTE:
1153 c->value = (VIDEO_AUDIO_MUTE & va.flags) ? 1 : 0;
1154 break;
1155 case V4L2_CID_AUDIO_VOLUME:
1156 c->value = va.volume;
1157 break;
1158 case V4L2_CID_AUDIO_BALANCE:
1159 c->value = va.balance;
1160 break;
1161 case V4L2_CID_AUDIO_BASS:
1162 c->value = va.bass;
1163 break;
1164 case V4L2_CID_AUDIO_TREBLE:
1165 c->value = va.treble;
1166 break;
1167
1168 case V4L2_CID_PRIVATE_CHROMA_AGC:
1169 c->value = btv->opt_chroma_agc;
1170 break;
1171 case V4L2_CID_PRIVATE_COMBFILTER:
1172 c->value = btv->opt_combfilter;
1173 break;
1174 case V4L2_CID_PRIVATE_LUMAFILTER:
1175 c->value = btv->opt_lumafilter;
1176 break;
1177 case V4L2_CID_PRIVATE_AUTOMUTE:
1178 c->value = btv->opt_automute;
1179 break;
1180 case V4L2_CID_PRIVATE_AGC_CRUSH:
1181 c->value = btv->opt_adc_crush;
1182 break;
1183 case V4L2_CID_PRIVATE_VCR_HACK:
1184 c->value = btv->opt_vcr_hack;
1185 break;
1186 case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
1187 c->value = btv->opt_whitecrush_upper;
1188 break;
1189 case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
1190 c->value = btv->opt_whitecrush_lower;
1191 break;
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -07001192 case V4L2_CID_PRIVATE_UV_RATIO:
1193 c->value = btv->opt_uv_ratio;
1194 break;
1195 case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
1196 c->value = btv->opt_full_luma_range;
1197 break;
1198 case V4L2_CID_PRIVATE_CORING:
1199 c->value = btv->opt_coring;
1200 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 default:
1202 return -EINVAL;
1203 }
1204 return 0;
1205}
1206
1207static int set_control(struct bttv *btv, struct v4l2_control *c)
1208{
1209 struct video_audio va;
1210 int i,val;
1211
1212 for (i = 0; i < BTTV_CTLS; i++)
1213 if (bttv_ctls[i].id == c->id)
1214 break;
1215 if (i == BTTV_CTLS)
1216 return -EINVAL;
1217 if (i >= 4 && i <= 8) {
1218 memset(&va,0,sizeof(va));
1219 bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
1220 if (btv->audio_hook)
1221 btv->audio_hook(btv,&va,0);
1222 }
1223 switch (c->id) {
1224 case V4L2_CID_BRIGHTNESS:
1225 bt848_bright(btv,c->value);
1226 break;
1227 case V4L2_CID_HUE:
1228 bt848_hue(btv,c->value);
1229 break;
1230 case V4L2_CID_CONTRAST:
1231 bt848_contrast(btv,c->value);
1232 break;
1233 case V4L2_CID_SATURATION:
1234 bt848_sat(btv,c->value);
1235 break;
1236 case V4L2_CID_AUDIO_MUTE:
1237 if (c->value) {
1238 va.flags |= VIDEO_AUDIO_MUTE;
1239 audio_mux(btv, AUDIO_MUTE);
1240 } else {
1241 va.flags &= ~VIDEO_AUDIO_MUTE;
1242 audio_mux(btv, AUDIO_UNMUTE);
1243 }
1244 break;
1245
1246 case V4L2_CID_AUDIO_VOLUME:
1247 va.volume = c->value;
1248 break;
1249 case V4L2_CID_AUDIO_BALANCE:
1250 va.balance = c->value;
1251 break;
1252 case V4L2_CID_AUDIO_BASS:
1253 va.bass = c->value;
1254 break;
1255 case V4L2_CID_AUDIO_TREBLE:
1256 va.treble = c->value;
1257 break;
1258
1259 case V4L2_CID_PRIVATE_CHROMA_AGC:
1260 btv->opt_chroma_agc = c->value;
1261 val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
1262 btwrite(val, BT848_E_SCLOOP);
1263 btwrite(val, BT848_O_SCLOOP);
1264 break;
1265 case V4L2_CID_PRIVATE_COMBFILTER:
1266 btv->opt_combfilter = c->value;
1267 break;
1268 case V4L2_CID_PRIVATE_LUMAFILTER:
1269 btv->opt_lumafilter = c->value;
1270 if (btv->opt_lumafilter) {
1271 btand(~BT848_CONTROL_LDEC, BT848_E_CONTROL);
1272 btand(~BT848_CONTROL_LDEC, BT848_O_CONTROL);
1273 } else {
1274 btor(BT848_CONTROL_LDEC, BT848_E_CONTROL);
1275 btor(BT848_CONTROL_LDEC, BT848_O_CONTROL);
1276 }
1277 break;
1278 case V4L2_CID_PRIVATE_AUTOMUTE:
1279 btv->opt_automute = c->value;
1280 break;
1281 case V4L2_CID_PRIVATE_AGC_CRUSH:
1282 btv->opt_adc_crush = c->value;
1283 btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
1284 BT848_ADC);
1285 break;
1286 case V4L2_CID_PRIVATE_VCR_HACK:
1287 btv->opt_vcr_hack = c->value;
1288 break;
1289 case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
1290 btv->opt_whitecrush_upper = c->value;
1291 btwrite(c->value, BT848_WC_UP);
1292 break;
1293 case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
1294 btv->opt_whitecrush_lower = c->value;
1295 btwrite(c->value, BT848_WC_DOWN);
1296 break;
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -07001297 case V4L2_CID_PRIVATE_UV_RATIO:
1298 btv->opt_uv_ratio = c->value;
1299 bt848_sat(btv, btv->saturation);
1300 break;
1301 case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
1302 btv->opt_full_luma_range = c->value;
1303 btaor((c->value<<7), ~BT848_OFORM_RANGE, BT848_OFORM);
1304 break;
1305 case V4L2_CID_PRIVATE_CORING:
1306 btv->opt_coring = c->value;
1307 btaor((c->value<<5), ~BT848_OFORM_CORE32, BT848_OFORM);
1308 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 default:
1310 return -EINVAL;
1311 }
1312 if (i >= 4 && i <= 8) {
1313 bttv_call_i2c_clients(btv, VIDIOCSAUDIO, &va);
1314 if (btv->audio_hook)
1315 btv->audio_hook(btv,&va,1);
1316 }
1317 return 0;
1318}
1319
1320/* ----------------------------------------------------------------------- */
1321
1322void bttv_gpio_tracking(struct bttv *btv, char *comment)
1323{
1324 unsigned int outbits, data;
1325 outbits = btread(BT848_GPIO_OUT_EN);
1326 data = btread(BT848_GPIO_DATA);
1327 printk(KERN_DEBUG "bttv%d: gpio: en=%08x, out=%08x in=%08x [%s]\n",
1328 btv->c.nr,outbits,data & outbits, data & ~outbits, comment);
1329}
1330
1331static void bttv_field_count(struct bttv *btv)
1332{
1333 int need_count = 0;
1334
1335 if (btv->users)
1336 need_count++;
1337
1338 if (need_count) {
1339 /* start field counter */
1340 btor(BT848_INT_VSYNC,BT848_INT_MASK);
1341 } else {
1342 /* stop field counter */
1343 btand(~BT848_INT_VSYNC,BT848_INT_MASK);
1344 btv->field_count = 0;
1345 }
1346}
1347
1348static const struct bttv_format*
1349format_by_palette(int palette)
1350{
1351 unsigned int i;
1352
1353 for (i = 0; i < BTTV_FORMATS; i++) {
1354 if (-1 == bttv_formats[i].palette)
1355 continue;
1356 if (bttv_formats[i].palette == palette)
1357 return bttv_formats+i;
1358 }
1359 return NULL;
1360}
1361
1362static const struct bttv_format*
1363format_by_fourcc(int fourcc)
1364{
1365 unsigned int i;
1366
1367 for (i = 0; i < BTTV_FORMATS; i++) {
1368 if (-1 == bttv_formats[i].fourcc)
1369 continue;
1370 if (bttv_formats[i].fourcc == fourcc)
1371 return bttv_formats+i;
1372 }
1373 return NULL;
1374}
1375
1376/* ----------------------------------------------------------------------- */
1377/* misc helpers */
1378
1379static int
1380bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh,
1381 struct bttv_buffer *new)
1382{
1383 struct bttv_buffer *old;
1384 unsigned long flags;
1385 int retval = 0;
1386
1387 dprintk("switch_overlay: enter [new=%p]\n",new);
1388 if (new)
1389 new->vb.state = STATE_DONE;
1390 spin_lock_irqsave(&btv->s_lock,flags);
1391 old = btv->screen;
1392 btv->screen = new;
1393 btv->loop_irq |= 1;
1394 bttv_set_dma(btv, 0x03);
1395 spin_unlock_irqrestore(&btv->s_lock,flags);
1396 if (NULL == new)
1397 free_btres(btv,fh,RESOURCE_OVERLAY);
1398 if (NULL != old) {
1399 dprintk("switch_overlay: old=%p state is %d\n",old,old->vb.state);
1400 bttv_dma_free(btv, old);
1401 kfree(old);
1402 }
1403 dprintk("switch_overlay: done\n");
1404 return retval;
1405}
1406
1407/* ----------------------------------------------------------------------- */
1408/* video4linux (1) interface */
1409
1410static int bttv_prepare_buffer(struct bttv *btv, struct bttv_buffer *buf,
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001411 const struct bttv_format *fmt,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412 unsigned int width, unsigned int height,
1413 enum v4l2_field field)
1414{
1415 int redo_dma_risc = 0;
1416 int rc;
1417
1418 /* check settings */
1419 if (NULL == fmt)
1420 return -EINVAL;
1421 if (fmt->btformat == BT848_COLOR_FMT_RAW) {
1422 width = RAW_BPL;
1423 height = RAW_LINES*2;
1424 if (width*height > buf->vb.bsize)
1425 return -EINVAL;
1426 buf->vb.size = buf->vb.bsize;
1427 } else {
1428 if (width < 48 ||
1429 height < 32 ||
1430 width > bttv_tvnorms[btv->tvnorm].swidth ||
1431 height > bttv_tvnorms[btv->tvnorm].sheight)
1432 return -EINVAL;
1433 buf->vb.size = (width * height * fmt->depth) >> 3;
1434 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
1435 return -EINVAL;
1436 }
1437
1438 /* alloc + fill struct bttv_buffer (if changed) */
1439 if (buf->vb.width != width || buf->vb.height != height ||
1440 buf->vb.field != field ||
1441 buf->tvnorm != btv->tvnorm || buf->fmt != fmt) {
1442 buf->vb.width = width;
1443 buf->vb.height = height;
1444 buf->vb.field = field;
1445 buf->tvnorm = btv->tvnorm;
1446 buf->fmt = fmt;
1447 redo_dma_risc = 1;
1448 }
1449
1450 /* alloc risc memory */
1451 if (STATE_NEEDS_INIT == buf->vb.state) {
1452 redo_dma_risc = 1;
1453 if (0 != (rc = videobuf_iolock(btv->c.pci,&buf->vb,&btv->fbuf)))
1454 goto fail;
1455 }
1456
1457 if (redo_dma_risc)
1458 if (0 != (rc = bttv_buffer_risc(btv,buf)))
1459 goto fail;
1460
1461 buf->vb.state = STATE_PREPARED;
1462 return 0;
1463
1464 fail:
1465 bttv_dma_free(btv,buf);
1466 return rc;
1467}
1468
1469static int
1470buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
1471{
1472 struct bttv_fh *fh = q->priv_data;
1473
1474 *size = fh->fmt->depth*fh->width*fh->height >> 3;
1475 if (0 == *count)
1476 *count = gbuffers;
1477 while (*size * *count > gbuffers * gbufsize)
1478 (*count)--;
1479 return 0;
1480}
1481
1482static int
1483buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
1484 enum v4l2_field field)
1485{
1486 struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
1487 struct bttv_fh *fh = q->priv_data;
1488
1489 return bttv_prepare_buffer(fh->btv, buf, fh->fmt,
1490 fh->width, fh->height, field);
1491}
1492
1493static void
1494buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
1495{
1496 struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
1497 struct bttv_fh *fh = q->priv_data;
1498 struct bttv *btv = fh->btv;
1499
1500 buf->vb.state = STATE_QUEUED;
1501 list_add_tail(&buf->vb.queue,&btv->capture);
1502 if (!btv->curr.frame_irq) {
1503 btv->loop_irq |= 1;
1504 bttv_set_dma(btv, 0x03);
1505 }
1506}
1507
1508static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
1509{
1510 struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
1511 struct bttv_fh *fh = q->priv_data;
1512
1513 bttv_dma_free(fh->btv,buf);
1514}
1515
1516static struct videobuf_queue_ops bttv_video_qops = {
1517 .buf_setup = buffer_setup,
1518 .buf_prepare = buffer_prepare,
1519 .buf_queue = buffer_queue,
1520 .buf_release = buffer_release,
1521};
1522
1523static const char *v4l1_ioctls[] = {
1524 "?", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT", "SPICT",
1525 "CCAPTURE", "GWIN", "SWIN", "GFBUF", "SFBUF", "KEY", "GFREQ",
1526 "SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT",
1527 "GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO",
1528 "SMICROCODE", "GVBIFMT", "SVBIFMT" };
1529#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
1530
1531static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
1532{
1533 switch (cmd) {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001534 case BTTV_VERSION:
1535 return BTTV_VERSION_CODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536
1537 /* *** v4l1 *** ************************************************ */
1538 case VIDIOCGFREQ:
1539 {
1540 unsigned long *freq = arg;
1541 *freq = btv->freq;
1542 return 0;
1543 }
1544 case VIDIOCSFREQ:
1545 {
1546 unsigned long *freq = arg;
1547 down(&btv->lock);
1548 btv->freq=*freq;
1549 bttv_call_i2c_clients(btv,VIDIOCSFREQ,freq);
1550 if (btv->has_matchbox && btv->radio_user)
1551 tea5757_set_freq(btv,*freq);
1552 up(&btv->lock);
1553 return 0;
1554 }
1555
1556 case VIDIOCGTUNER:
1557 {
1558 struct video_tuner *v = arg;
1559
1560 if (UNSET == bttv_tvcards[btv->c.type].tuner)
1561 return -EINVAL;
1562 if (v->tuner) /* Only tuner 0 */
1563 return -EINVAL;
1564 strcpy(v->name, "Television");
1565 v->rangelow = 0;
1566 v->rangehigh = 0x7FFFFFFF;
1567 v->flags = VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM;
1568 v->mode = btv->tvnorm;
1569 v->signal = (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC) ? 0xFFFF : 0;
1570 bttv_call_i2c_clients(btv,cmd,v);
1571 return 0;
1572 }
1573 case VIDIOCSTUNER:
1574 {
1575 struct video_tuner *v = arg;
1576
1577 if (v->tuner) /* Only tuner 0 */
1578 return -EINVAL;
1579 if (v->mode >= BTTV_TVNORMS)
1580 return -EINVAL;
1581
1582 down(&btv->lock);
1583 set_tvnorm(btv,v->mode);
1584 bttv_call_i2c_clients(btv,cmd,v);
1585 up(&btv->lock);
1586 return 0;
1587 }
1588
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001589 case VIDIOCGCHAN:
1590 {
1591 struct video_channel *v = arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 unsigned int channel = v->channel;
1593
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001594 if (channel >= bttv_tvcards[btv->c.type].video_inputs)
1595 return -EINVAL;
1596 v->tuners=0;
1597 v->flags = VIDEO_VC_AUDIO;
1598 v->type = VIDEO_TYPE_CAMERA;
1599 v->norm = btv->tvnorm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600 if (channel == bttv_tvcards[btv->c.type].tuner) {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001601 strcpy(v->name,"Television");
1602 v->flags|=VIDEO_VC_TUNER;
1603 v->type=VIDEO_TYPE_TV;
1604 v->tuners=1;
1605 } else if (channel == btv->svhs) {
1606 strcpy(v->name,"S-Video");
1607 } else {
1608 sprintf(v->name,"Composite%d",channel);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609 }
1610 return 0;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001611 }
1612 case VIDIOCSCHAN:
1613 {
1614 struct video_channel *v = arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615 unsigned int channel = v->channel;
1616
1617 if (channel >= bttv_tvcards[btv->c.type].video_inputs)
1618 return -EINVAL;
1619 if (v->norm >= BTTV_TVNORMS)
1620 return -EINVAL;
1621
1622 down(&btv->lock);
1623 if (channel == btv->input &&
1624 v->norm == btv->tvnorm) {
1625 /* nothing to do */
1626 up(&btv->lock);
1627 return 0;
1628 }
1629
1630 btv->tvnorm = v->norm;
1631 set_input(btv,v->channel);
1632 up(&btv->lock);
1633 return 0;
1634 }
1635
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001636 case VIDIOCGAUDIO:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637 {
1638 struct video_audio *v = arg;
1639
1640 memset(v,0,sizeof(*v));
1641 strcpy(v->name,"Television");
1642 v->flags |= VIDEO_AUDIO_MUTABLE;
1643 v->mode = VIDEO_SOUND_MONO;
1644
1645 down(&btv->lock);
1646 bttv_call_i2c_clients(btv,cmd,v);
1647
1648 /* card specific hooks */
1649 if (btv->audio_hook)
1650 btv->audio_hook(btv,v,0);
1651
1652 up(&btv->lock);
1653 return 0;
1654 }
1655 case VIDIOCSAUDIO:
1656 {
1657 struct video_audio *v = arg;
1658 unsigned int audio = v->audio;
1659
1660 if (audio >= bttv_tvcards[btv->c.type].audio_inputs)
1661 return -EINVAL;
1662
1663 down(&btv->lock);
1664 audio_mux(btv, (v->flags&VIDEO_AUDIO_MUTE) ? AUDIO_MUTE : AUDIO_UNMUTE);
1665 bttv_call_i2c_clients(btv,cmd,v);
1666
1667 /* card specific hooks */
1668 if (btv->audio_hook)
1669 btv->audio_hook(btv,v,1);
1670
1671 up(&btv->lock);
1672 return 0;
1673 }
1674
1675 /* *** v4l2 *** ************************************************ */
1676 case VIDIOC_ENUMSTD:
1677 {
1678 struct v4l2_standard *e = arg;
1679 unsigned int index = e->index;
1680
1681 if (index >= BTTV_TVNORMS)
1682 return -EINVAL;
1683 v4l2_video_std_construct(e, bttv_tvnorms[e->index].v4l2_id,
1684 bttv_tvnorms[e->index].name);
1685 e->index = index;
1686 return 0;
1687 }
1688 case VIDIOC_G_STD:
1689 {
1690 v4l2_std_id *id = arg;
1691 *id = bttv_tvnorms[btv->tvnorm].v4l2_id;
1692 return 0;
1693 }
1694 case VIDIOC_S_STD:
1695 {
1696 v4l2_std_id *id = arg;
1697 unsigned int i;
1698
1699 for (i = 0; i < BTTV_TVNORMS; i++)
1700 if (*id & bttv_tvnorms[i].v4l2_id)
1701 break;
1702 if (i == BTTV_TVNORMS)
1703 return -EINVAL;
1704
1705 down(&btv->lock);
1706 set_tvnorm(btv,i);
1707 i2c_vidiocschan(btv);
1708 up(&btv->lock);
1709 return 0;
1710 }
1711 case VIDIOC_QUERYSTD:
1712 {
1713 v4l2_std_id *id = arg;
1714
1715 if (btread(BT848_DSTATUS) & BT848_DSTATUS_NUML)
1716 *id = V4L2_STD_625_50;
1717 else
1718 *id = V4L2_STD_525_60;
1719 return 0;
1720 }
1721
1722 case VIDIOC_ENUMINPUT:
1723 {
1724 struct v4l2_input *i = arg;
1725 unsigned int n;
1726
1727 n = i->index;
1728 if (n >= bttv_tvcards[btv->c.type].video_inputs)
1729 return -EINVAL;
1730 memset(i,0,sizeof(*i));
1731 i->index = n;
1732 i->type = V4L2_INPUT_TYPE_CAMERA;
Michael H. Schimekbbf78712005-12-01 00:51:40 -08001733 i->audioset = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734 if (i->index == bttv_tvcards[btv->c.type].tuner) {
1735 sprintf(i->name, "Television");
1736 i->type = V4L2_INPUT_TYPE_TUNER;
1737 i->tuner = 0;
1738 } else if (i->index == btv->svhs) {
1739 sprintf(i->name, "S-Video");
1740 } else {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001741 sprintf(i->name,"Composite%d",i->index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742 }
1743 if (i->index == btv->input) {
1744 __u32 dstatus = btread(BT848_DSTATUS);
1745 if (0 == (dstatus & BT848_DSTATUS_PRES))
1746 i->status |= V4L2_IN_ST_NO_SIGNAL;
1747 if (0 == (dstatus & BT848_DSTATUS_HLOC))
1748 i->status |= V4L2_IN_ST_NO_H_LOCK;
1749 }
1750 for (n = 0; n < BTTV_TVNORMS; n++)
1751 i->std |= bttv_tvnorms[n].v4l2_id;
1752 return 0;
1753 }
1754 case VIDIOC_G_INPUT:
1755 {
1756 int *i = arg;
1757 *i = btv->input;
1758 return 0;
1759 }
1760 case VIDIOC_S_INPUT:
1761 {
1762 unsigned int *i = arg;
1763
1764 if (*i > bttv_tvcards[btv->c.type].video_inputs)
1765 return -EINVAL;
1766 down(&btv->lock);
1767 set_input(btv,*i);
1768 up(&btv->lock);
1769 return 0;
1770 }
1771
1772 case VIDIOC_G_TUNER:
1773 {
1774 struct v4l2_tuner *t = arg;
1775
1776 if (UNSET == bttv_tvcards[btv->c.type].tuner)
1777 return -EINVAL;
1778 if (0 != t->index)
1779 return -EINVAL;
1780 down(&btv->lock);
1781 memset(t,0,sizeof(*t));
1782 strcpy(t->name, "Television");
1783 t->type = V4L2_TUNER_ANALOG_TV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001784 t->capability = V4L2_TUNER_CAP_NORM;
1785 t->rxsubchans = V4L2_TUNER_SUB_MONO;
1786 if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)
1787 t->signal = 0xffff;
1788 {
Michael H. Schimekbbf78712005-12-01 00:51:40 -08001789 struct video_tuner tuner;
1790
1791 memset(&tuner, 0, sizeof (tuner));
1792 tuner.rangehigh = 0xffffffffUL;
1793 bttv_call_i2c_clients(btv, VIDIOCGTUNER, &tuner);
1794 t->rangelow = tuner.rangelow;
1795 t->rangehigh = tuner.rangehigh;
1796 }
1797 {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798 /* Hmmm ... */
1799 struct video_audio va;
1800 memset(&va, 0, sizeof(struct video_audio));
1801 bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
1802 if (btv->audio_hook)
1803 btv->audio_hook(btv,&va,0);
1804 if(va.mode & VIDEO_SOUND_STEREO) {
1805 t->audmode = V4L2_TUNER_MODE_STEREO;
1806 t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
1807 }
1808 if(va.mode & VIDEO_SOUND_LANG1) {
1809 t->audmode = V4L2_TUNER_MODE_LANG1;
1810 t->rxsubchans = V4L2_TUNER_SUB_LANG1
1811 | V4L2_TUNER_SUB_LANG2;
1812 }
1813 }
1814 /* FIXME: fill capability+audmode */
1815 up(&btv->lock);
1816 return 0;
1817 }
1818 case VIDIOC_S_TUNER:
1819 {
1820 struct v4l2_tuner *t = arg;
1821
1822 if (UNSET == bttv_tvcards[btv->c.type].tuner)
1823 return -EINVAL;
1824 if (0 != t->index)
1825 return -EINVAL;
1826 down(&btv->lock);
1827 {
1828 struct video_audio va;
1829 memset(&va, 0, sizeof(struct video_audio));
1830 bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
1831 if (t->audmode == V4L2_TUNER_MODE_MONO)
1832 va.mode = VIDEO_SOUND_MONO;
1833 else if (t->audmode == V4L2_TUNER_MODE_STEREO)
1834 va.mode = VIDEO_SOUND_STEREO;
1835 else if (t->audmode == V4L2_TUNER_MODE_LANG1)
1836 va.mode = VIDEO_SOUND_LANG1;
1837 else if (t->audmode == V4L2_TUNER_MODE_LANG2)
1838 va.mode = VIDEO_SOUND_LANG2;
1839 bttv_call_i2c_clients(btv, VIDIOCSAUDIO, &va);
1840 if (btv->audio_hook)
1841 btv->audio_hook(btv,&va,1);
1842 }
1843 up(&btv->lock);
1844 return 0;
1845 }
1846
1847 case VIDIOC_G_FREQUENCY:
1848 {
1849 struct v4l2_frequency *f = arg;
1850
1851 memset(f,0,sizeof(*f));
1852 f->type = V4L2_TUNER_ANALOG_TV;
1853 f->frequency = btv->freq;
1854 return 0;
1855 }
1856 case VIDIOC_S_FREQUENCY:
1857 {
1858 struct v4l2_frequency *f = arg;
1859
1860 if (unlikely(f->tuner != 0))
1861 return -EINVAL;
Mauro Carvalho Chehabfa9846a2005-07-12 13:58:42 -07001862 if (unlikely (f->type != V4L2_TUNER_ANALOG_TV))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863 return -EINVAL;
1864 down(&btv->lock);
1865 btv->freq = f->frequency;
1866 bttv_call_i2c_clients(btv,VIDIOCSFREQ,&btv->freq);
1867 if (btv->has_matchbox && btv->radio_user)
1868 tea5757_set_freq(btv,btv->freq);
1869 up(&btv->lock);
1870 return 0;
1871 }
Hans Verkuil299392b2005-11-08 21:37:42 -08001872 case VIDIOC_LOG_STATUS:
1873 {
Luiz Capitulino97cb4452005-12-01 00:51:24 -08001874 bttv_call_i2c_clients(btv, VIDIOC_LOG_STATUS, NULL);
Hans Verkuil299392b2005-11-08 21:37:42 -08001875 return 0;
1876 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877
1878 default:
1879 return -ENOIOCTLCMD;
1880
1881 }
1882 return 0;
1883}
1884
1885static int verify_window(const struct bttv_tvnorm *tvn,
1886 struct v4l2_window *win, int fixup)
1887{
1888 enum v4l2_field field;
1889 int maxw, maxh;
1890
1891 if (win->w.width < 48 || win->w.height < 32)
1892 return -EINVAL;
1893 if (win->clipcount > 2048)
1894 return -EINVAL;
1895
1896 field = win->field;
1897 maxw = tvn->swidth;
1898 maxh = tvn->sheight;
1899
1900 if (V4L2_FIELD_ANY == field) {
1901 field = (win->w.height > maxh/2)
1902 ? V4L2_FIELD_INTERLACED
1903 : V4L2_FIELD_TOP;
1904 }
1905 switch (field) {
1906 case V4L2_FIELD_TOP:
1907 case V4L2_FIELD_BOTTOM:
1908 maxh = maxh / 2;
1909 break;
1910 case V4L2_FIELD_INTERLACED:
1911 break;
1912 default:
1913 return -EINVAL;
1914 }
1915
1916 if (!fixup && (win->w.width > maxw || win->w.height > maxh))
1917 return -EINVAL;
1918
1919 if (win->w.width > maxw)
1920 win->w.width = maxw;
1921 if (win->w.height > maxh)
1922 win->w.height = maxh;
1923 win->field = field;
1924 return 0;
1925}
1926
1927static int setup_window(struct bttv_fh *fh, struct bttv *btv,
1928 struct v4l2_window *win, int fixup)
1929{
1930 struct v4l2_clip *clips = NULL;
1931 int n,size,retval = 0;
1932
1933 if (NULL == fh->ovfmt)
1934 return -EINVAL;
1935 if (!(fh->ovfmt->flags & FORMAT_FLAGS_PACKED))
1936 return -EINVAL;
1937 retval = verify_window(&bttv_tvnorms[btv->tvnorm],win,fixup);
1938 if (0 != retval)
1939 return retval;
1940
1941 /* copy clips -- luckily v4l1 + v4l2 are binary
1942 compatible here ...*/
1943 n = win->clipcount;
1944 size = sizeof(*clips)*(n+4);
1945 clips = kmalloc(size,GFP_KERNEL);
1946 if (NULL == clips)
1947 return -ENOMEM;
1948 if (n > 0) {
1949 if (copy_from_user(clips,win->clips,sizeof(struct v4l2_clip)*n)) {
1950 kfree(clips);
1951 return -EFAULT;
1952 }
1953 }
1954 /* clip against screen */
1955 if (NULL != btv->fbuf.base)
1956 n = btcx_screen_clips(btv->fbuf.fmt.width, btv->fbuf.fmt.height,
1957 &win->w, clips, n);
1958 btcx_sort_clips(clips,n);
1959
1960 /* 4-byte alignments */
1961 switch (fh->ovfmt->depth) {
1962 case 8:
1963 case 24:
1964 btcx_align(&win->w, clips, n, 3);
1965 break;
1966 case 16:
1967 btcx_align(&win->w, clips, n, 1);
1968 break;
1969 case 32:
1970 /* no alignment fixups needed */
1971 break;
1972 default:
1973 BUG();
1974 }
1975
1976 down(&fh->cap.lock);
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -08001977 kfree(fh->ov.clips);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978 fh->ov.clips = clips;
1979 fh->ov.nclips = n;
1980
1981 fh->ov.w = win->w;
1982 fh->ov.field = win->field;
1983 fh->ov.setup_ok = 1;
1984 btv->init.ov.w.width = win->w.width;
1985 btv->init.ov.w.height = win->w.height;
1986 btv->init.ov.field = win->field;
1987
1988 /* update overlay if needed */
1989 retval = 0;
1990 if (check_btres(fh, RESOURCE_OVERLAY)) {
1991 struct bttv_buffer *new;
1992
1993 new = videobuf_alloc(sizeof(*new));
1994 bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
1995 retval = bttv_switch_overlay(btv,fh,new);
1996 }
1997 up(&fh->cap.lock);
1998 return retval;
1999}
2000
2001/* ----------------------------------------------------------------------- */
2002
2003static struct videobuf_queue* bttv_queue(struct bttv_fh *fh)
2004{
2005 struct videobuf_queue* q = NULL;
2006
2007 switch (fh->type) {
2008 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2009 q = &fh->cap;
2010 break;
2011 case V4L2_BUF_TYPE_VBI_CAPTURE:
2012 q = &fh->vbi;
2013 break;
2014 default:
2015 BUG();
2016 }
2017 return q;
2018}
2019
2020static int bttv_resource(struct bttv_fh *fh)
2021{
2022 int res = 0;
2023
2024 switch (fh->type) {
2025 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2026 res = RESOURCE_VIDEO;
2027 break;
2028 case V4L2_BUF_TYPE_VBI_CAPTURE:
2029 res = RESOURCE_VBI;
2030 break;
2031 default:
2032 BUG();
2033 }
2034 return res;
2035}
2036
2037static int bttv_switch_type(struct bttv_fh *fh, enum v4l2_buf_type type)
2038{
2039 struct videobuf_queue *q = bttv_queue(fh);
2040 int res = bttv_resource(fh);
2041
2042 if (check_btres(fh,res))
2043 return -EBUSY;
2044 if (videobuf_queue_is_busy(q))
2045 return -EBUSY;
2046 fh->type = type;
2047 return 0;
2048}
2049
Michael H. Schimekc87c9482005-12-01 00:51:33 -08002050static void
2051pix_format_set_size (struct v4l2_pix_format * f,
2052 const struct bttv_format * fmt,
2053 unsigned int width,
2054 unsigned int height)
2055{
2056 f->width = width;
2057 f->height = height;
2058
2059 if (fmt->flags & FORMAT_FLAGS_PLANAR) {
2060 f->bytesperline = width; /* Y plane */
2061 f->sizeimage = (width * height * fmt->depth) >> 3;
2062 } else {
2063 f->bytesperline = (width * fmt->depth) >> 3;
2064 f->sizeimage = height * f->bytesperline;
2065 }
2066}
2067
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068static int bttv_g_fmt(struct bttv_fh *fh, struct v4l2_format *f)
2069{
2070 switch (f->type) {
2071 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2072 memset(&f->fmt.pix,0,sizeof(struct v4l2_pix_format));
Michael H. Schimekc87c9482005-12-01 00:51:33 -08002073 pix_format_set_size (&f->fmt.pix, fh->fmt,
2074 fh->width, fh->height);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075 f->fmt.pix.field = fh->cap.field;
2076 f->fmt.pix.pixelformat = fh->fmt->fourcc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077 return 0;
2078 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
2079 memset(&f->fmt.win,0,sizeof(struct v4l2_window));
2080 f->fmt.win.w = fh->ov.w;
2081 f->fmt.win.field = fh->ov.field;
2082 return 0;
2083 case V4L2_BUF_TYPE_VBI_CAPTURE:
2084 bttv_vbi_get_fmt(fh,f);
2085 return 0;
2086 default:
2087 return -EINVAL;
2088 }
2089}
2090
2091static int bttv_try_fmt(struct bttv_fh *fh, struct bttv *btv,
2092 struct v4l2_format *f)
2093{
2094 switch (f->type) {
2095 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2096 {
2097 const struct bttv_format *fmt;
2098 enum v4l2_field field;
2099 unsigned int maxw,maxh;
2100
2101 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
2102 if (NULL == fmt)
2103 return -EINVAL;
2104
2105 /* fixup format */
2106 maxw = bttv_tvnorms[btv->tvnorm].swidth;
2107 maxh = bttv_tvnorms[btv->tvnorm].sheight;
2108 field = f->fmt.pix.field;
2109 if (V4L2_FIELD_ANY == field)
2110 field = (f->fmt.pix.height > maxh/2)
2111 ? V4L2_FIELD_INTERLACED
2112 : V4L2_FIELD_BOTTOM;
2113 if (V4L2_FIELD_SEQ_BT == field)
2114 field = V4L2_FIELD_SEQ_TB;
2115 switch (field) {
2116 case V4L2_FIELD_TOP:
2117 case V4L2_FIELD_BOTTOM:
2118 case V4L2_FIELD_ALTERNATE:
2119 maxh = maxh/2;
2120 break;
2121 case V4L2_FIELD_INTERLACED:
2122 break;
2123 case V4L2_FIELD_SEQ_TB:
2124 if (fmt->flags & FORMAT_FLAGS_PLANAR)
2125 return -EINVAL;
2126 break;
2127 default:
2128 return -EINVAL;
2129 }
2130
2131 /* update data for the application */
2132 f->fmt.pix.field = field;
2133 if (f->fmt.pix.width < 48)
2134 f->fmt.pix.width = 48;
2135 if (f->fmt.pix.height < 32)
2136 f->fmt.pix.height = 32;
2137 if (f->fmt.pix.width > maxw)
2138 f->fmt.pix.width = maxw;
2139 if (f->fmt.pix.height > maxh)
2140 f->fmt.pix.height = maxh;
Michael H. Schimekc87c9482005-12-01 00:51:33 -08002141 pix_format_set_size (&f->fmt.pix, fmt,
2142 f->fmt.pix.width & ~3,
2143 f->fmt.pix.height);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144
2145 return 0;
2146 }
2147 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
2148 return verify_window(&bttv_tvnorms[btv->tvnorm],
2149 &f->fmt.win, 1);
2150 case V4L2_BUF_TYPE_VBI_CAPTURE:
2151 bttv_vbi_try_fmt(fh,f);
2152 return 0;
2153 default:
2154 return -EINVAL;
2155 }
2156}
2157
2158static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv,
2159 struct v4l2_format *f)
2160{
2161 int retval;
2162
2163 switch (f->type) {
2164 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2165 {
2166 const struct bttv_format *fmt;
2167
2168 retval = bttv_switch_type(fh,f->type);
2169 if (0 != retval)
2170 return retval;
2171 retval = bttv_try_fmt(fh,btv,f);
2172 if (0 != retval)
2173 return retval;
2174 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
2175
2176 /* update our state informations */
2177 down(&fh->cap.lock);
2178 fh->fmt = fmt;
2179 fh->cap.field = f->fmt.pix.field;
2180 fh->cap.last = V4L2_FIELD_NONE;
2181 fh->width = f->fmt.pix.width;
2182 fh->height = f->fmt.pix.height;
2183 btv->init.fmt = fmt;
2184 btv->init.width = f->fmt.pix.width;
2185 btv->init.height = f->fmt.pix.height;
2186 up(&fh->cap.lock);
2187
2188 return 0;
2189 }
2190 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07002191 if (no_overlay > 0) {
2192 printk ("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
2193 return -EINVAL;
2194 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195 return setup_window(fh, btv, &f->fmt.win, 1);
2196 case V4L2_BUF_TYPE_VBI_CAPTURE:
2197 retval = bttv_switch_type(fh,f->type);
2198 if (0 != retval)
2199 return retval;
2200 if (locked_btres(fh->btv, RESOURCE_VBI))
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08002201 return -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202 bttv_vbi_try_fmt(fh,f);
2203 bttv_vbi_setlines(fh,btv,f->fmt.vbi.count[0]);
2204 bttv_vbi_get_fmt(fh,f);
2205 return 0;
2206 default:
2207 return -EINVAL;
2208 }
2209}
2210
2211static int bttv_do_ioctl(struct inode *inode, struct file *file,
2212 unsigned int cmd, void *arg)
2213{
2214 struct bttv_fh *fh = file->private_data;
2215 struct bttv *btv = fh->btv;
2216 unsigned long flags;
2217 int retval = 0;
2218
2219 if (bttv_debug > 1) {
2220 switch (_IOC_TYPE(cmd)) {
2221 case 'v':
2222 printk("bttv%d: ioctl 0x%x (v4l1, VIDIOC%s)\n",
2223 btv->c.nr, cmd, (_IOC_NR(cmd) < V4L1_IOCTLS) ?
2224 v4l1_ioctls[_IOC_NR(cmd)] : "???");
2225 break;
2226 case 'V':
2227 printk("bttv%d: ioctl 0x%x (v4l2, %s)\n",
2228 btv->c.nr, cmd, v4l2_ioctl_names[_IOC_NR(cmd)]);
2229 break;
2230 default:
2231 printk("bttv%d: ioctl 0x%x (???)\n",
2232 btv->c.nr, cmd);
2233 }
2234 }
2235 if (btv->errors)
2236 bttv_reinit_bt848(btv);
2237
2238 switch (cmd) {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08002239 case VIDIOCSFREQ:
2240 case VIDIOCSTUNER:
2241 case VIDIOCSCHAN:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242 case VIDIOC_S_CTRL:
2243 case VIDIOC_S_STD:
2244 case VIDIOC_S_INPUT:
2245 case VIDIOC_S_TUNER:
2246 case VIDIOC_S_FREQUENCY:
2247 retval = v4l2_prio_check(&btv->prio,&fh->prio);
2248 if (0 != retval)
2249 return retval;
2250 };
2251
2252 switch (cmd) {
2253
2254 /* *** v4l1 *** ************************************************ */
2255 case VIDIOCGCAP:
2256 {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08002257 struct video_capability *cap = arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258
2259 memset(cap,0,sizeof(*cap));
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08002260 strcpy(cap->name,btv->video_dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261 if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
2262 /* vbi */
2263 cap->type = VID_TYPE_TUNER|VID_TYPE_TELETEXT;
2264 } else {
2265 /* others */
2266 cap->type = VID_TYPE_CAPTURE|
2267 VID_TYPE_TUNER|
Linus Torvalds1da177e2005-04-16 15:20:36 -07002268 VID_TYPE_CLIPPING|
2269 VID_TYPE_SCALES;
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07002270 if (no_overlay <= 0)
2271 cap->type |= VID_TYPE_OVERLAY;
2272
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273 cap->maxwidth = bttv_tvnorms[btv->tvnorm].swidth;
2274 cap->maxheight = bttv_tvnorms[btv->tvnorm].sheight;
2275 cap->minwidth = 48;
2276 cap->minheight = 32;
2277 }
2278 cap->channels = bttv_tvcards[btv->c.type].video_inputs;
2279 cap->audios = bttv_tvcards[btv->c.type].audio_inputs;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08002280 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002281 }
2282
2283 case VIDIOCGPICT:
2284 {
2285 struct video_picture *pic = arg;
2286
2287 memset(pic,0,sizeof(*pic));
2288 pic->brightness = btv->bright;
2289 pic->contrast = btv->contrast;
2290 pic->hue = btv->hue;
2291 pic->colour = btv->saturation;
2292 if (fh->fmt) {
2293 pic->depth = fh->fmt->depth;
2294 pic->palette = fh->fmt->palette;
2295 }
2296 return 0;
2297 }
2298 case VIDIOCSPICT:
2299 {
2300 struct video_picture *pic = arg;
2301 const struct bttv_format *fmt;
2302
2303 fmt = format_by_palette(pic->palette);
2304 if (NULL == fmt)
2305 return -EINVAL;
2306 down(&fh->cap.lock);
2307 if (fmt->depth != pic->depth) {
2308 retval = -EINVAL;
2309 goto fh_unlock_and_return;
2310 }
Michael H. Schimek13c72802005-12-01 00:51:37 -08002311 if (fmt->flags & FORMAT_FLAGS_RAW) {
2312 /* VIDIOCMCAPTURE uses gbufsize, not RAW_BPL *
2313 RAW_LINES * 2. F1 is stored at offset 0, F2
2314 at buffer size / 2. */
2315 fh->width = RAW_BPL;
2316 fh->height = gbufsize / RAW_BPL;
2317 btv->init.width = RAW_BPL;
2318 btv->init.height = gbufsize / RAW_BPL;
2319 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320 fh->ovfmt = fmt;
2321 fh->fmt = fmt;
2322 btv->init.ovfmt = fmt;
2323 btv->init.fmt = fmt;
2324 if (bigendian) {
2325 /* dirty hack time: swap bytes for overlay if the
2326 display adaptor is big endian (insmod option) */
2327 if (fmt->palette == VIDEO_PALETTE_RGB555 ||
2328 fmt->palette == VIDEO_PALETTE_RGB565 ||
2329 fmt->palette == VIDEO_PALETTE_RGB32) {
2330 fh->ovfmt = fmt+1;
2331 }
2332 }
2333 bt848_bright(btv,pic->brightness);
2334 bt848_contrast(btv,pic->contrast);
2335 bt848_hue(btv,pic->hue);
2336 bt848_sat(btv,pic->colour);
2337 up(&fh->cap.lock);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08002338 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002339 }
2340
2341 case VIDIOCGWIN:
2342 {
2343 struct video_window *win = arg;
2344
2345 memset(win,0,sizeof(*win));
2346 win->x = fh->ov.w.left;
2347 win->y = fh->ov.w.top;
2348 win->width = fh->ov.w.width;
2349 win->height = fh->ov.w.height;
2350 return 0;
2351 }
2352 case VIDIOCSWIN:
2353 {
2354 struct video_window *win = arg;
2355 struct v4l2_window w2;
2356
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07002357 if (no_overlay > 0) {
2358 printk ("VIDIOCSWIN: no_overlay\n");
2359 return -EINVAL;
2360 }
2361
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362 w2.field = V4L2_FIELD_ANY;
2363 w2.w.left = win->x;
2364 w2.w.top = win->y;
2365 w2.w.width = win->width;
2366 w2.w.height = win->height;
2367 w2.clipcount = win->clipcount;
2368 w2.clips = (struct v4l2_clip __user *)win->clips;
2369 retval = setup_window(fh, btv, &w2, 0);
2370 if (0 == retval) {
2371 /* on v4l1 this ioctl affects the read() size too */
2372 fh->width = fh->ov.w.width;
2373 fh->height = fh->ov.w.height;
2374 btv->init.width = fh->ov.w.width;
2375 btv->init.height = fh->ov.w.height;
2376 }
2377 return retval;
2378 }
2379
2380 case VIDIOCGFBUF:
2381 {
2382 struct video_buffer *fbuf = arg;
2383
2384 fbuf->base = btv->fbuf.base;
2385 fbuf->width = btv->fbuf.fmt.width;
2386 fbuf->height = btv->fbuf.fmt.height;
2387 fbuf->bytesperline = btv->fbuf.fmt.bytesperline;
2388 if (fh->ovfmt)
2389 fbuf->depth = fh->ovfmt->depth;
2390 return 0;
2391 }
2392 case VIDIOCSFBUF:
2393 {
2394 struct video_buffer *fbuf = arg;
2395 const struct bttv_format *fmt;
2396 unsigned long end;
2397
2398 if(!capable(CAP_SYS_ADMIN) &&
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08002399 !capable(CAP_SYS_RAWIO))
2400 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401 end = (unsigned long)fbuf->base +
2402 fbuf->height * fbuf->bytesperline;
2403 down(&fh->cap.lock);
2404 retval = -EINVAL;
2405
2406 switch (fbuf->depth) {
2407 case 8:
2408 fmt = format_by_palette(VIDEO_PALETTE_HI240);
2409 break;
2410 case 16:
2411 fmt = format_by_palette(VIDEO_PALETTE_RGB565);
2412 break;
2413 case 24:
2414 fmt = format_by_palette(VIDEO_PALETTE_RGB24);
2415 break;
2416 case 32:
2417 fmt = format_by_palette(VIDEO_PALETTE_RGB32);
2418 break;
2419 case 15:
2420 fbuf->depth = 16;
2421 fmt = format_by_palette(VIDEO_PALETTE_RGB555);
2422 break;
2423 default:
2424 fmt = NULL;
2425 break;
2426 }
2427 if (NULL == fmt)
2428 goto fh_unlock_and_return;
2429
2430 fh->ovfmt = fmt;
2431 fh->fmt = fmt;
2432 btv->init.ovfmt = fmt;
2433 btv->init.fmt = fmt;
2434 btv->fbuf.base = fbuf->base;
2435 btv->fbuf.fmt.width = fbuf->width;
2436 btv->fbuf.fmt.height = fbuf->height;
2437 if (fbuf->bytesperline)
2438 btv->fbuf.fmt.bytesperline = fbuf->bytesperline;
2439 else
2440 btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fbuf->depth/8;
2441 up(&fh->cap.lock);
2442 return 0;
2443 }
2444
2445 case VIDIOCCAPTURE:
2446 case VIDIOC_OVERLAY:
2447 {
2448 struct bttv_buffer *new;
2449 int *on = arg;
2450
2451 if (*on) {
2452 /* verify args */
2453 if (NULL == btv->fbuf.base)
2454 return -EINVAL;
2455 if (!fh->ov.setup_ok) {
2456 dprintk("bttv%d: overlay: !setup_ok\n",btv->c.nr);
2457 return -EINVAL;
2458 }
2459 }
2460
2461 if (!check_alloc_btres(btv,fh,RESOURCE_OVERLAY))
2462 return -EBUSY;
2463
2464 down(&fh->cap.lock);
2465 if (*on) {
2466 fh->ov.tvnorm = btv->tvnorm;
2467 new = videobuf_alloc(sizeof(*new));
2468 bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
2469 } else {
2470 new = NULL;
2471 }
2472
2473 /* switch over */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08002474 retval = bttv_switch_overlay(btv,fh,new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002475 up(&fh->cap.lock);
2476 return retval;
2477 }
2478
2479 case VIDIOCGMBUF:
2480 {
2481 struct video_mbuf *mbuf = arg;
2482 unsigned int i;
2483
2484 down(&fh->cap.lock);
2485 retval = videobuf_mmap_setup(&fh->cap,gbuffers,gbufsize,
2486 V4L2_MEMORY_MMAP);
2487 if (retval < 0)
2488 goto fh_unlock_and_return;
2489 memset(mbuf,0,sizeof(*mbuf));
2490 mbuf->frames = gbuffers;
2491 mbuf->size = gbuffers * gbufsize;
2492 for (i = 0; i < gbuffers; i++)
2493 mbuf->offsets[i] = i * gbufsize;
2494 up(&fh->cap.lock);
2495 return 0;
2496 }
2497 case VIDIOCMCAPTURE:
2498 {
2499 struct video_mmap *vm = arg;
2500 struct bttv_buffer *buf;
2501 enum v4l2_field field;
2502
2503 if (vm->frame >= VIDEO_MAX_FRAME)
2504 return -EINVAL;
2505
2506 down(&fh->cap.lock);
2507 retval = -EINVAL;
2508 buf = (struct bttv_buffer *)fh->cap.bufs[vm->frame];
2509 if (NULL == buf)
2510 goto fh_unlock_and_return;
2511 if (0 == buf->vb.baddr)
2512 goto fh_unlock_and_return;
2513 if (buf->vb.state == STATE_QUEUED ||
2514 buf->vb.state == STATE_ACTIVE)
2515 goto fh_unlock_and_return;
2516
2517 field = (vm->height > bttv_tvnorms[btv->tvnorm].sheight/2)
2518 ? V4L2_FIELD_INTERLACED
2519 : V4L2_FIELD_BOTTOM;
2520 retval = bttv_prepare_buffer(btv,buf,
2521 format_by_palette(vm->format),
2522 vm->width,vm->height,field);
2523 if (0 != retval)
2524 goto fh_unlock_and_return;
2525 spin_lock_irqsave(&btv->s_lock,flags);
2526 buffer_queue(&fh->cap,&buf->vb);
2527 spin_unlock_irqrestore(&btv->s_lock,flags);
2528 up(&fh->cap.lock);
2529 return 0;
2530 }
2531 case VIDIOCSYNC:
2532 {
2533 int *frame = arg;
2534 struct bttv_buffer *buf;
2535
2536 if (*frame >= VIDEO_MAX_FRAME)
2537 return -EINVAL;
2538
2539 down(&fh->cap.lock);
2540 retval = -EINVAL;
2541 buf = (struct bttv_buffer *)fh->cap.bufs[*frame];
2542 if (NULL == buf)
2543 goto fh_unlock_and_return;
2544 retval = videobuf_waiton(&buf->vb,0,1);
2545 if (0 != retval)
2546 goto fh_unlock_and_return;
2547 switch (buf->vb.state) {
2548 case STATE_ERROR:
2549 retval = -EIO;
2550 /* fall through */
2551 case STATE_DONE:
2552 videobuf_dma_pci_sync(btv->c.pci,&buf->vb.dma);
2553 bttv_dma_free(btv,buf);
2554 break;
2555 default:
2556 retval = -EINVAL;
2557 break;
2558 }
2559 up(&fh->cap.lock);
2560 return retval;
2561 }
2562
2563 case VIDIOCGVBIFMT:
2564 {
2565 struct vbi_format *fmt = (void *) arg;
2566 struct v4l2_format fmt2;
2567
2568 if (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE) {
2569 retval = bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE);
2570 if (0 != retval)
2571 return retval;
2572 }
2573 bttv_vbi_get_fmt(fh, &fmt2);
2574
2575 memset(fmt,0,sizeof(*fmt));
2576 fmt->sampling_rate = fmt2.fmt.vbi.sampling_rate;
2577 fmt->samples_per_line = fmt2.fmt.vbi.samples_per_line;
2578 fmt->sample_format = VIDEO_PALETTE_RAW;
2579 fmt->start[0] = fmt2.fmt.vbi.start[0];
2580 fmt->count[0] = fmt2.fmt.vbi.count[0];
2581 fmt->start[1] = fmt2.fmt.vbi.start[1];
2582 fmt->count[1] = fmt2.fmt.vbi.count[1];
Michael H. Schimek67f15702006-01-09 15:25:27 -02002583 if (fmt2.fmt.vbi.flags & V4L2_VBI_UNSYNC)
2584 fmt->flags |= VBI_UNSYNC;
2585 if (fmt2.fmt.vbi.flags & V4L2_VBI_INTERLACED)
2586 fmt->flags |= VBI_INTERLACED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587 return 0;
2588 }
2589 case VIDIOCSVBIFMT:
2590 {
2591 struct vbi_format *fmt = (void *) arg;
2592 struct v4l2_format fmt2;
2593
2594 retval = bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE);
2595 if (0 != retval)
2596 return retval;
2597 bttv_vbi_get_fmt(fh, &fmt2);
2598
2599 if (fmt->sampling_rate != fmt2.fmt.vbi.sampling_rate ||
2600 fmt->samples_per_line != fmt2.fmt.vbi.samples_per_line ||
2601 fmt->sample_format != VIDEO_PALETTE_RAW ||
2602 fmt->start[0] != fmt2.fmt.vbi.start[0] ||
2603 fmt->start[1] != fmt2.fmt.vbi.start[1] ||
2604 fmt->count[0] != fmt->count[1] ||
2605 fmt->count[0] < 1 ||
2606 fmt->count[0] > 32 /* VBI_MAXLINES */)
2607 return -EINVAL;
2608
2609 bttv_vbi_setlines(fh,btv,fmt->count[0]);
2610 return 0;
2611 }
2612
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08002613 case BTTV_VERSION:
2614 case VIDIOCGFREQ:
2615 case VIDIOCSFREQ:
2616 case VIDIOCGTUNER:
2617 case VIDIOCSTUNER:
2618 case VIDIOCGCHAN:
2619 case VIDIOCSCHAN:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620 case VIDIOCGAUDIO:
2621 case VIDIOCSAUDIO:
2622 return bttv_common_ioctls(btv,cmd,arg);
2623
2624 /* *** v4l2 *** ************************************************ */
2625 case VIDIOC_QUERYCAP:
2626 {
2627 struct v4l2_capability *cap = arg;
2628
2629 if (0 == v4l2)
2630 return -EINVAL;
Michael H. Schimekbbf78712005-12-01 00:51:40 -08002631 memset(cap, 0, sizeof (*cap));
2632 strlcpy(cap->driver, "bttv", sizeof (cap->driver));
2633 strlcpy(cap->card, btv->video_dev->name, sizeof (cap->card));
2634 snprintf(cap->bus_info, sizeof (cap->bus_info),
2635 "PCI:%s", pci_name(btv->c.pci));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636 cap->version = BTTV_VERSION_CODE;
2637 cap->capabilities =
2638 V4L2_CAP_VIDEO_CAPTURE |
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639 V4L2_CAP_VBI_CAPTURE |
2640 V4L2_CAP_READWRITE |
2641 V4L2_CAP_STREAMING;
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07002642 if (no_overlay <= 0)
2643 cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
2644
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645 if (bttv_tvcards[btv->c.type].tuner != UNSET &&
2646 bttv_tvcards[btv->c.type].tuner != TUNER_ABSENT)
2647 cap->capabilities |= V4L2_CAP_TUNER;
2648 return 0;
2649 }
2650
2651 case VIDIOC_ENUM_FMT:
2652 {
2653 struct v4l2_fmtdesc *f = arg;
2654 enum v4l2_buf_type type;
2655 unsigned int i;
2656 int index;
2657
2658 type = f->type;
2659 if (V4L2_BUF_TYPE_VBI_CAPTURE == type) {
2660 /* vbi */
2661 index = f->index;
2662 if (0 != index)
2663 return -EINVAL;
2664 memset(f,0,sizeof(*f));
2665 f->index = index;
2666 f->type = type;
2667 f->pixelformat = V4L2_PIX_FMT_GREY;
2668 strcpy(f->description,"vbi data");
2669 return 0;
2670 }
2671
2672 /* video capture + overlay */
2673 index = -1;
2674 for (i = 0; i < BTTV_FORMATS; i++) {
2675 if (bttv_formats[i].fourcc != -1)
2676 index++;
2677 if ((unsigned int)index == f->index)
2678 break;
2679 }
2680 if (BTTV_FORMATS == i)
2681 return -EINVAL;
2682
2683 switch (f->type) {
2684 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2685 break;
2686 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
2687 if (!(bttv_formats[i].flags & FORMAT_FLAGS_PACKED))
2688 return -EINVAL;
2689 break;
2690 default:
2691 return -EINVAL;
2692 }
2693 memset(f,0,sizeof(*f));
2694 f->index = index;
2695 f->type = type;
2696 f->pixelformat = bttv_formats[i].fourcc;
2697 strlcpy(f->description,bttv_formats[i].name,sizeof(f->description));
2698 return 0;
2699 }
2700
2701 case VIDIOC_TRY_FMT:
2702 {
2703 struct v4l2_format *f = arg;
2704 return bttv_try_fmt(fh,btv,f);
2705 }
2706 case VIDIOC_G_FMT:
2707 {
2708 struct v4l2_format *f = arg;
2709 return bttv_g_fmt(fh,f);
2710 }
2711 case VIDIOC_S_FMT:
2712 {
2713 struct v4l2_format *f = arg;
2714 return bttv_s_fmt(fh,btv,f);
2715 }
2716
2717 case VIDIOC_G_FBUF:
2718 {
2719 struct v4l2_framebuffer *fb = arg;
2720
2721 *fb = btv->fbuf;
2722 fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
2723 if (fh->ovfmt)
2724 fb->fmt.pixelformat = fh->ovfmt->fourcc;
2725 return 0;
2726 }
2727 case VIDIOC_S_FBUF:
2728 {
2729 struct v4l2_framebuffer *fb = arg;
2730 const struct bttv_format *fmt;
2731
2732 if(!capable(CAP_SYS_ADMIN) &&
2733 !capable(CAP_SYS_RAWIO))
2734 return -EPERM;
2735
2736 /* check args */
2737 fmt = format_by_fourcc(fb->fmt.pixelformat);
2738 if (NULL == fmt)
2739 return -EINVAL;
2740 if (0 == (fmt->flags & FORMAT_FLAGS_PACKED))
2741 return -EINVAL;
2742
2743 down(&fh->cap.lock);
2744 retval = -EINVAL;
2745 if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
2746 if (fb->fmt.width > bttv_tvnorms[btv->tvnorm].swidth)
2747 goto fh_unlock_and_return;
2748 if (fb->fmt.height > bttv_tvnorms[btv->tvnorm].sheight)
2749 goto fh_unlock_and_return;
2750 }
2751
2752 /* ok, accept it */
2753 btv->fbuf.base = fb->base;
2754 btv->fbuf.fmt.width = fb->fmt.width;
2755 btv->fbuf.fmt.height = fb->fmt.height;
2756 if (0 != fb->fmt.bytesperline)
2757 btv->fbuf.fmt.bytesperline = fb->fmt.bytesperline;
2758 else
2759 btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fmt->depth/8;
2760
2761 retval = 0;
2762 fh->ovfmt = fmt;
2763 btv->init.ovfmt = fmt;
2764 if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
2765 fh->ov.w.left = 0;
2766 fh->ov.w.top = 0;
2767 fh->ov.w.width = fb->fmt.width;
2768 fh->ov.w.height = fb->fmt.height;
2769 btv->init.ov.w.width = fb->fmt.width;
2770 btv->init.ov.w.height = fb->fmt.height;
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -08002771 kfree(fh->ov.clips);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002772 fh->ov.clips = NULL;
2773 fh->ov.nclips = 0;
2774
2775 if (check_btres(fh, RESOURCE_OVERLAY)) {
2776 struct bttv_buffer *new;
2777
2778 new = videobuf_alloc(sizeof(*new));
2779 bttv_overlay_risc(btv,&fh->ov,fh->ovfmt,new);
2780 retval = bttv_switch_overlay(btv,fh,new);
2781 }
2782 }
2783 up(&fh->cap.lock);
2784 return retval;
2785 }
2786
2787 case VIDIOC_REQBUFS:
2788 return videobuf_reqbufs(bttv_queue(fh),arg);
2789
2790 case VIDIOC_QUERYBUF:
2791 return videobuf_querybuf(bttv_queue(fh),arg);
2792
2793 case VIDIOC_QBUF:
2794 return videobuf_qbuf(bttv_queue(fh),arg);
2795
2796 case VIDIOC_DQBUF:
2797 return videobuf_dqbuf(bttv_queue(fh),arg,
2798 file->f_flags & O_NONBLOCK);
2799
2800 case VIDIOC_STREAMON:
2801 {
2802 int res = bttv_resource(fh);
2803
2804 if (!check_alloc_btres(btv,fh,res))
2805 return -EBUSY;
2806 return videobuf_streamon(bttv_queue(fh));
2807 }
2808 case VIDIOC_STREAMOFF:
2809 {
2810 int res = bttv_resource(fh);
2811
2812 retval = videobuf_streamoff(bttv_queue(fh));
2813 if (retval < 0)
2814 return retval;
2815 free_btres(btv,fh,res);
2816 return 0;
2817 }
2818
2819 case VIDIOC_QUERYCTRL:
2820 {
2821 struct v4l2_queryctrl *c = arg;
2822 int i;
2823
2824 if ((c->id < V4L2_CID_BASE ||
2825 c->id >= V4L2_CID_LASTP1) &&
2826 (c->id < V4L2_CID_PRIVATE_BASE ||
2827 c->id >= V4L2_CID_PRIVATE_LASTP1))
2828 return -EINVAL;
2829 for (i = 0; i < BTTV_CTLS; i++)
2830 if (bttv_ctls[i].id == c->id)
2831 break;
2832 if (i == BTTV_CTLS) {
2833 *c = no_ctl;
2834 return 0;
2835 }
2836 *c = bttv_ctls[i];
2837 if (i >= 4 && i <= 8) {
2838 struct video_audio va;
2839 memset(&va,0,sizeof(va));
2840 bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
2841 if (btv->audio_hook)
2842 btv->audio_hook(btv,&va,0);
2843 switch (bttv_ctls[i].id) {
2844 case V4L2_CID_AUDIO_VOLUME:
2845 if (!(va.flags & VIDEO_AUDIO_VOLUME))
2846 *c = no_ctl;
2847 break;
2848 case V4L2_CID_AUDIO_BALANCE:
2849 if (!(va.flags & VIDEO_AUDIO_BALANCE))
2850 *c = no_ctl;
2851 break;
2852 case V4L2_CID_AUDIO_BASS:
2853 if (!(va.flags & VIDEO_AUDIO_BASS))
2854 *c = no_ctl;
2855 break;
2856 case V4L2_CID_AUDIO_TREBLE:
2857 if (!(va.flags & VIDEO_AUDIO_TREBLE))
2858 *c = no_ctl;
2859 break;
2860 }
2861 }
2862 return 0;
2863 }
2864 case VIDIOC_G_CTRL:
2865 return get_control(btv,arg);
2866 case VIDIOC_S_CTRL:
2867 return set_control(btv,arg);
2868 case VIDIOC_G_PARM:
2869 {
2870 struct v4l2_streamparm *parm = arg;
2871 struct v4l2_standard s;
2872 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
2873 return -EINVAL;
2874 memset(parm,0,sizeof(*parm));
2875 v4l2_video_std_construct(&s, bttv_tvnorms[btv->tvnorm].v4l2_id,
2876 bttv_tvnorms[btv->tvnorm].name);
2877 parm->parm.capture.timeperframe = s.frameperiod;
2878 return 0;
2879 }
2880
2881 case VIDIOC_G_PRIORITY:
2882 {
2883 enum v4l2_priority *p = arg;
2884
2885 *p = v4l2_prio_max(&btv->prio);
2886 return 0;
2887 }
2888 case VIDIOC_S_PRIORITY:
2889 {
2890 enum v4l2_priority *prio = arg;
2891
2892 return v4l2_prio_change(&btv->prio, &fh->prio, *prio);
2893 }
2894
2895 case VIDIOC_ENUMSTD:
2896 case VIDIOC_G_STD:
2897 case VIDIOC_S_STD:
2898 case VIDIOC_ENUMINPUT:
2899 case VIDIOC_G_INPUT:
2900 case VIDIOC_S_INPUT:
2901 case VIDIOC_G_TUNER:
2902 case VIDIOC_S_TUNER:
2903 case VIDIOC_G_FREQUENCY:
2904 case VIDIOC_S_FREQUENCY:
Hans Verkuil299392b2005-11-08 21:37:42 -08002905 case VIDIOC_LOG_STATUS:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002906 return bttv_common_ioctls(btv,cmd,arg);
2907
2908 default:
2909 return -ENOIOCTLCMD;
2910 }
2911 return 0;
2912
2913 fh_unlock_and_return:
2914 up(&fh->cap.lock);
2915 return retval;
2916}
2917
2918static int bttv_ioctl(struct inode *inode, struct file *file,
2919 unsigned int cmd, unsigned long arg)
2920{
2921 struct bttv_fh *fh = file->private_data;
2922
2923 switch (cmd) {
2924 case BTTV_VBISIZE:
2925 bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE);
2926 return fh->lines * 2 * 2048;
2927 default:
2928 return video_usercopy(inode, file, cmd, arg, bttv_do_ioctl);
2929 }
2930}
2931
2932static ssize_t bttv_read(struct file *file, char __user *data,
2933 size_t count, loff_t *ppos)
2934{
2935 struct bttv_fh *fh = file->private_data;
2936 int retval = 0;
2937
2938 if (fh->btv->errors)
2939 bttv_reinit_bt848(fh->btv);
2940 dprintk("bttv%d: read count=%d type=%s\n",
2941 fh->btv->c.nr,(int)count,v4l2_type_names[fh->type]);
2942
2943 switch (fh->type) {
2944 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2945 if (locked_btres(fh->btv,RESOURCE_VIDEO))
2946 return -EBUSY;
2947 retval = videobuf_read_one(&fh->cap, data, count, ppos,
2948 file->f_flags & O_NONBLOCK);
2949 break;
2950 case V4L2_BUF_TYPE_VBI_CAPTURE:
2951 if (!check_alloc_btres(fh->btv,fh,RESOURCE_VBI))
2952 return -EBUSY;
2953 retval = videobuf_read_stream(&fh->vbi, data, count, ppos, 1,
2954 file->f_flags & O_NONBLOCK);
2955 break;
2956 default:
2957 BUG();
2958 }
2959 return retval;
2960}
2961
2962static unsigned int bttv_poll(struct file *file, poll_table *wait)
2963{
2964 struct bttv_fh *fh = file->private_data;
2965 struct bttv_buffer *buf;
2966 enum v4l2_field field;
2967
2968 if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
2969 if (!check_alloc_btres(fh->btv,fh,RESOURCE_VBI))
2970 return POLLERR;
2971 return videobuf_poll_stream(file, &fh->vbi, wait);
2972 }
2973
2974 if (check_btres(fh,RESOURCE_VIDEO)) {
2975 /* streaming capture */
2976 if (list_empty(&fh->cap.stream))
2977 return POLLERR;
2978 buf = list_entry(fh->cap.stream.next,struct bttv_buffer,vb.stream);
2979 } else {
2980 /* read() capture */
2981 down(&fh->cap.lock);
2982 if (NULL == fh->cap.read_buf) {
2983 /* need to capture a new frame */
2984 if (locked_btres(fh->btv,RESOURCE_VIDEO)) {
2985 up(&fh->cap.lock);
2986 return POLLERR;
2987 }
2988 fh->cap.read_buf = videobuf_alloc(fh->cap.msize);
2989 if (NULL == fh->cap.read_buf) {
2990 up(&fh->cap.lock);
2991 return POLLERR;
2992 }
2993 fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR;
2994 field = videobuf_next_field(&fh->cap);
2995 if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,field)) {
Nickolay V. Shmyrev50ab5ed2005-12-01 00:51:32 -08002996 kfree (fh->cap.read_buf);
2997 fh->cap.read_buf = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002998 up(&fh->cap.lock);
2999 return POLLERR;
3000 }
3001 fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf);
3002 fh->cap.read_off = 0;
3003 }
3004 up(&fh->cap.lock);
3005 buf = (struct bttv_buffer*)fh->cap.read_buf;
3006 }
3007
3008 poll_wait(file, &buf->vb.done, wait);
3009 if (buf->vb.state == STATE_DONE ||
3010 buf->vb.state == STATE_ERROR)
3011 return POLLIN|POLLRDNORM;
3012 return 0;
3013}
3014
3015static int bttv_open(struct inode *inode, struct file *file)
3016{
3017 int minor = iminor(inode);
3018 struct bttv *btv = NULL;
3019 struct bttv_fh *fh;
3020 enum v4l2_buf_type type = 0;
3021 unsigned int i;
3022
3023 dprintk(KERN_DEBUG "bttv: open minor=%d\n",minor);
3024
3025 for (i = 0; i < bttv_num; i++) {
3026 if (bttvs[i].video_dev &&
3027 bttvs[i].video_dev->minor == minor) {
3028 btv = &bttvs[i];
3029 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
3030 break;
3031 }
3032 if (bttvs[i].vbi_dev &&
3033 bttvs[i].vbi_dev->minor == minor) {
3034 btv = &bttvs[i];
3035 type = V4L2_BUF_TYPE_VBI_CAPTURE;
3036 break;
3037 }
3038 }
3039 if (NULL == btv)
3040 return -ENODEV;
3041
3042 dprintk(KERN_DEBUG "bttv%d: open called (type=%s)\n",
3043 btv->c.nr,v4l2_type_names[type]);
3044
3045 /* allocate per filehandle data */
3046 fh = kmalloc(sizeof(*fh),GFP_KERNEL);
3047 if (NULL == fh)
3048 return -ENOMEM;
3049 file->private_data = fh;
3050 *fh = btv->init;
3051 fh->type = type;
3052 fh->ov.setup_ok = 0;
3053 v4l2_prio_open(&btv->prio,&fh->prio);
3054
3055 videobuf_queue_init(&fh->cap, &bttv_video_qops,
3056 btv->c.pci, &btv->s_lock,
3057 V4L2_BUF_TYPE_VIDEO_CAPTURE,
3058 V4L2_FIELD_INTERLACED,
3059 sizeof(struct bttv_buffer),
3060 fh);
3061 videobuf_queue_init(&fh->vbi, &bttv_vbi_qops,
3062 btv->c.pci, &btv->s_lock,
3063 V4L2_BUF_TYPE_VBI_CAPTURE,
3064 V4L2_FIELD_SEQ_TB,
3065 sizeof(struct bttv_buffer),
3066 fh);
3067 i2c_vidiocschan(btv);
3068
3069 btv->users++;
3070 if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type)
3071 bttv_vbi_setlines(fh,btv,16);
3072 bttv_field_count(btv);
3073 return 0;
3074}
3075
3076static int bttv_release(struct inode *inode, struct file *file)
3077{
3078 struct bttv_fh *fh = file->private_data;
3079 struct bttv *btv = fh->btv;
3080
3081 /* turn off overlay */
3082 if (check_btres(fh, RESOURCE_OVERLAY))
3083 bttv_switch_overlay(btv,fh,NULL);
3084
3085 /* stop video capture */
3086 if (check_btres(fh, RESOURCE_VIDEO)) {
3087 videobuf_streamoff(&fh->cap);
3088 free_btres(btv,fh,RESOURCE_VIDEO);
3089 }
3090 if (fh->cap.read_buf) {
3091 buffer_release(&fh->cap,fh->cap.read_buf);
3092 kfree(fh->cap.read_buf);
3093 }
3094
3095 /* stop vbi capture */
3096 if (check_btres(fh, RESOURCE_VBI)) {
3097 if (fh->vbi.streaming)
3098 videobuf_streamoff(&fh->vbi);
3099 if (fh->vbi.reading)
3100 videobuf_read_stop(&fh->vbi);
3101 free_btres(btv,fh,RESOURCE_VBI);
3102 }
3103
3104 /* free stuff */
3105 videobuf_mmap_free(&fh->cap);
3106 videobuf_mmap_free(&fh->vbi);
3107 v4l2_prio_close(&btv->prio,&fh->prio);
3108 file->private_data = NULL;
3109 kfree(fh);
3110
3111 btv->users--;
3112 bttv_field_count(btv);
3113 return 0;
3114}
3115
3116static int
3117bttv_mmap(struct file *file, struct vm_area_struct *vma)
3118{
3119 struct bttv_fh *fh = file->private_data;
3120
3121 dprintk("bttv%d: mmap type=%s 0x%lx+%ld\n",
3122 fh->btv->c.nr, v4l2_type_names[fh->type],
3123 vma->vm_start, vma->vm_end - vma->vm_start);
3124 return videobuf_mmap_mapper(bttv_queue(fh),vma);
3125}
3126
3127static struct file_operations bttv_fops =
3128{
3129 .owner = THIS_MODULE,
3130 .open = bttv_open,
3131 .release = bttv_release,
3132 .ioctl = bttv_ioctl,
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02003133 .compat_ioctl = v4l_compat_ioctl32,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003134 .llseek = no_llseek,
3135 .read = bttv_read,
3136 .mmap = bttv_mmap,
3137 .poll = bttv_poll,
3138};
3139
3140static struct video_device bttv_video_template =
3141{
3142 .name = "UNSET",
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07003143 .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003144 VID_TYPE_CLIPPING|VID_TYPE_SCALES,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003145 .hardware = VID_HARDWARE_BT848,
3146 .fops = &bttv_fops,
3147 .minor = -1,
3148};
3149
3150static struct video_device bttv_vbi_template =
3151{
3152 .name = "bt848/878 vbi",
3153 .type = VID_TYPE_TUNER|VID_TYPE_TELETEXT,
3154 .hardware = VID_HARDWARE_BT848,
3155 .fops = &bttv_fops,
3156 .minor = -1,
3157};
3158
3159/* ----------------------------------------------------------------------- */
3160/* radio interface */
3161
3162static int radio_open(struct inode *inode, struct file *file)
3163{
3164 int minor = iminor(inode);
3165 struct bttv *btv = NULL;
3166 unsigned int i;
3167
3168 dprintk("bttv: open minor=%d\n",minor);
3169
3170 for (i = 0; i < bttv_num; i++) {
3171 if (bttvs[i].radio_dev->minor == minor) {
3172 btv = &bttvs[i];
3173 break;
3174 }
3175 }
3176 if (NULL == btv)
3177 return -ENODEV;
3178
3179 dprintk("bttv%d: open called (radio)\n",btv->c.nr);
3180 down(&btv->lock);
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003181
Linus Torvalds1da177e2005-04-16 15:20:36 -07003182 btv->radio_user++;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003183
Linus Torvalds1da177e2005-04-16 15:20:36 -07003184 file->private_data = btv;
3185
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003186 bttv_call_i2c_clients(btv,AUDC_SET_RADIO,&btv->tuner_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187 audio_mux(btv,AUDIO_RADIO);
3188
3189 up(&btv->lock);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003190 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003191}
3192
3193static int radio_release(struct inode *inode, struct file *file)
3194{
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003195 struct bttv *btv = file->private_data;
3196 struct rds_command cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197
3198 btv->radio_user--;
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003199
3200 bttv_call_i2c_clients(btv, RDS_CMD_CLOSE, &cmd);
3201
Linus Torvalds1da177e2005-04-16 15:20:36 -07003202 return 0;
3203}
3204
3205static int radio_do_ioctl(struct inode *inode, struct file *file,
3206 unsigned int cmd, void *arg)
3207{
3208 struct bttv *btv = file->private_data;
3209
3210 switch (cmd) {
3211 case VIDIOCGCAP:
3212 {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003213 struct video_capability *cap = arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003214
3215 memset(cap,0,sizeof(*cap));
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003216 strcpy(cap->name,btv->radio_dev->name);
3217 cap->type = VID_TYPE_TUNER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003218 cap->channels = 1;
3219 cap->audios = 1;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003220 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003221 }
3222
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003223 case VIDIOCGTUNER:
3224 {
3225 struct video_tuner *v = arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003226
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003227 if(v->tuner)
3228 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003229 memset(v,0,sizeof(*v));
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003230 strcpy(v->name, "Radio");
3231 bttv_call_i2c_clients(btv,cmd,v);
3232 return 0;
3233 }
3234 case VIDIOCSTUNER:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003235 /* nothing to do */
3236 return 0;
3237
3238 case BTTV_VERSION:
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003239 case VIDIOCGFREQ:
3240 case VIDIOCSFREQ:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003241 case VIDIOCGAUDIO:
3242 case VIDIOCSAUDIO:
3243 return bttv_common_ioctls(btv,cmd,arg);
3244
3245 default:
3246 return -ENOIOCTLCMD;
3247 }
3248 return 0;
3249}
3250
3251static int radio_ioctl(struct inode *inode, struct file *file,
3252 unsigned int cmd, unsigned long arg)
3253{
3254 return video_usercopy(inode, file, cmd, arg, radio_do_ioctl);
3255}
3256
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003257static ssize_t radio_read(struct file *file, char __user *data,
3258 size_t count, loff_t *ppos)
3259{
3260 struct bttv *btv = file->private_data;
3261 struct rds_command cmd;
3262 cmd.block_count = count/3;
3263 cmd.buffer = data;
3264 cmd.instance = file;
3265 cmd.result = -ENODEV;
3266
3267 bttv_call_i2c_clients(btv, RDS_CMD_READ, &cmd);
3268
3269 return cmd.result;
3270}
3271
3272static unsigned int radio_poll(struct file *file, poll_table *wait)
3273{
3274 struct bttv *btv = file->private_data;
3275 struct rds_command cmd;
3276 cmd.instance = file;
3277 cmd.event_list = wait;
3278 cmd.result = -ENODEV;
3279 bttv_call_i2c_clients(btv, RDS_CMD_POLL, &cmd);
3280
3281 return cmd.result;
3282}
3283
Linus Torvalds1da177e2005-04-16 15:20:36 -07003284static struct file_operations radio_fops =
3285{
3286 .owner = THIS_MODULE,
3287 .open = radio_open,
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003288 .read = radio_read,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003289 .release = radio_release,
3290 .ioctl = radio_ioctl,
3291 .llseek = no_llseek,
Mauro Carvalho Chehab24a70fd2005-09-09 13:03:39 -07003292 .poll = radio_poll,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003293};
3294
3295static struct video_device radio_template =
3296{
3297 .name = "bt848/878 radio",
3298 .type = VID_TYPE_TUNER,
3299 .hardware = VID_HARDWARE_BT848,
3300 .fops = &radio_fops,
3301 .minor = -1,
3302};
3303
3304/* ----------------------------------------------------------------------- */
3305/* some debug code */
3306
Adrian Bunk408b6642005-05-01 08:59:29 -07003307static int bttv_risc_decode(u32 risc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003308{
3309 static char *instr[16] = {
3310 [ BT848_RISC_WRITE >> 28 ] = "write",
3311 [ BT848_RISC_SKIP >> 28 ] = "skip",
3312 [ BT848_RISC_WRITEC >> 28 ] = "writec",
3313 [ BT848_RISC_JUMP >> 28 ] = "jump",
3314 [ BT848_RISC_SYNC >> 28 ] = "sync",
3315 [ BT848_RISC_WRITE123 >> 28 ] = "write123",
3316 [ BT848_RISC_SKIP123 >> 28 ] = "skip123",
3317 [ BT848_RISC_WRITE1S23 >> 28 ] = "write1s23",
3318 };
3319 static int incr[16] = {
3320 [ BT848_RISC_WRITE >> 28 ] = 2,
3321 [ BT848_RISC_JUMP >> 28 ] = 2,
3322 [ BT848_RISC_SYNC >> 28 ] = 2,
3323 [ BT848_RISC_WRITE123 >> 28 ] = 5,
3324 [ BT848_RISC_SKIP123 >> 28 ] = 2,
3325 [ BT848_RISC_WRITE1S23 >> 28 ] = 3,
3326 };
3327 static char *bits[] = {
3328 "be0", "be1", "be2", "be3/resync",
3329 "set0", "set1", "set2", "set3",
3330 "clr0", "clr1", "clr2", "clr3",
3331 "irq", "res", "eol", "sol",
3332 };
3333 int i;
3334
3335 printk("0x%08x [ %s", risc,
3336 instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
3337 for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
3338 if (risc & (1 << (i + 12)))
3339 printk(" %s",bits[i]);
3340 printk(" count=%d ]\n", risc & 0xfff);
3341 return incr[risc >> 28] ? incr[risc >> 28] : 1;
3342}
3343
Adrian Bunk408b6642005-05-01 08:59:29 -07003344static void bttv_risc_disasm(struct bttv *btv,
3345 struct btcx_riscmem *risc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003346{
3347 unsigned int i,j,n;
3348
3349 printk("%s: risc disasm: %p [dma=0x%08lx]\n",
3350 btv->c.name, risc->cpu, (unsigned long)risc->dma);
3351 for (i = 0; i < (risc->size >> 2); i += n) {
3352 printk("%s: 0x%lx: ", btv->c.name,
3353 (unsigned long)(risc->dma + (i<<2)));
3354 n = bttv_risc_decode(risc->cpu[i]);
3355 for (j = 1; j < n; j++)
3356 printk("%s: 0x%lx: 0x%08x [ arg #%d ]\n",
3357 btv->c.name, (unsigned long)(risc->dma + ((i+j)<<2)),
3358 risc->cpu[i+j], j);
3359 if (0 == risc->cpu[i])
3360 break;
3361 }
3362}
3363
3364static void bttv_print_riscaddr(struct bttv *btv)
3365{
3366 printk(" main: %08Lx\n",
3367 (unsigned long long)btv->main.dma);
3368 printk(" vbi : o=%08Lx e=%08Lx\n",
3369 btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
3370 btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0);
3371 printk(" cap : o=%08Lx e=%08Lx\n",
3372 btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0,
3373 btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
3374 printk(" scr : o=%08Lx e=%08Lx\n",
3375 btv->screen ? (unsigned long long)btv->screen->top.dma : 0,
3376 btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0);
3377 bttv_risc_disasm(btv, &btv->main);
3378}
3379
3380/* ----------------------------------------------------------------------- */
3381/* irq handler */
3382
3383static char *irq_name[] = {
3384 "FMTCHG", // format change detected (525 vs. 625)
3385 "VSYNC", // vertical sync (new field)
3386 "HSYNC", // horizontal sync
3387 "OFLOW", // chroma/luma AGC overflow
3388 "HLOCK", // horizontal lock changed
3389 "VPRES", // video presence changed
3390 "6", "7",
3391 "I2CDONE", // hw irc operation finished
3392 "GPINT", // gpio port triggered irq
3393 "10",
3394 "RISCI", // risc instruction triggered irq
3395 "FBUS", // pixel data fifo dropped data (high pci bus latencies)
3396 "FTRGT", // pixel data fifo overrun
3397 "FDSR", // fifo data stream resyncronisation
3398 "PPERR", // parity error (data transfer)
3399 "RIPERR", // parity error (read risc instructions)
3400 "PABORT", // pci abort
3401 "OCERR", // risc instruction error
3402 "SCERR", // syncronisation error
3403};
3404
3405static void bttv_print_irqbits(u32 print, u32 mark)
3406{
3407 unsigned int i;
3408
3409 printk("bits:");
3410 for (i = 0; i < ARRAY_SIZE(irq_name); i++) {
3411 if (print & (1 << i))
3412 printk(" %s",irq_name[i]);
3413 if (mark & (1 << i))
3414 printk("*");
3415 }
3416}
3417
3418static void bttv_irq_debug_low_latency(struct bttv *btv, u32 rc)
3419{
3420 printk("bttv%d: irq: skipped frame [main=%lx,o_vbi=%lx,o_field=%lx,rc=%lx]\n",
3421 btv->c.nr,
3422 (unsigned long)btv->main.dma,
3423 (unsigned long)btv->main.cpu[RISC_SLOT_O_VBI+1],
3424 (unsigned long)btv->main.cpu[RISC_SLOT_O_FIELD+1],
3425 (unsigned long)rc);
3426
3427 if (0 == (btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC)) {
3428 printk("bttv%d: Oh, there (temporarely?) is no input signal. "
3429 "Ok, then this is harmless, don't worry ;)\n",
3430 btv->c.nr);
3431 return;
3432 }
3433 printk("bttv%d: Uhm. Looks like we have unusual high IRQ latencies.\n",
3434 btv->c.nr);
3435 printk("bttv%d: Lets try to catch the culpit red-handed ...\n",
3436 btv->c.nr);
3437 dump_stack();
3438}
3439
3440static int
3441bttv_irq_next_video(struct bttv *btv, struct bttv_buffer_set *set)
3442{
3443 struct bttv_buffer *item;
3444
3445 memset(set,0,sizeof(*set));
3446
3447 /* capture request ? */
3448 if (!list_empty(&btv->capture)) {
3449 set->frame_irq = 1;
3450 item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
3451 if (V4L2_FIELD_HAS_TOP(item->vb.field))
3452 set->top = item;
3453 if (V4L2_FIELD_HAS_BOTTOM(item->vb.field))
3454 set->bottom = item;
3455
3456 /* capture request for other field ? */
3457 if (!V4L2_FIELD_HAS_BOTH(item->vb.field) &&
3458 (item->vb.queue.next != &btv->capture)) {
3459 item = list_entry(item->vb.queue.next, struct bttv_buffer, vb.queue);
3460 if (!V4L2_FIELD_HAS_BOTH(item->vb.field)) {
3461 if (NULL == set->top &&
3462 V4L2_FIELD_TOP == item->vb.field) {
3463 set->top = item;
3464 }
3465 if (NULL == set->bottom &&
3466 V4L2_FIELD_BOTTOM == item->vb.field) {
3467 set->bottom = item;
3468 }
3469 if (NULL != set->top && NULL != set->bottom)
3470 set->top_irq = 2;
3471 }
3472 }
3473 }
3474
3475 /* screen overlay ? */
3476 if (NULL != btv->screen) {
3477 if (V4L2_FIELD_HAS_BOTH(btv->screen->vb.field)) {
3478 if (NULL == set->top && NULL == set->bottom) {
3479 set->top = btv->screen;
3480 set->bottom = btv->screen;
3481 }
3482 } else {
3483 if (V4L2_FIELD_TOP == btv->screen->vb.field &&
3484 NULL == set->top) {
3485 set->top = btv->screen;
3486 }
3487 if (V4L2_FIELD_BOTTOM == btv->screen->vb.field &&
3488 NULL == set->bottom) {
3489 set->bottom = btv->screen;
3490 }
3491 }
3492 }
3493
3494 dprintk("bttv%d: next set: top=%p bottom=%p [screen=%p,irq=%d,%d]\n",
3495 btv->c.nr,set->top, set->bottom,
3496 btv->screen,set->frame_irq,set->top_irq);
3497 return 0;
3498}
3499
3500static void
3501bttv_irq_wakeup_video(struct bttv *btv, struct bttv_buffer_set *wakeup,
3502 struct bttv_buffer_set *curr, unsigned int state)
3503{
3504 struct timeval ts;
3505
3506 do_gettimeofday(&ts);
3507
3508 if (wakeup->top == wakeup->bottom) {
3509 if (NULL != wakeup->top && curr->top != wakeup->top) {
3510 if (irq_debug > 1)
3511 printk("bttv%d: wakeup: both=%p\n",btv->c.nr,wakeup->top);
3512 wakeup->top->vb.ts = ts;
3513 wakeup->top->vb.field_count = btv->field_count;
3514 wakeup->top->vb.state = state;
3515 wake_up(&wakeup->top->vb.done);
3516 }
3517 } else {
3518 if (NULL != wakeup->top && curr->top != wakeup->top) {
3519 if (irq_debug > 1)
3520 printk("bttv%d: wakeup: top=%p\n",btv->c.nr,wakeup->top);
3521 wakeup->top->vb.ts = ts;
3522 wakeup->top->vb.field_count = btv->field_count;
3523 wakeup->top->vb.state = state;
3524 wake_up(&wakeup->top->vb.done);
3525 }
3526 if (NULL != wakeup->bottom && curr->bottom != wakeup->bottom) {
3527 if (irq_debug > 1)
3528 printk("bttv%d: wakeup: bottom=%p\n",btv->c.nr,wakeup->bottom);
3529 wakeup->bottom->vb.ts = ts;
3530 wakeup->bottom->vb.field_count = btv->field_count;
3531 wakeup->bottom->vb.state = state;
3532 wake_up(&wakeup->bottom->vb.done);
3533 }
3534 }
3535}
3536
3537static void
3538bttv_irq_wakeup_vbi(struct bttv *btv, struct bttv_buffer *wakeup,
3539 unsigned int state)
3540{
3541 struct timeval ts;
3542
3543 if (NULL == wakeup)
3544 return;
3545
3546 do_gettimeofday(&ts);
3547 wakeup->vb.ts = ts;
3548 wakeup->vb.field_count = btv->field_count;
3549 wakeup->vb.state = state;
3550 wake_up(&wakeup->vb.done);
3551}
3552
3553static void bttv_irq_timeout(unsigned long data)
3554{
3555 struct bttv *btv = (struct bttv *)data;
3556 struct bttv_buffer_set old,new;
3557 struct bttv_buffer *ovbi;
3558 struct bttv_buffer *item;
3559 unsigned long flags;
3560
3561 if (bttv_verbose) {
3562 printk(KERN_INFO "bttv%d: timeout: drop=%d irq=%d/%d, risc=%08x, ",
3563 btv->c.nr, btv->framedrop, btv->irq_me, btv->irq_total,
3564 btread(BT848_RISC_COUNT));
3565 bttv_print_irqbits(btread(BT848_INT_STAT),0);
3566 printk("\n");
3567 }
3568
3569 spin_lock_irqsave(&btv->s_lock,flags);
3570
3571 /* deactivate stuff */
3572 memset(&new,0,sizeof(new));
3573 old = btv->curr;
3574 ovbi = btv->cvbi;
3575 btv->curr = new;
3576 btv->cvbi = NULL;
3577 btv->loop_irq = 0;
3578 bttv_buffer_activate_video(btv, &new);
3579 bttv_buffer_activate_vbi(btv, NULL);
3580 bttv_set_dma(btv, 0);
3581
3582 /* wake up */
3583 bttv_irq_wakeup_video(btv, &old, &new, STATE_ERROR);
3584 bttv_irq_wakeup_vbi(btv, ovbi, STATE_ERROR);
3585
3586 /* cancel all outstanding capture / vbi requests */
3587 while (!list_empty(&btv->capture)) {
3588 item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
3589 list_del(&item->vb.queue);
3590 item->vb.state = STATE_ERROR;
3591 wake_up(&item->vb.done);
3592 }
3593 while (!list_empty(&btv->vcapture)) {
3594 item = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
3595 list_del(&item->vb.queue);
3596 item->vb.state = STATE_ERROR;
3597 wake_up(&item->vb.done);
3598 }
3599
3600 btv->errors++;
3601 spin_unlock_irqrestore(&btv->s_lock,flags);
3602}
3603
3604static void
3605bttv_irq_wakeup_top(struct bttv *btv)
3606{
3607 struct bttv_buffer *wakeup = btv->curr.top;
3608
3609 if (NULL == wakeup)
3610 return;
3611
3612 spin_lock(&btv->s_lock);
3613 btv->curr.top_irq = 0;
3614 btv->curr.top = NULL;
3615 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
3616
3617 do_gettimeofday(&wakeup->vb.ts);
3618 wakeup->vb.field_count = btv->field_count;
3619 wakeup->vb.state = STATE_DONE;
3620 wake_up(&wakeup->vb.done);
3621 spin_unlock(&btv->s_lock);
3622}
3623
3624static inline int is_active(struct btcx_riscmem *risc, u32 rc)
3625{
3626 if (rc < risc->dma)
3627 return 0;
3628 if (rc > risc->dma + risc->size)
3629 return 0;
3630 return 1;
3631}
3632
3633static void
3634bttv_irq_switch_video(struct bttv *btv)
3635{
3636 struct bttv_buffer_set new;
3637 struct bttv_buffer_set old;
3638 dma_addr_t rc;
3639
3640 spin_lock(&btv->s_lock);
3641
3642 /* new buffer set */
3643 bttv_irq_next_video(btv, &new);
3644 rc = btread(BT848_RISC_COUNT);
3645 if ((btv->curr.top && is_active(&btv->curr.top->top, rc)) ||
3646 (btv->curr.bottom && is_active(&btv->curr.bottom->bottom, rc))) {
3647 btv->framedrop++;
3648 if (debug_latency)
3649 bttv_irq_debug_low_latency(btv, rc);
3650 spin_unlock(&btv->s_lock);
3651 return;
3652 }
3653
3654 /* switch over */
3655 old = btv->curr;
3656 btv->curr = new;
3657 btv->loop_irq &= ~1;
3658 bttv_buffer_activate_video(btv, &new);
3659 bttv_set_dma(btv, 0);
3660
3661 /* switch input */
3662 if (UNSET != btv->new_input) {
3663 video_mux(btv,btv->new_input);
3664 btv->new_input = UNSET;
3665 }
3666
3667 /* wake up finished buffers */
3668 bttv_irq_wakeup_video(btv, &old, &new, STATE_DONE);
3669 spin_unlock(&btv->s_lock);
3670}
3671
3672static void
3673bttv_irq_switch_vbi(struct bttv *btv)
3674{
3675 struct bttv_buffer *new = NULL;
3676 struct bttv_buffer *old;
3677 u32 rc;
3678
3679 spin_lock(&btv->s_lock);
3680
3681 if (!list_empty(&btv->vcapture))
3682 new = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
3683 old = btv->cvbi;
3684
3685 rc = btread(BT848_RISC_COUNT);
3686 if (NULL != old && (is_active(&old->top, rc) ||
3687 is_active(&old->bottom, rc))) {
3688 btv->framedrop++;
3689 if (debug_latency)
3690 bttv_irq_debug_low_latency(btv, rc);
3691 spin_unlock(&btv->s_lock);
3692 return;
3693 }
3694
3695 /* switch */
3696 btv->cvbi = new;
3697 btv->loop_irq &= ~4;
3698 bttv_buffer_activate_vbi(btv, new);
3699 bttv_set_dma(btv, 0);
3700
3701 bttv_irq_wakeup_vbi(btv, old, STATE_DONE);
3702 spin_unlock(&btv->s_lock);
3703}
3704
3705static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
3706{
3707 u32 stat,astat;
3708 u32 dstat;
3709 int count;
3710 struct bttv *btv;
3711 int handled = 0;
3712
3713 btv=(struct bttv *)dev_id;
Mark Weaver6c6c0b22005-11-13 16:07:52 -08003714
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02003715 if (btv->custom_irq)
3716 handled = btv->custom_irq(btv);
Mark Weaver6c6c0b22005-11-13 16:07:52 -08003717
Linus Torvalds1da177e2005-04-16 15:20:36 -07003718 count=0;
3719 while (1) {
3720 /* get/clear interrupt status bits */
3721 stat=btread(BT848_INT_STAT);
3722 astat=stat&btread(BT848_INT_MASK);
3723 if (!astat)
3724 break;
3725 handled = 1;
3726 btwrite(stat,BT848_INT_STAT);
3727
3728 /* get device status bits */
3729 dstat=btread(BT848_DSTATUS);
3730
3731 if (irq_debug) {
3732 printk(KERN_DEBUG "bttv%d: irq loop=%d fc=%d "
3733 "riscs=%x, riscc=%08x, ",
3734 btv->c.nr, count, btv->field_count,
3735 stat>>28, btread(BT848_RISC_COUNT));
3736 bttv_print_irqbits(stat,astat);
3737 if (stat & BT848_INT_HLOCK)
3738 printk(" HLOC => %s", (dstat & BT848_DSTATUS_HLOC)
3739 ? "yes" : "no");
3740 if (stat & BT848_INT_VPRES)
3741 printk(" PRES => %s", (dstat & BT848_DSTATUS_PRES)
3742 ? "yes" : "no");
3743 if (stat & BT848_INT_FMTCHG)
3744 printk(" NUML => %s", (dstat & BT848_DSTATUS_NUML)
3745 ? "625" : "525");
3746 printk("\n");
3747 }
3748
3749 if (astat&BT848_INT_VSYNC)
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003750 btv->field_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003751
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02003752 if ((astat & BT848_INT_GPINT) && btv->remote) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003753 wake_up(&btv->gpioq);
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02003754 bttv_input_irq(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003755 }
3756
3757 if (astat & BT848_INT_I2CDONE) {
3758 btv->i2c_done = stat;
3759 wake_up(&btv->i2c_queue);
3760 }
3761
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003762 if ((astat & BT848_INT_RISCI) && (stat & (4<<28)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003763 bttv_irq_switch_vbi(btv);
3764
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003765 if ((astat & BT848_INT_RISCI) && (stat & (2<<28)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003766 bttv_irq_wakeup_top(btv);
3767
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003768 if ((astat & BT848_INT_RISCI) && (stat & (1<<28)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003769 bttv_irq_switch_video(btv);
3770
3771 if ((astat & BT848_INT_HLOCK) && btv->opt_automute)
3772 audio_mux(btv, -1);
3773
3774 if (astat & (BT848_INT_SCERR|BT848_INT_OCERR)) {
3775 printk(KERN_INFO "bttv%d: %s%s @ %08x,",btv->c.nr,
3776 (astat & BT848_INT_SCERR) ? "SCERR" : "",
3777 (astat & BT848_INT_OCERR) ? "OCERR" : "",
3778 btread(BT848_RISC_COUNT));
3779 bttv_print_irqbits(stat,astat);
3780 printk("\n");
3781 if (bttv_debug)
3782 bttv_print_riscaddr(btv);
3783 }
3784 if (fdsr && astat & BT848_INT_FDSR) {
3785 printk(KERN_INFO "bttv%d: FDSR @ %08x\n",
3786 btv->c.nr,btread(BT848_RISC_COUNT));
3787 if (bttv_debug)
3788 bttv_print_riscaddr(btv);
3789 }
3790
3791 count++;
3792 if (count > 4) {
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08003793
3794 if (count > 8 || !(astat & BT848_INT_GPINT)) {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003795 btwrite(0, BT848_INT_MASK);
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08003796
3797 printk(KERN_ERR
3798 "bttv%d: IRQ lockup, cleared int mask [", btv->c.nr);
3799 } else {
3800 printk(KERN_ERR
3801 "bttv%d: IRQ lockup, clearing GPINT from int mask [", btv->c.nr);
3802
3803 btwrite(btread(BT848_INT_MASK) & (-1 ^ BT848_INT_GPINT),
3804 BT848_INT_MASK);
3805 };
3806
Linus Torvalds1da177e2005-04-16 15:20:36 -07003807 bttv_print_irqbits(stat,astat);
nshmyrev@yandex.ruc58c21c2005-11-08 21:37:41 -08003808
Linus Torvalds1da177e2005-04-16 15:20:36 -07003809 printk("]\n");
3810 }
3811 }
3812 btv->irq_total++;
3813 if (handled)
3814 btv->irq_me++;
3815 return IRQ_RETVAL(handled);
3816}
3817
3818
3819/* ----------------------------------------------------------------------- */
3820/* initialitation */
3821
3822static struct video_device *vdev_init(struct bttv *btv,
3823 struct video_device *template,
3824 char *type)
3825{
3826 struct video_device *vfd;
3827
3828 vfd = video_device_alloc();
3829 if (NULL == vfd)
3830 return NULL;
3831 *vfd = *template;
3832 vfd->minor = -1;
3833 vfd->dev = &btv->c.pci->dev;
3834 vfd->release = video_device_release;
3835 snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
3836 btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "",
3837 type, bttv_tvcards[btv->c.type].name);
3838 return vfd;
3839}
3840
3841static void bttv_unregister_video(struct bttv *btv)
3842{
3843 if (btv->video_dev) {
3844 if (-1 != btv->video_dev->minor)
3845 video_unregister_device(btv->video_dev);
3846 else
3847 video_device_release(btv->video_dev);
3848 btv->video_dev = NULL;
3849 }
3850 if (btv->vbi_dev) {
3851 if (-1 != btv->vbi_dev->minor)
3852 video_unregister_device(btv->vbi_dev);
3853 else
3854 video_device_release(btv->vbi_dev);
3855 btv->vbi_dev = NULL;
3856 }
3857 if (btv->radio_dev) {
3858 if (-1 != btv->radio_dev->minor)
3859 video_unregister_device(btv->radio_dev);
3860 else
3861 video_device_release(btv->radio_dev);
3862 btv->radio_dev = NULL;
3863 }
3864}
3865
3866/* register video4linux devices */
3867static int __devinit bttv_register_video(struct bttv *btv)
3868{
Mauro Carvalho Chehab4dcef522005-08-04 12:53:30 -07003869 if (no_overlay <= 0) {
3870 bttv_video_template.type |= VID_TYPE_OVERLAY;
3871 } else {
3872 printk("bttv: Overlay support disabled.\n");
3873 }
3874
Linus Torvalds1da177e2005-04-16 15:20:36 -07003875 /* video */
3876 btv->video_dev = vdev_init(btv, &bttv_video_template, "video");
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003877 if (NULL == btv->video_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003878 goto err;
3879 if (video_register_device(btv->video_dev,VFL_TYPE_GRABBER,video_nr)<0)
3880 goto err;
3881 printk(KERN_INFO "bttv%d: registered device video%d\n",
3882 btv->c.nr,btv->video_dev->minor & 0x1f);
3883 video_device_create_file(btv->video_dev, &class_device_attr_card);
3884
3885 /* vbi */
3886 btv->vbi_dev = vdev_init(btv, &bttv_vbi_template, "vbi");
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003887 if (NULL == btv->vbi_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003888 goto err;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003889 if (video_register_device(btv->vbi_dev,VFL_TYPE_VBI,vbi_nr)<0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003890 goto err;
3891 printk(KERN_INFO "bttv%d: registered device vbi%d\n",
3892 btv->c.nr,btv->vbi_dev->minor & 0x1f);
3893
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003894 if (!btv->has_radio)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895 return 0;
3896 /* radio */
3897 btv->radio_dev = vdev_init(btv, &radio_template, "radio");
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003898 if (NULL == btv->radio_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003899 goto err;
3900 if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,radio_nr)<0)
3901 goto err;
3902 printk(KERN_INFO "bttv%d: registered device radio%d\n",
3903 btv->c.nr,btv->radio_dev->minor & 0x1f);
3904
3905 /* all done */
3906 return 0;
3907
3908 err:
3909 bttv_unregister_video(btv);
3910 return -1;
3911}
3912
3913
3914/* on OpenFirmware machines (PowerMac at least), PCI memory cycle */
3915/* response on cards with no firmware is not enabled by OF */
3916static void pci_set_command(struct pci_dev *dev)
3917{
3918#if defined(__powerpc__)
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003919 unsigned int cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003920
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003921 pci_read_config_dword(dev, PCI_COMMAND, &cmd);
3922 cmd = (cmd | PCI_COMMAND_MEMORY );
3923 pci_write_config_dword(dev, PCI_COMMAND, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003924#endif
3925}
3926
3927static int __devinit bttv_probe(struct pci_dev *dev,
3928 const struct pci_device_id *pci_id)
3929{
3930 int result;
3931 unsigned char lat;
3932 struct bttv *btv;
3933
3934 if (bttv_num == BTTV_MAX)
3935 return -ENOMEM;
3936 printk(KERN_INFO "bttv: Bt8xx card found (%d).\n", bttv_num);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003937 btv=&bttvs[bttv_num];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003938 memset(btv,0,sizeof(*btv));
3939 btv->c.nr = bttv_num;
3940 sprintf(btv->c.name,"bttv%d",btv->c.nr);
3941
3942 /* initialize structs / fill in defaults */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003943 init_MUTEX(&btv->lock);
3944 init_MUTEX(&btv->reslock);
3945 spin_lock_init(&btv->s_lock);
3946 spin_lock_init(&btv->gpio_lock);
3947 init_waitqueue_head(&btv->gpioq);
3948 init_waitqueue_head(&btv->i2c_queue);
3949 INIT_LIST_HEAD(&btv->c.subs);
3950 INIT_LIST_HEAD(&btv->capture);
3951 INIT_LIST_HEAD(&btv->vcapture);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003952 v4l2_prio_init(&btv->prio);
3953
3954 init_timer(&btv->timeout);
3955 btv->timeout.function = bttv_irq_timeout;
3956 btv->timeout.data = (unsigned long)btv;
3957
Michael Krufky7c08fb02005-11-08 21:36:21 -08003958 btv->i2c_rc = -1;
3959 btv->tuner_type = UNSET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003960 btv->new_input = UNSET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003961 btv->has_radio=radio[btv->c.nr];
3962
3963 /* pci stuff (init, get irq/mmio, ... */
3964 btv->c.pci = dev;
Michael Krufky7c08fb02005-11-08 21:36:21 -08003965 btv->id = dev->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003966 if (pci_enable_device(dev)) {
Michael Krufky7c08fb02005-11-08 21:36:21 -08003967 printk(KERN_WARNING "bttv%d: Can't enable device.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003968 btv->c.nr);
3969 return -EIO;
3970 }
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003971 if (pci_set_dma_mask(dev, DMA_32BIT_MASK)) {
3972 printk(KERN_WARNING "bttv%d: No suitable DMA available.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003973 btv->c.nr);
3974 return -EIO;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003975 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003976 if (!request_mem_region(pci_resource_start(dev,0),
3977 pci_resource_len(dev,0),
3978 btv->c.name)) {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003979 printk(KERN_WARNING "bttv%d: can't request iomem (0x%lx).\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003980 btv->c.nr, pci_resource_start(dev,0));
3981 return -EBUSY;
3982 }
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003983 pci_set_master(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003984 pci_set_command(dev);
3985 pci_set_drvdata(dev,btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003986
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08003987 pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision);
3988 pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
3989 printk(KERN_INFO "bttv%d: Bt%d (rev %d) at %s, ",
3990 bttv_num,btv->id, btv->revision, pci_name(dev));
3991 printk("irq: %d, latency: %d, mmio: 0x%lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003992 btv->c.pci->irq, lat, pci_resource_start(dev,0));
3993 schedule();
3994
3995 btv->bt848_mmio=ioremap(pci_resource_start(dev,0), 0x1000);
3996 if (NULL == ioremap(pci_resource_start(dev,0), 0x1000)) {
3997 printk("bttv%d: ioremap() failed\n", btv->c.nr);
3998 result = -EIO;
3999 goto fail1;
4000 }
4001
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004002 /* identify card */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004003 bttv_idcard(btv);
4004
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004005 /* disable irqs, register irq handler */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004006 btwrite(0, BT848_INT_MASK);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004007 result = request_irq(btv->c.pci->irq, bttv_irq,
4008 SA_SHIRQ | SA_INTERRUPT,btv->c.name,(void *)btv);
4009 if (result < 0) {
4010 printk(KERN_ERR "bttv%d: can't get IRQ %d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004011 bttv_num,btv->c.pci->irq);
4012 goto fail1;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004013 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004014
4015 if (0 != bttv_handle_chipset(btv)) {
4016 result = -EIO;
4017 goto fail2;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004018 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004019
4020 /* init options from insmod args */
4021 btv->opt_combfilter = combfilter;
4022 btv->opt_lumafilter = lumafilter;
4023 btv->opt_automute = automute;
4024 btv->opt_chroma_agc = chroma_agc;
4025 btv->opt_adc_crush = adc_crush;
4026 btv->opt_vcr_hack = vcr_hack;
4027 btv->opt_whitecrush_upper = whitecrush_upper;
4028 btv->opt_whitecrush_lower = whitecrush_lower;
Mauro Carvalho Chehab060d3022005-06-28 20:45:25 -07004029 btv->opt_uv_ratio = uv_ratio;
4030 btv->opt_full_luma_range = full_luma_range;
4031 btv->opt_coring = coring;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004032
4033 /* fill struct bttv with some useful defaults */
4034 btv->init.btv = btv;
4035 btv->init.ov.w.width = 320;
4036 btv->init.ov.w.height = 240;
4037 btv->init.fmt = format_by_palette(VIDEO_PALETTE_RGB24);
4038 btv->init.width = 320;
4039 btv->init.height = 240;
4040 btv->init.lines = 16;
4041 btv->input = 0;
4042
4043 /* initialize hardware */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004044 if (bttv_gpio)
4045 bttv_gpio_tracking(btv,"pre-init");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046
4047 bttv_risc_init_main(btv);
4048 init_bt848(btv);
4049
4050 /* gpio */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004051 btwrite(0x00, BT848_GPIO_REG_INP);
4052 btwrite(0x00, BT848_GPIO_OUT_EN);
4053 if (bttv_verbose)
4054 bttv_gpio_tracking(btv,"init");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004055
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004056 /* needs to be done before i2c is registered */
4057 bttv_init_card1(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004058
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004059 /* register i2c + gpio */
4060 init_bttv_i2c(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004061
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004062 /* some card-specific stuff (needs working i2c) */
4063 bttv_init_card2(btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004064 init_irqreg(btv);
4065
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004066 /* register video4linux + input */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067 if (!bttv_tvcards[btv->c.type].no_video) {
4068 bttv_register_video(btv);
4069 bt848_bright(btv,32768);
4070 bt848_contrast(btv,32768);
4071 bt848_hue(btv,32768);
4072 bt848_sat(btv,32768);
4073 audio_mux(btv,AUDIO_MUTE);
4074 set_input(btv,0);
4075 }
4076
4077 /* add subdevices */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078 if (bttv_tvcards[btv->c.type].has_dvb)
4079 bttv_sub_add_device(&btv->c, "dvb");
4080
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02004081 bttv_input_init(btv);
4082
Linus Torvalds1da177e2005-04-16 15:20:36 -07004083 /* everything is fine */
4084 bttv_num++;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004085 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004086
4087 fail2:
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004088 free_irq(btv->c.pci->irq,btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004089
4090 fail1:
4091 if (btv->bt848_mmio)
4092 iounmap(btv->bt848_mmio);
4093 release_mem_region(pci_resource_start(btv->c.pci,0),
4094 pci_resource_len(btv->c.pci,0));
4095 pci_set_drvdata(dev,NULL);
4096 return result;
4097}
4098
4099static void __devexit bttv_remove(struct pci_dev *pci_dev)
4100{
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004101 struct bttv *btv = pci_get_drvdata(pci_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004102
4103 if (bttv_verbose)
4104 printk("bttv%d: unloading\n",btv->c.nr);
4105
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004106 /* shutdown everything (DMA+IRQs) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004107 btand(~15, BT848_GPIO_DMA_CTL);
4108 btwrite(0, BT848_INT_MASK);
4109 btwrite(~0x0, BT848_INT_STAT);
4110 btwrite(0x0, BT848_GPIO_OUT_EN);
4111 if (bttv_gpio)
4112 bttv_gpio_tracking(btv,"cleanup");
4113
4114 /* tell gpio modules we are leaving ... */
4115 btv->shutdown=1;
4116 wake_up(&btv->gpioq);
Ricardo Cerqueira4abdfed2006-01-09 15:25:25 -02004117 bttv_input_fini(btv);
Christopher Pascoe889aee82006-01-09 15:25:28 -02004118 bttv_sub_del_devices(&btv->c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004119
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004120 /* unregister i2c_bus + input */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004121 fini_bttv_i2c(btv);
4122
4123 /* unregister video4linux */
4124 bttv_unregister_video(btv);
4125
4126 /* free allocated memory */
4127 btcx_riscmem_free(btv->c.pci,&btv->main);
4128
4129 /* free ressources */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004130 free_irq(btv->c.pci->irq,btv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004131 iounmap(btv->bt848_mmio);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004132 release_mem_region(pci_resource_start(btv->c.pci,0),
4133 pci_resource_len(btv->c.pci,0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004134
4135 pci_set_drvdata(pci_dev, NULL);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004136 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004137}
4138
4139static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state)
4140{
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004141 struct bttv *btv = pci_get_drvdata(pci_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004142 struct bttv_buffer_set idle;
4143 unsigned long flags;
4144
Mauro Carvalho Chehab0f97a932005-09-09 13:04:05 -07004145 dprintk("bttv%d: suspend %d\n", btv->c.nr, state.event);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004146
4147 /* stop dma + irqs */
4148 spin_lock_irqsave(&btv->s_lock,flags);
4149 memset(&idle, 0, sizeof(idle));
4150 btv->state.video = btv->curr;
4151 btv->state.vbi = btv->cvbi;
4152 btv->state.loop_irq = btv->loop_irq;
4153 btv->curr = idle;
4154 btv->loop_irq = 0;
4155 bttv_buffer_activate_video(btv, &idle);
4156 bttv_buffer_activate_vbi(btv, NULL);
4157 bttv_set_dma(btv, 0);
4158 btwrite(0, BT848_INT_MASK);
4159 spin_unlock_irqrestore(&btv->s_lock,flags);
4160
4161 /* save bt878 state */
4162 btv->state.gpio_enable = btread(BT848_GPIO_OUT_EN);
4163 btv->state.gpio_data = gpio_read();
4164
4165 /* save pci state */
4166 pci_save_state(pci_dev);
4167 if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
4168 pci_disable_device(pci_dev);
4169 btv->state.disabled = 1;
4170 }
4171 return 0;
4172}
4173
4174static int bttv_resume(struct pci_dev *pci_dev)
4175{
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004176 struct bttv *btv = pci_get_drvdata(pci_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004177 unsigned long flags;
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004178 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004179
4180 dprintk("bttv%d: resume\n", btv->c.nr);
4181
4182 /* restore pci state */
4183 if (btv->state.disabled) {
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004184 err=pci_enable_device(pci_dev);
4185 if (err) {
4186 printk(KERN_WARNING "bttv%d: Can't enable device.\n",
4187 btv->c.nr);
4188 return err;
4189 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004190 btv->state.disabled = 0;
4191 }
Mauro Carvalho Chehab08adb9e2005-09-09 13:03:55 -07004192 err=pci_set_power_state(pci_dev, PCI_D0);
4193 if (err) {
4194 pci_disable_device(pci_dev);
4195 printk(KERN_WARNING "bttv%d: Can't enable device.\n",
4196 btv->c.nr);
4197 btv->state.disabled = 1;
4198 return err;
4199 }
4200
Linus Torvalds1da177e2005-04-16 15:20:36 -07004201 pci_restore_state(pci_dev);
4202
4203 /* restore bt878 state */
4204 bttv_reinit_bt848(btv);
4205 gpio_inout(0xffffff, btv->state.gpio_enable);
4206 gpio_write(btv->state.gpio_data);
4207
4208 /* restart dma */
4209 spin_lock_irqsave(&btv->s_lock,flags);
4210 btv->curr = btv->state.video;
4211 btv->cvbi = btv->state.vbi;
4212 btv->loop_irq = btv->state.loop_irq;
4213 bttv_buffer_activate_video(btv, &btv->curr);
4214 bttv_buffer_activate_vbi(btv, btv->cvbi);
4215 bttv_set_dma(btv, 0);
4216 spin_unlock_irqrestore(&btv->s_lock,flags);
4217 return 0;
4218}
4219
4220static struct pci_device_id bttv_pci_tbl[] = {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004221 {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848,
4222 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
Linus Torvalds1da177e2005-04-16 15:20:36 -07004223 {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849,
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004224 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
Linus Torvalds1da177e2005-04-16 15:20:36 -07004225 {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878,
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004226 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
Linus Torvalds1da177e2005-04-16 15:20:36 -07004227 {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879,
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004228 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
4229 {0,}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004230};
4231
4232MODULE_DEVICE_TABLE(pci, bttv_pci_tbl);
4233
4234static struct pci_driver bttv_pci_driver = {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08004235 .name = "bttv",
4236 .id_table = bttv_pci_tbl,
4237 .probe = bttv_probe,
4238 .remove = __devexit_p(bttv_remove),
Linus Torvalds1da177e2005-04-16 15:20:36 -07004239 .suspend = bttv_suspend,
4240 .resume = bttv_resume,
4241};
4242
4243static int bttv_init_module(void)
4244{
4245 bttv_num = 0;
4246
4247 printk(KERN_INFO "bttv: driver version %d.%d.%d loaded\n",
4248 (BTTV_VERSION_CODE >> 16) & 0xff,
4249 (BTTV_VERSION_CODE >> 8) & 0xff,
4250 BTTV_VERSION_CODE & 0xff);
4251#ifdef SNAPSHOT
4252 printk(KERN_INFO "bttv: snapshot date %04d-%02d-%02d\n",
4253 SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
4254#endif
4255 if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME)
4256 gbuffers = 2;
4257 if (gbufsize < 0 || gbufsize > BTTV_MAX_FBUF)
4258 gbufsize = BTTV_MAX_FBUF;
4259 gbufsize = (gbufsize + PAGE_SIZE - 1) & PAGE_MASK;
4260 if (bttv_verbose)
4261 printk(KERN_INFO "bttv: using %d buffers with %dk (%d pages) each for capture\n",
4262 gbuffers, gbufsize >> 10, gbufsize >> PAGE_SHIFT);
4263
4264 bttv_check_chipset();
4265
4266 bus_register(&bttv_sub_bus_type);
Otavio Salvador23047592006-01-09 15:25:17 -02004267 return pci_register_driver(&bttv_pci_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004268}
4269
4270static void bttv_cleanup_module(void)
4271{
4272 pci_unregister_driver(&bttv_pci_driver);
4273 bus_unregister(&bttv_sub_bus_type);
4274 return;
4275}
4276
4277module_init(bttv_init_module);
4278module_exit(bttv_cleanup_module);
4279
4280/*
4281 * Local variables:
4282 * c-basic-offset: 8
4283 * End:
4284 */