Merge commit 'crater/master'
[dragonfly.git] / sys / dev / video / meteor / meteor.c
blob9214a31bdd7cfeca0eb52419282dd2b3f03ebdc2
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 (NULL);
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 make_dev(&meteor_ops, unit, 0, 0, 0644, "meteor");
1111 #define UNIT(x) ((x) & 0x07)
1113 #ifdef unused
1114 static int
1115 meteor_reset(cdev_t dev)
1117 int unit = UNIT(minor(dev));
1118 struct saa7116_regs *m;
1120 if(unit >= NMETEOR)
1121 return ENXIO;
1123 m = meteor[unit].base;
1125 m->cap_cntl = 0x0;
1126 tsleep((caddr_t)m, METPRI, "Mreset", hz/50);
1128 m->cap_cntl = 0x8ff0;
1129 m->cap_cntl = 0x80c0;
1130 m->cap_cntl = 0x8040;
1131 tsleep((caddr_t)m, METPRI, "Mreset", hz/10);
1132 m->cap_cntl = 0x80c0;
1134 return 0;
1137 #endif
1139 /*---------------------------------------------------------
1141 ** Meteor character device driver routines
1143 **---------------------------------------------------------
1147 meteor_open(struct dev_open_args *ap)
1149 cdev_t dev = ap->a_head.a_dev;
1150 meteor_reg_t *mtr;
1151 int unit;
1152 int i;
1154 unit = UNIT(minor(dev));
1155 if (unit >= NMETEOR) /* unit out of range */
1156 return(ENXIO);
1158 mtr = &(meteor[unit]);
1160 if (!(mtr->flags & METEOR_INITALIZED)) /* device not found */
1161 return(ENXIO);
1163 if (mtr->flags & METEOR_OPEN) /* device is busy */
1164 return(EBUSY);
1166 mtr->flags |= METEOR_OPEN;
1168 * Make sure that the i2c regs are set the same for each open.
1170 for(i=0; i< NUM_SAA7196_I2C_REGS; i++) {
1171 SAA7196_WRITE(mtr, i, saa7196_i2c_default[i]);
1174 mtr->fifo_errors = 0;
1175 mtr->dma_errors = 0;
1176 mtr->frames_captured = 0;
1177 mtr->even_fields_captured = 0;
1178 mtr->odd_fields_captured = 0;
1179 mtr->proc = NULL;
1180 set_fps(mtr, 30);
1181 #ifdef METEOR_TEST_VIDEO
1182 mtr->video.addr = 0;
1183 mtr->video.width = 0;
1184 mtr->video.banksize = 0;
1185 mtr->video.ramsize = 0;
1186 #endif
1188 return(0);
1192 meteor_close(struct dev_close_args *ap)
1194 cdev_t dev = ap->a_head.a_dev;
1195 meteor_reg_t *mtr;
1196 int unit;
1197 #ifdef METEOR_DEALLOC_ABOVE
1198 int temp;
1199 #endif
1201 unit = UNIT(minor(dev));
1202 if (unit >= NMETEOR) /* unit out of range */
1203 return(ENXIO);
1205 mtr = &(meteor[unit]);
1206 mtr->flags &= ~METEOR_OPEN;
1208 if(mtr->flags & METEOR_SINGLE)
1209 /* this should not happen, the read capture
1210 should have completed or in the very least
1211 recieved a signal before close is called. */
1212 wakeup((caddr_t)mtr); /* continue read */
1214 * Turn off capture mode.
1216 mtr->base->cap_cntl = 0x8ff0;
1217 mtr->flags &= ~(METEOR_CAP_MASK|METEOR_WANT_MASK);
1218 mtr->proc = NULL;
1220 #ifdef METEOR_DEALLOC_PAGES
1221 if (mtr->bigbuf != NULL) {
1222 kmem_free(&kernel_map, mtr->bigbuf,
1223 (mtr->alloc_pages * PAGE_SIZE));
1224 mtr->bigbuf = NULL;
1225 mtr->alloc_pages = 0;
1227 #else
1228 #ifdef METEOR_DEALLOC_ABOVE
1229 if (mtr->bigbuf != NULL && mtr->alloc_pages > METEOR_DEALLOC_ABOVE) {
1230 temp = METEOR_DEALLOC_ABOVE - mtr->alloc_pages;
1231 kmem_free(&kernel_map,
1232 mtr->bigbuf+((mtr->alloc_pages - temp) * PAGE_SIZE),
1233 (temp * PAGE_SIZE));
1234 mtr->alloc_pages = METEOR_DEALLOC_ABOVE;
1236 #endif
1237 #endif
1239 return(0);
1242 static void
1243 start_capture(meteor_reg_t *mtr, unsigned type)
1245 mreg_t *cap = &mtr->base->cap_cntl;
1247 mtr->flags |= type;
1248 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1249 case METEOR_ONLY_EVEN_FIELDS:
1250 mtr->flags |= METEOR_WANT_EVEN;
1251 if(type == METEOR_SINGLE)
1252 *cap = 0x0ff4 | mtr->range_enable;
1253 else
1254 *cap = 0x0ff1 | mtr->range_enable;
1255 break;
1256 case METEOR_ONLY_ODD_FIELDS:
1257 mtr->flags |= METEOR_WANT_ODD;
1258 if(type == METEOR_SINGLE)
1259 *cap = 0x0ff8 | mtr->range_enable;
1260 else
1261 *cap = 0x0ff2 | mtr->range_enable;
1262 break;
1263 default:
1264 mtr->flags |= METEOR_WANT_MASK;
1265 if(type == METEOR_SINGLE)
1266 *cap = 0x0ffc | mtr->range_enable;
1267 else
1268 *cap = 0x0ff3 | mtr->range_enable;
1269 break;
1274 meteor_read(struct dev_read_args *ap)
1276 cdev_t dev = ap->a_head.a_dev;
1277 struct uio *uio = ap->a_uio;
1278 meteor_reg_t *mtr;
1279 int unit;
1280 int status;
1281 int count;
1283 unit = UNIT(minor(dev));
1284 if (unit >= NMETEOR) /* unit out of range */
1285 return(ENXIO);
1287 mtr = &(meteor[unit]);
1288 if (mtr->bigbuf == 0)/* no frame buffer allocated (ioctl failed) */
1289 return(ENOMEM);
1291 if (mtr->flags & METEOR_CAP_MASK)
1292 return(EIO); /* already capturing */
1294 count = mtr->rows * mtr->cols * mtr->depth;
1295 if (uio->uio_iov->iov_len < count)
1296 return(EINVAL);
1298 /* Start capture */
1299 start_capture(mtr, METEOR_SINGLE);
1301 status=tsleep((caddr_t)mtr, METPRI, "capturing", 0);
1302 if (!status) /* successful capture */
1303 status = uiomove((caddr_t)mtr->bigbuf, count, uio);
1304 else
1305 kprintf ("meteor%d: read: tsleep error %d\n", unit, status);
1307 mtr->flags &= ~(METEOR_SINGLE | METEOR_WANT_MASK);
1309 return(status);
1313 meteor_write(struct dev_write_args *ap)
1315 return(0);
1319 meteor_ioctl(struct dev_ioctl_args *ap)
1321 cdev_t dev = ap->a_head.a_dev;
1322 caddr_t data = ap->a_data;
1323 int error;
1324 int unit;
1325 unsigned int temp;
1326 meteor_reg_t *mtr;
1327 struct meteor_counts *cnt;
1328 struct meteor_geomet *geo;
1329 struct meteor_mem *mem;
1330 struct meteor_capframe *frame;
1331 #ifdef METEOR_TEST_VIDEO
1332 struct meteor_video *video;
1333 #endif
1334 vm_offset_t buf;
1335 struct saa7116_regs *base;
1337 error = 0;
1339 if (data == NULL)
1340 return(EINVAL);
1341 unit = UNIT(minor(dev));
1342 if (unit >= NMETEOR) /* unit out of range */
1343 return(ENXIO);
1345 mtr = &(meteor[unit]);
1346 base = mtr->base;
1348 switch (ap->a_cmd) {
1349 case METEORSTS:
1350 if(*data)
1351 mtr->flags |= METEOR_WANT_TS;
1352 else
1353 mtr->flags &= ~METEOR_WANT_TS;
1354 break;
1355 case METEORGTS:
1356 if(mtr->flags & METEOR_WANT_TS)
1357 *data = 1;
1358 else
1359 *data = 0;
1360 break;
1361 #ifdef METEOR_TEST_VIDEO
1362 case METEORGVIDEO:
1363 video = (struct meteor_video *)data;
1364 video->addr = mtr->video.addr;
1365 video->width = mtr->video.width;
1366 video->banksize = mtr->video.banksize;
1367 video->ramsize = mtr->video.ramsize;
1368 break;
1369 case METEORSVIDEO:
1370 video = (struct meteor_video *)data;
1371 mtr->video.addr = video->addr;
1372 mtr->video.width = video->width;
1373 mtr->video.banksize = video->banksize;
1374 mtr->video.ramsize = video->ramsize;
1375 break;
1376 #endif
1377 case METEORSFPS:
1378 set_fps(mtr, *(u_short *)data);
1379 break;
1380 case METEORGFPS:
1381 *(u_short *)data = mtr->fps;
1382 break;
1383 case METEORSSIGNAL:
1384 if (*(int *)data < 0 || *(int *)data > _SIG_MAXSIG)
1385 return EINVAL;
1386 mtr->signal = *(int *) data;
1387 if (mtr->signal) {
1388 mtr->proc = curproc; /* might be NULL */
1389 } else {
1390 mtr->proc = NULL;
1392 break;
1393 case METEORGSIGNAL:
1394 *(int *)data = mtr->signal;
1395 break;
1396 case METEORSTATUS: /* get 7196 status */
1397 temp = 0;
1398 SAA7196_WRITE(mtr, SAA7196_STDC,
1399 SAA7196_REG(mtr, SAA7196_STDC) | 0x02);
1400 SAA7196_READ(mtr);
1401 temp |= (base->i2c_read & 0xff000000L) >> 24;
1402 SAA7196_WRITE(mtr, SAA7196_STDC,
1403 SAA7196_REG(mtr, SAA7196_STDC) & ~0x02);
1404 SAA7196_READ(mtr);
1405 temp |= (base->i2c_read & 0xff000000L) >> 16;
1406 *(u_short *)data = temp;
1407 break;
1408 case METEORSHUE: /* set hue */
1409 SAA7196_WRITE(mtr, SAA7196_HUEC, *(char *)data);
1410 break;
1411 case METEORGHUE: /* get hue */
1412 *(char *)data = SAA7196_REG(mtr, SAA7196_HUEC);
1413 break;
1414 case METEORSCHCV: /* set chrominance gain */
1415 SAA7196_WRITE(mtr, SAA7196_CGAINR, *(char *)data);
1416 break;
1417 case METEORGCHCV: /* get chrominance gain */
1418 *(char *)data = SAA7196_REG(mtr, SAA7196_CGAINR);
1419 break;
1420 case METEORSBRIG: /* set brightness */
1421 SAA7196_WRITE(mtr, SAA7196_BRIG, *(char *)data);
1422 break;
1423 case METEORGBRIG: /* get brightness */
1424 *(char *)data = SAA7196_REG(mtr, SAA7196_BRIG);
1425 break;
1426 case METEORSCSAT: /* set chroma saturation */
1427 SAA7196_WRITE(mtr, SAA7196_CSAT, *(char *)data);
1428 break;
1429 case METEORGCSAT: /* get chroma saturation */
1430 *(char *)data = SAA7196_REG(mtr, SAA7196_CSAT);
1431 break;
1432 case METEORSCONT: /* set contrast */
1433 SAA7196_WRITE(mtr, SAA7196_CONT, *(char *)data);
1434 break;
1435 case METEORGCONT: /* get contrast */
1436 *(char *)data = SAA7196_REG(mtr, SAA7196_CONT);
1437 break;
1438 case METEORSBT254:
1439 if((mtr->flags & METEOR_RGB) == 0)
1440 return EINVAL;
1441 temp = *(unsigned short *)data;
1442 bt254_write(mtr, temp & 0xf, (temp & 0x0ff0) >> 4);
1443 break;
1444 case METEORGBT254:
1445 if((mtr->flags & METEOR_RGB) == 0)
1446 return EINVAL;
1447 temp = *(unsigned short *)data & 0x7;
1448 *(unsigned short *)data = mtr->bt254_reg[temp] << 4 | temp;
1449 break;
1450 case METEORSHWS: /* set horizontal window start */
1451 SAA7196_WRITE(mtr, SAA7196_HWS, *(char *)data);
1452 break;
1453 case METEORGHWS: /* get horizontal window start */
1454 *(char *)data = SAA7196_REG(mtr, SAA7196_HWS);
1455 break;
1456 case METEORSVWS: /* set vertical window start */
1457 SAA7196_WRITE(mtr, SAA7196_VWS, *(char *)data);
1458 break;
1459 case METEORGVWS: /* get vertical window start */
1460 *(char *)data = SAA7196_REG(mtr, SAA7196_VWS);
1461 break;
1462 case METEORSINPUT: /* set input device */
1463 switch(*(unsigned long *)data & METEOR_DEV_MASK) {
1464 case 0: /* default */
1465 case METEOR_INPUT_DEV0:
1466 if(mtr->flags & METEOR_RGB)
1467 select_saa7196(mtr);
1468 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1469 | METEOR_DEV0;
1470 SAA7196_WRITE(mtr, 0x0e,
1471 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x0);
1472 SAA7196_WRITE(mtr, 0x06,
1473 (SAA7196_REG(mtr, 0x06) & ~0x80));
1474 break;
1475 case METEOR_INPUT_DEV1:
1476 if(mtr->flags & METEOR_RGB)
1477 select_saa7196(mtr);
1478 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1479 | METEOR_DEV1;
1480 SAA7196_WRITE(mtr, 0x0e,
1481 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x1);
1482 SAA7196_WRITE(mtr, 0x06,
1483 (SAA7196_REG(mtr, 0x06) & ~0x80));
1484 break;
1485 case METEOR_INPUT_DEV2:
1486 if(mtr->flags & METEOR_RGB)
1487 select_saa7196(mtr);
1488 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1489 | METEOR_DEV2;
1490 SAA7196_WRITE(mtr, 0x0e,
1491 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x2);
1492 SAA7196_WRITE(mtr, 0x06,
1493 (SAA7196_REG(mtr, 0x06) & ~0x80));
1494 break;
1495 case METEOR_INPUT_DEV3:
1496 if(mtr->flags & METEOR_RGB)
1497 select_saa7196(mtr);
1498 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1499 | METEOR_DEV3;
1500 SAA7196_WRITE(mtr, 0x0e,
1501 (SAA7196_REG(mtr, 0x0e) | 0x3));
1502 SAA7196_WRITE(mtr, 0x06,
1503 (SAA7196_REG(mtr, 0x06) & ~0x80) );
1504 break;
1505 case METEOR_INPUT_DEV_SVIDEO:
1506 if(mtr->flags & METEOR_RGB)
1507 select_saa7196(mtr);
1508 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1509 | METEOR_DEV_SVIDEO;
1510 SAA7196_WRITE(mtr, 0x0e,
1511 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x2);
1512 SAA7196_WRITE(mtr, 0x06,
1513 (SAA7196_REG(mtr, 0x06) & ~0x80) | 0x80);
1514 break;
1515 case METEOR_INPUT_DEV_RGB:
1516 if((mtr->flags & METEOR_RGB) == 0)
1517 return EINVAL;
1518 mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1519 | METEOR_DEV_RGB;
1520 SAA7196_WRITE(mtr, 0x0e,
1521 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x3);
1522 SAA7196_WRITE(mtr, 0x06,
1523 (SAA7196_REG(mtr, 0x06) & ~0x80));
1524 select_bt254(mtr);
1525 SAA7196_WRITE(mtr, 0x0e, /* chn 3 for synch */
1526 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x3);
1527 break;
1528 default:
1529 return EINVAL;
1531 break;
1532 case METEORGINPUT: /* get input device */
1533 *(u_long *)data = mtr->flags & METEOR_DEV_MASK;
1534 break;
1535 case METEORSFMT: /* set input format */
1536 switch(*(unsigned long *)data & METEOR_FORM_MASK ) {
1537 case 0: /* default */
1538 case METEOR_FMT_NTSC:
1539 mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1540 METEOR_NTSC;
1541 SAA7196_WRITE(mtr, SAA7196_STDC,
1542 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01));
1543 SAA7196_WRITE(mtr, 0x0f,
1544 (SAA7196_REG(mtr, 0x0f) & ~0xe0) | 0x40);
1545 SAA7196_WRITE(mtr, 0x22, 0x80);
1546 SAA7196_WRITE(mtr, 0x24,
1547 (SAA7196_REG(mtr, 0x24) & ~0x0c) | 0x08);
1548 SAA7196_WRITE(mtr, 0x26, 0xf0);
1549 SAA7196_WRITE(mtr, 0x28,
1550 (SAA7196_REG(mtr, 0x28) & ~0x0c)) ;
1551 if(mtr->flags & METEOR_RGB){
1552 bt254_ntsc(mtr, 1);
1554 break;
1555 case METEOR_FMT_PAL:
1556 mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1557 METEOR_PAL;
1558 SAA7196_WRITE(mtr, SAA7196_STDC,
1559 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01));
1560 SAA7196_WRITE(mtr, 0x0f,
1561 (SAA7196_REG(mtr, 0x0f) & ~0xe0));
1562 SAA7196_WRITE(mtr, 0x22, 0x00);
1563 SAA7196_WRITE(mtr, 0x24,
1564 (SAA7196_REG(mtr, 0x24) | 0x0c));
1565 SAA7196_WRITE(mtr, 0x26, 0x20);
1566 SAA7196_WRITE(mtr, 0x28,
1567 (SAA7196_REG(mtr, 0x28) & ~0x0c) | 0x04) ;
1568 if(mtr->flags & METEOR_RGB){
1569 bt254_ntsc(mtr, 0);
1571 break;
1572 case METEOR_FMT_SECAM:
1573 mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1574 METEOR_SECAM;
1575 SAA7196_WRITE(mtr, SAA7196_STDC,
1576 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01) | 0x1);
1577 SAA7196_WRITE(mtr, 0x0f,
1578 (SAA7196_REG(mtr, 0x0f) & ~0xe0) | 0x20);
1579 SAA7196_WRITE(mtr, 0x22, 0x00);
1580 SAA7196_WRITE(mtr, 0x24,
1581 (SAA7196_REG(mtr, 0x24) | 0x0c));
1582 SAA7196_WRITE(mtr, 0x26, 0x20);
1583 SAA7196_WRITE(mtr, 0x28,
1584 (SAA7196_REG(mtr, 0x28) & ~0x0c) | 0x04) ;
1585 if(mtr->flags & METEOR_RGB){
1586 bt254_ntsc(mtr, 0);
1588 break;
1589 case METEOR_FMT_AUTOMODE:
1590 mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1591 METEOR_AUTOMODE;
1592 SAA7196_WRITE(mtr, SAA7196_STDC,
1593 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01));
1594 SAA7196_WRITE(mtr, 0x0f,
1595 (SAA7196_REG(mtr, 0x0f) & ~0xe0) | 0x80);
1596 break;
1597 default:
1598 return EINVAL;
1600 break;
1601 case METEORGFMT: /* get input format */
1602 *(u_long *)data = mtr->flags & METEOR_FORM_MASK;
1603 break;
1604 case METEORCAPTUR:
1605 temp = mtr->flags;
1606 switch (*(int *) data) {
1607 case METEOR_CAP_SINGLE:
1608 if (mtr->bigbuf==0) /* no frame buffer allocated */
1609 return(ENOMEM);
1611 if (temp & METEOR_CAP_MASK)
1612 return(EIO); /* already capturing */
1614 start_capture(mtr, METEOR_SINGLE);
1616 /* wait for capture to complete */
1617 error=tsleep((caddr_t)mtr, METPRI, "capturing", 0);
1618 if(error)
1619 kprintf("meteor%d: ioctl: tsleep error %d\n",
1620 unit, error);
1621 mtr->flags &= ~(METEOR_SINGLE|METEOR_WANT_MASK);
1622 break;
1623 case METEOR_CAP_CONTINOUS:
1624 if (mtr->bigbuf==0) /* no frame buffer allocated */
1625 return(ENOMEM);
1627 if (temp & METEOR_CAP_MASK)
1628 return(EIO); /* already capturing */
1630 start_capture(mtr, METEOR_CONTIN);
1632 break;
1633 case METEOR_CAP_STOP_CONT:
1634 if (mtr->flags & METEOR_CONTIN) {
1635 /* turn off capture */
1636 base->cap_cntl = 0x8ff0;
1637 mtr->flags &= ~(METEOR_CONTIN|METEOR_WANT_MASK);
1639 break;
1641 default:
1642 error = EINVAL;
1643 break;
1645 break;
1646 case METEORCAPFRM:
1647 frame = (struct meteor_capframe *) data;
1648 if (!frame)
1649 return(EINVAL);
1650 switch (frame->command) {
1651 case METEOR_CAP_N_FRAMES:
1652 if (mtr->flags & METEOR_CAP_MASK)
1653 return(EIO);
1654 if (mtr->flags & (METEOR_YUV_PLANAR | METEOR_YUV_422)) /* XXX */
1655 return(EINVAL); /* should fix intr so we allow these */
1656 if (mtr->bigbuf == 0)
1657 return(ENOMEM);
1658 if ((mtr->frames < 2) ||
1659 (frame->lowat < 1 || frame->lowat >= mtr->frames) ||
1660 (frame->hiwat < 1 || frame->hiwat >= mtr->frames) ||
1661 (frame->lowat > frame->hiwat))
1662 return(EINVAL);
1663 /* meteor_mem structure is on the page after the data */
1664 mem = mtr->mem = (struct meteor_mem *) (mtr->bigbuf +
1665 (round_page(mtr->frame_size * mtr->frames)));
1666 mtr->current = 1;
1667 mtr->synch_wait = 0;
1668 mem->num_bufs = mtr->frames;
1669 mem->frame_size= mtr->frame_size;
1670 /* user and kernel change these */
1671 mem->lowat = frame->lowat;
1672 mem->hiwat = frame->hiwat;
1673 mem->active = 0;
1674 mem->num_active_bufs = 0;
1675 /* Start capture */
1676 start_capture(mtr, METEOR_SYNCAP);
1677 break;
1678 case METEOR_CAP_STOP_FRAMES:
1679 if (mtr->flags & METEOR_SYNCAP) {
1680 /* turn off capture */
1681 base->cap_cntl = 0x8ff0;
1682 mtr->flags &= ~(METEOR_SYNCAP|METEOR_WANT_MASK);
1684 break;
1685 case METEOR_HALT_N_FRAMES:
1686 if(mtr->flags & METEOR_SYNCAP) {
1687 base->cap_cntl = 0x8ff0;
1688 mtr->flags &= ~(METEOR_WANT_MASK);
1690 break;
1691 case METEOR_CONT_N_FRAMES:
1692 if(!(mtr->flags & METEOR_SYNCAP)) {
1693 error = EINVAL;
1694 break;
1696 start_capture(mtr, METEOR_SYNCAP);
1697 break;
1698 default:
1699 error = EINVAL;
1700 break;
1702 break;
1704 case METEORSETGEO:
1705 geo = (struct meteor_geomet *) data;
1707 /* Either even or odd, if even & odd, then these a zero */
1708 if((geo->oformat & METEOR_GEO_ODD_ONLY) &&
1709 (geo->oformat & METEOR_GEO_EVEN_ONLY)) {
1710 kprintf("meteor%d: ioctl: Geometry odd or even only.\n",
1711 unit);
1712 return EINVAL;
1714 /* set/clear even/odd flags */
1715 if(geo->oformat & METEOR_GEO_ODD_ONLY)
1716 mtr->flags |= METEOR_ONLY_ODD_FIELDS;
1717 else
1718 mtr->flags &= ~METEOR_ONLY_ODD_FIELDS;
1719 if(geo->oformat & METEOR_GEO_EVEN_ONLY)
1720 mtr->flags |= METEOR_ONLY_EVEN_FIELDS;
1721 else
1722 mtr->flags &= ~METEOR_ONLY_EVEN_FIELDS;
1724 /* can't change parameters while capturing */
1725 if (mtr->flags & METEOR_CAP_MASK)
1726 return(EBUSY);
1728 if ((geo->columns & 0x3fe) != geo->columns) {
1729 kprintf(
1730 "meteor%d: ioctl: %d: columns too large or not even.\n",
1731 unit, geo->columns);
1732 error = EINVAL;
1734 if (((geo->rows & 0x7fe) != geo->rows) ||
1735 ((geo->oformat & METEOR_GEO_FIELD_MASK) &&
1736 ((geo->rows & 0x3fe) != geo->rows)) ) {
1737 kprintf(
1738 "meteor%d: ioctl: %d: rows too large or not even.\n",
1739 unit, geo->rows);
1740 error = EINVAL;
1742 if (geo->frames > 32) {
1743 kprintf("meteor%d: ioctl: too many frames.\n", unit);
1744 error = EINVAL;
1746 if(error) return error;
1748 if ((temp=geo->rows * geo->columns * geo->frames * 2) != 0) {
1749 if (geo->oformat & METEOR_GEO_RGB24) temp = temp * 2;
1751 /* meteor_mem structure for SYNC Capture */
1752 if (geo->frames > 1) temp += PAGE_SIZE;
1754 temp = btoc(temp);
1755 if (temp > mtr->alloc_pages
1756 #ifdef METEOR_TEST_VIDEO
1757 && mtr->video.addr == 0
1758 #endif
1760 buf = get_meteor_mem(unit, temp*PAGE_SIZE);
1761 if(buf != 0) {
1762 kmem_free(&kernel_map, mtr->bigbuf,
1763 (mtr->alloc_pages * PAGE_SIZE));
1764 mtr->bigbuf = buf;
1765 mtr->alloc_pages = temp;
1766 if(bootverbose)
1767 kprintf(
1768 "meteor%d: ioctl: Allocating %d bytes\n",
1769 unit, temp*PAGE_SIZE);
1770 } else {
1771 error = ENOMEM;
1775 if(error) return error;
1777 mtr->rows = geo->rows;
1778 mtr->cols = geo->columns;
1779 mtr->frames = geo->frames;
1781 #ifdef METEOR_TEST_VIDEO
1782 if(mtr->video.addr)
1783 buf = vtophys(mtr->video.addr);
1784 else
1785 #endif
1786 buf = vtophys(mtr->bigbuf);
1788 /* set defaults and end of buffer locations */
1789 base->dma1e = buf;
1790 base->dma2e = buf;
1791 base->dma3e = buf;
1792 base->dma1o = buf;
1793 base->dma2o = buf;
1794 base->dma3o = buf;
1795 base->stride1e = 0;
1796 base->stride2e = 0;
1797 base->stride3e = 0;
1798 base->stride1o = 0;
1799 base->stride2o = 0;
1800 base->stride3o = 0;
1801 /* set end of DMA location, even/odd */
1802 base->dma_end_e =
1803 base->dma_end_o = buf + mtr->alloc_pages * PAGE_SIZE;
1806 * Determine if we can use the hardware range detect.
1808 if(mtr->alloc_pages * PAGE_SIZE < RANGE_BOUNDARY &&
1809 ((buf & 0xff000000) | base->dma_end_e) ==
1810 (buf + mtr->alloc_pages * PAGE_SIZE) )
1811 mtr->range_enable = 0x8000;
1812 else {
1813 mtr->range_enable = 0x0;
1814 base->dma_end_e =
1815 base->dma_end_o = 0xffffffff;
1819 switch (geo->oformat & METEOR_GEO_OUTPUT_MASK) {
1820 case 0: /* default */
1821 case METEOR_GEO_RGB16:
1822 mtr->depth = 2;
1823 mtr->frame_size = mtr->rows * mtr->cols * mtr->depth;
1824 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1825 mtr->flags |= METEOR_RGB16;
1826 temp = mtr->cols * mtr->depth;
1827 /* recal stride and starting point */
1828 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1829 case METEOR_ONLY_ODD_FIELDS:
1830 base->dma1o = buf;
1831 #ifdef METEOR_TEST_VIDEO
1832 if(mtr->video.addr && mtr->video.width)
1833 base->stride1o = mtr->video.width-temp;
1834 #endif
1835 SAA7196_WRITE(mtr, 0x20, 0xd0);
1836 break;
1837 case METEOR_ONLY_EVEN_FIELDS:
1838 base->dma1e = buf;
1839 #ifdef METEOR_TEST_VIDEO
1840 if(mtr->video.addr && mtr->video.width)
1841 base->stride1e = mtr->video.width-temp;
1842 #endif
1843 SAA7196_WRITE(mtr, 0x20, 0xf0);
1844 break;
1845 default: /* interlaced even/odd */
1846 base->dma1e = buf;
1847 base->dma1o = buf + temp;
1848 base->stride1e = base->stride1o = temp;
1849 #ifdef METEOR_TEST_VIDEO
1850 if(mtr->video.addr && mtr->video.width) {
1851 base->dma1o = buf + mtr->video.width;
1852 base->stride1e = base->stride1o =
1853 mtr->video.width -
1854 temp + mtr->video.width;
1856 #endif
1857 SAA7196_WRITE(mtr, 0x20, 0x90);
1858 break;
1860 base->routee = base->routeo = 0xeeeeee01;
1861 break;
1862 case METEOR_GEO_RGB24:
1863 mtr->depth = 4;
1864 mtr->frame_size = mtr->rows * mtr->cols * mtr->depth;
1865 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1866 mtr->flags |= METEOR_RGB24;
1867 temp = mtr->cols * mtr->depth;
1868 /* recal stride and starting point */
1869 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1870 case METEOR_ONLY_ODD_FIELDS:
1871 base->dma1o = buf;
1872 #ifdef METEOR_TEST_VIDEO
1873 if(mtr->video.addr && mtr->video.width)
1874 base->stride1o = mtr->video.width-temp;
1875 #endif
1876 SAA7196_WRITE(mtr, 0x20, 0xd2);
1877 break;
1878 case METEOR_ONLY_EVEN_FIELDS:
1879 base->dma1e = buf;
1880 #ifdef METEOR_TEST_VIDEO
1881 if(mtr->video.addr && mtr->video.width)
1882 base->stride1e = mtr->video.width-temp;
1883 #endif
1884 SAA7196_WRITE(mtr, 0x20, 0xf2);
1885 break;
1886 default: /* interlaced even/odd */
1887 base->dma1e = buf;
1888 base->dma1o = buf + mtr->cols * mtr->depth;
1889 base->stride1e = base->stride1o =
1890 mtr->cols * mtr->depth;
1891 #ifdef METEOR_TEST_VIDEO
1892 if(mtr->video.addr && mtr->video.width) {
1893 base->dma1o = buf + mtr->video.width;
1894 base->stride1e = base->stride1o =
1895 mtr->video.width -
1896 temp + mtr->video.width;
1898 #endif
1899 SAA7196_WRITE(mtr, 0x20, 0x92);
1900 break;
1902 base->routee= base->routeo= 0x39393900;
1903 break;
1904 case METEOR_GEO_YUV_PLANAR:
1905 mtr->depth = 2;
1906 temp = mtr->rows * mtr->cols; /* compute frame size */
1907 mtr->frame_size = temp * mtr->depth;
1908 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1909 mtr->flags |= METEOR_YUV_PLANAR;
1910 /* recal stride and starting point */
1911 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1912 case METEOR_ONLY_ODD_FIELDS:
1913 base->dma1o = buf; /* Y Odd */
1914 base->dma2o = buf + temp; /* U Odd */
1915 temp >>= 1;
1916 base->dma3o = base->dma2o + temp; /* V Odd */
1917 SAA7196_WRITE(mtr, 0x20, 0xd1);
1918 break;
1919 case METEOR_ONLY_EVEN_FIELDS:
1920 base->dma1e = buf; /* Y Even */
1921 base->dma2e = buf + temp; /* U Even */
1922 temp >>= 1;
1923 base->dma2e= base->dma2e + temp; /* V Even */
1924 SAA7196_WRITE(mtr, 0x20, 0xf1);
1925 break;
1926 default: /* interlaced even/odd */
1927 base->dma1e = buf; /* Y Even */
1928 base->dma2e = buf + temp; /* U Even */
1929 temp >>= 2;
1930 base->dma3e = base->dma2e + temp; /* V Even */
1931 base->dma1o = base->dma1e+mtr->cols;/* Y Odd */
1932 base->dma2o = base->dma3e + temp; /* U Odd */
1933 base->dma3o = base->dma2o + temp; /* V Odd */
1934 base->stride1e = base->stride1o = mtr->cols;
1935 SAA7196_WRITE(mtr, 0x20, 0x91);
1936 break;
1938 switch (geo->oformat &
1939 (METEOR_GEO_YUV_12 | METEOR_GEO_YUV_9)) {
1940 case METEOR_GEO_YUV_9:
1941 base->routee=base->routeo = 0xaaaaffc3;
1942 break;
1943 case METEOR_GEO_YUV_12:
1944 base->routee=base->routeo = 0xaaaaffc2;
1945 break;
1946 default:
1947 base->routee=base->routeo = 0xaaaaffc1;
1948 break;
1950 break;
1951 case METEOR_GEO_YUV_422:/* same as planer, different uv order */
1952 mtr->depth = 2;
1953 temp = mtr->rows * mtr->cols; /* compute frame size */
1954 mtr->frame_size = temp * mtr->depth;
1955 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1956 mtr->flags |= METEOR_YUV_422;
1957 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1958 case METEOR_ONLY_ODD_FIELDS:
1959 base->dma1o = buf;
1960 base->dma2o = buf + temp;
1961 base->dma3o = base->dma2o + (temp >> 1);
1962 SAA7196_WRITE(mtr, 0x20, 0xd1);
1963 break;
1964 case METEOR_ONLY_EVEN_FIELDS:
1965 base->dma1e = buf;
1966 base->dma2e = buf + temp;
1967 base->dma3e = base->dma2e + (temp >> 1);
1968 SAA7196_WRITE(mtr, 0x20, 0xf1);
1969 break;
1970 default: /* interlaced even/odd */
1971 base->dma1e = buf; /* Y even */
1972 base->dma2e = buf + temp; /* U even */
1973 base->dma3e =
1974 base->dma2e + (temp >> 1);/* V even */
1975 base->dma1o = base->dma1e+mtr->cols;/* Y odd */
1976 temp = mtr->cols >> 1;
1977 base->dma2o = base->dma2e+temp; /* U odd */
1978 base->dma3o = base->dma3e+temp; /* V odd */
1979 base->stride1e =
1980 base->stride1o = mtr->cols; /* Y stride */
1981 base->stride2e =
1982 base->stride2o = temp; /* U stride */
1983 base->stride3e =
1984 base->stride3o = temp; /* V stride */
1985 SAA7196_WRITE(mtr, 0x20, 0x91);
1986 break;
1988 switch (geo->oformat &
1989 (METEOR_GEO_YUV_12 | METEOR_GEO_YUV_9)) {
1990 case METEOR_GEO_YUV_9:
1991 base->routee=base->routeo = 0xaaaaffc3;
1992 break;
1993 case METEOR_GEO_YUV_12:
1994 base->routee=base->routeo = 0xaaaaffc2;
1995 break;
1996 default:
1997 base->routee=base->routeo = 0xaaaaffc1;
1998 break;
2000 break;
2001 case METEOR_GEO_YUV_PACKED:
2002 mtr->depth = 2;
2003 mtr->frame_size = mtr->rows * mtr->cols * mtr->depth;
2004 mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
2005 mtr->flags |= METEOR_YUV_PACKED;
2006 /* recal stride and odd starting point */
2007 switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
2008 case METEOR_ONLY_ODD_FIELDS:
2009 base->dma1o = buf;
2010 SAA7196_WRITE(mtr, 0x20, 0xd1);
2011 break;
2012 case METEOR_ONLY_EVEN_FIELDS:
2013 base->dma1e = buf;
2014 SAA7196_WRITE(mtr, 0x20, 0xf1);
2015 break;
2016 default: /* interlaced even/odd */
2017 base->dma1e = buf;
2018 base->dma1o = buf + mtr->cols * mtr->depth;
2019 base->stride1e = base->stride1o =
2020 mtr->cols * mtr->depth;
2021 SAA7196_WRITE(mtr, 0x20, 0x91);
2022 break;
2024 base->routee = base->routeo = 0xeeeeee41;
2025 break;
2026 default:
2027 error = EINVAL; /* invalid argument */
2028 kprintf("meteor%d: ioctl: invalid output format\n",unit);
2029 break;
2031 /* set cols */
2032 SAA7196_WRITE(mtr, 0x21, mtr->cols & 0xff);
2033 SAA7196_WRITE(mtr, 0x24,
2034 ((SAA7196_REG(mtr, 0x24) & ~0x03) |
2035 ((mtr->cols >> 8) & 0x03)));
2036 /* set rows */
2037 if(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
2038 SAA7196_WRITE(mtr, 0x25, ((mtr->rows) & 0xff));
2039 SAA7196_WRITE(mtr, 0x28,
2040 ((SAA7196_REG(mtr, 0x28) & ~0x03) |
2041 ((mtr->rows >> 8) & 0x03)));
2042 } else { /* Interlaced */
2043 SAA7196_WRITE(mtr, 0x25, ((mtr->rows >> 1) & 0xff));
2044 SAA7196_WRITE(mtr, 0x28,
2045 ((SAA7196_REG(mtr, 0x28) & ~0x03) |
2046 ((mtr->rows >> 9) & 0x03)));
2048 /* set signed/unsigned chrominance */
2049 SAA7196_WRITE(mtr, 0x30, (SAA7196_REG(mtr, 0x30) & ~0x10) |
2050 ((geo->oformat&METEOR_GEO_UNSIGNED)?0:0x10));
2051 break;
2052 case METEORGETGEO:
2053 geo = (struct meteor_geomet *) data;
2054 geo->rows = mtr->rows;
2055 geo->columns = mtr->cols;
2056 geo->frames = mtr->frames;
2057 geo->oformat = (mtr->flags & METEOR_OUTPUT_FMT_MASK) |
2058 (mtr->flags & METEOR_ONLY_FIELDS_MASK) |
2059 (SAA7196_REG(mtr, 0x30) & 0x10 ?
2060 0:METEOR_GEO_UNSIGNED);
2061 switch(base->routee & 0xff) {
2062 case 0xc3:
2063 geo->oformat |= METEOR_GEO_YUV_9;
2064 break;
2065 case 0xc2:
2066 geo->oformat |= METEOR_GEO_YUV_12;
2067 break;
2068 default:
2069 break;
2071 break;
2072 case METEORSCOUNT: /* (re)set error counts */
2073 cnt = (struct meteor_counts *) data;
2074 mtr->fifo_errors = cnt->fifo_errors;
2075 mtr->dma_errors = cnt->dma_errors;
2076 mtr->frames_captured = cnt->frames_captured;
2077 mtr->even_fields_captured = cnt->even_fields_captured;
2078 mtr->odd_fields_captured = cnt->odd_fields_captured;
2079 break;
2080 case METEORGCOUNT: /* get error counts */
2081 cnt = (struct meteor_counts *) data;
2082 cnt->fifo_errors = mtr->fifo_errors;
2083 cnt->dma_errors = mtr->dma_errors;
2084 cnt->frames_captured = mtr->frames_captured;
2085 cnt->even_fields_captured = mtr->even_fields_captured;
2086 cnt->odd_fields_captured = mtr->odd_fields_captured;
2087 break;
2088 default:
2089 kprintf("meteor%d: ioctl: invalid ioctl request\n", unit);
2090 error = ENOTTY;
2091 break;
2093 return(error);
2097 meteor_mmap(struct dev_mmap_args *ap)
2099 cdev_t dev = ap->a_head.a_dev;
2100 int unit;
2101 meteor_reg_t *mtr;
2103 unit = UNIT(minor(dev));
2104 if (unit >= NMETEOR) /* at this point could this happen? */
2105 return(-1);
2107 mtr = &(meteor[unit]);
2110 if (ap->a_nprot & PROT_EXEC)
2111 return -1;
2113 if (ap->a_offset >= mtr->alloc_pages * PAGE_SIZE)
2114 return -1;
2116 return i386_btop(vtophys(mtr->bigbuf) + ap->a_offset);