Rev 257 | Rev 428 | 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 |
||
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,2000 Gerd Knorr <kraxel@goldbach.in-berlin.de> |
||
7 | |||
8 | This program is free software; you can redistribute it and/or modify |
||
9 | it under the terms of the GNU General Public License as published by |
||
10 | the Free Software Foundation; either version 2 of the License, or |
||
11 | (at your option) any later version. |
||
12 | |||
13 | This program is distributed in the hope that it will be useful, |
||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
16 | GNU General Public License for more details. |
||
17 | |||
18 | You should have received a copy of the GNU General Public License |
||
19 | along with this program; if not, write to the Free Software |
||
20 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
||
21 | */ |
||
22 | |||
23 | /* SHARK version by Giacomo Guidi <giacomo@gandalf.sssup.it> */ |
||
24 | |||
25 | #include <sys/types.h> |
||
26 | #include <string.h> |
||
27 | #include <stdio.h> |
||
28 | #include <unistd.h> |
||
29 | #include <stdlib.h> |
||
30 | #include <linux/pci.h> |
||
31 | |||
32 | #include "drivers/compbttv.h" |
||
33 | #include "drivers/bttv.h" |
||
34 | #include "drivers/tuner.h" |
||
35 | |||
36 | #define DEBUG(x) /* Debug driver */ |
||
37 | #define MIN(a,b) (((a)>(b))?(b):(a)) |
||
38 | #define MAX(a,b) (((a)>(b))?(a):(b)) |
||
39 | |||
40 | static inline int copy_to_user (void *s, void *d, size_t size) |
||
41 | { |
||
42 | memcpy(s,d,size); |
||
43 | return 0; |
||
44 | |||
45 | } |
||
46 | |||
47 | static inline int copy_from_user (void *s, void *d, size_t size) |
||
48 | { |
||
49 | memcpy(s,d,size); |
||
50 | return 0; |
||
51 | |||
52 | } |
||
53 | |||
54 | static void bt848_set_risc_jmps(struct bttv *btv, int state); |
||
55 | |||
56 | int bttv_num; /* number of Bt848s in use */ |
||
57 | int in_irq = 0; |
||
179 | giacomo | 58 | DWORD oldpci_command; |
170 | giacomo | 59 | struct bttv *btvirq; |
60 | struct bttv bttvs[BTTV_MAX]; |
||
61 | |||
62 | /* configuration variables */ |
||
63 | #if defined(__sparc__) || defined(__powerpc__) || defined(__hppa__) |
||
64 | static unsigned int bigendian=1; |
||
65 | #else |
||
66 | static unsigned int bigendian=0; |
||
67 | #endif |
||
68 | static unsigned int radio[BTTV_MAX]; |
||
69 | static unsigned int fieldnr = 0; |
||
70 | static unsigned int irq_debug = 0; |
||
71 | static unsigned int gbuffers = 2; |
||
72 | unsigned int gbufsize = BTTV_MAX_FBUF; |
||
73 | static int latency = -1; |
||
74 | |||
75 | static unsigned int combfilter = 0; |
||
76 | static unsigned int lumafilter = 0; |
||
77 | static unsigned int chroma_agc = 0; |
||
78 | static unsigned int adc_crush = 1; |
||
79 | unsigned int bttv_debug = 0; |
||
80 | unsigned int bttv_verbose = 1; |
||
81 | unsigned int bttv_gpio = 0; |
||
82 | |||
83 | //#define I2C_TIMING (0x7<<4) |
||
84 | //#define I2C_DELAY 10 |
||
85 | |||
86 | #define I2C_TIMING (0x3<<4) |
||
87 | #define I2C_DELAY 40 |
||
88 | |||
89 | #define I2C_SET(CTRL,DATA) \ |
||
90 | { btwrite((CTRL<<1)|(DATA), BT848_I2C); udelay(I2C_DELAY); } |
||
91 | #define I2C_GET() (btread(BT848_I2C)&1) |
||
92 | |||
93 | #define BURSTOFFSET 76 |
||
94 | #define BTTV_ERRORS 5 |
||
95 | |||
96 | |||
97 | /*******************************/ |
||
98 | /* Memory management functions */ |
||
99 | /*******************************/ |
||
100 | |||
101 | #define MDEBUG(x) do { } while(0) /* Debug memory management */ |
||
102 | |||
103 | /* [DaveM] I've recoded most of this so that: |
||
104 | * 1) It's easier to tell what is happening |
||
105 | * 2) It's more portable, especially for translating things |
||
106 | * out of vmalloc mapped areas in the kernel. |
||
107 | * 3) Less unnecessary translations happen. |
||
108 | * |
||
109 | * The code used to assume that the kernel vmalloc mappings |
||
110 | * existed in the page tables of every process, this is simply |
||
111 | * not guarenteed. We now use pgd_offset_k which is the |
||
112 | * defined way to get at the kernel page tables. |
||
113 | */ |
||
114 | |||
115 | |||
116 | static inline unsigned long cpu_to_le32(unsigned long adr) |
||
117 | { |
||
118 | return adr; |
||
119 | } |
||
120 | |||
121 | static inline unsigned long virt_to_bus(unsigned long adr) |
||
122 | { |
||
123 | return (unsigned long)(adr); |
||
124 | } |
||
125 | |||
126 | static void * vmalloc_32(size_t size) |
||
127 | { |
||
128 | void *mem; |
||
129 | unsigned long diff; |
||
130 | |||
131 | mem = malloc(size+8); |
||
132 | |||
133 | diff = (unsigned long)((((unsigned long)mem/4)+1)*4-(unsigned long)mem); |
||
134 | |||
135 | *(unsigned long *)(mem+diff) = (unsigned long)diff; |
||
136 | |||
137 | return (mem+diff+4); |
||
138 | |||
139 | } |
||
140 | |||
141 | static void vfree_32(void *ptr) |
||
142 | { |
||
143 | |||
144 | free(ptr-4-*(unsigned long *)(ptr-4)); |
||
145 | |||
146 | } |
||
147 | |||
148 | void bttv_gpio_tracking(struct bttv *btv, char *comment) |
||
149 | { |
||
150 | unsigned int outbits, data; |
||
151 | outbits = btread(BT848_GPIO_OUT_EN); |
||
152 | data = gpioread(); |
||
153 | printk(KERN_DEBUG "bttv%d: gpio: en=%08x, out=%08x in=%08x [%s]\n", |
||
154 | btv->nr,outbits,data & outbits, data & ~outbits, comment); |
||
155 | } |
||
156 | |||
157 | static inline void bt848_dma(struct bttv *btv, uint state) |
||
158 | { |
||
159 | if (state) |
||
160 | btor(3, BT848_GPIO_DMA_CTL); |
||
161 | else |
||
162 | btand(~3, BT848_GPIO_DMA_CTL); |
||
163 | } |
||
164 | |||
165 | |||
166 | /* If Bt848a or Bt849, use PLL for PAL/SECAM and crystal for NTSC*/ |
||
167 | |||
168 | /* Frequency = (F_input / PLL_X) * PLL_I.PLL_F/PLL_C |
||
169 | PLL_X = Reference pre-divider (0=1, 1=2) |
||
170 | PLL_C = Post divider (0=6, 1=4) |
||
171 | PLL_I = Integer input |
||
172 | PLL_F = Fractional input |
||
173 | |||
174 | F_input = 28.636363 MHz: |
||
175 | PAL (CLKx2 = 35.46895 MHz): PLL_X = 1, PLL_I = 0x0E, PLL_F = 0xDCF9, PLL_C = 0 |
||
176 | */ |
||
177 | |||
178 | static void set_pll_freq(struct bttv *btv, unsigned int fin, unsigned int fout) |
||
179 | { |
||
180 | unsigned char fl, fh, fi; |
||
181 | |||
182 | /* prevent overflows */ |
||
183 | fin/=4; |
||
184 | fout/=4; |
||
185 | |||
186 | fout*=12; |
||
187 | fi=fout/fin; |
||
188 | |||
189 | fout=(fout%fin)*256; |
||
190 | fh=fout/fin; |
||
191 | |||
192 | fout=(fout%fin)*256; |
||
193 | fl=fout/fin; |
||
194 | |||
195 | /*printk("0x%02x 0x%02x 0x%02x\n", fi, fh, fl);*/ |
||
196 | btwrite(fl, BT848_PLL_F_LO); |
||
197 | btwrite(fh, BT848_PLL_F_HI); |
||
198 | btwrite(fi|BT848_PLL_X, BT848_PLL_XCI); |
||
199 | } |
||
200 | |||
201 | static int set_pll(struct bttv *btv) |
||
202 | { |
||
203 | int i; |
||
204 | |||
205 | if (!btv->pll.pll_crystal) |
||
206 | return 0; |
||
207 | |||
208 | if (btv->pll.pll_ifreq == btv->pll.pll_ofreq) { |
||
209 | /* no PLL needed */ |
||
210 | if (btv->pll.pll_current == 0) { |
||
211 | /* printk ("bttv%d: PLL: is off\n",btv->nr); */ |
||
212 | return 0; |
||
213 | } |
||
214 | if (bttv_verbose) |
||
215 | printk(KERN_INFO "bttv%d: PLL: switching off\n",btv->nr); |
||
216 | btwrite(0x00,BT848_TGCTRL); |
||
217 | btwrite(0x00,BT848_PLL_XCI); |
||
218 | btv->pll.pll_current = 0; |
||
219 | return 0; |
||
220 | } |
||
221 | |||
222 | if (btv->pll.pll_ofreq == btv->pll.pll_current) { |
||
223 | /* printk("bttv%d: PLL: no change required\n",btv->nr); */ |
||
224 | return 1; |
||
225 | } |
||
226 | |||
227 | if (bttv_verbose) |
||
228 | cprintf("[info ] bttv%d: PLL: %d => %d ... ",btv->nr, |
||
229 | btv->pll.pll_ifreq, btv->pll.pll_ofreq); |
||
230 | |||
231 | set_pll_freq(btv, btv->pll.pll_ifreq, btv->pll.pll_ofreq); |
||
232 | |||
233 | /* Let other people run while the PLL stabilizes */ |
||
234 | udelay(100000); |
||
235 | |||
236 | for (i=0; i<100; i++) |
||
237 | { |
||
238 | if ((btread(BT848_DSTATUS)&BT848_DSTATUS_PLOCK)) |
||
239 | btwrite(0,BT848_DSTATUS); |
||
240 | else |
||
241 | { |
||
242 | btwrite(0x08,BT848_TGCTRL); |
||
243 | btv->pll.pll_current = btv->pll.pll_ofreq; |
||
244 | if (bttv_verbose) |
||
245 | cprintf("ok\n"); |
||
246 | return 1; |
||
247 | } |
||
248 | udelay(10000); |
||
249 | } |
||
250 | btv->pll.pll_current = 0; |
||
251 | if (bttv_verbose) |
||
252 | cprintf("oops\n"); |
||
253 | return -1; |
||
254 | } |
||
255 | |||
256 | static void bt848_muxsel(struct bttv *btv, unsigned int input) |
||
257 | { |
||
258 | /* needed by RemoteVideo MX */ |
||
259 | btor(bttv_tvcards[btv->type].gpiomask2,BT848_GPIO_OUT_EN); |
||
260 | |||
261 | /* This seems to get rid of some synchronization problems */ |
||
262 | btand(~(3<<5), BT848_IFORM); |
||
263 | udelay(10000); |
||
264 | |||
265 | input %= bttv_tvcards[btv->type].video_inputs; |
||
266 | if (input==bttv_tvcards[btv->type].svhs) |
||
267 | { |
||
268 | btor(BT848_CONTROL_COMP, BT848_E_CONTROL); |
||
269 | btor(BT848_CONTROL_COMP, BT848_O_CONTROL); |
||
270 | } |
||
271 | else |
||
272 | { |
||
273 | btand(~BT848_CONTROL_COMP, BT848_E_CONTROL); |
||
274 | btand(~BT848_CONTROL_COMP, BT848_O_CONTROL); |
||
275 | } |
||
276 | |||
277 | btaor((bttv_tvcards[btv->type].muxsel[input]&3)<<5, ~(3<<5), BT848_IFORM); |
||
278 | |||
279 | gpioaor(bttv_tvcards[btv->type].muxsel[input]>>4, |
||
280 | ~bttv_tvcards[btv->type].gpiomask2); |
||
281 | |||
282 | /* card specific hook */ |
||
283 | if( bttv_tvcards[btv->type].muxsel_hook ) |
||
284 | bttv_tvcards[btv->type].muxsel_hook ( btv, input ); |
||
285 | |||
286 | if (bttv_gpio) |
||
287 | bttv_gpio_tracking(btv,"muxsel"); |
||
288 | |||
289 | } |
||
290 | |||
291 | |||
292 | struct tvnorm |
||
293 | { |
||
294 | u32 Fsc; |
||
295 | u16 swidth, sheight; /* scaled standard width, height */ |
||
296 | u16 totalwidth; |
||
297 | u8 adelay, bdelay, iform; |
||
298 | u32 scaledtwidth; |
||
299 | u16 hdelayx1, hactivex1; |
||
300 | u16 vdelay; |
||
301 | u8 vbipack; |
||
302 | }; |
||
303 | |||
304 | static struct tvnorm tvnorms[] = { |
||
305 | /* PAL-BDGHI */ |
||
306 | /* max. active video is actually 922, but 924 is divisible by 4 and 3! */ |
||
307 | /* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */ |
||
308 | { 35468950, |
||
309 | 924, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1), |
||
310 | 1135, 186, 924, |
||
311 | #ifdef VIDEODAT_HACK |
||
312 | VBI_MAXLINES*2, |
||
313 | #else |
||
314 | 0x20, |
||
315 | #endif |
||
316 | 255}, |
||
317 | |||
318 | /* NTSC */ |
||
319 | { 28636363, |
||
320 | 768, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC|BT848_IFORM_XT0), |
||
321 | 910, 128, 910, 0x1a, 144}, |
||
322 | #if 0 |
||
323 | /* SECAM EAST */ |
||
324 | { 35468950, |
||
325 | 768, 576, 1135, 0x7f, 0xb0, (BT848_IFORM_SECAM|BT848_IFORM_XT1), |
||
326 | 944, 186, 922, 0x20, 255}, |
||
327 | #else |
||
328 | /* SECAM L */ |
||
329 | { 35468950, |
||
330 | 924, 576, 1135, 0x7f, 0xb0, (BT848_IFORM_SECAM|BT848_IFORM_XT1), |
||
331 | 1135, 186, 922, 0x20, 255}, |
||
332 | #endif |
||
333 | /* PAL-NC */ |
||
334 | { 28636363, |
||
335 | 640, 576, 910, 0x68, 0x5d, (BT848_IFORM_PAL_NC|BT848_IFORM_XT0), |
||
336 | 780, 130, 734, 0x1a, 144}, |
||
337 | /* PAL-M */ |
||
338 | { 28636363, |
||
339 | 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_PAL_M|BT848_IFORM_XT0), |
||
340 | 780, 135, 754, 0x1a, 144}, |
||
341 | /* PAL-N */ |
||
342 | { 35468950, |
||
343 | 768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_N|BT848_IFORM_XT1), |
||
344 | 944, 186, 922, 0x20, 144}, |
||
345 | /* NTSC-Japan */ |
||
346 | { 28636363, |
||
347 | 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC_J|BT848_IFORM_XT0), |
||
348 | 780, 135, 754, 0x16, 144}, |
||
349 | }; |
||
350 | #define TVNORMS (sizeof(tvnorms)/sizeof(tvnorm)) |
||
351 | #define VBI_SPL 2044 |
||
352 | |||
353 | /* RISC command to write one VBI data line */ |
||
354 | #define VBI_RISC BT848_RISC_WRITE|VBI_SPL|BT848_RISC_EOL|BT848_RISC_SOL |
||
355 | |||
356 | static void make_vbitab(struct bttv *btv) |
||
357 | { |
||
358 | int i; |
||
359 | unsigned int *po=(unsigned int *) btv->vbi_odd; |
||
360 | unsigned int *pe=(unsigned int *) btv->vbi_even; |
||
361 | |||
362 | if (bttv_debug > 1) |
||
363 | cprintf("bttv%d: vbi1: po=%08lx pe=%08lx\n", |
||
364 | btv->nr,virt_to_bus((unsigned long)po), virt_to_bus((unsigned long)pe)); |
||
365 | |||
366 | *(po++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(po++)=0; |
||
367 | for (i=0; i<VBI_MAXLINES; i++) |
||
368 | { |
||
369 | *(po++)=cpu_to_le32(VBI_RISC); |
||
370 | *(po++)=cpu_to_le32(virt_to_bus((unsigned long)btv->vbibuf+i*2048)); |
||
371 | } |
||
372 | *(po++)=cpu_to_le32(BT848_RISC_JUMP); |
||
373 | *(po++)=cpu_to_le32(virt_to_bus((unsigned long)btv->risc_jmp+16)); |
||
374 | |||
375 | *(pe++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(pe++)=0; |
||
376 | for (i=VBI_MAXLINES; i<VBI_MAXLINES*2; i++) |
||
377 | { |
||
378 | *(pe++)=cpu_to_le32(VBI_RISC); |
||
379 | *(pe++)=cpu_to_le32(virt_to_bus((unsigned long)btv->vbibuf+i*2048)); |
||
380 | } |
||
381 | *(pe++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(0x01<<16)); |
||
382 | *(pe++)=cpu_to_le32(virt_to_bus((unsigned long)btv->risc_jmp+40)); |
||
383 | |||
384 | if (bttv_debug > 1) |
||
385 | cprintf("bttv%d: vbi2: po=%08lx pe=%08lx\n", |
||
386 | btv->nr,virt_to_bus((unsigned long)po), virt_to_bus((unsigned long)pe)); |
||
387 | } |
||
388 | |||
389 | static int fmtbppx2[16] = { |
||
390 | 8, 6, 4, 4, 4, 3, 2, 2, 4, 3, 0, 0, 0, 0, 2, 0 |
||
391 | }; |
||
392 | |||
393 | static int palette2fmt[] = { |
||
394 | 0, |
||
395 | BT848_COLOR_FMT_Y8, |
||
396 | BT848_COLOR_FMT_RGB8, |
||
397 | BT848_COLOR_FMT_RGB16, |
||
398 | BT848_COLOR_FMT_RGB24, |
||
399 | BT848_COLOR_FMT_RGB32, |
||
400 | BT848_COLOR_FMT_RGB15, |
||
401 | BT848_COLOR_FMT_YUY2, |
||
402 | BT848_COLOR_FMT_YUY2, |
||
403 | -1, |
||
404 | -1, |
||
405 | -1, |
||
406 | BT848_COLOR_FMT_RAW, |
||
407 | BT848_COLOR_FMT_YCrCb422, |
||
408 | BT848_COLOR_FMT_YCrCb411, |
||
409 | BT848_COLOR_FMT_YCrCb422, |
||
410 | BT848_COLOR_FMT_YCrCb411, |
||
411 | }; |
||
412 | #define PALETTEFMT_MAX (sizeof(palette2fmt)/sizeof(int)) |
||
413 | |||
414 | static int make_rawrisctab(struct bttv *btv, unsigned int *ro, |
||
415 | unsigned int *re, unsigned int *vbuf) |
||
416 | { |
||
417 | unsigned long line; |
||
418 | unsigned long bpl=1024; /* bytes per line */ |
||
419 | unsigned long vadr = (unsigned long)vbuf; |
||
420 | |||
421 | *(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); |
||
422 | *(ro++)=cpu_to_le32(0); |
||
423 | *(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); |
||
424 | *(re++)=cpu_to_le32(0); |
||
425 | |||
426 | /* In PAL 650 blocks of 256 DWORDs are sampled, but only if VDELAY |
||
427 | is 2 and without separate VBI grabbing. |
||
428 | We'll have to handle this inside the IRQ handler ... */ |
||
429 | |||
430 | for (line=0; line < 640; line++) |
||
431 | { |
||
432 | *(ro++)=cpu_to_le32(BT848_RISC_WRITE|bpl|BT848_RISC_SOL|BT848_RISC_EOL); |
||
433 | *(ro++)=cpu_to_le32(virt_to_bus(vadr)); |
||
434 | *(re++)=cpu_to_le32(BT848_RISC_WRITE|bpl|BT848_RISC_SOL|BT848_RISC_EOL); |
||
435 | *(re++)=cpu_to_le32(virt_to_bus(vadr+gbufsize/2)); |
||
436 | vadr+=bpl; |
||
437 | } |
||
438 | |||
439 | *(ro++)=cpu_to_le32(BT848_RISC_JUMP); |
||
440 | *(ro++)=cpu_to_le32(btv->bus_vbi_even); |
||
441 | *(re++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16)); |
||
442 | *(re++)=cpu_to_le32(btv->bus_vbi_odd); |
||
443 | |||
444 | return 0; |
||
445 | } |
||
446 | |||
447 | static int make_prisctab(struct bttv *btv, unsigned int *ro, |
||
448 | unsigned int *re, |
||
449 | unsigned int *vbuf, unsigned short width, |
||
450 | unsigned short height, unsigned short fmt) |
||
451 | { |
||
452 | unsigned long line, lmask; |
||
453 | unsigned long bl, blcr, blcb, rcmd; |
||
454 | unsigned long todo; |
||
455 | unsigned int **rp; |
||
456 | int inter; |
||
457 | unsigned long cbadr, cradr; |
||
458 | unsigned long vadr=(unsigned long) vbuf; |
||
459 | int shift, csize; |
||
460 | |||
461 | if (bttv_debug > 1) |
||
462 | cprintf("bttv%d: prisc1: ro=%08lx re=%08lx\n", |
||
463 | btv->nr,virt_to_bus((unsigned long)ro), virt_to_bus((unsigned long)re)); |
||
464 | |||
465 | switch(fmt) |
||
466 | { |
||
467 | case VIDEO_PALETTE_YUV422P: |
||
468 | csize=(width*height)>>1; |
||
469 | shift=1; |
||
470 | lmask=0; |
||
471 | break; |
||
472 | |||
473 | case VIDEO_PALETTE_YUV411P: |
||
474 | csize=(width*height)>>2; |
||
475 | shift=2; |
||
476 | lmask=0; |
||
477 | break; |
||
478 | |||
479 | case VIDEO_PALETTE_YUV420P: |
||
480 | csize=(width*height)>>2; |
||
481 | shift=1; |
||
482 | lmask=1; |
||
483 | break; |
||
484 | |||
485 | case VIDEO_PALETTE_YUV410P: |
||
486 | csize=(width*height)>>4; |
||
487 | shift=2; |
||
488 | lmask=3; |
||
489 | break; |
||
490 | |||
491 | default: |
||
492 | return -1; |
||
493 | } |
||
494 | cbadr=vadr+(width*height); |
||
495 | cradr=cbadr+csize; |
||
496 | inter = (height>tvnorms[btv->win.norm].sheight/2) ? 1 : 0; |
||
497 | |||
498 | *(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3); |
||
499 | *(ro++)=0; |
||
500 | *(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3); |
||
501 | *(re++)=0; |
||
502 | |||
503 | for (line=0; line < (height<<(1^inter)); line++) |
||
504 | { |
||
505 | if(line==height) |
||
506 | { |
||
507 | vadr+=csize<<1; |
||
508 | cbadr=vadr+(width*height); |
||
509 | cradr=cbadr+csize; |
||
510 | } |
||
511 | if (inter) |
||
512 | rp= (line&1) ? &re : &ro; |
||
513 | else |
||
514 | rp= (line>=height) ? &ro : &re; |
||
515 | |||
516 | |||
517 | if(line&lmask) |
||
518 | rcmd=BT848_RISC_WRITE1S23|BT848_RISC_SOL; |
||
519 | else |
||
520 | rcmd=BT848_RISC_WRITE123|BT848_RISC_SOL; |
||
521 | |||
522 | todo=width; |
||
523 | while(todo) |
||
524 | { |
||
525 | bl=PAGE_SIZE-((PAGE_SIZE-1)&vadr); |
||
526 | blcr=(PAGE_SIZE-((PAGE_SIZE-1)&cradr))<<shift; |
||
527 | blcb=(PAGE_SIZE-((PAGE_SIZE-1)&cbadr))<<shift; |
||
528 | bl=(blcr<bl) ? blcr : bl; |
||
529 | bl=(blcb<bl) ? blcb : bl; |
||
530 | bl=(bl>todo) ? todo : bl; |
||
531 | blcr=bl>>shift; |
||
532 | blcb=blcr; |
||
533 | /* bl now containts the longest row that can be written */ |
||
534 | todo-=bl; |
||
535 | if(!todo) rcmd|=BT848_RISC_EOL; /* if this is the last EOL */ |
||
536 | |||
537 | *((*rp)++)=cpu_to_le32(rcmd|bl); |
||
538 | *((*rp)++)=cpu_to_le32(blcb|(blcr<<16)); |
||
539 | *((*rp)++)=cpu_to_le32(virt_to_bus(vadr)); |
||
540 | vadr+=bl; |
||
541 | if((rcmd&(15<<28))==BT848_RISC_WRITE123) |
||
542 | { |
||
543 | *((*rp)++)=cpu_to_le32(virt_to_bus(cbadr)); |
||
544 | cbadr+=blcb; |
||
545 | *((*rp)++)=cpu_to_le32(virt_to_bus(cradr)); |
||
546 | cradr+=blcr; |
||
547 | } |
||
548 | |||
549 | rcmd&=~BT848_RISC_SOL; /* only the first has SOL */ |
||
550 | } |
||
551 | } |
||
552 | |||
553 | *(ro++)=cpu_to_le32(BT848_RISC_JUMP); |
||
554 | *(ro++)=cpu_to_le32(btv->bus_vbi_even); |
||
555 | *(re++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16)); |
||
556 | *(re++)=cpu_to_le32(btv->bus_vbi_odd); |
||
557 | |||
558 | if (bttv_debug > 1) |
||
559 | cprintf("bttv%d: prisc2: ro=%08lx re=%08lx\n", |
||
560 | btv->nr,virt_to_bus((unsigned long)ro), virt_to_bus((unsigned long)re)); |
||
561 | |||
562 | return 0; |
||
563 | } |
||
564 | |||
565 | static int make_vrisctab(struct bttv *btv, unsigned int *ro, |
||
566 | unsigned int *re, |
||
567 | unsigned int *vbuf, unsigned short width, |
||
568 | unsigned short height, unsigned short palette) |
||
569 | { |
||
570 | unsigned long line; |
||
571 | unsigned long bpl; /* bytes per line */ |
||
572 | unsigned int **rp; |
||
573 | int inter; |
||
574 | unsigned long vadr=(unsigned long) vbuf; |
||
575 | |||
576 | if (palette==VIDEO_PALETTE_RAW) |
||
577 | return make_rawrisctab(btv, ro, re, vbuf); |
||
578 | if (palette>=VIDEO_PALETTE_PLANAR) |
||
579 | return make_prisctab(btv, ro, re, vbuf, width, height, palette); |
||
580 | |||
581 | if (bttv_debug > 1) |
||
582 | cprintf("bttv%d: vrisc1: ro=%08lx re=%08lx\n", |
||
583 | btv->nr,virt_to_bus((unsigned long)ro), virt_to_bus((unsigned long)re)); |
||
584 | |||
585 | inter = (height>tvnorms[btv->win.norm].sheight/2) ? 1 : 0; |
||
586 | bpl=width*fmtbppx2[palette2fmt[palette]&0xf]/2; |
||
587 | |||
588 | *(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); |
||
589 | *(ro++)=cpu_to_le32(0); |
||
590 | *(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); |
||
591 | *(re++)=cpu_to_le32(0); |
||
592 | |||
593 | for (line=0; line < (height<<(1^inter)); line++) |
||
594 | { |
||
595 | if (inter) |
||
596 | rp= (line&1) ? &re : &ro; |
||
597 | else |
||
598 | rp= (line>=height) ? &ro : &re; |
||
599 | |||
600 | *((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL| |
||
601 | BT848_RISC_EOL|bpl); |
||
602 | *((*rp)++)=cpu_to_le32(virt_to_bus(vadr)); |
||
603 | vadr+=bpl; |
||
604 | } |
||
605 | |||
606 | *(ro++)=cpu_to_le32(BT848_RISC_JUMP); |
||
607 | *(ro++)=cpu_to_le32(btv->bus_vbi_even); |
||
608 | *(re++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16)); |
||
609 | *(re++)=cpu_to_le32(btv->bus_vbi_odd); |
||
610 | |||
611 | if (bttv_debug > 1) |
||
612 | cprintf("bttv%d: vrisc2: ro=%08lx re=%08lx\n", |
||
613 | btv->nr,virt_to_bus((unsigned long)ro), virt_to_bus((unsigned long)re)); |
||
614 | |||
615 | return 0; |
||
616 | } |
||
617 | |||
618 | static unsigned char lmaskt[8] = |
||
619 | { 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80}; |
||
620 | static unsigned char rmaskt[8] = |
||
621 | { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; |
||
622 | |||
623 | static void clip_draw_rectangle(unsigned char *clipmap, int x, int y, int w, int h) |
||
624 | { |
||
625 | unsigned char lmask, rmask, *p; |
||
626 | int W, l, r; |
||
627 | int i; |
||
628 | |||
629 | if (bttv_debug > 1) |
||
630 | cprintf("bttv clip: %dx%d+%d+%d\n",w,h,x,y); |
||
631 | |||
632 | /* bitmap is fixed width, 128 bytes (1024 pixels represented) */ |
||
633 | if (x<0) |
||
634 | { |
||
635 | w+=x; |
||
636 | x=0; |
||
637 | } |
||
638 | if (y<0) |
||
639 | { |
||
640 | h+=y; |
||
641 | y=0; |
||
642 | } |
||
643 | if (w < 0 || h < 0) /* catch bad clips */ |
||
644 | return; |
||
645 | /* out of range data should just fall through */ |
||
646 | if (y+h>=625) |
||
647 | h=625-y; |
||
648 | if (x+w>=1024) |
||
649 | w=1024-x; |
||
650 | |||
651 | l=x>>3; |
||
652 | r=(x+w-1)>>3; |
||
653 | W=r-l-1; |
||
654 | lmask=lmaskt[x&7]; |
||
655 | rmask=rmaskt[(x+w-1)&7]; |
||
656 | p=clipmap+128*y+l; |
||
657 | |||
658 | if (W>0) |
||
659 | { |
||
660 | for (i=0; i<h; i++, p+=128) |
||
661 | { |
||
662 | *p|=lmask; |
||
663 | memset(p+1, 0xff, W); |
||
664 | p[W+1]|=rmask; |
||
665 | } |
||
666 | } else if (!W) { |
||
667 | for (i=0; i<h; i++, p+=128) |
||
668 | { |
||
669 | p[0]|=lmask; |
||
670 | p[1]|=rmask; |
||
671 | } |
||
672 | } else { |
||
673 | for (i=0; i<h; i++, p+=128) |
||
674 | p[0]|=lmask&rmask; |
||
675 | } |
||
676 | |||
677 | |||
678 | } |
||
679 | |||
680 | static void make_clip_tab(struct bttv *btv, struct video_clip *cr, int ncr) |
||
681 | { |
||
682 | int i, line, x, y, bpl, width, height, inter, maxw; |
||
683 | unsigned int bpp, dx, sx, **rp, *ro, *re, flags, len; |
||
684 | unsigned long adr; |
||
685 | unsigned char *clipmap, *clipline, cbit, lastbit, outofmem; |
||
686 | |||
687 | /* take care: bpp != btv->win.bpp is allowed here */ |
||
688 | bpp = fmtbppx2[btv->win.color_fmt&0xf]/2; |
||
689 | bpl=btv->win.bpl; |
||
690 | adr=btv->win.vidadr + btv->win.x * btv->win.bpp + btv->win.y * bpl; |
||
691 | inter=(btv->win.interlace&1)^1; |
||
692 | width=btv->win.width; |
||
693 | height=btv->win.height; |
||
694 | if (bttv_debug > 1) |
||
695 | cprintf("bttv%d: clip1: pal=%d size=%dx%d, bpl=%d bpp=%d\n", |
||
696 | btv->nr,btv->picture.palette,width,height,bpl,bpp); |
||
697 | if(width > 1023) |
||
698 | width = 1023; /* sanity check */ |
||
699 | if(height > 625) |
||
700 | height = 625; /* sanity check */ |
||
701 | ro=(unsigned int *)btv->risc_scr_odd; |
||
702 | re=(unsigned int *)btv->risc_scr_even; |
||
703 | |||
704 | if (bttv_debug) |
||
705 | cprintf("bttv%d: clip: ro=%08lx re=%08lx\n", |
||
706 | btv->nr,virt_to_bus((unsigned long)ro), virt_to_bus((unsigned long)re)); |
||
707 | |||
708 | if ((clipmap=vmalloc_32(VIDEO_CLIPMAP_SIZE))==NULL) { |
||
709 | /* can't clip, don't generate any risc code */ |
||
710 | *(ro++)=cpu_to_le32(BT848_RISC_JUMP); |
||
711 | *(ro++)=cpu_to_le32(btv->bus_vbi_even); |
||
712 | *(re++)=cpu_to_le32(BT848_RISC_JUMP); |
||
713 | *(re++)=cpu_to_le32(btv->bus_vbi_odd); |
||
714 | } |
||
715 | if (ncr < 0) { /* bitmap was pased */ |
||
716 | memcpy(clipmap, (unsigned char *)cr, VIDEO_CLIPMAP_SIZE); |
||
717 | } else { /* convert rectangular clips to a bitmap */ |
||
718 | memset(clipmap, 0, VIDEO_CLIPMAP_SIZE); /* clear map */ |
||
719 | for (i=0; i<ncr; i++) |
||
720 | clip_draw_rectangle(clipmap, cr[i].x, cr[i].y, |
||
721 | cr[i].width, cr[i].height); |
||
722 | } |
||
723 | /* clip against viewing window AND screen |
||
724 | so we do not have to rely on the user program |
||
725 | */ |
||
726 | maxw = (bpl - btv->win.x * btv->win.bpp) / bpp; |
||
727 | clip_draw_rectangle(clipmap, (width > maxw) ? maxw : width, |
||
728 | 0, 1024, 768); |
||
729 | clip_draw_rectangle(clipmap,0,(btv->win.y+height>btv->win.sheight) ? |
||
730 | (btv->win.sheight-btv->win.y) : height,1024,768); |
||
731 | if (btv->win.x<0) |
||
732 | clip_draw_rectangle(clipmap, 0, 0, -(btv->win.x), 768); |
||
733 | if (btv->win.y<0) |
||
734 | clip_draw_rectangle(clipmap, 0, 0, 1024, -(btv->win.y)); |
||
735 | |||
736 | *(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); |
||
737 | *(ro++)=cpu_to_le32(0); |
||
738 | *(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); |
||
739 | *(re++)=cpu_to_le32(0); |
||
740 | |||
741 | /* translate bitmap to risc code */ |
||
742 | for (line=outofmem=0; line < (height<<inter) && !outofmem; line++) |
||
743 | { |
||
744 | y = line>>inter; |
||
745 | rp= (line&1) ? &re : &ro; |
||
746 | clipline = clipmap + (y<<7); /* running pointers ... */ |
||
747 | lastbit = *clipline & 1; |
||
748 | for(x=dx=0,sx=0; x<=width && !outofmem;) { |
||
749 | if (0 == (x&7)) { |
||
750 | /* check bytes not bits if we can ... */ |
||
751 | if (lastbit) { |
||
752 | while (0xff==*clipline && x<width-8) { |
||
753 | x += 8; |
||
754 | dx += 8; |
||
755 | clipline++; |
||
756 | } |
||
757 | } else { |
||
758 | while (0x00==*clipline && x<width-8) { |
||
759 | x += 8; |
||
760 | dx += 8; |
||
761 | clipline++; |
||
762 | } |
||
763 | } |
||
764 | } |
||
765 | cbit = *clipline & (1<<(x&7)); |
||
766 | if (x < width && !lastbit == !cbit) { |
||
767 | dx++; |
||
768 | } else { |
||
769 | /* generate the dma controller code */ |
||
770 | len = dx * bpp; |
||
771 | flags = ((bpp==4) ? BT848_RISC_BYTE3 : 0); |
||
772 | flags |= ((!sx) ? BT848_RISC_SOL : 0); |
||
773 | flags |= ((sx + dx == width) ? BT848_RISC_EOL : 0); |
||
774 | if (!lastbit) { |
||
775 | *((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|flags|len); |
||
776 | *((*rp)++)=cpu_to_le32(adr + bpp * sx); |
||
777 | } else { |
||
778 | *((*rp)++)=cpu_to_le32(BT848_RISC_SKIP|flags|len); |
||
779 | } |
||
780 | lastbit=cbit; |
||
781 | sx += dx; |
||
782 | dx = 1; |
||
783 | if (ro - (unsigned int *)btv->risc_scr_odd>(RISCMEM_LEN>>3) - 16) |
||
784 | outofmem++; |
||
785 | if (re - (unsigned int *)btv->risc_scr_even>(RISCMEM_LEN>>3) - 16) |
||
786 | outofmem++; |
||
787 | } |
||
788 | x++; |
||
789 | if (0 == (x&7)) |
||
790 | clipline++; |
||
791 | } |
||
792 | if ((!inter)||(line&1)) |
||
793 | adr+=bpl; |
||
794 | } |
||
795 | |||
796 | vfree_32(clipmap); |
||
797 | /* outofmem flag relies on the following code to discard extra data */ |
||
798 | *(ro++)=cpu_to_le32(BT848_RISC_JUMP); |
||
799 | *(ro++)=cpu_to_le32(btv->bus_vbi_even); |
||
800 | *(re++)=cpu_to_le32(BT848_RISC_JUMP); |
||
801 | *(re++)=cpu_to_le32(btv->bus_vbi_odd); |
||
802 | |||
803 | if (bttv_debug > 1) |
||
804 | cprintf("bttv%d: clip2: pal=%d size=%dx%d, bpl=%d bpp=%d\n", |
||
805 | btv->nr,btv->picture.palette,width,height,bpl,bpp); |
||
806 | } |
||
807 | |||
808 | /* |
||
809 | * Set the registers for the size we have specified. Don't bother |
||
810 | * trying to understand this without the BT848 manual in front of |
||
811 | * you [AC]. |
||
812 | * |
||
813 | * PS: The manual is free for download in .pdf format from |
||
814 | * www.brooktree.com - nicely done those folks. |
||
815 | */ |
||
816 | |||
817 | static inline void bt848_set_eogeo(struct bttv *btv, struct tvnorm *tvn, |
||
818 | int odd, int width, int height) |
||
819 | { |
||
820 | u16 vscale, hscale; |
||
821 | u32 xsf, sr; |
||
822 | u16 hdelay; |
||
823 | u8 crop, vtc; |
||
824 | int inter = (height>tvn->sheight/2) ? 0 : 1; |
||
825 | int off = odd ? 0x80 : 0x00; |
||
826 | |||
827 | xsf = (width*tvn->scaledtwidth)/tvn->swidth; |
||
828 | hscale = ((tvn->totalwidth*4096UL)/xsf-4096); |
||
829 | hdelay = tvn->hdelayx1; |
||
830 | hdelay = (hdelay*width)/tvn->swidth; |
||
831 | hdelay &= 0x3fe; |
||
832 | sr=((tvn->sheight>>inter)*512)/height-512; |
||
833 | vscale=(0x10000UL-sr)&0x1fff; |
||
834 | crop=((width>>8)&0x03)|((hdelay>>6)&0x0c)| |
||
835 | ((tvn->sheight>>4)&0x30)|((tvn->vdelay>>2)&0xc0); |
||
836 | vscale |= inter ? (BT848_VSCALE_INT<<8) : 0; |
||
837 | |||
838 | if (combfilter) { |
||
839 | /* Some people say interpolation looks bad ... */ |
||
840 | vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0); |
||
841 | if (width < 769) |
||
842 | btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off); |
||
843 | else |
||
844 | btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off); |
||
845 | } else { |
||
846 | vtc = 0; |
||
847 | btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off); |
||
848 | } |
||
849 | |||
850 | btwrite(vtc, BT848_E_VTC+off); |
||
851 | btwrite(hscale>>8, BT848_E_HSCALE_HI+off); |
||
852 | btwrite(hscale&0xff, BT848_E_HSCALE_LO+off); |
||
853 | btaor((vscale>>8), 0xe0, BT848_E_VSCALE_HI+off); |
||
854 | btwrite(vscale&0xff, BT848_E_VSCALE_LO+off); |
||
855 | btwrite(width&0xff, BT848_E_HACTIVE_LO+off); |
||
856 | btwrite(hdelay&0xff, BT848_E_HDELAY_LO+off); |
||
857 | btwrite(tvn->sheight&0xff, BT848_E_VACTIVE_LO+off); |
||
858 | btwrite(tvn->vdelay&0xff, BT848_E_VDELAY_LO+off); |
||
859 | btwrite(crop, BT848_E_CROP+off); |
||
860 | } |
||
861 | |||
862 | |||
863 | static void bt848_set_geo(struct bttv *btv) |
||
864 | { |
||
865 | u16 ewidth, eheight, owidth, oheight; |
||
866 | u16 format, bswap; |
||
867 | struct tvnorm *tvn; |
||
868 | |||
869 | tvn=&tvnorms[btv->win.norm]; |
||
870 | |||
871 | btwrite(tvn->adelay, BT848_ADELAY); |
||
872 | btwrite(tvn->bdelay, BT848_BDELAY); |
||
873 | btaor(tvn->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH), BT848_IFORM); |
||
874 | btwrite(tvn->vbipack, BT848_VBI_PACK_SIZE); |
||
875 | btwrite(1, BT848_VBI_PACK_DEL); |
||
876 | |||
877 | btv->pll.pll_ofreq = tvn->Fsc; |
||
878 | if (!in_irq) set_pll(btv); |
||
879 | |||
880 | btv->win.interlace = (btv->win.height>tvn->sheight/2) ? 1 : 0; |
||
881 | |||
882 | if (0 == btv->risc_cap_odd && |
||
883 | |||
884 | /* overlay only */ |
||
885 | owidth = btv->win.width; |
||
886 | oheight = btv->win.height; |
||
887 | ewidth = btv->win.width; |
||
888 | eheight = btv->win.height; |
||
889 | format = btv->win.color_fmt; |
||
890 | bswap = btv->fb_color_ctl; |
||
891 | } else if (-1 != btv->gq_grab && |
||
892 | |||
893 | !btv->win.interlace && |
||
894 | btv->scr_on) { |
||
895 | /* odd field -> overlay, even field -> capture */ |
||
896 | owidth = btv->win.width; |
||
897 | oheight = btv->win.height; |
||
898 | ewidth = btv->gbuf[btv->gq_grab].width; |
||
899 | eheight = btv->gbuf[btv->gq_grab].height; |
||
900 | format = (btv->win.color_fmt & 0xf0) | |
||
901 | (btv->gbuf[btv->gq_grab].fmt & 0x0f); |
||
902 | bswap = btv->fb_color_ctl & 0x0a; |
||
903 | } else { |
||
904 | /* capture only */ |
||
905 | owidth = btv->gbuf[btv->gq_grab].width; |
||
906 | oheight = btv->gbuf[btv->gq_grab].height; |
||
907 | ewidth = btv->gbuf[btv->gq_grab].width; |
||
908 | eheight = btv->gbuf[btv->gq_grab].height; |
||
909 | format = btv->gbuf[btv->gq_grab].fmt; |
||
910 | bswap = 0; |
||
911 | } |
||
912 | |||
913 | /* program odd + even fields */ |
||
914 | bt848_set_eogeo(btv, tvn, 1, owidth, oheight); |
||
915 | bt848_set_eogeo(btv, tvn, 0, ewidth, eheight); |
||
916 | |||
917 | btwrite(format, BT848_COLOR_FMT); |
||
918 | btwrite(bswap | BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL); |
||
919 | } |
||
920 | |||
921 | |||
922 | static int bpp2fmt[4] = { |
||
923 | BT848_COLOR_FMT_RGB8, BT848_COLOR_FMT_RGB16, |
||
924 | BT848_COLOR_FMT_RGB24, BT848_COLOR_FMT_RGB32 |
||
925 | }; |
||
926 | |||
927 | static void bt848_set_winsize(struct bttv *btv) |
||
928 | { |
||
929 | unsigned short format; |
||
930 | |||
931 | if (btv->picture.palette > 0 && btv->picture.palette <= VIDEO_PALETTE_YUV422) { |
||
932 | /* format set by VIDIOCSPICT */ |
||
933 | format = palette2fmt[btv->picture.palette]; |
||
934 | } else { |
||
935 | /* use default for the given color depth */ |
||
936 | format = (btv->win.depth==15) ? BT848_COLOR_FMT_RGB15 : |
||
937 | bpp2fmt[(btv->win.bpp-1)&3]; |
||
938 | } |
||
939 | btv->win.color_fmt = format; |
||
940 | if (bigendian && |
||
941 | format == BT848_COLOR_FMT_RGB32) { |
||
942 | btv->fb_color_ctl = |
||
943 | BT848_COLOR_CTL_WSWAP_ODD | |
||
944 | BT848_COLOR_CTL_WSWAP_EVEN | |
||
945 | BT848_COLOR_CTL_BSWAP_ODD | |
||
946 | BT848_COLOR_CTL_BSWAP_EVEN; |
||
947 | } else if (bigendian && |
||
948 | (format == BT848_COLOR_FMT_RGB16 || |
||
949 | format == BT848_COLOR_FMT_RGB15)) { |
||
950 | btv->fb_color_ctl = |
||
951 | BT848_COLOR_CTL_BSWAP_ODD | |
||
952 | BT848_COLOR_CTL_BSWAP_EVEN; |
||
953 | } else { |
||
954 | btv->fb_color_ctl = 0; |
||
955 | } |
||
956 | |||
957 | /* RGB8 seems to be a 9x5x5 GRB color cube starting at |
||
958 | * color 16. Why the h... can't they even mention this in the |
||
959 | * data sheet? [AC - because it's a standard format so I guess |
||
960 | * it never occurred to them] |
||
961 | * Enable dithering in this mode. |
||
962 | */ |
||
963 | |||
964 | if (format==BT848_COLOR_FMT_RGB8) |
||
965 | btand(~BT848_CAP_CTL_DITH_FRAME, BT848_CAP_CTL); |
||
966 | else |
||
967 | btor(BT848_CAP_CTL_DITH_FRAME, BT848_CAP_CTL); |
||
968 | |||
969 | bt848_set_geo(btv); |
||
970 | } |
||
971 | |||
972 | /* |
||
973 | * Grab into virtual memory. |
||
974 | */ |
||
975 | static int vgrab(struct bttv *btv, struct video_mmap *mp) |
||
976 | { |
||
977 | unsigned int *ro, *re; |
||
978 | unsigned int *vbuf; |
||
979 | |||
980 | if(btv->fbuffer==NULL) |
||
179 | giacomo | 981 | return -ENOBUFS; |
170 | giacomo | 982 | |
983 | if(mp->frame >= gbuffers || mp->frame < 0) |
||
984 | return -EINVAL; |
||
985 | |||
986 | if(mp->height < 32 || mp->width < 48) |
||
987 | return -EINVAL; |
||
988 | if (mp->format >= PALETTEFMT_MAX) |
||
989 | return -EINVAL; |
||
990 | |||
991 | if (mp->height*mp->width*fmtbppx2[palette2fmt[mp->format]&0x0f]/2 |
||
992 | > gbufsize) |
||
993 | return -EINVAL; |
||
994 | if (-1 == palette2fmt[mp->format]) |
||
995 | return -EINVAL; |
||
996 | |||
997 | /* |
||
998 | * Ok load up the BT848 |
||
999 | */ |
||
1000 | |||
1001 | vbuf=(unsigned int *)(btv->fbuffer+gbufsize*mp->frame); |
||
1002 | ro=(unsigned int *)btv->gbuf[mp->frame].risc; |
||
1003 | re=ro+2048; |
||
1004 | make_vrisctab(btv, ro, re, vbuf, mp->width, mp->height, mp->format); |
||
1005 | |||
1006 | if (bttv_debug) |
||
1007 | printk("bttv%d: cap vgrab: queue %d (%d:%dx%d)\n", |
||
1008 | btv->nr,mp->frame,mp->format,mp->width,mp->height); |
||
1009 | btv->gbuf[mp->frame].stat = GBUFFER_GRABBING; |
||
1010 | btv->gbuf[mp->frame].fmt = palette2fmt[mp->format]; |
||
1011 | btv->gbuf[mp->frame].width = mp->width; |
||
1012 | btv->gbuf[mp->frame].height = mp->height; |
||
1013 | btv->gbuf[mp->frame].ro = virt_to_bus((unsigned long)ro); |
||
1014 | btv->gbuf[mp->frame].re = virt_to_bus((unsigned long)re); |
||
1015 | |||
1016 | #if 1 |
||
1017 | if (mp->height <= tvnorms[btv->win.norm].sheight/2 && |
||
1018 | mp->format != VIDEO_PALETTE_RAW) |
||
1019 | btv->gbuf[mp->frame].ro = 0; |
||
1020 | #endif |
||
1021 | |||
1022 | if (-1 == btv->gq_grab && btv->gq_in == btv->gq_out) { |
||
1023 | btv->gq_start = 1; |
||
1024 | btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ); |
||
1025 | } |
||
1026 | btv->gqueue[btv->gq_in++] = mp->frame; |
||
1027 | btv->gq_in = btv->gq_in % MAX_GBUFFERS; |
||
1028 | |||
1029 | btor(3, BT848_CAP_CTL); |
||
1030 | btor(3, BT848_GPIO_DMA_CTL); |
||
1031 | return 0; |
||
1032 | } |
||
1033 | |||
1034 | static inline void burst(int on) |
||
1035 | { |
||
1036 | tvnorms[0].scaledtwidth = 1135 - (on?BURSTOFFSET-2:0); |
||
1037 | tvnorms[0].hdelayx1 = 186 - (on?BURSTOFFSET :0); |
||
1038 | tvnorms[2].scaledtwidth = 1135 - (on?BURSTOFFSET-2:0); |
||
1039 | tvnorms[2].hdelayx1 = 186 - (on?BURSTOFFSET :0); |
||
1040 | } |
||
1041 | |||
1042 | /* |
||
1043 | * called from irq handler on fatal errors. Takes the grabber chip |
||
1044 | * offline, flag it needs a reinitialization (which can't be done |
||
1045 | * from irq context) and wake up all sleeping proccesses. They would |
||
1046 | * block forever else. We also need someone who actually does the |
||
1047 | * reinitialization from process context... |
||
1048 | */ |
||
1049 | static void bt848_offline(struct bttv *btv) |
||
1050 | { |
||
1051 | int i; |
||
1052 | |||
1053 | /* cancel all outstanding grab requests */ |
||
1054 | btv->gq_in = 0; |
||
1055 | btv->gq_out = 0; |
||
1056 | btv->gq_grab = -1; |
||
1057 | for (i = 0; i < gbuffers; i++) |
||
1058 | if (btv->gbuf[i].stat == GBUFFER_GRABBING) |
||
1059 | btv->gbuf[i].stat = GBUFFER_ERROR; |
||
1060 | |||
1061 | /* disable screen overlay and DMA */ |
||
1062 | btv->risc_cap_odd = 0; |
||
1063 | btv->risc_cap_even = 0; |
||
1064 | bt848_set_risc_jmps(btv,0); |
||
1065 | |||
1066 | /* flag the chip needs a restart */ |
||
1067 | btv->needs_restart = 1; |
||
1068 | |||
1069 | } |
||
1070 | |||
1071 | static void bt848_restart(struct bttv *btv) |
||
1072 | { |
||
1073 | if (bttv_verbose) |
||
1074 | printk(KERN_INFO "bttv%d: resetting chip\n",btv->nr); |
||
1075 | btwrite(0xfffffUL, BT848_INT_STAT); |
||
1076 | btand(~15, BT848_GPIO_DMA_CTL); |
||
1077 | btwrite(0, BT848_SRESET); |
||
1078 | btwrite(virt_to_bus((unsigned long)btv->risc_jmp+8), |
||
1079 | BT848_RISC_STRT_ADD); |
||
1080 | |||
1081 | /* enforce pll reprogramming */ |
||
1082 | btv->pll.pll_current = 0; |
||
1083 | set_pll(btv); |
||
1084 | |||
1085 | btv->errors = 0; |
||
1086 | btv->needs_restart = 0; |
||
1087 | bt848_set_geo(btv); |
||
1088 | bt848_set_risc_jmps(btv,-1); |
||
1089 | } |
||
1090 | |||
1091 | /* |
||
1092 | * Open a bttv card. Right now the flags stuff is just playing |
||
1093 | */ |
||
1094 | |||
1095 | int bttv_open(struct bttv *btv) |
||
1096 | { |
||
1097 | int i,ret; |
||
1098 | |||
1099 | ret = -EBUSY; |
||
1100 | if (bttv_debug) |
||
1101 | cprintf("bttv%d: open called\n",btv->nr); |
||
1102 | |||
1103 | btv->fbuffer=(unsigned char *) vmalloc_32(gbuffers*gbufsize); |
||
1104 | ret = -ENOMEM; |
||
1105 | |||
1106 | btv->gq_in = 0; |
||
1107 | btv->gq_out = 0; |
||
1108 | btv->gq_grab = -1; |
||
1109 | for (i = 0; i < gbuffers; i++) |
||
1110 | btv->gbuf[i].stat = GBUFFER_UNUSED; |
||
1111 | |||
1112 | burst(0); |
||
1113 | set_pll(btv); |
||
1114 | btv->user++; |
||
1115 | return 0; |
||
1116 | |||
1117 | } |
||
1118 | |||
1119 | void bttv_close(struct bttv *btv) |
||
1120 | { |
||
1121 | int need_wait; |
||
1122 | |||
257 | giacomo | 1123 | handler_remove(btv->dev->irq); |
1124 | |||
179 | giacomo | 1125 | vfree_32(btv->fbuffer); |
1126 | btv->fbuffer = NULL; |
||
1127 | |||
170 | giacomo | 1128 | btv->user--; |
1129 | need_wait = (-1 != btv->gq_grab); |
||
1130 | btv->gq_start = 0; |
||
1131 | btv->gq_in = 0; |
||
1132 | btv->gq_out = 0; |
||
1133 | btv->gq_grab = -1; |
||
1134 | btv->scr_on = 0; |
||
1135 | btv->risc_cap_odd = 0; |
||
1136 | btv->risc_cap_even = 0; |
||
1137 | |||
179 | giacomo | 1138 | pci_write_config_dword(btv->dev,PCI_COMMAND,oldpci_command); |
1139 | |||
170 | giacomo | 1140 | } |
1141 | |||
1142 | /***********************************/ |
||
1143 | /* ioctls and supporting functions */ |
||
1144 | /***********************************/ |
||
1145 | |||
1146 | static inline void bt848_bright(struct bttv *btv, uint bright) |
||
1147 | { |
||
1148 | btwrite(bright&0xff, BT848_BRIGHT); |
||
1149 | } |
||
1150 | |||
1151 | static inline void bt848_hue(struct bttv *btv, uint hue) |
||
1152 | { |
||
1153 | btwrite(hue&0xff, BT848_HUE); |
||
1154 | } |
||
1155 | |||
1156 | static inline void bt848_contrast(struct bttv *btv, uint cont) |
||
1157 | { |
||
1158 | unsigned int conthi; |
||
1159 | |||
1160 | conthi=(cont>>6)&4; |
||
1161 | btwrite(cont&0xff, BT848_CONTRAST_LO); |
||
1162 | btaor(conthi, ~4, BT848_E_CONTROL); |
||
1163 | btaor(conthi, ~4, BT848_O_CONTROL); |
||
1164 | } |
||
1165 | |||
1166 | static inline void bt848_sat_u(struct bttv *btv, unsigned long data) |
||
1167 | { |
||
1168 | u32 datahi; |
||
1169 | |||
1170 | datahi=(data>>7)&2; |
||
1171 | btwrite(data&0xff, BT848_SAT_U_LO); |
||
1172 | btaor(datahi, ~2, BT848_E_CONTROL); |
||
1173 | btaor(datahi, ~2, BT848_O_CONTROL); |
||
1174 | } |
||
1175 | |||
1176 | static inline void bt848_sat_v(struct bttv *btv, unsigned long data) |
||
1177 | { |
||
1178 | u32 datahi; |
||
1179 | |||
1180 | datahi=(data>>8)&1; |
||
1181 | btwrite(data&0xff, BT848_SAT_V_LO); |
||
1182 | btaor(datahi, ~1, BT848_E_CONTROL); |
||
1183 | btaor(datahi, ~1, BT848_O_CONTROL); |
||
1184 | } |
||
1185 | |||
1186 | /* |
||
1187 | * ioctl routine |
||
1188 | */ |
||
1189 | |||
1190 | int bttv_ioctl(struct bttv *btv, unsigned int cmd, void *arg) |
||
1191 | { |
||
1192 | int i; |
||
1193 | |||
1194 | if (bttv_debug > 1) |
||
1195 | cprintf("bttv%d: ioctl 0x%x\n",btv->nr,cmd); |
||
1196 | |||
1197 | switch (cmd) { |
||
1198 | case VIDIOCGCAP: |
||
1199 | { |
||
1200 | struct video_capability b; |
||
1201 | strcpy(b.name,btv->video_dev.name); |
||
1202 | b.type = VID_TYPE_CAPTURE| |
||
1203 | ((bttv_tvcards[btv->type].tuner != -1) ? VID_TYPE_TUNER : 0) | |
||
1204 | VID_TYPE_OVERLAY| |
||
1205 | VID_TYPE_CLIPPING| |
||
1206 | VID_TYPE_FRAMERAM| |
||
1207 | VID_TYPE_SCALES; |
||
1208 | b.channels = bttv_tvcards[btv->type].video_inputs; |
||
1209 | b.audios = bttv_tvcards[btv->type].audio_inputs; |
||
1210 | b.maxwidth = tvnorms[btv->win.norm].swidth; |
||
1211 | b.maxheight = tvnorms[btv->win.norm].sheight; |
||
1212 | b.minwidth = 48; |
||
1213 | b.minheight = 32; |
||
1214 | if(copy_to_user(arg,&b,sizeof(b))) |
||
1215 | return -EFAULT; |
||
1216 | return 0; |
||
1217 | } |
||
1218 | case VIDIOCGCHAN: |
||
1219 | { |
||
1220 | struct video_channel v; |
||
1221 | if(copy_from_user(&v, arg,sizeof(v))) |
||
1222 | return -EFAULT; |
||
1223 | v.flags=VIDEO_VC_AUDIO; |
||
1224 | v.tuners=0; |
||
1225 | v.type=VIDEO_TYPE_CAMERA; |
||
1226 | v.norm = btv->win.norm; |
||
1227 | if (v.channel>=bttv_tvcards[btv->type].video_inputs) |
||
1228 | return -EINVAL; |
||
1229 | if(v.channel==bttv_tvcards[btv->type].tuner) |
||
1230 | { |
||
1231 | strcpy(v.name,"Television"); |
||
1232 | v.flags|=VIDEO_VC_TUNER; |
||
1233 | v.type=VIDEO_TYPE_TV; |
||
1234 | v.tuners=1; |
||
1235 | } |
||
1236 | else if(v.channel==bttv_tvcards[btv->type].svhs) |
||
1237 | strcpy(v.name,"S-Video"); |
||
1238 | else |
||
1239 | sprintf(v.name,"Composite%d",v.channel); |
||
1240 | |||
1241 | if(copy_to_user(arg,&v,sizeof(v))) |
||
1242 | return -EFAULT; |
||
1243 | return 0; |
||
1244 | } |
||
1245 | /* |
||
1246 | * Each channel has 1 tuner |
||
1247 | */ |
||
1248 | case VIDIOCSCHAN: |
||
1249 | { |
||
1250 | struct video_channel v; |
||
1251 | if(copy_from_user(&v, arg,sizeof(v))) |
||
1252 | return -EFAULT; |
||
1253 | |||
1254 | if (v.channel>bttv_tvcards[btv->type].video_inputs) |
||
1255 | return -EINVAL; |
||
1256 | if (v.norm > (sizeof(tvnorms)/sizeof(*tvnorms))) |
||
1257 | return -EOPNOTSUPP; |
||
1258 | |||
1259 | bttv_call_i2c_clients(btv,cmd,&v); |
||
1260 | bt848_muxsel(btv, v.channel); |
||
1261 | btv->channel=v.channel; |
||
1262 | if (btv->win.norm != v.norm) { |
||
1263 | if(btv->type== BTTV_VOODOOTV_FM) |
||
1264 | bttv_tda9880_setnorm(btv,v.norm); |
||
1265 | btv->win.norm = v.norm; |
||
1266 | make_vbitab(btv); |
||
1267 | bt848_set_winsize(btv); |
||
1268 | } |
||
1269 | return 0; |
||
1270 | } |
||
1271 | case VIDIOCGTUNER: |
||
1272 | { |
||
1273 | struct video_tuner v; |
||
1274 | if(copy_from_user(&v,arg,sizeof(v))!=0) |
||
1275 | return -EFAULT; |
||
1276 | #if 0 /* tuner.signal might be of intrest for non-tuner sources too ... */ |
||
1277 | if(v.tuner||btv->channel) /* Only tuner 0 */ |
||
1278 | return -EINVAL; |
||
1279 | #endif |
||
1280 | strcpy(v.name, "Television"); |
||
1281 | v.rangelow=0; |
||
1282 | v.rangehigh=0xFFFFFFFF; |
||
1283 | v.flags=VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM; |
||
1284 | v.mode = btv->win.norm; |
||
1285 | v.signal = (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC) ? 0xFFFF : 0; |
||
1286 | bttv_call_i2c_clients(btv,cmd,&v); |
||
1287 | if(copy_to_user(arg,&v,sizeof(v))) |
||
1288 | return -EFAULT; |
||
1289 | return 0; |
||
1290 | } |
||
1291 | /* We have but one tuner */ |
||
1292 | case VIDIOCSTUNER: |
||
1293 | { |
||
1294 | struct video_tuner v; |
||
1295 | if(copy_from_user(&v, arg, sizeof(v))) |
||
1296 | return -EFAULT; |
||
1297 | /* Only one channel has a tuner */ |
||
1298 | if(v.tuner!=bttv_tvcards[btv->type].tuner) |
||
1299 | return -EINVAL; |
||
1300 | |||
1301 | if(v.mode!=VIDEO_MODE_PAL&&v.mode!=VIDEO_MODE_NTSC |
||
1302 | &&v.mode!=VIDEO_MODE_SECAM) |
||
1303 | return -EOPNOTSUPP; |
||
1304 | bttv_call_i2c_clients(btv,cmd,&v); |
||
1305 | if (btv->win.norm != v.mode) { |
||
1306 | btv->win.norm = v.mode; |
||
1307 | set_pll(btv); |
||
1308 | make_vbitab(btv); |
||
1309 | bt848_set_winsize(btv); |
||
1310 | } |
||
1311 | return 0; |
||
1312 | } |
||
1313 | case VIDIOCGPICT: |
||
1314 | { |
||
1315 | struct video_picture p=btv->picture; |
||
1316 | if(copy_to_user(arg, &p, sizeof(p))) |
||
1317 | return -EFAULT; |
||
1318 | return 0; |
||
1319 | } |
||
1320 | case VIDIOCSPICT: |
||
1321 | { |
||
1322 | struct video_picture p; |
||
1323 | if (copy_from_user(&p, arg,sizeof(p))) |
||
1324 | return -EFAULT; |
||
1325 | if (p.palette > PALETTEFMT_MAX) |
||
1326 | return -EINVAL; |
||
1327 | if (-1 == palette2fmt[p.palette]) |
||
1328 | return -EINVAL; |
||
1329 | /* We want -128 to 127 we get 0-65535 */ |
||
1330 | bt848_bright(btv, (p.brightness>>8)-128); |
||
1331 | /* 0-511 for the colour */ |
||
1332 | bt848_sat_u(btv, p.colour>>7); |
||
1333 | bt848_sat_v(btv, ((p.colour>>7)*201L)/237); |
||
1334 | /* -128 to 127 */ |
||
1335 | bt848_hue(btv, (p.hue>>8)-128); |
||
1336 | /* 0-511 */ |
||
1337 | bt848_contrast(btv, p.contrast>>7); |
||
1338 | btv->picture = p; |
||
1339 | return 0; |
||
1340 | } |
||
1341 | case VIDIOCSWIN: |
||
1342 | { |
||
1343 | struct video_window vw; |
||
1344 | struct video_clip *vcp = NULL; |
||
1345 | |||
1346 | if(copy_from_user(&vw,arg,sizeof(vw))) |
||
1347 | return -EFAULT; |
||
1348 | |||
1349 | if(vw.flags || vw.width < 16 || vw.height < 16) |
||
1350 | { |
||
1351 | btv->scr_on = 0; |
||
1352 | bt848_set_risc_jmps(btv,-1); |
||
1353 | return -EINVAL; |
||
1354 | } |
||
1355 | if (btv->win.bpp < 4) |
||
1356 | { /* adjust and align writes */ |
||
1357 | vw.x = (vw.x + 3) & ~3; |
||
1358 | vw.width &= ~3; |
||
1359 | } |
||
1360 | if (btv->needs_restart) |
||
1361 | bt848_restart(btv); |
||
1362 | btv->win.x=vw.x; |
||
1363 | btv->win.y=vw.y; |
||
1364 | btv->win.width=vw.width; |
||
1365 | btv->win.height=vw.height; |
||
1366 | |||
1367 | bt848_set_risc_jmps(btv,0); |
||
1368 | bt848_set_winsize(btv); |
||
1369 | |||
1370 | /* |
||
1371 | * Do any clips. |
||
1372 | */ |
||
1373 | if(vw.clipcount<0) { |
||
1374 | if((vcp=vmalloc_32(VIDEO_CLIPMAP_SIZE))==NULL) { |
||
1375 | return -ENOMEM; |
||
1376 | } |
||
1377 | if(copy_from_user(vcp, vw.clips, |
||
1378 | VIDEO_CLIPMAP_SIZE)) { |
||
1379 | vfree_32(vcp); |
||
1380 | return -EFAULT; |
||
1381 | } |
||
1382 | } else if (vw.clipcount > 2048) { |
||
1383 | return -EINVAL; |
||
1384 | } else if (vw.clipcount) { |
||
1385 | if((vcp=vmalloc_32(sizeof(struct video_clip)* |
||
1386 | (vw.clipcount))) == NULL) { |
||
1387 | return -ENOMEM; |
||
1388 | } |
||
1389 | if(copy_from_user(vcp,vw.clips, |
||
1390 | sizeof(struct video_clip)* |
||
1391 | vw.clipcount)) { |
||
1392 | vfree_32(vcp); |
||
1393 | return -EFAULT; |
||
1394 | } |
||
1395 | } |
||
1396 | make_clip_tab(btv, vcp, vw.clipcount); |
||
1397 | if (vw.clipcount != 0) |
||
1398 | vfree_32(vcp); |
||
1399 | bt848_set_risc_jmps(btv,-1); |
||
1400 | return 0; |
||
1401 | } |
||
1402 | case VIDIOCGWIN: |
||
1403 | { |
||
1404 | struct video_window vw; |
||
1405 | memset(&vw,0,sizeof(vw)); |
||
1406 | vw.x=btv->win.x; |
||
1407 | vw.y=btv->win.y; |
||
1408 | vw.width=btv->win.width; |
||
1409 | vw.height=btv->win.height; |
||
1410 | if(btv->win.interlace) |
||
1411 | vw.flags|=VIDEO_WINDOW_INTERLACE; |
||
1412 | if(copy_to_user(arg,&vw,sizeof(vw))) |
||
1413 | return -EFAULT; |
||
1414 | return 0; |
||
1415 | } |
||
1416 | case VIDIOCCAPTURE: |
||
1417 | { |
||
1418 | int v; |
||
1419 | if(copy_from_user(&v, arg,sizeof(v))) |
||
1420 | return -EFAULT; |
||
1421 | if(btv->win.vidadr == 0) |
||
1422 | return -EINVAL; |
||
1423 | if (btv->win.width==0 || btv->win.height==0) |
||
1424 | return -EINVAL; |
||
1425 | if (1 == no_overlay) |
||
1426 | return -EIO; |
||
1427 | if (v == 1 && btv->win.vidadr != 0) |
||
1428 | btv->scr_on = 1; |
||
1429 | if (v == 0) |
||
1430 | btv->scr_on = 0; |
||
1431 | bt848_set_risc_jmps(btv,-1); |
||
1432 | return 0; |
||
1433 | } |
||
1434 | case VIDIOCGFBUF: |
||
1435 | { |
||
1436 | struct video_buffer v; |
||
1437 | v.base=(void *)btv->win.vidadr; |
||
1438 | v.height=btv->win.sheight; |
||
1439 | v.width=btv->win.swidth; |
||
1440 | v.depth=btv->win.depth; |
||
1441 | v.bytesperline=btv->win.bpl; |
||
1442 | if(copy_to_user(arg, &v,sizeof(v))) |
||
1443 | return -EFAULT; |
||
1444 | return 0; |
||
1445 | |||
1446 | } |
||
1447 | case VIDIOCSFBUF: |
||
1448 | { |
||
1449 | struct video_buffer v; |
||
1450 | if(copy_from_user(&v, arg,sizeof(v))) |
||
1451 | return -EFAULT; |
||
1452 | if(v.depth!=8 && v.depth!=15 && v.depth!=16 && |
||
1453 | v.depth!=24 && v.depth!=32 && v.width > 16 && |
||
1454 | v.height > 16 && v.bytesperline > 16) |
||
1455 | return -EINVAL; |
||
1456 | if (v.base) |
||
1457 | btv->win.vidadr=(unsigned long)v.base; |
||
1458 | btv->win.sheight=v.height; |
||
1459 | btv->win.swidth=v.width; |
||
1460 | btv->win.bpp=((v.depth+7)&0x38)/8; |
||
1461 | btv->win.depth=v.depth; |
||
1462 | btv->win.bpl=v.bytesperline; |
||
1463 | |||
1464 | #if 0 /* was broken for ages and nobody noticed. Looks like we don't need |
||
1465 | it any more as everybody explicitly sets the palette using VIDIOCSPICT |
||
1466 | these days */ |
||
1467 | /* set sefault color format */ |
||
1468 | switch (v.depth) { |
||
1469 | case 8: btv->picture.palette = VIDEO_PALETTE_HI240; break; |
||
1470 | case 15: btv->picture.palette = VIDEO_PALETTE_RGB555; break; |
||
1471 | case 16: btv->picture.palette = VIDEO_PALETTE_RGB565; break; |
||
1472 | case 24: btv->picture.palette = VIDEO_PALETTE_RGB24; break; |
||
1473 | case 32: btv->picture.palette = VIDEO_PALETTE_RGB32; break; |
||
1474 | } |
||
1475 | #endif |
||
1476 | |||
1477 | if (bttv_debug) |
||
1478 | cprintf("Display at %p is %d by %d, bytedepth %d, bpl %d\n", |
||
1479 | v.base, v.width,v.height, btv->win.bpp, btv->win.bpl); |
||
1480 | bt848_set_winsize(btv); |
||
1481 | return 0; |
||
1482 | } |
||
1483 | case VIDIOCKEY: |
||
1484 | { |
||
1485 | /* Will be handled higher up .. */ |
||
1486 | return 0; |
||
1487 | } |
||
1488 | case VIDIOCGFREQ: |
||
1489 | { |
||
1490 | unsigned long v=btv->win.freq; |
||
1491 | if(copy_to_user(arg,&v,sizeof(v))) |
||
1492 | return -EFAULT; |
||
1493 | return 0; |
||
1494 | } |
||
1495 | case VIDIOCSFREQ: |
||
1496 | { |
||
1497 | unsigned long v; |
||
1498 | if(copy_from_user(&v, arg, sizeof(v))) |
||
1499 | return -EFAULT; |
||
1500 | btv->win.freq=v; |
||
1501 | bttv_call_i2c_clients(btv,cmd,&v); |
||
1502 | return 0; |
||
1503 | } |
||
1504 | |||
1505 | case VIDIOCSYNC: |
||
1506 | { |
||
1507 | return (btv->gbuf[0].stat == GBUFFER_DONE); |
||
1508 | |||
1509 | } |
||
1510 | |||
1511 | case BTTV_FIELDNR: |
||
1512 | if(copy_to_user((void *) arg, (void *) &btv->last_field, |
||
1513 | sizeof(btv->last_field))) |
||
1514 | return -EFAULT; |
||
1515 | break; |
||
1516 | |||
1517 | case BTTV_PLLSET: { |
||
1518 | struct bttv_pll_info p; |
||
1519 | if(!capable(CAP_SYS_ADMIN)) |
||
1520 | return -EPERM; |
||
1521 | if(copy_from_user(&p , (void *) arg, sizeof(btv->pll))) |
||
1522 | return -EFAULT; |
||
1523 | btv->pll.pll_ifreq = p.pll_ifreq; |
||
1524 | btv->pll.pll_ofreq = p.pll_ofreq; |
||
1525 | btv->pll.pll_crystal = p.pll_crystal; |
||
1526 | break; |
||
1527 | } |
||
1528 | |||
1529 | case VIDIOCMCAPTURE: |
||
1530 | { |
||
1531 | struct video_mmap vm; |
||
1532 | int ret; |
||
1533 | if(copy_from_user((void *) &vm, (void *) arg, sizeof(vm))) |
||
1534 | return -EFAULT; |
||
1535 | ret = vgrab(btv, &vm); |
||
1536 | return ret; |
||
1537 | } |
||
1538 | |||
1539 | case VIDIOCGMBUF: |
||
1540 | { |
||
1541 | struct video_mbuf vm; |
||
1542 | memset(&vm, 0 , sizeof(vm)); |
||
1543 | vm.size=gbufsize*gbuffers; |
||
1544 | vm.frames=gbuffers; |
||
1545 | for (i = 0; i < gbuffers; i++) |
||
1546 | vm.offsets[i]=i*gbufsize; |
||
1547 | if(copy_to_user((void *)arg, (void *)&vm, sizeof(vm))) |
||
1548 | return -EFAULT; |
||
1549 | return 0; |
||
1550 | } |
||
1551 | |||
1552 | case VIDIOCGUNIT: |
||
1553 | { |
||
1554 | struct video_unit vu; |
||
1555 | vu.video=btv->video_dev.minor; |
||
1556 | vu.vbi=btv->vbi_dev.minor; |
||
1557 | if(btv->radio_dev.minor!=-1) |
||
1558 | vu.radio=btv->radio_dev.minor; |
||
1559 | else |
||
1560 | vu.radio=VIDEO_NO_UNIT; |
||
1561 | vu.audio=VIDEO_NO_UNIT; |
||
1562 | vu.teletext=VIDEO_NO_UNIT; |
||
1563 | if(copy_to_user((void *)arg, (void *)&vu, sizeof(vu))) |
||
1564 | return -EFAULT; |
||
1565 | return 0; |
||
1566 | } |
||
1567 | |||
1568 | case BTTV_BURST_ON: |
||
1569 | { |
||
1570 | burst(1); |
||
1571 | return 0; |
||
1572 | } |
||
1573 | |||
1574 | case BTTV_BURST_OFF: |
||
1575 | { |
||
1576 | burst(0); |
||
1577 | return 0; |
||
1578 | } |
||
1579 | |||
1580 | case BTTV_VERSION: |
||
1581 | { |
||
1582 | return 0; |
||
1583 | } |
||
1584 | |||
1585 | case BTTV_PICNR: |
||
1586 | { |
||
1587 | /* return picture;*/ |
||
1588 | return 0; |
||
1589 | } |
||
1590 | |||
1591 | default: |
||
1592 | return 0; |
||
1593 | } |
||
1594 | return 0; |
||
1595 | } |
||
1596 | |||
1597 | static void bt848_set_risc_jmps(struct bttv *btv, int flags) |
||
1598 | { |
||
1599 | if (-1 == flags) { |
||
1600 | /* defaults */ |
||
1601 | flags = 0; |
||
1602 | if (btv->scr_on) |
||
1603 | flags |= 0x03; |
||
1604 | if (btv->vbi_on) |
||
1605 | flags |= 0x0c; |
||
1606 | #if 0 |
||
1607 | /* Hmm ... */ |
||
1608 | if ((0 != btv->risc_cap_even) || |
||
1609 | (0 != btv->risc_cap_odd)) |
||
1610 | flags |= 0x0c; |
||
1611 | #endif |
||
1612 | } |
||
1613 | |||
1614 | if (bttv_debug > 1) |
||
1615 | cprintf("bttv%d: set_risc_jmp %08lx:", |
||
1616 | btv->nr,virt_to_bus((unsigned long)btv->risc_jmp)); |
||
1617 | |||
1618 | /* Sync to start of odd field */ |
||
1619 | btv->risc_jmp[0]=cpu_to_le32(BT848_RISC_SYNC|BT848_RISC_RESYNC |
||
1620 | |BT848_FIFO_STATUS_VRE); |
||
1621 | btv->risc_jmp[1]=cpu_to_le32(0); |
||
1622 | |||
1623 | /* Jump to odd vbi sub */ |
||
1624 | btv->risc_jmp[2]=cpu_to_le32(BT848_RISC_JUMP|(0xd<<20)); |
||
1625 | if (flags&8) { |
||
1626 | if (bttv_debug > 1) |
||
1627 | cprintf(" ev=%08lx",virt_to_bus((unsigned long)btv->vbi_odd)); |
||
1628 | btv->risc_jmp[3]=cpu_to_le32(virt_to_bus((unsigned long)btv->vbi_odd)); |
||
1629 | } else { |
||
1630 | if (bttv_debug > 1) |
||
1631 | cprintf(" -----------"); |
||
1632 | btv->risc_jmp[3]=cpu_to_le32(virt_to_bus((unsigned long)btv->risc_jmp+16)); |
||
1633 | } |
||
1634 | |||
1635 | /* Jump to odd sub */ |
||
1636 | btv->risc_jmp[4]=cpu_to_le32(BT848_RISC_JUMP|(0xe<<20)); |
||
1637 | if (0 != btv->risc_cap_odd) { |
||
1638 | if (bttv_debug > 1) |
||
1639 | cprintf(" e%d=%08lx",btv->gq_grab,btv->risc_cap_odd); |
||
1640 | flags |= 3; |
||
1641 | btv->risc_jmp[5]=cpu_to_le32(btv->risc_cap_odd); |
||
1642 | } else if ((flags&2) && |
||
1643 | (!btv->win.interlace || 0 == btv->risc_cap_even)) { |
||
1644 | if (bttv_debug > 1) |
||
1645 | cprintf(" eo=%08lx",virt_to_bus((unsigned long)btv->risc_scr_odd)); |
||
1646 | btv->risc_jmp[5]=cpu_to_le32(virt_to_bus((unsigned long)btv->risc_scr_odd)); |
||
1647 | } else { |
||
1648 | if (bttv_debug > 1) |
||
1649 | cprintf(" -----------"); |
||
1650 | btv->risc_jmp[5]=cpu_to_le32(virt_to_bus((unsigned long)btv->risc_jmp+24)); |
||
1651 | } |
||
1652 | |||
1653 | |||
1654 | /* Sync to start of even field */ |
||
1655 | btv->risc_jmp[6]=cpu_to_le32(BT848_RISC_SYNC|BT848_RISC_RESYNC |
||
1656 | |BT848_FIFO_STATUS_VRO); |
||
1657 | btv->risc_jmp[7]=cpu_to_le32(0); |
||
1658 | |||
1659 | /* Jump to even vbi sub */ |
||
1660 | btv->risc_jmp[8]=cpu_to_le32(BT848_RISC_JUMP); |
||
1661 | if (flags&4) { |
||
1662 | if (bttv_debug > 1) |
||
1663 | cprintf(" ov=%08lx",virt_to_bus((unsigned long)btv->vbi_even)); |
||
1664 | btv->risc_jmp[9]=cpu_to_le32(virt_to_bus((unsigned long)btv->vbi_even)); |
||
1665 | } else { |
||
1666 | if (bttv_debug > 1) |
||
1667 | cprintf(" -----------"); |
||
1668 | btv->risc_jmp[9]=cpu_to_le32(virt_to_bus((unsigned long)btv->risc_jmp+40)); |
||
1669 | } |
||
1670 | |||
1671 | /* Jump to even sub */ |
||
1672 | btv->risc_jmp[10]=cpu_to_le32(BT848_RISC_JUMP|(8<<20)); |
||
1673 | if (0 != btv->risc_cap_even) { |
||
1674 | if (bttv_debug > 1) |
||
1675 | cprintf(" o%d=%08lx",btv->gq_grab,btv->risc_cap_even); |
||
1676 | flags |= 3; |
||
1677 | btv->risc_jmp[11]=cpu_to_le32(btv->risc_cap_even); |
||
1678 | } else if ((flags&1) && |
||
1679 | btv->win.interlace) { |
||
1680 | if (bttv_debug > 1) |
||
1681 | cprintf(" oo=%08lx",virt_to_bus((unsigned long)btv->risc_scr_even)); |
||
1682 | btv->risc_jmp[11]=cpu_to_le32(virt_to_bus((unsigned long)btv->risc_scr_even)); |
||
1683 | } else { |
||
1684 | if (bttv_debug > 1) |
||
1685 | cprintf(" -----------"); |
||
1686 | btv->risc_jmp[11]=cpu_to_le32(virt_to_bus((unsigned long)btv->risc_jmp+48)); |
||
1687 | } |
||
1688 | |||
1689 | if (btv->gq_start) { |
||
1690 | btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ); |
||
1691 | } else { |
||
1692 | btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP); |
||
1693 | } |
||
1694 | btv->risc_jmp[13]=cpu_to_le32(virt_to_bus((unsigned long)btv->risc_jmp)); |
||
1695 | |||
1696 | /* enable cpaturing and DMA */ |
||
1697 | if (bttv_debug > 1) |
||
1698 | cprintf(" flags=0x%x dma=%s\n", |
||
1699 | flags,(flags&0x0f) ? "on" : "off"); |
||
1700 | btaor(flags, ~0x0f, BT848_CAP_CTL); |
||
1701 | if (flags&0x0f) |
||
1702 | bt848_dma(btv, 3); |
||
1703 | else |
||
1704 | bt848_dma(btv, 0); |
||
1705 | } |
||
1706 | |||
1707 | static int init_bt848(struct bttv *btv) |
||
1708 | { |
||
1709 | int j,val; |
||
1710 | |||
1711 | btv->user=0; |
||
1712 | |||
1713 | /* bringup the gpio internals (quick! before anyone uses it) */ |
||
1714 | init_gpio_adapter(&(btv->gpio_adap)); |
||
1715 | |||
1716 | /* dump current state of the gpio registers before changing them, |
||
1717 | * might help to make a new card work */ |
||
1718 | if (bttv_gpio) |
||
1719 | bttv_gpio_tracking(btv,"init #1"); |
||
1720 | |||
1721 | |||
1722 | /* reset the bt848 */ |
||
1723 | btwrite(0, BT848_SRESET); |
||
1724 | DEBUG(printk(KERN_DEBUG "bttv%d: bt848_mem: 0x%lx\n", btv->nr, (unsigned long) btv->bt848_mem)); |
||
1725 | |||
1726 | /* not registered yet */ |
||
1727 | btv->video_dev.minor = -1; |
||
1728 | btv->radio_dev.minor = -1; |
||
1729 | btv->vbi_dev.minor = -1; |
||
1730 | |||
1731 | /* default setup for max. PAL size in a 1024xXXX hicolor framebuffer */ |
||
1732 | btv->win.norm=0; /* change this to 1 for NTSC, 2 for SECAM */ |
||
1733 | btv->win.interlace=1; |
||
1734 | btv->win.x=0; |
||
1735 | btv->win.y=0; |
||
1736 | btv->win.width=320; |
||
1737 | btv->win.height=240; |
||
1738 | btv->win.bpp=2; |
||
1739 | btv->win.depth=16; |
||
1740 | btv->win.color_fmt=BT848_COLOR_FMT_RGB16; |
||
1741 | btv->win.bpl=1024*btv->win.bpp; |
||
1742 | btv->win.swidth=1024; |
||
1743 | btv->win.sheight=768; |
||
1744 | btv->win.vidadr=0; |
||
1745 | btv->vbi_on=0; |
||
1746 | btv->scr_on=0; |
||
1747 | |||
1748 | btv->risc_scr_odd=0; |
||
1749 | btv->risc_scr_even=0; |
||
1750 | btv->risc_cap_odd=0; |
||
1751 | btv->risc_cap_even=0; |
||
1752 | btv->risc_jmp=0; |
||
1753 | btv->vbibuf=0; |
||
1754 | btv->field=btv->last_field=0; |
||
1755 | |||
1756 | btv->errors=0; |
||
1757 | btv->needs_restart=0; |
||
1758 | btv->has_radio=radio[btv->nr]; |
||
1759 | |||
1760 | if (!(btv->risc_scr_odd= (unsigned long *) vmalloc_32(RISCMEM_LEN/2))) |
||
1761 | return -1; |
||
1762 | if (!(btv->risc_scr_even=(unsigned long *) vmalloc_32(RISCMEM_LEN/2))) |
||
1763 | return -1; |
||
1764 | if (!(btv->risc_jmp =(unsigned long *) vmalloc_32(2048))) |
||
1765 | return -1; |
||
1766 | btv->vbi_odd=btv->risc_jmp+64; |
||
1767 | btv->vbi_even=btv->vbi_odd+1024; |
||
1768 | btv->bus_vbi_odd=virt_to_bus((unsigned long)btv->risc_jmp+48); |
||
1769 | btv->bus_vbi_even=virt_to_bus((unsigned long)btv->risc_jmp+24); |
||
1770 | |||
1771 | btwrite(virt_to_bus((unsigned long)btv->risc_jmp+8), BT848_RISC_STRT_ADD); |
||
1772 | btv->vbibuf=(unsigned char *) vmalloc_32(VBIBUF_SIZE); |
||
1773 | if (!btv->vbibuf) |
||
1774 | return -1; |
||
1775 | if (!(btv->gbuf = vmalloc_32(sizeof(struct bttv_gbuf)*gbuffers))) |
||
1776 | return -1; |
||
1777 | for (j = 0; j < gbuffers; j++) { |
||
1778 | if (!(btv->gbuf[j].risc = vmalloc_32(16384))) |
||
1779 | return -1; |
||
1780 | } |
||
1781 | |||
1782 | memset(btv->vbibuf, 0, VBIBUF_SIZE); /* We don't want to return random |
||
1783 | memory to the user */ |
||
1784 | |||
1785 | btv->fbuffer=NULL; |
||
1786 | |||
1787 | /* btwrite(0, BT848_TDEC); */ |
||
1788 | btwrite(0x10, BT848_COLOR_CTL); |
||
1789 | btwrite(0x00, BT848_CAP_CTL); |
||
1790 | /* set planar and packed mode trigger points and */ |
||
1791 | /* set rising edge of inverted GPINTR pin as irq trigger */ |
||
1792 | btwrite(BT848_GPIO_DMA_CTL_PKTP_32| |
||
1793 | BT848_GPIO_DMA_CTL_PLTP1_16| |
||
1794 | BT848_GPIO_DMA_CTL_PLTP23_16| |
||
1795 | BT848_GPIO_DMA_CTL_GPINTC| |
||
1796 | BT848_GPIO_DMA_CTL_GPINTI, |
||
1797 | BT848_GPIO_DMA_CTL); |
||
1798 | |||
1799 | /* select direct input */ |
||
1800 | btwrite(0x00, BT848_GPIO_REG_INP); |
||
1801 | btwrite(0x00, BT848_GPIO_OUT_EN); |
||
1802 | if (bttv_gpio) |
||
1803 | bttv_gpio_tracking(btv,"init #2"); |
||
1804 | |||
1805 | btwrite(BT848_IFORM_MUX1 | BT848_IFORM_XTAUTO | BT848_IFORM_AUTO, |
||
1806 | BT848_IFORM); |
||
1807 | |||
1808 | btwrite(0xd8, BT848_CONTRAST_LO); |
||
1809 | bt848_bright(btv, 0x10); |
||
1810 | |||
1811 | btwrite(0x20, BT848_E_VSCALE_HI); |
||
1812 | btwrite(0x20, BT848_O_VSCALE_HI); |
||
1813 | btwrite(BT848_ADC_RESERVED | (adc_crush ? BT848_ADC_CRUSH : 0), |
||
1814 | BT848_ADC); |
||
1815 | |||
1816 | if (lumafilter) { |
||
1817 | btwrite(0, BT848_E_CONTROL); |
||
1818 | btwrite(0, BT848_O_CONTROL); |
||
1819 | } else { |
||
1820 | btwrite(BT848_CONTROL_LDEC, BT848_E_CONTROL); |
||
1821 | btwrite(BT848_CONTROL_LDEC, BT848_O_CONTROL); |
||
1822 | } |
||
1823 | |||
1824 | btv->picture.colour=254<<7; |
||
1825 | btv->picture.brightness=128<<8; |
||
1826 | btv->picture.hue=128<<8; |
||
1827 | btv->picture.contrast=0xd8<<7; |
||
1828 | |||
1829 | val = chroma_agc ? BT848_SCLOOP_CAGC : 0; |
||
1830 | btwrite(val, BT848_E_SCLOOP); |
||
1831 | btwrite(val, BT848_O_SCLOOP); |
||
1832 | |||
1833 | /* clear interrupt status */ |
||
1834 | btwrite(0xfffffUL, BT848_INT_STAT); |
||
1835 | |||
1836 | /* set interrupt mask */ |
||
1837 | btwrite(btv->triton1| |
||
1838 | /*BT848_INT_PABORT|BT848_INT_RIPERR|BT848_INT_PPERR| |
||
1839 | BT848_INT_FDSR|BT848_INT_FTRGT|BT848_INT_FBUS|*/ |
||
1840 | (fieldnr ? BT848_INT_VSYNC : 0)| |
||
1841 | BT848_INT_GPINT| |
||
1842 | BT848_INT_SCERR| |
||
1843 | BT848_INT_RISCI|BT848_INT_OCERR|BT848_INT_VPRES| |
||
1844 | BT848_INT_FMTCHG|BT848_INT_HLOCK, |
||
1845 | BT848_INT_MASK); |
||
1846 | |||
1847 | bt848_muxsel(btv, 1); |
||
1848 | bt848_set_winsize(btv); |
||
1849 | make_vbitab(btv); |
||
1850 | bt848_set_risc_jmps(btv,-1); |
||
1851 | |||
1852 | /* needs to be done before i2c is registered */ |
||
1853 | bttv_init_card1(btv); |
||
1854 | |||
1855 | /* register i2c */ |
||
1856 | btv->tuner_type=-1; |
||
1857 | init_bttv_i2c(btv); |
||
1858 | |||
1859 | /* some card-specific stuff (needs working i2c) */ |
||
1860 | bttv_init_card2(btv); |
||
1861 | |||
1862 | return 0; |
||
1863 | } |
||
1864 | |||
1865 | /* ----------------------------------------------------------------------- */ |
||
1866 | |||
1867 | static char *irq_name[] = { "FMTCHG", "VSYNC", "HSYNC", "OFLOW", "HLOCK", |
||
1868 | "VPRES", "6", "7", "I2CDONE", "GPINT", "10", |
||
1869 | "RISCI", "FBUS", "FTRGT", "FDSR", "PPERR", |
||
1870 | "RIPERR", "PABORT", "OCERR", "SCERR" }; |
||
1871 | |||
1872 | static void bttv_irq(void) |
||
1873 | { |
||
1874 | u32 stat,astat; |
||
1875 | u32 dstat; |
||
1876 | int count; |
||
1877 | struct bttv *btv = btvirq; |
||
1878 | |||
257 | giacomo | 1879 | cli(); |
1880 | |||
170 | giacomo | 1881 | in_irq = 1; |
1882 | count=0; |
||
1883 | while (1) |
||
1884 | { |
||
1885 | /* get/clear interrupt status bits */ |
||
1886 | stat=btread(BT848_INT_STAT); |
||
1887 | astat=stat&btread(BT848_INT_MASK); |
||
1888 | if (!astat) { |
||
1889 | in_irq = 0; |
||
257 | giacomo | 1890 | sti(); |
170 | giacomo | 1891 | return; |
1892 | } |
||
1893 | btwrite(stat,BT848_INT_STAT); |
||
1894 | |||
1895 | /* get device status bits */ |
||
1896 | dstat=btread(BT848_DSTATUS); |
||
1897 | |||
1898 | if (irq_debug) { |
||
1899 | int i; |
||
1900 | cprintf("bttv%d: irq loop=%d risc=%lx, bits:", |
||
1901 | btv->nr, count, stat>>28); |
||
1902 | for (i = 0; i < (sizeof(irq_name)/sizeof(char*)); i++) { |
||
1903 | if (stat & (1 << i)) |
||
1904 | cprintf(" %s",irq_name[i]); |
||
1905 | if (astat & (1 << i)) |
||
1906 | cprintf(" *"); |
||
1907 | } |
||
1908 | if (stat & BT848_INT_HLOCK) |
||
1909 | cprintf(" HLOC => %s", (dstat & BT848_DSTATUS_HLOC) |
||
1910 | ? "yes" : "no"); |
||
1911 | if (stat & BT848_INT_VPRES) |
||
1912 | cprintf(" PRES => %s", (dstat & BT848_DSTATUS_PRES) |
||
1913 | ? "yes" : "no"); |
||
1914 | if (stat & BT848_INT_FMTCHG) |
||
1915 | cprintf(" NUML => %s", (dstat & BT848_DSTATUS_PRES) |
||
1916 | ? "625" : "525"); |
||
1917 | cprintf("\n"); |
||
1918 | } |
||
1919 | |||
1920 | if (astat&BT848_INT_VSYNC) |
||
1921 | btv->field++; |
||
1922 | |||
1923 | if (astat&(BT848_INT_SCERR|BT848_INT_OCERR)) { |
||
1924 | if (bttv_verbose) |
||
1925 | cprintf("bttv%d: irq:%s%s risc_count=%08lx\n", |
||
1926 | btv->nr, |
||
1927 | (astat&BT848_INT_SCERR) ? " SCERR" : "", |
||
1928 | (astat&BT848_INT_OCERR) ? " OCERR" : "", |
||
1929 | btread(BT848_RISC_COUNT)); |
||
1930 | btv->errors++; |
||
1931 | if (btv->errors < BTTV_ERRORS) { |
||
1932 | btand(~15, BT848_GPIO_DMA_CTL); |
||
1933 | btwrite(virt_to_bus((unsigned long)(btv->risc_jmp+8)), |
||
1934 | BT848_RISC_STRT_ADD); |
||
1935 | bt848_set_geo(btv); |
||
1936 | bt848_set_risc_jmps(btv,-1); |
||
1937 | } else { |
||
1938 | if (bttv_verbose) |
||
1939 | cprintf("bttv%d: aiee: error loops\n",btv->nr); |
||
1940 | bt848_offline(btv); |
||
1941 | } |
||
1942 | } |
||
1943 | if (astat&BT848_INT_RISCI) |
||
1944 | { |
||
1945 | if (bttv_debug > 1) |
||
1946 | cprintf("bttv%d: IRQ_RISCI\n",btv->nr); |
||
1947 | |||
1948 | /* captured VBI frame */ |
||
1949 | if (stat&(1<<28)) |
||
1950 | { |
||
1951 | btv->vbip=0; |
||
1952 | /* inc vbi frame count for detecting drops */ |
||
1953 | (*(u32 *)&(btv->vbibuf[VBIBUF_SIZE - 4]))++; |
||
1954 | } |
||
1955 | |||
1956 | /* captured full frame */ |
||
1957 | if (stat&(2<<28) && btv->gq_grab != -1) |
||
1958 | { |
||
1959 | btv->last_field=btv->field; |
||
1960 | if (bttv_debug) |
||
1961 | cprintf("bttv%d: cap irq: done %d\n",btv->nr,btv->gq_grab); |
||
1962 | btv->gbuf[btv->gq_grab].stat = GBUFFER_DONE; |
||
1963 | btv->gq_grab = -1; |
||
1964 | if (btv->gq_in != btv->gq_out) |
||
1965 | { |
||
1966 | btv->gq_grab = btv->gqueue[btv->gq_out++]; |
||
1967 | btv->gq_out = btv->gq_out % MAX_GBUFFERS; |
||
1968 | if (bttv_debug) |
||
1969 | cprintf("bttv%d: cap irq: capture %d\n",btv->nr,btv->gq_grab); |
||
1970 | btv->risc_cap_odd = btv->gbuf[btv->gq_grab].ro; |
||
1971 | btv->risc_cap_even = btv->gbuf[btv->gq_grab].re; |
||
1972 | bt848_set_risc_jmps(btv,-1); |
||
1973 | bt848_set_geo(btv); |
||
1974 | btwrite(BT848_COLOR_CTL_GAMMA, |
||
1975 | BT848_COLOR_CTL); |
||
1976 | } else { |
||
1977 | btv->risc_cap_odd = 0; |
||
1978 | btv->risc_cap_even = 0; |
||
1979 | bt848_set_risc_jmps(btv,-1); |
||
1980 | bt848_set_geo(btv); |
||
1981 | btwrite(btv->fb_color_ctl | BT848_COLOR_CTL_GAMMA, |
||
1982 | BT848_COLOR_CTL); |
||
1983 | } |
||
1984 | break; |
||
1985 | } |
||
1986 | if (stat&(8<<28) && btv->gq_start) |
||
1987 | { |
||
1988 | btv->gq_start = 0; |
||
1989 | btv->gq_grab = btv->gqueue[btv->gq_out++]; |
||
1990 | btv->gq_out = btv->gq_out % MAX_GBUFFERS; |
||
1991 | if (bttv_debug) |
||
1992 | cprintf("bttv%d: cap irq: capture %d [start]\n",btv->nr,btv->gq_grab); |
||
1993 | btv->risc_cap_odd = btv->gbuf[btv->gq_grab].ro; |
||
1994 | btv->risc_cap_even = btv->gbuf[btv->gq_grab].re; |
||
1995 | bt848_set_risc_jmps(btv,-1); |
||
1996 | bt848_set_geo(btv); |
||
1997 | btwrite(BT848_COLOR_CTL_GAMMA, |
||
1998 | BT848_COLOR_CTL); |
||
1999 | } |
||
2000 | } |
||
2001 | |||
2002 | count++; |
||
2003 | if (count > 20) { |
||
2004 | btwrite(0, BT848_INT_MASK); |
||
2005 | cprintf("bttv%d: IRQ lockup, cleared int mask\n", btv->nr); |
||
2006 | bt848_offline(btv); |
||
2007 | } |
||
2008 | } |
||
2009 | |||
2010 | in_irq = 0; |
||
257 | giacomo | 2011 | |
2012 | sti(); |
||
170 | giacomo | 2013 | |
2014 | } |
||
2015 | |||
2016 | int bttv_probe(struct bttv *btv) |
||
2017 | { |
||
2018 | unsigned char lat; |
||
2019 | |||
2020 | if (bttv_num == BTTV_MAX) |
||
2021 | return -ENOMEM; |
||
2022 | printk(KERN_INFO "bttv: Bt8xx card found (%d).\n", bttv_num); |
||
2023 | |||
2024 | btvirq = btv; |
||
2025 | btv->nr = bttv_num; |
||
2026 | //because not all compilers allow anonymous unions duplication is needed |
||
2027 | btv->gpio_adap.bt848_mem = btv->bt848_mem = NULL; |
||
2028 | btv->vbibuf=NULL; |
||
2029 | btv->risc_jmp=NULL; |
||
2030 | btv->vbi_odd=NULL; |
||
2031 | btv->vbi_even=NULL; |
||
2032 | btv->vbip=VBIBUF_SIZE; |
||
2033 | btv->shutdown=0; |
||
274 | giacomo | 2034 | |
2035 | btv->id = 848; |
||
170 | giacomo | 2036 | btv->bt848_adr=pci_resource_start(btv->dev,0); |
2037 | if (btv->id >= 878) |
||
2038 | btv->i2c_command = 0x83; |
||
2039 | else |
||
2040 | btv->i2c_command=(I2C_TIMING | BT848_I2C_SCL | BT848_I2C_SDA); |
||
2041 | |||
2042 | if (-1 != latency) { |
||
2043 | printk(KERN_INFO "bttv%d: setting pci latency timer to %d\n", |
||
2044 | bttv_num,latency); |
||
2045 | pci_write_config_byte(btv->dev, PCI_LATENCY_TIMER, latency); |
||
2046 | } |
||
2047 | pci_read_config_byte(btv->dev, PCI_CLASS_REVISION, &btv->revision); |
||
2048 | pci_read_config_byte(btv->dev, PCI_LATENCY_TIMER, &lat); |
||
2049 | printk(KERN_INFO "bttv%d: Bt%d (rev %d) at %2x:%2x\n", bttv_num,btv->id, btv->revision, btv->dev->bus->number, btv->dev->devfn); |
||
2050 | printk(KERN_INFO "irq: %d, latency: %d, mmio: 0x%lx\n", |
||
2051 | btv->dev->irq, lat, btv->bt848_adr); |
||
2052 | |||
2053 | btv->bt848_mem = (void *)btv->bt848_adr; |
||
2054 | btv->gpio_adap.bt848_mem = btv->bt848_mem; |
||
2055 | |||
2056 | btv->pll.pll_crystal = 0; |
||
2057 | |||
2058 | bttv_idcard(btv); |
||
2059 | |||
2060 | /* clear interrupt mask */ |
||
2061 | btwrite(0, BT848_INT_MASK); |
||
2062 | |||
2063 | handler_set(btv->dev->irq, (void (*)(int)) bttv_irq, NIL); |
||
2064 | |||
2065 | bttv_handle_chipset(btv); |
||
2066 | |||
2067 | init_bt848(btv); |
||
2068 | |||
2069 | bttv_num++; |
||
2070 | |||
2071 | return 0; |
||
2072 | |||
2073 | } |
||
2074 | |||
2075 | extern void i2c_init_all(void); |
||
2076 | |||
2077 | int bttv_start(struct bttv *btv) |
||
2078 | { |
||
195 | giacomo | 2079 | struct pci_regs *reg; |
170 | giacomo | 2080 | BYTE dv, bus; |
2081 | DWORD dw; |
||
2082 | |||
2083 | printk(KERN_INFO "Initializing PCI BUS...\n"); |
||
179 | giacomo | 2084 | |
170 | giacomo | 2085 | btv->dev = vmalloc_32(sizeof(struct pci_dev)); |
2086 | |||
2087 | /* Scan the devices connected to the PCI bus */ |
||
184 | giacomo | 2088 | if (pci_init() != 1) return -1; |
170 | giacomo | 2089 | |
2090 | bttv_num = 0; |
||
2091 | |||
2092 | if (gbuffers < 2 || gbuffers > MAX_GBUFFERS) |
||
2093 | gbuffers = 2; |
||
2094 | if (gbufsize < 0 || gbufsize > BTTV_MAX_FBUF) |
||
2095 | gbufsize = BTTV_MAX_FBUF; |
||
2096 | if (bttv_verbose) |
||
2097 | printk(KERN_INFO "bttv: using %d buffers with %dk (%dk total) for capture\n", |
||
2098 | gbuffers,gbufsize/1024,gbuffers*gbufsize/1024); |
||
2099 | |||
195 | giacomo | 2100 | if (pci_present()) { |
2101 | |||
2102 | reg = (struct pci_regs *) pci_class((0x0400) << 8,0,&bus,&dv) ; |
||
2103 | if (reg != NULL) { |
||
170 | giacomo | 2104 | btv->dev->bus->number = bus; |
195 | giacomo | 2105 | btv->dev->devfn = dv; |
2106 | btv->dev->base_address[0] = (reg->IoBaseAddress-0x08); |
||
2107 | btv->dev->irq = reg->InterruptLine; |
||
2108 | } else { |
||
2109 | return -1; |
||
2110 | } |
||
170 | giacomo | 2111 | |
195 | giacomo | 2112 | printk(KERN_INFO "PCI INFO bus=%d devfn=%d irq=%d base=%08lx\n",bus,dv,btv->dev->irq,btv->dev->base_address[0]); |
170 | giacomo | 2113 | |
195 | giacomo | 2114 | pcibios_read_config_dword(bus,dv,PCI_COMMAND,&dw); |
2115 | oldpci_command = dw; |
||
2116 | dw |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); |
||
2117 | pcibios_write_config_dword(bus,dv,PCI_COMMAND,dw); |
||
2118 | |||
2119 | } |
||
2120 | |||
170 | giacomo | 2121 | i2c_init_all(); |
2122 | |||
2123 | bttv_check_chipset(); |
||
2124 | |||
2125 | bttv_probe(btv); |
||
2126 | |||
2127 | bttv_open(btv); |
||
2128 | |||
2129 | return 0; |
||
2130 | |||
2131 | } |