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