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.14 2004/07/23 14:09:31 joerg 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.
149 #include "use_meteor.h"
150 #include "opt_meteor.h"
152 #include <sys/param.h>
153 #include <sys/systm.h>
154 #include <sys/conf.h>
155 #include <sys/kernel.h>
156 #include <sys/signalvar.h>
157 #include <sys/mman.h>
160 #if defined(METEOR_FreeBSD_210)
161 #include <machine/cpu.h> /* bootverbose */
165 #include <vm/vm_kern.h>
167 #include <vm/vm_extern.h>
169 #include <bus/pci/pcivar.h>
170 #include <bus/pci/pcireg.h>
171 #include <dev/video/meteor/ioctl_meteor.h>
172 #include <dev/video/meteor/meteor_reg.h>
175 static void meteor_intr (void *arg);
178 * Allocate enough memory for:
179 * 768x576 RGB 16 or YUV (16 storage bits/pixel) = 884736 = 216 pages
181 * You may override this using the options "METEOR_ALLOC_PAGES=value" in your
182 * kernel configuration file.
184 #ifndef METEOR_ALLOC_PAGES
185 #define METEOR_ALLOC_PAGES 217
187 #define METEOR_ALLOC (METEOR_ALLOC_PAGES * PAGE_SIZE)
189 static meteor_reg_t meteor[NMETEOR];
190 #define METEOR_NUM(mtr) ((mtr - &meteor[0])/sizeof(meteor_reg_t))
192 #define METPRI PCATCH
194 static const char* met_probe (pcici_t tag, pcidi_t type);
195 static void met_attach(pcici_t tag, int unit);
196 static u_long met_count;
198 static struct pci_device met_device = {
205 COMPAT_PCI_DRIVER (meteor, met_device);
207 #if defined(METEOR_FreeBSD_210) /* XXX */
208 d_open_t meteor_open;
209 d_close_t meteor_close;
210 d_read_t meteor_read;
211 d_write_t meteor_write;
212 d_ioctl_t meteor_ioctl;
213 d_mmap_t meteor_mmap;
215 static d_open_t meteor_open;
216 static d_close_t meteor_close;
217 static d_read_t meteor_read;
218 static d_write_t meteor_write;
219 static d_ioctl_t meteor_ioctl;
220 static d_mmap_t meteor_mmap;
222 #define CDEV_MAJOR 67
223 static struct cdevsw meteor_cdevsw = {
225 /* maj */ CDEV_MAJOR,
230 /* open */ meteor_open,
231 /* close */ meteor_close,
232 /* read */ meteor_read,
233 /* write */ meteor_write,
234 /* ioctl */ meteor_ioctl,
236 /* mmap */ meteor_mmap,
237 /* strategy */ nostrategy,
243 static mreg_t saa7116_pci_default[sizeof(struct saa7116_regs)/sizeof(mreg_t)]={
244 /* PCI Memory registers */
245 /* BITS Type Description */
246 /* 0x00 */ 0x00000000, /* 31:1 e*RW DMA 1 (Even)
248 /* 0x04 */ 0x00000000, /* 31:2 e*RW DMA 2 (Even)
250 /* 0x08 */ 0x00000000, /* 31:2 e*RW DMA 3 (Even)
252 /* 0x0c */ 0x00000000, /* 31:1 o*RW DMA 1 (Odd)
254 /* 0x10 */ 0x00000000, /* 31:2 o*RW DMA 2 (Odd)
256 /* 0x14 */ 0x00000000, /* 31:2 o*RW DMA 3 (Odd)
258 /* 0x18 */ 0x00000500, /* 15:2 e*RW Stride 1 (Even)
260 /* 0x1c */ 0x00000000, /* 15:2 e*RW Stride 2 (Even)
262 /* 0x20 */ 0x00000000, /* 15:2 e*RW Stride 3 (Even)
264 /* 0x24 */ 0x00000500, /* 15:2 o*RW Stride 1 (Odd)
266 /* 0x28 */ 0x00000000, /* 15:2 o*RW Stride 2 (Odd)
268 /* 0x2c */ 0x00000000, /* 15:2 o*RW Stride 3 (Odd)
270 /* 0x30 */ 0xeeeeee01, /* 31:8 *RW Route (Even)
271 7:0 *RW Mode (Even) */
272 /* 0x34 */ 0xeeeeee01, /* 31:8 *RW Route (Odd)
273 7:0 *RW Mode (Odd) */
274 /* 0x38 */ 0x00200020, /* 22:16 *RW FIFO Trigger Planer Mode,
275 6:0 *RW FIFO Trigger Packed Mode */
276 /* 0x3c */ 0x00000107, /* 9:8 *RW Reserved (0x0)
279 0 *RW Reserved (0x1) */
280 /* 0x40 */ 0x000000c0, /* 15 *RW Range Enable
281 14 *RW Corrupt Disable
282 11 *RR Address Error (Odd)
283 10 *RR Address Error (Even)
284 9 *RR Field Corrupt (Odd)
285 8 *RR Field Corrupt (Even)
288 5 *RR Field Done (Odd)
289 4 *RR Field Done (Even)
290 3 *RS Single Field Capture (Odd)
291 2 *RS Single Field Capture (Even)
292 1 *RW Capture (ODD) Continous
293 0 *RW Capture (Even) Continous */
294 /* 0x44 */ 0x00000000, /* 7:0 *RW Retry Wait Counter */
295 /* 0x48 */ 0x00000307, /* 10 *RW Interrupt mask, start of field
296 9 *RW Interrupt mask, end odd field
297 8 *RW Interrupt mask, end even field
298 2 *RR Interrupt status, start of field
299 1 *RR Interrupt status, end of odd
300 0 *RR Interrupt status, end of even */
301 /* 0x4c */ 0x00000001, /* 31:0 *RW Field Mask (Even) continous */
302 /* 0x50 */ 0x00000001, /* 31:0 *RW Field Mask (Odd) continous */
303 /* 0x54 */ 0x00000000, /* 20:16 *RW Mask Length (Odd)
304 4:0 *RW Mask Length (Even) */
305 /* 0x58 */ 0x0005007c, /* 22:16 *RW FIFO almost empty
306 6:0 *RW FIFO almost full */
307 /* 0x5c */ 0x461e1e0f, /* 31:24 *RW I2C Phase 4
308 23:16 *RW I2C Phase 3
310 7:0 *RW I2C Phase 1 */
311 /* 0x60 */ 0x00000300, /* 31:24 *RO I2C Read Data
312 23:16 **RW I2C Auto Address
315 9 RR I2C Direct Abort
320 0 RW I2C Auto Enable */
321 /* 0x64 */ 0x00000000, /* 24 RS I2C New Cycle
322 23:16 **RW I2C Direct Address
323 15:8 **RW I2C Direct Sub-address
324 7:0 **RW I2C Direct Write Address */
325 /* 0x68 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 1 (Even)
326 23:16 **RW I2C Auto Data 1 (Even)
327 15:8 **RW I2C Auto Sub-address 0 (Even)
328 7:0 **RW I2C Auto Data 0 (Even) */
329 /* 0x6c */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 3 (Even)
330 23:16 **RW I2C Auto Data 3 (Even)
331 15:8 **RW I2C Auto Sub-address 2 (Even)
332 7:0 **RW I2C Auto Data 2 (Even) */
333 /* 0x70 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 5 (Even)
334 23:16 **RW I2C Auto Data 5 (Even)
335 15:8 **RW I2C Auto Sub-address 4 (Even)
336 7:0 **RW I2C Auto Data 4 (Even) */
337 /* 0x74 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 7 (Even)
338 23:16 **RW I2C Auto Data 7 (Even)
339 15:8 **RW I2C Auto Sub-address 6 (Even)
340 7:0 **RW I2C Auto Data 6 (Even) */
341 /* 0x78 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 1 (Odd)
342 23:16 **RW I2C Auto Data 1 (Odd)
343 15:8 **RW I2C Auto Sub-address 0 (Odd)
344 7:0 **RW I2C Auto Data 0 (Odd) */
345 /* 0x7c */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 3 (Odd)
346 23:16 **RW I2C Auto Data 3 (Odd)
347 15:8 **RW I2C Auto Sub-address 2 (Odd)
348 7:0 **RW I2C Auto Data 2 (Odd) */
349 /* 0x80 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 5 (Odd)
350 23:16 **RW I2C Auto Data 5 (Odd)
351 15:8 **RW I2C Auto Sub-address 4 (Odd)
352 7:0 **RW I2C Auto Data 4 (Odd) */
353 /* 0x84 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 7 (Odd)
354 23:16 **RW I2C Auto Data 7 (Odd)
355 15:8 **RW I2C Auto Sub-address 6 (Odd)
356 7:0 **RW I2C Auto Data 6 (Odd) */
357 /* 0x88 */ 0x00000000, /* 23:16 **RW I2C Register Enable (Odd)
358 7:0 **RW I2C Register Enable (Even) */
359 /* 0x8c */ 0x00000000, /* 23:2 e*RW DMA End (Even)
361 /* 0x90 */ 0x00000000 /* 23:2 e*RW DMA End (Odd)
365 static u_char saa7196_i2c_default[NUM_SAA7196_I2C_REGS] = {
366 /* SAA7196 I2C bus control */
368 /* 00 */ 0x50, /* 7:0 Increment Delay */
369 /* 01 */ 0x30, /* 7:0 Horizontal Sync Begin for 50hz */
370 /* 02 */ 0x00, /* 7:0 Horizontal Sync Stop for 50hz */
371 /* 03 */ 0xe8, /* 7:0 Horizontal Sync Clamp Start for 50hz */
372 /* 04 */ 0xb6, /* 7:0 Horizontal Sync Clamp Stop for 50hz */
373 /* 05 */ 0xf4, /* 7:0 Horizontal Sync Start after PH1 for 50hz */
374 /* 06 */ 0x46, /* 7 Input mode =0 CVBS, =1 S-Video
376 5:4 Aperture Bandpass characteristics
377 3:2 Coring range for high freq
378 1:0 Aperture bandpass filter weights */
379 /* 07 */ 0x00, /* 7:0 Hue */
380 /* 08 */ 0x7f, /* 7:3 Colour-killer threshold QAM (PAL, NTSC) */
381 /* 09 */ 0x7f, /* 7:3 Colour-killer threshold SECAM */
382 /* 0a */ 0x7f, /* 7:0 PAL switch sensitivity */
383 /* 0b */ 0x7f, /* 7:0 SECAM switch sensitivity */
384 /* 0c */ 0x40, /* 7 Colour-on bit
386 /* 0d */ 0x84, /* 7 VTR/TV mode bit = 1->VTR mode
387 3 Realtime output mode select bit
388 2 HREF position select
391 /* 0e */ 0x38, /* 7 Horizontal clock PLL
392 5 Select interal/external clock source
393 4 Output enable of Horizontal/Vertical sync
394 3 Data output YUV enable
398 /* 0f */ 0x50, /* 7 Automatic Field detection
399 6 Field Select 0 = 50hz, 1=60hz
400 5 SECAM cross-colour reduction
401 4 Enable sync and clamping pulse
402 3:1 Luminance delay compensation */
403 /* 10 */ 0x00, /* 2 Select HREF Position
404 1:0 Vertical noise reduction */
405 /* 11 */ 0x2c, /* 7:0 Chrominance gain conrtol for QAM */
406 /* 12 */ 0x40, /* 7:0 Chrominance saturation control for VRAM port */
407 /* 13 */ 0x40, /* 7:0 Luminance contract control for VRAM port */
408 /* 14 */ 0x34, /* 7:0 Horizontal sync begin for 60hz */
410 /* 15 */ 0x0c, /* 7:0 Horizontal sync stop for 60hz */
411 /* 16 */ 0xfb, /* 7:0 Horizontal clamp begin for 60hz */
412 /* 17 */ 0xd4, /* 7:0 Horizontal clamp stop for 60hz */
413 /* 18 */ 0xec, /* 7:0 Horizontal sync start after PH1 for 60hz */
415 0x0a, 0xf4, 0xce, 0xf4,
417 /* 19 */ 0x80, /* 7:0 Luminance brightness control for VRAM port */
424 /* 20 */ 0x90, /* 7 ROM table bypass switch
425 6:5 Set output field mode
426 4 VRAM port outputs enable
427 3:2 First pixel position in VRO data
428 1:0 FIFO output register select */
429 /* 21 */ 0x80, /* 7:0 [7:0] Pixel number per line on output */
430 /* 22 */ 0x80, /* 7:0 [7:0] Pixel number per line on input */
431 /* 23 */ 0x03, /* 7:0 [7:0] Horizontal start position of scaling win*/
432 /* 24 */ 0x8a, /* 7:5 Horizontal decimation filter
433 4 [8] Horizontal start position of scaling win
434 3:2 [9:8] Pixel number per line on input
435 1:0 [9:8] Pixel number per line on output */
436 /* 25 */ 0xf0, /* 7:0 [7:0] Line number per output field */
437 /* 26 */ 0xf0, /* 7:0 [7:0] Line number per input field */
438 /* 27 */ 0x0f, /* 7:0 [7:0] Vertical start of scaling window */
439 /* 28 */ 0x80, /* 7 Adaptive filter switch
440 6:5 Vertical luminance data processing
441 4 [8] Vertical start of scaling window
442 3:2 [9:8] Line number per input field
443 1:0 [9:8] Line number per output field */
444 /* 29 */ 0x16, /* 7:0 [7:0] Vertical bypass start */
445 /* 2a */ 0x00, /* 7:0 [7:0] Vertical bypass count */
446 /* 2b */ 0x00, /* 4 [8] Vertical bypass start
447 2 [8] Vertical bypass count
448 0 Polarity, internally detected odd even flag */
449 /* 2c */ 0x80, /* 7:0 Set lower limit V for colour-keying */
450 /* 2d */ 0x7f, /* 7:0 Set upper limit V for colour-keying */
451 /* 2e */ 0x80, /* 7:0 Set lower limit U for colour-keying */
452 /* 2f */ 0x7f, /* 7:0 Set upper limit U for colour-keying */
453 /* 30 */ 0xbf /* 7 VRAM bus output format
454 6 Adaptive geometrical filter
455 5 Luminance limiting value
456 4 Monochrome and two's complement output data sel
457 3 Line quailifier flag
458 2 Pixel qualifier flag
459 1 Transparent data transfer
460 0 Extended formats enable bit */
463 static u_char bt254_default[NUM_BT254_REGS] = {
475 * Returns 0 Succesful completion.
476 * Returns 1 If transfer aborted or timeout occured.
479 static int i2c_print_err = 1;
481 i2c_write(meteor_reg_t * mtr, u_char slave, u_char rw, u_char reg, u_char data)
483 unsigned long wait_counter = 0x0001ffff;
484 mreg_t * iic_write_loc = &mtr->base->i2c_write;
488 /* Write the data the the i2c write register */
489 *iic_write_loc = SAA7116_IIC_NEW_CYCLE |
490 (((u_long)slave|(u_long)rw) << 16) |
491 ((u_long)reg << 8) | (u_long)data;
493 /* Wait until the i2c cycle is compeleted */
494 while((*iic_write_loc & SAA7116_IIC_NEW_CYCLE)) {
495 if(!wait_counter) break;
499 /* 1ffff should be enough delay time for the i2c cycle to complete */
502 printf("meteor%d: %d i2c %s transfer timeout 0x%x",
503 METEOR_NUM(mtr), slave,
504 rw ? "read" : "write", *iic_write_loc);
509 /* Check for error on direct write, clear if any */
510 if(mtr->base->i2c_read & SAA7116_IIC_DIRECT_TRANSFER_ABORTED){
511 mtr->base->i2c_read |= SAA7116_IIC_DIRECT_TRANSFER_ABORTED;
513 printf("meteor%d: 0x%x i2c %s tranfer aborted",
514 METEOR_NUM(mtr), slave,
515 rw ? "read" : "write" );
521 printf(" - reg=0x%x, value=0x%x.\n", reg, data);
529 met_probe (pcici_t tag, pcidi_t type)
532 case SAA7116_PHILIPS_ID: /* meteor */
533 return("Philips SAA 7116");
538 /* interrupt handling routine
539 complete meteor_read() if using interrupts
542 meteor_intr(void *arg)
544 meteor_reg_t *mtr = (meteor_reg_t *) arg;
545 mreg_t *cap = &mtr->base->cap_cntl,
546 *base = &mtr->base->dma1e,
547 *stat = &mtr->base->irq_stat;
548 u_long status = *stat,
549 cap_err = *cap & 0x00000f00,
550 #ifdef METEOR_CHECK_PCI_BUS
551 pci_err = pci_conf_read(mtr->tag,
552 PCI_COMMAND_STATUS_REG),
554 next_base = (u_long)(vtophys(mtr->bigbuf));
557 * Disable future interrupts if a capture mode is not selected.
558 * This can happen when we are in the process of closing or
559 * changing capture modes, otherwise it shouldn't happen.
561 if(!(mtr->flags & METEOR_CAP_MASK)) {
562 *cap &= 0x8ff0; /* disable future interrupts */
564 #ifdef METEOR_CHECK_PCI_BUS
566 * Check for pci bus errors.
568 #define METEOR_MASTER_ABORT 0x20000000
569 #define METEOR_TARGET_ABORT 0x10000000
570 if(pci_err & METEOR_MASTER_ABORT) {
571 printf("meteor%d: intr: pci bus master dma abort: 0x%x 0x%x.\n",
572 METEOR_NUM(mtr), *base, *(base+3));
573 pci_conf_write(mtr->tag, PCI_COMMAND_STATUS_REG, pci_err);
575 if(pci_err & METEOR_TARGET_ABORT) {
576 printf("meteor%d: intr: pci bus target dma abort: 0x%x 0x%x.\n",
577 METEOR_NUM(mtr), *base, *(base+3));
578 pci_conf_write(mtr->tag, PCI_COMMAND_STATUS_REG, pci_err);
585 if (cap_err & 0x300) {
586 if(mtr->fifo_errors % 50 == 0) {
587 printf("meteor%d: capture error", METEOR_NUM(mtr));
588 printf(": %s FIFO overflow.\n",
589 cap_err&0x0100? "even" : "odd");
591 mtr->fifo_errors++ ; /* increment fifo capture errors cnt */
593 if (cap_err & 0xc00) {
594 if(mtr->dma_errors % 50 == 0) {
595 printf("meteor%d: capture error", METEOR_NUM(mtr));
596 printf(": %s DMA address.\n",
597 cap_err&0x0400? "even" : "odd");
599 mtr->dma_errors++ ; /* increment DMA capture errors cnt */
602 *cap |= 0x0f30; /* clear error and field done */
605 * In synchronous capture mode we need to know what the address
606 * offset for the next field/frame will be. next_base holds the
607 * value for the even dma buffers (for odd, one must add stride).
609 if((mtr->flags & METEOR_SYNCAP) && !mtr->synch_wait &&
610 (mtr->current < mtr->frames)) { /* could be !=, but < is safer */
611 /* next_base is initialized to mtr->bigbuf */
612 next_base += mtr->frame_size * mtr->current;
613 if(mtr->flags & METEOR_WANT_TS)
614 next_base += sizeof(struct timeval) * mtr->current;
618 * Count the field and clear the field flag.
620 * In single mode capture, clear the continuous capture mode.
622 * In synchronous capture mode, if we have room for another field,
623 * adjust DMA buffer pointers.
624 * When we are above the hi water mark (hiwat), mtr->synch_wait will
625 * be set and we will not bump the DMA buffer pointers. Thus, once
626 * we reach the hi water mark, the driver acts like a continuous mode
627 * capture on the mtr->current frame until we hit the low water
628 * mark (lowat). The user had the option of stopping or halting
629 * the capture if this is not the desired effect.
631 if (status & 0x1) { /* even field */
632 mtr->even_fields_captured++;
633 mtr->flags &= ~METEOR_WANT_EVEN;
634 if((mtr->flags & METEOR_SYNCAP) && !mtr->synch_wait) {
636 /* XXX should add adjustments for YUV_422 & PLANAR */
639 * If the user requested to be notified via signal,
640 * let them know the field is complete.
642 if(mtr->proc && (mtr->signal & METEOR_SIG_MODE_MASK))
643 psignal(mtr->proc, mtr->signal&(~METEOR_SIG_MODE_MASK));
645 if (status & 0x2) { /* odd field */
646 mtr->odd_fields_captured++;
647 mtr->flags &= ~METEOR_WANT_ODD;
648 if((mtr->flags & METEOR_SYNCAP) && !mtr->synch_wait) {
649 *(base+3) = next_base + *(base+6);
650 /* XXX should add adjustments for YUV_422 & PLANAR */
653 * If the user requested to be notified via signal,
654 * let them know the field is complete.
656 if(mtr->proc && (mtr->signal & METEOR_SIG_MODE_MASK))
657 psignal(mtr->proc, mtr->signal&(~METEOR_SIG_MODE_MASK));
661 * If we have a complete frame.
663 if(!(mtr->flags & METEOR_WANT_MASK)) {
664 mtr->frames_captured++;
666 * post the completion time.
668 if(mtr->flags & METEOR_WANT_TS) {
671 if(mtr->alloc_pages * PAGE_SIZE <= (mtr->frame_size +
672 sizeof(struct timeval))) {
673 ts =(struct timeval *)mtr->bigbuf +
675 /* doesn't work in synch mode except for first frame */
681 * Wake up the user in single capture mode.
683 if(mtr->flags & METEOR_SINGLE)
684 wakeup((caddr_t)mtr);
686 * If the user requested to be notified via signal,
687 * let them know the frame is complete.
689 if(mtr->proc && !(mtr->signal & METEOR_SIG_MODE_MASK))
690 psignal(mtr->proc, mtr->signal&(~METEOR_SIG_MODE_MASK));
692 * Reset the want flags if in continuous or
693 * synchronous capture mode.
695 if(mtr->flags & (METEOR_CONTIN|METEOR_SYNCAP)) {
696 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
697 case METEOR_ONLY_ODD_FIELDS:
698 mtr->flags |= METEOR_WANT_ODD;
700 case METEOR_ONLY_EVEN_FIELDS:
701 mtr->flags |= METEOR_WANT_EVEN;
704 mtr->flags |= METEOR_WANT_MASK;
709 * Special handling for synchronous capture mode.
711 if(mtr->flags & METEOR_SYNCAP) {
712 struct meteor_mem *mm = mtr->mem;
714 * Mark the current frame as active. It is up to
715 * the user to clear this, but we will clear it
716 * for the user for the current frame being captured
717 * if we are within the water marks (see below).
719 mm->active |= 1 << (mtr->current - 1);
722 * Since the user can muck with these values, we need
723 * to check and see if they are sane. If they don't
724 * pass the sanity check, disable the capture mode.
725 * This is rather rude, but then so was the user.
727 * Do we really need all of this or should we just
728 * eliminate the possiblity of allowing the
729 * user to change hi and lo water marks while it
732 if(mm->num_active_bufs < 0 ||
733 mm->num_active_bufs > mtr->frames ||
734 mm->lowat < 1 || mm->lowat >= mtr->frames ||
735 mm->hiwat < 1 || mm->hiwat >= mtr->frames ||
736 mm->lowat > mm->hiwat ) {
738 mtr->flags &= ~(METEOR_SYNCAP|METEOR_WANT_MASK);
741 * Ok, they are sane, now we want to
742 * check the water marks.
744 if(mm->num_active_bufs <= mm->lowat)
746 if(mm->num_active_bufs >= mm->hiwat)
749 * Clear the active frame bit for this frame
750 * and advance the counters if we are within
751 * the banks of the water marks.
753 if(!mtr->synch_wait) {
754 mm->active &= ~(1 << mtr->current);
756 if(mtr->current > mtr->frames)
758 mm->num_active_bufs++;
764 *stat |= 0x7; /* clear interrupt status */
769 set_fps(meteor_reg_t *mtr, u_short fps)
771 struct saa7116_regs *s7116 = mtr->base;
773 unsigned maxfps, mask = 0x1, length = 0;
775 SAA7196_WRITE(mtr, SAA7196_STDC, SAA7196_REG(mtr, SAA7196_STDC) | 0x02);
777 status = (s7116->i2c_read & 0xff000000L) >> 24;
780 * Determine if there is an input signal. Depending on the
781 * frequency we either have a max of 25 fps (50 hz) or 30 fps (60 hz).
782 * If there is no input signal, then we need some defaults. If the
783 * user neglected to specify any defaults, just set to the fps to max.
785 if((status & 0x40) == 0) { /* Is there a signal ? */
787 maxfps = 30; /* 60 hz system */
789 maxfps = 25; /* 50 hz system */
791 } else { /* We have no signal, check defaults */
792 #if METEOR_SYSTEM_DEFAULT == METEOR_PAL || METEOR_SYSTEM_DEFAULT == METEOR_SECAM
794 #elif METEOR_SYSTEM_DEFAULT == METEOR_NTSC
797 /* Don't really know what to do, just set max */
804 * A little sanity checking...
807 if(fps > maxfps) fps = maxfps;
810 * Compute the mask/length using the fps.
815 } else if ((float)fps == maxfps/2.0) {
818 } else if (fps > maxfps/2) {
821 mask = (1<<maxfps) - 1;
823 step = (float)(maxfps - 1)/(float)(maxfps - fps);
824 for(b=step; b < maxfps; b += step) {
825 mask &= ~(1<<((int)b)); /* mask out the bth frame */
827 } else { /* fps < maxfps/2 */
832 step = (float)(maxfps -1)/(float)(fps);
833 for(b = step + 1; b < maxfps - 1; b += step) {
834 mask |= (1<<((int)b)); /* mask in the bth frame */
841 s7116->fme = s7116->fmo = mask;
842 s7116->fml = (length << 16) | length;;
851 * There is also a problem with range checking on the 7116.
852 * It seems to only work for 22 bits, so the max size we can allocate
853 * is 22 bits long or 4194304 bytes assuming that we put the beginning
854 * of the buffer on a 2^24 bit boundary. The range registers will use
855 * the top 8 bits of the dma start registers along with the bottom 22
856 * bits of the range register to determine if we go out of range.
857 * This makes getting memory a real kludge.
860 #define RANGE_BOUNDARY (1<<22)
862 get_meteor_mem(int unit, unsigned size)
864 vm_offset_t addr = 0;
866 addr = vm_page_alloc_contig(size, 0, 0xffffffff, 1<<24);
868 addr = vm_page_alloc_contig(size, 0, 0xffffffff, PAGE_SIZE);
870 printf("meteor%d: Unable to allocate %d bytes of memory.\n",
878 bt254_write(meteor_reg_t *mtr, u_char addr, u_char data)
880 addr &= 0x7; /* sanity? */
881 mtr->bt254_reg[addr] = data;
882 PCF8574_DATA_WRITE(mtr, data); /* set data */
883 PCF8574_CTRL_WRITE(mtr, (PCF8574_CTRL_REG(mtr) & ~0x7) | addr);
884 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) & ~0x10); /* WR/ to 0 */
885 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x10); /* WR to 1 */
886 PCF8574_DATA_WRITE(mtr, 0xff); /* clr data */
891 bt254_init(meteor_reg_t *mtr)
895 PCF8574_CTRL_WRITE(mtr, 0x7f);
896 PCF8574_DATA_WRITE(mtr, 0xff); /* data port must be 0xff */
897 PCF8574_CTRL_WRITE(mtr, 0x7f);
899 /* init RGB module for 24bpp, composite input */
900 for(i=0; i<NUM_BT254_REGS; i++)
901 bt254_write(mtr, i, bt254_default[i]);
903 bt254_write(mtr, BT254_COMMAND, 0x00); /* 24 bpp */
907 bt254_ntsc(meteor_reg_t *mtr, int arg)
911 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x20);
915 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) &= ~0x20);
920 select_bt254(meteor_reg_t *mtr)
922 /* disable saa7196, saaen = 1 */
923 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x80);
924 /* enable Bt254, bten = 0 */
925 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) & ~0x40);
929 select_saa7196(meteor_reg_t *mtr)
931 /* disable Bt254, bten = 1 */
932 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x40);
933 /* enable saa7196, saaen = 0 */
934 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) & ~0x80);
938 * Initialize the 7116, 7196 and the RGB module.
941 meteor_init ( meteor_reg_t *mtr )
947 * Initialize the Philips SAA7116
949 mtr->base->cap_cntl = 0x00000040L;
950 vbase_addr = &mtr->base->dma1e;
951 for (i = 0 ; i < (sizeof(struct saa7116_regs)/sizeof(mreg_t)); i++)
952 *vbase_addr++ = saa7116_pci_default[i];
955 * Check for the Philips SAA7196
958 if(i2c_write(mtr, SAA7196_I2C_ADDR, SAA7116_I2C_WRITE, 0, 0xff) == 0) {
963 for (i = 0; i < NUM_SAA7196_I2C_REGS; i++)
964 SAA7196_WRITE(mtr, i, saa7196_i2c_default[i]);
966 * Get version number.
968 SAA7196_WRITE(mtr, SAA7196_STDC,
969 SAA7196_REG(mtr, SAA7196_STDC) & ~0x02);
971 printf("meteor%d: <Philips SAA 7196> rev 0x%x\n",
973 (unsigned)((mtr->base->i2c_read & 0xff000000L) >> 28));
976 printf("meteor%d: <Philips SAA 7196 NOT FOUND>\n",
980 * Check for RGB module, initialized if found.
983 if(i2c_write(mtr,PCF8574_DATA_I2C_ADDR,SAA7116_I2C_WRITE,0,0xff) == 0) {
985 printf("meteor%d: <Booktree 254 (RGB module)>\n",
986 METEOR_NUM(mtr)); /* does this have a rev #? */
987 bt254_init(mtr); /* Set up RGB module */
988 mtr->flags = METEOR_RGB;
999 met_attach(pcici_t tag, int unit)
1002 u_long old_irq, new_irq;
1003 #endif /* METEOR_IRQ */
1008 if (unit >= NMETEOR) {
1009 printf("meteor%d: attach: only %d units configured.\n",
1011 printf("meteor%d: attach: invalid unit number.\n", unit);
1016 * Check for Meteor/PPB (PCI-PCI Bridge)
1017 * Reprogram IBM Bridge if detected.
1018 * New Meteor cards have an IBM PCI-PCI bridge, creating a secondary
1019 * PCI bus. The SAA chip is connected to this secondary bus.
1022 /* If we are not on PCI Bus 0, check for the Bridge */
1023 if ( pci_get_bus_from_tag( tag ) != 0) {
1026 /* get tag of parent bridge */
1027 bridge_tag = pci_get_parent_from_tag( tag );
1029 /* Look for IBM 82351, 82352 or 82353 */
1030 if (pci_conf_read(bridge_tag, PCI_ID_REG) == 0x00221014) {
1033 printf("meteor%d: PPB device detected, reprogramming IBM bridge.\n", unit);
1036 pci_cfgwrite(bridge_tag, 0x05, 0x00, 1);
1038 pci_cfgwrite(bridge_tag, 0x0d, 0x20, 1);
1039 /* write posting enable, prefetch enabled --> GRAB direction */
1040 pci_cfgwrite(bridge_tag, 0x42, 0x14, 1);
1041 /* set PRTR Primary retry timer register */
1042 pci_cfgwrite(bridge_tag, 0x4c, 0x10, 1);
1046 mtr = &meteor[unit];
1048 pci_map_mem(tag, PCI_MAP_REG_START, (vm_offset_t *)&mtr->base,
1051 #ifdef METEOR_IRQ /* from the configuration file */
1052 old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
1053 pci_conf_write(tag, PCI_INTERRUPT_REG, METEOR_IRQ);
1054 new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
1055 printf("meteor%d: attach: irq changed from %d to %d\n",
1056 unit, (old_irq & 0xff), (new_irq & 0xff));
1057 #endif /* METEOR_IRQ */
1058 /* setup the interrupt handling routine */
1059 pci_map_int(tag, meteor_intr, (void*) mtr, &net_imask);
1062 * PCI latency timer. 32 is a good value for 4 bus mastering slots, if
1063 * you have more than for, then 16 would probably be a better value.
1066 #ifndef METEOR_DEF_LATENCY_VALUE
1067 #define METEOR_DEF_LATENCY_VALUE 32
1069 latency = pci_conf_read(tag, PCI_LATENCY_TIMER);
1070 latency = (latency >> 8) & 0xff;
1073 printf("meteor%d: PCI bus latency is", unit);
1075 printf("meteor%d: PCI bus latency was 0 changing to",
1079 latency = METEOR_DEF_LATENCY_VALUE;
1080 pci_conf_write(tag, PCI_LATENCY_TIMER, latency<<8);
1083 printf(" %lu.\n", latency);
1086 meteor_init(mtr); /* set up saa7116, saa7196, and rgb module */
1089 buf = get_meteor_mem(unit, METEOR_ALLOC);
1093 printf("meteor%d: buffer size %d, addr 0x%llx\n",
1094 unit, METEOR_ALLOC, vtophys(buf));
1098 mtr->alloc_pages = METEOR_ALLOC_PAGES;
1100 bzero((caddr_t) buf, METEOR_ALLOC);
1102 /* 640x480 RGB 16 */
1103 mtr->base->dma1e = buf;
1104 mtr->base->dma1o = buf + 0x500;
1105 mtr->base->dma_end_e =
1106 mtr->base->dma_end_o = buf + METEOR_ALLOC;
1108 /* 1 frame of 640x480 RGB 16 */
1111 mtr->depth = 2; /* two bytes per pixel */
1112 mtr->frames = 1; /* one frame */
1114 mtr->flags |= METEOR_INITALIZED | METEOR_AUTOMODE | METEOR_DEV0 |
1116 cdevsw_add(&meteor_cdevsw, -1, unit);
1117 make_dev(&meteor_cdevsw, unit, 0, 0, 0644, "meteor");
1120 #define UNIT(x) ((x) & 0x07)
1124 meteor_reset(dev_t dev)
1126 int unit = UNIT(minor(dev));
1127 struct saa7116_regs *m;
1132 m = meteor[unit].base;
1135 tsleep((caddr_t)m, METPRI, "Mreset", hz/50);
1137 m->cap_cntl = 0x8ff0;
1138 m->cap_cntl = 0x80c0;
1139 m->cap_cntl = 0x8040;
1140 tsleep((caddr_t)m, METPRI, "Mreset", hz/10);
1141 m->cap_cntl = 0x80c0;
1148 /*---------------------------------------------------------
1150 ** Meteor character device driver routines
1152 **---------------------------------------------------------
1157 meteor_open(dev_t dev, int flags, int fmt, struct thread *td)
1163 unit = UNIT(minor(dev));
1164 if (unit >= NMETEOR) /* unit out of range */
1167 mtr = &(meteor[unit]);
1169 if (!(mtr->flags & METEOR_INITALIZED)) /* device not found */
1172 if (mtr->flags & METEOR_OPEN) /* device is busy */
1175 mtr->flags |= METEOR_OPEN;
1177 * Make sure that the i2c regs are set the same for each open.
1179 for(i=0; i< NUM_SAA7196_I2C_REGS; i++) {
1180 SAA7196_WRITE(mtr, i, saa7196_i2c_default[i]);
1183 mtr->fifo_errors = 0;
1184 mtr->dma_errors = 0;
1185 mtr->frames_captured = 0;
1186 mtr->even_fields_captured = 0;
1187 mtr->odd_fields_captured = 0;
1188 mtr->proc = (struct proc *)0;
1190 #ifdef METEOR_TEST_VIDEO
1191 mtr->video.addr = 0;
1192 mtr->video.width = 0;
1193 mtr->video.banksize = 0;
1194 mtr->video.ramsize = 0;
1201 meteor_close(dev_t dev, int flags, int fmt, struct thread *td)
1205 #ifdef METEOR_DEALLOC_ABOVE
1209 unit = UNIT(minor(dev));
1210 if (unit >= NMETEOR) /* unit out of range */
1213 mtr = &(meteor[unit]);
1214 mtr->flags &= ~METEOR_OPEN;
1216 if(mtr->flags & METEOR_SINGLE)
1217 /* this should not happen, the read capture
1218 should have completed or in the very least
1219 recieved a signal before close is called. */
1220 wakeup((caddr_t)mtr); /* continue read */
1222 * Turn off capture mode.
1224 mtr->base->cap_cntl = 0x8ff0;
1225 mtr->flags &= ~(METEOR_CAP_MASK|METEOR_WANT_MASK);
1226 mtr->proc = (struct proc *)0;
1228 #ifdef METEOR_DEALLOC_PAGES
1229 if (mtr->bigbuf != NULL) {
1230 kmem_free(kernel_map,mtr->bigbuf,(mtr->alloc_pages*PAGE_SIZE));
1232 mtr->alloc_pages = 0;
1235 #ifdef METEOR_DEALLOC_ABOVE
1236 if (mtr->bigbuf != NULL && mtr->alloc_pages > METEOR_DEALLOC_ABOVE) {
1237 temp = METEOR_DEALLOC_ABOVE - mtr->alloc_pages;
1238 kmem_free(kernel_map,
1239 mtr->bigbuf+((mtr->alloc_pages - temp) * PAGE_SIZE),
1240 (temp * PAGE_SIZE));
1241 mtr->alloc_pages = METEOR_DEALLOC_ABOVE;
1250 start_capture(meteor_reg_t *mtr, unsigned type)
1252 mreg_t *cap = &mtr->base->cap_cntl;
1255 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1256 case METEOR_ONLY_EVEN_FIELDS:
1257 mtr->flags |= METEOR_WANT_EVEN;
1258 if(type == METEOR_SINGLE)
1259 *cap = 0x0ff4 | mtr->range_enable;
1261 *cap = 0x0ff1 | mtr->range_enable;
1263 case METEOR_ONLY_ODD_FIELDS:
1264 mtr->flags |= METEOR_WANT_ODD;
1265 if(type == METEOR_SINGLE)
1266 *cap = 0x0ff8 | mtr->range_enable;
1268 *cap = 0x0ff2 | mtr->range_enable;
1271 mtr->flags |= METEOR_WANT_MASK;
1272 if(type == METEOR_SINGLE)
1273 *cap = 0x0ffc | mtr->range_enable;
1275 *cap = 0x0ff3 | mtr->range_enable;
1281 meteor_read(dev_t dev, struct uio *uio, int ioflag)
1288 unit = UNIT(minor(dev));
1289 if (unit >= NMETEOR) /* unit out of range */
1292 mtr = &(meteor[unit]);
1293 if (mtr->bigbuf == 0)/* no frame buffer allocated (ioctl failed) */
1296 if (mtr->flags & METEOR_CAP_MASK)
1297 return(EIO); /* already capturing */
1299 count = mtr->rows * mtr->cols * mtr->depth;
1300 if (uio->uio_iov->iov_len < count)
1304 start_capture(mtr, METEOR_SINGLE);
1306 status=tsleep((caddr_t)mtr, METPRI, "capturing", 0);
1307 if (!status) /* successful capture */
1308 status = uiomove((caddr_t)mtr->bigbuf, count, uio);
1310 printf ("meteor%d: read: tsleep error %d\n", unit, status);
1312 mtr->flags &= ~(METEOR_SINGLE | METEOR_WANT_MASK);
1318 meteor_write(dev_t dev, struct uio *uio, int ioflag)
1324 meteor_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
1330 struct meteor_counts *cnt;
1331 struct meteor_geomet *geo;
1332 struct meteor_mem *mem;
1333 struct meteor_capframe *frame;
1334 #ifdef METEOR_TEST_VIDEO
1335 struct meteor_video *video;
1338 struct saa7116_regs *base;
1342 if (!arg) return(EINVAL);
1343 unit = UNIT(minor(dev));
1344 if (unit >= NMETEOR) /* unit out of range */
1347 mtr = &(meteor[unit]);
1353 mtr->flags |= METEOR_WANT_TS;
1355 mtr->flags &= ~METEOR_WANT_TS;
1358 if(mtr->flags & METEOR_WANT_TS)
1363 #ifdef METEOR_TEST_VIDEO
1365 video = (struct meteor_video *)arg;
1366 video->addr = mtr->video.addr;
1367 video->width = mtr->video.width;
1368 video->banksize = mtr->video.banksize;
1369 video->ramsize = mtr->video.ramsize;
1372 video = (struct meteor_video *)arg;
1373 mtr->video.addr = video->addr;
1374 mtr->video.width = video->width;
1375 mtr->video.banksize = video->banksize;
1376 mtr->video.ramsize = video->ramsize;
1380 set_fps(mtr, *(u_short *)arg);
1383 *(u_short *)arg = mtr->fps;
1386 if (*(int *)arg < 0 || *(int *)arg > _SIG_MAXSIG)
1388 mtr->signal = *(int *) arg;
1390 mtr->proc = td->td_proc; /* might be NULL */
1392 mtr->proc = (struct proc *)0;
1396 *(int *)arg = mtr->signal;
1398 case METEORSTATUS: /* get 7196 status */
1400 SAA7196_WRITE(mtr, SAA7196_STDC,
1401 SAA7196_REG(mtr, SAA7196_STDC) | 0x02);
1403 temp |= (base->i2c_read & 0xff000000L) >> 24;
1404 SAA7196_WRITE(mtr, SAA7196_STDC,
1405 SAA7196_REG(mtr, SAA7196_STDC) & ~0x02);
1407 temp |= (base->i2c_read & 0xff000000L) >> 16;
1408 *(u_short *)arg = temp;
1410 case METEORSHUE: /* set hue */
1411 SAA7196_WRITE(mtr, SAA7196_HUEC, *(char *)arg);
1413 case METEORGHUE: /* get hue */
1414 *(char *)arg = SAA7196_REG(mtr, SAA7196_HUEC);
1416 case METEORSCHCV: /* set chrominance gain */
1417 SAA7196_WRITE(mtr, SAA7196_CGAINR, *(char *)arg);
1419 case METEORGCHCV: /* get chrominance gain */
1420 *(char *)arg = SAA7196_REG(mtr, SAA7196_CGAINR);
1422 case METEORSBRIG: /* set brightness */
1423 SAA7196_WRITE(mtr, SAA7196_BRIG, *(char *)arg);
1425 case METEORGBRIG: /* get brightness */
1426 *(char *)arg = SAA7196_REG(mtr, SAA7196_BRIG);
1428 case METEORSCSAT: /* set chroma saturation */
1429 SAA7196_WRITE(mtr, SAA7196_CSAT, *(char *)arg);
1431 case METEORGCSAT: /* get chroma saturation */
1432 *(char *)arg = SAA7196_REG(mtr, SAA7196_CSAT);
1434 case METEORSCONT: /* set contrast */
1435 SAA7196_WRITE(mtr, SAA7196_CONT, *(char *)arg);
1437 case METEORGCONT: /* get contrast */
1438 *(char *)arg = SAA7196_REG(mtr, SAA7196_CONT);
1441 if((mtr->flags & METEOR_RGB) == 0)
1443 temp = *(unsigned short *)arg;
1444 bt254_write(mtr, temp & 0xf, (temp & 0x0ff0) >> 4);
1447 if((mtr->flags & METEOR_RGB) == 0)
1449 temp = *(unsigned short *)arg & 0x7;
1450 *(unsigned short *)arg = mtr->bt254_reg[temp] << 4 | temp;
1452 case METEORSHWS: /* set horizontal window start */
1453 SAA7196_WRITE(mtr, SAA7196_HWS, *(char *)arg);
1455 case METEORGHWS: /* get horizontal window start */
1456 *(char *)arg = SAA7196_REG(mtr, SAA7196_HWS);
1458 case METEORSVWS: /* set vertical window start */
1459 SAA7196_WRITE(mtr, SAA7196_VWS, *(char *)arg);
1461 case METEORGVWS: /* get vertical window start */
1462 *(char *)arg = SAA7196_REG(mtr, SAA7196_VWS);
1464 case METEORSINPUT: /* set input device */
1465 switch(*(unsigned long *)arg & METEOR_DEV_MASK) {
1466 case 0: /* default */
1467 case METEOR_INPUT_DEV0:
1468 if(mtr->flags & METEOR_RGB)
1469 select_saa7196(mtr);
1470 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1472 SAA7196_WRITE(mtr, 0x0e,
1473 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x0);
1474 SAA7196_WRITE(mtr, 0x06,
1475 (SAA7196_REG(mtr, 0x06) & ~0x80));
1477 case METEOR_INPUT_DEV1:
1478 if(mtr->flags & METEOR_RGB)
1479 select_saa7196(mtr);
1480 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1482 SAA7196_WRITE(mtr, 0x0e,
1483 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x1);
1484 SAA7196_WRITE(mtr, 0x06,
1485 (SAA7196_REG(mtr, 0x06) & ~0x80));
1487 case METEOR_INPUT_DEV2:
1488 if(mtr->flags & METEOR_RGB)
1489 select_saa7196(mtr);
1490 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1492 SAA7196_WRITE(mtr, 0x0e,
1493 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x2);
1494 SAA7196_WRITE(mtr, 0x06,
1495 (SAA7196_REG(mtr, 0x06) & ~0x80));
1497 case METEOR_INPUT_DEV3:
1498 if(mtr->flags & METEOR_RGB)
1499 select_saa7196(mtr);
1500 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1502 SAA7196_WRITE(mtr, 0x0e,
1503 (SAA7196_REG(mtr, 0x0e) | 0x3));
1504 SAA7196_WRITE(mtr, 0x06,
1505 (SAA7196_REG(mtr, 0x06) & ~0x80) );
1507 case METEOR_INPUT_DEV_SVIDEO:
1508 if(mtr->flags & METEOR_RGB)
1509 select_saa7196(mtr);
1510 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1511 | METEOR_DEV_SVIDEO;
1512 SAA7196_WRITE(mtr, 0x0e,
1513 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x2);
1514 SAA7196_WRITE(mtr, 0x06,
1515 (SAA7196_REG(mtr, 0x06) & ~0x80) | 0x80);
1517 case METEOR_INPUT_DEV_RGB:
1518 if((mtr->flags & METEOR_RGB) == 0)
1520 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1522 SAA7196_WRITE(mtr, 0x0e,
1523 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x3);
1524 SAA7196_WRITE(mtr, 0x06,
1525 (SAA7196_REG(mtr, 0x06) & ~0x80));
1527 SAA7196_WRITE(mtr, 0x0e, /* chn 3 for synch */
1528 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x3);
1534 case METEORGINPUT: /* get input device */
1535 *(u_long *)arg = mtr->flags & METEOR_DEV_MASK;
1537 case METEORSFMT: /* set input format */
1538 switch(*(unsigned long *)arg & METEOR_FORM_MASK ) {
1539 case 0: /* default */
1540 case METEOR_FMT_NTSC:
1541 mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1543 SAA7196_WRITE(mtr, SAA7196_STDC,
1544 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01));
1545 SAA7196_WRITE(mtr, 0x0f,
1546 (SAA7196_REG(mtr, 0x0f) & ~0xe0) | 0x40);
1547 SAA7196_WRITE(mtr, 0x22, 0x80);
1548 SAA7196_WRITE(mtr, 0x24,
1549 (SAA7196_REG(mtr, 0x24) & ~0x0c) | 0x08);
1550 SAA7196_WRITE(mtr, 0x26, 0xf0);
1551 SAA7196_WRITE(mtr, 0x28,
1552 (SAA7196_REG(mtr, 0x28) & ~0x0c)) ;
1553 if(mtr->flags & METEOR_RGB){
1557 case METEOR_FMT_PAL:
1558 mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1560 SAA7196_WRITE(mtr, SAA7196_STDC,
1561 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01));
1562 SAA7196_WRITE(mtr, 0x0f,
1563 (SAA7196_REG(mtr, 0x0f) & ~0xe0));
1564 SAA7196_WRITE(mtr, 0x22, 0x00);
1565 SAA7196_WRITE(mtr, 0x24,
1566 (SAA7196_REG(mtr, 0x24) | 0x0c));
1567 SAA7196_WRITE(mtr, 0x26, 0x20);
1568 SAA7196_WRITE(mtr, 0x28,
1569 (SAA7196_REG(mtr, 0x28) & ~0x0c) | 0x04) ;
1570 if(mtr->flags & METEOR_RGB){
1574 case METEOR_FMT_SECAM:
1575 mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1577 SAA7196_WRITE(mtr, SAA7196_STDC,
1578 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01) | 0x1);
1579 SAA7196_WRITE(mtr, 0x0f,
1580 (SAA7196_REG(mtr, 0x0f) & ~0xe0) | 0x20);
1581 SAA7196_WRITE(mtr, 0x22, 0x00);
1582 SAA7196_WRITE(mtr, 0x24,
1583 (SAA7196_REG(mtr, 0x24) | 0x0c));
1584 SAA7196_WRITE(mtr, 0x26, 0x20);
1585 SAA7196_WRITE(mtr, 0x28,
1586 (SAA7196_REG(mtr, 0x28) & ~0x0c) | 0x04) ;
1587 if(mtr->flags & METEOR_RGB){
1591 case METEOR_FMT_AUTOMODE:
1592 mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1594 SAA7196_WRITE(mtr, SAA7196_STDC,
1595 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01));
1596 SAA7196_WRITE(mtr, 0x0f,
1597 (SAA7196_REG(mtr, 0x0f) & ~0xe0) | 0x80);
1603 case METEORGFMT: /* get input format */
1604 *(u_long *)arg = mtr->flags & METEOR_FORM_MASK;
1608 switch (*(int *) arg) {
1609 case METEOR_CAP_SINGLE:
1610 if (mtr->bigbuf==0) /* no frame buffer allocated */
1613 if (temp & METEOR_CAP_MASK)
1614 return(EIO); /* already capturing */
1616 start_capture(mtr, METEOR_SINGLE);
1618 /* wait for capture to complete */
1619 error=tsleep((caddr_t)mtr, METPRI, "capturing", 0);
1621 printf("meteor%d: ioctl: tsleep error %d\n",
1623 mtr->flags &= ~(METEOR_SINGLE|METEOR_WANT_MASK);
1625 case METEOR_CAP_CONTINOUS:
1626 if (mtr->bigbuf==0) /* no frame buffer allocated */
1629 if (temp & METEOR_CAP_MASK)
1630 return(EIO); /* already capturing */
1632 start_capture(mtr, METEOR_CONTIN);
1635 case METEOR_CAP_STOP_CONT:
1636 if (mtr->flags & METEOR_CONTIN) {
1637 /* turn off capture */
1638 base->cap_cntl = 0x8ff0;
1639 mtr->flags &= ~(METEOR_CONTIN|METEOR_WANT_MASK);
1649 frame = (struct meteor_capframe *) arg;
1652 switch (frame->command) {
1653 case METEOR_CAP_N_FRAMES:
1654 if (mtr->flags & METEOR_CAP_MASK)
1656 if (mtr->flags & (METEOR_YUV_PLANAR | METEOR_YUV_422)) /* XXX */
1657 return(EINVAL); /* should fix intr so we allow these */
1658 if (mtr->bigbuf == 0)
1660 if ((mtr->frames < 2) ||
1661 (frame->lowat < 1 || frame->lowat >= mtr->frames) ||
1662 (frame->hiwat < 1 || frame->hiwat >= mtr->frames) ||
1663 (frame->lowat > frame->hiwat))
1665 /* meteor_mem structure is on the page after the data */
1666 mem = mtr->mem = (struct meteor_mem *) (mtr->bigbuf +
1667 (round_page(mtr->frame_size * mtr->frames)));
1669 mtr->synch_wait = 0;
1670 mem->num_bufs = mtr->frames;
1671 mem->frame_size= mtr->frame_size;
1672 /* user and kernel change these */
1673 mem->lowat = frame->lowat;
1674 mem->hiwat = frame->hiwat;
1676 mem->num_active_bufs = 0;
1678 start_capture(mtr, METEOR_SYNCAP);
1680 case METEOR_CAP_STOP_FRAMES:
1681 if (mtr->flags & METEOR_SYNCAP) {
1682 /* turn off capture */
1683 base->cap_cntl = 0x8ff0;
1684 mtr->flags &= ~(METEOR_SYNCAP|METEOR_WANT_MASK);
1687 case METEOR_HALT_N_FRAMES:
1688 if(mtr->flags & METEOR_SYNCAP) {
1689 base->cap_cntl = 0x8ff0;
1690 mtr->flags &= ~(METEOR_WANT_MASK);
1693 case METEOR_CONT_N_FRAMES:
1694 if(!(mtr->flags & METEOR_SYNCAP)) {
1698 start_capture(mtr, METEOR_SYNCAP);
1707 geo = (struct meteor_geomet *) arg;
1709 /* Either even or odd, if even & odd, then these a zero */
1710 if((geo->oformat & METEOR_GEO_ODD_ONLY) &&
1711 (geo->oformat & METEOR_GEO_EVEN_ONLY)) {
1712 printf("meteor%d: ioctl: Geometry odd or even only.\n",
1716 /* set/clear even/odd flags */
1717 if(geo->oformat & METEOR_GEO_ODD_ONLY)
1718 mtr->flags |= METEOR_ONLY_ODD_FIELDS;
1720 mtr->flags &= ~METEOR_ONLY_ODD_FIELDS;
1721 if(geo->oformat & METEOR_GEO_EVEN_ONLY)
1722 mtr->flags |= METEOR_ONLY_EVEN_FIELDS;
1724 mtr->flags &= ~METEOR_ONLY_EVEN_FIELDS;
1726 /* can't change parameters while capturing */
1727 if (mtr->flags & METEOR_CAP_MASK)
1730 if ((geo->columns & 0x3fe) != geo->columns) {
1732 "meteor%d: ioctl: %d: columns too large or not even.\n",
1733 unit, geo->columns);
1736 if (((geo->rows & 0x7fe) != geo->rows) ||
1737 ((geo->oformat & METEOR_GEO_FIELD_MASK) &&
1738 ((geo->rows & 0x3fe) != geo->rows)) ) {
1740 "meteor%d: ioctl: %d: rows too large or not even.\n",
1744 if (geo->frames > 32) {
1745 printf("meteor%d: ioctl: too many frames.\n", unit);
1748 if(error) return error;
1750 if ((temp=geo->rows * geo->columns * geo->frames * 2) != 0) {
1751 if (geo->oformat & METEOR_GEO_RGB24) temp = temp * 2;
1753 /* meteor_mem structure for SYNC Capture */
1754 if (geo->frames > 1) temp += PAGE_SIZE;
1757 if (temp > mtr->alloc_pages
1758 #ifdef METEOR_TEST_VIDEO
1759 && mtr->video.addr == 0
1762 buf = get_meteor_mem(unit, temp*PAGE_SIZE);
1764 kmem_free(kernel_map, mtr->bigbuf,
1765 (mtr->alloc_pages * PAGE_SIZE));
1767 mtr->alloc_pages = temp;
1770 "meteor%d: ioctl: Allocating %d bytes\n",
1771 unit, temp*PAGE_SIZE);
1777 if(error) return error;
1779 mtr->rows = geo->rows;
1780 mtr->cols = geo->columns;
1781 mtr->frames = geo->frames;
1783 #ifdef METEOR_TEST_VIDEO
1785 buf = vtophys(mtr->video.addr);
1788 buf = vtophys(mtr->bigbuf);
1790 /* set defaults and end of buffer locations */
1803 /* set end of DMA location, even/odd */
1805 base->dma_end_o = buf + mtr->alloc_pages * PAGE_SIZE;
1808 * Determine if we can use the hardware range detect.
1810 if(mtr->alloc_pages * PAGE_SIZE < RANGE_BOUNDARY &&
1811 ((buf & 0xff000000) | base->dma_end_e) ==
1812 (buf + mtr->alloc_pages * PAGE_SIZE) )
1813 mtr->range_enable = 0x8000;
1815 mtr->range_enable = 0x0;
1817 base->dma_end_o = 0xffffffff;
1821 switch (geo->oformat & METEOR_GEO_OUTPUT_MASK) {
1822 case 0: /* default */
1823 case METEOR_GEO_RGB16:
1825 mtr->frame_size = mtr->rows * mtr->cols * mtr->depth;
1826 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1827 mtr->flags |= METEOR_RGB16;
1828 temp = mtr->cols * mtr->depth;
1829 /* recal stride and starting point */
1830 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1831 case METEOR_ONLY_ODD_FIELDS:
1833 #ifdef METEOR_TEST_VIDEO
1834 if(mtr->video.addr && mtr->video.width)
1835 base->stride1o = mtr->video.width-temp;
1837 SAA7196_WRITE(mtr, 0x20, 0xd0);
1839 case METEOR_ONLY_EVEN_FIELDS:
1841 #ifdef METEOR_TEST_VIDEO
1842 if(mtr->video.addr && mtr->video.width)
1843 base->stride1e = mtr->video.width-temp;
1845 SAA7196_WRITE(mtr, 0x20, 0xf0);
1847 default: /* interlaced even/odd */
1849 base->dma1o = buf + temp;
1850 base->stride1e = base->stride1o = temp;
1851 #ifdef METEOR_TEST_VIDEO
1852 if(mtr->video.addr && mtr->video.width) {
1853 base->dma1o = buf + mtr->video.width;
1854 base->stride1e = base->stride1o =
1856 temp + mtr->video.width;
1859 SAA7196_WRITE(mtr, 0x20, 0x90);
1862 base->routee = base->routeo = 0xeeeeee01;
1864 case METEOR_GEO_RGB24:
1866 mtr->frame_size = mtr->rows * mtr->cols * mtr->depth;
1867 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1868 mtr->flags |= METEOR_RGB24;
1869 temp = mtr->cols * mtr->depth;
1870 /* recal stride and starting point */
1871 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1872 case METEOR_ONLY_ODD_FIELDS:
1874 #ifdef METEOR_TEST_VIDEO
1875 if(mtr->video.addr && mtr->video.width)
1876 base->stride1o = mtr->video.width-temp;
1878 SAA7196_WRITE(mtr, 0x20, 0xd2);
1880 case METEOR_ONLY_EVEN_FIELDS:
1882 #ifdef METEOR_TEST_VIDEO
1883 if(mtr->video.addr && mtr->video.width)
1884 base->stride1e = mtr->video.width-temp;
1886 SAA7196_WRITE(mtr, 0x20, 0xf2);
1888 default: /* interlaced even/odd */
1890 base->dma1o = buf + mtr->cols * mtr->depth;
1891 base->stride1e = base->stride1o =
1892 mtr->cols * mtr->depth;
1893 #ifdef METEOR_TEST_VIDEO
1894 if(mtr->video.addr && mtr->video.width) {
1895 base->dma1o = buf + mtr->video.width;
1896 base->stride1e = base->stride1o =
1898 temp + mtr->video.width;
1901 SAA7196_WRITE(mtr, 0x20, 0x92);
1904 base->routee= base->routeo= 0x39393900;
1906 case METEOR_GEO_YUV_PLANAR:
1908 temp = mtr->rows * mtr->cols; /* compute frame size */
1909 mtr->frame_size = temp * mtr->depth;
1910 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1911 mtr->flags |= METEOR_YUV_PLANAR;
1912 /* recal stride and starting point */
1913 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1914 case METEOR_ONLY_ODD_FIELDS:
1915 base->dma1o = buf; /* Y Odd */
1916 base->dma2o = buf + temp; /* U Odd */
1918 base->dma3o = base->dma2o + temp; /* V Odd */
1919 SAA7196_WRITE(mtr, 0x20, 0xd1);
1921 case METEOR_ONLY_EVEN_FIELDS:
1922 base->dma1e = buf; /* Y Even */
1923 base->dma2e = buf + temp; /* U Even */
1925 base->dma2e= base->dma2e + temp; /* V Even */
1926 SAA7196_WRITE(mtr, 0x20, 0xf1);
1928 default: /* interlaced even/odd */
1929 base->dma1e = buf; /* Y Even */
1930 base->dma2e = buf + temp; /* U Even */
1932 base->dma3e = base->dma2e + temp; /* V Even */
1933 base->dma1o = base->dma1e+mtr->cols;/* Y Odd */
1934 base->dma2o = base->dma3e + temp; /* U Odd */
1935 base->dma3o = base->dma2o + temp; /* V Odd */
1936 base->stride1e = base->stride1o = mtr->cols;
1937 SAA7196_WRITE(mtr, 0x20, 0x91);
1940 switch (geo->oformat &
1941 (METEOR_GEO_YUV_12 | METEOR_GEO_YUV_9)) {
1942 case METEOR_GEO_YUV_9:
1943 base->routee=base->routeo = 0xaaaaffc3;
1945 case METEOR_GEO_YUV_12:
1946 base->routee=base->routeo = 0xaaaaffc2;
1949 base->routee=base->routeo = 0xaaaaffc1;
1953 case METEOR_GEO_YUV_422:/* same as planer, different uv order */
1955 temp = mtr->rows * mtr->cols; /* compute frame size */
1956 mtr->frame_size = temp * mtr->depth;
1957 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1958 mtr->flags |= METEOR_YUV_422;
1959 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1960 case METEOR_ONLY_ODD_FIELDS:
1962 base->dma2o = buf + temp;
1963 base->dma3o = base->dma2o + (temp >> 1);
1964 SAA7196_WRITE(mtr, 0x20, 0xd1);
1966 case METEOR_ONLY_EVEN_FIELDS:
1968 base->dma2e = buf + temp;
1969 base->dma3e = base->dma2e + (temp >> 1);
1970 SAA7196_WRITE(mtr, 0x20, 0xf1);
1972 default: /* interlaced even/odd */
1973 base->dma1e = buf; /* Y even */
1974 base->dma2e = buf + temp; /* U even */
1976 base->dma2e + (temp >> 1);/* V even */
1977 base->dma1o = base->dma1e+mtr->cols;/* Y odd */
1978 temp = mtr->cols >> 1;
1979 base->dma2o = base->dma2e+temp; /* U odd */
1980 base->dma3o = base->dma3e+temp; /* V odd */
1982 base->stride1o = mtr->cols; /* Y stride */
1984 base->stride2o = temp; /* U stride */
1986 base->stride3o = temp; /* V stride */
1987 SAA7196_WRITE(mtr, 0x20, 0x91);
1990 switch (geo->oformat &
1991 (METEOR_GEO_YUV_12 | METEOR_GEO_YUV_9)) {
1992 case METEOR_GEO_YUV_9:
1993 base->routee=base->routeo = 0xaaaaffc3;
1995 case METEOR_GEO_YUV_12:
1996 base->routee=base->routeo = 0xaaaaffc2;
1999 base->routee=base->routeo = 0xaaaaffc1;
2003 case METEOR_GEO_YUV_PACKED:
2005 mtr->frame_size = mtr->rows * mtr->cols * mtr->depth;
2006 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
2007 mtr->flags |= METEOR_YUV_PACKED;
2008 /* recal stride and odd starting point */
2009 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
2010 case METEOR_ONLY_ODD_FIELDS:
2012 SAA7196_WRITE(mtr, 0x20, 0xd1);
2014 case METEOR_ONLY_EVEN_FIELDS:
2016 SAA7196_WRITE(mtr, 0x20, 0xf1);
2018 default: /* interlaced even/odd */
2020 base->dma1o = buf + mtr->cols * mtr->depth;
2021 base->stride1e = base->stride1o =
2022 mtr->cols * mtr->depth;
2023 SAA7196_WRITE(mtr, 0x20, 0x91);
2026 base->routee = base->routeo = 0xeeeeee41;
2029 error = EINVAL; /* invalid argument */
2030 printf("meteor%d: ioctl: invalid output format\n",unit);
2034 SAA7196_WRITE(mtr, 0x21, mtr->cols & 0xff);
2035 SAA7196_WRITE(mtr, 0x24,
2036 ((SAA7196_REG(mtr, 0x24) & ~0x03) |
2037 ((mtr->cols >> 8) & 0x03)));
2039 if(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
2040 SAA7196_WRITE(mtr, 0x25, ((mtr->rows) & 0xff));
2041 SAA7196_WRITE(mtr, 0x28,
2042 ((SAA7196_REG(mtr, 0x28) & ~0x03) |
2043 ((mtr->rows >> 8) & 0x03)));
2044 } else { /* Interlaced */
2045 SAA7196_WRITE(mtr, 0x25, ((mtr->rows >> 1) & 0xff));
2046 SAA7196_WRITE(mtr, 0x28,
2047 ((SAA7196_REG(mtr, 0x28) & ~0x03) |
2048 ((mtr->rows >> 9) & 0x03)));
2050 /* set signed/unsigned chrominance */
2051 SAA7196_WRITE(mtr, 0x30, (SAA7196_REG(mtr, 0x30) & ~0x10) |
2052 ((geo->oformat&METEOR_GEO_UNSIGNED)?0:0x10));
2055 geo = (struct meteor_geomet *) arg;
2056 geo->rows = mtr->rows;
2057 geo->columns = mtr->cols;
2058 geo->frames = mtr->frames;
2059 geo->oformat = (mtr->flags & METEOR_OUTPUT_FMT_MASK) |
2060 (mtr->flags & METEOR_ONLY_FIELDS_MASK) |
2061 (SAA7196_REG(mtr, 0x30) & 0x10 ?
2062 0:METEOR_GEO_UNSIGNED);
2063 switch(base->routee & 0xff) {
2065 geo->oformat |= METEOR_GEO_YUV_9;
2068 geo->oformat |= METEOR_GEO_YUV_12;
2074 case METEORSCOUNT: /* (re)set error counts */
2075 cnt = (struct meteor_counts *) arg;
2076 mtr->fifo_errors = cnt->fifo_errors;
2077 mtr->dma_errors = cnt->dma_errors;
2078 mtr->frames_captured = cnt->frames_captured;
2079 mtr->even_fields_captured = cnt->even_fields_captured;
2080 mtr->odd_fields_captured = cnt->odd_fields_captured;
2082 case METEORGCOUNT: /* get error counts */
2083 cnt = (struct meteor_counts *) arg;
2084 cnt->fifo_errors = mtr->fifo_errors;
2085 cnt->dma_errors = mtr->dma_errors;
2086 cnt->frames_captured = mtr->frames_captured;
2087 cnt->even_fields_captured = mtr->even_fields_captured;
2088 cnt->odd_fields_captured = mtr->odd_fields_captured;
2091 printf("meteor%d: ioctl: invalid ioctl request\n", unit);
2099 meteor_mmap(dev_t dev, vm_offset_t offset, int nprot)
2105 unit = UNIT(minor(dev));
2106 if (unit >= NMETEOR) /* at this point could this happen? */
2109 mtr = &(meteor[unit]);
2112 if(nprot & PROT_EXEC)
2115 if(offset >= mtr->alloc_pages * PAGE_SIZE)
2118 return i386_btop(vtophys(mtr->bigbuf) + offset);