2 * Copyright (c) 1995 Mark Tinguely and Jim Lowe
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Mark Tinguely and Jim Lowe
16 * 4. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
31 * $FreeBSD: src/sys/pci/meteor.c,v 1.49 1999/09/25 18:24:41 phk Exp $
32 * $DragonFly: src/sys/dev/video/meteor/meteor.c,v 1.2 2003/06/17 04:28:57 dillon Exp $
37 8/23/95 On advice from Stefan Esser, added volatile to PCI
38 memory pointers to remove PCI caching .
39 8/29/95 Fixes suggested by Bruce Evans.
40 meteor_mmap should return -1 on error rather than 0.
41 unit # > NMETEOR should be unit # >= NMETEOR.
42 10/24/95 Turn 50 Hz processing for SECAM and 60 Hz processing
44 11/11/95 Change UV from always begin signed to ioctl selected
45 to either signed or unsigned.
46 12/07/95 Changed 7196 startup codes for 50 Hz as recommended
47 by Luigi Rizzo (luigi@iet.unipi.it)
48 12/08/95 Clear SECAM bit in PAL/NTSC and set input field count
49 bits for 50 Hz mode (PAL/SECAM) before I was setting the
50 output count bits. by Luigi Rizzo (luigi@iet.unipi.it)
51 12/18/95 Correct odd DMA field (never exceed, but good for safety
52 Changed 7196 startup codes for 50 Hz as recommended
53 by Luigi Rizzo (luigi@iet.unipi.it)
54 12/19/95 Changed field toggle mode to enable (offset 0x3c)
55 recommended by luigi@iet.unipi.it
56 Added in prototyping, include file, staticizing,
57 and DEVFS changes from FreeBSD team.
58 Changed the default allocated pages from 151 (NTSC)
60 Cleaned up some old comments in iic_write().
61 Added a Field (even or odd) only capture mode to
62 eliminate the high frequency problems with compression
63 algorithms. Recommended by luigi@iet.unipi.it.
64 Changed geometry ioctl so if it couldn't allocated a
65 large enough contiguous space, it wouldn't free the
67 Added new mode called YUV_422 which delivers the
68 data in planer Y followed by U followed by V. This
69 differs from the standard YUV_PACKED mode in that
70 the chrominance (UV) data is in the correct (different)
71 order. This is for programs like vic and mpeg_encode
72 so they don't have to reorder the chrominance data.
73 Added field count to stats.
74 Increment frame count stat if capturing continuous on
76 Added my email address to these comments
77 (james@cs.uwm.edu) suggested by (luigi@iet.unipt.it :-).
78 Changed the user mode signal mechanism to allow the
79 user program to be interrupted at the end of a frame
80 in any one of the modes. Added SSIGNAL ioctl.
81 Added a SFPS/GFPS ioctl so one may set the frames per
82 second that the card catpures. This code needs to be
84 Changed the interrupt routine so synchronous capture
85 will work on fields or frames and the starting frame
86 can be either even or odd.
87 Added HALT_N_FRAMES and CONT_N_FRAMES so one could
88 stop and continue synchronous capture mode.
89 Change the tsleep/wakeup function to wait on mtr
90 rather than &read_intr_wait.
91 1/22/96 Add option (METEOR_FreeBSD_210) for FreeBSD 2.1
93 Changed intr so it only printed errors every 50 times.
94 Added unit number to error messages.
95 Added get_meteor_mem and enabled range checking.
96 1/30/96 Added prelim test stuff for direct video dma transfers
97 from Amancio Hasty (hasty@rah.star-gate.com). Until
98 we get some stuff sorted out, this will be ifdef'ed
99 with METEOR_DIRECT_VIDEO. This is very dangerous to
100 use at present since we don't check the address that
101 is passed by the user!!!!!
102 2/26/96 Added special SVIDEO input device type.
103 2/27/96 Added meteor_reg.h file and associate types Converted
104 meteor.c over to using meteor.h file. Prompted by
105 Lars Jonas Olsson <ljo@po.cwru.edu>.
106 2/28/96 Added meteor RGB code from Lars Jonas Olsson
107 <ljo@po.cwru.edu>. I make some mods to this code, so
108 I hope it still works as I don't have an rgb card to
110 2/29/96 <ljo@po.cwru.edu> tested the meteor RGB and supplied
111 me with diffs. Thanks, we now have a working RGB
112 version of the driver. Still need to clean up this
114 3/1/96 Fixed a nasty little bug that was clearing the VTR
115 mode bit when the 7196 status was requested.
116 3/15/96 Fixed bug introduced in previous version that
117 stopped the only fields mode from working.
118 Added METEOR{GS}TS ioctl, still needs work.
119 3/25/96 Added YUV_9 and YUV_12 modes. Cleaned up some of the
120 code and converted variables to use the new register
122 4/8/96 Fixed the a bug in with the range enable. Pointed
124 5/13/96 Fix the FPS ioctl so it actually sets the frames
125 per second. Code supplied by ian@robots.ox.ac.uk.
126 The new code implements a new define:
127 METEOR_SYSTEM_DEFAULT which should be defined as
128 METEOR_PAL, METEOR_SECAM, or METEOR_NTSC in your system
129 configuration file. If METEOR_SYSTEM_DEFAULT isn't
130 defined, and there is not a signal when set_fps is
131 called, then the call has no effect.
132 Changed the spelling of PLANER to PLANAR as pointed
133 out by Paco Hope <paco@cs.virigina.edu> and define
134 PLANER to be PLANAR for backward compatibility.
135 5/28/95 METEOR_INPUT_DEV_RCA -> METEOR_INPUT_DEV0, not
136 METEOR_GEO_DEV0. Pointed out by Ian Reid,
137 <ian@robots.ox.ac.uk>.
138 METEOR_DEV_MASK should be 0x0000f000 and not
139 0x2000f000, otherwise METEOR_RGB gets masked
140 out. Pointed out by Ian Reid.
141 Changed the fps code to give even distribution for
142 low frame rates. Code supplied by Ian Reid.
143 Fix some problems with the RGB version. Patch supplied
144 by <ljo@po.cwru.edu>.
145 Added METEOR_FIELD_MODE to include files for a
146 future version of this driver.
151 #include "opt_meteor.h"
153 #include <sys/param.h>
154 #include <sys/systm.h>
155 #include <sys/conf.h>
156 #include <sys/kernel.h>
157 #include <sys/signalvar.h>
158 #include <sys/mman.h>
161 #if defined(METEOR_FreeBSD_210)
162 #include <machine/cpu.h> /* bootverbose */
166 #include <vm/vm_kern.h>
168 #include <vm/vm_extern.h>
170 #include <pci/pcivar.h>
171 #include <pci/pcireg.h>
172 #include <machine/ioctl_meteor.h>
173 #include <pci/meteor_reg.h>
176 static void meteor_intr __P((void *arg));
179 * Allocate enough memory for:
180 * 768x576 RGB 16 or YUV (16 storage bits/pixel) = 884736 = 216 pages
182 * You may override this using the options "METEOR_ALLOC_PAGES=value" in your
183 * kernel configuration file.
185 #ifndef METEOR_ALLOC_PAGES
186 #define METEOR_ALLOC_PAGES 217
188 #define METEOR_ALLOC (METEOR_ALLOC_PAGES * PAGE_SIZE)
190 static meteor_reg_t meteor[NMETEOR];
191 #define METEOR_NUM(mtr) ((mtr - &meteor[0])/sizeof(meteor_reg_t))
193 #define METPRI (PZERO+8)|PCATCH
195 static const char* met_probe (pcici_t tag, pcidi_t type);
196 static void met_attach(pcici_t tag, int unit);
197 static u_long met_count;
199 static struct pci_device met_device = {
206 COMPAT_PCI_DRIVER (meteor, met_device);
208 #if defined(METEOR_FreeBSD_210) /* XXX */
209 d_open_t meteor_open;
210 d_close_t meteor_close;
211 d_read_t meteor_read;
212 d_write_t meteor_write;
213 d_ioctl_t meteor_ioctl;
214 d_mmap_t meteor_mmap;
216 static d_open_t meteor_open;
217 static d_close_t meteor_close;
218 static d_read_t meteor_read;
219 static d_write_t meteor_write;
220 static d_ioctl_t meteor_ioctl;
221 static d_mmap_t meteor_mmap;
223 #define CDEV_MAJOR 67
224 static struct cdevsw meteor_cdevsw = {
225 /* open */ meteor_open,
226 /* close */ meteor_close,
227 /* read */ meteor_read,
228 /* write */ meteor_write,
229 /* ioctl */ meteor_ioctl,
231 /* mmap */ meteor_mmap,
232 /* strategy */ nostrategy,
234 /* maj */ CDEV_MAJOR,
242 static mreg_t saa7116_pci_default[sizeof(struct saa7116_regs)/sizeof(mreg_t)]={
243 /* PCI Memory registers */
244 /* BITS Type Description */
245 /* 0x00 */ 0x00000000, /* 31:1 e*RW DMA 1 (Even)
247 /* 0x04 */ 0x00000000, /* 31:2 e*RW DMA 2 (Even)
249 /* 0x08 */ 0x00000000, /* 31:2 e*RW DMA 3 (Even)
251 /* 0x0c */ 0x00000000, /* 31:1 o*RW DMA 1 (Odd)
253 /* 0x10 */ 0x00000000, /* 31:2 o*RW DMA 2 (Odd)
255 /* 0x14 */ 0x00000000, /* 31:2 o*RW DMA 3 (Odd)
257 /* 0x18 */ 0x00000500, /* 15:2 e*RW Stride 1 (Even)
259 /* 0x1c */ 0x00000000, /* 15:2 e*RW Stride 2 (Even)
261 /* 0x20 */ 0x00000000, /* 15:2 e*RW Stride 3 (Even)
263 /* 0x24 */ 0x00000500, /* 15:2 o*RW Stride 1 (Odd)
265 /* 0x28 */ 0x00000000, /* 15:2 o*RW Stride 2 (Odd)
267 /* 0x2c */ 0x00000000, /* 15:2 o*RW Stride 3 (Odd)
269 /* 0x30 */ 0xeeeeee01, /* 31:8 *RW Route (Even)
270 7:0 *RW Mode (Even) */
271 /* 0x34 */ 0xeeeeee01, /* 31:8 *RW Route (Odd)
272 7:0 *RW Mode (Odd) */
273 /* 0x38 */ 0x00200020, /* 22:16 *RW FIFO Trigger Planer Mode,
274 6:0 *RW FIFO Trigger Packed Mode */
275 /* 0x3c */ 0x00000107, /* 9:8 *RW Reserved (0x0)
278 0 *RW Reserved (0x1) */
279 /* 0x40 */ 0x000000c0, /* 15 *RW Range Enable
280 14 *RW Corrupt Disable
281 11 *RR Address Error (Odd)
282 10 *RR Address Error (Even)
283 9 *RR Field Corrupt (Odd)
284 8 *RR Field Corrupt (Even)
287 5 *RR Field Done (Odd)
288 4 *RR Field Done (Even)
289 3 *RS Single Field Capture (Odd)
290 2 *RS Single Field Capture (Even)
291 1 *RW Capture (ODD) Continous
292 0 *RW Capture (Even) Continous */
293 /* 0x44 */ 0x00000000, /* 7:0 *RW Retry Wait Counter */
294 /* 0x48 */ 0x00000307, /* 10 *RW Interrupt mask, start of field
295 9 *RW Interrupt mask, end odd field
296 8 *RW Interrupt mask, end even field
297 2 *RR Interrupt status, start of field
298 1 *RR Interrupt status, end of odd
299 0 *RR Interrupt status, end of even */
300 /* 0x4c */ 0x00000001, /* 31:0 *RW Field Mask (Even) continous */
301 /* 0x50 */ 0x00000001, /* 31:0 *RW Field Mask (Odd) continous */
302 /* 0x54 */ 0x00000000, /* 20:16 *RW Mask Length (Odd)
303 4:0 *RW Mask Length (Even) */
304 /* 0x58 */ 0x0005007c, /* 22:16 *RW FIFO almost empty
305 6:0 *RW FIFO almost full */
306 /* 0x5c */ 0x461e1e0f, /* 31:24 *RW I2C Phase 4
307 23:16 *RW I2C Phase 3
309 7:0 *RW I2C Phase 1 */
310 /* 0x60 */ 0x00000300, /* 31:24 *RO I2C Read Data
311 23:16 **RW I2C Auto Address
314 9 RR I2C Direct Abort
319 0 RW I2C Auto Enable */
320 /* 0x64 */ 0x00000000, /* 24 RS I2C New Cycle
321 23:16 **RW I2C Direct Address
322 15:8 **RW I2C Direct Sub-address
323 7:0 **RW I2C Direct Write Address */
324 /* 0x68 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 1 (Even)
325 23:16 **RW I2C Auto Data 1 (Even)
326 15:8 **RW I2C Auto Sub-address 0 (Even)
327 7:0 **RW I2C Auto Data 0 (Even) */
328 /* 0x6c */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 3 (Even)
329 23:16 **RW I2C Auto Data 3 (Even)
330 15:8 **RW I2C Auto Sub-address 2 (Even)
331 7:0 **RW I2C Auto Data 2 (Even) */
332 /* 0x70 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 5 (Even)
333 23:16 **RW I2C Auto Data 5 (Even)
334 15:8 **RW I2C Auto Sub-address 4 (Even)
335 7:0 **RW I2C Auto Data 4 (Even) */
336 /* 0x74 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 7 (Even)
337 23:16 **RW I2C Auto Data 7 (Even)
338 15:8 **RW I2C Auto Sub-address 6 (Even)
339 7:0 **RW I2C Auto Data 6 (Even) */
340 /* 0x78 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 1 (Odd)
341 23:16 **RW I2C Auto Data 1 (Odd)
342 15:8 **RW I2C Auto Sub-address 0 (Odd)
343 7:0 **RW I2C Auto Data 0 (Odd) */
344 /* 0x7c */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 3 (Odd)
345 23:16 **RW I2C Auto Data 3 (Odd)
346 15:8 **RW I2C Auto Sub-address 2 (Odd)
347 7:0 **RW I2C Auto Data 2 (Odd) */
348 /* 0x80 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 5 (Odd)
349 23:16 **RW I2C Auto Data 5 (Odd)
350 15:8 **RW I2C Auto Sub-address 4 (Odd)
351 7:0 **RW I2C Auto Data 4 (Odd) */
352 /* 0x84 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 7 (Odd)
353 23:16 **RW I2C Auto Data 7 (Odd)
354 15:8 **RW I2C Auto Sub-address 6 (Odd)
355 7:0 **RW I2C Auto Data 6 (Odd) */
356 /* 0x88 */ 0x00000000, /* 23:16 **RW I2C Register Enable (Odd)
357 7:0 **RW I2C Register Enable (Even) */
358 /* 0x8c */ 0x00000000, /* 23:2 e*RW DMA End (Even)
360 /* 0x90 */ 0x00000000 /* 23:2 e*RW DMA End (Odd)
364 static u_char saa7196_i2c_default[NUM_SAA7196_I2C_REGS] = {
365 /* SAA7196 I2C bus control */
367 /* 00 */ 0x50, /* 7:0 Increment Delay */
368 /* 01 */ 0x30, /* 7:0 Horizontal Sync Begin for 50hz */
369 /* 02 */ 0x00, /* 7:0 Horizontal Sync Stop for 50hz */
370 /* 03 */ 0xe8, /* 7:0 Horizontal Sync Clamp Start for 50hz */
371 /* 04 */ 0xb6, /* 7:0 Horizontal Sync Clamp Stop for 50hz */
372 /* 05 */ 0xf4, /* 7:0 Horizontal Sync Start after PH1 for 50hz */
373 /* 06 */ 0x46, /* 7 Input mode =0 CVBS, =1 S-Video
375 5:4 Aperture Bandpass characteristics
376 3:2 Coring range for high freq
377 1:0 Aperture bandpass filter weights */
378 /* 07 */ 0x00, /* 7:0 Hue */
379 /* 08 */ 0x7f, /* 7:3 Colour-killer threshold QAM (PAL, NTSC) */
380 /* 09 */ 0x7f, /* 7:3 Colour-killer threshold SECAM */
381 /* 0a */ 0x7f, /* 7:0 PAL switch sensitivity */
382 /* 0b */ 0x7f, /* 7:0 SECAM switch sensitivity */
383 /* 0c */ 0x40, /* 7 Colour-on bit
385 /* 0d */ 0x84, /* 7 VTR/TV mode bit = 1->VTR mode
386 3 Realtime output mode select bit
387 2 HREF position select
390 /* 0e */ 0x38, /* 7 Horizontal clock PLL
391 5 Select interal/external clock source
392 4 Output enable of Horizontal/Vertical sync
393 3 Data output YUV enable
397 /* 0f */ 0x50, /* 7 Automatic Field detection
398 6 Field Select 0 = 50hz, 1=60hz
399 5 SECAM cross-colour reduction
400 4 Enable sync and clamping pulse
401 3:1 Luminance delay compensation */
402 /* 10 */ 0x00, /* 2 Select HREF Position
403 1:0 Vertical noise reduction */
404 /* 11 */ 0x2c, /* 7:0 Chrominance gain conrtol for QAM */
405 /* 12 */ 0x40, /* 7:0 Chrominance saturation control for VRAM port */
406 /* 13 */ 0x40, /* 7:0 Luminance contract control for VRAM port */
407 /* 14 */ 0x34, /* 7:0 Horizontal sync begin for 60hz */
409 /* 15 */ 0x0c, /* 7:0 Horizontal sync stop for 60hz */
410 /* 16 */ 0xfb, /* 7:0 Horizontal clamp begin for 60hz */
411 /* 17 */ 0xd4, /* 7:0 Horizontal clamp stop for 60hz */
412 /* 18 */ 0xec, /* 7:0 Horizontal sync start after PH1 for 60hz */
414 0x0a, 0xf4, 0xce, 0xf4,
416 /* 19 */ 0x80, /* 7:0 Luminance brightness control for VRAM port */
423 /* 20 */ 0x90, /* 7 ROM table bypass switch
424 6:5 Set output field mode
425 4 VRAM port outputs enable
426 3:2 First pixel position in VRO data
427 1:0 FIFO output register select */
428 /* 21 */ 0x80, /* 7:0 [7:0] Pixel number per line on output */
429 /* 22 */ 0x80, /* 7:0 [7:0] Pixel number per line on input */
430 /* 23 */ 0x03, /* 7:0 [7:0] Horizontal start position of scaling win*/
431 /* 24 */ 0x8a, /* 7:5 Horizontal decimation filter
432 4 [8] Horizontal start position of scaling win
433 3:2 [9:8] Pixel number per line on input
434 1:0 [9:8] Pixel number per line on output */
435 /* 25 */ 0xf0, /* 7:0 [7:0] Line number per output field */
436 /* 26 */ 0xf0, /* 7:0 [7:0] Line number per input field */
437 /* 27 */ 0x0f, /* 7:0 [7:0] Vertical start of scaling window */
438 /* 28 */ 0x80, /* 7 Adaptive filter switch
439 6:5 Vertical luminance data processing
440 4 [8] Vertical start of scaling window
441 3:2 [9:8] Line number per input field
442 1:0 [9:8] Line number per output field */
443 /* 29 */ 0x16, /* 7:0 [7:0] Vertical bypass start */
444 /* 2a */ 0x00, /* 7:0 [7:0] Vertical bypass count */
445 /* 2b */ 0x00, /* 4 [8] Vertical bypass start
446 2 [8] Vertical bypass count
447 0 Polarity, internally detected odd even flag */
448 /* 2c */ 0x80, /* 7:0 Set lower limit V for colour-keying */
449 /* 2d */ 0x7f, /* 7:0 Set upper limit V for colour-keying */
450 /* 2e */ 0x80, /* 7:0 Set lower limit U for colour-keying */
451 /* 2f */ 0x7f, /* 7:0 Set upper limit U for colour-keying */
452 /* 30 */ 0xbf /* 7 VRAM bus output format
453 6 Adaptive geometrical filter
454 5 Luminance limiting value
455 4 Monochrome and two's complement output data sel
456 3 Line quailifier flag
457 2 Pixel qualifier flag
458 1 Transparent data transfer
459 0 Extended formats enable bit */
462 static u_char bt254_default[NUM_BT254_REGS] = {
474 * Returns 0 Succesful completion.
475 * Returns 1 If transfer aborted or timeout occured.
478 static int i2c_print_err = 1;
480 i2c_write(meteor_reg_t * mtr, u_char slave, u_char rw, u_char reg, u_char data)
482 register unsigned long wait_counter = 0x0001ffff;
483 register mreg_t * iic_write_loc = &mtr->base->i2c_write;
484 register int err = 0;
487 /* Write the data the the i2c write register */
488 *iic_write_loc = SAA7116_IIC_NEW_CYCLE |
489 (((u_long)slave|(u_long)rw) << 16) |
490 ((u_long)reg << 8) | (u_long)data;
492 /* Wait until the i2c cycle is compeleted */
493 while((*iic_write_loc & SAA7116_IIC_NEW_CYCLE)) {
494 if(!wait_counter) break;
498 /* 1ffff should be enough delay time for the i2c cycle to complete */
501 printf("meteor%d: %d i2c %s transfer timeout 0x%x",
502 METEOR_NUM(mtr), slave,
503 rw ? "read" : "write", *iic_write_loc);
508 /* Check for error on direct write, clear if any */
509 if(mtr->base->i2c_read & SAA7116_IIC_DIRECT_TRANSFER_ABORTED){
510 mtr->base->i2c_read |= SAA7116_IIC_DIRECT_TRANSFER_ABORTED;
512 printf("meteor%d: 0x%x i2c %s tranfer aborted",
513 METEOR_NUM(mtr), slave,
514 rw ? "read" : "write" );
520 printf(" - reg=0x%x, value=0x%x.\n", reg, data);
528 met_probe (pcici_t tag, pcidi_t type)
533 cdevsw_add(&meteor_cdevsw);
536 case SAA7116_PHILIPS_ID: /* meteor */
537 return("Philips SAA 7116");
542 /* interrupt handling routine
543 complete meteor_read() if using interrupts
546 meteor_intr(void *arg)
548 meteor_reg_t *mtr = (meteor_reg_t *) arg;
549 mreg_t *cap = &mtr->base->cap_cntl,
550 *base = &mtr->base->dma1e,
551 *stat = &mtr->base->irq_stat;
552 u_long status = *stat,
553 cap_err = *cap & 0x00000f00,
554 #ifdef METEOR_CHECK_PCI_BUS
555 pci_err = pci_conf_read(mtr->tag,
556 PCI_COMMAND_STATUS_REG),
558 next_base = (u_long)(vtophys(mtr->bigbuf));
561 * Disable future interrupts if a capture mode is not selected.
562 * This can happen when we are in the process of closing or
563 * changing capture modes, otherwise it shouldn't happen.
565 if(!(mtr->flags & METEOR_CAP_MASK)) {
566 *cap &= 0x8ff0; /* disable future interrupts */
568 #ifdef METEOR_CHECK_PCI_BUS
570 * Check for pci bus errors.
572 #define METEOR_MASTER_ABORT 0x20000000
573 #define METEOR_TARGET_ABORT 0x10000000
574 if(pci_err & METEOR_MASTER_ABORT) {
575 printf("meteor%d: intr: pci bus master dma abort: 0x%x 0x%x.\n",
576 METEOR_NUM(mtr), *base, *(base+3));
577 pci_conf_write(mtr->tag, PCI_COMMAND_STATUS_REG, pci_err);
579 if(pci_err & METEOR_TARGET_ABORT) {
580 printf("meteor%d: intr: pci bus target dma abort: 0x%x 0x%x.\n",
581 METEOR_NUM(mtr), *base, *(base+3));
582 pci_conf_write(mtr->tag, PCI_COMMAND_STATUS_REG, pci_err);
589 if (cap_err & 0x300) {
590 if(mtr->fifo_errors % 50 == 0) {
591 printf("meteor%d: capture error", METEOR_NUM(mtr));
592 printf(": %s FIFO overflow.\n",
593 cap_err&0x0100? "even" : "odd");
595 mtr->fifo_errors++ ; /* increment fifo capture errors cnt */
597 if (cap_err & 0xc00) {
598 if(mtr->dma_errors % 50 == 0) {
599 printf("meteor%d: capture error", METEOR_NUM(mtr));
600 printf(": %s DMA address.\n",
601 cap_err&0x0400? "even" : "odd");
603 mtr->dma_errors++ ; /* increment DMA capture errors cnt */
606 *cap |= 0x0f30; /* clear error and field done */
609 * In synchronous capture mode we need to know what the address
610 * offset for the next field/frame will be. next_base holds the
611 * value for the even dma buffers (for odd, one must add stride).
613 if((mtr->flags & METEOR_SYNCAP) && !mtr->synch_wait &&
614 (mtr->current < mtr->frames)) { /* could be !=, but < is safer */
615 /* next_base is initialized to mtr->bigbuf */
616 next_base += mtr->frame_size * mtr->current;
617 if(mtr->flags & METEOR_WANT_TS)
618 next_base += sizeof(struct timeval) * mtr->current;
622 * Count the field and clear the field flag.
624 * In single mode capture, clear the continuous capture mode.
626 * In synchronous capture mode, if we have room for another field,
627 * adjust DMA buffer pointers.
628 * When we are above the hi water mark (hiwat), mtr->synch_wait will
629 * be set and we will not bump the DMA buffer pointers. Thus, once
630 * we reach the hi water mark, the driver acts like a continuous mode
631 * capture on the mtr->current frame until we hit the low water
632 * mark (lowat). The user had the option of stopping or halting
633 * the capture if this is not the desired effect.
635 if (status & 0x1) { /* even field */
636 mtr->even_fields_captured++;
637 mtr->flags &= ~METEOR_WANT_EVEN;
638 if((mtr->flags & METEOR_SYNCAP) && !mtr->synch_wait) {
640 /* XXX should add adjustments for YUV_422 & PLANAR */
643 * If the user requested to be notified via signal,
644 * let them know the field is complete.
646 if(mtr->proc && (mtr->signal & METEOR_SIG_MODE_MASK))
647 psignal(mtr->proc, mtr->signal&(~METEOR_SIG_MODE_MASK));
649 if (status & 0x2) { /* odd field */
650 mtr->odd_fields_captured++;
651 mtr->flags &= ~METEOR_WANT_ODD;
652 if((mtr->flags & METEOR_SYNCAP) && !mtr->synch_wait) {
653 *(base+3) = next_base + *(base+6);
654 /* XXX should add adjustments for YUV_422 & PLANAR */
657 * If the user requested to be notified via signal,
658 * let them know the field is complete.
660 if(mtr->proc && (mtr->signal & METEOR_SIG_MODE_MASK))
661 psignal(mtr->proc, mtr->signal&(~METEOR_SIG_MODE_MASK));
665 * If we have a complete frame.
667 if(!(mtr->flags & METEOR_WANT_MASK)) {
668 mtr->frames_captured++;
670 * post the completion time.
672 if(mtr->flags & METEOR_WANT_TS) {
675 if(mtr->alloc_pages * PAGE_SIZE <= (mtr->frame_size +
676 sizeof(struct timeval))) {
677 ts =(struct timeval *)mtr->bigbuf +
679 /* doesn't work in synch mode except for first frame */
685 * Wake up the user in single capture mode.
687 if(mtr->flags & METEOR_SINGLE)
688 wakeup((caddr_t)mtr);
690 * If the user requested to be notified via signal,
691 * let them know the frame is complete.
693 if(mtr->proc && !(mtr->signal & METEOR_SIG_MODE_MASK))
694 psignal(mtr->proc, mtr->signal&(~METEOR_SIG_MODE_MASK));
696 * Reset the want flags if in continuous or
697 * synchronous capture mode.
699 if(mtr->flags & (METEOR_CONTIN|METEOR_SYNCAP)) {
700 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
701 case METEOR_ONLY_ODD_FIELDS:
702 mtr->flags |= METEOR_WANT_ODD;
704 case METEOR_ONLY_EVEN_FIELDS:
705 mtr->flags |= METEOR_WANT_EVEN;
708 mtr->flags |= METEOR_WANT_MASK;
713 * Special handling for synchronous capture mode.
715 if(mtr->flags & METEOR_SYNCAP) {
716 struct meteor_mem *mm = mtr->mem;
718 * Mark the current frame as active. It is up to
719 * the user to clear this, but we will clear it
720 * for the user for the current frame being captured
721 * if we are within the water marks (see below).
723 mm->active |= 1 << (mtr->current - 1);
726 * Since the user can muck with these values, we need
727 * to check and see if they are sane. If they don't
728 * pass the sanity check, disable the capture mode.
729 * This is rather rude, but then so was the user.
731 * Do we really need all of this or should we just
732 * eliminate the possiblity of allowing the
733 * user to change hi and lo water marks while it
736 if(mm->num_active_bufs < 0 ||
737 mm->num_active_bufs > mtr->frames ||
738 mm->lowat < 1 || mm->lowat >= mtr->frames ||
739 mm->hiwat < 1 || mm->hiwat >= mtr->frames ||
740 mm->lowat > mm->hiwat ) {
742 mtr->flags &= ~(METEOR_SYNCAP|METEOR_WANT_MASK);
745 * Ok, they are sane, now we want to
746 * check the water marks.
748 if(mm->num_active_bufs <= mm->lowat)
750 if(mm->num_active_bufs >= mm->hiwat)
753 * Clear the active frame bit for this frame
754 * and advance the counters if we are within
755 * the banks of the water marks.
757 if(!mtr->synch_wait) {
758 mm->active &= ~(1 << mtr->current);
760 if(mtr->current > mtr->frames)
762 mm->num_active_bufs++;
768 *stat |= 0x7; /* clear interrupt status */
773 set_fps(meteor_reg_t *mtr, u_short fps)
775 struct saa7116_regs *s7116 = mtr->base;
777 unsigned maxfps, mask = 0x1, length = 0;
779 SAA7196_WRITE(mtr, SAA7196_STDC, SAA7196_REG(mtr, SAA7196_STDC) | 0x02);
781 status = (s7116->i2c_read & 0xff000000L) >> 24;
784 * Determine if there is an input signal. Depending on the
785 * frequency we either have a max of 25 fps (50 hz) or 30 fps (60 hz).
786 * If there is no input signal, then we need some defaults. If the
787 * user neglected to specify any defaults, just set to the fps to max.
789 if((status & 0x40) == 0) { /* Is there a signal ? */
791 maxfps = 30; /* 60 hz system */
793 maxfps = 25; /* 50 hz system */
795 } else { /* We have no signal, check defaults */
796 #if METEOR_SYSTEM_DEFAULT == METEOR_PAL || METEOR_SYSTEM_DEFAULT == METEOR_SECAM
798 #elif METEOR_SYSTEM_DEFAULT == METEOR_NTSC
801 /* Don't really know what to do, just set max */
808 * A little sanity checking...
811 if(fps > maxfps) fps = maxfps;
814 * Compute the mask/length using the fps.
819 } else if ((float)fps == maxfps/2.0) {
822 } else if (fps > maxfps/2) {
825 mask = (1<<maxfps) - 1;
827 step = (float)(maxfps - 1)/(float)(maxfps - fps);
828 for(b=step; b < maxfps; b += step) {
829 mask &= ~(1<<((int)b)); /* mask out the bth frame */
831 } else { /* fps < maxfps/2 */
836 step = (float)(maxfps -1)/(float)(fps);
837 for(b = step + 1; b < maxfps - 1; b += step) {
838 mask |= (1<<((int)b)); /* mask in the bth frame */
845 s7116->fme = s7116->fmo = mask;
846 s7116->fml = (length << 16) | length;;
855 * There is also a problem with range checking on the 7116.
856 * It seems to only work for 22 bits, so the max size we can allocate
857 * is 22 bits long or 4194304 bytes assuming that we put the beginning
858 * of the buffer on a 2^24 bit boundary. The range registers will use
859 * the top 8 bits of the dma start registers along with the bottom 22
860 * bits of the range register to determine if we go out of range.
861 * This makes getting memory a real kludge.
864 #define RANGE_BOUNDARY (1<<22)
866 get_meteor_mem(int unit, unsigned size)
868 vm_offset_t addr = 0;
870 addr = vm_page_alloc_contig(size, 0, 0xffffffff, 1<<24);
872 addr = vm_page_alloc_contig(size, 0, 0xffffffff, PAGE_SIZE);
874 printf("meteor%d: Unable to allocate %d bytes of memory.\n",
882 bt254_write(meteor_reg_t *mtr, u_char addr, u_char data)
884 addr &= 0x7; /* sanity? */
885 mtr->bt254_reg[addr] = data;
886 PCF8574_DATA_WRITE(mtr, data); /* set data */
887 PCF8574_CTRL_WRITE(mtr, (PCF8574_CTRL_REG(mtr) & ~0x7) | addr);
888 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) & ~0x10); /* WR/ to 0 */
889 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x10); /* WR to 1 */
890 PCF8574_DATA_WRITE(mtr, 0xff); /* clr data */
895 bt254_init(meteor_reg_t *mtr)
899 PCF8574_CTRL_WRITE(mtr, 0x7f);
900 PCF8574_DATA_WRITE(mtr, 0xff); /* data port must be 0xff */
901 PCF8574_CTRL_WRITE(mtr, 0x7f);
903 /* init RGB module for 24bpp, composite input */
904 for(i=0; i<NUM_BT254_REGS; i++)
905 bt254_write(mtr, i, bt254_default[i]);
907 bt254_write(mtr, BT254_COMMAND, 0x00); /* 24 bpp */
911 bt254_ntsc(meteor_reg_t *mtr, int arg)
915 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x20);
919 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) &= ~0x20);
924 select_bt254(meteor_reg_t *mtr)
926 /* disable saa7196, saaen = 1 */
927 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x80);
928 /* enable Bt254, bten = 0 */
929 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) & ~0x40);
933 select_saa7196(meteor_reg_t *mtr)
935 /* disable Bt254, bten = 1 */
936 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x40);
937 /* enable saa7196, saaen = 0 */
938 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) & ~0x80);
942 * Initialize the 7116, 7196 and the RGB module.
945 meteor_init ( meteor_reg_t *mtr )
951 * Initialize the Philips SAA7116
953 mtr->base->cap_cntl = 0x00000040L;
954 vbase_addr = &mtr->base->dma1e;
955 for (i = 0 ; i < (sizeof(struct saa7116_regs)/sizeof(mreg_t)); i++)
956 *vbase_addr++ = saa7116_pci_default[i];
959 * Check for the Philips SAA7196
962 if(i2c_write(mtr, SAA7196_I2C_ADDR, SAA7116_I2C_WRITE, 0, 0xff) == 0) {
967 for (i = 0; i < NUM_SAA7196_I2C_REGS; i++)
968 SAA7196_WRITE(mtr, i, saa7196_i2c_default[i]);
970 * Get version number.
972 SAA7196_WRITE(mtr, SAA7196_STDC,
973 SAA7196_REG(mtr, SAA7196_STDC) & ~0x02);
975 printf("meteor%d: <Philips SAA 7196> rev 0x%x\n",
977 (unsigned)((mtr->base->i2c_read & 0xff000000L) >> 28));
980 printf("meteor%d: <Philips SAA 7196 NOT FOUND>\n",
984 * Check for RGB module, initialized if found.
987 if(i2c_write(mtr,PCF8574_DATA_I2C_ADDR,SAA7116_I2C_WRITE,0,0xff) == 0) {
989 printf("meteor%d: <Booktree 254 (RGB module)>\n",
990 METEOR_NUM(mtr)); /* does this have a rev #? */
991 bt254_init(mtr); /* Set up RGB module */
992 mtr->flags = METEOR_RGB;
1003 met_attach(pcici_t tag, int unit)
1006 u_long old_irq, new_irq;
1012 if (unit >= NMETEOR) {
1013 printf("meteor%d: attach: only %d units configured.\n",
1015 printf("meteor%d: attach: invalid unit number.\n", unit);
1020 * Check for Meteor/PPB (PCI-PCI Bridge)
1021 * Reprogram IBM Bridge if detected.
1022 * New Meteor cards have an IBM PCI-PCI bridge, creating a secondary
1023 * PCI bus. The SAA chip is connected to this secondary bus.
1026 /* If we are not on PCI Bus 0, check for the Bridge */
1027 if ( pci_get_bus_from_tag( tag ) != 0) {
1030 /* get tag of parent bridge */
1031 bridge_tag = pci_get_parent_from_tag( tag );
1033 /* Look for IBM 82351, 82352 or 82353 */
1034 if (pci_conf_read(bridge_tag, PCI_ID_REG) == 0x00221014) {
1037 printf("meteor%d: PPB device detected, reprogramming IBM bridge.\n", unit);
1040 pci_cfgwrite(bridge_tag, 0x05, 0x00, 1);
1042 pci_cfgwrite(bridge_tag, 0x0d, 0x20, 1);
1043 /* write posting enable, prefetch enabled --> GRAB direction */
1044 pci_cfgwrite(bridge_tag, 0x42, 0x14, 1);
1045 /* set PRTR Primary retry timer register */
1046 pci_cfgwrite(bridge_tag, 0x4c, 0x10, 1);
1050 mtr = &meteor[unit];
1052 pci_map_mem(tag, PCI_MAP_REG_START, (vm_offset_t *)&mtr->base,
1055 #ifdef METEOR_IRQ /* from the configuration file */
1056 old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
1057 pci_conf_write(tag, PCI_INTERRUPT_REG, METEOR_IRQ);
1058 new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
1059 printf("meteor%d: attach: irq changed from %d to %d\n",
1060 unit, (old_irq & 0xff), (new_irq & 0xff));
1062 /* setup the interrupt handling routine */
1063 pci_map_int(tag, meteor_intr, (void*) mtr, &net_imask);
1066 * PCI latency timer. 32 is a good value for 4 bus mastering slots, if
1067 * you have more than for, then 16 would probably be a better value.
1070 #ifndef METEOR_DEF_LATENCY_VALUE
1071 #define METEOR_DEF_LATENCY_VALUE 32
1073 latency = pci_conf_read(tag, PCI_LATENCY_TIMER);
1074 latency = (latency >> 8) & 0xff;
1077 printf("meteor%d: PCI bus latency is", unit);
1079 printf("meteor%d: PCI bus latency was 0 changing to",
1083 latency = METEOR_DEF_LATENCY_VALUE;
1084 pci_conf_write(tag, PCI_LATENCY_TIMER, latency<<8);
1087 printf(" %lu.\n", latency);
1090 meteor_init(mtr); /* set up saa7116, saa7196, and rgb module */
1093 buf = get_meteor_mem(unit, METEOR_ALLOC);
1097 printf("meteor%d: buffer size %d, addr 0x%x\n",
1098 unit, METEOR_ALLOC, vtophys(buf));
1102 mtr->alloc_pages = METEOR_ALLOC_PAGES;
1104 bzero((caddr_t) buf, METEOR_ALLOC);
1106 /* 640x480 RGB 16 */
1107 mtr->base->dma1e = buf;
1108 mtr->base->dma1o = buf + 0x500;
1109 mtr->base->dma_end_e =
1110 mtr->base->dma_end_o = buf + METEOR_ALLOC;
1112 /* 1 frame of 640x480 RGB 16 */
1115 mtr->depth = 2; /* two bytes per pixel */
1116 mtr->frames = 1; /* one frame */
1118 mtr->flags |= METEOR_INITALIZED | METEOR_AUTOMODE | METEOR_DEV0 |
1120 make_dev(&meteor_cdevsw, unit, 0, 0, 0644, "meteor");
1123 #define UNIT(x) ((x) & 0x07)
1127 meteor_reset(dev_t dev)
1129 int unit = UNIT(minor(dev));
1130 struct saa7116_regs *m;
1135 m = meteor[unit].base;
1138 tsleep((caddr_t)m, METPRI, "Mreset", hz/50);
1140 m->cap_cntl = 0x8ff0;
1141 m->cap_cntl = 0x80c0;
1142 m->cap_cntl = 0x8040;
1143 tsleep((caddr_t)m, METPRI, "Mreset", hz/10);
1144 m->cap_cntl = 0x80c0;
1151 /*---------------------------------------------------------
1153 ** Meteor character device driver routines
1155 **---------------------------------------------------------
1160 meteor_open(dev_t dev, int flags, int fmt, struct proc *p)
1166 unit = UNIT(minor(dev));
1167 if (unit >= NMETEOR) /* unit out of range */
1170 mtr = &(meteor[unit]);
1172 if (!(mtr->flags & METEOR_INITALIZED)) /* device not found */
1175 if (mtr->flags & METEOR_OPEN) /* device is busy */
1178 mtr->flags |= METEOR_OPEN;
1180 * Make sure that the i2c regs are set the same for each open.
1182 for(i=0; i< NUM_SAA7196_I2C_REGS; i++) {
1183 SAA7196_WRITE(mtr, i, saa7196_i2c_default[i]);
1186 mtr->fifo_errors = 0;
1187 mtr->dma_errors = 0;
1188 mtr->frames_captured = 0;
1189 mtr->even_fields_captured = 0;
1190 mtr->odd_fields_captured = 0;
1191 mtr->proc = (struct proc *)0;
1193 #ifdef METEOR_TEST_VIDEO
1194 mtr->video.addr = 0;
1195 mtr->video.width = 0;
1196 mtr->video.banksize = 0;
1197 mtr->video.ramsize = 0;
1204 meteor_close(dev_t dev, int flags, int fmt, struct proc *p)
1208 #ifdef METEOR_DEALLOC_ABOVE
1212 unit = UNIT(minor(dev));
1213 if (unit >= NMETEOR) /* unit out of range */
1216 mtr = &(meteor[unit]);
1217 mtr->flags &= ~METEOR_OPEN;
1219 if(mtr->flags & METEOR_SINGLE)
1220 /* this should not happen, the read capture
1221 should have completed or in the very least
1222 recieved a signal before close is called. */
1223 wakeup((caddr_t)mtr); /* continue read */
1225 * Turn off capture mode.
1227 mtr->base->cap_cntl = 0x8ff0;
1228 mtr->flags &= ~(METEOR_CAP_MASK|METEOR_WANT_MASK);
1229 mtr->proc = (struct proc *)0;
1231 #ifdef METEOR_DEALLOC_PAGES
1232 if (mtr->bigbuf != NULL) {
1233 kmem_free(kernel_map,mtr->bigbuf,(mtr->alloc_pages*PAGE_SIZE));
1235 mtr->alloc_pages = 0;
1238 #ifdef METEOR_DEALLOC_ABOVE
1239 if (mtr->bigbuf != NULL && mtr->alloc_pages > METEOR_DEALLOC_ABOVE) {
1240 temp = METEOR_DEALLOC_ABOVE - mtr->alloc_pages;
1241 kmem_free(kernel_map,
1242 mtr->bigbuf+((mtr->alloc_pages - temp) * PAGE_SIZE),
1243 (temp * PAGE_SIZE));
1244 mtr->alloc_pages = METEOR_DEALLOC_ABOVE;
1253 start_capture(meteor_reg_t *mtr, unsigned type)
1255 mreg_t *cap = &mtr->base->cap_cntl;
1258 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1259 case METEOR_ONLY_EVEN_FIELDS:
1260 mtr->flags |= METEOR_WANT_EVEN;
1261 if(type == METEOR_SINGLE)
1262 *cap = 0x0ff4 | mtr->range_enable;
1264 *cap = 0x0ff1 | mtr->range_enable;
1266 case METEOR_ONLY_ODD_FIELDS:
1267 mtr->flags |= METEOR_WANT_ODD;
1268 if(type == METEOR_SINGLE)
1269 *cap = 0x0ff8 | mtr->range_enable;
1271 *cap = 0x0ff2 | mtr->range_enable;
1274 mtr->flags |= METEOR_WANT_MASK;
1275 if(type == METEOR_SINGLE)
1276 *cap = 0x0ffc | mtr->range_enable;
1278 *cap = 0x0ff3 | mtr->range_enable;
1284 meteor_read(dev_t dev, struct uio *uio, int ioflag)
1291 unit = UNIT(minor(dev));
1292 if (unit >= NMETEOR) /* unit out of range */
1295 mtr = &(meteor[unit]);
1296 if (mtr->bigbuf == 0)/* no frame buffer allocated (ioctl failed) */
1299 if (mtr->flags & METEOR_CAP_MASK)
1300 return(EIO); /* already capturing */
1302 count = mtr->rows * mtr->cols * mtr->depth;
1303 if (uio->uio_iov->iov_len < count)
1307 start_capture(mtr, METEOR_SINGLE);
1309 status=tsleep((caddr_t)mtr, METPRI, "capturing", 0);
1310 if (!status) /* successful capture */
1311 status = uiomove((caddr_t)mtr->bigbuf, count, uio);
1313 printf ("meteor%d: read: tsleep error %d\n", unit, status);
1315 mtr->flags &= ~(METEOR_SINGLE | METEOR_WANT_MASK);
1321 meteor_write(dev_t dev, struct uio *uio, int ioflag)
1327 meteor_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *pr)
1333 struct meteor_counts *cnt;
1334 struct meteor_geomet *geo;
1335 struct meteor_mem *mem;
1336 struct meteor_capframe *frame;
1337 #ifdef METEOR_TEST_VIDEO
1338 struct meteor_video *video;
1341 struct saa7116_regs *base;
1345 if (!arg) return(EINVAL);
1346 unit = UNIT(minor(dev));
1347 if (unit >= NMETEOR) /* unit out of range */
1350 mtr = &(meteor[unit]);
1356 mtr->flags |= METEOR_WANT_TS;
1358 mtr->flags &= ~METEOR_WANT_TS;
1361 if(mtr->flags & METEOR_WANT_TS)
1366 #ifdef METEOR_TEST_VIDEO
1368 video = (struct meteor_video *)arg;
1369 video->addr = mtr->video.addr;
1370 video->width = mtr->video.width;
1371 video->banksize = mtr->video.banksize;
1372 video->ramsize = mtr->video.ramsize;
1375 video = (struct meteor_video *)arg;
1376 mtr->video.addr = video->addr;
1377 mtr->video.width = video->width;
1378 mtr->video.banksize = video->banksize;
1379 mtr->video.ramsize = video->ramsize;
1383 set_fps(mtr, *(u_short *)arg);
1386 *(u_short *)arg = mtr->fps;
1389 mtr->signal = *(int *) arg;
1393 mtr->proc = (struct proc *)0;
1397 *(int *)arg = mtr->signal;
1399 case METEORSTATUS: /* get 7196 status */
1401 SAA7196_WRITE(mtr, SAA7196_STDC,
1402 SAA7196_REG(mtr, SAA7196_STDC) | 0x02);
1404 temp |= (base->i2c_read & 0xff000000L) >> 24;
1405 SAA7196_WRITE(mtr, SAA7196_STDC,
1406 SAA7196_REG(mtr, SAA7196_STDC) & ~0x02);
1408 temp |= (base->i2c_read & 0xff000000L) >> 16;
1409 *(u_short *)arg = temp;
1411 case METEORSHUE: /* set hue */
1412 SAA7196_WRITE(mtr, SAA7196_HUEC, *(char *)arg);
1414 case METEORGHUE: /* get hue */
1415 *(char *)arg = SAA7196_REG(mtr, SAA7196_HUEC);
1417 case METEORSCHCV: /* set chrominance gain */
1418 SAA7196_WRITE(mtr, SAA7196_CGAINR, *(char *)arg);
1420 case METEORGCHCV: /* get chrominance gain */
1421 *(char *)arg = SAA7196_REG(mtr, SAA7196_CGAINR);
1423 case METEORSBRIG: /* set brightness */
1424 SAA7196_WRITE(mtr, SAA7196_BRIG, *(char *)arg);
1426 case METEORGBRIG: /* get brightness */
1427 *(char *)arg = SAA7196_REG(mtr, SAA7196_BRIG);
1429 case METEORSCSAT: /* set chroma saturation */
1430 SAA7196_WRITE(mtr, SAA7196_CSAT, *(char *)arg);
1432 case METEORGCSAT: /* get chroma saturation */
1433 *(char *)arg = SAA7196_REG(mtr, SAA7196_CSAT);
1435 case METEORSCONT: /* set contrast */
1436 SAA7196_WRITE(mtr, SAA7196_CONT, *(char *)arg);
1438 case METEORGCONT: /* get contrast */
1439 *(char *)arg = SAA7196_REG(mtr, SAA7196_CONT);
1442 if((mtr->flags & METEOR_RGB) == 0)
1444 temp = *(unsigned short *)arg;
1445 bt254_write(mtr, temp & 0xf, (temp & 0x0ff0) >> 4);
1448 if((mtr->flags & METEOR_RGB) == 0)
1450 temp = *(unsigned short *)arg & 0x7;
1451 *(unsigned short *)arg = mtr->bt254_reg[temp] << 4 | temp;
1453 case METEORSHWS: /* set horizontal window start */
1454 SAA7196_WRITE(mtr, SAA7196_HWS, *(char *)arg);
1456 case METEORGHWS: /* get horizontal window start */
1457 *(char *)arg = SAA7196_REG(mtr, SAA7196_HWS);
1459 case METEORSVWS: /* set vertical window start */
1460 SAA7196_WRITE(mtr, SAA7196_VWS, *(char *)arg);
1462 case METEORGVWS: /* get vertical window start */
1463 *(char *)arg = SAA7196_REG(mtr, SAA7196_VWS);
1465 case METEORSINPUT: /* set input device */
1466 switch(*(unsigned long *)arg & METEOR_DEV_MASK) {
1467 case 0: /* default */
1468 case METEOR_INPUT_DEV0:
1469 if(mtr->flags & METEOR_RGB)
1470 select_saa7196(mtr);
1471 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1473 SAA7196_WRITE(mtr, 0x0e,
1474 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x0);
1475 SAA7196_WRITE(mtr, 0x06,
1476 (SAA7196_REG(mtr, 0x06) & ~0x80));
1478 case METEOR_INPUT_DEV1:
1479 if(mtr->flags & METEOR_RGB)
1480 select_saa7196(mtr);
1481 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1483 SAA7196_WRITE(mtr, 0x0e,
1484 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x1);
1485 SAA7196_WRITE(mtr, 0x06,
1486 (SAA7196_REG(mtr, 0x06) & ~0x80));
1488 case METEOR_INPUT_DEV2:
1489 if(mtr->flags & METEOR_RGB)
1490 select_saa7196(mtr);
1491 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1493 SAA7196_WRITE(mtr, 0x0e,
1494 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x2);
1495 SAA7196_WRITE(mtr, 0x06,
1496 (SAA7196_REG(mtr, 0x06) & ~0x80));
1498 case METEOR_INPUT_DEV3:
1499 if(mtr->flags & METEOR_RGB)
1500 select_saa7196(mtr);
1501 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1503 SAA7196_WRITE(mtr, 0x0e,
1504 (SAA7196_REG(mtr, 0x0e) | 0x3));
1505 SAA7196_WRITE(mtr, 0x06,
1506 (SAA7196_REG(mtr, 0x06) & ~0x80) );
1508 case METEOR_INPUT_DEV_SVIDEO:
1509 if(mtr->flags & METEOR_RGB)
1510 select_saa7196(mtr);
1511 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1512 | METEOR_DEV_SVIDEO;
1513 SAA7196_WRITE(mtr, 0x0e,
1514 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x2);
1515 SAA7196_WRITE(mtr, 0x06,
1516 (SAA7196_REG(mtr, 0x06) & ~0x80) | 0x80);
1518 case METEOR_INPUT_DEV_RGB:
1519 if((mtr->flags & METEOR_RGB) == 0)
1521 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1523 SAA7196_WRITE(mtr, 0x0e,
1524 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x3);
1525 SAA7196_WRITE(mtr, 0x06,
1526 (SAA7196_REG(mtr, 0x06) & ~0x80));
1528 SAA7196_WRITE(mtr, 0x0e, /* chn 3 for synch */
1529 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x3);
1535 case METEORGINPUT: /* get input device */
1536 *(u_long *)arg = mtr->flags & METEOR_DEV_MASK;
1538 case METEORSFMT: /* set input format */
1539 switch(*(unsigned long *)arg & METEOR_FORM_MASK ) {
1540 case 0: /* default */
1541 case METEOR_FMT_NTSC:
1542 mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1544 SAA7196_WRITE(mtr, SAA7196_STDC,
1545 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01));
1546 SAA7196_WRITE(mtr, 0x0f,
1547 (SAA7196_REG(mtr, 0x0f) & ~0xe0) | 0x40);
1548 SAA7196_WRITE(mtr, 0x22, 0x80);
1549 SAA7196_WRITE(mtr, 0x24,
1550 (SAA7196_REG(mtr, 0x24) & ~0x0c) | 0x08);
1551 SAA7196_WRITE(mtr, 0x26, 0xf0);
1552 SAA7196_WRITE(mtr, 0x28,
1553 (SAA7196_REG(mtr, 0x28) & ~0x0c)) ;
1554 if(mtr->flags & METEOR_RGB){
1558 case METEOR_FMT_PAL:
1559 mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1561 SAA7196_WRITE(mtr, SAA7196_STDC,
1562 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01));
1563 SAA7196_WRITE(mtr, 0x0f,
1564 (SAA7196_REG(mtr, 0x0f) & ~0xe0));
1565 SAA7196_WRITE(mtr, 0x22, 0x00);
1566 SAA7196_WRITE(mtr, 0x24,
1567 (SAA7196_REG(mtr, 0x24) | 0x0c));
1568 SAA7196_WRITE(mtr, 0x26, 0x20);
1569 SAA7196_WRITE(mtr, 0x28,
1570 (SAA7196_REG(mtr, 0x28) & ~0x0c) | 0x04) ;
1571 if(mtr->flags & METEOR_RGB){
1575 case METEOR_FMT_SECAM:
1576 mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1578 SAA7196_WRITE(mtr, SAA7196_STDC,
1579 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01) | 0x1);
1580 SAA7196_WRITE(mtr, 0x0f,
1581 (SAA7196_REG(mtr, 0x0f) & ~0xe0) | 0x20);
1582 SAA7196_WRITE(mtr, 0x22, 0x00);
1583 SAA7196_WRITE(mtr, 0x24,
1584 (SAA7196_REG(mtr, 0x24) | 0x0c));
1585 SAA7196_WRITE(mtr, 0x26, 0x20);
1586 SAA7196_WRITE(mtr, 0x28,
1587 (SAA7196_REG(mtr, 0x28) & ~0x0c) | 0x04) ;
1588 if(mtr->flags & METEOR_RGB){
1592 case METEOR_FMT_AUTOMODE:
1593 mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1595 SAA7196_WRITE(mtr, SAA7196_STDC,
1596 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01));
1597 SAA7196_WRITE(mtr, 0x0f,
1598 (SAA7196_REG(mtr, 0x0f) & ~0xe0) | 0x80);
1604 case METEORGFMT: /* get input format */
1605 *(u_long *)arg = mtr->flags & METEOR_FORM_MASK;
1609 switch (*(int *) arg) {
1610 case METEOR_CAP_SINGLE:
1611 if (mtr->bigbuf==0) /* no frame buffer allocated */
1614 if (temp & METEOR_CAP_MASK)
1615 return(EIO); /* already capturing */
1617 start_capture(mtr, METEOR_SINGLE);
1619 /* wait for capture to complete */
1620 error=tsleep((caddr_t)mtr, METPRI, "capturing", 0);
1622 printf("meteor%d: ioctl: tsleep error %d\n",
1624 mtr->flags &= ~(METEOR_SINGLE|METEOR_WANT_MASK);
1626 case METEOR_CAP_CONTINOUS:
1627 if (mtr->bigbuf==0) /* no frame buffer allocated */
1630 if (temp & METEOR_CAP_MASK)
1631 return(EIO); /* already capturing */
1633 start_capture(mtr, METEOR_CONTIN);
1636 case METEOR_CAP_STOP_CONT:
1637 if (mtr->flags & METEOR_CONTIN) {
1638 /* turn off capture */
1639 base->cap_cntl = 0x8ff0;
1640 mtr->flags &= ~(METEOR_CONTIN|METEOR_WANT_MASK);
1650 frame = (struct meteor_capframe *) arg;
1653 switch (frame->command) {
1654 case METEOR_CAP_N_FRAMES:
1655 if (mtr->flags & METEOR_CAP_MASK)
1657 if (mtr->flags & (METEOR_YUV_PLANAR | METEOR_YUV_422)) /* XXX */
1658 return(EINVAL); /* should fix intr so we allow these */
1659 if (mtr->bigbuf == 0)
1661 if ((mtr->frames < 2) ||
1662 (frame->lowat < 1 || frame->lowat >= mtr->frames) ||
1663 (frame->hiwat < 1 || frame->hiwat >= mtr->frames) ||
1664 (frame->lowat > frame->hiwat))
1666 /* meteor_mem structure is on the page after the data */
1667 mem = mtr->mem = (struct meteor_mem *) (mtr->bigbuf +
1668 (round_page(mtr->frame_size * mtr->frames)));
1670 mtr->synch_wait = 0;
1671 mem->num_bufs = mtr->frames;
1672 mem->frame_size= mtr->frame_size;
1673 /* user and kernel change these */
1674 mem->lowat = frame->lowat;
1675 mem->hiwat = frame->hiwat;
1677 mem->num_active_bufs = 0;
1679 start_capture(mtr, METEOR_SYNCAP);
1681 case METEOR_CAP_STOP_FRAMES:
1682 if (mtr->flags & METEOR_SYNCAP) {
1683 /* turn off capture */
1684 base->cap_cntl = 0x8ff0;
1685 mtr->flags &= ~(METEOR_SYNCAP|METEOR_WANT_MASK);
1688 case METEOR_HALT_N_FRAMES:
1689 if(mtr->flags & METEOR_SYNCAP) {
1690 base->cap_cntl = 0x8ff0;
1691 mtr->flags &= ~(METEOR_WANT_MASK);
1694 case METEOR_CONT_N_FRAMES:
1695 if(!(mtr->flags & METEOR_SYNCAP)) {
1699 start_capture(mtr, METEOR_SYNCAP);
1708 geo = (struct meteor_geomet *) arg;
1710 /* Either even or odd, if even & odd, then these a zero */
1711 if((geo->oformat & METEOR_GEO_ODD_ONLY) &&
1712 (geo->oformat & METEOR_GEO_EVEN_ONLY)) {
1713 printf("meteor%d: ioctl: Geometry odd or even only.\n",
1717 /* set/clear even/odd flags */
1718 if(geo->oformat & METEOR_GEO_ODD_ONLY)
1719 mtr->flags |= METEOR_ONLY_ODD_FIELDS;
1721 mtr->flags &= ~METEOR_ONLY_ODD_FIELDS;
1722 if(geo->oformat & METEOR_GEO_EVEN_ONLY)
1723 mtr->flags |= METEOR_ONLY_EVEN_FIELDS;
1725 mtr->flags &= ~METEOR_ONLY_EVEN_FIELDS;
1727 /* can't change parameters while capturing */
1728 if (mtr->flags & METEOR_CAP_MASK)
1731 if ((geo->columns & 0x3fe) != geo->columns) {
1733 "meteor%d: ioctl: %d: columns too large or not even.\n",
1734 unit, geo->columns);
1737 if (((geo->rows & 0x7fe) != geo->rows) ||
1738 ((geo->oformat & METEOR_GEO_FIELD_MASK) &&
1739 ((geo->rows & 0x3fe) != geo->rows)) ) {
1741 "meteor%d: ioctl: %d: rows too large or not even.\n",
1745 if (geo->frames > 32) {
1746 printf("meteor%d: ioctl: too many frames.\n", unit);
1749 if(error) return error;
1751 if ((temp=geo->rows * geo->columns * geo->frames * 2) != 0) {
1752 if (geo->oformat & METEOR_GEO_RGB24) temp = temp * 2;
1754 /* meteor_mem structure for SYNC Capture */
1755 if (geo->frames > 1) temp += PAGE_SIZE;
1758 if (temp > mtr->alloc_pages
1759 #ifdef METEOR_TEST_VIDEO
1760 && mtr->video.addr == 0
1763 buf = get_meteor_mem(unit, temp*PAGE_SIZE);
1765 kmem_free(kernel_map, mtr->bigbuf,
1766 (mtr->alloc_pages * PAGE_SIZE));
1768 mtr->alloc_pages = temp;
1771 "meteor%d: ioctl: Allocating %d bytes\n",
1772 unit, temp*PAGE_SIZE);
1778 if(error) return error;
1780 mtr->rows = geo->rows;
1781 mtr->cols = geo->columns;
1782 mtr->frames = geo->frames;
1784 #ifdef METEOR_TEST_VIDEO
1786 buf = vtophys(mtr->video.addr);
1789 buf = vtophys(mtr->bigbuf);
1791 /* set defaults and end of buffer locations */
1804 /* set end of DMA location, even/odd */
1806 base->dma_end_o = buf + mtr->alloc_pages * PAGE_SIZE;
1809 * Determine if we can use the hardware range detect.
1811 if(mtr->alloc_pages * PAGE_SIZE < RANGE_BOUNDARY &&
1812 ((buf & 0xff000000) | base->dma_end_e) ==
1813 (buf + mtr->alloc_pages * PAGE_SIZE) )
1814 mtr->range_enable = 0x8000;
1816 mtr->range_enable = 0x0;
1818 base->dma_end_o = 0xffffffff;
1822 switch (geo->oformat & METEOR_GEO_OUTPUT_MASK) {
1823 case 0: /* default */
1824 case METEOR_GEO_RGB16:
1826 mtr->frame_size = mtr->rows * mtr->cols * mtr->depth;
1827 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1828 mtr->flags |= METEOR_RGB16;
1829 temp = mtr->cols * mtr->depth;
1830 /* recal stride and starting point */
1831 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1832 case METEOR_ONLY_ODD_FIELDS:
1834 #ifdef METEOR_TEST_VIDEO
1835 if(mtr->video.addr && mtr->video.width)
1836 base->stride1o = mtr->video.width-temp;
1838 SAA7196_WRITE(mtr, 0x20, 0xd0);
1840 case METEOR_ONLY_EVEN_FIELDS:
1842 #ifdef METEOR_TEST_VIDEO
1843 if(mtr->video.addr && mtr->video.width)
1844 base->stride1e = mtr->video.width-temp;
1846 SAA7196_WRITE(mtr, 0x20, 0xf0);
1848 default: /* interlaced even/odd */
1850 base->dma1o = buf + temp;
1851 base->stride1e = base->stride1o = temp;
1852 #ifdef METEOR_TEST_VIDEO
1853 if(mtr->video.addr && mtr->video.width) {
1854 base->dma1o = buf + mtr->video.width;
1855 base->stride1e = base->stride1o =
1857 temp + mtr->video.width;
1860 SAA7196_WRITE(mtr, 0x20, 0x90);
1863 base->routee = base->routeo = 0xeeeeee01;
1865 case METEOR_GEO_RGB24:
1867 mtr->frame_size = mtr->rows * mtr->cols * mtr->depth;
1868 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1869 mtr->flags |= METEOR_RGB24;
1870 temp = mtr->cols * mtr->depth;
1871 /* recal stride and starting point */
1872 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1873 case METEOR_ONLY_ODD_FIELDS:
1875 #ifdef METEOR_TEST_VIDEO
1876 if(mtr->video.addr && mtr->video.width)
1877 base->stride1o = mtr->video.width-temp;
1879 SAA7196_WRITE(mtr, 0x20, 0xd2);
1881 case METEOR_ONLY_EVEN_FIELDS:
1883 #ifdef METEOR_TEST_VIDEO
1884 if(mtr->video.addr && mtr->video.width)
1885 base->stride1e = mtr->video.width-temp;
1887 SAA7196_WRITE(mtr, 0x20, 0xf2);
1889 default: /* interlaced even/odd */
1891 base->dma1o = buf + mtr->cols * mtr->depth;
1892 base->stride1e = base->stride1o =
1893 mtr->cols * mtr->depth;
1894 #ifdef METEOR_TEST_VIDEO
1895 if(mtr->video.addr && mtr->video.width) {
1896 base->dma1o = buf + mtr->video.width;
1897 base->stride1e = base->stride1o =
1899 temp + mtr->video.width;
1902 SAA7196_WRITE(mtr, 0x20, 0x92);
1905 base->routee= base->routeo= 0x39393900;
1907 case METEOR_GEO_YUV_PLANAR:
1909 temp = mtr->rows * mtr->cols; /* compute frame size */
1910 mtr->frame_size = temp * mtr->depth;
1911 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1912 mtr->flags |= METEOR_YUV_PLANAR;
1913 /* recal stride and starting point */
1914 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1915 case METEOR_ONLY_ODD_FIELDS:
1916 base->dma1o = buf; /* Y Odd */
1917 base->dma2o = buf + temp; /* U Odd */
1919 base->dma3o = base->dma2o + temp; /* V Odd */
1920 SAA7196_WRITE(mtr, 0x20, 0xd1);
1922 case METEOR_ONLY_EVEN_FIELDS:
1923 base->dma1e = buf; /* Y Even */
1924 base->dma2e = buf + temp; /* U Even */
1926 base->dma2e= base->dma2e + temp; /* V Even */
1927 SAA7196_WRITE(mtr, 0x20, 0xf1);
1929 default: /* interlaced even/odd */
1930 base->dma1e = buf; /* Y Even */
1931 base->dma2e = buf + temp; /* U Even */
1933 base->dma3e = base->dma2e + temp; /* V Even */
1934 base->dma1o = base->dma1e+mtr->cols;/* Y Odd */
1935 base->dma2o = base->dma3e + temp; /* U Odd */
1936 base->dma3o = base->dma2o + temp; /* V Odd */
1937 base->stride1e = base->stride1o = mtr->cols;
1938 SAA7196_WRITE(mtr, 0x20, 0x91);
1941 switch (geo->oformat &
1942 (METEOR_GEO_YUV_12 | METEOR_GEO_YUV_9)) {
1943 case METEOR_GEO_YUV_9:
1944 base->routee=base->routeo = 0xaaaaffc3;
1946 case METEOR_GEO_YUV_12:
1947 base->routee=base->routeo = 0xaaaaffc2;
1950 base->routee=base->routeo = 0xaaaaffc1;
1954 case METEOR_GEO_YUV_422:/* same as planer, different uv order */
1956 temp = mtr->rows * mtr->cols; /* compute frame size */
1957 mtr->frame_size = temp * mtr->depth;
1958 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1959 mtr->flags |= METEOR_YUV_422;
1960 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1961 case METEOR_ONLY_ODD_FIELDS:
1963 base->dma2o = buf + temp;
1964 base->dma3o = base->dma2o + (temp >> 1);
1965 SAA7196_WRITE(mtr, 0x20, 0xd1);
1967 case METEOR_ONLY_EVEN_FIELDS:
1969 base->dma2e = buf + temp;
1970 base->dma3e = base->dma2e + (temp >> 1);
1971 SAA7196_WRITE(mtr, 0x20, 0xf1);
1973 default: /* interlaced even/odd */
1974 base->dma1e = buf; /* Y even */
1975 base->dma2e = buf + temp; /* U even */
1977 base->dma2e + (temp >> 1);/* V even */
1978 base->dma1o = base->dma1e+mtr->cols;/* Y odd */
1979 temp = mtr->cols >> 1;
1980 base->dma2o = base->dma2e+temp; /* U odd */
1981 base->dma3o = base->dma3e+temp; /* V odd */
1983 base->stride1o = mtr->cols; /* Y stride */
1985 base->stride2o = temp; /* U stride */
1987 base->stride3o = temp; /* V stride */
1988 SAA7196_WRITE(mtr, 0x20, 0x91);
1991 switch (geo->oformat &
1992 (METEOR_GEO_YUV_12 | METEOR_GEO_YUV_9)) {
1993 case METEOR_GEO_YUV_9:
1994 base->routee=base->routeo = 0xaaaaffc3;
1996 case METEOR_GEO_YUV_12:
1997 base->routee=base->routeo = 0xaaaaffc2;
2000 base->routee=base->routeo = 0xaaaaffc1;
2004 case METEOR_GEO_YUV_PACKED:
2006 mtr->frame_size = mtr->rows * mtr->cols * mtr->depth;
2007 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
2008 mtr->flags |= METEOR_YUV_PACKED;
2009 /* recal stride and odd starting point */
2010 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
2011 case METEOR_ONLY_ODD_FIELDS:
2013 SAA7196_WRITE(mtr, 0x20, 0xd1);
2015 case METEOR_ONLY_EVEN_FIELDS:
2017 SAA7196_WRITE(mtr, 0x20, 0xf1);
2019 default: /* interlaced even/odd */
2021 base->dma1o = buf + mtr->cols * mtr->depth;
2022 base->stride1e = base->stride1o =
2023 mtr->cols * mtr->depth;
2024 SAA7196_WRITE(mtr, 0x20, 0x91);
2027 base->routee = base->routeo = 0xeeeeee41;
2030 error = EINVAL; /* invalid argument */
2031 printf("meteor%d: ioctl: invalid output format\n",unit);
2035 SAA7196_WRITE(mtr, 0x21, mtr->cols & 0xff);
2036 SAA7196_WRITE(mtr, 0x24,
2037 ((SAA7196_REG(mtr, 0x24) & ~0x03) |
2038 ((mtr->cols >> 8) & 0x03)));
2040 if(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
2041 SAA7196_WRITE(mtr, 0x25, ((mtr->rows) & 0xff));
2042 SAA7196_WRITE(mtr, 0x28,
2043 ((SAA7196_REG(mtr, 0x28) & ~0x03) |
2044 ((mtr->rows >> 8) & 0x03)));
2045 } else { /* Interlaced */
2046 SAA7196_WRITE(mtr, 0x25, ((mtr->rows >> 1) & 0xff));
2047 SAA7196_WRITE(mtr, 0x28,
2048 ((SAA7196_REG(mtr, 0x28) & ~0x03) |
2049 ((mtr->rows >> 9) & 0x03)));
2051 /* set signed/unsigned chrominance */
2052 SAA7196_WRITE(mtr, 0x30, (SAA7196_REG(mtr, 0x30) & ~0x10) |
2053 ((geo->oformat&METEOR_GEO_UNSIGNED)?0:0x10));
2056 geo = (struct meteor_geomet *) arg;
2057 geo->rows = mtr->rows;
2058 geo->columns = mtr->cols;
2059 geo->frames = mtr->frames;
2060 geo->oformat = (mtr->flags & METEOR_OUTPUT_FMT_MASK) |
2061 (mtr->flags & METEOR_ONLY_FIELDS_MASK) |
2062 (SAA7196_REG(mtr, 0x30) & 0x10 ?
2063 0:METEOR_GEO_UNSIGNED);
2064 switch(base->routee & 0xff) {
2066 geo->oformat |= METEOR_GEO_YUV_9;
2069 geo->oformat |= METEOR_GEO_YUV_12;
2075 case METEORSCOUNT: /* (re)set error counts */
2076 cnt = (struct meteor_counts *) arg;
2077 mtr->fifo_errors = cnt->fifo_errors;
2078 mtr->dma_errors = cnt->dma_errors;
2079 mtr->frames_captured = cnt->frames_captured;
2080 mtr->even_fields_captured = cnt->even_fields_captured;
2081 mtr->odd_fields_captured = cnt->odd_fields_captured;
2083 case METEORGCOUNT: /* get error counts */
2084 cnt = (struct meteor_counts *) arg;
2085 cnt->fifo_errors = mtr->fifo_errors;
2086 cnt->dma_errors = mtr->dma_errors;
2087 cnt->frames_captured = mtr->frames_captured;
2088 cnt->even_fields_captured = mtr->even_fields_captured;
2089 cnt->odd_fields_captured = mtr->odd_fields_captured;
2092 printf("meteor%d: ioctl: invalid ioctl request\n", unit);
2100 meteor_mmap(dev_t dev, vm_offset_t offset, int nprot)
2106 unit = UNIT(minor(dev));
2107 if (unit >= NMETEOR) /* at this point could this happen? */
2110 mtr = &(meteor[unit]);
2113 if(nprot & PROT_EXEC)
2116 if(offset >= mtr->alloc_pages * PAGE_SIZE)
2119 return i386_btop(vtophys(mtr->bigbuf) + offset);