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