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