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