The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/pci/meteor.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: b71cdfd9a8337a3a263a941b917219fa


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.