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