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