DEVFS - remove dev_ops_add(), dev_ops_get(), and get_dev()
[dragonfly.git] / sys / dev / video / meteor / meteor.c
CommitLineData
984263bc
MD
1/*
2 * Copyright (c) 1995 Mark Tinguely and Jim Lowe
3 * All rights reserved.
4 *
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.
18 *
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.
30 *
31 * $FreeBSD: src/sys/pci/meteor.c,v 1.49 1999/09/25 18:24:41 phk Exp $
3f625015 32 * $DragonFly: src/sys/dev/video/meteor/meteor.c,v 1.22 2007/05/13 18:33:58 swildner Exp $
984263bc
MD
33 */
34
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.
147*/
148
1f2de5d4 149#include "use_meteor.h"
984263bc
MD
150#include "opt_meteor.h"
151
152#include <sys/param.h>
153#include <sys/systm.h>
154#include <sys/conf.h>
fef8985e 155#include <sys/device.h>
984263bc
MD
156#include <sys/kernel.h>
157#include <sys/signalvar.h>
158#include <sys/mman.h>
159#include <sys/uio.h>
160
161#if defined(METEOR_FreeBSD_210)
162#include <machine/cpu.h> /* bootverbose */
163#endif
164
165#include <vm/vm.h>
166#include <vm/vm_kern.h>
167#include <vm/pmap.h>
168#include <vm/vm_extern.h>
169
1f2de5d4
MD
170#include <bus/pci/pcivar.h>
171#include <bus/pci/pcireg.h>
a35cc233
JS
172#include <dev/video/meteor/ioctl_meteor.h>
173#include <dev/video/meteor/meteor_reg.h>
984263bc
MD
174
175
5ca58d54 176static void meteor_intr (void *arg);
984263bc
MD
177
178/*
179 * Allocate enough memory for:
180 * 768x576 RGB 16 or YUV (16 storage bits/pixel) = 884736 = 216 pages
181 *
182 * You may override this using the options "METEOR_ALLOC_PAGES=value" in your
183 * kernel configuration file.
184 */
185#ifndef METEOR_ALLOC_PAGES
186#define METEOR_ALLOC_PAGES 217
187#endif
188#define METEOR_ALLOC (METEOR_ALLOC_PAGES * PAGE_SIZE)
189
190static meteor_reg_t meteor[NMETEOR];
191#define METEOR_NUM(mtr) ((mtr - &meteor[0])/sizeof(meteor_reg_t))
192
377d4740 193#define METPRI PCATCH
984263bc
MD
194
195static const char* met_probe (pcici_t tag, pcidi_t type);
196static void met_attach(pcici_t tag, int unit);
197static u_long met_count;
198
199static struct pci_device met_device = {
200 "meteor",
201 met_probe,
202 met_attach,
203 &met_count
204};
205
206COMPAT_PCI_DRIVER (meteor, met_device);
207
208#if defined(METEOR_FreeBSD_210) /* XXX */
209d_open_t meteor_open;
210d_close_t meteor_close;
211d_read_t meteor_read;
212d_write_t meteor_write;
213d_ioctl_t meteor_ioctl;
214d_mmap_t meteor_mmap;
215#else
216static d_open_t meteor_open;
217static d_close_t meteor_close;
218static d_read_t meteor_read;
219static d_write_t meteor_write;
220static d_ioctl_t meteor_ioctl;
221static d_mmap_t meteor_mmap;
222
223#define CDEV_MAJOR 67
fef8985e
MD
224static 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,
984263bc
MD
232};
233#endif
234
235static 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 */
355};
356
357static 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 */
453};
454
455static u_char bt254_default[NUM_BT254_REGS] = {
456 0x00, /* 24 bpp */
457 0xa0,
458 0xa0,
459 0xa0,
460 0x50,
461 0x50,
462 0x50,
463} ;
464
465/*
466 * i2c_write:
467 * Returns 0 Succesful completion.
468 * Returns 1 If transfer aborted or timeout occured.
469 *
470 */
471static int i2c_print_err = 1;
472static int
473i2c_write(meteor_reg_t * mtr, u_char slave, u_char rw, u_char reg, u_char data)
474{
3d0f5f54
RG
475unsigned long wait_counter = 0x0001ffff;
476mreg_t * iic_write_loc = &mtr->base->i2c_write;
477int err = 0;
984263bc
MD
478
479
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;
484
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--;
489 }
490
491 /* 1ffff should be enough delay time for the i2c cycle to complete */
492 if(!wait_counter) {
493 if(i2c_print_err)
e3869ec7 494 kprintf("meteor%d: %d i2c %s transfer timeout 0x%x",
984263bc
MD
495 METEOR_NUM(mtr), slave,
496 rw ? "read" : "write", *iic_write_loc);
497
498 err=1;
499 }
500
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)
3f625015 505 kprintf("meteor%d: 0x%x i2c %s transfer aborted",
984263bc
MD
506 METEOR_NUM(mtr), slave,
507 rw ? "read" : "write" );
508 err= 1;
509 }
510
511 if(err) {
512 if(i2c_print_err)
e3869ec7 513 kprintf(" - reg=0x%x, value=0x%x.\n", reg, data);
984263bc
MD
514 }
515
516 return err;
517}
518#undef i2c_print
519
520static const char *
521met_probe (pcici_t tag, pcidi_t type)
522{
984263bc
MD
523 switch (type) {
524 case SAA7116_PHILIPS_ID: /* meteor */
525 return("Philips SAA 7116");
526 };
60233e58 527 return (NULL);
984263bc
MD
528}
529
530 /* interrupt handling routine
531 complete meteor_read() if using interrupts
532 */
533static void
534meteor_intr(void *arg)
535{
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));
547
548 /*
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.
552 */
553 if(!(mtr->flags & METEOR_CAP_MASK)) {
554 *cap &= 0x8ff0; /* disable future interrupts */
555 }
556#ifdef METEOR_CHECK_PCI_BUS
557 /*
558 * Check for pci bus errors.
559 */
560#define METEOR_MASTER_ABORT 0x20000000
561#define METEOR_TARGET_ABORT 0x10000000
562 if(pci_err & METEOR_MASTER_ABORT) {
e3869ec7 563 kprintf("meteor%d: intr: pci bus master dma abort: 0x%x 0x%x.\n",
984263bc
MD
564 METEOR_NUM(mtr), *base, *(base+3));
565 pci_conf_write(mtr->tag, PCI_COMMAND_STATUS_REG, pci_err);
566 }
567 if(pci_err & METEOR_TARGET_ABORT) {
e3869ec7 568 kprintf("meteor%d: intr: pci bus target dma abort: 0x%x 0x%x.\n",
984263bc
MD
569 METEOR_NUM(mtr), *base, *(base+3));
570 pci_conf_write(mtr->tag, PCI_COMMAND_STATUS_REG, pci_err);
571 }
572#endif
573 /*
574 * Check for errors.
575 */
576 if (cap_err) {
577 if (cap_err & 0x300) {
578 if(mtr->fifo_errors % 50 == 0) {
e3869ec7
SW
579 kprintf("meteor%d: capture error", METEOR_NUM(mtr));
580 kprintf(": %s FIFO overflow.\n",
984263bc
MD
581 cap_err&0x0100? "even" : "odd");
582 }
583 mtr->fifo_errors++ ; /* increment fifo capture errors cnt */
584 }
585 if (cap_err & 0xc00) {
586 if(mtr->dma_errors % 50 == 0) {
e3869ec7
SW
587 kprintf("meteor%d: capture error", METEOR_NUM(mtr));
588 kprintf(": %s DMA address.\n",
984263bc
MD
589 cap_err&0x0400? "even" : "odd");
590 }
591 mtr->dma_errors++ ; /* increment DMA capture errors cnt */
592 }
593 }
594 *cap |= 0x0f30; /* clear error and field done */
595
596 /*
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).
600 */
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;
607 }
608
609 /*
610 * Count the field and clear the field flag.
611 *
612 * In single mode capture, clear the continuous capture mode.
613 *
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.
622 */
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 */
629 }
630 /*
631 * If the user requested to be notified via signal,
632 * let them know the field is complete.
633 */
634 if(mtr->proc && (mtr->signal & METEOR_SIG_MODE_MASK))
84204577 635 ksignal(mtr->proc, mtr->signal&(~METEOR_SIG_MODE_MASK));
984263bc
MD
636 }
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 */
643 }
644 /*
645 * If the user requested to be notified via signal,
646 * let them know the field is complete.
647 */
648 if(mtr->proc && (mtr->signal & METEOR_SIG_MODE_MASK))
84204577 649 ksignal(mtr->proc, mtr->signal&(~METEOR_SIG_MODE_MASK));
984263bc
MD
650 }
651
652 /*
653 * If we have a complete frame.
654 */
655 if(!(mtr->flags & METEOR_WANT_MASK)) {
656 mtr->frames_captured++;
657 /*
658 * post the completion time.
659 */
660 if(mtr->flags & METEOR_WANT_TS) {
661 struct timeval *ts;
662
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);
670 }
671 }
672 /*
673 * Wake up the user in single capture mode.
674 */
675 if(mtr->flags & METEOR_SINGLE)
676 wakeup((caddr_t)mtr);
677 /*
678 * If the user requested to be notified via signal,
679 * let them know the frame is complete.
680 */
681 if(mtr->proc && !(mtr->signal & METEOR_SIG_MODE_MASK))
84204577 682 ksignal(mtr->proc, mtr->signal&(~METEOR_SIG_MODE_MASK));
984263bc
MD
683 /*
684 * Reset the want flags if in continuous or
685 * synchronous capture mode.
686 */
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;
698 }
699 }
700 /*
701 * Special handling for synchronous capture mode.
702 */
703 if(mtr->flags & METEOR_SYNCAP) {
704 struct meteor_mem *mm = mtr->mem;
705 /*
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).
710 */
711 mm->active |= 1 << (mtr->current - 1);
712
713 /*
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.
718 *
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
723 */
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 {
732 /*
733 * Ok, they are sane, now we want to
734 * check the water marks.
735 */
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;
740 /*
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.
744 */
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++;
751 }
752 }
753 }
754 }
755
756 *stat |= 0x7; /* clear interrupt status */
757 return;
758}
759
760static void
761set_fps(meteor_reg_t *mtr, u_short fps)
762{
763 struct saa7116_regs *s7116 = mtr->base;
764 unsigned status;
765 unsigned maxfps, mask = 0x1, length = 0;
766
767 SAA7196_WRITE(mtr, SAA7196_STDC, SAA7196_REG(mtr, SAA7196_STDC) | 0x02);
768 SAA7196_READ(mtr);
769 status = (s7116->i2c_read & 0xff000000L) >> 24;
770
771 /*
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.
776 */
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 */
782 }
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
793 }
794
795 /*
796 * A little sanity checking...
797 */
798 if(fps < 1) fps = 1;
799 if(fps > maxfps) fps = maxfps;
800
801 /*
802 * Compute the mask/length using the fps.
803 */
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;
812
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 */
818 }
819 } else { /* fps < maxfps/2 */
820 float step, b;
821
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 */
827 }
828 }
829
830 /*
831 * Set the fps.
832 */
833 s7116->fme = s7116->fmo = mask;
fc6d0222 834 s7116->fml = (length << 16) | length;
984263bc
MD
835
836 mtr->fps = fps;
837
838 return;
839
840}
841
842/*
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.
850 *
851 */
852#define RANGE_BOUNDARY (1<<22)
853static vm_offset_t
854get_meteor_mem(int unit, unsigned size)
855{
856vm_offset_t addr = 0;
857
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) {
e3869ec7 862 kprintf("meteor%d: Unable to allocate %d bytes of memory.\n",
984263bc
MD
863 unit, size);
864 }
865
866 return addr;
867}
868
869static void
870bt254_write(meteor_reg_t *mtr, u_char addr, u_char data)
871{
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 */
879
880}
881
882static void
883bt254_init(meteor_reg_t *mtr)
884{
885int i;
886
887 PCF8574_CTRL_WRITE(mtr, 0x7f);
888 PCF8574_DATA_WRITE(mtr, 0xff); /* data port must be 0xff */
889 PCF8574_CTRL_WRITE(mtr, 0x7f);
890
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]);
894
895 bt254_write(mtr, BT254_COMMAND, 0x00); /* 24 bpp */
896}
897
898static void
899bt254_ntsc(meteor_reg_t *mtr, int arg)
900{
901 if (arg){
902 /* Set NTSC bit */
903 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x20);
904 }
905 else {
906 /* reset NTSC bit */
907 PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) &= ~0x20);
908 }
909}
910
911static void
912select_bt254(meteor_reg_t *mtr)
913{
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);
918}
919
920static void
921select_saa7196(meteor_reg_t *mtr)
922{
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);
927}
928
929/*
930 * Initialize the 7116, 7196 and the RGB module.
931 */
932static void
933meteor_init ( meteor_reg_t *mtr )
934{
935 mreg_t *vbase_addr;
936 int i;
937
938 /*
939 * Initialize the Philips SAA7116
940 */
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];
945
946 /*
947 * Check for the Philips SAA7196
948 */
949 i2c_print_err = 0;
950 if(i2c_write(mtr, SAA7196_I2C_ADDR, SAA7116_I2C_WRITE, 0, 0xff) == 0) {
951 i2c_print_err = 1;
952 /*
953 * Initialize 7196
954 */
955 for (i = 0; i < NUM_SAA7196_I2C_REGS; i++)
956 SAA7196_WRITE(mtr, i, saa7196_i2c_default[i]);
957 /*
958 * Get version number.
959 */
960 SAA7196_WRITE(mtr, SAA7196_STDC,
961 SAA7196_REG(mtr, SAA7196_STDC) & ~0x02);
962 SAA7196_READ(mtr);
e3869ec7 963 kprintf("meteor%d: <Philips SAA 7196> rev 0x%x\n",
984263bc
MD
964 METEOR_NUM(mtr),
965 (unsigned)((mtr->base->i2c_read & 0xff000000L) >> 28));
966 } else {
967 i2c_print_err = 1;
e3869ec7 968 kprintf("meteor%d: <Philips SAA 7196 NOT FOUND>\n",
984263bc
MD
969 METEOR_NUM(mtr));
970 }
971 /*
972 * Check for RGB module, initialized if found.
973 */
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;
e3869ec7 977 kprintf("meteor%d: <Booktree 254 (RGB module)>\n",
984263bc
MD
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;
984 }
985
986 set_fps(mtr, 30);
987
988}
989
990static void
991met_attach(pcici_t tag, int unit)
992{
993#ifdef METEOR_IRQ
994 u_long old_irq, new_irq;
06dca418 995#endif /* METEOR_IRQ */
984263bc
MD
996 meteor_reg_t *mtr;
997 vm_offset_t buf;
998 u_long latency;
999
1000 if (unit >= NMETEOR) {
e3869ec7 1001 kprintf("meteor%d: attach: only %d units configured.\n",
984263bc 1002 unit, NMETEOR);
e3869ec7 1003 kprintf("meteor%d: attach: invalid unit number.\n", unit);
984263bc
MD
1004 return ;
1005 }
1006
1007 /*
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.
1012 */
1013
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;
1017
1018 /* get tag of parent bridge */
1019 bridge_tag = pci_get_parent_from_tag( tag );
1020
1021 /* Look for IBM 82351, 82352 or 82353 */
1022 if (pci_conf_read(bridge_tag, PCI_ID_REG) == 0x00221014) {
1023
1024 if ( bootverbose)
e3869ec7 1025 kprintf("meteor%d: PPB device detected, reprogramming IBM bridge.\n", unit);
984263bc
MD
1026
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);
1035 }
1036 }
1037
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);
1042
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);
e3869ec7 1047 kprintf("meteor%d: attach: irq changed from %d to %d\n",
984263bc 1048 unit, (old_irq & 0xff), (new_irq & 0xff));
06dca418 1049#endif /* METEOR_IRQ */
984263bc 1050 /* setup the interrupt handling routine */
38787eef 1051 pci_map_int(tag, meteor_intr, (void*) mtr);
984263bc
MD
1052
1053/*
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.
1056 *
1057 */
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)
e3869ec7 1065 kprintf("meteor%d: PCI bus latency is", unit);
984263bc 1066 else
e3869ec7 1067 kprintf("meteor%d: PCI bus latency was 0 changing to",
984263bc
MD
1068 unit);
1069 }
1070 if(!latency) {
1071 latency = METEOR_DEF_LATENCY_VALUE;
1072 pci_conf_write(tag, PCI_LATENCY_TIMER, latency<<8);
1073 }
1074 if(bootverbose) {
e3869ec7 1075 kprintf(" %lu.\n", latency);
984263bc
MD
1076 }
1077
1078 meteor_init(mtr); /* set up saa7116, saa7196, and rgb module */
1079
1080 if(METEOR_ALLOC)
1081 buf = get_meteor_mem(unit, METEOR_ALLOC);
1082 else
1083 buf = 0;
1084 if(bootverbose) {
e3869ec7 1085 kprintf("meteor%d: buffer size %d, addr 0x%llx\n",
984263bc
MD
1086 unit, METEOR_ALLOC, vtophys(buf));
1087 }
1088
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;
1099 }
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 */
1105
1106 mtr->flags |= METEOR_INITALIZED | METEOR_AUTOMODE | METEOR_DEV0 |
3e82b46c 1107 METEOR_RGB16;
fef8985e 1108 make_dev(&meteor_ops, unit, 0, 0, 0644, "meteor");
984263bc
MD
1109}
1110
1111#define UNIT(x) ((x) & 0x07)
1112
1113#ifdef unused
1114static int
b13267a5 1115meteor_reset(cdev_t dev)
984263bc
MD
1116{
1117int unit = UNIT(minor(dev));
1118struct saa7116_regs *m;
1119
1120 if(unit >= NMETEOR)
1121 return ENXIO;
1122
1123 m = meteor[unit].base;
1124
1125 m->cap_cntl = 0x0;
1126 tsleep((caddr_t)m, METPRI, "Mreset", hz/50);
1127
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;
1133
1134 return 0;
1135
1136}
1137#endif
1138
1139/*---------------------------------------------------------
1140**
1141** Meteor character device driver routines
1142**
1143**---------------------------------------------------------
1144*/
1145
984263bc 1146int
fef8985e 1147meteor_open(struct dev_open_args *ap)
984263bc 1148{
b13267a5 1149 cdev_t dev = ap->a_head.a_dev;
984263bc
MD
1150 meteor_reg_t *mtr;
1151 int unit;
1152 int i;
1153
1154 unit = UNIT(minor(dev));
1155 if (unit >= NMETEOR) /* unit out of range */
1156 return(ENXIO);
1157
1158 mtr = &(meteor[unit]);
1159
1160 if (!(mtr->flags & METEOR_INITALIZED)) /* device not found */
1161 return(ENXIO);
1162
1163 if (mtr->flags & METEOR_OPEN) /* device is busy */
1164 return(EBUSY);
1165
1166 mtr->flags |= METEOR_OPEN;
1167 /*
1168 * Make sure that the i2c regs are set the same for each open.
1169 */
1170 for(i=0; i< NUM_SAA7196_I2C_REGS; i++) {
1171 SAA7196_WRITE(mtr, i, saa7196_i2c_default[i]);
1172 }
1173
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;
60233e58 1179 mtr->proc = NULL;
984263bc
MD
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
1187
1188 return(0);
1189}
1190
1191int
fef8985e 1192meteor_close(struct dev_close_args *ap)
984263bc 1193{
b13267a5 1194 cdev_t dev = ap->a_head.a_dev;
984263bc
MD
1195 meteor_reg_t *mtr;
1196 int unit;
1197#ifdef METEOR_DEALLOC_ABOVE
1198 int temp;
1199#endif
1200
1201 unit = UNIT(minor(dev));
1202 if (unit >= NMETEOR) /* unit out of range */
1203 return(ENXIO);
1204
1205 mtr = &(meteor[unit]);
1206 mtr->flags &= ~METEOR_OPEN;
1207
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 */
1213 /*
1214 * Turn off capture mode.
1215 */
1216 mtr->base->cap_cntl = 0x8ff0;
1217 mtr->flags &= ~(METEOR_CAP_MASK|METEOR_WANT_MASK);
60233e58 1218 mtr->proc = NULL;
984263bc
MD
1219
1220#ifdef METEOR_DEALLOC_PAGES
1221 if (mtr->bigbuf != NULL) {
e4846942
MD
1222 kmem_free(&kernel_map, mtr->bigbuf,
1223 (mtr->alloc_pages * PAGE_SIZE));
984263bc
MD
1224 mtr->bigbuf = NULL;
1225 mtr->alloc_pages = 0;
1226 }
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;
e4846942 1231 kmem_free(&kernel_map,
984263bc
MD
1232 mtr->bigbuf+((mtr->alloc_pages - temp) * PAGE_SIZE),
1233 (temp * PAGE_SIZE));
1234 mtr->alloc_pages = METEOR_DEALLOC_ABOVE;
1235 }
1236#endif
1237#endif
1238
1239 return(0);
1240}
1241
1242static void
1243start_capture(meteor_reg_t *mtr, unsigned type)
1244{
1245mreg_t *cap = &mtr->base->cap_cntl;
1246
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;
1270 }
1271}
1272
1273int
fef8985e 1274meteor_read(struct dev_read_args *ap)
984263bc 1275{
b13267a5 1276 cdev_t dev = ap->a_head.a_dev;
fef8985e 1277 struct uio *uio = ap->a_uio;
984263bc
MD
1278 meteor_reg_t *mtr;
1279 int unit;
1280 int status;
1281 int count;
1282
1283 unit = UNIT(minor(dev));
1284 if (unit >= NMETEOR) /* unit out of range */
1285 return(ENXIO);
1286
1287 mtr = &(meteor[unit]);
1288 if (mtr->bigbuf == 0)/* no frame buffer allocated (ioctl failed) */
1289 return(ENOMEM);
1290
1291 if (mtr->flags & METEOR_CAP_MASK)
1292 return(EIO); /* already capturing */
1293
1294 count = mtr->rows * mtr->cols * mtr->depth;
1295 if (uio->uio_iov->iov_len < count)
1296 return(EINVAL);
1297
1298 /* Start capture */
1299 start_capture(mtr, METEOR_SINGLE);
1300
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
e3869ec7 1305 kprintf ("meteor%d: read: tsleep error %d\n", unit, status);
984263bc
MD
1306
1307 mtr->flags &= ~(METEOR_SINGLE | METEOR_WANT_MASK);
1308
1309 return(status);
1310}
1311
1312int
fef8985e 1313meteor_write(struct dev_write_args *ap)
984263bc
MD
1314{
1315 return(0);
1316}
1317
1318int
fef8985e 1319meteor_ioctl(struct dev_ioctl_args *ap)
984263bc 1320{
b13267a5 1321 cdev_t dev = ap->a_head.a_dev;
fef8985e 1322 caddr_t data = ap->a_data;
984263bc
MD
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;
1336
1337 error = 0;
1338
fef8985e
MD
1339 if (data == NULL)
1340 return(EINVAL);
984263bc
MD
1341 unit = UNIT(minor(dev));
1342 if (unit >= NMETEOR) /* unit out of range */
1343 return(ENXIO);
1344
1345 mtr = &(meteor[unit]);
1346 base = mtr->base;
1347
fef8985e 1348 switch (ap->a_cmd) {
984263bc 1349 case METEORSTS:
fef8985e 1350 if(*data)
984263bc
MD
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)
fef8985e 1357 *data = 1;
984263bc 1358 else
fef8985e 1359 *data = 0;
984263bc
MD
1360 break;
1361#ifdef METEOR_TEST_VIDEO
1362 case METEORGVIDEO:
fef8985e 1363 video = (struct meteor_video *)data;
984263bc
MD
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:
fef8985e 1370 video = (struct meteor_video *)data;
984263bc
MD
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:
fef8985e 1378 set_fps(mtr, *(u_short *)data);
984263bc
MD
1379 break;
1380 case METEORGFPS:
fef8985e 1381 *(u_short *)data = mtr->fps;
984263bc
MD
1382 break;
1383 case METEORSSIGNAL:
fef8985e 1384 if (*(int *)data < 0 || *(int *)data > _SIG_MAXSIG)
d82eda3e 1385 return EINVAL;
fef8985e 1386 mtr->signal = *(int *) data;
984263bc 1387 if (mtr->signal) {
fef8985e 1388 mtr->proc = curproc; /* might be NULL */
984263bc 1389 } else {
60233e58 1390 mtr->proc = NULL;
984263bc
MD
1391 }
1392 break;
1393 case METEORGSIGNAL:
fef8985e 1394 *(int *)data = mtr->signal;
984263bc
MD
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;
fef8985e 1406 *(u_short *)data = temp;
984263bc
MD
1407 break;
1408 case METEORSHUE: /* set hue */
fef8985e 1409 SAA7196_WRITE(mtr, SAA7196_HUEC, *(char *)data);
984263bc
MD
1410 break;
1411 case METEORGHUE: /* get hue */
fef8985e 1412 *(char *)data = SAA7196_REG(mtr, SAA7196_HUEC);
984263bc
MD
1413 break;
1414 case METEORSCHCV: /* set chrominance gain */
fef8985e 1415 SAA7196_WRITE(mtr, SAA7196_CGAINR, *(char *)data);
984263bc
MD
1416 break;
1417 case METEORGCHCV: /* get chrominance gain */
fef8985e 1418 *(char *)data = SAA7196_REG(mtr, SAA7196_CGAINR);
984263bc
MD
1419 break;
1420 case METEORSBRIG: /* set brightness */
fef8985e 1421 SAA7196_WRITE(mtr, SAA7196_BRIG, *(char *)data);
984263bc
MD
1422 break;
1423 case METEORGBRIG: /* get brightness */
fef8985e 1424 *(char *)data = SAA7196_REG(mtr, SAA7196_BRIG);
984263bc
MD
1425 break;
1426 case METEORSCSAT: /* set chroma saturation */
fef8985e 1427 SAA7196_WRITE(mtr, SAA7196_CSAT, *(char *)data);
984263bc
MD
1428 break;
1429 case METEORGCSAT: /* get chroma saturation */
fef8985e 1430 *(char *)data = SAA7196_REG(mtr, SAA7196_CSAT);
984263bc
MD
1431 break;
1432 case METEORSCONT: /* set contrast */
fef8985e 1433 SAA7196_WRITE(mtr, SAA7196_CONT, *(char *)data);
984263bc
MD
1434 break;
1435 case METEORGCONT: /* get contrast */
fef8985e 1436 *(char *)data = SAA7196_REG(mtr, SAA7196_CONT);
984263bc
MD
1437 break;
1438 case METEORSBT254:
1439 if((mtr->flags & METEOR_RGB) == 0)
1440 return EINVAL;
fef8985e 1441 temp = *(unsigned short *)data;
984263bc
MD
1442 bt254_write(mtr, temp & 0xf, (temp & 0x0ff0) >> 4);
1443 break;
1444 case METEORGBT254:
1445 if((mtr->flags & METEOR_RGB) == 0)
1446 return EINVAL;
fef8985e
MD
1447 temp = *(unsigned short *)data & 0x7;
1448 *(unsigned short *)data = mtr->bt254_reg[temp] << 4 | temp;
984263bc
MD
1449 break;
1450 case METEORSHWS: /* set horizontal window start */
fef8985e 1451 SAA7196_WRITE(mtr, SAA7196_HWS, *(char *)data);
984263bc
MD
1452 break;
1453 case METEORGHWS: /* get horizontal window start */
fef8985e 1454 *(char *)data = SAA7196_REG(mtr, SAA7196_HWS);
984263bc
MD
1455 break;
1456 case METEORSVWS: /* set vertical window start */
fef8985e 1457 SAA7196_WRITE(mtr, SAA7196_VWS, *(char *)data);
984263bc
MD
1458 break;
1459 case METEORGVWS: /* get vertical window start */
fef8985e 1460 *(char *)data = SAA7196_REG(mtr, SAA7196_VWS);
984263bc
MD
1461 break;
1462 case METEORSINPUT: /* set input device */
fef8985e 1463 switch(*(unsigned long *)data & METEOR_DEV_MASK) {
984263bc
MD
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;
1530 }
1531 break;
1532 case METEORGINPUT: /* get input device */
fef8985e 1533 *(u_long *)data = mtr->flags & METEOR_DEV_MASK;
984263bc
MD
1534 break;
1535 case METEORSFMT: /* set input format */
fef8985e 1536 switch(*(unsigned long *)data & METEOR_FORM_MASK ) {
984263bc
MD
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);
1553 }
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);
1570 }
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);
1587 }
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;
1599 }
1600 break;
1601 case METEORGFMT: /* get input format */
fef8985e 1602 *(u_long *)data = mtr->flags & METEOR_FORM_MASK;
984263bc
MD
1603 break;
1604 case METEORCAPTUR:
1605 temp = mtr->flags;
fef8985e 1606 switch (*(int *) data) {
984263bc
MD
1607 case METEOR_CAP_SINGLE:
1608 if (mtr->bigbuf==0) /* no frame buffer allocated */
1609 return(ENOMEM);
1610
1611 if (temp & METEOR_CAP_MASK)
1612 return(EIO); /* already capturing */
1613
1614 start_capture(mtr, METEOR_SINGLE);
1615
1616 /* wait for capture to complete */
1617 error=tsleep((caddr_t)mtr, METPRI, "capturing", 0);
1618 if(error)
e3869ec7 1619 kprintf("meteor%d: ioctl: tsleep error %d\n",
984263bc
MD
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);
1626
1627 if (temp & METEOR_CAP_MASK)
1628 return(EIO); /* already capturing */
1629
1630 start_capture(mtr, METEOR_CONTIN);
1631
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);
1638 }
1639 break;
1640
1641 default:
1642 error = EINVAL;
1643 break;
1644 }
1645 break;
1646 case METEORCAPFRM:
fef8985e 1647 frame = (struct meteor_capframe *) data;
984263bc
MD
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);
1683 }
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);
1689 }
1690 break;
1691 case METEOR_CONT_N_FRAMES:
1692 if(!(mtr->flags & METEOR_SYNCAP)) {
1693 error = EINVAL;
1694 break;
1695 }
1696 start_capture(mtr, METEOR_SYNCAP);
1697 break;
1698 default:
1699 error = EINVAL;
1700 break;
1701 }
1702 break;
1703
1704 case METEORSETGEO:
fef8985e 1705 geo = (struct meteor_geomet *) data;
984263bc
MD
1706
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)) {
e3869ec7 1710 kprintf("meteor%d: ioctl: Geometry odd or even only.\n",
984263bc
MD
1711 unit);
1712 return EINVAL;
1713 }
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;
1723
1724 /* can't change parameters while capturing */
1725 if (mtr->flags & METEOR_CAP_MASK)
1726 return(EBUSY);
1727
1728 if ((geo->columns & 0x3fe) != geo->columns) {
e3869ec7 1729 kprintf(
984263bc
MD
1730 "meteor%d: ioctl: %d: columns too large or not even.\n",
1731 unit, geo->columns);
1732 error = EINVAL;
1733 }
1734 if (((geo->rows & 0x7fe) != geo->rows) ||
1735 ((geo->oformat & METEOR_GEO_FIELD_MASK) &&
1736 ((geo->rows & 0x3fe) != geo->rows)) ) {
e3869ec7 1737 kprintf(
984263bc
MD
1738 "meteor%d: ioctl: %d: rows too large or not even.\n",
1739 unit, geo->rows);
1740 error = EINVAL;
1741 }
1742 if (geo->frames > 32) {
e3869ec7 1743 kprintf("meteor%d: ioctl: too many frames.\n", unit);
984263bc
MD
1744 error = EINVAL;
1745 }
1746 if(error) return error;
1747
1748 if ((temp=geo->rows * geo->columns * geo->frames * 2) != 0) {
1749 if (geo->oformat & METEOR_GEO_RGB24) temp = temp * 2;
1750
1751 /* meteor_mem structure for SYNC Capture */
1752 if (geo->frames > 1) temp += PAGE_SIZE;
1753
1754 temp = btoc(temp);
1755 if (temp > mtr->alloc_pages
1756#ifdef METEOR_TEST_VIDEO
1757 && mtr->video.addr == 0
1758#endif
1759 ) {
1760 buf = get_meteor_mem(unit, temp*PAGE_SIZE);
1761 if(buf != 0) {
e4846942 1762 kmem_free(&kernel_map, mtr->bigbuf,
984263bc
MD
1763 (mtr->alloc_pages * PAGE_SIZE));
1764 mtr->bigbuf = buf;
1765 mtr->alloc_pages = temp;
1766 if(bootverbose)
e3869ec7 1767 kprintf(
984263bc
MD
1768 "meteor%d: ioctl: Allocating %d bytes\n",
1769 unit, temp*PAGE_SIZE);
1770 } else {
1771 error = ENOMEM;
1772 }
1773 }
1774 }
1775 if(error) return error;
1776
1777 mtr->rows = geo->rows;
1778 mtr->cols = geo->columns;
1779 mtr->frames = geo->frames;
1780
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);
1787
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;
1804
1805 /*
1806 * Determine if we can use the hardware range detect.
1807 */
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;
1816 }
1817
1818
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;
1855 }
1856#endif
1857 SAA7196_WRITE(mtr, 0x20, 0x90);
1858 break;
1859 }
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;
1897 }
1898#endif
1899 SAA7196_WRITE(mtr, 0x20, 0x92);
1900 break;
1901 }
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;
1937 }
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;
1949 }
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;
1987 }
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;
1999 }
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;
2023 }
2024 base->routee = base->routeo = 0xeeeeee41;
2025 break;
2026 default:
2027 error = EINVAL; /* invalid argument */
e3869ec7 2028 kprintf("meteor%d: ioctl: invalid output format\n",unit);
984263bc
MD
2029 break;
2030 }
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)));
2047 }
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:
fef8985e 2053 geo = (struct meteor_geomet *) data;
984263bc
MD
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;
2070 }
2071 break;
2072 case METEORSCOUNT: /* (re)set error counts */
fef8985e 2073 cnt = (struct meteor_counts *) data;
984263bc
MD
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 */
fef8985e 2081 cnt = (struct meteor_counts *) data;
984263bc
MD
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:
e3869ec7 2089 kprintf("meteor%d: ioctl: invalid ioctl request\n", unit);
984263bc
MD
2090 error = ENOTTY;
2091 break;
2092 }
2093 return(error);
2094}
2095
2096int
fef8985e 2097meteor_mmap(struct dev_mmap_args *ap)
984263bc 2098{
b13267a5 2099 cdev_t dev = ap->a_head.a_dev;
984263bc
MD
2100 int unit;
2101 meteor_reg_t *mtr;
2102
2103 unit = UNIT(minor(dev));
2104 if (unit >= NMETEOR) /* at this point could this happen? */
2105 return(-1);
2106
2107 mtr = &(meteor[unit]);
2108
2109
fef8985e 2110 if (ap->a_nprot & PROT_EXEC)
984263bc
MD
2111 return -1;
2112
fef8985e 2113 if (ap->a_offset >= mtr->alloc_pages * PAGE_SIZE)
984263bc
MD
2114 return -1;
2115
fef8985e 2116 return i386_btop(vtophys(mtr->bigbuf) + ap->a_offset);
984263bc 2117}