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