HAMMER 61E/Many: Stabilization, Performance
[dragonfly.git] / sys / dev / video / meteor / meteor.c
blob2fb6c5a4d102d2f0aba12ead1cf5901f0b59a21a
1 /*
2 * Copyright (c) 1995 Mark Tinguely and Jim Lowe
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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.22 2007/05/13 18:33:58 swildner Exp $
35 /* Change History:
36 8/21/95 Release
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
43 off for AUTOMODE.
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)
59 to 217 (PAL).
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
66 stuff it already had.
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
75 even frame grabs.
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
83 completed.
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
92 to compile.
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
109 test with.
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
113 code.
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
121 types.
122 4/8/96 Fixed the a bug in with the range enable. Pointed
123 out by Jim Bray.
124 5/13/96 Fix the FPS ioctl so it actually sets the frames
125 per second. Code supplied by ian@robots.ox.ac.uk.
126 The new code implements a new define:
127 METEOR_SYSTEM_DEFAULT which should be defined as
128 METEOR_PAL, METEOR_SECAM, or METEOR_NTSC in your system
129 configuration file. If METEOR_SYSTEM_DEFAULT isn't
130 defined, and there is not a signal when set_fps is
131 called, then the call has no effect.
132 Changed the spelling of PLANER to PLANAR as pointed
133 out by Paco Hope <paco@cs.virigina.edu> and define
134 PLANER to be PLANAR for backward compatibility.
135 5/28/95 METEOR_INPUT_DEV_RCA -> METEOR_INPUT_DEV0, not
136 METEOR_GEO_DEV0. Pointed out by Ian Reid,
137 <ian@robots.ox.ac.uk>.
138 METEOR_DEV_MASK should be 0x0000f000 and not
139 0x2000f000, otherwise METEOR_RGB gets masked
140 out. Pointed out by Ian Reid.
141 Changed the fps code to give even distribution for
142 low frame rates. Code supplied by Ian Reid.
143 Fix some problems with the RGB version. Patch supplied
144 by <ljo@po.cwru.edu>.
145 Added METEOR_FIELD_MODE to include files for a
146 future version of this driver.
149 #include "use_meteor.h"
150 #include "opt_meteor.h"
152 #include <sys/param.h>
153 #include <sys/systm.h>
154 #include <sys/conf.h>
155 #include <sys/device.h>
156 #include <sys/kernel.h>
157 #include <sys/signalvar.h>
158 #include <sys/mman.h>
159 #include <sys/uio.h>
161 #if defined(METEOR_FreeBSD_210)
162 #include <machine/cpu.h> /* bootverbose */
163 #endif
165 #include <vm/vm.h>
166 #include <vm/vm_kern.h>
167 #include <vm/pmap.h>
168 #include <vm/vm_extern.h>
170 #include <bus/pci/pcivar.h>
171 #include <bus/pci/pcireg.h>
172 #include <dev/video/meteor/ioctl_meteor.h>
173 #include <dev/video/meteor/meteor_reg.h>
176 static void meteor_intr (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
187 #endif
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 = {
200 "meteor",
201 met_probe,
202 met_attach,
203 &met_count
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;
215 #else
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 dev_ops meteor_ops = {
225 { "meteor", CDEV_MAJOR, 0 },
226 .d_open = meteor_open,
227 .d_close = meteor_close,
228 .d_read = meteor_read,
229 .d_write = meteor_write,
230 .d_ioctl = meteor_ioctl,
231 .d_mmap = meteor_mmap,
233 #endif
235 static mreg_t saa7116_pci_default[sizeof(struct saa7116_regs)/sizeof(mreg_t)]={
236 /* PCI Memory registers */
237 /* BITS Type Description */
238 /* 0x00 */ 0x00000000, /* 31:1 e*RW DMA 1 (Even)
239 0 RO 0x0 */
240 /* 0x04 */ 0x00000000, /* 31:2 e*RW DMA 2 (Even)
241 1:0 RO 0x0 */
242 /* 0x08 */ 0x00000000, /* 31:2 e*RW DMA 3 (Even)
243 1:0 RO 0x0 */
244 /* 0x0c */ 0x00000000, /* 31:1 o*RW DMA 1 (Odd)
245 0 RO 0x0 */
246 /* 0x10 */ 0x00000000, /* 31:2 o*RW DMA 2 (Odd)
247 1:0 RO 0x0 */
248 /* 0x14 */ 0x00000000, /* 31:2 o*RW DMA 3 (Odd)
249 1:0 RO 0x0 */
250 /* 0x18 */ 0x00000500, /* 15:2 e*RW Stride 1 (Even)
251 1:0 RO 0x0 */
252 /* 0x1c */ 0x00000000, /* 15:2 e*RW Stride 2 (Even)
253 1:0 RO 0x0 */
254 /* 0x20 */ 0x00000000, /* 15:2 e*RW Stride 3 (Even)
255 1:0 RO 0x0 */
256 /* 0x24 */ 0x00000500, /* 15:2 o*RW Stride 1 (Odd)
257 1:0 RO 0x0 */
258 /* 0x28 */ 0x00000000, /* 15:2 o*RW Stride 2 (Odd)
259 1:0 RO 0x0 */
260 /* 0x2c */ 0x00000000, /* 15:2 o*RW Stride 3 (Odd)
261 1:0 RO 0x0 */
262 /* 0x30 */ 0xeeeeee01, /* 31:8 *RW Route (Even)
263 7:0 *RW Mode (Even) */
264 /* 0x34 */ 0xeeeeee01, /* 31:8 *RW Route (Odd)
265 7:0 *RW Mode (Odd) */
266 /* 0x38 */ 0x00200020, /* 22:16 *RW FIFO Trigger Planer Mode,
267 6:0 *RW FIFO Trigger Packed Mode */
268 /* 0x3c */ 0x00000107, /* 9:8 *RW Reserved (0x0)
269 2 *RW Field Toggle
270 1 *RW Reserved (0x1)
271 0 *RW Reserved (0x1) */
272 /* 0x40 */ 0x000000c0, /* 15 *RW Range Enable
273 14 *RW Corrupt Disable
274 11 *RR Address Error (Odd)
275 10 *RR Address Error (Even)
276 9 *RR Field Corrupt (Odd)
277 8 *RR Field Corrupt (Even)
278 7 *RW Fifo Enable
279 6 *RW VRSTN#
280 5 *RR Field Done (Odd)
281 4 *RR Field Done (Even)
282 3 *RS Single Field Capture (Odd)
283 2 *RS Single Field Capture (Even)
284 1 *RW Capture (ODD) Continous
285 0 *RW Capture (Even) Continous */
286 /* 0x44 */ 0x00000000, /* 7:0 *RW Retry Wait Counter */
287 /* 0x48 */ 0x00000307, /* 10 *RW Interrupt mask, start of field
288 9 *RW Interrupt mask, end odd field
289 8 *RW Interrupt mask, end even field
290 2 *RR Interrupt status, start of field
291 1 *RR Interrupt status, end of odd
292 0 *RR Interrupt status, end of even */
293 /* 0x4c */ 0x00000001, /* 31:0 *RW Field Mask (Even) continous */
294 /* 0x50 */ 0x00000001, /* 31:0 *RW Field Mask (Odd) continous */
295 /* 0x54 */ 0x00000000, /* 20:16 *RW Mask Length (Odd)
296 4:0 *RW Mask Length (Even) */
297 /* 0x58 */ 0x0005007c, /* 22:16 *RW FIFO almost empty
298 6:0 *RW FIFO almost full */
299 /* 0x5c */ 0x461e1e0f, /* 31:24 *RW I2C Phase 4
300 23:16 *RW I2C Phase 3
301 15:8 *RW I2C Phase 2
302 7:0 *RW I2C Phase 1 */
303 /* 0x60 */ 0x00000300, /* 31:24 *RO I2C Read Data
304 23:16 **RW I2C Auto Address
305 11 RO I2C SCL Input
306 10 RO I2C SDA Input
307 9 RR I2C Direct Abort
308 8 RR I2C Auto Abort
309 3 RW I2C SCL Output
310 2 RW I2C SDA Output
311 1 RW I2C Bypass
312 0 RW I2C Auto Enable */
313 /* 0x64 */ 0x00000000, /* 24 RS I2C New Cycle
314 23:16 **RW I2C Direct Address
315 15:8 **RW I2C Direct Sub-address
316 7:0 **RW I2C Direct Write Address */
317 /* 0x68 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 1 (Even)
318 23:16 **RW I2C Auto Data 1 (Even)
319 15:8 **RW I2C Auto Sub-address 0 (Even)
320 7:0 **RW I2C Auto Data 0 (Even) */
321 /* 0x6c */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 3 (Even)
322 23:16 **RW I2C Auto Data 3 (Even)
323 15:8 **RW I2C Auto Sub-address 2 (Even)
324 7:0 **RW I2C Auto Data 2 (Even) */
325 /* 0x70 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 5 (Even)
326 23:16 **RW I2C Auto Data 5 (Even)
327 15:8 **RW I2C Auto Sub-address 4 (Even)
328 7:0 **RW I2C Auto Data 4 (Even) */
329 /* 0x74 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 7 (Even)
330 23:16 **RW I2C Auto Data 7 (Even)
331 15:8 **RW I2C Auto Sub-address 6 (Even)
332 7:0 **RW I2C Auto Data 6 (Even) */
333 /* 0x78 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 1 (Odd)
334 23:16 **RW I2C Auto Data 1 (Odd)
335 15:8 **RW I2C Auto Sub-address 0 (Odd)
336 7:0 **RW I2C Auto Data 0 (Odd) */
337 /* 0x7c */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 3 (Odd)
338 23:16 **RW I2C Auto Data 3 (Odd)
339 15:8 **RW I2C Auto Sub-address 2 (Odd)
340 7:0 **RW I2C Auto Data 2 (Odd) */
341 /* 0x80 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 5 (Odd)
342 23:16 **RW I2C Auto Data 5 (Odd)
343 15:8 **RW I2C Auto Sub-address 4 (Odd)
344 7:0 **RW I2C Auto Data 4 (Odd) */
345 /* 0x84 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 7 (Odd)
346 23:16 **RW I2C Auto Data 7 (Odd)
347 15:8 **RW I2C Auto Sub-address 6 (Odd)
348 7:0 **RW I2C Auto Data 6 (Odd) */
349 /* 0x88 */ 0x00000000, /* 23:16 **RW I2C Register Enable (Odd)
350 7:0 **RW I2C Register Enable (Even) */
351 /* 0x8c */ 0x00000000, /* 23:2 e*RW DMA End (Even)
352 1:0 RO 0x0 */
353 /* 0x90 */ 0x00000000 /* 23:2 e*RW DMA End (Odd)
354 1:0 RO 0x0 */
357 static u_char saa7196_i2c_default[NUM_SAA7196_I2C_REGS] = {
358 /* SAA7196 I2C bus control */
359 /* BITS Function */
360 /* 00 */ 0x50, /* 7:0 Increment Delay */
361 /* 01 */ 0x30, /* 7:0 Horizontal Sync Begin for 50hz */
362 /* 02 */ 0x00, /* 7:0 Horizontal Sync Stop for 50hz */
363 /* 03 */ 0xe8, /* 7:0 Horizontal Sync Clamp Start for 50hz */
364 /* 04 */ 0xb6, /* 7:0 Horizontal Sync Clamp Stop for 50hz */
365 /* 05 */ 0xf4, /* 7:0 Horizontal Sync Start after PH1 for 50hz */
366 /* 06 */ 0x46, /* 7 Input mode =0 CVBS, =1 S-Video
367 6 Pre filter
368 5:4 Aperture Bandpass characteristics
369 3:2 Coring range for high freq
370 1:0 Aperture bandpass filter weights */
371 /* 07 */ 0x00, /* 7:0 Hue */
372 /* 08 */ 0x7f, /* 7:3 Colour-killer threshold QAM (PAL, NTSC) */
373 /* 09 */ 0x7f, /* 7:3 Colour-killer threshold SECAM */
374 /* 0a */ 0x7f, /* 7:0 PAL switch sensitivity */
375 /* 0b */ 0x7f, /* 7:0 SECAM switch sensitivity */
376 /* 0c */ 0x40, /* 7 Colour-on bit
377 6:5 AGC filter */
378 /* 0d */ 0x84, /* 7 VTR/TV mode bit = 1->VTR mode
379 3 Realtime output mode select bit
380 2 HREF position select
381 1 Status byte select
382 0 SECAM mode bit */
383 /* 0e */ 0x38, /* 7 Horizontal clock PLL
384 5 Select interal/external clock source
385 4 Output enable of Horizontal/Vertical sync
386 3 Data output YUV enable
387 2 S-VHS bit
388 1 GPSW2
389 0 GPSW1 */
390 /* 0f */ 0x50, /* 7 Automatic Field detection
391 6 Field Select 0 = 50hz, 1=60hz
392 5 SECAM cross-colour reduction
393 4 Enable sync and clamping pulse
394 3:1 Luminance delay compensation */
395 /* 10 */ 0x00, /* 2 Select HREF Position
396 1:0 Vertical noise reduction */
397 /* 11 */ 0x2c, /* 7:0 Chrominance gain conrtol for QAM */
398 /* 12 */ 0x40, /* 7:0 Chrominance saturation control for VRAM port */
399 /* 13 */ 0x40, /* 7:0 Luminance contract control for VRAM port */
400 /* 14 */ 0x34, /* 7:0 Horizontal sync begin for 60hz */
401 #ifdef notdef
402 /* 15 */ 0x0c, /* 7:0 Horizontal sync stop for 60hz */
403 /* 16 */ 0xfb, /* 7:0 Horizontal clamp begin for 60hz */
404 /* 17 */ 0xd4, /* 7:0 Horizontal clamp stop for 60hz */
405 /* 18 */ 0xec, /* 7:0 Horizontal sync start after PH1 for 60hz */
406 #else
407 0x0a, 0xf4, 0xce, 0xf4,
408 #endif
409 /* 19 */ 0x80, /* 7:0 Luminance brightness control for VRAM port */
410 /* 1a */ 0x00,
411 /* 1b */ 0x00,
412 /* 1c */ 0x00,
413 /* 1d */ 0x00,
414 /* 1e */ 0x00,
415 /* 1f */ 0x00,
416 /* 20 */ 0x90, /* 7 ROM table bypass switch
417 6:5 Set output field mode
418 4 VRAM port outputs enable
419 3:2 First pixel position in VRO data
420 1:0 FIFO output register select */
421 /* 21 */ 0x80, /* 7:0 [7:0] Pixel number per line on output */
422 /* 22 */ 0x80, /* 7:0 [7:0] Pixel number per line on input */
423 /* 23 */ 0x03, /* 7:0 [7:0] Horizontal start position of scaling win*/
424 /* 24 */ 0x8a, /* 7:5 Horizontal decimation filter
425 4 [8] Horizontal start position of scaling win
426 3:2 [9:8] Pixel number per line on input
427 1:0 [9:8] Pixel number per line on output */
428 /* 25 */ 0xf0, /* 7:0 [7:0] Line number per output field */
429 /* 26 */ 0xf0, /* 7:0 [7:0] Line number per input field */
430 /* 27 */ 0x0f, /* 7:0 [7:0] Vertical start of scaling window */
431 /* 28 */ 0x80, /* 7 Adaptive filter switch
432 6:5 Vertical luminance data processing
433 4 [8] Vertical start of scaling window
434 3:2 [9:8] Line number per input field
435 1:0 [9:8] Line number per output field */
436 /* 29 */ 0x16, /* 7:0 [7:0] Vertical bypass start */
437 /* 2a */ 0x00, /* 7:0 [7:0] Vertical bypass count */
438 /* 2b */ 0x00, /* 4 [8] Vertical bypass start
439 2 [8] Vertical bypass count
440 0 Polarity, internally detected odd even flag */
441 /* 2c */ 0x80, /* 7:0 Set lower limit V for colour-keying */
442 /* 2d */ 0x7f, /* 7:0 Set upper limit V for colour-keying */
443 /* 2e */ 0x80, /* 7:0 Set lower limit U for colour-keying */
444 /* 2f */ 0x7f, /* 7:0 Set upper limit U for colour-keying */
445 /* 30 */ 0xbf /* 7 VRAM bus output format
446 6 Adaptive geometrical filter
447 5 Luminance limiting value
448 4 Monochrome and two's complement output data sel
449 3 Line quailifier flag
450 2 Pixel qualifier flag
451 1 Transparent data transfer
452 0 Extended formats enable bit */
455 static u_char bt254_default[NUM_BT254_REGS] = {
456 0x00, /* 24 bpp */
457 0xa0,
458 0xa0,
459 0xa0,
460 0x50,
461 0x50,
462 0x50,
466 * i2c_write:
467 * Returns 0 Succesful completion.
468 * Returns 1 If transfer aborted or timeout occured.
471 static int i2c_print_err = 1;
472 static int
473 i2c_write(meteor_reg_t * mtr, u_char slave, u_char rw, u_char reg, u_char data)
475 unsigned long wait_counter = 0x0001ffff;
476 mreg_t * iic_write_loc = &mtr->base->i2c_write;
477 int err = 0;
480 /* Write the data the the i2c write register */
481 *iic_write_loc = SAA7116_IIC_NEW_CYCLE |
482 (((u_long)slave|(u_long)rw) << 16) |
483 ((u_long)reg << 8) | (u_long)data;
485 /* Wait until the i2c cycle is compeleted */
486 while((*iic_write_loc & SAA7116_IIC_NEW_CYCLE)) {
487 if(!wait_counter) break;
488 wait_counter--;
491 /* 1ffff should be enough delay time for the i2c cycle to complete */
492 if(!wait_counter) {
493 if(i2c_print_err)
494 kprintf("meteor%d: %d i2c %s transfer timeout 0x%x",
495 METEOR_NUM(mtr), slave,
496 rw ? "read" : "write", *iic_write_loc);
498 err=1;
501 /* Check for error on direct write, clear if any */
502 if(mtr->base->i2c_read & SAA7116_IIC_DIRECT_TRANSFER_ABORTED){
503 mtr->base->i2c_read |= SAA7116_IIC_DIRECT_TRANSFER_ABORTED;
504 if(i2c_print_err)
505 kprintf("meteor%d: 0x%x i2c %s transfer aborted",
506 METEOR_NUM(mtr), slave,
507 rw ? "read" : "write" );
508 err= 1;
511 if(err) {
512 if(i2c_print_err)
513 kprintf(" - reg=0x%x, value=0x%x.\n", reg, data);
516 return err;
518 #undef i2c_print
520 static const char *
521 met_probe (pcici_t tag, pcidi_t type)
523 switch (type) {
524 case SAA7116_PHILIPS_ID: /* meteor */
525 return("Philips SAA 7116");
527 return ((char *)0);
530 /* interrupt handling routine
531 complete meteor_read() if using interrupts
533 static void
534 meteor_intr(void *arg)
536 meteor_reg_t *mtr = (meteor_reg_t *) arg;
537 mreg_t *cap = &mtr->base->cap_cntl,
538 *base = &mtr->base->dma1e,
539 *stat = &mtr->base->irq_stat;
540 u_long status = *stat,
541 cap_err = *cap & 0x00000f00,
542 #ifdef METEOR_CHECK_PCI_BUS
543 pci_err = pci_conf_read(mtr->tag,
544 PCI_COMMAND_STATUS_REG),
545 #endif
546 next_base = (u_long)(vtophys(mtr->bigbuf));
549 * Disable future interrupts if a capture mode is not selected.
550 * This can happen when we are in the process of closing or
551 * changing capture modes, otherwise it shouldn't happen.
553 if(!(mtr->flags & METEOR_CAP_MASK)) {
554 *cap &= 0x8ff0; /* disable future interrupts */
556 #ifdef METEOR_CHECK_PCI_BUS
558 * Check for pci bus errors.
560 #define METEOR_MASTER_ABORT 0x20000000
561 #define METEOR_TARGET_ABORT 0x10000000
562 if(pci_err & METEOR_MASTER_ABORT) {
563 kprintf("meteor%d: intr: pci bus master dma abort: 0x%x 0x%x.\n",
564 METEOR_NUM(mtr), *base, *(base+3));
565 pci_conf_write(mtr->tag, PCI_COMMAND_STATUS_REG, pci_err);
567 if(pci_err & METEOR_TARGET_ABORT) {
568 kprintf("meteor%d: intr: pci bus target dma abort: 0x%x 0x%x.\n",
569 METEOR_NUM(mtr), *base, *(base+3));
570 pci_conf_write(mtr->tag, PCI_COMMAND_STATUS_REG, pci_err);
572 #endif
574 * Check for errors.
576 if (cap_err) {
577 if (cap_err & 0x300) {
578 if(mtr->fifo_errors % 50 == 0) {
579 kprintf("meteor%d: capture error", METEOR_NUM(mtr));
580 kprintf(": %s FIFO overflow.\n",
581 cap_err&0x0100? "even" : "odd");
583 mtr->fifo_errors++ ; /* increment fifo capture errors cnt */
585 if (cap_err & 0xc00) {
586 if(mtr->dma_errors % 50 == 0) {
587 kprintf("meteor%d: capture error", METEOR_NUM(mtr));
588 kprintf(": %s DMA address.\n",
589 cap_err&0x0400? "even" : "odd");
591 mtr->dma_errors++ ; /* increment DMA capture errors cnt */
594 *cap |= 0x0f30; /* clear error and field done */
597 * In synchronous capture mode we need to know what the address
598 * offset for the next field/frame will be. next_base holds the
599 * value for the even dma buffers (for odd, one must add stride).
601 if((mtr->flags & METEOR_SYNCAP) && !mtr->synch_wait &&
602 (mtr->current < mtr->frames)) { /* could be !=, but < is safer */
603 /* next_base is initialized to mtr->bigbuf */
604 next_base += mtr->frame_size * mtr->current;
605 if(mtr->flags & METEOR_WANT_TS)
606 next_base += sizeof(struct timeval) * mtr->current;
610 * Count the field and clear the field flag.
612 * In single mode capture, clear the continuous capture mode.
614 * In synchronous capture mode, if we have room for another field,
615 * adjust DMA buffer pointers.
616 * When we are above the hi water mark (hiwat), mtr->synch_wait will
617 * be set and we will not bump the DMA buffer pointers. Thus, once
618 * we reach the hi water mark, the driver acts like a continuous mode
619 * capture on the mtr->current frame until we hit the low water
620 * mark (lowat). The user had the option of stopping or halting
621 * the capture if this is not the desired effect.
623 if (status & 0x1) { /* even field */
624 mtr->even_fields_captured++;
625 mtr->flags &= ~METEOR_WANT_EVEN;
626 if((mtr->flags & METEOR_SYNCAP) && !mtr->synch_wait) {
627 *base = next_base;
628 /* XXX should add adjustments for YUV_422 & PLANAR */
631 * If the user requested to be notified via signal,
632 * let them know the field is complete.
634 if(mtr->proc && (mtr->signal & METEOR_SIG_MODE_MASK))
635 ksignal(mtr->proc, mtr->signal&(~METEOR_SIG_MODE_MASK));
637 if (status & 0x2) { /* odd field */
638 mtr->odd_fields_captured++;
639 mtr->flags &= ~METEOR_WANT_ODD;
640 if((mtr->flags & METEOR_SYNCAP) && !mtr->synch_wait) {
641 *(base+3) = next_base + *(base+6);
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 ksignal(mtr->proc, mtr->signal&(~METEOR_SIG_MODE_MASK));
653 * If we have a complete frame.
655 if(!(mtr->flags & METEOR_WANT_MASK)) {
656 mtr->frames_captured++;
658 * post the completion time.
660 if(mtr->flags & METEOR_WANT_TS) {
661 struct timeval *ts;
663 if(mtr->alloc_pages * PAGE_SIZE <= (mtr->frame_size +
664 sizeof(struct timeval))) {
665 ts =(struct timeval *)mtr->bigbuf +
666 mtr->frame_size;
667 /* doesn't work in synch mode except for first frame */
668 /* XXX */
669 microtime(ts);
673 * Wake up the user in single capture mode.
675 if(mtr->flags & METEOR_SINGLE)
676 wakeup((caddr_t)mtr);
678 * If the user requested to be notified via signal,
679 * let them know the frame is complete.
681 if(mtr->proc && !(mtr->signal & METEOR_SIG_MODE_MASK))
682 ksignal(mtr->proc, mtr->signal&(~METEOR_SIG_MODE_MASK));
684 * Reset the want flags if in continuous or
685 * synchronous capture mode.
687 if(mtr->flags & (METEOR_CONTIN|METEOR_SYNCAP)) {
688 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
689 case METEOR_ONLY_ODD_FIELDS:
690 mtr->flags |= METEOR_WANT_ODD;
691 break;
692 case METEOR_ONLY_EVEN_FIELDS:
693 mtr->flags |= METEOR_WANT_EVEN;
694 break;
695 default:
696 mtr->flags |= METEOR_WANT_MASK;
697 break;
701 * Special handling for synchronous capture mode.
703 if(mtr->flags & METEOR_SYNCAP) {
704 struct meteor_mem *mm = mtr->mem;
706 * Mark the current frame as active. It is up to
707 * the user to clear this, but we will clear it
708 * for the user for the current frame being captured
709 * if we are within the water marks (see below).
711 mm->active |= 1 << (mtr->current - 1);
714 * Since the user can muck with these values, we need
715 * to check and see if they are sane. If they don't
716 * pass the sanity check, disable the capture mode.
717 * This is rather rude, but then so was the user.
719 * Do we really need all of this or should we just
720 * eliminate the possiblity of allowing the
721 * user to change hi and lo water marks while it
722 * is running? XXX
724 if(mm->num_active_bufs < 0 ||
725 mm->num_active_bufs > mtr->frames ||
726 mm->lowat < 1 || mm->lowat >= mtr->frames ||
727 mm->hiwat < 1 || mm->hiwat >= mtr->frames ||
728 mm->lowat > mm->hiwat ) {
729 *cap &= 0x8ff0;
730 mtr->flags &= ~(METEOR_SYNCAP|METEOR_WANT_MASK);
731 } else {
733 * Ok, they are sane, now we want to
734 * check the water marks.
736 if(mm->num_active_bufs <= mm->lowat)
737 mtr->synch_wait = 0;
738 if(mm->num_active_bufs >= mm->hiwat)
739 mtr->synch_wait = 1;
741 * Clear the active frame bit for this frame
742 * and advance the counters if we are within
743 * the banks of the water marks.
745 if(!mtr->synch_wait) {
746 mm->active &= ~(1 << mtr->current);
747 mtr->current++;
748 if(mtr->current > mtr->frames)
749 mtr->current = 1;
750 mm->num_active_bufs++;
756 *stat |= 0x7; /* clear interrupt status */
757 return;
760 static void
761 set_fps(meteor_reg_t *mtr, u_short fps)
763 struct saa7116_regs *s7116 = mtr->base;
764 unsigned status;
765 unsigned maxfps, mask = 0x1, length = 0;
767 SAA7196_WRITE(mtr, SAA7196_STDC, SAA7196_REG(mtr, SAA7196_STDC) | 0x02);
768 SAA7196_READ(mtr);
769 status = (s7116->i2c_read & 0xff000000L) >> 24;
772 * Determine if there is an input signal. Depending on the
773 * frequency we either have a max of 25 fps (50 hz) or 30 fps (60 hz).
774 * If there is no input signal, then we need some defaults. If the
775 * user neglected to specify any defaults, just set to the fps to max.
777 if((status & 0x40) == 0) { /* Is there a signal ? */
778 if(status & 0x20) {
779 maxfps = 30; /* 60 hz system */
780 } else {
781 maxfps = 25; /* 50 hz system */
783 } else { /* We have no signal, check defaults */
784 #if METEOR_SYSTEM_DEFAULT == METEOR_PAL || METEOR_SYSTEM_DEFAULT == METEOR_SECAM
785 maxfps = 25;
786 #elif METEOR_SYSTEM_DEFAULT == METEOR_NTSC
787 maxfps = 30;
788 #else
789 /* Don't really know what to do, just set max */
790 maxfps = 30;
791 fps = 30;
792 #endif
796 * A little sanity checking...
798 if(fps < 1) fps = 1;
799 if(fps > maxfps) fps = maxfps;
802 * Compute the mask/length using the fps.
804 if(fps == maxfps) {
805 mask = 0x1;
806 length = 0x0;
807 } else if ((float)fps == maxfps/2.0) {
808 mask = 0x1;
809 length = 0x1;
810 } else if (fps > maxfps/2) {
811 float step, b;
813 mask = (1<<maxfps) - 1;
814 length = maxfps - 1;
815 step = (float)(maxfps - 1)/(float)(maxfps - fps);
816 for(b=step; b < maxfps; b += step) {
817 mask &= ~(1<<((int)b)); /* mask out the bth frame */
819 } else { /* fps < maxfps/2 */
820 float step, b;
822 mask = 0x1;
823 length = maxfps - 1;
824 step = (float)(maxfps -1)/(float)(fps);
825 for(b = step + 1; b < maxfps - 1; b += step) {
826 mask |= (1<<((int)b)); /* mask in the bth frame */
831 * Set the fps.
833 s7116->fme = s7116->fmo = mask;
834 s7116->fml = (length << 16) | length;
836 mtr->fps = fps;
838 return;
843 * There is also a problem with range checking on the 7116.
844 * It seems to only work for 22 bits, so the max size we can allocate
845 * is 22 bits long or 4194304 bytes assuming that we put the beginning
846 * of the buffer on a 2^24 bit boundary. The range registers will use
847 * the top 8 bits of the dma start registers along with the bottom 22
848 * bits of the range register to determine if we go out of range.
849 * This makes getting memory a real kludge.
852 #define RANGE_BOUNDARY (1<<22)
853 static vm_offset_t
854 get_meteor_mem(int unit, unsigned size)
856 vm_offset_t addr = 0;
858 addr = vm_page_alloc_contig(size, 0, 0xffffffff, 1<<24);
859 if(addr == 0)
860 addr = vm_page_alloc_contig(size, 0, 0xffffffff, PAGE_SIZE);
861 if(addr == 0) {
862 kprintf("meteor%d: Unable to allocate %d bytes of memory.\n",
863 unit, size);
866 return addr;
869 static void
870 bt254_write(meteor_reg_t *mtr, u_char addr, u_char data)
872 addr &= 0x7; /* sanity? */
873 mtr->bt254_reg[addr] = data;
874 PCF8574_DATA_WRITE(mtr, data); /* set data */
875 PCF8574_CTRL_WRITE(mtr, (PCF8574_CTRL_REG(mtr) & ~0x7) | addr);
876 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) & ~0x10); /* WR/ to 0 */
877 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x10); /* WR to 1 */
878 PCF8574_DATA_WRITE(mtr, 0xff); /* clr data */
882 static void
883 bt254_init(meteor_reg_t *mtr)
885 int i;
887 PCF8574_CTRL_WRITE(mtr, 0x7f);
888 PCF8574_DATA_WRITE(mtr, 0xff); /* data port must be 0xff */
889 PCF8574_CTRL_WRITE(mtr, 0x7f);
891 /* init RGB module for 24bpp, composite input */
892 for(i=0; i<NUM_BT254_REGS; i++)
893 bt254_write(mtr, i, bt254_default[i]);
895 bt254_write(mtr, BT254_COMMAND, 0x00); /* 24 bpp */
898 static void
899 bt254_ntsc(meteor_reg_t *mtr, int arg)
901 if (arg){
902 /* Set NTSC bit */
903 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x20);
905 else {
906 /* reset NTSC bit */
907 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) &= ~0x20);
911 static void
912 select_bt254(meteor_reg_t *mtr)
914 /* disable saa7196, saaen = 1 */
915 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x80);
916 /* enable Bt254, bten = 0 */
917 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) & ~0x40);
920 static void
921 select_saa7196(meteor_reg_t *mtr)
923 /* disable Bt254, bten = 1 */
924 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x40);
925 /* enable saa7196, saaen = 0 */
926 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) & ~0x80);
930 * Initialize the 7116, 7196 and the RGB module.
932 static void
933 meteor_init ( meteor_reg_t *mtr )
935 mreg_t *vbase_addr;
936 int i;
939 * Initialize the Philips SAA7116
941 mtr->base->cap_cntl = 0x00000040L;
942 vbase_addr = &mtr->base->dma1e;
943 for (i = 0 ; i < (sizeof(struct saa7116_regs)/sizeof(mreg_t)); i++)
944 *vbase_addr++ = saa7116_pci_default[i];
947 * Check for the Philips SAA7196
949 i2c_print_err = 0;
950 if(i2c_write(mtr, SAA7196_I2C_ADDR, SAA7116_I2C_WRITE, 0, 0xff) == 0) {
951 i2c_print_err = 1;
953 * Initialize 7196
955 for (i = 0; i < NUM_SAA7196_I2C_REGS; i++)
956 SAA7196_WRITE(mtr, i, saa7196_i2c_default[i]);
958 * Get version number.
960 SAA7196_WRITE(mtr, SAA7196_STDC,
961 SAA7196_REG(mtr, SAA7196_STDC) & ~0x02);
962 SAA7196_READ(mtr);
963 kprintf("meteor%d: <Philips SAA 7196> rev 0x%x\n",
964 METEOR_NUM(mtr),
965 (unsigned)((mtr->base->i2c_read & 0xff000000L) >> 28));
966 } else {
967 i2c_print_err = 1;
968 kprintf("meteor%d: <Philips SAA 7196 NOT FOUND>\n",
969 METEOR_NUM(mtr));
972 * Check for RGB module, initialized if found.
974 i2c_print_err = 0;
975 if(i2c_write(mtr,PCF8574_DATA_I2C_ADDR,SAA7116_I2C_WRITE,0,0xff) == 0) {
976 i2c_print_err = 1;
977 kprintf("meteor%d: <Booktree 254 (RGB module)>\n",
978 METEOR_NUM(mtr)); /* does this have a rev #? */
979 bt254_init(mtr); /* Set up RGB module */
980 mtr->flags = METEOR_RGB;
981 } else {
982 i2c_print_err = 1;
983 mtr->flags = 0;
986 set_fps(mtr, 30);
990 static void
991 met_attach(pcici_t tag, int unit)
993 #ifdef METEOR_IRQ
994 u_long old_irq, new_irq;
995 #endif /* METEOR_IRQ */
996 meteor_reg_t *mtr;
997 vm_offset_t buf;
998 u_long latency;
1000 if (unit >= NMETEOR) {
1001 kprintf("meteor%d: attach: only %d units configured.\n",
1002 unit, NMETEOR);
1003 kprintf("meteor%d: attach: invalid unit number.\n", unit);
1004 return ;
1008 * Check for Meteor/PPB (PCI-PCI Bridge)
1009 * Reprogram IBM Bridge if detected.
1010 * New Meteor cards have an IBM PCI-PCI bridge, creating a secondary
1011 * PCI bus. The SAA chip is connected to this secondary bus.
1014 /* If we are not on PCI Bus 0, check for the Bridge */
1015 if ( pci_get_bus_from_tag( tag ) != 0) {
1016 pcici_t bridge_tag;
1018 /* get tag of parent bridge */
1019 bridge_tag = pci_get_parent_from_tag( tag );
1021 /* Look for IBM 82351, 82352 or 82353 */
1022 if (pci_conf_read(bridge_tag, PCI_ID_REG) == 0x00221014) {
1024 if ( bootverbose)
1025 kprintf("meteor%d: PPB device detected, reprogramming IBM bridge.\n", unit);
1027 /* disable SERR */
1028 pci_cfgwrite(bridge_tag, 0x05, 0x00, 1);
1029 /* set LATENCY */
1030 pci_cfgwrite(bridge_tag, 0x0d, 0x20, 1);
1031 /* write posting enable, prefetch enabled --> GRAB direction */
1032 pci_cfgwrite(bridge_tag, 0x42, 0x14, 1);
1033 /* set PRTR Primary retry timer register */
1034 pci_cfgwrite(bridge_tag, 0x4c, 0x10, 1);
1038 mtr = &meteor[unit];
1039 mtr->tag = tag;
1040 pci_map_mem(tag, PCI_MAP_REG_START, (vm_offset_t *)&mtr->base,
1041 &mtr->phys_base);
1043 #ifdef METEOR_IRQ /* from the configuration file */
1044 old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
1045 pci_conf_write(tag, PCI_INTERRUPT_REG, METEOR_IRQ);
1046 new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
1047 kprintf("meteor%d: attach: irq changed from %d to %d\n",
1048 unit, (old_irq & 0xff), (new_irq & 0xff));
1049 #endif /* METEOR_IRQ */
1050 /* setup the interrupt handling routine */
1051 pci_map_int(tag, meteor_intr, (void*) mtr);
1054 * PCI latency timer. 32 is a good value for 4 bus mastering slots, if
1055 * you have more than for, then 16 would probably be a better value.
1058 #ifndef METEOR_DEF_LATENCY_VALUE
1059 #define METEOR_DEF_LATENCY_VALUE 32
1060 #endif
1061 latency = pci_conf_read(tag, PCI_LATENCY_TIMER);
1062 latency = (latency >> 8) & 0xff;
1063 if(bootverbose) {
1064 if(latency)
1065 kprintf("meteor%d: PCI bus latency is", unit);
1066 else
1067 kprintf("meteor%d: PCI bus latency was 0 changing to",
1068 unit);
1070 if(!latency) {
1071 latency = METEOR_DEF_LATENCY_VALUE;
1072 pci_conf_write(tag, PCI_LATENCY_TIMER, latency<<8);
1074 if(bootverbose) {
1075 kprintf(" %lu.\n", latency);
1078 meteor_init(mtr); /* set up saa7116, saa7196, and rgb module */
1080 if(METEOR_ALLOC)
1081 buf = get_meteor_mem(unit, METEOR_ALLOC);
1082 else
1083 buf = 0;
1084 if(bootverbose) {
1085 kprintf("meteor%d: buffer size %d, addr 0x%llx\n",
1086 unit, METEOR_ALLOC, vtophys(buf));
1089 mtr->bigbuf = buf;
1090 mtr->alloc_pages = METEOR_ALLOC_PAGES;
1091 if(buf != 0) {
1092 bzero((caddr_t) buf, METEOR_ALLOC);
1093 buf = vtophys(buf);
1094 /* 640x480 RGB 16 */
1095 mtr->base->dma1e = buf;
1096 mtr->base->dma1o = buf + 0x500;
1097 mtr->base->dma_end_e =
1098 mtr->base->dma_end_o = buf + METEOR_ALLOC;
1100 /* 1 frame of 640x480 RGB 16 */
1101 mtr->cols = 640;
1102 mtr->rows = 480;
1103 mtr->depth = 2; /* two bytes per pixel */
1104 mtr->frames = 1; /* one frame */
1106 mtr->flags |= METEOR_INITALIZED | METEOR_AUTOMODE | METEOR_DEV0 |
1107 METEOR_RGB16;
1108 dev_ops_add(&meteor_ops, -1, unit);
1109 make_dev(&meteor_ops, unit, 0, 0, 0644, "meteor");
1112 #define UNIT(x) ((x) & 0x07)
1114 #ifdef unused
1115 static int
1116 meteor_reset(cdev_t dev)
1118 int unit = UNIT(minor(dev));
1119 struct saa7116_regs *m;
1121 if(unit >= NMETEOR)
1122 return ENXIO;
1124 m = meteor[unit].base;
1126 m->cap_cntl = 0x0;
1127 tsleep((caddr_t)m, METPRI, "Mreset", hz/50);
1129 m->cap_cntl = 0x8ff0;
1130 m->cap_cntl = 0x80c0;
1131 m->cap_cntl = 0x8040;
1132 tsleep((caddr_t)m, METPRI, "Mreset", hz/10);
1133 m->cap_cntl = 0x80c0;
1135 return 0;
1138 #endif
1140 /*---------------------------------------------------------
1142 ** Meteor character device driver routines
1144 **---------------------------------------------------------
1148 meteor_open(struct dev_open_args *ap)
1150 cdev_t dev = ap->a_head.a_dev;
1151 meteor_reg_t *mtr;
1152 int unit;
1153 int i;
1155 unit = UNIT(minor(dev));
1156 if (unit >= NMETEOR) /* unit out of range */
1157 return(ENXIO);
1159 mtr = &(meteor[unit]);
1161 if (!(mtr->flags & METEOR_INITALIZED)) /* device not found */
1162 return(ENXIO);
1164 if (mtr->flags & METEOR_OPEN) /* device is busy */
1165 return(EBUSY);
1167 mtr->flags |= METEOR_OPEN;
1169 * Make sure that the i2c regs are set the same for each open.
1171 for(i=0; i< NUM_SAA7196_I2C_REGS; i++) {
1172 SAA7196_WRITE(mtr, i, saa7196_i2c_default[i]);
1175 mtr->fifo_errors = 0;
1176 mtr->dma_errors = 0;
1177 mtr->frames_captured = 0;
1178 mtr->even_fields_captured = 0;
1179 mtr->odd_fields_captured = 0;
1180 mtr->proc = (struct proc *)0;
1181 set_fps(mtr, 30);
1182 #ifdef METEOR_TEST_VIDEO
1183 mtr->video.addr = 0;
1184 mtr->video.width = 0;
1185 mtr->video.banksize = 0;
1186 mtr->video.ramsize = 0;
1187 #endif
1189 return(0);
1193 meteor_close(struct dev_close_args *ap)
1195 cdev_t dev = ap->a_head.a_dev;
1196 meteor_reg_t *mtr;
1197 int unit;
1198 #ifdef METEOR_DEALLOC_ABOVE
1199 int temp;
1200 #endif
1202 unit = UNIT(minor(dev));
1203 if (unit >= NMETEOR) /* unit out of range */
1204 return(ENXIO);
1206 mtr = &(meteor[unit]);
1207 mtr->flags &= ~METEOR_OPEN;
1209 if(mtr->flags & METEOR_SINGLE)
1210 /* this should not happen, the read capture
1211 should have completed or in the very least
1212 recieved a signal before close is called. */
1213 wakeup((caddr_t)mtr); /* continue read */
1215 * Turn off capture mode.
1217 mtr->base->cap_cntl = 0x8ff0;
1218 mtr->flags &= ~(METEOR_CAP_MASK|METEOR_WANT_MASK);
1219 mtr->proc = (struct proc *)0;
1221 #ifdef METEOR_DEALLOC_PAGES
1222 if (mtr->bigbuf != NULL) {
1223 kmem_free(&kernel_map, mtr->bigbuf,
1224 (mtr->alloc_pages * PAGE_SIZE));
1225 mtr->bigbuf = NULL;
1226 mtr->alloc_pages = 0;
1228 #else
1229 #ifdef METEOR_DEALLOC_ABOVE
1230 if (mtr->bigbuf != NULL && mtr->alloc_pages > METEOR_DEALLOC_ABOVE) {
1231 temp = METEOR_DEALLOC_ABOVE - mtr->alloc_pages;
1232 kmem_free(&kernel_map,
1233 mtr->bigbuf+((mtr->alloc_pages - temp) * PAGE_SIZE),
1234 (temp * PAGE_SIZE));
1235 mtr->alloc_pages = METEOR_DEALLOC_ABOVE;
1237 #endif
1238 #endif
1240 return(0);
1243 static void
1244 start_capture(meteor_reg_t *mtr, unsigned type)
1246 mreg_t *cap = &mtr->base->cap_cntl;
1248 mtr->flags |= type;
1249 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1250 case METEOR_ONLY_EVEN_FIELDS:
1251 mtr->flags |= METEOR_WANT_EVEN;
1252 if(type == METEOR_SINGLE)
1253 *cap = 0x0ff4 | mtr->range_enable;
1254 else
1255 *cap = 0x0ff1 | mtr->range_enable;
1256 break;
1257 case METEOR_ONLY_ODD_FIELDS:
1258 mtr->flags |= METEOR_WANT_ODD;
1259 if(type == METEOR_SINGLE)
1260 *cap = 0x0ff8 | mtr->range_enable;
1261 else
1262 *cap = 0x0ff2 | mtr->range_enable;
1263 break;
1264 default:
1265 mtr->flags |= METEOR_WANT_MASK;
1266 if(type == METEOR_SINGLE)
1267 *cap = 0x0ffc | mtr->range_enable;
1268 else
1269 *cap = 0x0ff3 | mtr->range_enable;
1270 break;
1275 meteor_read(struct dev_read_args *ap)
1277 cdev_t dev = ap->a_head.a_dev;
1278 struct uio *uio = ap->a_uio;
1279 meteor_reg_t *mtr;
1280 int unit;
1281 int status;
1282 int count;
1284 unit = UNIT(minor(dev));
1285 if (unit >= NMETEOR) /* unit out of range */
1286 return(ENXIO);
1288 mtr = &(meteor[unit]);
1289 if (mtr->bigbuf == 0)/* no frame buffer allocated (ioctl failed) */
1290 return(ENOMEM);
1292 if (mtr->flags & METEOR_CAP_MASK)
1293 return(EIO); /* already capturing */
1295 count = mtr->rows * mtr->cols * mtr->depth;
1296 if (uio->uio_iov->iov_len < count)
1297 return(EINVAL);
1299 /* Start capture */
1300 start_capture(mtr, METEOR_SINGLE);
1302 status=tsleep((caddr_t)mtr, METPRI, "capturing", 0);
1303 if (!status) /* successful capture */
1304 status = uiomove((caddr_t)mtr->bigbuf, count, uio);
1305 else
1306 kprintf ("meteor%d: read: tsleep error %d\n", unit, status);
1308 mtr->flags &= ~(METEOR_SINGLE | METEOR_WANT_MASK);
1310 return(status);
1314 meteor_write(struct dev_write_args *ap)
1316 return(0);
1320 meteor_ioctl(struct dev_ioctl_args *ap)
1322 cdev_t dev = ap->a_head.a_dev;
1323 caddr_t data = ap->a_data;
1324 int error;
1325 int unit;
1326 unsigned int temp;
1327 meteor_reg_t *mtr;
1328 struct meteor_counts *cnt;
1329 struct meteor_geomet *geo;
1330 struct meteor_mem *mem;
1331 struct meteor_capframe *frame;
1332 #ifdef METEOR_TEST_VIDEO
1333 struct meteor_video *video;
1334 #endif
1335 vm_offset_t buf;
1336 struct saa7116_regs *base;
1338 error = 0;
1340 if (data == NULL)
1341 return(EINVAL);
1342 unit = UNIT(minor(dev));
1343 if (unit >= NMETEOR) /* unit out of range */
1344 return(ENXIO);
1346 mtr = &(meteor[unit]);
1347 base = mtr->base;
1349 switch (ap->a_cmd) {
1350 case METEORSTS:
1351 if(*data)
1352 mtr->flags |= METEOR_WANT_TS;
1353 else
1354 mtr->flags &= ~METEOR_WANT_TS;
1355 break;
1356 case METEORGTS:
1357 if(mtr->flags & METEOR_WANT_TS)
1358 *data = 1;
1359 else
1360 *data = 0;
1361 break;
1362 #ifdef METEOR_TEST_VIDEO
1363 case METEORGVIDEO:
1364 video = (struct meteor_video *)data;
1365 video->addr = mtr->video.addr;
1366 video->width = mtr->video.width;
1367 video->banksize = mtr->video.banksize;
1368 video->ramsize = mtr->video.ramsize;
1369 break;
1370 case METEORSVIDEO:
1371 video = (struct meteor_video *)data;
1372 mtr->video.addr = video->addr;
1373 mtr->video.width = video->width;
1374 mtr->video.banksize = video->banksize;
1375 mtr->video.ramsize = video->ramsize;
1376 break;
1377 #endif
1378 case METEORSFPS:
1379 set_fps(mtr, *(u_short *)data);
1380 break;
1381 case METEORGFPS:
1382 *(u_short *)data = mtr->fps;
1383 break;
1384 case METEORSSIGNAL:
1385 if (*(int *)data < 0 || *(int *)data > _SIG_MAXSIG)
1386 return EINVAL;
1387 mtr->signal = *(int *) data;
1388 if (mtr->signal) {
1389 mtr->proc = curproc; /* might be NULL */
1390 } else {
1391 mtr->proc = (struct proc *)0;
1393 break;
1394 case METEORGSIGNAL:
1395 *(int *)data = mtr->signal;
1396 break;
1397 case METEORSTATUS: /* get 7196 status */
1398 temp = 0;
1399 SAA7196_WRITE(mtr, SAA7196_STDC,
1400 SAA7196_REG(mtr, SAA7196_STDC) | 0x02);
1401 SAA7196_READ(mtr);
1402 temp |= (base->i2c_read & 0xff000000L) >> 24;
1403 SAA7196_WRITE(mtr, SAA7196_STDC,
1404 SAA7196_REG(mtr, SAA7196_STDC) & ~0x02);
1405 SAA7196_READ(mtr);
1406 temp |= (base->i2c_read & 0xff000000L) >> 16;
1407 *(u_short *)data = temp;
1408 break;
1409 case METEORSHUE: /* set hue */
1410 SAA7196_WRITE(mtr, SAA7196_HUEC, *(char *)data);
1411 break;
1412 case METEORGHUE: /* get hue */
1413 *(char *)data = SAA7196_REG(mtr, SAA7196_HUEC);
1414 break;
1415 case METEORSCHCV: /* set chrominance gain */
1416 SAA7196_WRITE(mtr, SAA7196_CGAINR, *(char *)data);
1417 break;
1418 case METEORGCHCV: /* get chrominance gain */
1419 *(char *)data = SAA7196_REG(mtr, SAA7196_CGAINR);
1420 break;
1421 case METEORSBRIG: /* set brightness */
1422 SAA7196_WRITE(mtr, SAA7196_BRIG, *(char *)data);
1423 break;
1424 case METEORGBRIG: /* get brightness */
1425 *(char *)data = SAA7196_REG(mtr, SAA7196_BRIG);
1426 break;
1427 case METEORSCSAT: /* set chroma saturation */
1428 SAA7196_WRITE(mtr, SAA7196_CSAT, *(char *)data);
1429 break;
1430 case METEORGCSAT: /* get chroma saturation */
1431 *(char *)data = SAA7196_REG(mtr, SAA7196_CSAT);
1432 break;
1433 case METEORSCONT: /* set contrast */
1434 SAA7196_WRITE(mtr, SAA7196_CONT, *(char *)data);
1435 break;
1436 case METEORGCONT: /* get contrast */
1437 *(char *)data = SAA7196_REG(mtr, SAA7196_CONT);
1438 break;
1439 case METEORSBT254:
1440 if((mtr->flags & METEOR_RGB) == 0)
1441 return EINVAL;
1442 temp = *(unsigned short *)data;
1443 bt254_write(mtr, temp & 0xf, (temp & 0x0ff0) >> 4);
1444 break;
1445 case METEORGBT254:
1446 if((mtr->flags & METEOR_RGB) == 0)
1447 return EINVAL;
1448 temp = *(unsigned short *)data & 0x7;
1449 *(unsigned short *)data = mtr->bt254_reg[temp] << 4 | temp;
1450 break;
1451 case METEORSHWS: /* set horizontal window start */
1452 SAA7196_WRITE(mtr, SAA7196_HWS, *(char *)data);
1453 break;
1454 case METEORGHWS: /* get horizontal window start */
1455 *(char *)data = SAA7196_REG(mtr, SAA7196_HWS);
1456 break;
1457 case METEORSVWS: /* set vertical window start */
1458 SAA7196_WRITE(mtr, SAA7196_VWS, *(char *)data);
1459 break;
1460 case METEORGVWS: /* get vertical window start */
1461 *(char *)data = SAA7196_REG(mtr, SAA7196_VWS);
1462 break;
1463 case METEORSINPUT: /* set input device */
1464 switch(*(unsigned long *)data & METEOR_DEV_MASK) {
1465 case 0: /* default */
1466 case METEOR_INPUT_DEV0:
1467 if(mtr->flags & METEOR_RGB)
1468 select_saa7196(mtr);
1469 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1470 | METEOR_DEV0;
1471 SAA7196_WRITE(mtr, 0x0e,
1472 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x0);
1473 SAA7196_WRITE(mtr, 0x06,
1474 (SAA7196_REG(mtr, 0x06) & ~0x80));
1475 break;
1476 case METEOR_INPUT_DEV1:
1477 if(mtr->flags & METEOR_RGB)
1478 select_saa7196(mtr);
1479 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1480 | METEOR_DEV1;
1481 SAA7196_WRITE(mtr, 0x0e,
1482 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x1);
1483 SAA7196_WRITE(mtr, 0x06,
1484 (SAA7196_REG(mtr, 0x06) & ~0x80));
1485 break;
1486 case METEOR_INPUT_DEV2:
1487 if(mtr->flags & METEOR_RGB)
1488 select_saa7196(mtr);
1489 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1490 | METEOR_DEV2;
1491 SAA7196_WRITE(mtr, 0x0e,
1492 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x2);
1493 SAA7196_WRITE(mtr, 0x06,
1494 (SAA7196_REG(mtr, 0x06) & ~0x80));
1495 break;
1496 case METEOR_INPUT_DEV3:
1497 if(mtr->flags & METEOR_RGB)
1498 select_saa7196(mtr);
1499 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1500 | METEOR_DEV3;
1501 SAA7196_WRITE(mtr, 0x0e,
1502 (SAA7196_REG(mtr, 0x0e) | 0x3));
1503 SAA7196_WRITE(mtr, 0x06,
1504 (SAA7196_REG(mtr, 0x06) & ~0x80) );
1505 break;
1506 case METEOR_INPUT_DEV_SVIDEO:
1507 if(mtr->flags & METEOR_RGB)
1508 select_saa7196(mtr);
1509 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1510 | METEOR_DEV_SVIDEO;
1511 SAA7196_WRITE(mtr, 0x0e,
1512 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x2);
1513 SAA7196_WRITE(mtr, 0x06,
1514 (SAA7196_REG(mtr, 0x06) & ~0x80) | 0x80);
1515 break;
1516 case METEOR_INPUT_DEV_RGB:
1517 if((mtr->flags & METEOR_RGB) == 0)
1518 return EINVAL;
1519 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1520 | METEOR_DEV_RGB;
1521 SAA7196_WRITE(mtr, 0x0e,
1522 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x3);
1523 SAA7196_WRITE(mtr, 0x06,
1524 (SAA7196_REG(mtr, 0x06) & ~0x80));
1525 select_bt254(mtr);
1526 SAA7196_WRITE(mtr, 0x0e, /* chn 3 for synch */
1527 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x3);
1528 break;
1529 default:
1530 return EINVAL;
1532 break;
1533 case METEORGINPUT: /* get input device */
1534 *(u_long *)data = mtr->flags & METEOR_DEV_MASK;
1535 break;
1536 case METEORSFMT: /* set input format */
1537 switch(*(unsigned long *)data & METEOR_FORM_MASK ) {
1538 case 0: /* default */
1539 case METEOR_FMT_NTSC:
1540 mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1541 METEOR_NTSC;
1542 SAA7196_WRITE(mtr, SAA7196_STDC,
1543 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01));
1544 SAA7196_WRITE(mtr, 0x0f,
1545 (SAA7196_REG(mtr, 0x0f) & ~0xe0) | 0x40);
1546 SAA7196_WRITE(mtr, 0x22, 0x80);
1547 SAA7196_WRITE(mtr, 0x24,
1548 (SAA7196_REG(mtr, 0x24) & ~0x0c) | 0x08);
1549 SAA7196_WRITE(mtr, 0x26, 0xf0);
1550 SAA7196_WRITE(mtr, 0x28,
1551 (SAA7196_REG(mtr, 0x28) & ~0x0c)) ;
1552 if(mtr->flags & METEOR_RGB){
1553 bt254_ntsc(mtr, 1);
1555 break;
1556 case METEOR_FMT_PAL:
1557 mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1558 METEOR_PAL;
1559 SAA7196_WRITE(mtr, SAA7196_STDC,
1560 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01));
1561 SAA7196_WRITE(mtr, 0x0f,
1562 (SAA7196_REG(mtr, 0x0f) & ~0xe0));
1563 SAA7196_WRITE(mtr, 0x22, 0x00);
1564 SAA7196_WRITE(mtr, 0x24,
1565 (SAA7196_REG(mtr, 0x24) | 0x0c));
1566 SAA7196_WRITE(mtr, 0x26, 0x20);
1567 SAA7196_WRITE(mtr, 0x28,
1568 (SAA7196_REG(mtr, 0x28) & ~0x0c) | 0x04) ;
1569 if(mtr->flags & METEOR_RGB){
1570 bt254_ntsc(mtr, 0);
1572 break;
1573 case METEOR_FMT_SECAM:
1574 mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1575 METEOR_SECAM;
1576 SAA7196_WRITE(mtr, SAA7196_STDC,
1577 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01) | 0x1);
1578 SAA7196_WRITE(mtr, 0x0f,
1579 (SAA7196_REG(mtr, 0x0f) & ~0xe0) | 0x20);
1580 SAA7196_WRITE(mtr, 0x22, 0x00);
1581 SAA7196_WRITE(mtr, 0x24,
1582 (SAA7196_REG(mtr, 0x24) | 0x0c));
1583 SAA7196_WRITE(mtr, 0x26, 0x20);
1584 SAA7196_WRITE(mtr, 0x28,
1585 (SAA7196_REG(mtr, 0x28) & ~0x0c) | 0x04) ;
1586 if(mtr->flags & METEOR_RGB){
1587 bt254_ntsc(mtr, 0);
1589 break;
1590 case METEOR_FMT_AUTOMODE:
1591 mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1592 METEOR_AUTOMODE;
1593 SAA7196_WRITE(mtr, SAA7196_STDC,
1594 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01));
1595 SAA7196_WRITE(mtr, 0x0f,
1596 (SAA7196_REG(mtr, 0x0f) & ~0xe0) | 0x80);
1597 break;
1598 default:
1599 return EINVAL;
1601 break;
1602 case METEORGFMT: /* get input format */
1603 *(u_long *)data = mtr->flags & METEOR_FORM_MASK;
1604 break;
1605 case METEORCAPTUR:
1606 temp = mtr->flags;
1607 switch (*(int *) data) {
1608 case METEOR_CAP_SINGLE:
1609 if (mtr->bigbuf==0) /* no frame buffer allocated */
1610 return(ENOMEM);
1612 if (temp & METEOR_CAP_MASK)
1613 return(EIO); /* already capturing */
1615 start_capture(mtr, METEOR_SINGLE);
1617 /* wait for capture to complete */
1618 error=tsleep((caddr_t)mtr, METPRI, "capturing", 0);
1619 if(error)
1620 kprintf("meteor%d: ioctl: tsleep error %d\n",
1621 unit, error);
1622 mtr->flags &= ~(METEOR_SINGLE|METEOR_WANT_MASK);
1623 break;
1624 case METEOR_CAP_CONTINOUS:
1625 if (mtr->bigbuf==0) /* no frame buffer allocated */
1626 return(ENOMEM);
1628 if (temp & METEOR_CAP_MASK)
1629 return(EIO); /* already capturing */
1631 start_capture(mtr, METEOR_CONTIN);
1633 break;
1634 case METEOR_CAP_STOP_CONT:
1635 if (mtr->flags & METEOR_CONTIN) {
1636 /* turn off capture */
1637 base->cap_cntl = 0x8ff0;
1638 mtr->flags &= ~(METEOR_CONTIN|METEOR_WANT_MASK);
1640 break;
1642 default:
1643 error = EINVAL;
1644 break;
1646 break;
1647 case METEORCAPFRM:
1648 frame = (struct meteor_capframe *) data;
1649 if (!frame)
1650 return(EINVAL);
1651 switch (frame->command) {
1652 case METEOR_CAP_N_FRAMES:
1653 if (mtr->flags & METEOR_CAP_MASK)
1654 return(EIO);
1655 if (mtr->flags & (METEOR_YUV_PLANAR | METEOR_YUV_422)) /* XXX */
1656 return(EINVAL); /* should fix intr so we allow these */
1657 if (mtr->bigbuf == 0)
1658 return(ENOMEM);
1659 if ((mtr->frames < 2) ||
1660 (frame->lowat < 1 || frame->lowat >= mtr->frames) ||
1661 (frame->hiwat < 1 || frame->hiwat >= mtr->frames) ||
1662 (frame->lowat > frame->hiwat))
1663 return(EINVAL);
1664 /* meteor_mem structure is on the page after the data */
1665 mem = mtr->mem = (struct meteor_mem *) (mtr->bigbuf +
1666 (round_page(mtr->frame_size * mtr->frames)));
1667 mtr->current = 1;
1668 mtr->synch_wait = 0;
1669 mem->num_bufs = mtr->frames;
1670 mem->frame_size= mtr->frame_size;
1671 /* user and kernel change these */
1672 mem->lowat = frame->lowat;
1673 mem->hiwat = frame->hiwat;
1674 mem->active = 0;
1675 mem->num_active_bufs = 0;
1676 /* Start capture */
1677 start_capture(mtr, METEOR_SYNCAP);
1678 break;
1679 case METEOR_CAP_STOP_FRAMES:
1680 if (mtr->flags & METEOR_SYNCAP) {
1681 /* turn off capture */
1682 base->cap_cntl = 0x8ff0;
1683 mtr->flags &= ~(METEOR_SYNCAP|METEOR_WANT_MASK);
1685 break;
1686 case METEOR_HALT_N_FRAMES:
1687 if(mtr->flags & METEOR_SYNCAP) {
1688 base->cap_cntl = 0x8ff0;
1689 mtr->flags &= ~(METEOR_WANT_MASK);
1691 break;
1692 case METEOR_CONT_N_FRAMES:
1693 if(!(mtr->flags & METEOR_SYNCAP)) {
1694 error = EINVAL;
1695 break;
1697 start_capture(mtr, METEOR_SYNCAP);
1698 break;
1699 default:
1700 error = EINVAL;
1701 break;
1703 break;
1705 case METEORSETGEO:
1706 geo = (struct meteor_geomet *) data;
1708 /* Either even or odd, if even & odd, then these a zero */
1709 if((geo->oformat & METEOR_GEO_ODD_ONLY) &&
1710 (geo->oformat & METEOR_GEO_EVEN_ONLY)) {
1711 kprintf("meteor%d: ioctl: Geometry odd or even only.\n",
1712 unit);
1713 return EINVAL;
1715 /* set/clear even/odd flags */
1716 if(geo->oformat & METEOR_GEO_ODD_ONLY)
1717 mtr->flags |= METEOR_ONLY_ODD_FIELDS;
1718 else
1719 mtr->flags &= ~METEOR_ONLY_ODD_FIELDS;
1720 if(geo->oformat & METEOR_GEO_EVEN_ONLY)
1721 mtr->flags |= METEOR_ONLY_EVEN_FIELDS;
1722 else
1723 mtr->flags &= ~METEOR_ONLY_EVEN_FIELDS;
1725 /* can't change parameters while capturing */
1726 if (mtr->flags & METEOR_CAP_MASK)
1727 return(EBUSY);
1729 if ((geo->columns & 0x3fe) != geo->columns) {
1730 kprintf(
1731 "meteor%d: ioctl: %d: columns too large or not even.\n",
1732 unit, geo->columns);
1733 error = EINVAL;
1735 if (((geo->rows & 0x7fe) != geo->rows) ||
1736 ((geo->oformat & METEOR_GEO_FIELD_MASK) &&
1737 ((geo->rows & 0x3fe) != geo->rows)) ) {
1738 kprintf(
1739 "meteor%d: ioctl: %d: rows too large or not even.\n",
1740 unit, geo->rows);
1741 error = EINVAL;
1743 if (geo->frames > 32) {
1744 kprintf("meteor%d: ioctl: too many frames.\n", unit);
1745 error = EINVAL;
1747 if(error) return error;
1749 if ((temp=geo->rows * geo->columns * geo->frames * 2) != 0) {
1750 if (geo->oformat & METEOR_GEO_RGB24) temp = temp * 2;
1752 /* meteor_mem structure for SYNC Capture */
1753 if (geo->frames > 1) temp += PAGE_SIZE;
1755 temp = btoc(temp);
1756 if (temp > mtr->alloc_pages
1757 #ifdef METEOR_TEST_VIDEO
1758 && mtr->video.addr == 0
1759 #endif
1761 buf = get_meteor_mem(unit, temp*PAGE_SIZE);
1762 if(buf != 0) {
1763 kmem_free(&kernel_map, mtr->bigbuf,
1764 (mtr->alloc_pages * PAGE_SIZE));
1765 mtr->bigbuf = buf;
1766 mtr->alloc_pages = temp;
1767 if(bootverbose)
1768 kprintf(
1769 "meteor%d: ioctl: Allocating %d bytes\n",
1770 unit, temp*PAGE_SIZE);
1771 } else {
1772 error = ENOMEM;
1776 if(error) return error;
1778 mtr->rows = geo->rows;
1779 mtr->cols = geo->columns;
1780 mtr->frames = geo->frames;
1782 #ifdef METEOR_TEST_VIDEO
1783 if(mtr->video.addr)
1784 buf = vtophys(mtr->video.addr);
1785 else
1786 #endif
1787 buf = vtophys(mtr->bigbuf);
1789 /* set defaults and end of buffer locations */
1790 base->dma1e = buf;
1791 base->dma2e = buf;
1792 base->dma3e = buf;
1793 base->dma1o = buf;
1794 base->dma2o = buf;
1795 base->dma3o = buf;
1796 base->stride1e = 0;
1797 base->stride2e = 0;
1798 base->stride3e = 0;
1799 base->stride1o = 0;
1800 base->stride2o = 0;
1801 base->stride3o = 0;
1802 /* set end of DMA location, even/odd */
1803 base->dma_end_e =
1804 base->dma_end_o = buf + mtr->alloc_pages * PAGE_SIZE;
1807 * Determine if we can use the hardware range detect.
1809 if(mtr->alloc_pages * PAGE_SIZE < RANGE_BOUNDARY &&
1810 ((buf & 0xff000000) | base->dma_end_e) ==
1811 (buf + mtr->alloc_pages * PAGE_SIZE) )
1812 mtr->range_enable = 0x8000;
1813 else {
1814 mtr->range_enable = 0x0;
1815 base->dma_end_e =
1816 base->dma_end_o = 0xffffffff;
1820 switch (geo->oformat & METEOR_GEO_OUTPUT_MASK) {
1821 case 0: /* default */
1822 case METEOR_GEO_RGB16:
1823 mtr->depth = 2;
1824 mtr->frame_size = mtr->rows * mtr->cols * mtr->depth;
1825 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1826 mtr->flags |= METEOR_RGB16;
1827 temp = mtr->cols * mtr->depth;
1828 /* recal stride and starting point */
1829 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1830 case METEOR_ONLY_ODD_FIELDS:
1831 base->dma1o = buf;
1832 #ifdef METEOR_TEST_VIDEO
1833 if(mtr->video.addr && mtr->video.width)
1834 base->stride1o = mtr->video.width-temp;
1835 #endif
1836 SAA7196_WRITE(mtr, 0x20, 0xd0);
1837 break;
1838 case METEOR_ONLY_EVEN_FIELDS:
1839 base->dma1e = buf;
1840 #ifdef METEOR_TEST_VIDEO
1841 if(mtr->video.addr && mtr->video.width)
1842 base->stride1e = mtr->video.width-temp;
1843 #endif
1844 SAA7196_WRITE(mtr, 0x20, 0xf0);
1845 break;
1846 default: /* interlaced even/odd */
1847 base->dma1e = buf;
1848 base->dma1o = buf + temp;
1849 base->stride1e = base->stride1o = temp;
1850 #ifdef METEOR_TEST_VIDEO
1851 if(mtr->video.addr && mtr->video.width) {
1852 base->dma1o = buf + mtr->video.width;
1853 base->stride1e = base->stride1o =
1854 mtr->video.width -
1855 temp + mtr->video.width;
1857 #endif
1858 SAA7196_WRITE(mtr, 0x20, 0x90);
1859 break;
1861 base->routee = base->routeo = 0xeeeeee01;
1862 break;
1863 case METEOR_GEO_RGB24:
1864 mtr->depth = 4;
1865 mtr->frame_size = mtr->rows * mtr->cols * mtr->depth;
1866 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1867 mtr->flags |= METEOR_RGB24;
1868 temp = mtr->cols * mtr->depth;
1869 /* recal stride and starting point */
1870 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1871 case METEOR_ONLY_ODD_FIELDS:
1872 base->dma1o = buf;
1873 #ifdef METEOR_TEST_VIDEO
1874 if(mtr->video.addr && mtr->video.width)
1875 base->stride1o = mtr->video.width-temp;
1876 #endif
1877 SAA7196_WRITE(mtr, 0x20, 0xd2);
1878 break;
1879 case METEOR_ONLY_EVEN_FIELDS:
1880 base->dma1e = buf;
1881 #ifdef METEOR_TEST_VIDEO
1882 if(mtr->video.addr && mtr->video.width)
1883 base->stride1e = mtr->video.width-temp;
1884 #endif
1885 SAA7196_WRITE(mtr, 0x20, 0xf2);
1886 break;
1887 default: /* interlaced even/odd */
1888 base->dma1e = buf;
1889 base->dma1o = buf + mtr->cols * mtr->depth;
1890 base->stride1e = base->stride1o =
1891 mtr->cols * mtr->depth;
1892 #ifdef METEOR_TEST_VIDEO
1893 if(mtr->video.addr && mtr->video.width) {
1894 base->dma1o = buf + mtr->video.width;
1895 base->stride1e = base->stride1o =
1896 mtr->video.width -
1897 temp + mtr->video.width;
1899 #endif
1900 SAA7196_WRITE(mtr, 0x20, 0x92);
1901 break;
1903 base->routee= base->routeo= 0x39393900;
1904 break;
1905 case METEOR_GEO_YUV_PLANAR:
1906 mtr->depth = 2;
1907 temp = mtr->rows * mtr->cols; /* compute frame size */
1908 mtr->frame_size = temp * mtr->depth;
1909 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1910 mtr->flags |= METEOR_YUV_PLANAR;
1911 /* recal stride and starting point */
1912 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1913 case METEOR_ONLY_ODD_FIELDS:
1914 base->dma1o = buf; /* Y Odd */
1915 base->dma2o = buf + temp; /* U Odd */
1916 temp >>= 1;
1917 base->dma3o = base->dma2o + temp; /* V Odd */
1918 SAA7196_WRITE(mtr, 0x20, 0xd1);
1919 break;
1920 case METEOR_ONLY_EVEN_FIELDS:
1921 base->dma1e = buf; /* Y Even */
1922 base->dma2e = buf + temp; /* U Even */
1923 temp >>= 1;
1924 base->dma2e= base->dma2e + temp; /* V Even */
1925 SAA7196_WRITE(mtr, 0x20, 0xf1);
1926 break;
1927 default: /* interlaced even/odd */
1928 base->dma1e = buf; /* Y Even */
1929 base->dma2e = buf + temp; /* U Even */
1930 temp >>= 2;
1931 base->dma3e = base->dma2e + temp; /* V Even */
1932 base->dma1o = base->dma1e+mtr->cols;/* Y Odd */
1933 base->dma2o = base->dma3e + temp; /* U Odd */
1934 base->dma3o = base->dma2o + temp; /* V Odd */
1935 base->stride1e = base->stride1o = mtr->cols;
1936 SAA7196_WRITE(mtr, 0x20, 0x91);
1937 break;
1939 switch (geo->oformat &
1940 (METEOR_GEO_YUV_12 | METEOR_GEO_YUV_9)) {
1941 case METEOR_GEO_YUV_9:
1942 base->routee=base->routeo = 0xaaaaffc3;
1943 break;
1944 case METEOR_GEO_YUV_12:
1945 base->routee=base->routeo = 0xaaaaffc2;
1946 break;
1947 default:
1948 base->routee=base->routeo = 0xaaaaffc1;
1949 break;
1951 break;
1952 case METEOR_GEO_YUV_422:/* same as planer, different uv order */
1953 mtr->depth = 2;
1954 temp = mtr->rows * mtr->cols; /* compute frame size */
1955 mtr->frame_size = temp * mtr->depth;
1956 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1957 mtr->flags |= METEOR_YUV_422;
1958 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1959 case METEOR_ONLY_ODD_FIELDS:
1960 base->dma1o = buf;
1961 base->dma2o = buf + temp;
1962 base->dma3o = base->dma2o + (temp >> 1);
1963 SAA7196_WRITE(mtr, 0x20, 0xd1);
1964 break;
1965 case METEOR_ONLY_EVEN_FIELDS:
1966 base->dma1e = buf;
1967 base->dma2e = buf + temp;
1968 base->dma3e = base->dma2e + (temp >> 1);
1969 SAA7196_WRITE(mtr, 0x20, 0xf1);
1970 break;
1971 default: /* interlaced even/odd */
1972 base->dma1e = buf; /* Y even */
1973 base->dma2e = buf + temp; /* U even */
1974 base->dma3e =
1975 base->dma2e + (temp >> 1);/* V even */
1976 base->dma1o = base->dma1e+mtr->cols;/* Y odd */
1977 temp = mtr->cols >> 1;
1978 base->dma2o = base->dma2e+temp; /* U odd */
1979 base->dma3o = base->dma3e+temp; /* V odd */
1980 base->stride1e =
1981 base->stride1o = mtr->cols; /* Y stride */
1982 base->stride2e =
1983 base->stride2o = temp; /* U stride */
1984 base->stride3e =
1985 base->stride3o = temp; /* V stride */
1986 SAA7196_WRITE(mtr, 0x20, 0x91);
1987 break;
1989 switch (geo->oformat &
1990 (METEOR_GEO_YUV_12 | METEOR_GEO_YUV_9)) {
1991 case METEOR_GEO_YUV_9:
1992 base->routee=base->routeo = 0xaaaaffc3;
1993 break;
1994 case METEOR_GEO_YUV_12:
1995 base->routee=base->routeo = 0xaaaaffc2;
1996 break;
1997 default:
1998 base->routee=base->routeo = 0xaaaaffc1;
1999 break;
2001 break;
2002 case METEOR_GEO_YUV_PACKED:
2003 mtr->depth = 2;
2004 mtr->frame_size = mtr->rows * mtr->cols * mtr->depth;
2005 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
2006 mtr->flags |= METEOR_YUV_PACKED;
2007 /* recal stride and odd starting point */
2008 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
2009 case METEOR_ONLY_ODD_FIELDS:
2010 base->dma1o = buf;
2011 SAA7196_WRITE(mtr, 0x20, 0xd1);
2012 break;
2013 case METEOR_ONLY_EVEN_FIELDS:
2014 base->dma1e = buf;
2015 SAA7196_WRITE(mtr, 0x20, 0xf1);
2016 break;
2017 default: /* interlaced even/odd */
2018 base->dma1e = buf;
2019 base->dma1o = buf + mtr->cols * mtr->depth;
2020 base->stride1e = base->stride1o =
2021 mtr->cols * mtr->depth;
2022 SAA7196_WRITE(mtr, 0x20, 0x91);
2023 break;
2025 base->routee = base->routeo = 0xeeeeee41;
2026 break;
2027 default:
2028 error = EINVAL; /* invalid argument */
2029 kprintf("meteor%d: ioctl: invalid output format\n",unit);
2030 break;
2032 /* set cols */
2033 SAA7196_WRITE(mtr, 0x21, mtr->cols & 0xff);
2034 SAA7196_WRITE(mtr, 0x24,
2035 ((SAA7196_REG(mtr, 0x24) & ~0x03) |
2036 ((mtr->cols >> 8) & 0x03)));
2037 /* set rows */
2038 if(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
2039 SAA7196_WRITE(mtr, 0x25, ((mtr->rows) & 0xff));
2040 SAA7196_WRITE(mtr, 0x28,
2041 ((SAA7196_REG(mtr, 0x28) & ~0x03) |
2042 ((mtr->rows >> 8) & 0x03)));
2043 } else { /* Interlaced */
2044 SAA7196_WRITE(mtr, 0x25, ((mtr->rows >> 1) & 0xff));
2045 SAA7196_WRITE(mtr, 0x28,
2046 ((SAA7196_REG(mtr, 0x28) & ~0x03) |
2047 ((mtr->rows >> 9) & 0x03)));
2049 /* set signed/unsigned chrominance */
2050 SAA7196_WRITE(mtr, 0x30, (SAA7196_REG(mtr, 0x30) & ~0x10) |
2051 ((geo->oformat&METEOR_GEO_UNSIGNED)?0:0x10));
2052 break;
2053 case METEORGETGEO:
2054 geo = (struct meteor_geomet *) data;
2055 geo->rows = mtr->rows;
2056 geo->columns = mtr->cols;
2057 geo->frames = mtr->frames;
2058 geo->oformat = (mtr->flags & METEOR_OUTPUT_FMT_MASK) |
2059 (mtr->flags & METEOR_ONLY_FIELDS_MASK) |
2060 (SAA7196_REG(mtr, 0x30) & 0x10 ?
2061 0:METEOR_GEO_UNSIGNED);
2062 switch(base->routee & 0xff) {
2063 case 0xc3:
2064 geo->oformat |= METEOR_GEO_YUV_9;
2065 break;
2066 case 0xc2:
2067 geo->oformat |= METEOR_GEO_YUV_12;
2068 break;
2069 default:
2070 break;
2072 break;
2073 case METEORSCOUNT: /* (re)set error counts */
2074 cnt = (struct meteor_counts *) data;
2075 mtr->fifo_errors = cnt->fifo_errors;
2076 mtr->dma_errors = cnt->dma_errors;
2077 mtr->frames_captured = cnt->frames_captured;
2078 mtr->even_fields_captured = cnt->even_fields_captured;
2079 mtr->odd_fields_captured = cnt->odd_fields_captured;
2080 break;
2081 case METEORGCOUNT: /* get error counts */
2082 cnt = (struct meteor_counts *) data;
2083 cnt->fifo_errors = mtr->fifo_errors;
2084 cnt->dma_errors = mtr->dma_errors;
2085 cnt->frames_captured = mtr->frames_captured;
2086 cnt->even_fields_captured = mtr->even_fields_captured;
2087 cnt->odd_fields_captured = mtr->odd_fields_captured;
2088 break;
2089 default:
2090 kprintf("meteor%d: ioctl: invalid ioctl request\n", unit);
2091 error = ENOTTY;
2092 break;
2094 return(error);
2098 meteor_mmap(struct dev_mmap_args *ap)
2100 cdev_t dev = ap->a_head.a_dev;
2101 int unit;
2102 meteor_reg_t *mtr;
2104 unit = UNIT(minor(dev));
2105 if (unit >= NMETEOR) /* at this point could this happen? */
2106 return(-1);
2108 mtr = &(meteor[unit]);
2111 if (ap->a_nprot & PROT_EXEC)
2112 return -1;
2114 if (ap->a_offset >= mtr->alloc_pages * PAGE_SIZE)
2115 return -1;
2117 return i386_btop(vtophys(mtr->bigbuf) + ap->a_offset);