summaryrefslogtreecommitdiff
path: root/Source/DirectFB/gfxdrivers/matrox/matrox_crtc2.c
diff options
context:
space:
mode:
Diffstat (limited to 'Source/DirectFB/gfxdrivers/matrox/matrox_crtc2.c')
-rwxr-xr-xSource/DirectFB/gfxdrivers/matrox/matrox_crtc2.c751
1 files changed, 751 insertions, 0 deletions
diff --git a/Source/DirectFB/gfxdrivers/matrox/matrox_crtc2.c b/Source/DirectFB/gfxdrivers/matrox/matrox_crtc2.c
new file mode 100755
index 0000000..36c83a3
--- /dev/null
+++ b/Source/DirectFB/gfxdrivers/matrox/matrox_crtc2.c
@@ -0,0 +1,751 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <config.h>
+
+#include <stdio.h>
+
+#include <directfb.h>
+
+#include <direct/messages.h>
+
+#include <core/coredefs.h>
+#include <core/coretypes.h>
+#include <core/layers.h>
+#include <core/screen.h>
+#include <core/surface.h>
+
+#include <misc/conf.h>
+
+#include "regs.h"
+#include "mmio.h"
+#include "matrox.h"
+#include "matrox_maven.h"
+
+typedef struct {
+ CoreLayerRegionConfig config;
+ DFBColorAdjustment adj;
+ int field;
+
+ /* Stored registers */
+ struct {
+ /* CRTC2 */
+ u32 c2CTL;
+ u32 c2DATACTL;
+ u32 c2MISC;
+ u32 c2OFFSET;
+
+ u32 c2HPARAM;
+ u32 c2VPARAM;
+
+ u32 c2STARTADD0;
+ u32 c2STARTADD1;
+ u32 c2PL2STARTADD0;
+ u32 c2PL2STARTADD1;
+ u32 c2PL3STARTADD0;
+ u32 c2PL3STARTADD1;
+ } regs;
+
+ MatroxMavenData mav;
+} MatroxCrtc2LayerData;
+
+static void crtc2_set_regs ( MatroxDriverData *mdrv,
+ MatroxCrtc2LayerData *mcrtc2 );
+
+static void crtc2_calc_regs ( MatroxDriverData *mdrv,
+ MatroxCrtc2LayerData *mcrtc2,
+ CoreLayerRegionConfig *config,
+ CoreSurface *surface,
+ CoreSurfaceBufferLock *lock );
+
+static void crtc2_calc_buffer ( MatroxDriverData *mdrv,
+ MatroxCrtc2LayerData *mcrtc2,
+ CoreSurface *surface,
+ CoreSurfaceBufferLock *lock );
+
+static void crtc2_set_buffer ( MatroxDriverData *mdrv,
+ MatroxCrtc2LayerData *mcrtc2 );
+
+static DFBResult crtc2_disable_output( MatroxDriverData *mdrv,
+ MatroxCrtc2LayerData *mcrtc2 );
+
+static DFBResult crtc2_enable_output ( MatroxDriverData *mdrv,
+ MatroxCrtc2LayerData *mcrtc2 );
+
+#define CRTC2_SUPPORTED_OPTIONS (DLOP_FIELD_PARITY)
+
+/**********************/
+
+static int
+crtc2LayerDataSize( void )
+{
+ return sizeof(MatroxCrtc2LayerData);
+}
+
+static const DFBColorAdjustment adjustments[2][2] = {
+ /* G400 */
+ {
+ /* PAL / PAL-60 */
+ {
+ .flags = DCAF_BRIGHTNESS | DCAF_CONTRAST | DCAF_HUE | DCAF_SATURATION,
+ .brightness = 0xA800,
+ .saturation = 0x9500,
+ .contrast = 0xFF00,
+ .hue = 0x0000,
+ },
+ /* NTSC */
+ {
+ .flags = DCAF_BRIGHTNESS | DCAF_CONTRAST | DCAF_HUE | DCAF_SATURATION,
+ .brightness = 0xB500,
+ .saturation = 0x8E00,
+ .contrast = 0xEA00,
+ .hue = 0x0000,
+ }
+ },
+ /* G450 / G550 */
+ {
+ /* PAL / PAL-60 */
+ {
+ .flags = DCAF_BRIGHTNESS | DCAF_CONTRAST | DCAF_HUE | DCAF_SATURATION,
+ .brightness = 0x9E00,
+ .saturation = 0xBB00,
+ .contrast = 0xFF00,
+ .hue = 0x0000,
+ },
+ /* NTSC */
+ {
+ .flags = DCAF_BRIGHTNESS | DCAF_CONTRAST | DCAF_HUE | DCAF_SATURATION,
+ .brightness = 0xAA00,
+ .saturation = 0xAE00,
+ .contrast = 0xEA00,
+ .hue = 0x0000,
+ }
+ }
+};
+
+static DFBResult
+crtc2InitLayer( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ DFBDisplayLayerDescription *description,
+ DFBDisplayLayerConfig *config,
+ DFBColorAdjustment *adjustment )
+{
+ MatroxDriverData *mdrv = (MatroxDriverData*) driver_data;
+ MatroxCrtc2LayerData *mcrtc2 = (MatroxCrtc2LayerData*) layer_data;
+ MatroxDeviceData *mdev = mdrv->device_data;
+ MatroxMavenData *mav = &mcrtc2->mav;
+ DFBResult res;
+
+ if ((res = maven_init( mav, mdrv )) != DFB_OK)
+ return res;
+
+ /* set capabilities and type */
+ description->caps = DLCAPS_SURFACE | DLCAPS_FIELD_PARITY |
+ DLCAPS_BRIGHTNESS | DLCAPS_CONTRAST |
+ DLCAPS_HUE | DLCAPS_SATURATION | DLCAPS_ALPHA_RAMP;
+ description->type = DLTF_GRAPHICS | DLTF_VIDEO | DLTF_STILL_PICTURE;
+
+ /* set name */
+ snprintf( description->name,
+ DFB_DISPLAY_LAYER_DESC_NAME_LENGTH, "Matrox CRTC2 Layer" );
+
+ /* fill out the default configuration */
+ config->flags = DLCONF_WIDTH | DLCONF_HEIGHT |
+ DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE |
+ DLCONF_OPTIONS | DLCONF_SURFACE_CAPS;
+ config->width = 720;
+ config->height = (dfb_config->matrox_tv_std != DSETV_PAL) ? 480 : 576;
+ config->pixelformat = DSPF_YUY2;
+ config->buffermode = DLBM_FRONTONLY;
+ config->options = DLOP_NONE;
+ config->surface_caps = DSCAPS_INTERLACED;
+
+ /* fill out default color adjustment,
+ only fields set in flags will be accepted from applications */
+ *adjustment = adjustments[mdev->g450_matrox][dfb_config->matrox_tv_std == DSETV_NTSC];
+
+ /* remember color adjustment */
+ mcrtc2->adj = *adjustment;
+
+ return DFB_OK;
+}
+
+static DFBResult
+crtc2TestRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ CoreLayerRegionConfig *config,
+ CoreLayerRegionConfigFlags *failed )
+{
+ CoreLayerRegionConfigFlags fail = 0;
+
+ if (config->options & ~CRTC2_SUPPORTED_OPTIONS)
+ fail |= CLRCF_OPTIONS;
+
+ if (config->surface_caps & ~(DSCAPS_INTERLACED | DSCAPS_SEPARATED))
+ fail |= CLRCF_SURFACE_CAPS;
+
+ switch (config->format) {
+ case DSPF_ARGB:
+ case DSPF_RGB32:
+ case DSPF_RGB555:
+ case DSPF_ARGB1555:
+ case DSPF_RGB16:
+ case DSPF_YUY2:
+ case DSPF_UYVY:
+ case DSPF_I420:
+ case DSPF_YV12:
+ break;
+ default:
+ fail |= CLRCF_FORMAT;
+ }
+
+ if (config->width != 720)
+ fail |= CLRCF_WIDTH;
+
+ if (config->height != ((dfb_config->matrox_tv_std != DSETV_PAL) ? 480 : 576))
+ fail |= CLRCF_HEIGHT;
+
+ if (failed)
+ *failed = fail;
+
+ if (fail)
+ return DFB_UNSUPPORTED;
+
+ return DFB_OK;
+}
+
+static DFBResult
+crtc2AddRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data,
+ CoreLayerRegionConfig *config )
+{
+ return DFB_OK;
+}
+
+static DFBResult
+crtc2SetRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data,
+ CoreLayerRegionConfig *config,
+ CoreLayerRegionConfigFlags updated,
+ CoreSurface *surface,
+ CorePalette *palette,
+ CoreSurfaceBufferLock *lock )
+{
+ DFBResult ret;
+ MatroxDriverData *mdrv = (MatroxDriverData*) driver_data;
+ MatroxCrtc2LayerData *mcrtc2 = (MatroxCrtc2LayerData*) layer_data;
+ MatroxDeviceData *mdev = mdrv->device_data;
+
+ /* remember configuration */
+ mcrtc2->config = *config;
+
+ if (updated & CLRCF_PARITY)
+ mcrtc2->field = !config->parity;
+
+ if (updated & (CLRCF_WIDTH | CLRCF_HEIGHT | CLRCF_FORMAT |
+ CLRCF_SURFACE_CAPS | CLRCF_ALPHA_RAMP | CLRCF_SURFACE)) {
+ crtc2_calc_regs( mdrv, mcrtc2, config, surface, lock );
+ crtc2_calc_buffer( mdrv, mcrtc2, surface, lock );
+
+ ret = crtc2_enable_output( mdrv, mcrtc2 );
+ if (ret)
+ return ret;
+
+ mdev->crtc2_separated = !!(surface->config.caps & DSCAPS_SEPARATED);
+ }
+
+ return DFB_OK;
+}
+
+static DFBResult
+crtc2RemoveRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data )
+{
+ MatroxDriverData *mdrv = (MatroxDriverData*) driver_data;
+ MatroxCrtc2LayerData *mcrtc2 = (MatroxCrtc2LayerData*) layer_data;
+
+ crtc2_disable_output( mdrv, mcrtc2 );
+
+ return DFB_OK;
+}
+
+static DFBResult
+crtc2FlipRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data,
+ CoreSurface *surface,
+ DFBSurfaceFlipFlags flags,
+ CoreSurfaceBufferLock *lock )
+{
+ MatroxDriverData *mdrv = (MatroxDriverData*) driver_data;
+ MatroxCrtc2LayerData *mcrtc2 = (MatroxCrtc2LayerData*) layer_data;
+ volatile u8 *mmio = mdrv->mmio_base;
+
+ crtc2_calc_buffer( mdrv, mcrtc2, surface, lock );
+
+ if (mcrtc2->config.options & DLOP_FIELD_PARITY) {
+ int field = (mga_in32( mmio, C2VCOUNT ) & C2FIELD) ? 1 : 0;
+
+ while (field == mcrtc2->field) {
+ dfb_screen_wait_vsync( mdrv->secondary );
+
+ field = (mga_in32( mmio, C2VCOUNT ) & C2FIELD) ? 1 : 0;
+ }
+ }
+ crtc2_set_buffer( mdrv, mcrtc2 );
+
+ dfb_surface_flip( surface, false );
+
+ if (flags & DSFLIP_WAIT)
+ dfb_screen_wait_vsync( mdrv->secondary );
+
+ return DFB_OK;
+}
+
+static DFBResult
+crtc2SetColorAdjustment( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ DFBColorAdjustment *adj )
+{
+ MatroxDriverData *mdrv = (MatroxDriverData*) driver_data;
+ MatroxCrtc2LayerData *mcrtc2 = (MatroxCrtc2LayerData*) layer_data;
+ MatroxMavenData *mav = &mcrtc2->mav;
+ DFBResult res;
+
+ if ((res = maven_open( mav, mdrv )) != DFB_OK)
+ return res;
+
+ if (adj->flags & DCAF_HUE)
+ maven_set_hue( mav, mdrv,
+ adj->hue >> 8 );
+ if (adj->flags & DCAF_SATURATION)
+ maven_set_saturation( mav, mdrv,
+ adj->saturation >> 8 );
+ if (adj->flags & DCAF_BRIGHTNESS ||
+ adj->flags & DCAF_CONTRAST)
+ maven_set_bwlevel( mav, mdrv,
+ adj->brightness >> 8,
+ adj->contrast >> 8 );
+
+ maven_close( mav, mdrv );
+
+ /* remember color adjustment */
+ mcrtc2->adj = *adj;
+
+ return DFB_OK;
+}
+
+static DFBResult
+crtc2GetCurrentOutputField( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ int *field )
+{
+ MatroxDriverData *mdrv = (MatroxDriverData*) driver_data;
+
+ if (!field)
+ return DFB_INVARG;
+
+ *field = (mga_in32( mdrv->mmio_base, C2VCOUNT ) & C2FIELD) ? 1 : 0;
+
+ return DFB_OK;
+}
+
+DisplayLayerFuncs matroxCrtc2Funcs = {
+ .LayerDataSize = crtc2LayerDataSize,
+ .InitLayer = crtc2InitLayer,
+
+ .TestRegion = crtc2TestRegion,
+ .AddRegion = crtc2AddRegion,
+ .SetRegion = crtc2SetRegion,
+ .RemoveRegion = crtc2RemoveRegion,
+ .FlipRegion = crtc2FlipRegion,
+
+ .SetColorAdjustment = crtc2SetColorAdjustment,
+ .GetCurrentOutputField = crtc2GetCurrentOutputField,
+};
+
+/* internal */
+
+static void crtc2_set_regs( MatroxDriverData *mdrv,
+ MatroxCrtc2LayerData *mcrtc2 )
+{
+ volatile u8 *mmio = mdrv->mmio_base;
+
+ mga_out32( mmio, mcrtc2->regs.c2CTL, C2CTL );
+ mga_out32( mmio, mcrtc2->regs.c2DATACTL, C2DATACTL );
+ mga_out32( mmio, mcrtc2->regs.c2HPARAM, C2HPARAM );
+ mga_out32( mmio, 0, C2HSYNC );
+ mga_out32( mmio, mcrtc2->regs.c2VPARAM, C2VPARAM );
+ mga_out32( mmio, 0, C2VSYNC );
+ mga_out32( mmio, mcrtc2->regs.c2OFFSET, C2OFFSET );
+ mga_out32( mmio, mcrtc2->regs.c2MISC, C2MISC );
+ mga_out32( mmio, 0, C2PRELOAD );
+}
+
+static void crtc2_calc_regs( MatroxDriverData *mdrv,
+ MatroxCrtc2LayerData *mcrtc2,
+ CoreLayerRegionConfig *config,
+ CoreSurface *surface,
+ CoreSurfaceBufferLock *lock )
+{
+ MatroxDeviceData *mdev = mdrv->device_data;
+
+ mcrtc2->regs.c2CTL = 0;
+
+ /* Don't touch sub-picture bits. */
+ mcrtc2->regs.c2DATACTL = mga_in32( mdrv->mmio_base, C2DATACTL );
+ mcrtc2->regs.c2DATACTL &= C2STATICKEY | C2OFFSETDIVEN | C2STATICKEYEN | C2SUBPICEN;
+
+ if (mdev->g450_matrox)
+ mcrtc2->regs.c2CTL |= C2PIXCLKSEL_CRISTAL;
+ else
+ mcrtc2->regs.c2CTL |= C2PIXCLKSEL_VDOCLK;
+
+ /*
+ * High priority request level.
+ * According to G400 specs these values should
+ * be fixed when CRTC2 is in YUV mode.
+ */
+ /* c2hiprilvl */
+ mcrtc2->regs.c2CTL |= 2 << 4;
+ /* c2maxhipri */
+ mcrtc2->regs.c2CTL |= 1 << 8;
+
+ switch (surface->config.format) {
+ case DSPF_RGB555:
+ case DSPF_ARGB1555:
+ case DSPF_RGB16:
+ case DSPF_RGB32:
+ case DSPF_ARGB:
+ mcrtc2->regs.c2DATACTL |= C2DITHEN | C2YFILTEN | C2CBCRFILTEN;
+ break;
+ default:
+ break;
+ }
+
+ if (dfb_config->matrox_tv_std != DSETV_PAL)
+ mcrtc2->regs.c2DATACTL |= C2NTSCEN;
+
+ /* pixel format settings */
+ switch (surface->config.format) {
+ case DSPF_I420:
+ case DSPF_YV12:
+ mcrtc2->regs.c2CTL |= C2DEPTH_YCBCR420;
+ break;
+
+ case DSPF_UYVY:
+ mcrtc2->regs.c2DATACTL |= C2UYVYFMT;
+ /* fall through */
+
+ case DSPF_YUY2:
+ mcrtc2->regs.c2CTL |= C2DEPTH_YCBCR422;
+ break;
+
+ case DSPF_RGB555:
+ case DSPF_ARGB1555:
+ mcrtc2->regs.c2CTL |= C2DEPTH_15BPP;
+ break;
+
+ case DSPF_RGB16:
+ mcrtc2->regs.c2CTL |= C2DEPTH_16BPP;
+ break;
+
+ case DSPF_RGB32:
+ case DSPF_ARGB:
+ mcrtc2->regs.c2CTL |= C2DEPTH_32BPP;
+ break;
+
+ default:
+ D_BUG( "unexpected pixelformat" );
+ return;
+ }
+
+ if (!(surface->config.caps & DSCAPS_INTERLACED))
+ mcrtc2->regs.c2CTL |= C2VCBCRSINGLE;
+
+ mcrtc2->regs.c2OFFSET = lock->pitch;
+ if (!(surface->config.caps & DSCAPS_SEPARATED))
+ mcrtc2->regs.c2OFFSET *= 2;
+
+ {
+ int hdisplay, htotal, vdisplay, vtotal;
+
+ if (dfb_config->matrox_tv_std != DSETV_PAL) {
+ hdisplay = 720;
+ htotal = 858;
+ vdisplay = 480 / 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.c2MISC = 0;
+ /* c2vlinecomp */
+ mcrtc2->regs.c2MISC |= (vdisplay + 1) << 16;
+ }
+
+ /* c2bpp15halpha */
+ mcrtc2->regs.c2DATACTL |= config->alpha_ramp[3] << 8;
+
+ /* c2bpp15lalpha */
+ mcrtc2->regs.c2DATACTL |= config->alpha_ramp[0] << 16;
+}
+
+static void crtc2_calc_buffer( MatroxDriverData *mdrv,
+ MatroxCrtc2LayerData *mcrtc2,
+ CoreSurface *surface,
+ CoreSurfaceBufferLock *lock )
+{
+ unsigned int field_offset = lock->pitch;
+
+ if (surface->config.caps & DSCAPS_SEPARATED)
+ field_offset *= surface->config.size.h / 2;
+
+ mcrtc2->regs.c2STARTADD1 = lock->offset;
+ mcrtc2->regs.c2STARTADD0 = mcrtc2->regs.c2STARTADD1 + field_offset;
+
+ if (surface->config.caps & DSCAPS_INTERLACED)
+ field_offset = lock->pitch / 2;
+ else
+ field_offset = 0;
+
+ if (surface->config.caps & DSCAPS_SEPARATED)
+ field_offset *= surface->config.size.h / 4;
+
+ switch (surface->config.format) {
+ case DSPF_I420:
+ mcrtc2->regs.c2PL2STARTADD1 = mcrtc2->regs.c2STARTADD1 + surface->config.size.h * lock->pitch;
+ mcrtc2->regs.c2PL2STARTADD0 = mcrtc2->regs.c2PL2STARTADD1 + field_offset;
+
+ mcrtc2->regs.c2PL3STARTADD1 = mcrtc2->regs.c2PL2STARTADD1 + surface->config.size.h/2 * lock->pitch/2;
+ mcrtc2->regs.c2PL3STARTADD0 = mcrtc2->regs.c2PL3STARTADD1 + field_offset;
+ break;
+ case DSPF_YV12:
+ mcrtc2->regs.c2PL3STARTADD1 = mcrtc2->regs.c2STARTADD1 + surface->config.size.h * lock->pitch;
+ mcrtc2->regs.c2PL3STARTADD0 = mcrtc2->regs.c2PL3STARTADD1 + field_offset;
+
+ mcrtc2->regs.c2PL2STARTADD1 = mcrtc2->regs.c2PL3STARTADD1 + surface->config.size.h/2 * lock->pitch/2;
+ mcrtc2->regs.c2PL2STARTADD0 = mcrtc2->regs.c2PL2STARTADD1 + field_offset;
+ break;
+ default:
+ break;
+ }
+}
+
+static void crtc2_set_buffer( MatroxDriverData *mdrv,
+ MatroxCrtc2LayerData *mcrtc2 )
+{
+ volatile u8 *mmio = mdrv->mmio_base;
+
+ 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 );
+}
+
+static void
+crtc2OnOff( MatroxDriverData *mdrv,
+ MatroxCrtc2LayerData *mcrtc2,
+ int on )
+{
+ volatile u8 *mmio = mdrv->mmio_base;
+
+ if (on)
+ mcrtc2->regs.c2CTL |= C2EN;
+ else
+ mcrtc2->regs.c2CTL &= ~C2EN;
+ mga_out32( mmio, mcrtc2->regs.c2CTL, C2CTL );
+
+ if (on)
+ mcrtc2->regs.c2CTL &= ~C2PIXCLKDIS;
+ else
+ mcrtc2->regs.c2CTL |= C2PIXCLKDIS;
+ mga_out32( mmio, mcrtc2->regs.c2CTL, C2CTL );
+
+ if (!on) {
+ mcrtc2->regs.c2CTL &= ~C2INTERLACE;
+ mga_out32( mmio, mcrtc2->regs.c2CTL, C2CTL );
+ }
+}
+
+static void crtc2_set_mafc( MatroxDriverData *mdrv,
+ int on )
+{
+ volatile u8 *mmio = mdrv->mmio_base;
+ u8 val;
+
+ val = mga_in_dac( mmio, XMISCCTRL );
+ if (on) {
+ val &= ~(MFCSEL_MASK | VDOUTSEL_MASK);
+ val |= MFCSEL_MAFC | VDOUTSEL_CRTC2656;
+ } else {
+ val &= ~MFCSEL_MASK;
+ val |= MFCSEL_DIS;
+ }
+ mga_out_dac( mmio, XMISCCTRL, val );
+}
+
+static DFBResult
+crtc2_disable_output( MatroxDriverData *mdrv,
+ MatroxCrtc2LayerData *mcrtc2 )
+{
+ MatroxDeviceData *mdev = mdrv->device_data;
+ MatroxMavenData *mav = &mcrtc2->mav;
+ DFBResult res;
+
+ if ((res = maven_open( mav, mdrv )) != DFB_OK)
+ return res;
+
+ maven_disable( mav, mdrv );
+ if (!mdev->g450_matrox)
+ crtc2_set_mafc( mdrv, 0 );
+ crtc2OnOff( mdrv, mcrtc2, 0 );
+
+ maven_close( mav, mdrv );
+
+ if (mdev->g450_matrox) {
+ volatile u8 *mmio = mdrv->mmio_base;
+ u8 val;
+
+ /* Set Rset to 0.7 V */
+ val = mga_in_dac( mmio, XGENIOCTRL );
+ val &= ~0x40;
+ mga_out_dac( mmio, XGENIOCTRL, val );
+ val = mga_in_dac( mmio, XGENIODATA );
+ val &= ~0x40;
+ mga_out_dac( mmio, XGENIODATA, val );
+
+ val = mga_in_dac( mmio, XPWRCTRL );
+ val &= ~(DAC2PDN | CFIFOPDN);
+ mga_out_dac( mmio, XPWRCTRL, val );
+
+ val = mga_in_dac( mmio, XDISPCTRL );
+ val &= ~DAC2OUTSEL_MASK;
+ val |= DAC2OUTSEL_DIS;
+ mga_out_dac( mmio, XDISPCTRL, val );
+ }
+
+ return DFB_OK;
+}
+
+static DFBResult
+crtc2_enable_output( MatroxDriverData *mdrv,
+ MatroxCrtc2LayerData *mcrtc2 )
+{
+ MatroxDeviceData *mdev = mdrv->device_data;
+ MatroxMavenData *mav = &mcrtc2->mav;
+ volatile u8 *mmio = mdrv->mmio_base;
+ DFBResult res;
+
+ if ((res = maven_open( mav, mdrv )) != DFB_OK)
+ return res;
+
+ if (mdev->g450_matrox) {
+ volatile u8 *mmio = mdrv->mmio_base;
+ u8 val;
+
+ /* Set Rset to 1.0 V */
+ val = mga_in_dac( mmio, XGENIOCTRL );
+ val |= 0x40;
+ mga_out_dac( mmio, XGENIOCTRL, val );
+ val = mga_in_dac( mmio, XGENIODATA );
+ val &= ~0x40;
+ mga_out_dac( mmio, XGENIODATA, val );
+
+ val = mga_in_dac( mmio, XPWRCTRL );
+ val |= DAC2PDN | CFIFOPDN;
+ mga_out_dac( mmio, XPWRCTRL, val );
+
+ val = mga_in_dac( mmio, XDISPCTRL );
+ val &= ~DAC2OUTSEL_MASK;
+ val |= DAC2OUTSEL_TVE;
+ mga_out_dac( mmio, XDISPCTRL, val );
+
+ if (dfb_config->matrox_cable == 1) {
+ val = mga_in_dac( mmio, XSYNCCTRL );
+ val &= ~(DAC2HSOFF | DAC2VSOFF | DAC2HSPOL | DAC2VSPOL);
+ mga_out_dac( mmio, XSYNCCTRL, val );
+ }
+ }
+
+ maven_disable( mav, mdrv );
+ if (!mdev->g450_matrox)
+ crtc2_set_mafc( mdrv, 0 );
+ crtc2OnOff( mdrv, mcrtc2, 0 );
+
+ crtc2_set_regs( mdrv, mcrtc2 );
+ crtc2_set_buffer( mdrv, mcrtc2 );
+
+ if (!mdev->g450_matrox)
+ crtc2_set_mafc( mdrv, 1 );
+ crtc2OnOff( mdrv, mcrtc2, 1 );
+
+ maven_set_regs( mav, mdrv, &mcrtc2->config, &mcrtc2->adj );
+
+ mcrtc2->regs.c2CTL |= C2INTERLACE;
+ if (mdev->g450_matrox)
+ mcrtc2->regs.c2CTL |= 0x1000; /* Undocumented bit */
+ while ((mga_in32( mmio, C2VCOUNT ) & 0x00000FFF) != 1)
+ ;
+ while ((mga_in32( mmio, C2VCOUNT ) & 0x00000FFF) != 0)
+ ;
+ mga_out32( mmio, mcrtc2->regs.c2CTL, C2CTL );
+
+ maven_enable( mav, mdrv );
+
+ if (!mdev->g450_matrox) {
+ while ((mga_in32( mmio, C2VCOUNT ) & 0x00000FFF) != 1)
+ ;
+ while ((mga_in32( mmio, C2VCOUNT ) & 0x00000FFF) != 0)
+ ;
+ maven_sync( mav, mdrv );
+ }
+
+ maven_close( mav, mdrv );
+
+ return DFB_OK;
+}