File:  [DragonFly] / src / sys / dev / video / meteor / meteor.c
Revision 1.12: download - view: text, annotated - select for diffs
Sat May 15 17:54:13 2004 UTC (10 years, 4 months ago) by joerg
Branches: MAIN
CVS tags: HEAD
Update bktr(4) to FreeBSD current's version. This most importantly
includes a new msp driver based on the Linux Brooktree driver.

Add support for Terratec TValue submitted by Patrick Mauritz
<oxygene@studentenbude.ath.cx>.

The ioctl headers are moved into the MI dev/ tree, symlinks for
compatibiliy are added in a separate commit.

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