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