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), ® },
{ 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