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