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 $
36 8/23/95 On advice from Stefan Esser, added volatile to PCI
37 memory pointers to remove PCI caching .
38 8/29/95 Fixes suggested by Bruce Evans.
39 meteor_mmap should return -1 on error rather than 0.
40 unit # > NMETEOR should be unit # >= NMETEOR.
41 10/24/95 Turn 50 Hz processing for SECAM and 60 Hz processing
43 11/11/95 Change UV from always begin signed to ioctl selected
44 to either signed or unsigned.
45 12/07/95 Changed 7196 startup codes for 50 Hz as recommended
46 by Luigi Rizzo (luigi@iet.unipi.it)
47 12/08/95 Clear SECAM bit in PAL/NTSC and set input field count
48 bits for 50 Hz mode (PAL/SECAM) before I was setting the
49 output count bits. by Luigi Rizzo (luigi@iet.unipi.it)
50 12/18/95 Correct odd DMA field (never exceed, but good for safety
51 Changed 7196 startup codes for 50 Hz as recommended
52 by Luigi Rizzo (luigi@iet.unipi.it)
53 12/19/95 Changed field toggle mode to enable (offset 0x3c)
54 recommended by luigi@iet.unipi.it
55 Added in prototyping, include file, staticizing,
56 and DEVFS changes from FreeBSD team.
57 Changed the default allocated pages from 151 (NTSC)
59 Cleaned up some old comments in iic_write().
60 Added a Field (even or odd) only capture mode to
61 eliminate the high frequency problems with compression
62 algorithms. Recommended by luigi@iet.unipi.it.
63 Changed geometry ioctl so if it couldn't allocated a
64 large enough contiguous space, it wouldn't free the
66 Added new mode called YUV_422 which delivers the
67 data in planer Y followed by U followed by V. This
68 differs from the standard YUV_PACKED mode in that
69 the chrominance (UV) data is in the correct (different)
70 order. This is for programs like vic and mpeg_encode
71 so they don't have to reorder the chrominance data.
72 Added field count to stats.
73 Increment frame count stat if capturing continuous on
75 Added my email address to these comments
76 (james@cs.uwm.edu) suggested by (luigi@iet.unipt.it :-).
77 Changed the user mode signal mechanism to allow the
78 user program to be interrupted at the end of a frame
79 in any one of the modes. Added SSIGNAL ioctl.
80 Added a SFPS/GFPS ioctl so one may set the frames per
81 second that the card catpures. This code needs to be
83 Changed the interrupt routine so synchronous capture
84 will work on fields or frames and the starting frame
85 can be either even or odd.
86 Added HALT_N_FRAMES and CONT_N_FRAMES so one could
87 stop and continue synchronous capture mode.
88 Change the tsleep/wakeup function to wait on mtr
89 rather than &read_intr_wait.
90 1/22/96 Add option (METEOR_FreeBSD_210) for FreeBSD 2.1
92 Changed intr so it only printed errors every 50 times.
93 Added unit number to error messages.
94 Added get_meteor_mem and enabled range checking.
95 1/30/96 Added prelim test stuff for direct video dma transfers
96 from Amancio Hasty (hasty@rah.star-gate.com). Until
97 we get some stuff sorted out, this will be ifdef'ed
98 with METEOR_DIRECT_VIDEO. This is very dangerous to
99 use at present since we don't check the address that
100 is passed by the user!!!!!
101 2/26/96 Added special SVIDEO input device type.
102 2/27/96 Added meteor_reg.h file and associate types Converted
103 meteor.c over to using meteor.h file. Prompted by
104 Lars Jonas Olsson <ljo@po.cwru.edu>.
105 2/28/96 Added meteor RGB code from Lars Jonas Olsson
106 <ljo@po.cwru.edu>. I make some mods to this code, so
107 I hope it still works as I don't have an rgb card to
109 2/29/96 <ljo@po.cwru.edu> tested the meteor RGB and supplied
110 me with diffs. Thanks, we now have a working RGB
111 version of the driver. Still need to clean up this
113 3/1/96 Fixed a nasty little bug that was clearing the VTR
114 mode bit when the 7196 status was requested.
115 3/15/96 Fixed bug introduced in previous version that
116 stopped the only fields mode from working.
117 Added METEOR{GS}TS ioctl, still needs work.
118 3/25/96 Added YUV_9 and YUV_12 modes. Cleaned up some of the
119 code and converted variables to use the new register
121 4/8/96 Fixed the a bug in with the range enable. Pointed
123 5/13/96 Fix the FPS ioctl so it actually sets the frames
124 per second. Code supplied by ian@robots.ox.ac.uk.
125 The new code implements a new define:
126 METEOR_SYSTEM_DEFAULT which should be defined as
127 METEOR_PAL, METEOR_SECAM, or METEOR_NTSC in your system
128 configuration file. If METEOR_SYSTEM_DEFAULT isn't
129 defined, and there is not a signal when set_fps is
130 called, then the call has no effect.
131 Changed the spelling of PLANER to PLANAR as pointed
132 out by Paco Hope <paco@cs.virigina.edu> and define
133 PLANER to be PLANAR for backward compatibility.
134 5/28/95 METEOR_INPUT_DEV_RCA -> METEOR_INPUT_DEV0, not
135 METEOR_GEO_DEV0. Pointed out by Ian Reid,
136 <ian@robots.ox.ac.uk>.
137 METEOR_DEV_MASK should be 0x0000f000 and not
138 0x2000f000, otherwise METEOR_RGB gets masked
139 out. Pointed out by Ian Reid.
140 Changed the fps code to give even distribution for
141 low frame rates. Code supplied by Ian Reid.
142 Fix some problems with the RGB version. Patch supplied
143 by <ljo@po.cwru.edu>.
144 Added METEOR_FIELD_MODE to include files for a
145 future version of this driver.
148 #include "use_meteor.h"
149 #include "opt_meteor.h"
151 #include <sys/param.h>
152 #include <sys/systm.h>
153 #include <sys/conf.h>
154 #include <sys/device.h>
155 #include <sys/kernel.h>
156 #include <sys/signalvar.h>
157 #include <sys/mman.h>
160 #if defined(METEOR_FreeBSD_210)
161 #include <machine/cpu.h> /* bootverbose */
165 #include <vm/vm_kern.h>
167 #include <vm/vm_extern.h>
169 #include <bus/pci/pcivar.h>
170 #include <bus/pci/pcireg.h>
171 #include <dev/video/meteor/ioctl_meteor.h>
172 #include <dev/video/meteor/meteor_reg.h>
175 static void meteor_intr (void *arg);
178 * Allocate enough memory for:
179 * 768x576 RGB 16 or YUV (16 storage bits/pixel) = 884736 = 216 pages
181 * You may override this using the options "METEOR_ALLOC_PAGES=value" in your
182 * kernel configuration file.
184 #ifndef METEOR_ALLOC_PAGES
185 #define METEOR_ALLOC_PAGES 217
187 #define METEOR_ALLOC (METEOR_ALLOC_PAGES * PAGE_SIZE)
189 static meteor_reg_t meteor[NMETEOR];
190 #define METEOR_NUM(mtr) ((mtr - &meteor[0])/sizeof(meteor_reg_t))
192 #define METPRI PCATCH
194 static const char* met_probe (pcici_t tag, pcidi_t type);
195 static void met_attach(pcici_t tag, int unit);
196 static u_long met_count;
198 static struct pci_device met_device = {
205 COMPAT_PCI_DRIVER (meteor, met_device);
207 #if defined(METEOR_FreeBSD_210) /* XXX */
208 d_open_t meteor_open;
209 d_close_t meteor_close;
210 d_read_t meteor_read;
211 d_write_t meteor_write;
212 d_ioctl_t meteor_ioctl;
213 d_mmap_t meteor_mmap;
215 static d_open_t meteor_open;
216 static d_close_t meteor_close;
217 static d_read_t meteor_read;
218 static d_write_t meteor_write;
219 static d_ioctl_t meteor_ioctl;
220 static d_mmap_t meteor_mmap;
222 static struct dev_ops meteor_ops = {
224 .d_open = meteor_open,
225 .d_close = meteor_close,
226 .d_read = meteor_read,
227 .d_write = meteor_write,
228 .d_ioctl = meteor_ioctl,
229 .d_mmap = meteor_mmap,
233 static mreg_t saa7116_pci_default[sizeof(struct saa7116_regs)/sizeof(mreg_t)]={
234 /* PCI Memory registers */
235 /* BITS Type Description */
236 /* 0x00 */ 0x00000000, /* 31:1 e*RW DMA 1 (Even)
238 /* 0x04 */ 0x00000000, /* 31:2 e*RW DMA 2 (Even)
240 /* 0x08 */ 0x00000000, /* 31:2 e*RW DMA 3 (Even)
242 /* 0x0c */ 0x00000000, /* 31:1 o*RW DMA 1 (Odd)
244 /* 0x10 */ 0x00000000, /* 31:2 o*RW DMA 2 (Odd)
246 /* 0x14 */ 0x00000000, /* 31:2 o*RW DMA 3 (Odd)
248 /* 0x18 */ 0x00000500, /* 15:2 e*RW Stride 1 (Even)
250 /* 0x1c */ 0x00000000, /* 15:2 e*RW Stride 2 (Even)
252 /* 0x20 */ 0x00000000, /* 15:2 e*RW Stride 3 (Even)
254 /* 0x24 */ 0x00000500, /* 15:2 o*RW Stride 1 (Odd)
256 /* 0x28 */ 0x00000000, /* 15:2 o*RW Stride 2 (Odd)
258 /* 0x2c */ 0x00000000, /* 15:2 o*RW Stride 3 (Odd)
260 /* 0x30 */ 0xeeeeee01, /* 31:8 *RW Route (Even)
261 7:0 *RW Mode (Even) */
262 /* 0x34 */ 0xeeeeee01, /* 31:8 *RW Route (Odd)
263 7:0 *RW Mode (Odd) */
264 /* 0x38 */ 0x00200020, /* 22:16 *RW FIFO Trigger Planer Mode,
265 6:0 *RW FIFO Trigger Packed Mode */
266 /* 0x3c */ 0x00000107, /* 9:8 *RW Reserved (0x0)
269 0 *RW Reserved (0x1) */
270 /* 0x40 */ 0x000000c0, /* 15 *RW Range Enable
271 14 *RW Corrupt Disable
272 11 *RR Address Error (Odd)
273 10 *RR Address Error (Even)
274 9 *RR Field Corrupt (Odd)
275 8 *RR Field Corrupt (Even)
278 5 *RR Field Done (Odd)
279 4 *RR Field Done (Even)
280 3 *RS Single Field Capture (Odd)
281 2 *RS Single Field Capture (Even)
282 1 *RW Capture (ODD) Continous
283 0 *RW Capture (Even) Continous */
284 /* 0x44 */ 0x00000000, /* 7:0 *RW Retry Wait Counter */
285 /* 0x48 */ 0x00000307, /* 10 *RW Interrupt mask, start of field
286 9 *RW Interrupt mask, end odd field
287 8 *RW Interrupt mask, end even field
288 2 *RR Interrupt status, start of field
289 1 *RR Interrupt status, end of odd
290 0 *RR Interrupt status, end of even */
291 /* 0x4c */ 0x00000001, /* 31:0 *RW Field Mask (Even) continous */
292 /* 0x50 */ 0x00000001, /* 31:0 *RW Field Mask (Odd) continous */
293 /* 0x54 */ 0x00000000, /* 20:16 *RW Mask Length (Odd)
294 4:0 *RW Mask Length (Even) */
295 /* 0x58 */ 0x0005007c, /* 22:16 *RW FIFO almost empty
296 6:0 *RW FIFO almost full */
297 /* 0x5c */ 0x461e1e0f, /* 31:24 *RW I2C Phase 4
298 23:16 *RW I2C Phase 3
300 7:0 *RW I2C Phase 1 */
301 /* 0x60 */ 0x00000300, /* 31:24 *RO I2C Read Data
302 23:16 **RW I2C Auto Address
305 9 RR I2C Direct Abort
310 0 RW I2C Auto Enable */
311 /* 0x64 */ 0x00000000, /* 24 RS I2C New Cycle
312 23:16 **RW I2C Direct Address
313 15:8 **RW I2C Direct Sub-address
314 7:0 **RW I2C Direct Write Address */
315 /* 0x68 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 1 (Even)
316 23:16 **RW I2C Auto Data 1 (Even)
317 15:8 **RW I2C Auto Sub-address 0 (Even)
318 7:0 **RW I2C Auto Data 0 (Even) */
319 /* 0x6c */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 3 (Even)
320 23:16 **RW I2C Auto Data 3 (Even)
321 15:8 **RW I2C Auto Sub-address 2 (Even)
322 7:0 **RW I2C Auto Data 2 (Even) */
323 /* 0x70 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 5 (Even)
324 23:16 **RW I2C Auto Data 5 (Even)
325 15:8 **RW I2C Auto Sub-address 4 (Even)
326 7:0 **RW I2C Auto Data 4 (Even) */
327 /* 0x74 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 7 (Even)
328 23:16 **RW I2C Auto Data 7 (Even)
329 15:8 **RW I2C Auto Sub-address 6 (Even)
330 7:0 **RW I2C Auto Data 6 (Even) */
331 /* 0x78 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 1 (Odd)
332 23:16 **RW I2C Auto Data 1 (Odd)
333 15:8 **RW I2C Auto Sub-address 0 (Odd)
334 7:0 **RW I2C Auto Data 0 (Odd) */
335 /* 0x7c */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 3 (Odd)
336 23:16 **RW I2C Auto Data 3 (Odd)
337 15:8 **RW I2C Auto Sub-address 2 (Odd)
338 7:0 **RW I2C Auto Data 2 (Odd) */
339 /* 0x80 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 5 (Odd)
340 23:16 **RW I2C Auto Data 5 (Odd)
341 15:8 **RW I2C Auto Sub-address 4 (Odd)
342 7:0 **RW I2C Auto Data 4 (Odd) */
343 /* 0x84 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 7 (Odd)
344 23:16 **RW I2C Auto Data 7 (Odd)
345 15:8 **RW I2C Auto Sub-address 6 (Odd)
346 7:0 **RW I2C Auto Data 6 (Odd) */
347 /* 0x88 */ 0x00000000, /* 23:16 **RW I2C Register Enable (Odd)
348 7:0 **RW I2C Register Enable (Even) */
349 /* 0x8c */ 0x00000000, /* 23:2 e*RW DMA End (Even)
351 /* 0x90 */ 0x00000000 /* 23:2 e*RW DMA End (Odd)
355 static u_char saa7196_i2c_default[NUM_SAA7196_I2C_REGS] = {
356 /* SAA7196 I2C bus control */
358 /* 00 */ 0x50, /* 7:0 Increment Delay */
359 /* 01 */ 0x30, /* 7:0 Horizontal Sync Begin for 50hz */
360 /* 02 */ 0x00, /* 7:0 Horizontal Sync Stop for 50hz */
361 /* 03 */ 0xe8, /* 7:0 Horizontal Sync Clamp Start for 50hz */
362 /* 04 */ 0xb6, /* 7:0 Horizontal Sync Clamp Stop for 50hz */
363 /* 05 */ 0xf4, /* 7:0 Horizontal Sync Start after PH1 for 50hz */
364 /* 06 */ 0x46, /* 7 Input mode =0 CVBS, =1 S-Video
366 5:4 Aperture Bandpass characteristics
367 3:2 Coring range for high freq
368 1:0 Aperture bandpass filter weights */
369 /* 07 */ 0x00, /* 7:0 Hue */
370 /* 08 */ 0x7f, /* 7:3 Colour-killer threshold QAM (PAL, NTSC) */
371 /* 09 */ 0x7f, /* 7:3 Colour-killer threshold SECAM */
372 /* 0a */ 0x7f, /* 7:0 PAL switch sensitivity */
373 /* 0b */ 0x7f, /* 7:0 SECAM switch sensitivity */
374 /* 0c */ 0x40, /* 7 Colour-on bit
376 /* 0d */ 0x84, /* 7 VTR/TV mode bit = 1->VTR mode
377 3 Realtime output mode select bit
378 2 HREF position select
381 /* 0e */ 0x38, /* 7 Horizontal clock PLL
382 5 Select interal/external clock source
383 4 Output enable of Horizontal/Vertical sync
384 3 Data output YUV enable
388 /* 0f */ 0x50, /* 7 Automatic Field detection
389 6 Field Select 0 = 50hz, 1=60hz
390 5 SECAM cross-colour reduction
391 4 Enable sync and clamping pulse
392 3:1 Luminance delay compensation */
393 /* 10 */ 0x00, /* 2 Select HREF Position
394 1:0 Vertical noise reduction */
395 /* 11 */ 0x2c, /* 7:0 Chrominance gain conrtol for QAM */
396 /* 12 */ 0x40, /* 7:0 Chrominance saturation control for VRAM port */
397 /* 13 */ 0x40, /* 7:0 Luminance contract control for VRAM port */
398 /* 14 */ 0x34, /* 7:0 Horizontal sync begin for 60hz */
400 /* 15 */ 0x0c, /* 7:0 Horizontal sync stop for 60hz */
401 /* 16 */ 0xfb, /* 7:0 Horizontal clamp begin for 60hz */
402 /* 17 */ 0xd4, /* 7:0 Horizontal clamp stop for 60hz */
403 /* 18 */ 0xec, /* 7:0 Horizontal sync start after PH1 for 60hz */
405 0x0a, 0xf4, 0xce, 0xf4,
407 /* 19 */ 0x80, /* 7:0 Luminance brightness control for VRAM port */
414 /* 20 */ 0x90, /* 7 ROM table bypass switch
415 6:5 Set output field mode
416 4 VRAM port outputs enable
417 3:2 First pixel position in VRO data
418 1:0 FIFO output register select */
419 /* 21 */ 0x80, /* 7:0 [7:0] Pixel number per line on output */
420 /* 22 */ 0x80, /* 7:0 [7:0] Pixel number per line on input */
421 /* 23 */ 0x03, /* 7:0 [7:0] Horizontal start position of scaling win*/
422 /* 24 */ 0x8a, /* 7:5 Horizontal decimation filter
423 4 [8] Horizontal start position of scaling win
424 3:2 [9:8] Pixel number per line on input
425 1:0 [9:8] Pixel number per line on output */
426 /* 25 */ 0xf0, /* 7:0 [7:0] Line number per output field */
427 /* 26 */ 0xf0, /* 7:0 [7:0] Line number per input field */
428 /* 27 */ 0x0f, /* 7:0 [7:0] Vertical start of scaling window */
429 /* 28 */ 0x80, /* 7 Adaptive filter switch
430 6:5 Vertical luminance data processing
431 4 [8] Vertical start of scaling window
432 3:2 [9:8] Line number per input field
433 1:0 [9:8] Line number per output field */
434 /* 29 */ 0x16, /* 7:0 [7:0] Vertical bypass start */
435 /* 2a */ 0x00, /* 7:0 [7:0] Vertical bypass count */
436 /* 2b */ 0x00, /* 4 [8] Vertical bypass start
437 2 [8] Vertical bypass count
438 0 Polarity, internally detected odd even flag */
439 /* 2c */ 0x80, /* 7:0 Set lower limit V for colour-keying */
440 /* 2d */ 0x7f, /* 7:0 Set upper limit V for colour-keying */
441 /* 2e */ 0x80, /* 7:0 Set lower limit U for colour-keying */
442 /* 2f */ 0x7f, /* 7:0 Set upper limit U for colour-keying */
443 /* 30 */ 0xbf /* 7 VRAM bus output format
444 6 Adaptive geometrical filter
445 5 Luminance limiting value
446 4 Monochrome and two's complement output data sel
447 3 Line quailifier flag
448 2 Pixel qualifier flag
449 1 Transparent data transfer
450 0 Extended formats enable bit */
453 static u_char bt254_default[NUM_BT254_REGS] = {
465 * Returns 0 Succesful completion.
466 * Returns 1 If transfer aborted or timeout occured.
469 static int i2c_print_err = 1;
471 i2c_write(meteor_reg_t * mtr, u_char slave, u_char rw, u_char reg, u_char data)
473 unsigned long wait_counter = 0x0001ffff;
474 mreg_t * iic_write_loc = &mtr->base->i2c_write;
478 /* Write the data the the i2c write register */
479 *iic_write_loc = SAA7116_IIC_NEW_CYCLE |
480 (((u_long)slave|(u_long)rw) << 16) |
481 ((u_long)reg << 8) | (u_long)data;
483 /* Wait until the i2c cycle is compeleted */
484 while((*iic_write_loc & SAA7116_IIC_NEW_CYCLE)) {
485 if(!wait_counter) break;
489 /* 1ffff should be enough delay time for the i2c cycle to complete */
492 kprintf("meteor%d: %d i2c %s transfer timeout 0x%x",
493 METEOR_NUM(mtr), slave,
494 rw ? "read" : "write", *iic_write_loc);
499 /* Check for error on direct write, clear if any */
500 if(mtr->base->i2c_read & SAA7116_IIC_DIRECT_TRANSFER_ABORTED){
501 mtr->base->i2c_read |= SAA7116_IIC_DIRECT_TRANSFER_ABORTED;
503 kprintf("meteor%d: 0x%x i2c %s transfer aborted",
504 METEOR_NUM(mtr), slave,
505 rw ? "read" : "write" );
511 kprintf(" - reg=0x%x, value=0x%x.\n", reg, data);
519 met_probe (pcici_t tag, pcidi_t type)
522 case SAA7116_PHILIPS_ID: /* meteor */
523 return("Philips SAA 7116");
528 /* interrupt handling routine
529 complete meteor_read() if using interrupts
532 meteor_intr(void *arg)
534 meteor_reg_t *mtr = (meteor_reg_t *) arg;
535 mreg_t *cap = &mtr->base->cap_cntl,
536 *base = &mtr->base->dma1e,
537 *stat = &mtr->base->irq_stat;
538 u_long status = *stat,
539 cap_err = *cap & 0x00000f00,
540 #ifdef METEOR_CHECK_PCI_BUS
541 pci_err = pci_conf_read(mtr->tag,
542 PCI_COMMAND_STATUS_REG),
544 next_base = (u_long)(vtophys(mtr->bigbuf));
547 * Disable future interrupts if a capture mode is not selected.
548 * This can happen when we are in the process of closing or
549 * changing capture modes, otherwise it shouldn't happen.
551 if(!(mtr->flags & METEOR_CAP_MASK)) {
552 *cap &= 0x8ff0; /* disable future interrupts */
554 #ifdef METEOR_CHECK_PCI_BUS
556 * Check for pci bus errors.
558 #define METEOR_MASTER_ABORT 0x20000000
559 #define METEOR_TARGET_ABORT 0x10000000
560 if(pci_err & METEOR_MASTER_ABORT) {
561 kprintf("meteor%d: intr: pci bus master dma abort: 0x%x 0x%x.\n",
562 METEOR_NUM(mtr), *base, *(base+3));
563 pci_conf_write(mtr->tag, PCI_COMMAND_STATUS_REG, pci_err);
565 if(pci_err & METEOR_TARGET_ABORT) {
566 kprintf("meteor%d: intr: pci bus target dma abort: 0x%x 0x%x.\n",
567 METEOR_NUM(mtr), *base, *(base+3));
568 pci_conf_write(mtr->tag, PCI_COMMAND_STATUS_REG, pci_err);
575 if (cap_err & 0x300) {
576 if(mtr->fifo_errors % 50 == 0) {
577 kprintf("meteor%d: capture error", METEOR_NUM(mtr));
578 kprintf(": %s FIFO overflow.\n",
579 cap_err&0x0100? "even" : "odd");
581 mtr->fifo_errors++ ; /* increment fifo capture errors cnt */
583 if (cap_err & 0xc00) {
584 if(mtr->dma_errors % 50 == 0) {
585 kprintf("meteor%d: capture error", METEOR_NUM(mtr));
586 kprintf(": %s DMA address.\n",
587 cap_err&0x0400? "even" : "odd");
589 mtr->dma_errors++ ; /* increment DMA capture errors cnt */
592 *cap |= 0x0f30; /* clear error and field done */
595 * In synchronous capture mode we need to know what the address
596 * offset for the next field/frame will be. next_base holds the
597 * value for the even dma buffers (for odd, one must add stride).
599 if((mtr->flags & METEOR_SYNCAP) && !mtr->synch_wait &&
600 (mtr->current < mtr->frames)) { /* could be !=, but < is safer */
601 /* next_base is initialized to mtr->bigbuf */
602 next_base += mtr->frame_size * mtr->current;
603 if(mtr->flags & METEOR_WANT_TS)
604 next_base += sizeof(struct timeval) * mtr->current;
608 * Count the field and clear the field flag.
610 * In single mode capture, clear the continuous capture mode.
612 * In synchronous capture mode, if we have room for another field,
613 * adjust DMA buffer pointers.
614 * When we are above the hi water mark (hiwat), mtr->synch_wait will
615 * be set and we will not bump the DMA buffer pointers. Thus, once
616 * we reach the hi water mark, the driver acts like a continuous mode
617 * capture on the mtr->current frame until we hit the low water
618 * mark (lowat). The user had the option of stopping or halting
619 * the capture if this is not the desired effect.
621 if (status & 0x1) { /* even field */
622 mtr->even_fields_captured++;
623 mtr->flags &= ~METEOR_WANT_EVEN;
624 if((mtr->flags & METEOR_SYNCAP) && !mtr->synch_wait) {
626 /* XXX should add adjustments for YUV_422 & PLANAR */
629 * If the user requested to be notified via signal,
630 * let them know the field is complete.
632 if(mtr->proc && (mtr->signal & METEOR_SIG_MODE_MASK))
633 ksignal(mtr->proc, mtr->signal&(~METEOR_SIG_MODE_MASK));
635 if (status & 0x2) { /* odd field */
636 mtr->odd_fields_captured++;
637 mtr->flags &= ~METEOR_WANT_ODD;
638 if((mtr->flags & METEOR_SYNCAP) && !mtr->synch_wait) {
639 *(base+3) = next_base + *(base+6);
640 /* XXX should add adjustments for YUV_422 & PLANAR */
643 * If the user requested to be notified via signal,
644 * let them know the field is complete.
646 if(mtr->proc && (mtr->signal & METEOR_SIG_MODE_MASK))
647 ksignal(mtr->proc, mtr->signal&(~METEOR_SIG_MODE_MASK));
651 * If we have a complete frame.
653 if(!(mtr->flags & METEOR_WANT_MASK)) {
654 mtr->frames_captured++;
656 * post the completion time.
658 if(mtr->flags & METEOR_WANT_TS) {
661 if(mtr->alloc_pages * PAGE_SIZE <= (mtr->frame_size +
662 sizeof(struct timeval))) {
663 ts =(struct timeval *)mtr->bigbuf +
665 /* doesn't work in synch mode except for first frame */
671 * Wake up the user in single capture mode.
673 if(mtr->flags & METEOR_SINGLE)
674 wakeup((caddr_t)mtr);
676 * If the user requested to be notified via signal,
677 * let them know the frame is complete.
679 if(mtr->proc && !(mtr->signal & METEOR_SIG_MODE_MASK))
680 ksignal(mtr->proc, mtr->signal&(~METEOR_SIG_MODE_MASK));
682 * Reset the want flags if in continuous or
683 * synchronous capture mode.
685 if(mtr->flags & (METEOR_CONTIN|METEOR_SYNCAP)) {
686 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
687 case METEOR_ONLY_ODD_FIELDS:
688 mtr->flags |= METEOR_WANT_ODD;
690 case METEOR_ONLY_EVEN_FIELDS:
691 mtr->flags |= METEOR_WANT_EVEN;
694 mtr->flags |= METEOR_WANT_MASK;
699 * Special handling for synchronous capture mode.
701 if(mtr->flags & METEOR_SYNCAP) {
702 struct meteor_mem *mm = mtr->mem;
704 * Mark the current frame as active. It is up to
705 * the user to clear this, but we will clear it
706 * for the user for the current frame being captured
707 * if we are within the water marks (see below).
709 mm->active |= 1 << (mtr->current - 1);
712 * Since the user can muck with these values, we need
713 * to check and see if they are sane. If they don't
714 * pass the sanity check, disable the capture mode.
715 * This is rather rude, but then so was the user.
717 * Do we really need all of this or should we just
718 * eliminate the possiblity of allowing the
719 * user to change hi and lo water marks while it
722 if(mm->num_active_bufs < 0 ||
723 mm->num_active_bufs > mtr->frames ||
724 mm->lowat < 1 || mm->lowat >= mtr->frames ||
725 mm->hiwat < 1 || mm->hiwat >= mtr->frames ||
726 mm->lowat > mm->hiwat ) {
728 mtr->flags &= ~(METEOR_SYNCAP|METEOR_WANT_MASK);
731 * Ok, they are sane, now we want to
732 * check the water marks.
734 if(mm->num_active_bufs <= mm->lowat)
736 if(mm->num_active_bufs >= mm->hiwat)
739 * Clear the active frame bit for this frame
740 * and advance the counters if we are within
741 * the banks of the water marks.
743 if(!mtr->synch_wait) {
744 mm->active &= ~(1 << mtr->current);
746 if(mtr->current > mtr->frames)
748 mm->num_active_bufs++;
754 *stat |= 0x7; /* clear interrupt status */
759 set_fps(meteor_reg_t *mtr, u_short fps)
761 struct saa7116_regs *s7116 = mtr->base;
763 unsigned maxfps, mask = 0x1, length = 0;
765 SAA7196_WRITE(mtr, SAA7196_STDC, SAA7196_REG(mtr, SAA7196_STDC) | 0x02);
767 status = (s7116->i2c_read & 0xff000000L) >> 24;
770 * Determine if there is an input signal. Depending on the
771 * frequency we either have a max of 25 fps (50 hz) or 30 fps (60 hz).
772 * If there is no input signal, then we need some defaults. If the
773 * user neglected to specify any defaults, just set to the fps to max.
775 if((status & 0x40) == 0) { /* Is there a signal ? */
777 maxfps = 30; /* 60 hz system */
779 maxfps = 25; /* 50 hz system */
781 } else { /* We have no signal, check defaults */
782 #if METEOR_SYSTEM_DEFAULT == METEOR_PAL || METEOR_SYSTEM_DEFAULT == METEOR_SECAM
784 #elif METEOR_SYSTEM_DEFAULT == METEOR_NTSC
787 /* Don't really know what to do, just set max */
794 * A little sanity checking...
797 if(fps > maxfps) fps = maxfps;
800 * Compute the mask/length using the fps.
805 } else if ((float)fps == maxfps/2.0) {
808 } else if (fps > maxfps/2) {
811 mask = (1<<maxfps) - 1;
813 step = (float)(maxfps - 1)/(float)(maxfps - fps);
814 for(b=step; b < maxfps; b += step) {
815 mask &= ~(1<<((int)b)); /* mask out the bth frame */
817 } else { /* fps < maxfps/2 */
822 step = (float)(maxfps -1)/(float)(fps);
823 for(b = step + 1; b < maxfps - 1; b += step) {
824 mask |= (1<<((int)b)); /* mask in the bth frame */
831 s7116->fme = s7116->fmo = mask;
832 s7116->fml = (length << 16) | length;
841 * There is also a problem with range checking on the 7116.
842 * It seems to only work for 22 bits, so the max size we can allocate
843 * is 22 bits long or 4194304 bytes assuming that we put the beginning
844 * of the buffer on a 2^24 bit boundary. The range registers will use
845 * the top 8 bits of the dma start registers along with the bottom 22
846 * bits of the range register to determine if we go out of range.
847 * This makes getting memory a real kludge.
850 #define RANGE_BOUNDARY (1<<22)
852 get_meteor_mem(int unit, unsigned size)
854 vm_offset_t addr = 0;
856 addr = vm_page_alloc_contig(size, 0, 0xffffffff, 1<<24);
858 addr = vm_page_alloc_contig(size, 0, 0xffffffff, PAGE_SIZE);
860 kprintf("meteor%d: Unable to allocate %d bytes of memory.\n",
868 bt254_write(meteor_reg_t *mtr, u_char addr, u_char data)
870 addr &= 0x7; /* sanity? */
871 mtr->bt254_reg[addr] = data;
872 PCF8574_DATA_WRITE(mtr, data); /* set data */
873 PCF8574_CTRL_WRITE(mtr, (PCF8574_CTRL_REG(mtr) & ~0x7) | addr);
874 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) & ~0x10); /* WR/ to 0 */
875 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x10); /* WR to 1 */
876 PCF8574_DATA_WRITE(mtr, 0xff); /* clr data */
881 bt254_init(meteor_reg_t *mtr)
885 PCF8574_CTRL_WRITE(mtr, 0x7f);
886 PCF8574_DATA_WRITE(mtr, 0xff); /* data port must be 0xff */
887 PCF8574_CTRL_WRITE(mtr, 0x7f);
889 /* init RGB module for 24bpp, composite input */
890 for(i=0; i<NUM_BT254_REGS; i++)
891 bt254_write(mtr, i, bt254_default[i]);
893 bt254_write(mtr, BT254_COMMAND, 0x00); /* 24 bpp */
897 bt254_ntsc(meteor_reg_t *mtr, int arg)
901 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x20);
905 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) &= ~0x20);
910 select_bt254(meteor_reg_t *mtr)
912 /* disable saa7196, saaen = 1 */
913 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x80);
914 /* enable Bt254, bten = 0 */
915 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) & ~0x40);
919 select_saa7196(meteor_reg_t *mtr)
921 /* disable Bt254, bten = 1 */
922 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x40);
923 /* enable saa7196, saaen = 0 */
924 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) & ~0x80);
928 * Initialize the 7116, 7196 and the RGB module.
931 meteor_init ( meteor_reg_t *mtr )
937 * Initialize the Philips SAA7116
939 mtr->base->cap_cntl = 0x00000040L;
940 vbase_addr = &mtr->base->dma1e;
941 for (i = 0 ; i < (sizeof(struct saa7116_regs)/sizeof(mreg_t)); i++)
942 *vbase_addr++ = saa7116_pci_default[i];
945 * Check for the Philips SAA7196
948 if(i2c_write(mtr, SAA7196_I2C_ADDR, SAA7116_I2C_WRITE, 0, 0xff) == 0) {
953 for (i = 0; i < NUM_SAA7196_I2C_REGS; i++)
954 SAA7196_WRITE(mtr, i, saa7196_i2c_default[i]);
956 * Get version number.
958 SAA7196_WRITE(mtr, SAA7196_STDC,
959 SAA7196_REG(mtr, SAA7196_STDC) & ~0x02);
961 kprintf("meteor%d: <Philips SAA 7196> rev 0x%x\n",
963 (unsigned)((mtr->base->i2c_read & 0xff000000L) >> 28));
966 kprintf("meteor%d: <Philips SAA 7196 NOT FOUND>\n",
970 * Check for RGB module, initialized if found.
973 if(i2c_write(mtr,PCF8574_DATA_I2C_ADDR,SAA7116_I2C_WRITE,0,0xff) == 0) {
975 kprintf("meteor%d: <Booktree 254 (RGB module)>\n",
976 METEOR_NUM(mtr)); /* does this have a rev #? */
977 bt254_init(mtr); /* Set up RGB module */
978 mtr->flags = METEOR_RGB;
989 met_attach(pcici_t tag, int unit)
992 u_long old_irq, new_irq;
993 #endif /* METEOR_IRQ */
998 if (unit >= NMETEOR) {
999 kprintf("meteor%d: attach: only %d units configured.\n",
1001 kprintf("meteor%d: attach: invalid unit number.\n", unit);
1006 * Check for Meteor/PPB (PCI-PCI Bridge)
1007 * Reprogram IBM Bridge if detected.
1008 * New Meteor cards have an IBM PCI-PCI bridge, creating a secondary
1009 * PCI bus. The SAA chip is connected to this secondary bus.
1012 /* If we are not on PCI Bus 0, check for the Bridge */
1013 if ( pci_get_bus_from_tag( tag ) != 0) {
1016 /* get tag of parent bridge */
1017 bridge_tag = pci_get_parent_from_tag( tag );
1019 /* Look for IBM 82351, 82352 or 82353 */
1020 if (pci_conf_read(bridge_tag, PCI_ID_REG) == 0x00221014) {
1023 kprintf("meteor%d: PPB device detected, reprogramming IBM bridge.\n", unit);
1026 pci_cfgwrite(bridge_tag, 0x05, 0x00, 1);
1028 pci_cfgwrite(bridge_tag, 0x0d, 0x20, 1);
1029 /* write posting enable, prefetch enabled --> GRAB direction */
1030 pci_cfgwrite(bridge_tag, 0x42, 0x14, 1);
1031 /* set PRTR Primary retry timer register */
1032 pci_cfgwrite(bridge_tag, 0x4c, 0x10, 1);
1036 mtr = &meteor[unit];
1038 pci_map_mem(tag, PCI_MAP_REG_START, (vm_offset_t *)&mtr->base,
1041 #ifdef METEOR_IRQ /* from the configuration file */
1042 old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
1043 pci_conf_write(tag, PCI_INTERRUPT_REG, METEOR_IRQ);
1044 new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
1045 kprintf("meteor%d: attach: irq changed from %d to %d\n",
1046 unit, (old_irq & 0xff), (new_irq & 0xff));
1047 #endif /* METEOR_IRQ */
1048 /* setup the interrupt handling routine */
1049 pci_map_int(tag, meteor_intr, (void*) mtr);
1052 * PCI latency timer. 32 is a good value for 4 bus mastering slots, if
1053 * you have more than for, then 16 would probably be a better value.
1056 #ifndef METEOR_DEF_LATENCY_VALUE
1057 #define METEOR_DEF_LATENCY_VALUE 32
1059 latency = pci_conf_read(tag, PCI_LATENCY_TIMER);
1060 latency = (latency >> 8) & 0xff;
1063 kprintf("meteor%d: PCI bus latency is", unit);
1065 kprintf("meteor%d: PCI bus latency was 0 changing to",
1069 latency = METEOR_DEF_LATENCY_VALUE;
1070 pci_conf_write(tag, PCI_LATENCY_TIMER, latency<<8);
1073 kprintf(" %lu.\n", latency);
1076 meteor_init(mtr); /* set up saa7116, saa7196, and rgb module */
1079 buf = get_meteor_mem(unit, METEOR_ALLOC);
1083 kprintf("meteor%d: buffer size %d, addr 0x%llx\n",
1084 unit, METEOR_ALLOC, vtophys(buf));
1088 mtr->alloc_pages = METEOR_ALLOC_PAGES;
1090 bzero((caddr_t) buf, METEOR_ALLOC);
1092 /* 640x480 RGB 16 */
1093 mtr->base->dma1e = buf;
1094 mtr->base->dma1o = buf + 0x500;
1095 mtr->base->dma_end_e =
1096 mtr->base->dma_end_o = buf + METEOR_ALLOC;
1098 /* 1 frame of 640x480 RGB 16 */
1101 mtr->depth = 2; /* two bytes per pixel */
1102 mtr->frames = 1; /* one frame */
1104 mtr->flags |= METEOR_INITALIZED | METEOR_AUTOMODE | METEOR_DEV0 |
1106 make_dev(&meteor_ops, unit, 0, 0, 0644, "meteor");
1109 #define UNIT(x) ((x) & 0x07)
1113 meteor_reset(cdev_t dev)
1115 int unit = UNIT(minor(dev));
1116 struct saa7116_regs *m;
1121 m = meteor[unit].base;
1124 tsleep((caddr_t)m, METPRI, "Mreset", hz/50);
1126 m->cap_cntl = 0x8ff0;
1127 m->cap_cntl = 0x80c0;
1128 m->cap_cntl = 0x8040;
1129 tsleep((caddr_t)m, METPRI, "Mreset", hz/10);
1130 m->cap_cntl = 0x80c0;
1137 /*---------------------------------------------------------
1139 ** Meteor character device driver routines
1141 **---------------------------------------------------------
1145 meteor_open(struct dev_open_args *ap)
1147 cdev_t dev = ap->a_head.a_dev;
1152 unit = UNIT(minor(dev));
1153 if (unit >= NMETEOR) /* unit out of range */
1156 mtr = &(meteor[unit]);
1158 if (!(mtr->flags & METEOR_INITALIZED)) /* device not found */
1161 if (mtr->flags & METEOR_OPEN) /* device is busy */
1164 mtr->flags |= METEOR_OPEN;
1166 * Make sure that the i2c regs are set the same for each open.
1168 for(i=0; i< NUM_SAA7196_I2C_REGS; i++) {
1169 SAA7196_WRITE(mtr, i, saa7196_i2c_default[i]);
1172 mtr->fifo_errors = 0;
1173 mtr->dma_errors = 0;
1174 mtr->frames_captured = 0;
1175 mtr->even_fields_captured = 0;
1176 mtr->odd_fields_captured = 0;
1179 #ifdef METEOR_TEST_VIDEO
1180 mtr->video.addr = 0;
1181 mtr->video.width = 0;
1182 mtr->video.banksize = 0;
1183 mtr->video.ramsize = 0;
1190 meteor_close(struct dev_close_args *ap)
1192 cdev_t dev = ap->a_head.a_dev;
1195 #ifdef METEOR_DEALLOC_ABOVE
1199 unit = UNIT(minor(dev));
1200 if (unit >= NMETEOR) /* unit out of range */
1203 mtr = &(meteor[unit]);
1204 mtr->flags &= ~METEOR_OPEN;
1206 if(mtr->flags & METEOR_SINGLE)
1207 /* this should not happen, the read capture
1208 should have completed or in the very least
1209 recieved a signal before close is called. */
1210 wakeup((caddr_t)mtr); /* continue read */
1212 * Turn off capture mode.
1214 mtr->base->cap_cntl = 0x8ff0;
1215 mtr->flags &= ~(METEOR_CAP_MASK|METEOR_WANT_MASK);
1218 #ifdef METEOR_DEALLOC_PAGES
1219 if (mtr->bigbuf != NULL) {
1220 kmem_free(&kernel_map, mtr->bigbuf,
1221 (mtr->alloc_pages * PAGE_SIZE));
1223 mtr->alloc_pages = 0;
1226 #ifdef METEOR_DEALLOC_ABOVE
1227 if (mtr->bigbuf != NULL && mtr->alloc_pages > METEOR_DEALLOC_ABOVE) {
1228 temp = METEOR_DEALLOC_ABOVE - mtr->alloc_pages;
1229 kmem_free(&kernel_map,
1230 mtr->bigbuf+((mtr->alloc_pages - temp) * PAGE_SIZE),
1231 (temp * PAGE_SIZE));
1232 mtr->alloc_pages = METEOR_DEALLOC_ABOVE;
1241 start_capture(meteor_reg_t *mtr, unsigned type)
1243 mreg_t *cap = &mtr->base->cap_cntl;
1246 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1247 case METEOR_ONLY_EVEN_FIELDS:
1248 mtr->flags |= METEOR_WANT_EVEN;
1249 if(type == METEOR_SINGLE)
1250 *cap = 0x0ff4 | mtr->range_enable;
1252 *cap = 0x0ff1 | mtr->range_enable;
1254 case METEOR_ONLY_ODD_FIELDS:
1255 mtr->flags |= METEOR_WANT_ODD;
1256 if(type == METEOR_SINGLE)
1257 *cap = 0x0ff8 | mtr->range_enable;
1259 *cap = 0x0ff2 | mtr->range_enable;
1262 mtr->flags |= METEOR_WANT_MASK;
1263 if(type == METEOR_SINGLE)
1264 *cap = 0x0ffc | mtr->range_enable;
1266 *cap = 0x0ff3 | mtr->range_enable;
1272 meteor_read(struct dev_read_args *ap)
1274 cdev_t dev = ap->a_head.a_dev;
1275 struct uio *uio = ap->a_uio;
1281 unit = UNIT(minor(dev));
1282 if (unit >= NMETEOR) /* unit out of range */
1285 mtr = &(meteor[unit]);
1286 if (mtr->bigbuf == 0)/* no frame buffer allocated (ioctl failed) */
1289 if (mtr->flags & METEOR_CAP_MASK)
1290 return(EIO); /* already capturing */
1292 count = mtr->rows * mtr->cols * mtr->depth;
1293 if (uio->uio_iov->iov_len < count)
1297 start_capture(mtr, METEOR_SINGLE);
1299 status=tsleep((caddr_t)mtr, METPRI, "capturing", 0);
1300 if (!status) /* successful capture */
1301 status = uiomove((caddr_t)mtr->bigbuf, count, uio);
1303 kprintf ("meteor%d: read: tsleep error %d\n", unit, status);
1305 mtr->flags &= ~(METEOR_SINGLE | METEOR_WANT_MASK);
1311 meteor_write(struct dev_write_args *ap)
1317 meteor_ioctl(struct dev_ioctl_args *ap)
1319 cdev_t dev = ap->a_head.a_dev;
1320 caddr_t data = ap->a_data;
1325 struct meteor_counts *cnt;
1326 struct meteor_geomet *geo;
1327 struct meteor_mem *mem;
1328 struct meteor_capframe *frame;
1329 #ifdef METEOR_TEST_VIDEO
1330 struct meteor_video *video;
1333 struct saa7116_regs *base;
1339 unit = UNIT(minor(dev));
1340 if (unit >= NMETEOR) /* unit out of range */
1343 mtr = &(meteor[unit]);
1346 switch (ap->a_cmd) {
1349 mtr->flags |= METEOR_WANT_TS;
1351 mtr->flags &= ~METEOR_WANT_TS;
1354 if(mtr->flags & METEOR_WANT_TS)
1359 #ifdef METEOR_TEST_VIDEO
1361 video = (struct meteor_video *)data;
1362 video->addr = mtr->video.addr;
1363 video->width = mtr->video.width;
1364 video->banksize = mtr->video.banksize;
1365 video->ramsize = mtr->video.ramsize;
1368 video = (struct meteor_video *)data;
1369 mtr->video.addr = video->addr;
1370 mtr->video.width = video->width;
1371 mtr->video.banksize = video->banksize;
1372 mtr->video.ramsize = video->ramsize;
1376 set_fps(mtr, *(u_short *)data);
1379 *(u_short *)data = mtr->fps;
1382 if (*(int *)data < 0 || *(int *)data > _SIG_MAXSIG)
1384 mtr->signal = *(int *) data;
1386 mtr->proc = curproc; /* might be NULL */
1392 *(int *)data = mtr->signal;
1394 case METEORSTATUS: /* get 7196 status */
1396 SAA7196_WRITE(mtr, SAA7196_STDC,
1397 SAA7196_REG(mtr, SAA7196_STDC) | 0x02);
1399 temp |= (base->i2c_read & 0xff000000L) >> 24;
1400 SAA7196_WRITE(mtr, SAA7196_STDC,
1401 SAA7196_REG(mtr, SAA7196_STDC) & ~0x02);
1403 temp |= (base->i2c_read & 0xff000000L) >> 16;
1404 *(u_short *)data = temp;
1406 case METEORSHUE: /* set hue */
1407 SAA7196_WRITE(mtr, SAA7196_HUEC, *(char *)data);
1409 case METEORGHUE: /* get hue */
1410 *(char *)data = SAA7196_REG(mtr, SAA7196_HUEC);
1412 case METEORSCHCV: /* set chrominance gain */
1413 SAA7196_WRITE(mtr, SAA7196_CGAINR, *(char *)data);
1415 case METEORGCHCV: /* get chrominance gain */
1416 *(char *)data = SAA7196_REG(mtr, SAA7196_CGAINR);
1418 case METEORSBRIG: /* set brightness */
1419 SAA7196_WRITE(mtr, SAA7196_BRIG, *(char *)data);
1421 case METEORGBRIG: /* get brightness */
1422 *(char *)data = SAA7196_REG(mtr, SAA7196_BRIG);
1424 case METEORSCSAT: /* set chroma saturation */
1425 SAA7196_WRITE(mtr, SAA7196_CSAT, *(char *)data);
1427 case METEORGCSAT: /* get chroma saturation */
1428 *(char *)data = SAA7196_REG(mtr, SAA7196_CSAT);
1430 case METEORSCONT: /* set contrast */
1431 SAA7196_WRITE(mtr, SAA7196_CONT, *(char *)data);
1433 case METEORGCONT: /* get contrast */
1434 *(char *)data = SAA7196_REG(mtr, SAA7196_CONT);
1437 if((mtr->flags & METEOR_RGB) == 0)
1439 temp = *(unsigned short *)data;
1440 bt254_write(mtr, temp & 0xf, (temp & 0x0ff0) >> 4);
1443 if((mtr->flags & METEOR_RGB) == 0)
1445 temp = *(unsigned short *)data & 0x7;
1446 *(unsigned short *)data = mtr->bt254_reg[temp] << 4 | temp;
1448 case METEORSHWS: /* set horizontal window start */
1449 SAA7196_WRITE(mtr, SAA7196_HWS, *(char *)data);
1451 case METEORGHWS: /* get horizontal window start */
1452 *(char *)data = SAA7196_REG(mtr, SAA7196_HWS);
1454 case METEORSVWS: /* set vertical window start */
1455 SAA7196_WRITE(mtr, SAA7196_VWS, *(char *)data);
1457 case METEORGVWS: /* get vertical window start */
1458 *(char *)data = SAA7196_REG(mtr, SAA7196_VWS);
1460 case METEORSINPUT: /* set input device */
1461 switch(*(unsigned long *)data & METEOR_DEV_MASK) {
1462 case 0: /* default */
1463 case METEOR_INPUT_DEV0:
1464 if(mtr->flags & METEOR_RGB)
1465 select_saa7196(mtr);
1466 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1468 SAA7196_WRITE(mtr, 0x0e,
1469 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x0);
1470 SAA7196_WRITE(mtr, 0x06,
1471 (SAA7196_REG(mtr, 0x06) & ~0x80));
1473 case METEOR_INPUT_DEV1:
1474 if(mtr->flags & METEOR_RGB)
1475 select_saa7196(mtr);
1476 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1478 SAA7196_WRITE(mtr, 0x0e,
1479 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x1);
1480 SAA7196_WRITE(mtr, 0x06,
1481 (SAA7196_REG(mtr, 0x06) & ~0x80));
1483 case METEOR_INPUT_DEV2:
1484 if(mtr->flags & METEOR_RGB)
1485 select_saa7196(mtr);
1486 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1488 SAA7196_WRITE(mtr, 0x0e,
1489 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x2);
1490 SAA7196_WRITE(mtr, 0x06,
1491 (SAA7196_REG(mtr, 0x06) & ~0x80));
1493 case METEOR_INPUT_DEV3:
1494 if(mtr->flags & METEOR_RGB)
1495 select_saa7196(mtr);
1496 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1498 SAA7196_WRITE(mtr, 0x0e,
1499 (SAA7196_REG(mtr, 0x0e) | 0x3));
1500 SAA7196_WRITE(mtr, 0x06,
1501 (SAA7196_REG(mtr, 0x06) & ~0x80) );
1503 case METEOR_INPUT_DEV_SVIDEO:
1504 if(mtr->flags & METEOR_RGB)
1505 select_saa7196(mtr);
1506 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1507 | METEOR_DEV_SVIDEO;
1508 SAA7196_WRITE(mtr, 0x0e,
1509 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x2);
1510 SAA7196_WRITE(mtr, 0x06,
1511 (SAA7196_REG(mtr, 0x06) & ~0x80) | 0x80);
1513 case METEOR_INPUT_DEV_RGB:
1514 if((mtr->flags & METEOR_RGB) == 0)
1516 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1518 SAA7196_WRITE(mtr, 0x0e,
1519 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x3);
1520 SAA7196_WRITE(mtr, 0x06,
1521 (SAA7196_REG(mtr, 0x06) & ~0x80));
1523 SAA7196_WRITE(mtr, 0x0e, /* chn 3 for synch */
1524 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x3);
1530 case METEORGINPUT: /* get input device */
1531 *(u_long *)data = mtr->flags & METEOR_DEV_MASK;
1533 case METEORSFMT: /* set input format */
1534 switch(*(unsigned long *)data & METEOR_FORM_MASK ) {
1535 case 0: /* default */
1536 case METEOR_FMT_NTSC:
1537 mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1539 SAA7196_WRITE(mtr, SAA7196_STDC,
1540 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01));
1541 SAA7196_WRITE(mtr, 0x0f,
1542 (SAA7196_REG(mtr, 0x0f) & ~0xe0) | 0x40);
1543 SAA7196_WRITE(mtr, 0x22, 0x80);
1544 SAA7196_WRITE(mtr, 0x24,
1545 (SAA7196_REG(mtr, 0x24) & ~0x0c) | 0x08);
1546 SAA7196_WRITE(mtr, 0x26, 0xf0);
1547 SAA7196_WRITE(mtr, 0x28,
1548 (SAA7196_REG(mtr, 0x28) & ~0x0c)) ;
1549 if(mtr->flags & METEOR_RGB){
1553 case METEOR_FMT_PAL:
1554 mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1556 SAA7196_WRITE(mtr, SAA7196_STDC,
1557 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01));
1558 SAA7196_WRITE(mtr, 0x0f,
1559 (SAA7196_REG(mtr, 0x0f) & ~0xe0));
1560 SAA7196_WRITE(mtr, 0x22, 0x00);
1561 SAA7196_WRITE(mtr, 0x24,
1562 (SAA7196_REG(mtr, 0x24) | 0x0c));
1563 SAA7196_WRITE(mtr, 0x26, 0x20);
1564 SAA7196_WRITE(mtr, 0x28,
1565 (SAA7196_REG(mtr, 0x28) & ~0x0c) | 0x04) ;
1566 if(mtr->flags & METEOR_RGB){
1570 case METEOR_FMT_SECAM:
1571 mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1573 SAA7196_WRITE(mtr, SAA7196_STDC,
1574 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01) | 0x1);
1575 SAA7196_WRITE(mtr, 0x0f,
1576 (SAA7196_REG(mtr, 0x0f) & ~0xe0) | 0x20);
1577 SAA7196_WRITE(mtr, 0x22, 0x00);
1578 SAA7196_WRITE(mtr, 0x24,
1579 (SAA7196_REG(mtr, 0x24) | 0x0c));
1580 SAA7196_WRITE(mtr, 0x26, 0x20);
1581 SAA7196_WRITE(mtr, 0x28,
1582 (SAA7196_REG(mtr, 0x28) & ~0x0c) | 0x04) ;
1583 if(mtr->flags & METEOR_RGB){
1587 case METEOR_FMT_AUTOMODE:
1588 mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1590 SAA7196_WRITE(mtr, SAA7196_STDC,
1591 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01));
1592 SAA7196_WRITE(mtr, 0x0f,
1593 (SAA7196_REG(mtr, 0x0f) & ~0xe0) | 0x80);
1599 case METEORGFMT: /* get input format */
1600 *(u_long *)data = mtr->flags & METEOR_FORM_MASK;
1604 switch (*(int *) data) {
1605 case METEOR_CAP_SINGLE:
1606 if (mtr->bigbuf==0) /* no frame buffer allocated */
1609 if (temp & METEOR_CAP_MASK)
1610 return(EIO); /* already capturing */
1612 start_capture(mtr, METEOR_SINGLE);
1614 /* wait for capture to complete */
1615 error=tsleep((caddr_t)mtr, METPRI, "capturing", 0);
1617 kprintf("meteor%d: ioctl: tsleep error %d\n",
1619 mtr->flags &= ~(METEOR_SINGLE|METEOR_WANT_MASK);
1621 case METEOR_CAP_CONTINOUS:
1622 if (mtr->bigbuf==0) /* no frame buffer allocated */
1625 if (temp & METEOR_CAP_MASK)
1626 return(EIO); /* already capturing */
1628 start_capture(mtr, METEOR_CONTIN);
1631 case METEOR_CAP_STOP_CONT:
1632 if (mtr->flags & METEOR_CONTIN) {
1633 /* turn off capture */
1634 base->cap_cntl = 0x8ff0;
1635 mtr->flags &= ~(METEOR_CONTIN|METEOR_WANT_MASK);
1645 frame = (struct meteor_capframe *) data;
1648 switch (frame->command) {
1649 case METEOR_CAP_N_FRAMES:
1650 if (mtr->flags & METEOR_CAP_MASK)
1652 if (mtr->flags & (METEOR_YUV_PLANAR | METEOR_YUV_422)) /* XXX */
1653 return(EINVAL); /* should fix intr so we allow these */
1654 if (mtr->bigbuf == 0)
1656 if ((mtr->frames < 2) ||
1657 (frame->lowat < 1 || frame->lowat >= mtr->frames) ||
1658 (frame->hiwat < 1 || frame->hiwat >= mtr->frames) ||
1659 (frame->lowat > frame->hiwat))
1661 /* meteor_mem structure is on the page after the data */
1662 mem = mtr->mem = (struct meteor_mem *) (mtr->bigbuf +
1663 (round_page(mtr->frame_size * mtr->frames)));
1665 mtr->synch_wait = 0;
1666 mem->num_bufs = mtr->frames;
1667 mem->frame_size= mtr->frame_size;
1668 /* user and kernel change these */
1669 mem->lowat = frame->lowat;
1670 mem->hiwat = frame->hiwat;
1672 mem->num_active_bufs = 0;
1674 start_capture(mtr, METEOR_SYNCAP);
1676 case METEOR_CAP_STOP_FRAMES:
1677 if (mtr->flags & METEOR_SYNCAP) {
1678 /* turn off capture */
1679 base->cap_cntl = 0x8ff0;
1680 mtr->flags &= ~(METEOR_SYNCAP|METEOR_WANT_MASK);
1683 case METEOR_HALT_N_FRAMES:
1684 if(mtr->flags & METEOR_SYNCAP) {
1685 base->cap_cntl = 0x8ff0;
1686 mtr->flags &= ~(METEOR_WANT_MASK);
1689 case METEOR_CONT_N_FRAMES:
1690 if(!(mtr->flags & METEOR_SYNCAP)) {
1694 start_capture(mtr, METEOR_SYNCAP);
1703 geo = (struct meteor_geomet *) data;
1705 /* Either even or odd, if even & odd, then these a zero */
1706 if((geo->oformat & METEOR_GEO_ODD_ONLY) &&
1707 (geo->oformat & METEOR_GEO_EVEN_ONLY)) {
1708 kprintf("meteor%d: ioctl: Geometry odd or even only.\n",
1712 /* set/clear even/odd flags */
1713 if(geo->oformat & METEOR_GEO_ODD_ONLY)
1714 mtr->flags |= METEOR_ONLY_ODD_FIELDS;
1716 mtr->flags &= ~METEOR_ONLY_ODD_FIELDS;
1717 if(geo->oformat & METEOR_GEO_EVEN_ONLY)
1718 mtr->flags |= METEOR_ONLY_EVEN_FIELDS;
1720 mtr->flags &= ~METEOR_ONLY_EVEN_FIELDS;
1722 /* can't change parameters while capturing */
1723 if (mtr->flags & METEOR_CAP_MASK)
1726 if ((geo->columns & 0x3fe) != geo->columns) {
1728 "meteor%d: ioctl: %d: columns too large or not even.\n",
1729 unit, geo->columns);
1732 if (((geo->rows & 0x7fe) != geo->rows) ||
1733 ((geo->oformat & METEOR_GEO_FIELD_MASK) &&
1734 ((geo->rows & 0x3fe) != geo->rows)) ) {
1736 "meteor%d: ioctl: %d: rows too large or not even.\n",
1740 if (geo->frames > 32) {
1741 kprintf("meteor%d: ioctl: too many frames.\n", unit);
1744 if(error) return error;
1746 if ((temp=geo->rows * geo->columns * geo->frames * 2) != 0) {
1747 if (geo->oformat & METEOR_GEO_RGB24) temp = temp * 2;
1749 /* meteor_mem structure for SYNC Capture */
1750 if (geo->frames > 1) temp += PAGE_SIZE;
1753 if (temp > mtr->alloc_pages
1754 #ifdef METEOR_TEST_VIDEO
1755 && mtr->video.addr == 0
1758 buf = get_meteor_mem(unit, temp*PAGE_SIZE);
1760 kmem_free(&kernel_map, mtr->bigbuf,
1761 (mtr->alloc_pages * PAGE_SIZE));
1763 mtr->alloc_pages = temp;
1766 "meteor%d: ioctl: Allocating %d bytes\n",
1767 unit, temp*PAGE_SIZE);
1773 if(error) return error;
1775 mtr->rows = geo->rows;
1776 mtr->cols = geo->columns;
1777 mtr->frames = geo->frames;
1779 #ifdef METEOR_TEST_VIDEO
1781 buf = vtophys(mtr->video.addr);
1784 buf = vtophys(mtr->bigbuf);
1786 /* set defaults and end of buffer locations */
1799 /* set end of DMA location, even/odd */
1801 base->dma_end_o = buf + mtr->alloc_pages * PAGE_SIZE;
1804 * Determine if we can use the hardware range detect.
1806 if(mtr->alloc_pages * PAGE_SIZE < RANGE_BOUNDARY &&
1807 ((buf & 0xff000000) | base->dma_end_e) ==
1808 (buf + mtr->alloc_pages * PAGE_SIZE) )
1809 mtr->range_enable = 0x8000;
1811 mtr->range_enable = 0x0;
1813 base->dma_end_o = 0xffffffff;
1817 switch (geo->oformat & METEOR_GEO_OUTPUT_MASK) {
1818 case 0: /* default */
1819 case METEOR_GEO_RGB16:
1821 mtr->frame_size = mtr->rows * mtr->cols * mtr->depth;
1822 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1823 mtr->flags |= METEOR_RGB16;
1824 temp = mtr->cols * mtr->depth;
1825 /* recal stride and starting point */
1826 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1827 case METEOR_ONLY_ODD_FIELDS:
1829 #ifdef METEOR_TEST_VIDEO
1830 if(mtr->video.addr && mtr->video.width)
1831 base->stride1o = mtr->video.width-temp;
1833 SAA7196_WRITE(mtr, 0x20, 0xd0);
1835 case METEOR_ONLY_EVEN_FIELDS:
1837 #ifdef METEOR_TEST_VIDEO
1838 if(mtr->video.addr && mtr->video.width)
1839 base->stride1e = mtr->video.width-temp;
1841 SAA7196_WRITE(mtr, 0x20, 0xf0);
1843 default: /* interlaced even/odd */
1845 base->dma1o = buf + temp;
1846 base->stride1e = base->stride1o = temp;
1847 #ifdef METEOR_TEST_VIDEO
1848 if(mtr->video.addr && mtr->video.width) {
1849 base->dma1o = buf + mtr->video.width;
1850 base->stride1e = base->stride1o =
1852 temp + mtr->video.width;
1855 SAA7196_WRITE(mtr, 0x20, 0x90);
1858 base->routee = base->routeo = 0xeeeeee01;
1860 case METEOR_GEO_RGB24:
1862 mtr->frame_size = mtr->rows * mtr->cols * mtr->depth;
1863 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1864 mtr->flags |= METEOR_RGB24;
1865 temp = mtr->cols * mtr->depth;
1866 /* recal stride and starting point */
1867 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1868 case METEOR_ONLY_ODD_FIELDS:
1870 #ifdef METEOR_TEST_VIDEO
1871 if(mtr->video.addr && mtr->video.width)
1872 base->stride1o = mtr->video.width-temp;
1874 SAA7196_WRITE(mtr, 0x20, 0xd2);
1876 case METEOR_ONLY_EVEN_FIELDS:
1878 #ifdef METEOR_TEST_VIDEO
1879 if(mtr->video.addr && mtr->video.width)
1880 base->stride1e = mtr->video.width-temp;
1882 SAA7196_WRITE(mtr, 0x20, 0xf2);
1884 default: /* interlaced even/odd */
1886 base->dma1o = buf + mtr->cols * mtr->depth;
1887 base->stride1e = base->stride1o =
1888 mtr->cols * mtr->depth;
1889 #ifdef METEOR_TEST_VIDEO
1890 if(mtr->video.addr && mtr->video.width) {
1891 base->dma1o = buf + mtr->video.width;
1892 base->stride1e = base->stride1o =
1894 temp + mtr->video.width;
1897 SAA7196_WRITE(mtr, 0x20, 0x92);
1900 base->routee= base->routeo= 0x39393900;
1902 case METEOR_GEO_YUV_PLANAR:
1904 temp = mtr->rows * mtr->cols; /* compute frame size */
1905 mtr->frame_size = temp * mtr->depth;
1906 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1907 mtr->flags |= METEOR_YUV_PLANAR;
1908 /* recal stride and starting point */
1909 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1910 case METEOR_ONLY_ODD_FIELDS:
1911 base->dma1o = buf; /* Y Odd */
1912 base->dma2o = buf + temp; /* U Odd */
1914 base->dma3o = base->dma2o + temp; /* V Odd */
1915 SAA7196_WRITE(mtr, 0x20, 0xd1);
1917 case METEOR_ONLY_EVEN_FIELDS:
1918 base->dma1e = buf; /* Y Even */
1919 base->dma2e = buf + temp; /* U Even */
1921 base->dma2e= base->dma2e + temp; /* V Even */
1922 SAA7196_WRITE(mtr, 0x20, 0xf1);
1924 default: /* interlaced even/odd */
1925 base->dma1e = buf; /* Y Even */
1926 base->dma2e = buf + temp; /* U Even */
1928 base->dma3e = base->dma2e + temp; /* V Even */
1929 base->dma1o = base->dma1e+mtr->cols;/* Y Odd */
1930 base->dma2o = base->dma3e + temp; /* U Odd */
1931 base->dma3o = base->dma2o + temp; /* V Odd */
1932 base->stride1e = base->stride1o = mtr->cols;
1933 SAA7196_WRITE(mtr, 0x20, 0x91);
1936 switch (geo->oformat &
1937 (METEOR_GEO_YUV_12 | METEOR_GEO_YUV_9)) {
1938 case METEOR_GEO_YUV_9:
1939 base->routee=base->routeo = 0xaaaaffc3;
1941 case METEOR_GEO_YUV_12:
1942 base->routee=base->routeo = 0xaaaaffc2;
1945 base->routee=base->routeo = 0xaaaaffc1;
1949 case METEOR_GEO_YUV_422:/* same as planer, different uv order */
1951 temp = mtr->rows * mtr->cols; /* compute frame size */
1952 mtr->frame_size = temp * mtr->depth;
1953 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1954 mtr->flags |= METEOR_YUV_422;
1955 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1956 case METEOR_ONLY_ODD_FIELDS:
1958 base->dma2o = buf + temp;
1959 base->dma3o = base->dma2o + (temp >> 1);
1960 SAA7196_WRITE(mtr, 0x20, 0xd1);
1962 case METEOR_ONLY_EVEN_FIELDS:
1964 base->dma2e = buf + temp;
1965 base->dma3e = base->dma2e + (temp >> 1);
1966 SAA7196_WRITE(mtr, 0x20, 0xf1);
1968 default: /* interlaced even/odd */
1969 base->dma1e = buf; /* Y even */
1970 base->dma2e = buf + temp; /* U even */
1972 base->dma2e + (temp >> 1);/* V even */
1973 base->dma1o = base->dma1e+mtr->cols;/* Y odd */
1974 temp = mtr->cols >> 1;
1975 base->dma2o = base->dma2e+temp; /* U odd */
1976 base->dma3o = base->dma3e+temp; /* V odd */
1978 base->stride1o = mtr->cols; /* Y stride */
1980 base->stride2o = temp; /* U stride */
1982 base->stride3o = temp; /* V stride */
1983 SAA7196_WRITE(mtr, 0x20, 0x91);
1986 switch (geo->oformat &
1987 (METEOR_GEO_YUV_12 | METEOR_GEO_YUV_9)) {
1988 case METEOR_GEO_YUV_9:
1989 base->routee=base->routeo = 0xaaaaffc3;
1991 case METEOR_GEO_YUV_12:
1992 base->routee=base->routeo = 0xaaaaffc2;
1995 base->routee=base->routeo = 0xaaaaffc1;
1999 case METEOR_GEO_YUV_PACKED:
2001 mtr->frame_size = mtr->rows * mtr->cols * mtr->depth;
2002 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
2003 mtr->flags |= METEOR_YUV_PACKED;
2004 /* recal stride and odd starting point */
2005 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
2006 case METEOR_ONLY_ODD_FIELDS:
2008 SAA7196_WRITE(mtr, 0x20, 0xd1);
2010 case METEOR_ONLY_EVEN_FIELDS:
2012 SAA7196_WRITE(mtr, 0x20, 0xf1);
2014 default: /* interlaced even/odd */
2016 base->dma1o = buf + mtr->cols * mtr->depth;
2017 base->stride1e = base->stride1o =
2018 mtr->cols * mtr->depth;
2019 SAA7196_WRITE(mtr, 0x20, 0x91);
2022 base->routee = base->routeo = 0xeeeeee41;
2025 error = EINVAL; /* invalid argument */
2026 kprintf("meteor%d: ioctl: invalid output format\n",unit);
2030 SAA7196_WRITE(mtr, 0x21, mtr->cols & 0xff);
2031 SAA7196_WRITE(mtr, 0x24,
2032 ((SAA7196_REG(mtr, 0x24) & ~0x03) |
2033 ((mtr->cols >> 8) & 0x03)));
2035 if(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
2036 SAA7196_WRITE(mtr, 0x25, ((mtr->rows) & 0xff));
2037 SAA7196_WRITE(mtr, 0x28,
2038 ((SAA7196_REG(mtr, 0x28) & ~0x03) |
2039 ((mtr->rows >> 8) & 0x03)));
2040 } else { /* Interlaced */
2041 SAA7196_WRITE(mtr, 0x25, ((mtr->rows >> 1) & 0xff));
2042 SAA7196_WRITE(mtr, 0x28,
2043 ((SAA7196_REG(mtr, 0x28) & ~0x03) |
2044 ((mtr->rows >> 9) & 0x03)));
2046 /* set signed/unsigned chrominance */
2047 SAA7196_WRITE(mtr, 0x30, (SAA7196_REG(mtr, 0x30) & ~0x10) |
2048 ((geo->oformat&METEOR_GEO_UNSIGNED)?0:0x10));
2051 geo = (struct meteor_geomet *) data;
2052 geo->rows = mtr->rows;
2053 geo->columns = mtr->cols;
2054 geo->frames = mtr->frames;
2055 geo->oformat = (mtr->flags & METEOR_OUTPUT_FMT_MASK) |
2056 (mtr->flags & METEOR_ONLY_FIELDS_MASK) |
2057 (SAA7196_REG(mtr, 0x30) & 0x10 ?
2058 0:METEOR_GEO_UNSIGNED);
2059 switch(base->routee & 0xff) {
2061 geo->oformat |= METEOR_GEO_YUV_9;
2064 geo->oformat |= METEOR_GEO_YUV_12;
2070 case METEORSCOUNT: /* (re)set error counts */
2071 cnt = (struct meteor_counts *) data;
2072 mtr->fifo_errors = cnt->fifo_errors;
2073 mtr->dma_errors = cnt->dma_errors;
2074 mtr->frames_captured = cnt->frames_captured;
2075 mtr->even_fields_captured = cnt->even_fields_captured;
2076 mtr->odd_fields_captured = cnt->odd_fields_captured;
2078 case METEORGCOUNT: /* get error counts */
2079 cnt = (struct meteor_counts *) data;
2080 cnt->fifo_errors = mtr->fifo_errors;
2081 cnt->dma_errors = mtr->dma_errors;
2082 cnt->frames_captured = mtr->frames_captured;
2083 cnt->even_fields_captured = mtr->even_fields_captured;
2084 cnt->odd_fields_captured = mtr->odd_fields_captured;
2087 kprintf("meteor%d: ioctl: invalid ioctl request\n", unit);
2095 meteor_mmap(struct dev_mmap_args *ap)
2097 cdev_t dev = ap->a_head.a_dev;
2101 unit = UNIT(minor(dev));
2102 if (unit >= NMETEOR) /* at this point could this happen? */
2105 mtr = &(meteor[unit]);
2108 if (ap->a_nprot & PROT_EXEC)
2111 if (ap->a_offset >= mtr->alloc_pages * PAGE_SIZE)
2114 return i386_btop(vtophys(mtr->bigbuf) + ap->a_offset);