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.10 2004/02/24 19:35:30 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 <machine/ioctl_meteor.h>
172 #include "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)
534 cdevsw_add(&meteor_cdevsw);
537 case SAA7116_PHILIPS_ID: /* meteor */
538 return("Philips SAA 7116");
543 /* interrupt handling routine
544 complete meteor_read() if using interrupts
547 meteor_intr(void *arg)
549 meteor_reg_t *mtr = (meteor_reg_t *) arg;
550 mreg_t *cap = &mtr->base->cap_cntl,
551 *base = &mtr->base->dma1e,
552 *stat = &mtr->base->irq_stat;
553 u_long status = *stat,
554 cap_err = *cap & 0x00000f00,
555 #ifdef METEOR_CHECK_PCI_BUS
556 pci_err = pci_conf_read(mtr->tag,
557 PCI_COMMAND_STATUS_REG),
559 next_base = (u_long)(vtophys(mtr->bigbuf));
562 * Disable future interrupts if a capture mode is not selected.
563 * This can happen when we are in the process of closing or
564 * changing capture modes, otherwise it shouldn't happen.
566 if(!(mtr->flags & METEOR_CAP_MASK)) {
567 *cap &= 0x8ff0; /* disable future interrupts */
569 #ifdef METEOR_CHECK_PCI_BUS
571 * Check for pci bus errors.
573 #define METEOR_MASTER_ABORT 0x20000000
574 #define METEOR_TARGET_ABORT 0x10000000
575 if(pci_err & METEOR_MASTER_ABORT) {
576 printf("meteor%d: intr: pci bus master 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);
580 if(pci_err & METEOR_TARGET_ABORT) {
581 printf("meteor%d: intr: pci bus target dma abort: 0x%x 0x%x.\n",
582 METEOR_NUM(mtr), *base, *(base+3));
583 pci_conf_write(mtr->tag, PCI_COMMAND_STATUS_REG, pci_err);
590 if (cap_err & 0x300) {
591 if(mtr->fifo_errors % 50 == 0) {
592 printf("meteor%d: capture error", METEOR_NUM(mtr));
593 printf(": %s FIFO overflow.\n",
594 cap_err&0x0100? "even" : "odd");
596 mtr->fifo_errors++ ; /* increment fifo capture errors cnt */
598 if (cap_err & 0xc00) {
599 if(mtr->dma_errors % 50 == 0) {
600 printf("meteor%d: capture error", METEOR_NUM(mtr));
601 printf(": %s DMA address.\n",
602 cap_err&0x0400? "even" : "odd");
604 mtr->dma_errors++ ; /* increment DMA capture errors cnt */
607 *cap |= 0x0f30; /* clear error and field done */
610 * In synchronous capture mode we need to know what the address
611 * offset for the next field/frame will be. next_base holds the
612 * value for the even dma buffers (for odd, one must add stride).
614 if((mtr->flags & METEOR_SYNCAP) && !mtr->synch_wait &&
615 (mtr->current < mtr->frames)) { /* could be !=, but < is safer */
616 /* next_base is initialized to mtr->bigbuf */
617 next_base += mtr->frame_size * mtr->current;
618 if(mtr->flags & METEOR_WANT_TS)
619 next_base += sizeof(struct timeval) * mtr->current;
623 * Count the field and clear the field flag.
625 * In single mode capture, clear the continuous capture mode.
627 * In synchronous capture mode, if we have room for another field,
628 * adjust DMA buffer pointers.
629 * When we are above the hi water mark (hiwat), mtr->synch_wait will
630 * be set and we will not bump the DMA buffer pointers. Thus, once
631 * we reach the hi water mark, the driver acts like a continuous mode
632 * capture on the mtr->current frame until we hit the low water
633 * mark (lowat). The user had the option of stopping or halting
634 * the capture if this is not the desired effect.
636 if (status & 0x1) { /* even field */
637 mtr->even_fields_captured++;
638 mtr->flags &= ~METEOR_WANT_EVEN;
639 if((mtr->flags & METEOR_SYNCAP) && !mtr->synch_wait) {
641 /* XXX should add adjustments for YUV_422 & PLANAR */
644 * If the user requested to be notified via signal,
645 * let them know the field is complete.
647 if(mtr->proc && (mtr->signal & METEOR_SIG_MODE_MASK))
648 psignal(mtr->proc, mtr->signal&(~METEOR_SIG_MODE_MASK));
650 if (status & 0x2) { /* odd field */
651 mtr->odd_fields_captured++;
652 mtr->flags &= ~METEOR_WANT_ODD;
653 if((mtr->flags & METEOR_SYNCAP) && !mtr->synch_wait) {
654 *(base+3) = next_base + *(base+6);
655 /* XXX should add adjustments for YUV_422 & PLANAR */
658 * If the user requested to be notified via signal,
659 * let them know the field is complete.
661 if(mtr->proc && (mtr->signal & METEOR_SIG_MODE_MASK))
662 psignal(mtr->proc, mtr->signal&(~METEOR_SIG_MODE_MASK));
666 * If we have a complete frame.
668 if(!(mtr->flags & METEOR_WANT_MASK)) {
669 mtr->frames_captured++;
671 * post the completion time.
673 if(mtr->flags & METEOR_WANT_TS) {
676 if(mtr->alloc_pages * PAGE_SIZE <= (mtr->frame_size +
677 sizeof(struct timeval))) {
678 ts =(struct timeval *)mtr->bigbuf +
680 /* doesn't work in synch mode except for first frame */
686 * Wake up the user in single capture mode.
688 if(mtr->flags & METEOR_SINGLE)
689 wakeup((caddr_t)mtr);
691 * If the user requested to be notified via signal,
692 * let them know the frame is complete.
694 if(mtr->proc && !(mtr->signal & METEOR_SIG_MODE_MASK))
695 psignal(mtr->proc, mtr->signal&(~METEOR_SIG_MODE_MASK));
697 * Reset the want flags if in continuous or
698 * synchronous capture mode.
700 if(mtr->flags & (METEOR_CONTIN|METEOR_SYNCAP)) {
701 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
702 case METEOR_ONLY_ODD_FIELDS:
703 mtr->flags |= METEOR_WANT_ODD;
705 case METEOR_ONLY_EVEN_FIELDS:
706 mtr->flags |= METEOR_WANT_EVEN;
709 mtr->flags |= METEOR_WANT_MASK;
714 * Special handling for synchronous capture mode.
716 if(mtr->flags & METEOR_SYNCAP) {
717 struct meteor_mem *mm = mtr->mem;
719 * Mark the current frame as active. It is up to
720 * the user to clear this, but we will clear it
721 * for the user for the current frame being captured
722 * if we are within the water marks (see below).
724 mm->active |= 1 << (mtr->current - 1);
727 * Since the user can muck with these values, we need
728 * to check and see if they are sane. If they don't
729 * pass the sanity check, disable the capture mode.
730 * This is rather rude, but then so was the user.
732 * Do we really need all of this or should we just
733 * eliminate the possiblity of allowing the
734 * user to change hi and lo water marks while it
737 if(mm->num_active_bufs < 0 ||
738 mm->num_active_bufs > mtr->frames ||
739 mm->lowat < 1 || mm->lowat >= mtr->frames ||
740 mm->hiwat < 1 || mm->hiwat >= mtr->frames ||
741 mm->lowat > mm->hiwat ) {
743 mtr->flags &= ~(METEOR_SYNCAP|METEOR_WANT_MASK);
746 * Ok, they are sane, now we want to
747 * check the water marks.
749 if(mm->num_active_bufs <= mm->lowat)
751 if(mm->num_active_bufs >= mm->hiwat)
754 * Clear the active frame bit for this frame
755 * and advance the counters if we are within
756 * the banks of the water marks.
758 if(!mtr->synch_wait) {
759 mm->active &= ~(1 << mtr->current);
761 if(mtr->current > mtr->frames)
763 mm->num_active_bufs++;
769 *stat |= 0x7; /* clear interrupt status */
774 set_fps(meteor_reg_t *mtr, u_short fps)
776 struct saa7116_regs *s7116 = mtr->base;
778 unsigned maxfps, mask = 0x1, length = 0;
780 SAA7196_WRITE(mtr, SAA7196_STDC, SAA7196_REG(mtr, SAA7196_STDC) | 0x02);
782 status = (s7116->i2c_read & 0xff000000L) >> 24;
785 * Determine if there is an input signal. Depending on the
786 * frequency we either have a max of 25 fps (50 hz) or 30 fps (60 hz).
787 * If there is no input signal, then we need some defaults. If the
788 * user neglected to specify any defaults, just set to the fps to max.
790 if((status & 0x40) == 0) { /* Is there a signal ? */
792 maxfps = 30; /* 60 hz system */
794 maxfps = 25; /* 50 hz system */
796 } else { /* We have no signal, check defaults */
797 #if METEOR_SYSTEM_DEFAULT == METEOR_PAL || METEOR_SYSTEM_DEFAULT == METEOR_SECAM
799 #elif METEOR_SYSTEM_DEFAULT == METEOR_NTSC
802 /* Don't really know what to do, just set max */
809 * A little sanity checking...
812 if(fps > maxfps) fps = maxfps;
815 * Compute the mask/length using the fps.
820 } else if ((float)fps == maxfps/2.0) {
823 } else if (fps > maxfps/2) {
826 mask = (1<<maxfps) - 1;
828 step = (float)(maxfps - 1)/(float)(maxfps - fps);
829 for(b=step; b < maxfps; b += step) {
830 mask &= ~(1<<((int)b)); /* mask out the bth frame */
832 } else { /* fps < maxfps/2 */
837 step = (float)(maxfps -1)/(float)(fps);
838 for(b = step + 1; b < maxfps - 1; b += step) {
839 mask |= (1<<((int)b)); /* mask in the bth frame */
846 s7116->fme = s7116->fmo = mask;
847 s7116->fml = (length << 16) | length;;
856 * There is also a problem with range checking on the 7116.
857 * It seems to only work for 22 bits, so the max size we can allocate
858 * is 22 bits long or 4194304 bytes assuming that we put the beginning
859 * of the buffer on a 2^24 bit boundary. The range registers will use
860 * the top 8 bits of the dma start registers along with the bottom 22
861 * bits of the range register to determine if we go out of range.
862 * This makes getting memory a real kludge.
865 #define RANGE_BOUNDARY (1<<22)
867 get_meteor_mem(int unit, unsigned size)
869 vm_offset_t addr = 0;
871 addr = vm_page_alloc_contig(size, 0, 0xffffffff, 1<<24);
873 addr = vm_page_alloc_contig(size, 0, 0xffffffff, PAGE_SIZE);
875 printf("meteor%d: Unable to allocate %d bytes of memory.\n",
883 bt254_write(meteor_reg_t *mtr, u_char addr, u_char data)
885 addr &= 0x7; /* sanity? */
886 mtr->bt254_reg[addr] = data;
887 PCF8574_DATA_WRITE(mtr, data); /* set data */
888 PCF8574_CTRL_WRITE(mtr, (PCF8574_CTRL_REG(mtr) & ~0x7) | addr);
889 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) & ~0x10); /* WR/ to 0 */
890 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x10); /* WR to 1 */
891 PCF8574_DATA_WRITE(mtr, 0xff); /* clr data */
896 bt254_init(meteor_reg_t *mtr)
900 PCF8574_CTRL_WRITE(mtr, 0x7f);
901 PCF8574_DATA_WRITE(mtr, 0xff); /* data port must be 0xff */
902 PCF8574_CTRL_WRITE(mtr, 0x7f);
904 /* init RGB module for 24bpp, composite input */
905 for(i=0; i<NUM_BT254_REGS; i++)
906 bt254_write(mtr, i, bt254_default[i]);
908 bt254_write(mtr, BT254_COMMAND, 0x00); /* 24 bpp */
912 bt254_ntsc(meteor_reg_t *mtr, int arg)
916 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x20);
920 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) &= ~0x20);
925 select_bt254(meteor_reg_t *mtr)
927 /* disable saa7196, saaen = 1 */
928 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x80);
929 /* enable Bt254, bten = 0 */
930 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) & ~0x40);
934 select_saa7196(meteor_reg_t *mtr)
936 /* disable Bt254, bten = 1 */
937 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x40);
938 /* enable saa7196, saaen = 0 */
939 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) & ~0x80);
943 * Initialize the 7116, 7196 and the RGB module.
946 meteor_init ( meteor_reg_t *mtr )
952 * Initialize the Philips SAA7116
954 mtr->base->cap_cntl = 0x00000040L;
955 vbase_addr = &mtr->base->dma1e;
956 for (i = 0 ; i < (sizeof(struct saa7116_regs)/sizeof(mreg_t)); i++)
957 *vbase_addr++ = saa7116_pci_default[i];
960 * Check for the Philips SAA7196
963 if(i2c_write(mtr, SAA7196_I2C_ADDR, SAA7116_I2C_WRITE, 0, 0xff) == 0) {
968 for (i = 0; i < NUM_SAA7196_I2C_REGS; i++)
969 SAA7196_WRITE(mtr, i, saa7196_i2c_default[i]);
971 * Get version number.
973 SAA7196_WRITE(mtr, SAA7196_STDC,
974 SAA7196_REG(mtr, SAA7196_STDC) & ~0x02);
976 printf("meteor%d: <Philips SAA 7196> rev 0x%x\n",
978 (unsigned)((mtr->base->i2c_read & 0xff000000L) >> 28));
981 printf("meteor%d: <Philips SAA 7196 NOT FOUND>\n",
985 * Check for RGB module, initialized if found.
988 if(i2c_write(mtr,PCF8574_DATA_I2C_ADDR,SAA7116_I2C_WRITE,0,0xff) == 0) {
990 printf("meteor%d: <Booktree 254 (RGB module)>\n",
991 METEOR_NUM(mtr)); /* does this have a rev #? */
992 bt254_init(mtr); /* Set up RGB module */
993 mtr->flags = METEOR_RGB;
1004 met_attach(pcici_t tag, int unit)
1007 u_long old_irq, new_irq;
1013 if (unit >= NMETEOR) {
1014 printf("meteor%d: attach: only %d units configured.\n",
1016 printf("meteor%d: attach: invalid unit number.\n", unit);
1021 * Check for Meteor/PPB (PCI-PCI Bridge)
1022 * Reprogram IBM Bridge if detected.
1023 * New Meteor cards have an IBM PCI-PCI bridge, creating a secondary
1024 * PCI bus. The SAA chip is connected to this secondary bus.
1027 /* If we are not on PCI Bus 0, check for the Bridge */
1028 if ( pci_get_bus_from_tag( tag ) != 0) {
1031 /* get tag of parent bridge */
1032 bridge_tag = pci_get_parent_from_tag( tag );
1034 /* Look for IBM 82351, 82352 or 82353 */
1035 if (pci_conf_read(bridge_tag, PCI_ID_REG) == 0x00221014) {
1038 printf("meteor%d: PPB device detected, reprogramming IBM bridge.\n", unit);
1041 pci_cfgwrite(bridge_tag, 0x05, 0x00, 1);
1043 pci_cfgwrite(bridge_tag, 0x0d, 0x20, 1);
1044 /* write posting enable, prefetch enabled --> GRAB direction */
1045 pci_cfgwrite(bridge_tag, 0x42, 0x14, 1);
1046 /* set PRTR Primary retry timer register */
1047 pci_cfgwrite(bridge_tag, 0x4c, 0x10, 1);
1051 mtr = &meteor[unit];
1053 pci_map_mem(tag, PCI_MAP_REG_START, (vm_offset_t *)&mtr->base,
1056 #ifdef METEOR_IRQ /* from the configuration file */
1057 old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
1058 pci_conf_write(tag, PCI_INTERRUPT_REG, METEOR_IRQ);
1059 new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
1060 printf("meteor%d: attach: irq changed from %d to %d\n",
1061 unit, (old_irq & 0xff), (new_irq & 0xff));
1063 /* setup the interrupt handling routine */
1064 pci_map_int(tag, meteor_intr, (void*) mtr, &net_imask);
1067 * PCI latency timer. 32 is a good value for 4 bus mastering slots, if
1068 * you have more than for, then 16 would probably be a better value.
1071 #ifndef METEOR_DEF_LATENCY_VALUE
1072 #define METEOR_DEF_LATENCY_VALUE 32
1074 latency = pci_conf_read(tag, PCI_LATENCY_TIMER);
1075 latency = (latency >> 8) & 0xff;
1078 printf("meteor%d: PCI bus latency is", unit);
1080 printf("meteor%d: PCI bus latency was 0 changing to",
1084 latency = METEOR_DEF_LATENCY_VALUE;
1085 pci_conf_write(tag, PCI_LATENCY_TIMER, latency<<8);
1088 printf(" %lu.\n", latency);
1091 meteor_init(mtr); /* set up saa7116, saa7196, and rgb module */
1094 buf = get_meteor_mem(unit, METEOR_ALLOC);
1098 printf("meteor%d: buffer size %d, addr 0x%llx\n",
1099 unit, METEOR_ALLOC, vtophys(buf));
1103 mtr->alloc_pages = METEOR_ALLOC_PAGES;
1105 bzero((caddr_t) buf, METEOR_ALLOC);
1107 /* 640x480 RGB 16 */
1108 mtr->base->dma1e = buf;
1109 mtr->base->dma1o = buf + 0x500;
1110 mtr->base->dma_end_e =
1111 mtr->base->dma_end_o = buf + METEOR_ALLOC;
1113 /* 1 frame of 640x480 RGB 16 */
1116 mtr->depth = 2; /* two bytes per pixel */
1117 mtr->frames = 1; /* one frame */
1119 mtr->flags |= METEOR_INITALIZED | METEOR_AUTOMODE | METEOR_DEV0 |
1121 make_dev(&meteor_cdevsw, unit, 0, 0, 0644, "meteor");
1124 #define UNIT(x) ((x) & 0x07)
1128 meteor_reset(dev_t dev)
1130 int unit = UNIT(minor(dev));
1131 struct saa7116_regs *m;
1136 m = meteor[unit].base;
1139 tsleep((caddr_t)m, METPRI, "Mreset", hz/50);
1141 m->cap_cntl = 0x8ff0;
1142 m->cap_cntl = 0x80c0;
1143 m->cap_cntl = 0x8040;
1144 tsleep((caddr_t)m, METPRI, "Mreset", hz/10);
1145 m->cap_cntl = 0x80c0;
1152 /*---------------------------------------------------------
1154 ** Meteor character device driver routines
1156 **---------------------------------------------------------
1161 meteor_open(dev_t dev, int flags, int fmt, struct thread *td)
1167 unit = UNIT(minor(dev));
1168 if (unit >= NMETEOR) /* unit out of range */
1171 mtr = &(meteor[unit]);
1173 if (!(mtr->flags & METEOR_INITALIZED)) /* device not found */
1176 if (mtr->flags & METEOR_OPEN) /* device is busy */
1179 mtr->flags |= METEOR_OPEN;
1181 * Make sure that the i2c regs are set the same for each open.
1183 for(i=0; i< NUM_SAA7196_I2C_REGS; i++) {
1184 SAA7196_WRITE(mtr, i, saa7196_i2c_default[i]);
1187 mtr->fifo_errors = 0;
1188 mtr->dma_errors = 0;
1189 mtr->frames_captured = 0;
1190 mtr->even_fields_captured = 0;
1191 mtr->odd_fields_captured = 0;
1192 mtr->proc = (struct proc *)0;
1194 #ifdef METEOR_TEST_VIDEO
1195 mtr->video.addr = 0;
1196 mtr->video.width = 0;
1197 mtr->video.banksize = 0;
1198 mtr->video.ramsize = 0;
1205 meteor_close(dev_t dev, int flags, int fmt, struct thread *td)
1209 #ifdef METEOR_DEALLOC_ABOVE
1213 unit = UNIT(minor(dev));
1214 if (unit >= NMETEOR) /* unit out of range */
1217 mtr = &(meteor[unit]);
1218 mtr->flags &= ~METEOR_OPEN;
1220 if(mtr->flags & METEOR_SINGLE)
1221 /* this should not happen, the read capture
1222 should have completed or in the very least
1223 recieved a signal before close is called. */
1224 wakeup((caddr_t)mtr); /* continue read */
1226 * Turn off capture mode.
1228 mtr->base->cap_cntl = 0x8ff0;
1229 mtr->flags &= ~(METEOR_CAP_MASK|METEOR_WANT_MASK);
1230 mtr->proc = (struct proc *)0;
1232 #ifdef METEOR_DEALLOC_PAGES
1233 if (mtr->bigbuf != NULL) {
1234 kmem_free(kernel_map,mtr->bigbuf,(mtr->alloc_pages*PAGE_SIZE));
1236 mtr->alloc_pages = 0;
1239 #ifdef METEOR_DEALLOC_ABOVE
1240 if (mtr->bigbuf != NULL && mtr->alloc_pages > METEOR_DEALLOC_ABOVE) {
1241 temp = METEOR_DEALLOC_ABOVE - mtr->alloc_pages;
1242 kmem_free(kernel_map,
1243 mtr->bigbuf+((mtr->alloc_pages - temp) * PAGE_SIZE),
1244 (temp * PAGE_SIZE));
1245 mtr->alloc_pages = METEOR_DEALLOC_ABOVE;
1254 start_capture(meteor_reg_t *mtr, unsigned type)
1256 mreg_t *cap = &mtr->base->cap_cntl;
1259 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1260 case METEOR_ONLY_EVEN_FIELDS:
1261 mtr->flags |= METEOR_WANT_EVEN;
1262 if(type == METEOR_SINGLE)
1263 *cap = 0x0ff4 | mtr->range_enable;
1265 *cap = 0x0ff1 | mtr->range_enable;
1267 case METEOR_ONLY_ODD_FIELDS:
1268 mtr->flags |= METEOR_WANT_ODD;
1269 if(type == METEOR_SINGLE)
1270 *cap = 0x0ff8 | mtr->range_enable;
1272 *cap = 0x0ff2 | mtr->range_enable;
1275 mtr->flags |= METEOR_WANT_MASK;
1276 if(type == METEOR_SINGLE)
1277 *cap = 0x0ffc | mtr->range_enable;
1279 *cap = 0x0ff3 | mtr->range_enable;
1285 meteor_read(dev_t dev, struct uio *uio, int ioflag)
1292 unit = UNIT(minor(dev));
1293 if (unit >= NMETEOR) /* unit out of range */
1296 mtr = &(meteor[unit]);
1297 if (mtr->bigbuf == 0)/* no frame buffer allocated (ioctl failed) */
1300 if (mtr->flags & METEOR_CAP_MASK)
1301 return(EIO); /* already capturing */
1303 count = mtr->rows * mtr->cols * mtr->depth;
1304 if (uio->uio_iov->iov_len < count)
1308 start_capture(mtr, METEOR_SINGLE);
1310 status=tsleep((caddr_t)mtr, METPRI, "capturing", 0);
1311 if (!status) /* successful capture */
1312 status = uiomove((caddr_t)mtr->bigbuf, count, uio);
1314 printf ("meteor%d: read: tsleep error %d\n", unit, status);
1316 mtr->flags &= ~(METEOR_SINGLE | METEOR_WANT_MASK);
1322 meteor_write(dev_t dev, struct uio *uio, int ioflag)
1328 meteor_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
1334 struct meteor_counts *cnt;
1335 struct meteor_geomet *geo;
1336 struct meteor_mem *mem;
1337 struct meteor_capframe *frame;
1338 #ifdef METEOR_TEST_VIDEO
1339 struct meteor_video *video;
1342 struct saa7116_regs *base;
1346 if (!arg) return(EINVAL);
1347 unit = UNIT(minor(dev));
1348 if (unit >= NMETEOR) /* unit out of range */
1351 mtr = &(meteor[unit]);
1357 mtr->flags |= METEOR_WANT_TS;
1359 mtr->flags &= ~METEOR_WANT_TS;
1362 if(mtr->flags & METEOR_WANT_TS)
1367 #ifdef METEOR_TEST_VIDEO
1369 video = (struct meteor_video *)arg;
1370 video->addr = mtr->video.addr;
1371 video->width = mtr->video.width;
1372 video->banksize = mtr->video.banksize;
1373 video->ramsize = mtr->video.ramsize;
1376 video = (struct meteor_video *)arg;
1377 mtr->video.addr = video->addr;
1378 mtr->video.width = video->width;
1379 mtr->video.banksize = video->banksize;
1380 mtr->video.ramsize = video->ramsize;
1384 set_fps(mtr, *(u_short *)arg);
1387 *(u_short *)arg = mtr->fps;
1390 if (*(int *)arg < 0 || *(int *)arg > _SIG_MAXSIG)
1392 mtr->signal = *(int *) arg;
1394 mtr->proc = td->td_proc; /* might be NULL */
1396 mtr->proc = (struct proc *)0;
1400 *(int *)arg = mtr->signal;
1402 case METEORSTATUS: /* get 7196 status */
1404 SAA7196_WRITE(mtr, SAA7196_STDC,
1405 SAA7196_REG(mtr, SAA7196_STDC) | 0x02);
1407 temp |= (base->i2c_read & 0xff000000L) >> 24;
1408 SAA7196_WRITE(mtr, SAA7196_STDC,
1409 SAA7196_REG(mtr, SAA7196_STDC) & ~0x02);
1411 temp |= (base->i2c_read & 0xff000000L) >> 16;
1412 *(u_short *)arg = temp;
1414 case METEORSHUE: /* set hue */
1415 SAA7196_WRITE(mtr, SAA7196_HUEC, *(char *)arg);
1417 case METEORGHUE: /* get hue */
1418 *(char *)arg = SAA7196_REG(mtr, SAA7196_HUEC);
1420 case METEORSCHCV: /* set chrominance gain */
1421 SAA7196_WRITE(mtr, SAA7196_CGAINR, *(char *)arg);
1423 case METEORGCHCV: /* get chrominance gain */
1424 *(char *)arg = SAA7196_REG(mtr, SAA7196_CGAINR);
1426 case METEORSBRIG: /* set brightness */
1427 SAA7196_WRITE(mtr, SAA7196_BRIG, *(char *)arg);
1429 case METEORGBRIG: /* get brightness */
1430 *(char *)arg = SAA7196_REG(mtr, SAA7196_BRIG);
1432 case METEORSCSAT: /* set chroma saturation */
1433 SAA7196_WRITE(mtr, SAA7196_CSAT, *(char *)arg);
1435 case METEORGCSAT: /* get chroma saturation */
1436 *(char *)arg = SAA7196_REG(mtr, SAA7196_CSAT);
1438 case METEORSCONT: /* set contrast */
1439 SAA7196_WRITE(mtr, SAA7196_CONT, *(char *)arg);
1441 case METEORGCONT: /* get contrast */
1442 *(char *)arg = SAA7196_REG(mtr, SAA7196_CONT);
1445 if((mtr->flags & METEOR_RGB) == 0)
1447 temp = *(unsigned short *)arg;
1448 bt254_write(mtr, temp & 0xf, (temp & 0x0ff0) >> 4);
1451 if((mtr->flags & METEOR_RGB) == 0)
1453 temp = *(unsigned short *)arg & 0x7;
1454 *(unsigned short *)arg = mtr->bt254_reg[temp] << 4 | temp;
1456 case METEORSHWS: /* set horizontal window start */
1457 SAA7196_WRITE(mtr, SAA7196_HWS, *(char *)arg);
1459 case METEORGHWS: /* get horizontal window start */
1460 *(char *)arg = SAA7196_REG(mtr, SAA7196_HWS);
1462 case METEORSVWS: /* set vertical window start */
1463 SAA7196_WRITE(mtr, SAA7196_VWS, *(char *)arg);
1465 case METEORGVWS: /* get vertical window start */
1466 *(char *)arg = SAA7196_REG(mtr, SAA7196_VWS);
1468 case METEORSINPUT: /* set input device */
1469 switch(*(unsigned long *)arg & METEOR_DEV_MASK) {
1470 case 0: /* default */
1471 case METEOR_INPUT_DEV0:
1472 if(mtr->flags & METEOR_RGB)
1473 select_saa7196(mtr);
1474 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1476 SAA7196_WRITE(mtr, 0x0e,
1477 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x0);
1478 SAA7196_WRITE(mtr, 0x06,
1479 (SAA7196_REG(mtr, 0x06) & ~0x80));
1481 case METEOR_INPUT_DEV1:
1482 if(mtr->flags & METEOR_RGB)
1483 select_saa7196(mtr);
1484 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1486 SAA7196_WRITE(mtr, 0x0e,
1487 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x1);
1488 SAA7196_WRITE(mtr, 0x06,
1489 (SAA7196_REG(mtr, 0x06) & ~0x80));
1491 case METEOR_INPUT_DEV2:
1492 if(mtr->flags & METEOR_RGB)
1493 select_saa7196(mtr);
1494 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1496 SAA7196_WRITE(mtr, 0x0e,
1497 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x2);
1498 SAA7196_WRITE(mtr, 0x06,
1499 (SAA7196_REG(mtr, 0x06) & ~0x80));
1501 case METEOR_INPUT_DEV3:
1502 if(mtr->flags & METEOR_RGB)
1503 select_saa7196(mtr);
1504 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1506 SAA7196_WRITE(mtr, 0x0e,
1507 (SAA7196_REG(mtr, 0x0e) | 0x3));
1508 SAA7196_WRITE(mtr, 0x06,
1509 (SAA7196_REG(mtr, 0x06) & ~0x80) );
1511 case METEOR_INPUT_DEV_SVIDEO:
1512 if(mtr->flags & METEOR_RGB)
1513 select_saa7196(mtr);
1514 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1515 | METEOR_DEV_SVIDEO;
1516 SAA7196_WRITE(mtr, 0x0e,
1517 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x2);
1518 SAA7196_WRITE(mtr, 0x06,
1519 (SAA7196_REG(mtr, 0x06) & ~0x80) | 0x80);
1521 case METEOR_INPUT_DEV_RGB:
1522 if((mtr->flags & METEOR_RGB) == 0)
1524 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1526 SAA7196_WRITE(mtr, 0x0e,
1527 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x3);
1528 SAA7196_WRITE(mtr, 0x06,
1529 (SAA7196_REG(mtr, 0x06) & ~0x80));
1531 SAA7196_WRITE(mtr, 0x0e, /* chn 3 for synch */
1532 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x3);
1538 case METEORGINPUT: /* get input device */
1539 *(u_long *)arg = mtr->flags & METEOR_DEV_MASK;
1541 case METEORSFMT: /* set input format */
1542 switch(*(unsigned long *)arg & METEOR_FORM_MASK ) {
1543 case 0: /* default */
1544 case METEOR_FMT_NTSC:
1545 mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1547 SAA7196_WRITE(mtr, SAA7196_STDC,
1548 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01));
1549 SAA7196_WRITE(mtr, 0x0f,
1550 (SAA7196_REG(mtr, 0x0f) & ~0xe0) | 0x40);
1551 SAA7196_WRITE(mtr, 0x22, 0x80);
1552 SAA7196_WRITE(mtr, 0x24,
1553 (SAA7196_REG(mtr, 0x24) & ~0x0c) | 0x08);
1554 SAA7196_WRITE(mtr, 0x26, 0xf0);
1555 SAA7196_WRITE(mtr, 0x28,
1556 (SAA7196_REG(mtr, 0x28) & ~0x0c)) ;
1557 if(mtr->flags & METEOR_RGB){
1561 case METEOR_FMT_PAL:
1562 mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1564 SAA7196_WRITE(mtr, SAA7196_STDC,
1565 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01));
1566 SAA7196_WRITE(mtr, 0x0f,
1567 (SAA7196_REG(mtr, 0x0f) & ~0xe0));
1568 SAA7196_WRITE(mtr, 0x22, 0x00);
1569 SAA7196_WRITE(mtr, 0x24,
1570 (SAA7196_REG(mtr, 0x24) | 0x0c));
1571 SAA7196_WRITE(mtr, 0x26, 0x20);
1572 SAA7196_WRITE(mtr, 0x28,
1573 (SAA7196_REG(mtr, 0x28) & ~0x0c) | 0x04) ;
1574 if(mtr->flags & METEOR_RGB){
1578 case METEOR_FMT_SECAM:
1579 mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1581 SAA7196_WRITE(mtr, SAA7196_STDC,
1582 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01) | 0x1);
1583 SAA7196_WRITE(mtr, 0x0f,
1584 (SAA7196_REG(mtr, 0x0f) & ~0xe0) | 0x20);
1585 SAA7196_WRITE(mtr, 0x22, 0x00);
1586 SAA7196_WRITE(mtr, 0x24,
1587 (SAA7196_REG(mtr, 0x24) | 0x0c));
1588 SAA7196_WRITE(mtr, 0x26, 0x20);
1589 SAA7196_WRITE(mtr, 0x28,
1590 (SAA7196_REG(mtr, 0x28) & ~0x0c) | 0x04) ;
1591 if(mtr->flags & METEOR_RGB){
1595 case METEOR_FMT_AUTOMODE:
1596 mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1598 SAA7196_WRITE(mtr, SAA7196_STDC,
1599 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01));
1600 SAA7196_WRITE(mtr, 0x0f,
1601 (SAA7196_REG(mtr, 0x0f) & ~0xe0) | 0x80);
1607 case METEORGFMT: /* get input format */
1608 *(u_long *)arg = mtr->flags & METEOR_FORM_MASK;
1612 switch (*(int *) arg) {
1613 case METEOR_CAP_SINGLE:
1614 if (mtr->bigbuf==0) /* no frame buffer allocated */
1617 if (temp & METEOR_CAP_MASK)
1618 return(EIO); /* already capturing */
1620 start_capture(mtr, METEOR_SINGLE);
1622 /* wait for capture to complete */
1623 error=tsleep((caddr_t)mtr, METPRI, "capturing", 0);
1625 printf("meteor%d: ioctl: tsleep error %d\n",
1627 mtr->flags &= ~(METEOR_SINGLE|METEOR_WANT_MASK);
1629 case METEOR_CAP_CONTINOUS:
1630 if (mtr->bigbuf==0) /* no frame buffer allocated */
1633 if (temp & METEOR_CAP_MASK)
1634 return(EIO); /* already capturing */
1636 start_capture(mtr, METEOR_CONTIN);
1639 case METEOR_CAP_STOP_CONT:
1640 if (mtr->flags & METEOR_CONTIN) {
1641 /* turn off capture */
1642 base->cap_cntl = 0x8ff0;
1643 mtr->flags &= ~(METEOR_CONTIN|METEOR_WANT_MASK);
1653 frame = (struct meteor_capframe *) arg;
1656 switch (frame->command) {
1657 case METEOR_CAP_N_FRAMES:
1658 if (mtr->flags & METEOR_CAP_MASK)
1660 if (mtr->flags & (METEOR_YUV_PLANAR | METEOR_YUV_422)) /* XXX */
1661 return(EINVAL); /* should fix intr so we allow these */
1662 if (mtr->bigbuf == 0)
1664 if ((mtr->frames < 2) ||
1665 (frame->lowat < 1 || frame->lowat >= mtr->frames) ||
1666 (frame->hiwat < 1 || frame->hiwat >= mtr->frames) ||
1667 (frame->lowat > frame->hiwat))
1669 /* meteor_mem structure is on the page after the data */
1670 mem = mtr->mem = (struct meteor_mem *) (mtr->bigbuf +
1671 (round_page(mtr->frame_size * mtr->frames)));
1673 mtr->synch_wait = 0;
1674 mem->num_bufs = mtr->frames;
1675 mem->frame_size= mtr->frame_size;
1676 /* user and kernel change these */
1677 mem->lowat = frame->lowat;
1678 mem->hiwat = frame->hiwat;
1680 mem->num_active_bufs = 0;
1682 start_capture(mtr, METEOR_SYNCAP);
1684 case METEOR_CAP_STOP_FRAMES:
1685 if (mtr->flags & METEOR_SYNCAP) {
1686 /* turn off capture */
1687 base->cap_cntl = 0x8ff0;
1688 mtr->flags &= ~(METEOR_SYNCAP|METEOR_WANT_MASK);
1691 case METEOR_HALT_N_FRAMES:
1692 if(mtr->flags & METEOR_SYNCAP) {
1693 base->cap_cntl = 0x8ff0;
1694 mtr->flags &= ~(METEOR_WANT_MASK);
1697 case METEOR_CONT_N_FRAMES:
1698 if(!(mtr->flags & METEOR_SYNCAP)) {
1702 start_capture(mtr, METEOR_SYNCAP);
1711 geo = (struct meteor_geomet *) arg;
1713 /* Either even or odd, if even & odd, then these a zero */
1714 if((geo->oformat & METEOR_GEO_ODD_ONLY) &&
1715 (geo->oformat & METEOR_GEO_EVEN_ONLY)) {
1716 printf("meteor%d: ioctl: Geometry odd or even only.\n",
1720 /* set/clear even/odd flags */
1721 if(geo->oformat & METEOR_GEO_ODD_ONLY)
1722 mtr->flags |= METEOR_ONLY_ODD_FIELDS;
1724 mtr->flags &= ~METEOR_ONLY_ODD_FIELDS;
1725 if(geo->oformat & METEOR_GEO_EVEN_ONLY)
1726 mtr->flags |= METEOR_ONLY_EVEN_FIELDS;
1728 mtr->flags &= ~METEOR_ONLY_EVEN_FIELDS;
1730 /* can't change parameters while capturing */
1731 if (mtr->flags & METEOR_CAP_MASK)
1734 if ((geo->columns & 0x3fe) != geo->columns) {
1736 "meteor%d: ioctl: %d: columns too large or not even.\n",
1737 unit, geo->columns);
1740 if (((geo->rows & 0x7fe) != geo->rows) ||
1741 ((geo->oformat & METEOR_GEO_FIELD_MASK) &&
1742 ((geo->rows & 0x3fe) != geo->rows)) ) {
1744 "meteor%d: ioctl: %d: rows too large or not even.\n",
1748 if (geo->frames > 32) {
1749 printf("meteor%d: ioctl: too many frames.\n", unit);
1752 if(error) return error;
1754 if ((temp=geo->rows * geo->columns * geo->frames * 2) != 0) {
1755 if (geo->oformat & METEOR_GEO_RGB24) temp = temp * 2;
1757 /* meteor_mem structure for SYNC Capture */
1758 if (geo->frames > 1) temp += PAGE_SIZE;
1761 if (temp > mtr->alloc_pages
1762 #ifdef METEOR_TEST_VIDEO
1763 && mtr->video.addr == 0
1766 buf = get_meteor_mem(unit, temp*PAGE_SIZE);
1768 kmem_free(kernel_map, mtr->bigbuf,
1769 (mtr->alloc_pages * PAGE_SIZE));
1771 mtr->alloc_pages = temp;
1774 "meteor%d: ioctl: Allocating %d bytes\n",
1775 unit, temp*PAGE_SIZE);
1781 if(error) return error;
1783 mtr->rows = geo->rows;
1784 mtr->cols = geo->columns;
1785 mtr->frames = geo->frames;
1787 #ifdef METEOR_TEST_VIDEO
1789 buf = vtophys(mtr->video.addr);
1792 buf = vtophys(mtr->bigbuf);
1794 /* set defaults and end of buffer locations */
1807 /* set end of DMA location, even/odd */
1809 base->dma_end_o = buf + mtr->alloc_pages * PAGE_SIZE;
1812 * Determine if we can use the hardware range detect.
1814 if(mtr->alloc_pages * PAGE_SIZE < RANGE_BOUNDARY &&
1815 ((buf & 0xff000000) | base->dma_end_e) ==
1816 (buf + mtr->alloc_pages * PAGE_SIZE) )
1817 mtr->range_enable = 0x8000;
1819 mtr->range_enable = 0x0;
1821 base->dma_end_o = 0xffffffff;
1825 switch (geo->oformat & METEOR_GEO_OUTPUT_MASK) {
1826 case 0: /* default */
1827 case METEOR_GEO_RGB16:
1829 mtr->frame_size = mtr->rows * mtr->cols * mtr->depth;
1830 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1831 mtr->flags |= METEOR_RGB16;
1832 temp = mtr->cols * mtr->depth;
1833 /* recal stride and starting point */
1834 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1835 case METEOR_ONLY_ODD_FIELDS:
1837 #ifdef METEOR_TEST_VIDEO
1838 if(mtr->video.addr && mtr->video.width)
1839 base->stride1o = mtr->video.width-temp;
1841 SAA7196_WRITE(mtr, 0x20, 0xd0);
1843 case METEOR_ONLY_EVEN_FIELDS:
1845 #ifdef METEOR_TEST_VIDEO
1846 if(mtr->video.addr && mtr->video.width)
1847 base->stride1e = mtr->video.width-temp;
1849 SAA7196_WRITE(mtr, 0x20, 0xf0);
1851 default: /* interlaced even/odd */
1853 base->dma1o = buf + temp;
1854 base->stride1e = base->stride1o = temp;
1855 #ifdef METEOR_TEST_VIDEO
1856 if(mtr->video.addr && mtr->video.width) {
1857 base->dma1o = buf + mtr->video.width;
1858 base->stride1e = base->stride1o =
1860 temp + mtr->video.width;
1863 SAA7196_WRITE(mtr, 0x20, 0x90);
1866 base->routee = base->routeo = 0xeeeeee01;
1868 case METEOR_GEO_RGB24:
1870 mtr->frame_size = mtr->rows * mtr->cols * mtr->depth;
1871 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1872 mtr->flags |= METEOR_RGB24;
1873 temp = mtr->cols * mtr->depth;
1874 /* recal stride and starting point */
1875 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1876 case METEOR_ONLY_ODD_FIELDS:
1878 #ifdef METEOR_TEST_VIDEO
1879 if(mtr->video.addr && mtr->video.width)
1880 base->stride1o = mtr->video.width-temp;
1882 SAA7196_WRITE(mtr, 0x20, 0xd2);
1884 case METEOR_ONLY_EVEN_FIELDS:
1886 #ifdef METEOR_TEST_VIDEO
1887 if(mtr->video.addr && mtr->video.width)
1888 base->stride1e = mtr->video.width-temp;
1890 SAA7196_WRITE(mtr, 0x20, 0xf2);
1892 default: /* interlaced even/odd */
1894 base->dma1o = buf + mtr->cols * mtr->depth;
1895 base->stride1e = base->stride1o =
1896 mtr->cols * mtr->depth;
1897 #ifdef METEOR_TEST_VIDEO
1898 if(mtr->video.addr && mtr->video.width) {
1899 base->dma1o = buf + mtr->video.width;
1900 base->stride1e = base->stride1o =
1902 temp + mtr->video.width;
1905 SAA7196_WRITE(mtr, 0x20, 0x92);
1908 base->routee= base->routeo= 0x39393900;
1910 case METEOR_GEO_YUV_PLANAR:
1912 temp = mtr->rows * mtr->cols; /* compute frame size */
1913 mtr->frame_size = temp * mtr->depth;
1914 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1915 mtr->flags |= METEOR_YUV_PLANAR;
1916 /* recal stride and starting point */
1917 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1918 case METEOR_ONLY_ODD_FIELDS:
1919 base->dma1o = buf; /* Y Odd */
1920 base->dma2o = buf + temp; /* U Odd */
1922 base->dma3o = base->dma2o + temp; /* V Odd */
1923 SAA7196_WRITE(mtr, 0x20, 0xd1);
1925 case METEOR_ONLY_EVEN_FIELDS:
1926 base->dma1e = buf; /* Y Even */
1927 base->dma2e = buf + temp; /* U Even */
1929 base->dma2e= base->dma2e + temp; /* V Even */
1930 SAA7196_WRITE(mtr, 0x20, 0xf1);
1932 default: /* interlaced even/odd */
1933 base->dma1e = buf; /* Y Even */
1934 base->dma2e = buf + temp; /* U Even */
1936 base->dma3e = base->dma2e + temp; /* V Even */
1937 base->dma1o = base->dma1e+mtr->cols;/* Y Odd */
1938 base->dma2o = base->dma3e + temp; /* U Odd */
1939 base->dma3o = base->dma2o + temp; /* V Odd */
1940 base->stride1e = base->stride1o = mtr->cols;
1941 SAA7196_WRITE(mtr, 0x20, 0x91);
1944 switch (geo->oformat &
1945 (METEOR_GEO_YUV_12 | METEOR_GEO_YUV_9)) {
1946 case METEOR_GEO_YUV_9:
1947 base->routee=base->routeo = 0xaaaaffc3;
1949 case METEOR_GEO_YUV_12:
1950 base->routee=base->routeo = 0xaaaaffc2;
1953 base->routee=base->routeo = 0xaaaaffc1;
1957 case METEOR_GEO_YUV_422:/* same as planer, different uv order */
1959 temp = mtr->rows * mtr->cols; /* compute frame size */
1960 mtr->frame_size = temp * mtr->depth;
1961 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1962 mtr->flags |= METEOR_YUV_422;
1963 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1964 case METEOR_ONLY_ODD_FIELDS:
1966 base->dma2o = buf + temp;
1967 base->dma3o = base->dma2o + (temp >> 1);
1968 SAA7196_WRITE(mtr, 0x20, 0xd1);
1970 case METEOR_ONLY_EVEN_FIELDS:
1972 base->dma2e = buf + temp;
1973 base->dma3e = base->dma2e + (temp >> 1);
1974 SAA7196_WRITE(mtr, 0x20, 0xf1);
1976 default: /* interlaced even/odd */
1977 base->dma1e = buf; /* Y even */
1978 base->dma2e = buf + temp; /* U even */
1980 base->dma2e + (temp >> 1);/* V even */
1981 base->dma1o = base->dma1e+mtr->cols;/* Y odd */
1982 temp = mtr->cols >> 1;
1983 base->dma2o = base->dma2e+temp; /* U odd */
1984 base->dma3o = base->dma3e+temp; /* V odd */
1986 base->stride1o = mtr->cols; /* Y stride */
1988 base->stride2o = temp; /* U stride */
1990 base->stride3o = temp; /* V stride */
1991 SAA7196_WRITE(mtr, 0x20, 0x91);
1994 switch (geo->oformat &
1995 (METEOR_GEO_YUV_12 | METEOR_GEO_YUV_9)) {
1996 case METEOR_GEO_YUV_9:
1997 base->routee=base->routeo = 0xaaaaffc3;
1999 case METEOR_GEO_YUV_12:
2000 base->routee=base->routeo = 0xaaaaffc2;
2003 base->routee=base->routeo = 0xaaaaffc1;
2007 case METEOR_GEO_YUV_PACKED:
2009 mtr->frame_size = mtr->rows * mtr->cols * mtr->depth;
2010 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
2011 mtr->flags |= METEOR_YUV_PACKED;
2012 /* recal stride and odd starting point */
2013 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
2014 case METEOR_ONLY_ODD_FIELDS:
2016 SAA7196_WRITE(mtr, 0x20, 0xd1);
2018 case METEOR_ONLY_EVEN_FIELDS:
2020 SAA7196_WRITE(mtr, 0x20, 0xf1);
2022 default: /* interlaced even/odd */
2024 base->dma1o = buf + mtr->cols * mtr->depth;
2025 base->stride1e = base->stride1o =
2026 mtr->cols * mtr->depth;
2027 SAA7196_WRITE(mtr, 0x20, 0x91);
2030 base->routee = base->routeo = 0xeeeeee41;
2033 error = EINVAL; /* invalid argument */
2034 printf("meteor%d: ioctl: invalid output format\n",unit);
2038 SAA7196_WRITE(mtr, 0x21, mtr->cols & 0xff);
2039 SAA7196_WRITE(mtr, 0x24,
2040 ((SAA7196_REG(mtr, 0x24) & ~0x03) |
2041 ((mtr->cols >> 8) & 0x03)));
2043 if(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
2044 SAA7196_WRITE(mtr, 0x25, ((mtr->rows) & 0xff));
2045 SAA7196_WRITE(mtr, 0x28,
2046 ((SAA7196_REG(mtr, 0x28) & ~0x03) |
2047 ((mtr->rows >> 8) & 0x03)));
2048 } else { /* Interlaced */
2049 SAA7196_WRITE(mtr, 0x25, ((mtr->rows >> 1) & 0xff));
2050 SAA7196_WRITE(mtr, 0x28,
2051 ((SAA7196_REG(mtr, 0x28) & ~0x03) |
2052 ((mtr->rows >> 9) & 0x03)));
2054 /* set signed/unsigned chrominance */
2055 SAA7196_WRITE(mtr, 0x30, (SAA7196_REG(mtr, 0x30) & ~0x10) |
2056 ((geo->oformat&METEOR_GEO_UNSIGNED)?0:0x10));
2059 geo = (struct meteor_geomet *) arg;
2060 geo->rows = mtr->rows;
2061 geo->columns = mtr->cols;
2062 geo->frames = mtr->frames;
2063 geo->oformat = (mtr->flags & METEOR_OUTPUT_FMT_MASK) |
2064 (mtr->flags & METEOR_ONLY_FIELDS_MASK) |
2065 (SAA7196_REG(mtr, 0x30) & 0x10 ?
2066 0:METEOR_GEO_UNSIGNED);
2067 switch(base->routee & 0xff) {
2069 geo->oformat |= METEOR_GEO_YUV_9;
2072 geo->oformat |= METEOR_GEO_YUV_12;
2078 case METEORSCOUNT: /* (re)set error counts */
2079 cnt = (struct meteor_counts *) arg;
2080 mtr->fifo_errors = cnt->fifo_errors;
2081 mtr->dma_errors = cnt->dma_errors;
2082 mtr->frames_captured = cnt->frames_captured;
2083 mtr->even_fields_captured = cnt->even_fields_captured;
2084 mtr->odd_fields_captured = cnt->odd_fields_captured;
2086 case METEORGCOUNT: /* get error counts */
2087 cnt = (struct meteor_counts *) arg;
2088 cnt->fifo_errors = mtr->fifo_errors;
2089 cnt->dma_errors = mtr->dma_errors;
2090 cnt->frames_captured = mtr->frames_captured;
2091 cnt->even_fields_captured = mtr->even_fields_captured;
2092 cnt->odd_fields_captured = mtr->odd_fields_captured;
2095 printf("meteor%d: ioctl: invalid ioctl request\n", unit);
2103 meteor_mmap(dev_t dev, vm_offset_t offset, int nprot)
2109 unit = UNIT(minor(dev));
2110 if (unit >= NMETEOR) /* at this point could this happen? */
2113 mtr = &(meteor[unit]);
2116 if(nprot & PROT_EXEC)
2119 if(offset >= mtr->alloc_pages * PAGE_SIZE)
2122 return i386_btop(vtophys(mtr->bigbuf) + offset);