Ho ho ho. Merry MatroXmas to all.

Here's a patch that adds support for a separate CRTC2 layer. It uses the
ITU-R 656 mode so YUV support is included.
Some noteworthy things:
- RGB15,16,32, ARGB, YUY2, UYVY, I420 and YV12 support :)
- Only 720x576 (864x625) PAL and 720x486 (858x525) (are these correct?)
NTSC resolutions
- Only TV out, no monitor.
- Sometimes MAVEN gets confused and seems to drop chrominance data. It
will correct itself with a few retries. Maybe some programming sequence
issue.
- Mike Pieper's maven parameter patch had some interesting stuff. 
Hue,sat etc. and some deflicker stuff so maybe DLOP_FLICKER_FILTERING can
be supported with that.
- CRTC2 address register are double buffered like the BES so some kind of
interrupt hack might be nice. Maybe glue some stuff onto
matroxfb-vsync-irq patch?
- MAVEN part is based on matroxfb_maven and some register dumping I did in
Windows. I have Petr Vandrovec's permission to release it under any
license I want.
- I don't know much about video stuff so some things might be wrong.
Please don't hesitate to correct me.
- Tested on a G400 DH w/ PAL TV.
- 'cvs diff' ignored new files so I've attached them as is.

To use it use must load i2c-matroxfb module but do not load
matroxfb_maven. It uses /dev/i2c interface and parses /proc/bus/i2c to
find the proper /dev/i2c entry so I suppose it requires i2c-proc and
i2c-dev as well.

Hope you like it :)

-- 
Ville Syrj�l�
[EMAIL PROTECTED]
http://www.sci.fi/~syrjala/
Index: DirectFB/gfxdrivers/matrox/Makefile.am
===================================================================
RCS file: /cvs/directfb/DirectFB/gfxdrivers/matrox/Makefile.am,v
retrieving revision 1.4
diff -u -d -r1.4 Makefile.am
--- DirectFB/gfxdrivers/matrox/Makefile.am      17 Jan 2002 14:46:03 -0000      1.4
+++ DirectFB/gfxdrivers/matrox/Makefile.am      2 Aug 2002 21:06:02 -0000
@@ -14,6 +14,9 @@
        matrox.c        \
        matrox.h        \
        matrox_bes.c    \
+       matrox_crtc2.c  \
+       matrox_maven.c  \
+       matrox_maven.h  \
        matrox_state.c  \
        matrox_state.h  \
        regs.h          \
Index: DirectFB/gfxdrivers/matrox/matrox.c
===================================================================
RCS file: /cvs/directfb/DirectFB/gfxdrivers/matrox/matrox.c,v
retrieving revision 1.34
diff -u -d -r1.34 matrox.c
--- DirectFB/gfxdrivers/matrox/matrox.c 30 Jun 2002 22:06:19 -0000      1.34
+++ DirectFB/gfxdrivers/matrox/matrox.c 2 Aug 2002 21:06:05 -0000
@@ -868,12 +868,15 @@
 
      /* will be set dynamically: funcs->Blit */
 
-     
+
      /* G200/G400/G450/G550 Backend Scaler Support */
      if (mdrv->accelerator == FB_ACCEL_MATROX_MGAG200 ||
          mdrv->accelerator == FB_ACCEL_MATROX_MGAG400)
           dfb_layers_register( device, driver_data, &matroxBesFuncs );
 
+     if (mdrv->accelerator == FB_ACCEL_MATROX_MGAG400)
+          dfb_layers_register( device, driver_data, &matroxCrtc2Funcs );
+
      return DFB_OK;
 }
 
@@ -965,7 +968,7 @@
 
      /* set hardware limitations */
      device_info->limits.surface_byteoffset_alignment = 32 * 4;
-     device_info->limits.surface_pixelpitch_alignment = 32;
+     device_info->limits.surface_pixelpitch_alignment = 128;
 
 
      mga_waitfifo( mdrv, mdev, 11 );
Index: DirectFB/gfxdrivers/matrox/matrox.h
===================================================================
RCS file: /cvs/directfb/DirectFB/gfxdrivers/matrox/matrox.h,v
retrieving revision 1.14
diff -u -d -r1.14 matrox.h
--- DirectFB/gfxdrivers/matrox/matrox.h 30 Jun 2002 22:06:19 -0000      1.14
+++ DirectFB/gfxdrivers/matrox/matrox.h 2 Aug 2002 21:06:05 -0000
@@ -87,6 +87,7 @@
 } MatroxDeviceData;
 
 extern DisplayLayerFuncs matroxBesFuncs;
+extern DisplayLayerFuncs matroxCrtc2Funcs;
 
 static inline unsigned int log2( unsigned int val )
 {
Index: DirectFB/gfxdrivers/matrox/mmio.h
===================================================================
RCS file: /cvs/directfb/DirectFB/gfxdrivers/matrox/mmio.h,v
retrieving revision 1.8
diff -u -d -r1.8 mmio.h
--- DirectFB/gfxdrivers/matrox/mmio.h   27 May 2002 15:51:54 -0000      1.8
+++ DirectFB/gfxdrivers/matrox/mmio.h   2 Aug 2002 21:06:05 -0000
@@ -102,5 +102,12 @@
      mga_out8( mmioaddr, val, DAC_DATA );
 }
 
+static inline volatile uint8
+mga_in_dac( volatile uint8 *mmioaddr, uint8 reg )
+{
+     mga_out8( mmioaddr, reg, DAC_INDEX );
+     return mga_in8( mmioaddr, DAC_DATA );
+}
+
 #endif
 
Index: DirectFB/gfxdrivers/matrox/regs.h
===================================================================
RCS file: /cvs/directfb/DirectFB/gfxdrivers/matrox/regs.h,v
retrieving revision 1.10
diff -u -d -r1.10 regs.h
--- DirectFB/gfxdrivers/matrox/regs.h   30 May 2002 09:22:05 -0000      1.10
+++ DirectFB/gfxdrivers/matrox/regs.h   2 Aug 2002 21:06:05 -0000
@@ -36,6 +36,27 @@
 
 #define OPMODE           0x1E54
 
+/* CRTC2 registers */
+#define C2CTL            0x3C10
+#define C2HPARAM         0x3C14
+#define C2HSYNC          0x3C18
+#define C2VPARAM         0x3C1C
+#define C2VSYNC          0x3C20
+#define C2PRELOAD        0x3C24
+#define C2STARTADD0      0x3C28
+#define C2STARTADD1      0x3C2C
+#define C2PL2STARTADD0   0x3C30
+#define C2PL2STARTADD1   0x3C34
+#define C2PL3STARTADD0   0x3C38
+#define C2PL3STARTADD1   0x3C3C
+#define C2OFFSET         0x3C40
+#define C2MISC           0x3C44
+#define C2VCOUNT         0x3C48
+#define C2DATACTL        0x3C4C
+#define C2SUBPICLUT      0x3C50
+#define C2SPICSTARTADD0  0x3C54
+#define C2SPICSTARTADD1  0x3C58
+
 /* Backend scaler registers */
 #define BESA1ORG         0x3D00
 #define BESA2ORG         0x3D04
@@ -325,6 +346,8 @@
 
 
 /* DAC registers */
+
+#define XMISCCTRL      0x1e
 
 #define XKEYOPMODE     0x51
 
Index: DirectFB/src/misc/conf.c
===================================================================
RCS file: /cvs/directfb/DirectFB/src/misc/conf.c,v
retrieving revision 1.34
diff -u -d -r1.34 conf.c
--- DirectFB/src/misc/conf.c    28 Jul 2002 23:09:25 -0000      1.34
+++ DirectFB/src/misc/conf.c    2 Aug 2002 21:06:06 -0000
@@ -113,6 +113,8 @@
     "Limit amount of Video RAM in kb\n"
     "  [no-]matrox-sgram              "
     "Use Matrox SGRAM features\n"
+    "  matrox-tv-standard=(pal|ntsc)  "
+    "Matrox TV standard (default=pal)\n"
     "  screenshot-dir=<directory>     "
     "Dump screen content on <Print> key presses\n"
     "  fbdebug=<device>               "
@@ -604,6 +606,25 @@
      } else
      if (strcmp (name, "matrox-sgram" ) == 0) {
           dfb_config->matrox_sgram = true;
+     } else
+     if (strcmp (name, "matrox-tv-standard" ) == 0) {
+          if (value) {
+               if (strcmp( value, "pal" ) == 0) {
+                    dfb_config->matrox_ntsc = false;
+               } else
+               if (strcmp( value, "ntsc" ) == 0) {
+                    dfb_config->matrox_ntsc = true;
+               } else {
+                    ERRORMSG( "DirectFB/Config: Unknown TV standard "
+                              "'%s'!\n", value );
+                    return DFB_INVARG;
+               }
+          }
+          else {
+               ERRORMSG( "DirectFB/Config: "
+                         "No TV standard specified!\n" );
+               return DFB_INVARG;
+          }
      } else
      if (strcmp (name, "no-matrox-sgram" ) == 0) {
           dfb_config->matrox_sgram = false;
Index: DirectFB/src/misc/conf.h
===================================================================
RCS file: /cvs/directfb/DirectFB/src/misc/conf.h,v
retrieving revision 1.25
diff -u -d -r1.25 conf.h
--- DirectFB/src/misc/conf.h    28 Jul 2002 23:09:25 -0000      1.25
+++ DirectFB/src/misc/conf.h    2 Aug 2002 21:06:07 -0000
@@ -74,6 +74,7 @@
                                                      as argb and not a8 */
 
      bool      matrox_sgram;                      /* Use Matrox SGRAM features*/
+     bool      matrox_ntsc;                       /* Matrox TV standard */
      bool      sync;                              /* Do sync() in core_init() */
      bool      vt_switching;                      /* Allow VT switching by
                                                      pressing Ctrl+Alt+<F?> */
/*
   (c) Copyright 2000-2002  convergence integrated media GmbH.
   (c) Copyright 2002       convergence GmbH.
   
   All rights reserved.

   Written by Denis Oliver Kropp <[EMAIL PROTECTED]>,
              Andreas Hundt <[EMAIL PROTECTED]>,
              Sven Neumann <[EMAIL PROTECTED]> and
              Ville Syrjala <[EMAIL PROTECTED]>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, write to the
   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.
*/

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

#include <sys/mman.h>
#include <fcntl.h>
#include <sys/ioctl.h>

#include <directfb.h>

#include <core/fusion/shmalloc.h>

#include <core/coredefs.h>
#include <core/coretypes.h>
#include <core/gfxcard.h>
#include <core/fbdev.h>
#include <core/layers.h>
#include <core/surfaces.h>
#include <core/windows.h>

#include <misc/mem.h>


#include "regs.h"
#include "mmio.h"
#include "matrox.h"
#include "matrox_maven.h"

typedef struct {
     bool                  listener_running;
     DFBDisplayLayerConfig config;

     /* Stored registers */
     struct {
          /* CRTC2 */
          __u32 c2CTL;
          __u32 c2DATACTL;
          __u32 c2MISC;
          __u32 c2OFFSET;

          __u32 c2HPARAM;
          __u32 c2HSYNC;
          __u32 c2VPARAM;
          __u32 c2VSYNC;
          __u32 c2PRELOAD;

          __u32 c2STARTADD0;
          __u32 c2STARTADD1;
          __u32 c2PL2STARTADD0;
          __u32 c2PL2STARTADD1;
          __u32 c2PL3STARTADD0;
          __u32 c2PL3STARTADD1;

          __u32 c2SPICSTARTADD0;
          __u32 c2SPICSTARTADD1;
          __u32 c2SUBPICLUT;

          __u32 c2VCOUNT;
     } regs;

     struct maven_data md;
     struct mavenregs mr;
} MatroxCrtc2LayerData;

static void crtc2_set_regs( MatroxDriverData *mdrv, MatroxCrtc2LayerData *mcrtc2 );
static void crtc2_calc_regs( MatroxDriverData *mdrv, MatroxCrtc2LayerData *mcrtc2,
                             DisplayLayer *layer );
static void crtc2_set_buffer( MatroxDriverData *mdrv, MatroxCrtc2LayerData *mcrtc2,
                              DisplayLayer *layer );

#define CRTC2_SUPPORTED_OPTIONS   (DLOP_DEINTERLACING)

/**********************/

static int
crtc2LayerDataSize()
{
     return sizeof(MatroxCrtc2LayerData);
}
     
static DFBResult
crtc2InitLayer( GraphicsDevice             *device,
                DisplayLayer               *layer,
                DisplayLayerInfo           *layer_info,
                DFBDisplayLayerConfig      *default_config,
                DFBColorAdjustment         *default_adj,
                void                       *driver_data,
                void                       *layer_data )
{
     MatroxDriverData     *mdrv   = (MatroxDriverData*) driver_data;
     MatroxCrtc2LayerData *mcrtc2 = (MatroxCrtc2LayerData*) layer_data;
     volatile __u8        *mmio   = mdrv->mmio_base;

     /* set capabilities and type */
     layer_info->desc.caps = DLCAPS_SURFACE |
                             DLCAPS_BRIGHTNESS | DLCAPS_CONTRAST |
                             DLCAPS_HUE | DLCAPS_SATURATION;
     layer_info->desc.type = DLTF_GRAPHICS | DLTF_VIDEO | DLTF_STILL_PICTURE;

     /* set name */
     snprintf( layer_info->name,
               DFB_DISPLAY_LAYER_INFO_NAME_LENGTH, "Matrox CRTC2" );

     /* fill out the default configuration */
     default_config->flags       = DLCONF_WIDTH | DLCONF_HEIGHT |
                                   DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE |
                                   DLCONF_OPTIONS;
     default_config->width       = 720;
     default_config->height      = dfb_config->matrox_ntsc ? 486 : 576;
     default_config->pixelformat = DSPF_YUY2;
     default_config->buffermode  = DLBM_FRONTONLY;
     default_config->options     = DLOP_NONE;

     /* fill out default color adjustment,
        only fields set in flags will be accepted from applications */
     default_adj->flags      = DCAF_BRIGHTNESS | DCAF_CONTRAST |
                               DCAF_HUE | DCAF_SATURATION;
     default_adj->brightness = 0x8000;
     default_adj->contrast   = 0x8000;
     default_adj->hue        = 0x8000;
     default_adj->saturation = 0x8000;

     /* disable crtc2 */
     mga_out32( mmio, 0, C2CTL );
     mga_out32( mmio, 8, C2CTL );

     maven_open( &mcrtc2->md );

     return DFB_OK;
}


static void
crtc2OnOff( MatroxDriverData     *mdrv,
            MatroxCrtc2LayerData *mcrtc2,
            int                   on )
{
     volatile __u8 *mmio = mdrv->mmio_base;

     if (on) {
          uint8 val;
          val = mga_in_dac( mmio, XMISCCTRL );
          /*
           * mfcsel = 01 (MAFC)
           * vdoutsel = 110 (CRTC2 ITU-R 656)
           */
          val &= 0x19;
          val |= 0xC2;
          mga_out_dac( mmio, XMISCCTRL, val );
     }

     if (on)
          /* c2en = 1 */
          mcrtc2->regs.c2CTL |= 1;
     else
          /* c2en = 0 */
          mcrtc2->regs.c2CTL &= ~1;
     mga_out32( mmio, mcrtc2->regs.c2CTL, C2CTL );

     if (on)
          /* c2pixclkdis = 0 */
          mcrtc2->regs.c2CTL &= ~8;
     else
          /* c2pixclkdis = 1 */
          mcrtc2->regs.c2CTL |= 8;
     mga_out32( mmio, mcrtc2->regs.c2CTL, C2CTL );

     if (on) {
          /* c2interlace = 1 */
          mcrtc2->regs.c2CTL |= (1 << 25);
          mga_out32( mmio, mcrtc2->regs.c2CTL, C2CTL );
     }
}

static DFBResult
crtc2Enable( DisplayLayer *layer,
             void         *driver_data,
             void         *layer_data )
{
     MatroxDriverData     *mdrv   = (MatroxDriverData*) driver_data;
     MatroxCrtc2LayerData *mcrtc2 = (MatroxCrtc2LayerData*) layer_data;

     /* enable crtc2 */
     crtc2OnOff( mdrv, mcrtc2, 1 );

     return DFB_OK;
}

static DFBResult
crtc2Disable( DisplayLayer *layer,
              void         *driver_data,
              void         *layer_data )
{
     MatroxDriverData     *mdrv   = (MatroxDriverData*) driver_data;
     MatroxCrtc2LayerData *mcrtc2 = (MatroxCrtc2LayerData*) layer_data;

     /* disable crtc2 */
     crtc2OnOff( mdrv, mcrtc2, 0 );

     return DFB_OK;
}

static DFBResult
crtc2TestConfiguration( DisplayLayer               *layer,
                        void                       *driver_data,
                        void                       *layer_data,
                        DFBDisplayLayerConfig      *config,
                        DFBDisplayLayerConfigFlags *failed )
{
     DFBDisplayLayerConfigFlags  fail = 0;

     if (config->options & ~CRTC2_SUPPORTED_OPTIONS)
          fail |= DLCONF_OPTIONS;

     switch (config->pixelformat) {
          case DSPF_ARGB:
          case DSPF_RGB32:
          case DSPF_RGB15:
          case DSPF_RGB16:
          case DSPF_YUY2:
          case DSPF_UYVY:
          case DSPF_I420:
          case DSPF_YV12:
               break;
          default:
               fail |= DLCONF_PIXELFORMAT;
     }

     if (config->width != 720)
          fail |= DLCONF_WIDTH;

     if (config->height != (dfb_config->matrox_ntsc ? 486 : 576))
          fail |= DLCONF_HEIGHT;

     if (failed)
          *failed = fail;

     if (fail)
          return DFB_UNSUPPORTED;

     return DFB_OK;
}

static DFBResult
crtc2SetConfiguration( DisplayLayer          *layer,
                       void                  *driver_data,
                       void                  *layer_data,
                       DFBDisplayLayerConfig *config )
{
     MatroxDriverData     *mdrv   = (MatroxDriverData*) driver_data;
     MatroxCrtc2LayerData *mcrtc2 = (MatroxCrtc2LayerData*) layer_data;

     /* remember configuration */
     mcrtc2->config = *config;

     maven_set_mode( &mcrtc2->md, dfb_config->matrox_ntsc ? MODE_NTSC : MODE_PAL );
     maven_compute( &mcrtc2->md, &mcrtc2->mr );
     crtc2_calc_regs( mdrv, mcrtc2, layer );

     crtc2OnOff( mdrv, mcrtc2, 0 );
     crtc2_set_regs( mdrv, mcrtc2 );
     crtc2_set_buffer( mdrv, mcrtc2, layer );
     crtc2OnOff( mdrv, mcrtc2, 1 );
     maven_program( &mcrtc2->md, &mcrtc2->mr );

     return DFB_OK;
}

static DFBResult
crtc2FlipBuffers( DisplayLayer        *layer,
                  void                *driver_data,
                  void                *layer_data,
                  DFBSurfaceFlipFlags  flags )
{
     MatroxDriverData     *mdrv    = (MatroxDriverData*) driver_data;
     MatroxCrtc2LayerData *mcrtc2  = (MatroxCrtc2LayerData*) layer_data;
     CoreSurface          *surface = dfb_layer_surface( layer );

     dfb_surface_flip_buffers( surface );

     crtc2_set_buffer( mdrv, mcrtc2, layer );

#if 0
     // FIXME modify matroxfb-vsync-irq patch?
     if (flags & DSFLIP_WAITFORSYNC)
          crtc2_wait_vsync();
#endif

     return DFB_OK;
}

static DFBResult
crtc2SetColorAdjustment( DisplayLayer       *layer,
                         void               *driver_data,
                         void               *layer_data,
                         DFBColorAdjustment *adj )
{
     // FIXME
     return DFB_OK;
}

DisplayLayerFuncs matroxCrtc2Funcs = {
     LayerDataSize:      crtc2LayerDataSize,
     InitLayer:          crtc2InitLayer,
     Enable:             crtc2Enable,
     Disable:            crtc2Disable,
     TestConfiguration:  crtc2TestConfiguration,
     SetConfiguration:   crtc2SetConfiguration,
     FlipBuffers:        crtc2FlipBuffers,
     SetColorAdjustment: crtc2SetColorAdjustment
};

/* internal */

static void crtc2_set_regs( MatroxDriverData *mdrv, MatroxCrtc2LayerData *mcrtc2 )
{
     volatile __u8 *mmio = mdrv->mmio_base;

     mga_out32( mmio, mcrtc2->regs.c2PRELOAD, C2PRELOAD);

     mga_out32( mmio, mcrtc2->regs.c2HPARAM, C2HPARAM);
     mga_out32( mmio, mcrtc2->regs.c2VPARAM, C2VPARAM);

     mga_out32( mmio, mcrtc2->regs.c2MISC, C2MISC);

     mga_out32( mmio, mcrtc2->regs.c2DATACTL, C2DATACTL);
}

static void crtc2_calc_regs( MatroxDriverData *mdrv, MatroxCrtc2LayerData *mcrtc2,
                             DisplayLayer *layer )
{
     CoreSurface   *surface = dfb_layer_surface( layer );
     bool           ntsc    = dfb_config->matrox_ntsc;

     mcrtc2->regs.c2CTL = 0;
     /* c2pixcksel = 01 (vdoclk) */
     mcrtc2->regs.c2CTL |= (1 << 1);

     /* c2vidrstmod = 01 */
     mcrtc2->regs.c2CTL |= (1 << 28);
     /* c2hploaden = 1 */
     mcrtc2->regs.c2CTL |= (1 << 30);
     /* c2vploaden = 1 */
     mcrtc2->regs.c2CTL |= (1 << 31);

     mcrtc2->regs.c2DATACTL = 0;
     // FIXME enable or disable filters?
     /* c2dithen = 1 */
     mcrtc2->regs.c2DATACTL |= (1 << 0);
     /* c2yfiltend = 1 */
     mcrtc2->regs.c2DATACTL |= (1 << 1);
     /* c2cbcrfilten = 1 */
     mcrtc2->regs.c2DATACTL |= (1 << 2);
     /* c2ntscen */
     if (ntsc)
          mcrtc2->regs.c2DATACTL |= (1 << 4);

     /* pixel format settings */
     switch (surface->format) {
          case DSPF_I420:
          case DSPF_YV12:
               /* c2depth = 111 */
               mcrtc2->regs.c2CTL |= (7 << 21);
               break;

          case DSPF_UYVY:
               /* c2uyvyfmt = 1 */
               mcrtc2->regs.c2DATACTL |= (1 << 7);
               /* fall through */

          case DSPF_YUY2:
               /* c2depth = 101 */
               mcrtc2->regs.c2CTL |= (5 << 21);
               break;

          case DSPF_RGB15:
               /* c2depth = 001 */
               mcrtc2->regs.c2CTL |= (1 << 21);
               break;

          case DSPF_RGB16:
               /* c2depth = 010 */
               mcrtc2->regs.c2CTL |= (2 << 21);
               break;

          case DSPF_RGB32:
          case DSPF_ARGB:
               /* c2depth = 100 */
               mcrtc2->regs.c2CTL |= (4 << 21);
               break;

          default:
               BUG( "unexpected pixelformat" );
               return;
     }

     {
          int hdisplay, htotal, vdisplay, vtotal;

          if (ntsc) {
               hdisplay = 720;
               htotal = 858;
               vdisplay = 486 / 2;
               vtotal = 525 / 2;
          } else {
               hdisplay = 720;
               htotal = 864;
               vdisplay = 576 / 2;
               vtotal = 625 / 2;
          }

          mcrtc2->regs.c2HPARAM = ((hdisplay - 8) << 16) | (htotal - 8);
          mcrtc2->regs.c2VPARAM = ((vdisplay - 1) << 16) | (vtotal - 1);

          mcrtc2->regs.c2PRELOAD = ((vtotal - 1) << 16) | (htotal - 8);

          mcrtc2->regs.c2MISC = 0;
          /* c2fieldline0 */
          mcrtc2->regs.c2MISC |= ((ntsc ? 2 : 1) << 0);
          /* c2fieldline1 */
          mcrtc2->regs.c2MISC |= (1 << 4);
          /* c2vlinecomp */
          mcrtc2->regs.c2MISC |= (vdisplay << 16);
     }
}

static void crtc2_set_buffer( MatroxDriverData *mdrv, MatroxCrtc2LayerData *mcrtc2,
                              DisplayLayer *layer )
{
     CoreSurface   *surface      = dfb_layer_surface( layer );
     SurfaceBuffer *front_buffer = surface->front_buffer;
     volatile __u8 *mmio         = mdrv->mmio_base;

     /* interleaved fields */
     mcrtc2->regs.c2OFFSET = front_buffer->video.pitch * 2;

     mcrtc2->regs.c2STARTADD0 = front_buffer->video.offset;
     mcrtc2->regs.c2STARTADD1 = front_buffer->video.offset + front_buffer->video.pitch;

     switch (surface->format) {
          case DSPF_I420:
               mcrtc2->regs.c2PL2STARTADD0 = mcrtc2->regs.c2STARTADD0 + 
surface->height *
                    front_buffer->video.pitch;
               mcrtc2->regs.c2PL3STARTADD0 = mcrtc2->regs.c2PL2STARTADD0 + 
surface->height/2 *
                    front_buffer->video.pitch/2;
               mcrtc2->regs.c2PL2STARTADD1 = mcrtc2->regs.c2PL2STARTADD0 +
                    front_buffer->video.pitch/2;
               mcrtc2->regs.c2PL3STARTADD1 = mcrtc2->regs.c2PL3STARTADD0 +
                    front_buffer->video.pitch/2;
               break;
          case DSPF_YV12:
               mcrtc2->regs.c2PL3STARTADD0 = mcrtc2->regs.c2STARTADD0 + 
surface->height *
                    front_buffer->video.pitch;
               mcrtc2->regs.c2PL2STARTADD0 = mcrtc2->regs.c2PL3STARTADD0 + 
surface->height/2 *
                    front_buffer->video.pitch/2;
               mcrtc2->regs.c2PL3STARTADD1 = mcrtc2->regs.c2PL3STARTADD0 +
                    front_buffer->video.pitch/2;
               mcrtc2->regs.c2PL2STARTADD1 = mcrtc2->regs.c2PL2STARTADD0 +
                    front_buffer->video.pitch/2;
               break;
          default:
               break;
     }

     mga_out32( mmio, mcrtc2->regs.c2OFFSET, C2OFFSET );
     mga_out32( mmio, mcrtc2->regs.c2STARTADD0, C2STARTADD0 );
     mga_out32( mmio, mcrtc2->regs.c2STARTADD1, C2STARTADD1 );
     mga_out32( mmio, mcrtc2->regs.c2PL2STARTADD0, C2PL2STARTADD0 );
     mga_out32( mmio, mcrtc2->regs.c2PL2STARTADD1, C2PL2STARTADD1 );
     mga_out32( mmio, mcrtc2->regs.c2PL3STARTADD0, C2PL3STARTADD0 );
     mga_out32( mmio, mcrtc2->regs.c2PL3STARTADD1, C2PL3STARTADD1 );
}
/*
   (c) 1998-2001 Petr Vandrovec <[EMAIL PROTECTED]>

   This code originally comes from matroxfb.
   Relicensed under the LGPL with the authors permission.
   Adapted for CRTC2 ITU-R 656 mode by Ville Syrjala <[EMAIL PROTECTED]>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, write to the
   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.
*/

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
#include "matrox_maven.h"

#define MAVEN_I2CID     (0x1B)

static int maven_get_reg( int fd, char reg )
{
     char dst;
     struct i2c_msg msgs[] = {{ MAVEN_I2CID, I2C_M_REV_DIR_ADDR, sizeof(reg), &reg },
                              { MAVEN_I2CID, I2C_M_RD | I2C_M_NOSTART, sizeof(dst), 
&dst }};
     struct i2c_rdwr_ioctl_data data;
     __s32 err;

     data.msgs = msgs;
     data.nmsgs = 2;
     err = ioctl( fd, I2C_RDWR, &data );
     if (err < 0)
          fprintf( stderr, "maven_get_reg(%d) failed\n", reg );
     return dst & 0xFF;
}

static int maven_set_reg( int fd, __u8 reg, __u8 val )
{
     __s32 err;

     err = i2c_smbus_write_byte_data( fd, reg, val );
     if (err)
          fprintf( stderr, "maven_set_reg(%d) failed\n", reg );
     return err;
}

static int maven_set_reg_pair( int fd, __u8 reg, __u16 val )
{
     __s32 err;

     err = i2c_smbus_write_word_data( fd, reg, val );
     if (err)
          fprintf( stderr, "maven_set_reg_pair(%d) failed\n", reg );
     return err;
}

static void maven_init_TVdata( const struct maven_data* md,
                               struct mavenregs* data )
{
     static struct mavenregs palregs = { {
          0x2A, 0x09, 0x8A, 0xCB,       /* 00: chroma subcarrier */
          0x00,
          0x00, /* ? not written */
          0x09, /* 06 */
          0x00, /* ? not written */
          0x7E, /* 08 */
          0x3C, /* 09 */
          0x82, /* 0A */
          0x2E, /* 0B */
          0x21, /* 0C */
          0x00, /* ? not written */
          0x3F, 0x03, /* 0E-0F */
          0x3F, 0x03, /* 10-11 */
          0x1A, /* 12 */
          0x2A, /* 13 */
          0x1C, 0x3D, 0x14, /* 14-16 */
          0x9C, 0x01, /* 17-18 */
          0x00, /* 19 */
          0xFE, /* 1A */
          0x7E, /* 1B */
          0x60, /* 1C */
          0x05, /* 1D */
          0xC4, 0x01, /* 1E-1F */
          0x95, /* 20 */
          0x07, /* 21 */
          0x95, /* 22 */
          0x00, /* 23 */
          0x00, /* 24 */
          0x00, /* 25 */
          0x08, /* 26 */
          0x04, /* 27 */
          0x00, /* 28 */
          0x1A, /* 29 */
          0x55, 0x01, /* 2A-2B */
          0x20, /* 2C */
          0x07, 0x7E, /* 2D-2E */
          0x02, 0x54, /* 2F-30 */
          0xB4, 0x00, /* 31-32 */
          0x14, /* 33 */
          0x49, /* 34 */
          0x1D, /* 35 written multiple times */
          0x00, /* 36 not written */
          0xA3, /* 37 */
          0xC8, /* 38 */
          0x22, /* 39 */
          0x02, /* 3A */
          0x22, /* 3B */
          0x3F, 0x03, /* 3C-3D */
          0x00, /* 3E written multiple times */
          0x20, /* 3F not written */
     }, MODE_PAL };
     static struct mavenregs ntscregs = { {
          0x21, 0xF0, 0x7C, 0x1F,       /* 00: chroma subcarrier */
          0x00,
          0x00, /* ? not written */
          0x09, /* modified by code (F9 written...) */
          0x00, /* ? not written */
          0x7E, /* 08 */
          0x43, /* 09 */
          0x7E, /* 0A */
          0x3D, /* 0B */
          0x00, /* 0C */
          0x00, /* ? not written */
          0x46, 0x03, /* 0E-0F */
          0x3C, 0x02, /* 10-11 */
          0x17, /* 12 */
          0x21, /* 13 */
          0x1B, 0x1B, 0x24, /* 14-16 */
          0x83, 0x01, /* 17-18 */
          0x00, /* 19 */
          0x0F, /* 1A */
          0x0F, /* 1B */
          0x60, /* 1C */
          0x05, /* 1D */
          0xC4, 0x02, /* 1E-1F */
          0x8E, /* 20 */
          0x04, /* 21 */
          0x8E, /* 22 */
          0x01, /* 23 */
          0x02, /* 24 */
          0x00, /* 25 */
          0x0A, /* 26 */
          0x05, /* 27 */
          0x00, /* 28 */
          0x10, /* 29 */
          0xFF, 0x03, /* 2A-2B */
          0x18, /* 2C */
          0x0F, 0x78, /* 2D-2E */
          0x00, 0x00, /* 2F-30 */
          0xB4, 0x00, /* 31-32 */
          0x14, /* 33 */
          0x02, /* 34 */
          0x1C, /* 35 written multiple times */
          0x00, /* 36 not written */
          0xA3, /* 37 */
          0xC8, /* 38 */
          0x15, /* 39 */
          0x05, /* 3A */
          0x15, /* 3B */
          0x3C, 0x00, /* 3C-3D */
          0x00, /* 3E written multiple times */
          0x20, /* never written */
     }, MODE_NTSC };

     if (md->mode & MODE_PAL)
          *data = palregs;
     else
          *data = ntscregs;

     /* gamma correction registers */
     data->regs[0x83] = 0x00;
     data->regs[0x84] = 0x00;
     data->regs[0x85] = 0x00;
     data->regs[0x86] = 0x1F;
     data->regs[0x87] = 0x10;
     data->regs[0x88] = 0x10;
     data->regs[0x89] = 0x10;
     data->regs[0x8A] = 0x64;   /* 100 */
     data->regs[0x8B] = 0xC8;   /* 200 */

}

#define LR(x) maven_set_reg(fd, (x), m->regs[(x)])
#define LRP(x) maven_set_reg_pair(fd, (x), m->regs[(x)] | (m->regs[(x)+1] << 8))

static void maven_init_TV( int fd, const struct mavenregs* m )
{
     maven_set_reg(fd, 0x3E, 0x01);
     maven_get_reg(fd, 0x82);   /* fetch oscillator state? */
     maven_set_reg(fd, 0x8C, 0x00);
     maven_get_reg(fd, 0x94);   /* get 0x82 */
     maven_set_reg(fd, 0x94, 0xA2);
     /* xmiscctrl */

     maven_set_reg_pair(fd, 0x8E, 0x1EFF);
     maven_set_reg(fd, 0xC6, 0x00);

     /* removed code... */

     maven_get_reg(fd, 0x06);
     maven_set_reg(fd, 0x06, 0x09);     /* or read |= 0xF0 ? */

     /* removed code here... */

     /* real code begins here? */
     /* chroma subcarrier */
     LR(0x00); LR(0x01); LR(0x02); LR(0x03);

     LR(0x04);

     LR(0x2C);
     LR(0x08);
     LR(0x0A);
     LR(0x09);
     LR(0x29);
     LRP(0x31);
     LRP(0x17);
     LR(0x0B);
     LR(0x0C);
     if (m->mode & MODE_PAL)
          maven_set_reg(fd, 0x35, 0x10); /* ... */
     else
          maven_set_reg(fd, 0x35, 0x0F); /* ... */

     LRP(0x10);

     LRP(0x0E);
     LRP(0x1E);

     LR(0x20);  /* saturation #1 */
     LR(0x22);  /* saturation #2 */
     LR(0x25);  /* hue */
     LR(0x34);
     LR(0x33);
     LR(0x19);
     LR(0x12);
     LR(0x3B);
     LR(0x13);
     LR(0x39);
     LR(0x1D);
     LR(0x3A);
     LR(0x24);
     LR(0x14);
     LR(0x15);
     LR(0x16);
     LRP(0x2D);
     LRP(0x2F);
     LR(0x1A);
     LR(0x1B);
     LR(0x1C);
     LR(0x23);
     LR(0x26);
     LR(0x28);
     LR(0x27);
     LR(0x21);
     LRP(0x2A);
     if (m->mode & MODE_PAL)
          maven_set_reg(fd, 0x35, 0x1D);        /* ... */
     else
          maven_set_reg(fd, 0x35, 0x1C);

     LRP(0x3C);
     LR(0x37);
     LR(0x38);
     maven_set_reg(fd, 0xB3, 0x01);

     maven_get_reg(fd, 0xB0);   /* read 0x80 */
     maven_set_reg(fd, 0xB0, 0x80);     /* ugh... */
     maven_get_reg(fd, 0xB9);   /* read 0x7C */
     maven_set_reg(fd, 0xB9, 0x78);
     maven_get_reg(fd, 0xBF);   /* read 0x00 */
     maven_set_reg(fd, 0xBF, 0x02);
     maven_get_reg(fd, 0x94);   /* read 0x82 */
     maven_set_reg(fd, 0x94, 0xA2);

     LR(0x80); /* 04 1A 91 or 05 21 91 */
     LR(0x81);
     LR(0x82);

     maven_set_reg(fd, 0x8C, 0x00);
     maven_get_reg(fd, 0x8D);
     maven_set_reg(fd, 0x8D, 0x03);

     LR(0x90); /* 4D 50 52 or 4E 05 45 */
     LR(0x91);
     LR(0x92);

     LR(0xBE);
     LR(0xC2);

     maven_get_reg(fd, 0x8D);
     maven_set_reg(fd, 0x8D, 0x03);

     LR(0x20);  /* saturation #1 */
     LR(0x22);  /* saturation #2 */
     LR(0x93);  /* whoops */
     LR(0x20);  /* oh, saturation #1 again */
     LR(0x22);  /* oh, saturation #2 again */
     LR(0x25);  /* hue */
     LRP(0x0E);
     LRP(0x1E);
     LRP(0x0E); /* problems with memory? */
     LRP(0x1E); /* yes, matrox must have problems in memory area... */

     /* load gamma correction stuff */
     LR(0x83);
     LR(0x84);
     LR(0x85);
     LR(0x86);
     LR(0x87);
     LR(0x88);
     LR(0x89);
     LR(0x8A);
     LR(0x8B);

     LR(0x33);
     LR(0x19);
     LR(0x12);
     LR(0x3B);
     LR(0x13);
     LR(0x39);
     LR(0x1D);
     LR(0x3A);
     LR(0x24);
     LR(0x14);
     LR(0x15);
     LR(0x16);
     LRP(0x2D);
     LRP(0x2F);
     LR(0x1A);
     LR(0x1B);
     LR(0x1C);
     LR(0x23);
     LR(0x26);
     LR(0x28);
     LR(0x27);
     LR(0x21);
     LRP(0x2A);
     if (m->mode & MODE_PAL)
          maven_set_reg(fd, 0x35, 0x1D);
     else
          maven_set_reg(fd, 0x35, 0x1C);
     LRP(0x3C);
     LR(0x37);
     LR(0x38);

     maven_get_reg(fd, 0xB0);
     LR(0xB0);  /* output mode */
     LR(0x90);
     LR(0xBE);
     LR(0xC2);

     maven_set_reg(fd, 0x3E, 0x00);
}


/* external */
void maven_set_mode( struct maven_data *md,
                     int mode )
{
     md->mode = mode;
}

void maven_compute( struct maven_data *md,
                    struct mavenregs* m )
{
     maven_init_TVdata(md, m);

     /* horizontal decimator 0x80 = 1:1 0x40 2:1 */
     m->regs[0x90] = 122;       /* < 0x40 || > 0x80 is bad... 0x80 is questionable */

     /* Vertical Decimator ((OutLines * Htotal * 32768)/Vtotal) */
     m->regs[0x91] = 69;
     m->regs[0x92] = 127;

     /* Antialiasing mode */
     m->regs[0x93] = 0x00;

     /* TV mode B3, Monitor mode B2 */
     m->regs[0x94] = 0xA2;

     m->regs[0xBE] = 46;
     m->regs[0xB0] = 0x80;
     m->regs[0xC2] = 0;

     m->regs[0x80] = 0x03;
     m->regs[0x81] = 0x03;
     m->regs[0x82] = 0x20;
}

void maven_program( struct maven_data* md,
                    const struct mavenregs* m ) {
     maven_init_TV( md->fd, m );
}

int maven_open( struct maven_data *md )
{
     char dev[16] = "/dev/";
     char line[256];
     FILE *file;
     int fd;

     /* Locate maven /dev/i2c entry */
     file = fopen( "/proc/bus/i2c", "r" );
     if (!file)
          return -1;
     while (fgets( line, 256, file )) {
          if (strstr( line, "MAVEN" )) {
               strtok( line, " \t\n" );
               strncat( dev, line, 10 );
               break;
          }
     }
     fclose( file );

     if ((fd = open( dev, O_RDWR )) < 0) {
          return -1;
     }

     if (ioctl( fd, I2C_SLAVE, MAVEN_I2CID ) < 0) {
          close(fd);
          return -1;
     }

     md->fd = fd;
     md->mode = MODE_PAL;

     return 0;
}

void maven_close( struct maven_data *md )
{
     close( md->fd );
}
/*
   (c) 1998-2001 Petr Vandrovec <[EMAIL PROTECTED]>

   This code originally comes from matroxfb.
   Relicensed under the LGPL with the authors permission.
   Adapted for CRTC2 ITU-R 656 mode by Ville Syrjala <[EMAIL PROTECTED]>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, write to the
   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.
*/

#ifndef __MATROX_MAVEN_H__
#define __MATROX_MAVEN_H__

#define MODE_PAL        1
#define MODE_NTSC       2

struct maven_data {
     int        fd;
     int        mode;
};

struct mavenregs {
     __u8       regs[256];
     int        mode;
};

int maven_open( struct maven_data *md );
void maven_close( struct maven_data *md );

void maven_set_mode( struct maven_data* md,
                     int mode );

void maven_compute( struct maven_data* md,
                    struct mavenregs* m );
void maven_program( struct maven_data* md,
                    const struct mavenregs* m );

#endif

Reply via email to