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