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.4 2003/07/21 05:50:46 dillon Exp $
37 8/23/95 On advice from Stefan Esser, added volatile to PCI
38 memory pointers to remove PCI caching .
39 8/29/95 Fixes suggested by Bruce Evans.
40 meteor_mmap should return -1 on error rather than 0.
41 unit # > NMETEOR should be unit # >= NMETEOR.
42 10/24/95 Turn 50 Hz processing for SECAM and 60 Hz processing
44 11/11/95 Change UV from always begin signed to ioctl selected
45 to either signed or unsigned.
46 12/07/95 Changed 7196 startup codes for 50 Hz as recommended
47 by Luigi Rizzo (luigi@iet.unipi.it)
48 12/08/95 Clear SECAM bit in PAL/NTSC and set input field count
49 bits for 50 Hz mode (PAL/SECAM) before I was setting the
50 output count bits. by Luigi Rizzo (luigi@iet.unipi.it)
51 12/18/95 Correct odd DMA field (never exceed, but good for safety
52 Changed 7196 startup codes for 50 Hz as recommended
53 by Luigi Rizzo (luigi@iet.unipi.it)
54 12/19/95 Changed field toggle mode to enable (offset 0x3c)
55 recommended by luigi@iet.unipi.it
56 Added in prototyping, include file, staticizing,
57 and DEVFS changes from FreeBSD team.
58 Changed the default allocated pages from 151 (NTSC)
60 Cleaned up some old comments in iic_write().
61 Added a Field (even or odd) only capture mode to
62 eliminate the high frequency problems with compression
63 algorithms. Recommended by luigi@iet.unipi.it.
64 Changed geometry ioctl so if it couldn't allocated a
65 large enough contiguous space, it wouldn't free the
67 Added new mode called YUV_422 which delivers the
68 data in planer Y followed by U followed by V. This
69 differs from the standard YUV_PACKED mode in that
70 the chrominance (UV) data is in the correct (different)
71 order. This is for programs like vic and mpeg_encode
72 so they don't have to reorder the chrominance data.
73 Added field count to stats.
74 Increment frame count stat if capturing continuous on
76 Added my email address to these comments
77 (james@cs.uwm.edu) suggested by (luigi@iet.unipt.it :-).
78 Changed the user mode signal mechanism to allow the
79 user program to be interrupted at the end of a frame
80 in any one of the modes. Added SSIGNAL ioctl.
81 Added a SFPS/GFPS ioctl so one may set the frames per
82 second that the card catpures. This code needs to be
84 Changed the interrupt routine so synchronous capture
85 will work on fields or frames and the starting frame
86 can be either even or odd.
87 Added HALT_N_FRAMES and CONT_N_FRAMES so one could
88 stop and continue synchronous capture mode.
89 Change the tsleep/wakeup function to wait on mtr
90 rather than &read_intr_wait.
91 1/22/96 Add option (METEOR_FreeBSD_210) for FreeBSD 2.1
93 Changed intr so it only printed errors every 50 times.
94 Added unit number to error messages.
95 Added get_meteor_mem and enabled range checking.
96 1/30/96 Added prelim test stuff for direct video dma transfers
97 from Amancio Hasty (hasty@rah.star-gate.com). Until
98 we get some stuff sorted out, this will be ifdef'ed
99 with METEOR_DIRECT_VIDEO. This is very dangerous to
100 use at present since we don't check the address that
101 is passed by the user!!!!!
102 2/26/96 Added special SVIDEO input device type.
103 2/27/96 Added meteor_reg.h file and associate types Converted
104 meteor.c over to using meteor.h file. Prompted by
105 Lars Jonas Olsson <ljo@po.cwru.edu>.
106 2/28/96 Added meteor RGB code from Lars Jonas Olsson
107 <ljo@po.cwru.edu>. I make some mods to this code, so
108 I hope it still works as I don't have an rgb card to
110 2/29/96 <ljo@po.cwru.edu> tested the meteor RGB and supplied
111 me with diffs. Thanks, we now have a working RGB
112 version of the driver. Still need to clean up this
114 3/1/96 Fixed a nasty little bug that was clearing the VTR
115 mode bit when the 7196 status was requested.
116 3/15/96 Fixed bug introduced in previous version that
117 stopped the only fields mode from working.
118 Added METEOR{GS}TS ioctl, still needs work.
119 3/25/96 Added YUV_9 and YUV_12 modes. Cleaned up some of the
120 code and converted variables to use the new register
122 4/8/96 Fixed the a bug in with the range enable. Pointed
124 5/13/96 Fix the FPS ioctl so it actually sets the frames
125 per second. Code supplied by ian@robots.ox.ac.uk.
126 The new code implements a new define:
127 METEOR_SYSTEM_DEFAULT which should be defined as
128 METEOR_PAL, METEOR_SECAM, or METEOR_NTSC in your system
129 configuration file. If METEOR_SYSTEM_DEFAULT isn't
130 defined, and there is not a signal when set_fps is
131 called, then the call has no effect.
132 Changed the spelling of PLANER to PLANAR as pointed
133 out by Paco Hope <paco@cs.virigina.edu> and define
134 PLANER to be PLANAR for backward compatibility.
135 5/28/95 METEOR_INPUT_DEV_RCA -> METEOR_INPUT_DEV0, not
136 METEOR_GEO_DEV0. Pointed out by Ian Reid,
137 <ian@robots.ox.ac.uk>.
138 METEOR_DEV_MASK should be 0x0000f000 and not
139 0x2000f000, otherwise METEOR_RGB gets masked
140 out. Pointed out by Ian Reid.
141 Changed the fps code to give even distribution for
142 low frame rates. Code supplied by Ian Reid.
143 Fix some problems with the RGB version. Patch supplied
144 by <ljo@po.cwru.edu>.
145 Added METEOR_FIELD_MODE to include files for a
146 future version of this driver.
151 #include "opt_meteor.h"
153 #include <sys/param.h>
154 #include <sys/systm.h>
155 #include <sys/conf.h>
156 #include <sys/kernel.h>
157 #include <sys/signalvar.h>
158 #include <sys/mman.h>
161 #if defined(METEOR_FreeBSD_210)
162 #include <machine/cpu.h> /* bootverbose */
166 #include <vm/vm_kern.h>
168 #include <vm/vm_extern.h>
170 #include <pci/pcivar.h>
171 #include <pci/pcireg.h>
172 #include <machine/ioctl_meteor.h>
173 #include <pci/meteor_reg.h>
176 static void meteor_intr __P((void *arg));
179 * Allocate enough memory for:
180 * 768x576 RGB 16 or YUV (16 storage bits/pixel) = 884736 = 216 pages
182 * You may override this using the options "METEOR_ALLOC_PAGES=value" in your
183 * kernel configuration file.
185 #ifndef METEOR_ALLOC_PAGES
186 #define METEOR_ALLOC_PAGES 217
188 #define METEOR_ALLOC (METEOR_ALLOC_PAGES * PAGE_SIZE)
190 static meteor_reg_t meteor[NMETEOR];
191 #define METEOR_NUM(mtr) ((mtr - &meteor[0])/sizeof(meteor_reg_t))
193 #define METPRI PCATCH
195 static const char* met_probe (pcici_t tag, pcidi_t type);
196 static void met_attach(pcici_t tag, int unit);
197 static u_long met_count;
199 static struct pci_device met_device = {
206 COMPAT_PCI_DRIVER (meteor, met_device);
208 #if defined(METEOR_FreeBSD_210) /* XXX */
209 d_open_t meteor_open;
210 d_close_t meteor_close;
211 d_read_t meteor_read;
212 d_write_t meteor_write;
213 d_ioctl_t meteor_ioctl;
214 d_mmap_t meteor_mmap;
216 static d_open_t meteor_open;
217 static d_close_t meteor_close;
218 static d_read_t meteor_read;
219 static d_write_t meteor_write;
220 static d_ioctl_t meteor_ioctl;
221 static d_mmap_t meteor_mmap;
223 #define CDEV_MAJOR 67
224 static struct cdevsw meteor_cdevsw = {
226 /* maj */ CDEV_MAJOR,
231 /* open */ meteor_open,
232 /* close */ meteor_close,
233 /* read */ meteor_read,
234 /* write */ meteor_write,
235 /* ioctl */ meteor_ioctl,
237 /* mmap */ meteor_mmap,
238 /* strategy */ nostrategy,
244 static mreg_t saa7116_pci_default[sizeof(struct saa7116_regs)/sizeof(mreg_t)]={
245 /* PCI Memory registers */
246 /* BITS Type Description */
247 /* 0x00 */ 0x00000000, /* 31:1 e*RW DMA 1 (Even)
249 /* 0x04 */ 0x00000000, /* 31:2 e*RW DMA 2 (Even)
251 /* 0x08 */ 0x00000000, /* 31:2 e*RW DMA 3 (Even)
253 /* 0x0c */ 0x00000000, /* 31:1 o*RW DMA 1 (Odd)
255 /* 0x10 */ 0x00000000, /* 31:2 o*RW DMA 2 (Odd)
257 /* 0x14 */ 0x00000000, /* 31:2 o*RW DMA 3 (Odd)
259 /* 0x18 */ 0x00000500, /* 15:2 e*RW Stride 1 (Even)
261 /* 0x1c */ 0x00000000, /* 15:2 e*RW Stride 2 (Even)
263 /* 0x20 */ 0x00000000, /* 15:2 e*RW Stride 3 (Even)
265 /* 0x24 */ 0x00000500, /* 15:2 o*RW Stride 1 (Odd)
267 /* 0x28 */ 0x00000000, /* 15:2 o*RW Stride 2 (Odd)
269 /* 0x2c */ 0x00000000, /* 15:2 o*RW Stride 3 (Odd)
271 /* 0x30 */ 0xeeeeee01, /* 31:8 *RW Route (Even)
272 7:0 *RW Mode (Even) */
273 /* 0x34 */ 0xeeeeee01, /* 31:8 *RW Route (Odd)
274 7:0 *RW Mode (Odd) */
275 /* 0x38 */ 0x00200020, /* 22:16 *RW FIFO Trigger Planer Mode,
276 6:0 *RW FIFO Trigger Packed Mode */
277 /* 0x3c */ 0x00000107, /* 9:8 *RW Reserved (0x0)
280 0 *RW Reserved (0x1) */
281 /* 0x40 */ 0x000000c0, /* 15 *RW Range Enable
282 14 *RW Corrupt Disable
283 11 *RR Address Error (Odd)
284 10 *RR Address Error (Even)
285 9 *RR Field Corrupt (Odd)
286 8 *RR Field Corrupt (Even)
289 5 *RR Field Done (Odd)
290 4 *RR Field Done (Even)
291 3 *RS Single Field Capture (Odd)
292 2 *RS Single Field Capture (Even)
293 1 *RW Capture (ODD) Continous
294 0 *RW Capture (Even) Continous */
295 /* 0x44 */ 0x00000000, /* 7:0 *RW Retry Wait Counter */
296 /* 0x48 */ 0x00000307, /* 10 *RW Interrupt mask, start of field
297 9 *RW Interrupt mask, end odd field
298 8 *RW Interrupt mask, end even field
299 2 *RR Interrupt status, start of field
300 1 *RR Interrupt status, end of odd
301 0 *RR Interrupt status, end of even */
302 /* 0x4c */ 0x00000001, /* 31:0 *RW Field Mask (Even) continous */
303 /* 0x50 */ 0x00000001, /* 31:0 *RW Field Mask (Odd) continous */
304 /* 0x54 */ 0x00000000, /* 20:16 *RW Mask Length (Odd)
305 4:0 *RW Mask Length (Even) */
306 /* 0x58 */ 0x0005007c, /* 22:16 *RW FIFO almost empty
307 6:0 *RW FIFO almost full */
308 /* 0x5c */ 0x461e1e0f, /* 31:24 *RW I2C Phase 4
309 23:16 *RW I2C Phase 3
311 7:0 *RW I2C Phase 1 */
312 /* 0x60 */ 0x00000300, /* 31:24 *RO I2C Read Data
313 23:16 **RW I2C Auto Address
316 9 RR I2C Direct Abort
321 0 RW I2C Auto Enable */
322 /* 0x64 */ 0x00000000, /* 24 RS I2C New Cycle
323 23:16 **RW I2C Direct Address
324 15:8 **RW I2C Direct Sub-address
325 7:0 **RW I2C Direct Write Address */
326 /* 0x68 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 1 (Even)
327 23:16 **RW I2C Auto Data 1 (Even)
328 15:8 **RW I2C Auto Sub-address 0 (Even)
329 7:0 **RW I2C Auto Data 0 (Even) */
330 /* 0x6c */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 3 (Even)
331 23:16 **RW I2C Auto Data 3 (Even)
332 15:8 **RW I2C Auto Sub-address 2 (Even)
333 7:0 **RW I2C Auto Data 2 (Even) */
334 /* 0x70 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 5 (Even)
335 23:16 **RW I2C Auto Data 5 (Even)
336 15:8 **RW I2C Auto Sub-address 4 (Even)
337 7:0 **RW I2C Auto Data 4 (Even) */
338 /* 0x74 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 7 (Even)
339 23:16 **RW I2C Auto Data 7 (Even)
340 15:8 **RW I2C Auto Sub-address 6 (Even)
341 7:0 **RW I2C Auto Data 6 (Even) */
342 /* 0x78 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 1 (Odd)
343 23:16 **RW I2C Auto Data 1 (Odd)
344 15:8 **RW I2C Auto Sub-address 0 (Odd)
345 7:0 **RW I2C Auto Data 0 (Odd) */
346 /* 0x7c */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 3 (Odd)
347 23:16 **RW I2C Auto Data 3 (Odd)
348 15:8 **RW I2C Auto Sub-address 2 (Odd)
349 7:0 **RW I2C Auto Data 2 (Odd) */
350 /* 0x80 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 5 (Odd)
351 23:16 **RW I2C Auto Data 5 (Odd)
352 15:8 **RW I2C Auto Sub-address 4 (Odd)
353 7:0 **RW I2C Auto Data 4 (Odd) */
354 /* 0x84 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 7 (Odd)
355 23:16 **RW I2C Auto Data 7 (Odd)
356 15:8 **RW I2C Auto Sub-address 6 (Odd)
357 7:0 **RW I2C Auto Data 6 (Odd) */
358 /* 0x88 */ 0x00000000, /* 23:16 **RW I2C Register Enable (Odd)
359 7:0 **RW I2C Register Enable (Even) */
360 /* 0x8c */ 0x00000000, /* 23:2 e*RW DMA End (Even)
362 /* 0x90 */ 0x00000000 /* 23:2 e*RW DMA End (Odd)
366 static u_char saa7196_i2c_default[NUM_SAA7196_I2C_REGS] = {
367 /* SAA7196 I2C bus control */
369 /* 00 */ 0x50, /* 7:0 Increment Delay */
370 /* 01 */ 0x30, /* 7:0 Horizontal Sync Begin for 50hz */
371 /* 02 */ 0x00, /* 7:0 Horizontal Sync Stop for 50hz */
372 /* 03 */ 0xe8, /* 7:0 Horizontal Sync Clamp Start for 50hz */
373 /* 04 */ 0xb6, /* 7:0 Horizontal Sync Clamp Stop for 50hz */
374 /* 05 */ 0xf4, /* 7:0 Horizontal Sync Start after PH1 for 50hz */
375 /* 06 */ 0x46, /* 7 Input mode =0 CVBS, =1 S-Video
377 5:4 Aperture Bandpass characteristics
378 3:2 Coring range for high freq
379 1:0 Aperture bandpass filter weights */
380 /* 07 */ 0x00, /* 7:0 Hue */
381 /* 08 */ 0x7f, /* 7:3 Colour-killer threshold QAM (PAL, NTSC) */
382 /* 09 */ 0x7f, /* 7:3 Colour-killer threshold SECAM */
383 /* 0a */ 0x7f, /* 7:0 PAL switch sensitivity */
384 /* 0b */ 0x7f, /* 7:0 SECAM switch sensitivity */
385 /* 0c */ 0x40, /* 7 Colour-on bit
387 /* 0d */ 0x84, /* 7 VTR/TV mode bit = 1->VTR mode
388 3 Realtime output mode select bit
389 2 HREF position select
392 /* 0e */ 0x38, /* 7 Horizontal clock PLL
393 5 Select interal/external clock source
394 4 Output enable of Horizontal/Vertical sync
395 3 Data output YUV enable
399 /* 0f */ 0x50, /* 7 Automatic Field detection
400 6 Field Select 0 = 50hz, 1=60hz
401 5 SECAM cross-colour reduction
402 4 Enable sync and clamping pulse
403 3:1 Luminance delay compensation */
404 /* 10 */ 0x00, /* 2 Select HREF Position
405 1:0 Vertical noise reduction */
406 /* 11 */ 0x2c, /* 7:0 Chrominance gain conrtol for QAM */
407 /* 12 */ 0x40, /* 7:0 Chrominance saturation control for VRAM port */
408 /* 13 */ 0x40, /* 7:0 Luminance contract control for VRAM port */
409 /* 14 */ 0x34, /* 7:0 Horizontal sync begin for 60hz */
411 /* 15 */ 0x0c, /* 7:0 Horizontal sync stop for 60hz */
412 /* 16 */ 0xfb, /* 7:0 Horizontal clamp begin for 60hz */
413 /* 17 */ 0xd4, /* 7:0 Horizontal clamp stop for 60hz */
414 /* 18 */ 0xec, /* 7:0 Horizontal sync start after PH1 for 60hz */
416 0x0a, 0xf4, 0xce, 0xf4,
418 /* 19 */ 0x80, /* 7:0 Luminance brightness control for VRAM port */
425 /* 20 */ 0x90, /* 7 ROM table bypass switch
426 6:5 Set output field mode
427 4 VRAM port outputs enable
428 3:2 First pixel position in VRO data
429 1:0 FIFO output register select */
430 /* 21 */ 0x80, /* 7:0 [7:0] Pixel number per line on output */
431 /* 22 */ 0x80, /* 7:0 [7:0] Pixel number per line on input */
432 /* 23 */ 0x03, /* 7:0 [7:0] Horizontal start position of scaling win*/
433 /* 24 */ 0x8a, /* 7:5 Horizontal decimation filter
434 4 [8] Horizontal start position of scaling win
435 3:2 [9:8] Pixel number per line on input
436 1:0 [9:8] Pixel number per line on output */
437 /* 25 */ 0xf0, /* 7:0 [7:0] Line number per output field */
438 /* 26 */ 0xf0, /* 7:0 [7:0] Line number per input field */
439 /* 27 */ 0x0f, /* 7:0 [7:0] Vertical start of scaling window */
440 /* 28 */ 0x80, /* 7 Adaptive filter switch
441 6:5 Vertical luminance data processing
442 4 [8] Vertical start of scaling window
443 3:2 [9:8] Line number per input field
444 1:0 [9:8] Line number per output field */
445 /* 29 */ 0x16, /* 7:0 [7:0] Vertical bypass start */
446 /* 2a */ 0x00, /* 7:0 [7:0] Vertical bypass count */
447 /* 2b */ 0x00, /* 4 [8] Vertical bypass start
448 2 [8] Vertical bypass count
449 0 Polarity, internally detected odd even flag */
450 /* 2c */ 0x80, /* 7:0 Set lower limit V for colour-keying */
451 /* 2d */ 0x7f, /* 7:0 Set upper limit V for colour-keying */
452 /* 2e */ 0x80, /* 7:0 Set lower limit U for colour-keying */
453 /* 2f */ 0x7f, /* 7:0 Set upper limit U for colour-keying */
454 /* 30 */ 0xbf /* 7 VRAM bus output format
455 6 Adaptive geometrical filter
456 5 Luminance limiting value
457 4 Monochrome and two's complement output data sel
458 3 Line quailifier flag
459 2 Pixel qualifier flag
460 1 Transparent data transfer
461 0 Extended formats enable bit */
464 static u_char bt254_default[NUM_BT254_REGS] = {
476 * Returns 0 Succesful completion.
477 * Returns 1 If transfer aborted or timeout occured.
480 static int i2c_print_err = 1;
482 i2c_write(meteor_reg_t * mtr, u_char slave, u_char rw, u_char reg, u_char data)
484 register unsigned long wait_counter = 0x0001ffff;
485 register mreg_t * iic_write_loc = &mtr->base->i2c_write;
486 register int err = 0;
489 /* Write the data the the i2c write register */
490 *iic_write_loc = SAA7116_IIC_NEW_CYCLE |
491 (((u_long)slave|(u_long)rw) << 16) |
492 ((u_long)reg << 8) | (u_long)data;
494 /* Wait until the i2c cycle is compeleted */
495 while((*iic_write_loc & SAA7116_IIC_NEW_CYCLE)) {
496 if(!wait_counter) break;
500 /* 1ffff should be enough delay time for the i2c cycle to complete */
503 printf("meteor%d: %d i2c %s transfer timeout 0x%x",
504 METEOR_NUM(mtr), slave,
505 rw ? "read" : "write", *iic_write_loc);
510 /* Check for error on direct write, clear if any */
511 if(mtr->base->i2c_read & SAA7116_IIC_DIRECT_TRANSFER_ABORTED){
512 mtr->base->i2c_read |= SAA7116_IIC_DIRECT_TRANSFER_ABORTED;
514 printf("meteor%d: 0x%x i2c %s tranfer aborted",
515 METEOR_NUM(mtr), slave,
516 rw ? "read" : "write" );
522 printf(" - reg=0x%x, value=0x%x.\n", reg, data);
530 met_probe (pcici_t tag, pcidi_t type)
535 cdevsw_add(&meteor_cdevsw);
538 case SAA7116_PHILIPS_ID: /* meteor */
539 return("Philips SAA 7116");
544 /* interrupt handling routine
545 complete meteor_read() if using interrupts
548 meteor_intr(void *arg)
550 meteor_reg_t *mtr = (meteor_reg_t *) arg;
551 mreg_t *cap = &mtr->base->cap_cntl,
552 *base = &mtr->base->dma1e,
553 *stat = &mtr->base->irq_stat;
554 u_long status = *stat,
555 cap_err = *cap & 0x00000f00,
556 #ifdef METEOR_CHECK_PCI_BUS
557 pci_err = pci_conf_read(mtr->tag,
558 PCI_COMMAND_STATUS_REG),
560 next_base = (u_long)(vtophys(mtr->bigbuf));
563 * Disable future interrupts if a capture mode is not selected.
564 * This can happen when we are in the process of closing or
565 * changing capture modes, otherwise it shouldn't happen.
567 if(!(mtr->flags & METEOR_CAP_MASK)) {
568 *cap &= 0x8ff0; /* disable future interrupts */
570 #ifdef METEOR_CHECK_PCI_BUS
572 * Check for pci bus errors.
574 #define METEOR_MASTER_ABORT 0x20000000
575 #define METEOR_TARGET_ABORT 0x10000000
576 if(pci_err & METEOR_MASTER_ABORT) {
577 printf("meteor%d: intr: pci bus master dma abort: 0x%x 0x%x.\n",
578 METEOR_NUM(mtr), *base, *(base+3));
579 pci_conf_write(mtr->tag, PCI_COMMAND_STATUS_REG, pci_err);
581 if(pci_err & METEOR_TARGET_ABORT) {
582 printf("meteor%d: intr: pci bus target dma abort: 0x%x 0x%x.\n",
583 METEOR_NUM(mtr), *base, *(base+3));
584 pci_conf_write(mtr->tag, PCI_COMMAND_STATUS_REG, pci_err);
591 if (cap_err & 0x300) {
592 if(mtr->fifo_errors % 50 == 0) {
593 printf("meteor%d: capture error", METEOR_NUM(mtr));
594 printf(": %s FIFO overflow.\n",
595 cap_err&0x0100? "even" : "odd");
597 mtr->fifo_errors++ ; /* increment fifo capture errors cnt */
599 if (cap_err & 0xc00) {
600 if(mtr->dma_errors % 50 == 0) {
601 printf("meteor%d: capture error", METEOR_NUM(mtr));
602 printf(": %s DMA address.\n",
603 cap_err&0x0400? "even" : "odd");
605 mtr->dma_errors++ ; /* increment DMA capture errors cnt */
608 *cap |= 0x0f30; /* clear error and field done */
611 * In synchronous capture mode we need to know what the address
612 * offset for the next field/frame will be. next_base holds the
613 * value for the even dma buffers (for odd, one must add stride).
615 if((mtr->flags & METEOR_SYNCAP) && !mtr->synch_wait &&
616 (mtr->current < mtr->frames)) { /* could be !=, but < is safer */
617 /* next_base is initialized to mtr->bigbuf */
618 next_base += mtr->frame_size * mtr->current;
619 if(mtr->flags & METEOR_WANT_TS)
620 next_base += sizeof(struct timeval) * mtr->current;
624 * Count the field and clear the field flag.
626 * In single mode capture, clear the continuous capture mode.
628 * In synchronous capture mode, if we have room for another field,
629 * adjust DMA buffer pointers.
630 * When we are above the hi water mark (hiwat), mtr->synch_wait will
631 * be set and we will not bump the DMA buffer pointers. Thus, once
632 * we reach the hi water mark, the driver acts like a continuous mode
633 * capture on the mtr->current frame until we hit the low water
634 * mark (lowat). The user had the option of stopping or halting
635 * the capture if this is not the desired effect.
637 if (status & 0x1) { /* even field */
638 mtr->even_fields_captured++;
639 mtr->flags &= ~METEOR_WANT_EVEN;
640 if((mtr->flags & METEOR_SYNCAP) && !mtr->synch_wait) {
642 /* XXX should add adjustments for YUV_422 & PLANAR */
645 * If the user requested to be notified via signal,
646 * let them know the field is complete.
648 if(mtr->proc && (mtr->signal & METEOR_SIG_MODE_MASK))
649 psignal(mtr->proc, mtr->signal&(~METEOR_SIG_MODE_MASK));
651 if (status & 0x2) { /* odd field */
652 mtr->odd_fields_captured++;
653 mtr->flags &= ~METEOR_WANT_ODD;
654 if((mtr->flags & METEOR_SYNCAP) && !mtr->synch_wait) {
655 *(base+3) = next_base + *(base+6);
656 /* XXX should add adjustments for YUV_422 & PLANAR */
659 * If the user requested to be notified via signal,
660 * let them know the field is complete.
662 if(mtr->proc && (mtr->signal & METEOR_SIG_MODE_MASK))
663 psignal(mtr->proc, mtr->signal&(~METEOR_SIG_MODE_MASK));
667 * If we have a complete frame.
669 if(!(mtr->flags & METEOR_WANT_MASK)) {
670 mtr->frames_captured++;
672 * post the completion time.
674 if(mtr->flags & METEOR_WANT_TS) {
677 if(mtr->alloc_pages * PAGE_SIZE <= (mtr->frame_size +
678 sizeof(struct timeval))) {
679 ts =(struct timeval *)mtr->bigbuf +
681 /* doesn't work in synch mode except for first frame */
687 * Wake up the user in single capture mode.
689 if(mtr->flags & METEOR_SINGLE)
690 wakeup((caddr_t)mtr);
692 * If the user requested to be notified via signal,
693 * let them know the frame is complete.
695 if(mtr->proc && !(mtr->signal & METEOR_SIG_MODE_MASK))
696 psignal(mtr->proc, mtr->signal&(~METEOR_SIG_MODE_MASK));
698 * Reset the want flags if in continuous or
699 * synchronous capture mode.
701 if(mtr->flags & (METEOR_CONTIN|METEOR_SYNCAP)) {
702 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
703 case METEOR_ONLY_ODD_FIELDS:
704 mtr->flags |= METEOR_WANT_ODD;
706 case METEOR_ONLY_EVEN_FIELDS:
707 mtr->flags |= METEOR_WANT_EVEN;
710 mtr->flags |= METEOR_WANT_MASK;
715 * Special handling for synchronous capture mode.
717 if(mtr->flags & METEOR_SYNCAP) {
718 struct meteor_mem *mm = mtr->mem;
720 * Mark the current frame as active. It is up to
721 * the user to clear this, but we will clear it
722 * for the user for the current frame being captured
723 * if we are within the water marks (see below).
725 mm->active |= 1 << (mtr->current - 1);
728 * Since the user can muck with these values, we need
729 * to check and see if they are sane. If they don't
730 * pass the sanity check, disable the capture mode.
731 * This is rather rude, but then so was the user.
733 * Do we really need all of this or should we just
734 * eliminate the possiblity of allowing the
735 * user to change hi and lo water marks while it
738 if(mm->num_active_bufs < 0 ||
739 mm->num_active_bufs > mtr->frames ||
740 mm->lowat < 1 || mm->lowat >= mtr->frames ||
741 mm->hiwat < 1 || mm->hiwat >= mtr->frames ||
742 mm->lowat > mm->hiwat ) {
744 mtr->flags &= ~(METEOR_SYNCAP|METEOR_WANT_MASK);
747 * Ok, they are sane, now we want to
748 * check the water marks.
750 if(mm->num_active_bufs <= mm->lowat)
752 if(mm->num_active_bufs >= mm->hiwat)
755 * Clear the active frame bit for this frame
756 * and advance the counters if we are within
757 * the banks of the water marks.
759 if(!mtr->synch_wait) {
760 mm->active &= ~(1 << mtr->current);
762 if(mtr->current > mtr->frames)
764 mm->num_active_bufs++;
770 *stat |= 0x7; /* clear interrupt status */
775 set_fps(meteor_reg_t *mtr, u_short fps)
777 struct saa7116_regs *s7116 = mtr->base;
779 unsigned maxfps, mask = 0x1, length = 0;
781 SAA7196_WRITE(mtr, SAA7196_STDC, SAA7196_REG(mtr, SAA7196_STDC) | 0x02);
783 status = (s7116->i2c_read & 0xff000000L) >> 24;
786 * Determine if there is an input signal. Depending on the
787 * frequency we either have a max of 25 fps (50 hz) or 30 fps (60 hz).
788 * If there is no input signal, then we need some defaults. If the
789 * user neglected to specify any defaults, just set to the fps to max.
791 if((status & 0x40) == 0) { /* Is there a signal ? */
793 maxfps = 30; /* 60 hz system */
795 maxfps = 25; /* 50 hz system */
797 } else { /* We have no signal, check defaults */
798 #if METEOR_SYSTEM_DEFAULT == METEOR_PAL || METEOR_SYSTEM_DEFAULT == METEOR_SECAM
800 #elif METEOR_SYSTEM_DEFAULT == METEOR_NTSC
803 /* Don't really know what to do, just set max */
810 * A little sanity checking...
813 if(fps > maxfps) fps = maxfps;
816 * Compute the mask/length using the fps.
821 } else if ((float)fps == maxfps/2.0) {
824 } else if (fps > maxfps/2) {
827 mask = (1<<maxfps) - 1;
829 step = (float)(maxfps - 1)/(float)(maxfps - fps);
830 for(b=step; b < maxfps; b += step) {
831 mask &= ~(1<<((int)b)); /* mask out the bth frame */
833 } else { /* fps < maxfps/2 */
838 step = (float)(maxfps -1)/(float)(fps);
839 for(b = step + 1; b < maxfps - 1; b += step) {
840 mask |= (1<<((int)b)); /* mask in the bth frame */
847 s7116->fme = s7116->fmo = mask;
848 s7116->fml = (length << 16) | length;;
857 * There is also a problem with range checking on the 7116.
858 * It seems to only work for 22 bits, so the max size we can allocate
859 * is 22 bits long or 4194304 bytes assuming that we put the beginning
860 * of the buffer on a 2^24 bit boundary. The range registers will use
861 * the top 8 bits of the dma start registers along with the bottom 22
862 * bits of the range register to determine if we go out of range.
863 * This makes getting memory a real kludge.
866 #define RANGE_BOUNDARY (1<<22)
868 get_meteor_mem(int unit, unsigned size)
870 vm_offset_t addr = 0;
872 addr = vm_page_alloc_contig(size, 0, 0xffffffff, 1<<24);
874 addr = vm_page_alloc_contig(size, 0, 0xffffffff, PAGE_SIZE);
876 printf("meteor%d: Unable to allocate %d bytes of memory.\n",
884 bt254_write(meteor_reg_t *mtr, u_char addr, u_char data)
886 addr &= 0x7; /* sanity? */
887 mtr->bt254_reg[addr] = data;
888 PCF8574_DATA_WRITE(mtr, data); /* set data */
889 PCF8574_CTRL_WRITE(mtr, (PCF8574_CTRL_REG(mtr) & ~0x7) | addr);
890 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) & ~0x10); /* WR/ to 0 */
891 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x10); /* WR to 1 */
892 PCF8574_DATA_WRITE(mtr, 0xff); /* clr data */
897 bt254_init(meteor_reg_t *mtr)
901 PCF8574_CTRL_WRITE(mtr, 0x7f);
902 PCF8574_DATA_WRITE(mtr, 0xff); /* data port must be 0xff */
903 PCF8574_CTRL_WRITE(mtr, 0x7f);
905 /* init RGB module for 24bpp, composite input */
906 for(i=0; i<NUM_BT254_REGS; i++)
907 bt254_write(mtr, i, bt254_default[i]);
909 bt254_write(mtr, BT254_COMMAND, 0x00); /* 24 bpp */
913 bt254_ntsc(meteor_reg_t *mtr, int arg)
917 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x20);
921 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) &= ~0x20);
926 select_bt254(meteor_reg_t *mtr)
928 /* disable saa7196, saaen = 1 */
929 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x80);
930 /* enable Bt254, bten = 0 */
931 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) & ~0x40);
935 select_saa7196(meteor_reg_t *mtr)
937 /* disable Bt254, bten = 1 */
938 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x40);
939 /* enable saa7196, saaen = 0 */
940 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) & ~0x80);
944 * Initialize the 7116, 7196 and the RGB module.
947 meteor_init ( meteor_reg_t *mtr )
953 * Initialize the Philips SAA7116
955 mtr->base->cap_cntl = 0x00000040L;
956 vbase_addr = &mtr->base->dma1e;
957 for (i = 0 ; i < (sizeof(struct saa7116_regs)/sizeof(mreg_t)); i++)
958 *vbase_addr++ = saa7116_pci_default[i];
961 * Check for the Philips SAA7196
964 if(i2c_write(mtr, SAA7196_I2C_ADDR, SAA7116_I2C_WRITE, 0, 0xff) == 0) {
969 for (i = 0; i < NUM_SAA7196_I2C_REGS; i++)
970 SAA7196_WRITE(mtr, i, saa7196_i2c_default[i]);
972 * Get version number.
974 SAA7196_WRITE(mtr, SAA7196_STDC,
975 SAA7196_REG(mtr, SAA7196_STDC) & ~0x02);
977 printf("meteor%d: <Philips SAA 7196> rev 0x%x\n",
979 (unsigned)((mtr->base->i2c_read & 0xff000000L) >> 28));
982 printf("meteor%d: <Philips SAA 7196 NOT FOUND>\n",
986 * Check for RGB module, initialized if found.
989 if(i2c_write(mtr,PCF8574_DATA_I2C_ADDR,SAA7116_I2C_WRITE,0,0xff) == 0) {
991 printf("meteor%d: <Booktree 254 (RGB module)>\n",
992 METEOR_NUM(mtr)); /* does this have a rev #? */
993 bt254_init(mtr); /* Set up RGB module */
994 mtr->flags = METEOR_RGB;
1005 met_attach(pcici_t tag, int unit)
1008 u_long old_irq, new_irq;
1014 if (unit >= NMETEOR) {
1015 printf("meteor%d: attach: only %d units configured.\n",
1017 printf("meteor%d: attach: invalid unit number.\n", unit);
1022 * Check for Meteor/PPB (PCI-PCI Bridge)
1023 * Reprogram IBM Bridge if detected.
1024 * New Meteor cards have an IBM PCI-PCI bridge, creating a secondary
1025 * PCI bus. The SAA chip is connected to this secondary bus.
1028 /* If we are not on PCI Bus 0, check for the Bridge */
1029 if ( pci_get_bus_from_tag( tag ) != 0) {
1032 /* get tag of parent bridge */
1033 bridge_tag = pci_get_parent_from_tag( tag );
1035 /* Look for IBM 82351, 82352 or 82353 */
1036 if (pci_conf_read(bridge_tag, PCI_ID_REG) == 0x00221014) {
1039 printf("meteor%d: PPB device detected, reprogramming IBM bridge.\n", unit);
1042 pci_cfgwrite(bridge_tag, 0x05, 0x00, 1);
1044 pci_cfgwrite(bridge_tag, 0x0d, 0x20, 1);
1045 /* write posting enable, prefetch enabled --> GRAB direction */
1046 pci_cfgwrite(bridge_tag, 0x42, 0x14, 1);
1047 /* set PRTR Primary retry timer register */
1048 pci_cfgwrite(bridge_tag, 0x4c, 0x10, 1);
1052 mtr = &meteor[unit];
1054 pci_map_mem(tag, PCI_MAP_REG_START, (vm_offset_t *)&mtr->base,
1057 #ifdef METEOR_IRQ /* from the configuration file */
1058 old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
1059 pci_conf_write(tag, PCI_INTERRUPT_REG, METEOR_IRQ);
1060 new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
1061 printf("meteor%d: attach: irq changed from %d to %d\n",
1062 unit, (old_irq & 0xff), (new_irq & 0xff));
1064 /* setup the interrupt handling routine */
1065 pci_map_int(tag, meteor_intr, (void*) mtr, &net_imask);
1068 * PCI latency timer. 32 is a good value for 4 bus mastering slots, if
1069 * you have more than for, then 16 would probably be a better value.
1072 #ifndef METEOR_DEF_LATENCY_VALUE
1073 #define METEOR_DEF_LATENCY_VALUE 32
1075 latency = pci_conf_read(tag, PCI_LATENCY_TIMER);
1076 latency = (latency >> 8) & 0xff;
1079 printf("meteor%d: PCI bus latency is", unit);
1081 printf("meteor%d: PCI bus latency was 0 changing to",
1085 latency = METEOR_DEF_LATENCY_VALUE;
1086 pci_conf_write(tag, PCI_LATENCY_TIMER, latency<<8);
1089 printf(" %lu.\n", latency);
1092 meteor_init(mtr); /* set up saa7116, saa7196, and rgb module */
1095 buf = get_meteor_mem(unit, METEOR_ALLOC);
1099 printf("meteor%d: buffer size %d, addr 0x%x\n",
1100 unit, METEOR_ALLOC, vtophys(buf));
1104 mtr->alloc_pages = METEOR_ALLOC_PAGES;
1106 bzero((caddr_t) buf, METEOR_ALLOC);
1108 /* 640x480 RGB 16 */
1109 mtr->base->dma1e = buf;
1110 mtr->base->dma1o = buf + 0x500;
1111 mtr->base->dma_end_e =
1112 mtr->base->dma_end_o = buf + METEOR_ALLOC;
1114 /* 1 frame of 640x480 RGB 16 */
1117 mtr->depth = 2; /* two bytes per pixel */
1118 mtr->frames = 1; /* one frame */
1120 mtr->flags |= METEOR_INITALIZED | METEOR_AUTOMODE | METEOR_DEV0 |
1122 make_dev(&meteor_cdevsw, unit, 0, 0, 0644, "meteor");
1125 #define UNIT(x) ((x) & 0x07)
1129 meteor_reset(dev_t dev)
1131 int unit = UNIT(minor(dev));
1132 struct saa7116_regs *m;
1137 m = meteor[unit].base;
1140 tsleep((caddr_t)m, METPRI, "Mreset", hz/50);
1142 m->cap_cntl = 0x8ff0;
1143 m->cap_cntl = 0x80c0;
1144 m->cap_cntl = 0x8040;
1145 tsleep((caddr_t)m, METPRI, "Mreset", hz/10);
1146 m->cap_cntl = 0x80c0;
1153 /*---------------------------------------------------------
1155 ** Meteor character device driver routines
1157 **---------------------------------------------------------
1162 meteor_open(dev_t dev, int flags, int fmt, struct proc *p)
1168 unit = UNIT(minor(dev));
1169 if (unit >= NMETEOR) /* unit out of range */
1172 mtr = &(meteor[unit]);
1174 if (!(mtr->flags & METEOR_INITALIZED)) /* device not found */
1177 if (mtr->flags & METEOR_OPEN) /* device is busy */
1180 mtr->flags |= METEOR_OPEN;
1182 * Make sure that the i2c regs are set the same for each open.
1184 for(i=0; i< NUM_SAA7196_I2C_REGS; i++) {
1185 SAA7196_WRITE(mtr, i, saa7196_i2c_default[i]);
1188 mtr->fifo_errors = 0;
1189 mtr->dma_errors = 0;
1190 mtr->frames_captured = 0;
1191 mtr->even_fields_captured = 0;
1192 mtr->odd_fields_captured = 0;
1193 mtr->proc = (struct proc *)0;
1195 #ifdef METEOR_TEST_VIDEO
1196 mtr->video.addr = 0;
1197 mtr->video.width = 0;
1198 mtr->video.banksize = 0;
1199 mtr->video.ramsize = 0;
1206 meteor_close(dev_t dev, int flags, int fmt, struct proc *p)
1210 #ifdef METEOR_DEALLOC_ABOVE
1214 unit = UNIT(minor(dev));
1215 if (unit >= NMETEOR) /* unit out of range */
1218 mtr = &(meteor[unit]);
1219 mtr->flags &= ~METEOR_OPEN;
1221 if(mtr->flags & METEOR_SINGLE)
1222 /* this should not happen, the read capture
1223 should have completed or in the very least
1224 recieved a signal before close is called. */
1225 wakeup((caddr_t)mtr); /* continue read */
1227 * Turn off capture mode.
1229 mtr->base->cap_cntl = 0x8ff0;
1230 mtr->flags &= ~(METEOR_CAP_MASK|METEOR_WANT_MASK);
1231 mtr->proc = (struct proc *)0;
1233 #ifdef METEOR_DEALLOC_PAGES
1234 if (mtr->bigbuf != NULL) {
1235 kmem_free(kernel_map,mtr->bigbuf,(mtr->alloc_pages*PAGE_SIZE));
1237 mtr->alloc_pages = 0;
1240 #ifdef METEOR_DEALLOC_ABOVE
1241 if (mtr->bigbuf != NULL && mtr->alloc_pages > METEOR_DEALLOC_ABOVE) {
1242 temp = METEOR_DEALLOC_ABOVE - mtr->alloc_pages;
1243 kmem_free(kernel_map,
1244 mtr->bigbuf+((mtr->alloc_pages - temp) * PAGE_SIZE),
1245 (temp * PAGE_SIZE));
1246 mtr->alloc_pages = METEOR_DEALLOC_ABOVE;
1255 start_capture(meteor_reg_t *mtr, unsigned type)
1257 mreg_t *cap = &mtr->base->cap_cntl;
1260 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1261 case METEOR_ONLY_EVEN_FIELDS:
1262 mtr->flags |= METEOR_WANT_EVEN;
1263 if(type == METEOR_SINGLE)
1264 *cap = 0x0ff4 | mtr->range_enable;
1266 *cap = 0x0ff1 | mtr->range_enable;
1268 case METEOR_ONLY_ODD_FIELDS:
1269 mtr->flags |= METEOR_WANT_ODD;
1270 if(type == METEOR_SINGLE)
1271 *cap = 0x0ff8 | mtr->range_enable;
1273 *cap = 0x0ff2 | mtr->range_enable;
1276 mtr->flags |= METEOR_WANT_MASK;
1277 if(type == METEOR_SINGLE)
1278 *cap = 0x0ffc | mtr->range_enable;
1280 *cap = 0x0ff3 | mtr->range_enable;
1286 meteor_read(dev_t dev, struct uio *uio, int ioflag)
1293 unit = UNIT(minor(dev));
1294 if (unit >= NMETEOR) /* unit out of range */
1297 mtr = &(meteor[unit]);
1298 if (mtr->bigbuf == 0)/* no frame buffer allocated (ioctl failed) */
1301 if (mtr->flags & METEOR_CAP_MASK)
1302 return(EIO); /* already capturing */
1304 count = mtr->rows * mtr->cols * mtr->depth;
1305 if (uio->uio_iov->iov_len < count)
1309 start_capture(mtr, METEOR_SINGLE);
1311 status=tsleep((caddr_t)mtr, METPRI, "capturing", 0);
1312 if (!status) /* successful capture */
1313 status = uiomove((caddr_t)mtr->bigbuf, count, uio);
1315 printf ("meteor%d: read: tsleep error %d\n", unit, status);
1317 mtr->flags &= ~(METEOR_SINGLE | METEOR_WANT_MASK);
1323 meteor_write(dev_t dev, struct uio *uio, int ioflag)
1329 meteor_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *pr)
1335 struct meteor_counts *cnt;
1336 struct meteor_geomet *geo;
1337 struct meteor_mem *mem;
1338 struct meteor_capframe *frame;
1339 #ifdef METEOR_TEST_VIDEO
1340 struct meteor_video *video;
1343 struct saa7116_regs *base;
1347 if (!arg) return(EINVAL);
1348 unit = UNIT(minor(dev));
1349 if (unit >= NMETEOR) /* unit out of range */
1352 mtr = &(meteor[unit]);
1358 mtr->flags |= METEOR_WANT_TS;
1360 mtr->flags &= ~METEOR_WANT_TS;
1363 if(mtr->flags & METEOR_WANT_TS)
1368 #ifdef METEOR_TEST_VIDEO
1370 video = (struct meteor_video *)arg;
1371 video->addr = mtr->video.addr;
1372 video->width = mtr->video.width;
1373 video->banksize = mtr->video.banksize;
1374 video->ramsize = mtr->video.ramsize;
1377 video = (struct meteor_video *)arg;
1378 mtr->video.addr = video->addr;
1379 mtr->video.width = video->width;
1380 mtr->video.banksize = video->banksize;
1381 mtr->video.ramsize = video->ramsize;
1385 set_fps(mtr, *(u_short *)arg);
1388 *(u_short *)arg = mtr->fps;
1391 mtr->signal = *(int *) arg;
1395 mtr->proc = (struct proc *)0;
1399 *(int *)arg = mtr->signal;
1401 case METEORSTATUS: /* get 7196 status */
1403 SAA7196_WRITE(mtr, SAA7196_STDC,
1404 SAA7196_REG(mtr, SAA7196_STDC) | 0x02);
1406 temp |= (base->i2c_read & 0xff000000L) >> 24;
1407 SAA7196_WRITE(mtr, SAA7196_STDC,
1408 SAA7196_REG(mtr, SAA7196_STDC) & ~0x02);
1410 temp |= (base->i2c_read & 0xff000000L) >> 16;
1411 *(u_short *)arg = temp;
1413 case METEORSHUE: /* set hue */
1414 SAA7196_WRITE(mtr, SAA7196_HUEC, *(char *)arg);
1416 case METEORGHUE: /* get hue */
1417 *(char *)arg = SAA7196_REG(mtr, SAA7196_HUEC);
1419 case METEORSCHCV: /* set chrominance gain */
1420 SAA7196_WRITE(mtr, SAA7196_CGAINR, *(char *)arg);
1422 case METEORGCHCV: /* get chrominance gain */
1423 *(char *)arg = SAA7196_REG(mtr, SAA7196_CGAINR);
1425 case METEORSBRIG: /* set brightness */
1426 SAA7196_WRITE(mtr, SAA7196_BRIG, *(char *)arg);
1428 case METEORGBRIG: /* get brightness */
1429 *(char *)arg = SAA7196_REG(mtr, SAA7196_BRIG);
1431 case METEORSCSAT: /* set chroma saturation */
1432 SAA7196_WRITE(mtr, SAA7196_CSAT, *(char *)arg);
1434 case METEORGCSAT: /* get chroma saturation */
1435 *(char *)arg = SAA7196_REG(mtr, SAA7196_CSAT);
1437 case METEORSCONT: /* set contrast */
1438 SAA7196_WRITE(mtr, SAA7196_CONT, *(char *)arg);
1440 case METEORGCONT: /* get contrast */
1441 *(char *)arg = SAA7196_REG(mtr, SAA7196_CONT);
1444 if((mtr->flags & METEOR_RGB) == 0)
1446 temp = *(unsigned short *)arg;
1447 bt254_write(mtr, temp & 0xf, (temp & 0x0ff0) >> 4);
1450 if((mtr->flags & METEOR_RGB) == 0)
1452 temp = *(unsigned short *)arg & 0x7;
1453 *(unsigned short *)arg = mtr->bt254_reg[temp] << 4 | temp;
1455 case METEORSHWS: /* set horizontal window start */
1456 SAA7196_WRITE(mtr, SAA7196_HWS, *(char *)arg);
1458 case METEORGHWS: /* get horizontal window start */
1459 *(char *)arg = SAA7196_REG(mtr, SAA7196_HWS);
1461 case METEORSVWS: /* set vertical window start */
1462 SAA7196_WRITE(mtr, SAA7196_VWS, *(char *)arg);
1464 case METEORGVWS: /* get vertical window start */
1465 *(char *)arg = SAA7196_REG(mtr, SAA7196_VWS);
1467 case METEORSINPUT: /* set input device */
1468 switch(*(unsigned long *)arg & METEOR_DEV_MASK) {
1469 case 0: /* default */
1470 case METEOR_INPUT_DEV0:
1471 if(mtr->flags & METEOR_RGB)
1472 select_saa7196(mtr);
1473 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1475 SAA7196_WRITE(mtr, 0x0e,
1476 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x0);
1477 SAA7196_WRITE(mtr, 0x06,
1478 (SAA7196_REG(mtr, 0x06) & ~0x80));
1480 case METEOR_INPUT_DEV1:
1481 if(mtr->flags & METEOR_RGB)
1482 select_saa7196(mtr);
1483 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1485 SAA7196_WRITE(mtr, 0x0e,
1486 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x1);
1487 SAA7196_WRITE(mtr, 0x06,
1488 (SAA7196_REG(mtr, 0x06) & ~0x80));
1490 case METEOR_INPUT_DEV2:
1491 if(mtr->flags & METEOR_RGB)
1492 select_saa7196(mtr);
1493 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1495 SAA7196_WRITE(mtr, 0x0e,
1496 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x2);
1497 SAA7196_WRITE(mtr, 0x06,
1498 (SAA7196_REG(mtr, 0x06) & ~0x80));
1500 case METEOR_INPUT_DEV3:
1501 if(mtr->flags & METEOR_RGB)
1502 select_saa7196(mtr);
1503 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1505 SAA7196_WRITE(mtr, 0x0e,
1506 (SAA7196_REG(mtr, 0x0e) | 0x3));
1507 SAA7196_WRITE(mtr, 0x06,
1508 (SAA7196_REG(mtr, 0x06) & ~0x80) );
1510 case METEOR_INPUT_DEV_SVIDEO:
1511 if(mtr->flags & METEOR_RGB)
1512 select_saa7196(mtr);
1513 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1514 | METEOR_DEV_SVIDEO;
1515 SAA7196_WRITE(mtr, 0x0e,
1516 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x2);
1517 SAA7196_WRITE(mtr, 0x06,
1518 (SAA7196_REG(mtr, 0x06) & ~0x80) | 0x80);
1520 case METEOR_INPUT_DEV_RGB:
1521 if((mtr->flags & METEOR_RGB) == 0)
1523 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1525 SAA7196_WRITE(mtr, 0x0e,
1526 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x3);
1527 SAA7196_WRITE(mtr, 0x06,
1528 (SAA7196_REG(mtr, 0x06) & ~0x80));
1530 SAA7196_WRITE(mtr, 0x0e, /* chn 3 for synch */
1531 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x3);
1537 case METEORGINPUT: /* get input device */
1538 *(u_long *)arg = mtr->flags & METEOR_DEV_MASK;
1540 case METEORSFMT: /* set input format */
1541 switch(*(unsigned long *)arg & METEOR_FORM_MASK ) {
1542 case 0: /* default */
1543 case METEOR_FMT_NTSC:
1544 mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1546 SAA7196_WRITE(mtr, SAA7196_STDC,
1547 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01));
1548 SAA7196_WRITE(mtr, 0x0f,
1549 (SAA7196_REG(mtr, 0x0f) & ~0xe0) | 0x40);
1550 SAA7196_WRITE(mtr, 0x22, 0x80);
1551 SAA7196_WRITE(mtr, 0x24,
1552 (SAA7196_REG(mtr, 0x24) & ~0x0c) | 0x08);
1553 SAA7196_WRITE(mtr, 0x26, 0xf0);
1554 SAA7196_WRITE(mtr, 0x28,
1555 (SAA7196_REG(mtr, 0x28) & ~0x0c)) ;
1556 if(mtr->flags & METEOR_RGB){
1560 case METEOR_FMT_PAL:
1561 mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1563 SAA7196_WRITE(mtr, SAA7196_STDC,
1564 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01));
1565 SAA7196_WRITE(mtr, 0x0f,
1566 (SAA7196_REG(mtr, 0x0f) & ~0xe0));
1567 SAA7196_WRITE(mtr, 0x22, 0x00);
1568 SAA7196_WRITE(mtr, 0x24,
1569 (SAA7196_REG(mtr, 0x24) | 0x0c));
1570 SAA7196_WRITE(mtr, 0x26, 0x20);
1571 SAA7196_WRITE(mtr, 0x28,
1572 (SAA7196_REG(mtr, 0x28) & ~0x0c) | 0x04) ;
1573 if(mtr->flags & METEOR_RGB){
1577 case METEOR_FMT_SECAM:
1578 mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1580 SAA7196_WRITE(mtr, SAA7196_STDC,
1581 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01) | 0x1);
1582 SAA7196_WRITE(mtr, 0x0f,
1583 (SAA7196_REG(mtr, 0x0f) & ~0xe0) | 0x20);
1584 SAA7196_WRITE(mtr, 0x22, 0x00);
1585 SAA7196_WRITE(mtr, 0x24,
1586 (SAA7196_REG(mtr, 0x24) | 0x0c));
1587 SAA7196_WRITE(mtr, 0x26, 0x20);
1588 SAA7196_WRITE(mtr, 0x28,
1589 (SAA7196_REG(mtr, 0x28) & ~0x0c) | 0x04) ;
1590 if(mtr->flags & METEOR_RGB){
1594 case METEOR_FMT_AUTOMODE:
1595 mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1597 SAA7196_WRITE(mtr, SAA7196_STDC,
1598 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01));
1599 SAA7196_WRITE(mtr, 0x0f,
1600 (SAA7196_REG(mtr, 0x0f) & ~0xe0) | 0x80);
1606 case METEORGFMT: /* get input format */
1607 *(u_long *)arg = mtr->flags & METEOR_FORM_MASK;
1611 switch (*(int *) arg) {
1612 case METEOR_CAP_SINGLE:
1613 if (mtr->bigbuf==0) /* no frame buffer allocated */
1616 if (temp & METEOR_CAP_MASK)
1617 return(EIO); /* already capturing */
1619 start_capture(mtr, METEOR_SINGLE);
1621 /* wait for capture to complete */
1622 error=tsleep((caddr_t)mtr, METPRI, "capturing", 0);
1624 printf("meteor%d: ioctl: tsleep error %d\n",
1626 mtr->flags &= ~(METEOR_SINGLE|METEOR_WANT_MASK);
1628 case METEOR_CAP_CONTINOUS:
1629 if (mtr->bigbuf==0) /* no frame buffer allocated */
1632 if (temp & METEOR_CAP_MASK)
1633 return(EIO); /* already capturing */
1635 start_capture(mtr, METEOR_CONTIN);
1638 case METEOR_CAP_STOP_CONT:
1639 if (mtr->flags & METEOR_CONTIN) {
1640 /* turn off capture */
1641 base->cap_cntl = 0x8ff0;
1642 mtr->flags &= ~(METEOR_CONTIN|METEOR_WANT_MASK);
1652 frame = (struct meteor_capframe *) arg;
1655 switch (frame->command) {
1656 case METEOR_CAP_N_FRAMES:
1657 if (mtr->flags & METEOR_CAP_MASK)
1659 if (mtr->flags & (METEOR_YUV_PLANAR | METEOR_YUV_422)) /* XXX */
1660 return(EINVAL); /* should fix intr so we allow these */
1661 if (mtr->bigbuf == 0)
1663 if ((mtr->frames < 2) ||
1664 (frame->lowat < 1 || frame->lowat >= mtr->frames) ||
1665 (frame->hiwat < 1 || frame->hiwat >= mtr->frames) ||
1666 (frame->lowat > frame->hiwat))
1668 /* meteor_mem structure is on the page after the data */
1669 mem = mtr->mem = (struct meteor_mem *) (mtr->bigbuf +
1670 (round_page(mtr->frame_size * mtr->frames)));
1672 mtr->synch_wait = 0;
1673 mem->num_bufs = mtr->frames;
1674 mem->frame_size= mtr->frame_size;
1675 /* user and kernel change these */
1676 mem->lowat = frame->lowat;
1677 mem->hiwat = frame->hiwat;
1679 mem->num_active_bufs = 0;
1681 start_capture(mtr, METEOR_SYNCAP);
1683 case METEOR_CAP_STOP_FRAMES:
1684 if (mtr->flags & METEOR_SYNCAP) {
1685 /* turn off capture */
1686 base->cap_cntl = 0x8ff0;
1687 mtr->flags &= ~(METEOR_SYNCAP|METEOR_WANT_MASK);
1690 case METEOR_HALT_N_FRAMES:
1691 if(mtr->flags & METEOR_SYNCAP) {
1692 base->cap_cntl = 0x8ff0;
1693 mtr->flags &= ~(METEOR_WANT_MASK);
1696 case METEOR_CONT_N_FRAMES:
1697 if(!(mtr->flags & METEOR_SYNCAP)) {
1701 start_capture(mtr, METEOR_SYNCAP);
1710 geo = (struct meteor_geomet *) arg;
1712 /* Either even or odd, if even & odd, then these a zero */
1713 if((geo->oformat & METEOR_GEO_ODD_ONLY) &&
1714 (geo->oformat & METEOR_GEO_EVEN_ONLY)) {
1715 printf("meteor%d: ioctl: Geometry odd or even only.\n",
1719 /* set/clear even/odd flags */
1720 if(geo->oformat & METEOR_GEO_ODD_ONLY)
1721 mtr->flags |= METEOR_ONLY_ODD_FIELDS;
1723 mtr->flags &= ~METEOR_ONLY_ODD_FIELDS;
1724 if(geo->oformat & METEOR_GEO_EVEN_ONLY)
1725 mtr->flags |= METEOR_ONLY_EVEN_FIELDS;
1727 mtr->flags &= ~METEOR_ONLY_EVEN_FIELDS;
1729 /* can't change parameters while capturing */
1730 if (mtr->flags & METEOR_CAP_MASK)
1733 if ((geo->columns & 0x3fe) != geo->columns) {
1735 "meteor%d: ioctl: %d: columns too large or not even.\n",
1736 unit, geo->columns);
1739 if (((geo->rows & 0x7fe) != geo->rows) ||
1740 ((geo->oformat & METEOR_GEO_FIELD_MASK) &&
1741 ((geo->rows & 0x3fe) != geo->rows)) ) {
1743 "meteor%d: ioctl: %d: rows too large or not even.\n",
1747 if (geo->frames > 32) {
1748 printf("meteor%d: ioctl: too many frames.\n", unit);
1751 if(error) return error;
1753 if ((temp=geo->rows * geo->columns * geo->frames * 2) != 0) {
1754 if (geo->oformat & METEOR_GEO_RGB24) temp = temp * 2;
1756 /* meteor_mem structure for SYNC Capture */
1757 if (geo->frames > 1) temp += PAGE_SIZE;
1760 if (temp > mtr->alloc_pages
1761 #ifdef METEOR_TEST_VIDEO
1762 && mtr->video.addr == 0
1765 buf = get_meteor_mem(unit, temp*PAGE_SIZE);
1767 kmem_free(kernel_map, mtr->bigbuf,
1768 (mtr->alloc_pages * PAGE_SIZE));
1770 mtr->alloc_pages = temp;
1773 "meteor%d: ioctl: Allocating %d bytes\n",
1774 unit, temp*PAGE_SIZE);
1780 if(error) return error;
1782 mtr->rows = geo->rows;
1783 mtr->cols = geo->columns;
1784 mtr->frames = geo->frames;
1786 #ifdef METEOR_TEST_VIDEO
1788 buf = vtophys(mtr->video.addr);
1791 buf = vtophys(mtr->bigbuf);
1793 /* set defaults and end of buffer locations */
1806 /* set end of DMA location, even/odd */
1808 base->dma_end_o = buf + mtr->alloc_pages * PAGE_SIZE;
1811 * Determine if we can use the hardware range detect.
1813 if(mtr->alloc_pages * PAGE_SIZE < RANGE_BOUNDARY &&
1814 ((buf & 0xff000000) | base->dma_end_e) ==
1815 (buf + mtr->alloc_pages * PAGE_SIZE) )
1816 mtr->range_enable = 0x8000;
1818 mtr->range_enable = 0x0;
1820 base->dma_end_o = 0xffffffff;
1824 switch (geo->oformat & METEOR_GEO_OUTPUT_MASK) {
1825 case 0: /* default */
1826 case METEOR_GEO_RGB16:
1828 mtr->frame_size = mtr->rows * mtr->cols * mtr->depth;
1829 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1830 mtr->flags |= METEOR_RGB16;
1831 temp = mtr->cols * mtr->depth;
1832 /* recal stride and starting point */
1833 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1834 case METEOR_ONLY_ODD_FIELDS:
1836 #ifdef METEOR_TEST_VIDEO
1837 if(mtr->video.addr && mtr->video.width)
1838 base->stride1o = mtr->video.width-temp;
1840 SAA7196_WRITE(mtr, 0x20, 0xd0);
1842 case METEOR_ONLY_EVEN_FIELDS:
1844 #ifdef METEOR_TEST_VIDEO
1845 if(mtr->video.addr && mtr->video.width)
1846 base->stride1e = mtr->video.width-temp;
1848 SAA7196_WRITE(mtr, 0x20, 0xf0);
1850 default: /* interlaced even/odd */
1852 base->dma1o = buf + temp;
1853 base->stride1e = base->stride1o = temp;
1854 #ifdef METEOR_TEST_VIDEO
1855 if(mtr->video.addr && mtr->video.width) {
1856 base->dma1o = buf + mtr->video.width;
1857 base->stride1e = base->stride1o =
1859 temp + mtr->video.width;
1862 SAA7196_WRITE(mtr, 0x20, 0x90);
1865 base->routee = base->routeo = 0xeeeeee01;
1867 case METEOR_GEO_RGB24:
1869 mtr->frame_size = mtr->rows * mtr->cols * mtr->depth;
1870 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1871 mtr->flags |= METEOR_RGB24;
1872 temp = mtr->cols * mtr->depth;
1873 /* recal stride and starting point */
1874 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1875 case METEOR_ONLY_ODD_FIELDS:
1877 #ifdef METEOR_TEST_VIDEO
1878 if(mtr->video.addr && mtr->video.width)
1879 base->stride1o = mtr->video.width-temp;
1881 SAA7196_WRITE(mtr, 0x20, 0xd2);
1883 case METEOR_ONLY_EVEN_FIELDS:
1885 #ifdef METEOR_TEST_VIDEO
1886 if(mtr->video.addr && mtr->video.width)
1887 base->stride1e = mtr->video.width-temp;
1889 SAA7196_WRITE(mtr, 0x20, 0xf2);
1891 default: /* interlaced even/odd */
1893 base->dma1o = buf + mtr->cols * mtr->depth;
1894 base->stride1e = base->stride1o =
1895 mtr->cols * mtr->depth;
1896 #ifdef METEOR_TEST_VIDEO
1897 if(mtr->video.addr && mtr->video.width) {
1898 base->dma1o = buf + mtr->video.width;
1899 base->stride1e = base->stride1o =
1901 temp + mtr->video.width;
1904 SAA7196_WRITE(mtr, 0x20, 0x92);
1907 base->routee= base->routeo= 0x39393900;
1909 case METEOR_GEO_YUV_PLANAR:
1911 temp = mtr->rows * mtr->cols; /* compute frame size */
1912 mtr->frame_size = temp * mtr->depth;
1913 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1914 mtr->flags |= METEOR_YUV_PLANAR;
1915 /* recal stride and starting point */
1916 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1917 case METEOR_ONLY_ODD_FIELDS:
1918 base->dma1o = buf; /* Y Odd */
1919 base->dma2o = buf + temp; /* U Odd */
1921 base->dma3o = base->dma2o + temp; /* V Odd */
1922 SAA7196_WRITE(mtr, 0x20, 0xd1);
1924 case METEOR_ONLY_EVEN_FIELDS:
1925 base->dma1e = buf; /* Y Even */
1926 base->dma2e = buf + temp; /* U Even */
1928 base->dma2e= base->dma2e + temp; /* V Even */
1929 SAA7196_WRITE(mtr, 0x20, 0xf1);
1931 default: /* interlaced even/odd */
1932 base->dma1e = buf; /* Y Even */
1933 base->dma2e = buf + temp; /* U Even */
1935 base->dma3e = base->dma2e + temp; /* V Even */
1936 base->dma1o = base->dma1e+mtr->cols;/* Y Odd */
1937 base->dma2o = base->dma3e + temp; /* U Odd */
1938 base->dma3o = base->dma2o + temp; /* V Odd */
1939 base->stride1e = base->stride1o = mtr->cols;
1940 SAA7196_WRITE(mtr, 0x20, 0x91);
1943 switch (geo->oformat &
1944 (METEOR_GEO_YUV_12 | METEOR_GEO_YUV_9)) {
1945 case METEOR_GEO_YUV_9:
1946 base->routee=base->routeo = 0xaaaaffc3;
1948 case METEOR_GEO_YUV_12:
1949 base->routee=base->routeo = 0xaaaaffc2;
1952 base->routee=base->routeo = 0xaaaaffc1;
1956 case METEOR_GEO_YUV_422:/* same as planer, different uv order */
1958 temp = mtr->rows * mtr->cols; /* compute frame size */
1959 mtr->frame_size = temp * mtr->depth;
1960 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1961 mtr->flags |= METEOR_YUV_422;
1962 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1963 case METEOR_ONLY_ODD_FIELDS:
1965 base->dma2o = buf + temp;
1966 base->dma3o = base->dma2o + (temp >> 1);
1967 SAA7196_WRITE(mtr, 0x20, 0xd1);
1969 case METEOR_ONLY_EVEN_FIELDS:
1971 base->dma2e = buf + temp;
1972 base->dma3e = base->dma2e + (temp >> 1);
1973 SAA7196_WRITE(mtr, 0x20, 0xf1);
1975 default: /* interlaced even/odd */
1976 base->dma1e = buf; /* Y even */
1977 base->dma2e = buf + temp; /* U even */
1979 base->dma2e + (temp >> 1);/* V even */
1980 base->dma1o = base->dma1e+mtr->cols;/* Y odd */
1981 temp = mtr->cols >> 1;
1982 base->dma2o = base->dma2e+temp; /* U odd */
1983 base->dma3o = base->dma3e+temp; /* V odd */
1985 base->stride1o = mtr->cols; /* Y stride */
1987 base->stride2o = temp; /* U stride */
1989 base->stride3o = temp; /* V stride */
1990 SAA7196_WRITE(mtr, 0x20, 0x91);
1993 switch (geo->oformat &
1994 (METEOR_GEO_YUV_12 | METEOR_GEO_YUV_9)) {
1995 case METEOR_GEO_YUV_9:
1996 base->routee=base->routeo = 0xaaaaffc3;
1998 case METEOR_GEO_YUV_12:
1999 base->routee=base->routeo = 0xaaaaffc2;
2002 base->routee=base->routeo = 0xaaaaffc1;
2006 case METEOR_GEO_YUV_PACKED:
2008 mtr->frame_size = mtr->rows * mtr->cols * mtr->depth;
2009 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
2010 mtr->flags |= METEOR_YUV_PACKED;
2011 /* recal stride and odd starting point */
2012 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
2013 case METEOR_ONLY_ODD_FIELDS:
2015 SAA7196_WRITE(mtr, 0x20, 0xd1);
2017 case METEOR_ONLY_EVEN_FIELDS:
2019 SAA7196_WRITE(mtr, 0x20, 0xf1);
2021 default: /* interlaced even/odd */
2023 base->dma1o = buf + mtr->cols * mtr->depth;
2024 base->stride1e = base->stride1o =
2025 mtr->cols * mtr->depth;
2026 SAA7196_WRITE(mtr, 0x20, 0x91);
2029 base->routee = base->routeo = 0xeeeeee41;
2032 error = EINVAL; /* invalid argument */
2033 printf("meteor%d: ioctl: invalid output format\n",unit);
2037 SAA7196_WRITE(mtr, 0x21, mtr->cols & 0xff);
2038 SAA7196_WRITE(mtr, 0x24,
2039 ((SAA7196_REG(mtr, 0x24) & ~0x03) |
2040 ((mtr->cols >> 8) & 0x03)));
2042 if(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
2043 SAA7196_WRITE(mtr, 0x25, ((mtr->rows) & 0xff));
2044 SAA7196_WRITE(mtr, 0x28,
2045 ((SAA7196_REG(mtr, 0x28) & ~0x03) |
2046 ((mtr->rows >> 8) & 0x03)));
2047 } else { /* Interlaced */
2048 SAA7196_WRITE(mtr, 0x25, ((mtr->rows >> 1) & 0xff));
2049 SAA7196_WRITE(mtr, 0x28,
2050 ((SAA7196_REG(mtr, 0x28) & ~0x03) |
2051 ((mtr->rows >> 9) & 0x03)));
2053 /* set signed/unsigned chrominance */
2054 SAA7196_WRITE(mtr, 0x30, (SAA7196_REG(mtr, 0x30) & ~0x10) |
2055 ((geo->oformat&METEOR_GEO_UNSIGNED)?0:0x10));
2058 geo = (struct meteor_geomet *) arg;
2059 geo->rows = mtr->rows;
2060 geo->columns = mtr->cols;
2061 geo->frames = mtr->frames;
2062 geo->oformat = (mtr->flags & METEOR_OUTPUT_FMT_MASK) |
2063 (mtr->flags & METEOR_ONLY_FIELDS_MASK) |
2064 (SAA7196_REG(mtr, 0x30) & 0x10 ?
2065 0:METEOR_GEO_UNSIGNED);
2066 switch(base->routee & 0xff) {
2068 geo->oformat |= METEOR_GEO_YUV_9;
2071 geo->oformat |= METEOR_GEO_YUV_12;
2077 case METEORSCOUNT: /* (re)set error counts */
2078 cnt = (struct meteor_counts *) arg;
2079 mtr->fifo_errors = cnt->fifo_errors;
2080 mtr->dma_errors = cnt->dma_errors;
2081 mtr->frames_captured = cnt->frames_captured;
2082 mtr->even_fields_captured = cnt->even_fields_captured;
2083 mtr->odd_fields_captured = cnt->odd_fields_captured;
2085 case METEORGCOUNT: /* get error counts */
2086 cnt = (struct meteor_counts *) arg;
2087 cnt->fifo_errors = mtr->fifo_errors;
2088 cnt->dma_errors = mtr->dma_errors;
2089 cnt->frames_captured = mtr->frames_captured;
2090 cnt->even_fields_captured = mtr->even_fields_captured;
2091 cnt->odd_fields_captured = mtr->odd_fields_captured;
2094 printf("meteor%d: ioctl: invalid ioctl request\n", unit);
2102 meteor_mmap(dev_t dev, vm_offset_t offset, int nprot)
2108 unit = UNIT(minor(dev));
2109 if (unit >= NMETEOR) /* at this point could this happen? */
2112 mtr = &(meteor[unit]);
2115 if(nprot & PROT_EXEC)
2118 if(offset >= mtr->alloc_pages * PAGE_SIZE)
2121 return i386_btop(vtophys(mtr->bigbuf) + offset);