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