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