From 7fe60435bce6595a9c58a9bfd8244d74b5320e96 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Tue, 15 Jan 2013 08:46:13 +0100 Subject: Import DirectFB141_2k11R3_beta5 --- Source/DirectFB/gfxdrivers/i830/i830_overlay.c | 807 +++++++++++++++++++++++++ 1 file changed, 807 insertions(+) create mode 100755 Source/DirectFB/gfxdrivers/i830/i830_overlay.c (limited to 'Source/DirectFB/gfxdrivers/i830/i830_overlay.c') diff --git a/Source/DirectFB/gfxdrivers/i830/i830_overlay.c b/Source/DirectFB/gfxdrivers/i830/i830_overlay.c new file mode 100755 index 0000000..5f64602 --- /dev/null +++ b/Source/DirectFB/gfxdrivers/i830/i830_overlay.c @@ -0,0 +1,807 @@ +/* + Intel i830 DirectFB graphics driver + + (c) Copyright 2005 Servision Ltd. + http://www.servision.net/ + + All rights reserved. + + Based on i810 driver written by Antonino Daplas + + Video Overlay Support based partly on XFree86's "i830_video.c" + + 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. +*/ + +/* + * i830_video.c: i830/i845 Xv driver. + * + * Copyright © 2002 by Alan Hourihane and David Dawes + * + * Authors: + * Alan Hourihane + * David Dawes + * + * Derived from i830 Xv driver: + * + * Authors of i830 code: + * Jonathan Bian + * Offscreen Images: + * Matt Sottek + */ + +#include + +#include /* FIXME: Needs to be included before dfb_types.h to work around a type clash with asm/types.h */ + +#include "i830.h" + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#include + +#define I830_OVERLAY_SUPPORTED_OPTIONS (DLOP_DST_COLORKEY) + +static void ovl_calc_regs( I830DriverData *idrv, + I830DeviceData *idev, + I830OverlayLayerData *iovl, + CoreLayer *layer, + CoreSurface *surface, + CoreLayerRegionConfig *config, + bool buffers_only, + CoreSurfaceBufferLock *lock ); + + +/* + * This is more or less the correct way to initalise, update, and shut down + * the overlay. Note OVERLAY_OFF should be used only after disabling the + * overlay in OCMD and calling OVERLAY_UPDATE. + * + * XXX Need to make sure that the overlay engine is cleanly shutdown in + * all modes of server exit. + */ + +static void +update_overlay( I830DriverData *idrv, + I830DeviceData *idev ) +{ + I830RingBlock block = { NULL, 0, 0 }; + + i830_begin_lp_ring( idrv, idev, 6, &block ); + + i830_out_ring( &block, MI_FLUSH | MI_WRITE_DIRTY_STATE ); + i830_out_ring( &block, MI_NOOP ); + + if (!idev->overlayOn) { + idev->overlayOn = true; + + i830_out_ring( &block, MI_NOOP ); + i830_out_ring( &block, MI_NOOP ); + i830_out_ring( &block, MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_ON ); + } + else { + i830_out_ring( &block, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP ); + i830_out_ring( &block, MI_NOOP ); + i830_out_ring( &block, MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE ); + } + + i830_out_ring( &block, idev->ovl_mem.physical | 1 ); + + i830_advance_lp_ring( idrv, idev, &block ); +} + +static void +disable_overlay( I830DriverData *idrv, + I830DeviceData *idev ) +{ + I830RingBlock block = { NULL, 0, 0 }; + + if (!idev->overlayOn) + return; + + i830_begin_lp_ring( idrv, idev, 8, &block ); + + i830_out_ring( &block, MI_FLUSH | MI_WRITE_DIRTY_STATE ); + i830_out_ring( &block, MI_NOOP ); + i830_out_ring( &block, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP ); + i830_out_ring( &block, MI_NOOP ); + i830_out_ring( &block, MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_OFF ); + i830_out_ring( &block, idev->ovl_mem.physical | 1 ); + i830_out_ring( &block, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP ); + i830_out_ring( &block, MI_NOOP ); + + i830_advance_lp_ring( idrv, idev, &block ); + + idev->overlayOn = false; +} + +void +i830ovlOnOff( I830DriverData *idrv, + I830DeviceData *idev, + bool on ) +{ + if (on) + idrv->oregs->OCMD |= OVERLAY_ENABLE; + else + idrv->oregs->OCMD &= ~OVERLAY_ENABLE; + + update_overlay( idrv, idev ); + + if (!on) + disable_overlay( idrv, idev ); +} + +static int +ovlLayerDataSize( void ) +{ + return sizeof(I830OverlayLayerData); +} + +static DFBResult +ovlInitLayer( CoreLayer *layer, + void *driver_data, + void *layer_data, + DFBDisplayLayerDescription *description, + DFBDisplayLayerConfig *config, + DFBColorAdjustment *adjustment ) +{ + I830DriverData *idrv = driver_data; + I830DeviceData *idev = idrv->idev; + I830OverlayLayerData *iovl = layer_data; + + idev->iovl = iovl; + + idrv->oregs = (I830OverlayRegs*) idrv->ovl_base; + + memset( (void*) idrv->oregs, 0, sizeof(I830OverlayRegs) ); + + /* set_capabilities */ + description->caps = DLCAPS_SURFACE | DLCAPS_SCREEN_LOCATION | + DLCAPS_BRIGHTNESS | DLCAPS_CONTRAST | DLCAPS_SATURATION | + DLCAPS_DST_COLORKEY; + + description->type = DLTF_GRAPHICS | DLTF_VIDEO | DLTF_STILL_PICTURE; + + /* set name */ + snprintf( description->name, + DFB_DISPLAY_LAYER_DESC_NAME_LENGTH, "Intel 830/845/855/865 Overlay" ); + + /* fill out the default configuration */ + config->flags = DLCONF_WIDTH | DLCONF_HEIGHT | + DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE | DLCONF_OPTIONS; + config->width = 640; + config->height = 480; + config->pixelformat = DSPF_YUY2; + config->buffermode = DLBM_FRONTONLY; + config->options = DLOP_NONE; + + /* fill out default color adjustment, + only fields set in flags will be accepted from applications */ + adjustment->flags = DCAF_BRIGHTNESS | DCAF_CONTRAST | DCAF_SATURATION; + adjustment->brightness = 0x8000; + adjustment->contrast = 0x8000; + adjustment->saturation = 0x8000; + + + idrv->oregs->OCLRC0 = 64 << 18; + idrv->oregs->OCLRC1 = 0x80; + + return DFB_OK; +} + +static DFBResult +ovlTestRegion( CoreLayer *layer, + void *driver_data, + void *layer_data, + CoreLayerRegionConfig *config, + CoreLayerRegionConfigFlags *failed ) +{ + CoreLayerRegionConfigFlags fail = CLRCF_NONE; + + if (config->options & ~I830_OVERLAY_SUPPORTED_OPTIONS) + fail |= CLRCF_OPTIONS; + + switch (config->format) { + case DSPF_I420: + case DSPF_YV12: + case DSPF_YUY2: + case DSPF_UYVY: + break; + default: + fail |= CLRCF_FORMAT; + } + + if (config->width > 1440 || config->width < 1) + fail |= CLRCF_WIDTH; + + if (config->height > 1023 || config->height < 1) + fail |= CLRCF_HEIGHT; + + if (failed) + *failed = fail; + + if (fail) + return DFB_UNSUPPORTED; + + return DFB_OK; +} + +static DFBResult +ovlSetRegion( CoreLayer *layer, + void *driver_data, + void *layer_data, + void *region_data, + CoreLayerRegionConfig *config, + CoreLayerRegionConfigFlags updated, + CoreSurface *surface, + CorePalette *palette, + CoreSurfaceBufferLock *lock ) +{ + I830DriverData *idrv = driver_data; + I830DeviceData *idev = idrv->idev; + I830OverlayLayerData *iovl = layer_data; + + iovl->config = *config; + + ovl_calc_regs ( idrv, idev, iovl, layer, surface, config, false, lock ); + + i830ovlOnOff( idrv, idev, true ); + + return DFB_OK; +} + +static DFBResult +ovlRemoveRegion( CoreLayer *layer, + void *driver_data, + void *layer_data, + void *region_data ) +{ + I830DriverData *idrv = driver_data; + I830DeviceData *idev = idrv->idev; + + /* disable overlay */ + i830ovlOnOff( idrv, idev, false ); + + return DFB_OK; +} + +static DFBResult +ovlFlipRegion( CoreLayer *layer, + void *driver_data, + void *layer_data, + void *region_data, + CoreSurface *surface, + DFBSurfaceFlipFlags flags, + CoreSurfaceBufferLock *lock ) +{ + I830DriverData *idrv = driver_data; + I830DeviceData *idev = idrv->idev; + I830OverlayLayerData *iovl = layer_data; + + dfb_surface_flip( surface, false ); + + ovl_calc_regs ( idrv, idev, iovl, layer, surface, &iovl->config, true, lock ); + + update_overlay( idrv, idev ); + + if (flags & DSFLIP_WAIT) + dfb_screen_wait_vsync( dfb_screens_at( DSCID_PRIMARY ) ); + + return DFB_OK; +} + +static DFBResult +ovlSetColorAdjustment( CoreLayer *layer, + void *driver_data, + void *layer_data, + DFBColorAdjustment *adj ) +{ + I830DriverData *idrv = driver_data; + I830DeviceData *idev = idrv->idev; + u16 b, c, s; + + if (adj->flags & DCAF_BRIGHTNESS) + b = ((adj->brightness >> 8) - 128) & 0xFF; + else + b = idrv->oregs->OCLRC0 & 0xFF; + + if (adj->flags & DCAF_CONTRAST) + c = (adj->contrast >> 8) & 0xFF; + else + c = (idrv->oregs->OCLRC0 >> 18) & 0xFF; + + if (adj->flags & DCAF_SATURATION) + s = (adj->saturation >> 8) & 0xFF; + else + s = idrv->oregs->OCLRC1 & 0xFF; + + idrv->oregs->OCLRC0 = b | (c << 18); + idrv->oregs->OCLRC1 = s; + + update_overlay( idrv, idev ); + + return DFB_OK; +} + +static DFBResult +ovlSetInputField( CoreLayer *layer, + void *driver_data, + void *layer_data, + void *region_data, + int field ) +{ + I830DriverData *idrv = driver_data; + I830DeviceData *idev = idrv->idev; + + idrv->oregs->OCMD &= ~FIELD_SELECT; + idrv->oregs->OCMD |= (field) ? FIELD1 : FIELD0; + + update_overlay( idrv, idev ); + + return DFB_OK; +} + +DisplayLayerFuncs i830OverlayFuncs = { + .LayerDataSize = ovlLayerDataSize, + .InitLayer = ovlInitLayer, + .TestRegion = ovlTestRegion, + .SetRegion = ovlSetRegion, + .RemoveRegion = ovlRemoveRegion, + .FlipRegion = ovlFlipRegion, + .SetColorAdjustment = ovlSetColorAdjustment, + .SetInputField = ovlSetInputField, +}; + + +typedef struct { + u8 sign; + u16 mantissa; + u8 exponent; +} coeffRec, *coeffPtr; + +static bool +SetCoeffRegs(double *coeff, int mantSize, coeffPtr pCoeff, int pos) +{ + int maxVal, icoeff, res; + int sign; + double c; + + sign = 0; + maxVal = 1 << mantSize; + c = *coeff; + if (c < 0.0) { + sign = 1; + c = -c; + } + + res = 12 - mantSize; + if ((icoeff = (int)(c * 4 * maxVal + 0.5)) < maxVal) { + pCoeff[pos].exponent = 3; + pCoeff[pos].mantissa = icoeff << res; + *coeff = (double)icoeff / (double)(4 * maxVal); + } + else if ((icoeff = (int)(c * 2 * maxVal + 0.5)) < maxVal) { + pCoeff[pos].exponent = 2; + pCoeff[pos].mantissa = icoeff << res; + *coeff = (double)icoeff / (double)(2 * maxVal); + } + else if ((icoeff = (int)(c * maxVal + 0.5)) < maxVal) { + pCoeff[pos].exponent = 1; + pCoeff[pos].mantissa = icoeff << res; + *coeff = (double)icoeff / (double)(maxVal); + } + else if ((icoeff = (int)(c * maxVal * 0.5 + 0.5)) < maxVal) { + pCoeff[pos].exponent = 0; + pCoeff[pos].mantissa = icoeff << res; + *coeff = (double)icoeff / (double)(maxVal / 2); + } + else { + /* Coeff out of range */ + return false; + } + + pCoeff[pos].sign = sign; + if (sign) + *coeff = -(*coeff); + return true; +} + +static void +UpdateCoeff(int taps, double fCutoff, bool isHoriz, bool isY, coeffPtr pCoeff) +{ + int i, j, j1, num, pos, mantSize; + double pi = 3.1415926535, val, sinc, window, sum; + double rawCoeff[MAX_TAPS * 32], coeffs[N_PHASES][MAX_TAPS]; + double diff; + int tapAdjust[MAX_TAPS], tap2Fix; + bool isVertAndUV; + + if (isHoriz) + mantSize = 7; + else + mantSize = 6; + + isVertAndUV = !isHoriz && !isY; + num = taps * 16; + for (i = 0; i < num * 2; i++) { + val = (1.0 / fCutoff) * taps * pi * (i - num) / (2 * num); + if (val == 0.0) + sinc = 1.0; + else + sinc = sin(val) / val; + + /* Hamming window */ + window = (0.5 - 0.5 * cos(i * pi / num)); + rawCoeff[i] = sinc * window; + } + + for (i = 0; i < N_PHASES; i++) { + /* Normalise the coefficients. */ + sum = 0.0; + for (j = 0; j < taps; j++) { + pos = i + j * 32; + sum += rawCoeff[pos]; + } + for (j = 0; j < taps; j++) { + pos = i + j * 32; + coeffs[i][j] = rawCoeff[pos] / sum; + } + + /* Set the register values. */ + for (j = 0; j < taps; j++) { + pos = j + i * taps; + if ((j == (taps - 1) / 2) && !isVertAndUV) + SetCoeffRegs(&coeffs[i][j], mantSize + 2, pCoeff, pos); + else + SetCoeffRegs(&coeffs[i][j], mantSize, pCoeff, pos); + } + + tapAdjust[0] = (taps - 1) / 2; + for (j = 1, j1 = 1; j <= tapAdjust[0]; j++, j1++) { + tapAdjust[j1] = tapAdjust[0] - j; + tapAdjust[++j1] = tapAdjust[0] + j; + } + + /* Adjust the coefficients. */ + sum = 0.0; + for (j = 0; j < taps; j++) + sum += coeffs[i][j]; + if (sum != 1.0) { + for (j1 = 0; j1 < taps; j1++) { + tap2Fix = tapAdjust[j1]; + diff = 1.0 - sum; + coeffs[i][tap2Fix] += diff; + pos = tap2Fix + i * taps; + if ((tap2Fix == (taps - 1) / 2) && !isVertAndUV) + SetCoeffRegs(&coeffs[i][tap2Fix], mantSize + 2, pCoeff, pos); + else + SetCoeffRegs(&coeffs[i][tap2Fix], mantSize, pCoeff, pos); + + sum = 0.0; + for (j = 0; j < taps; j++) + sum += coeffs[i][j]; + if (sum == 1.0) + break; + } + } + } +} + +static void +ovl_calc_regs( I830DriverData *idrv, + I830DeviceData *idev, + I830OverlayLayerData *iovl, + CoreLayer *layer, + CoreSurface *surface, + CoreLayerRegionConfig *config, + bool buffers_only, + CoreSurfaceBufferLock *lock ) +{ + I830OverlayRegs *regs = idrv->oregs; + int width = config->width; + int height = config->height; + + int y_offset, u_offset = 0, v_offset = 0; + + unsigned int swidth; + + + /* Set buffer pointers */ + y_offset = dfb_gfxcard_memory_physical( NULL, lock->offset ); + + switch (config->format) { + case DSPF_I420: + u_offset = y_offset + height * lock->pitch; + v_offset = u_offset + ((height >> 1) * (lock->pitch >> 1)); + break; + + case DSPF_YV12: + v_offset = y_offset + height * lock->pitch; + u_offset = v_offset + ((height >> 1) * (lock->pitch >> 1)); + break; + + case DSPF_UYVY: + case DSPF_YUY2: + break; + + default: + D_BUG( "unexpected format" ); + return; + } + + /* buffer locations */ + regs->OBUF_0Y = y_offset; + regs->OBUF_0U = u_offset; + regs->OBUF_0V = v_offset; + + //D_INFO("Buffers: Y0: 0x%08x, U0: 0x%08x, V0: 0x%08x\n", regs->OBUF_0Y, + // regs->OBUF_0U, regs->OBUF_0V); + + if (buffers_only) + return; + + switch (config->format) { + case DSPF_YV12: + case DSPF_I420: + swidth = (width + 1) & ~1 & 0xfff; + regs->SWIDTH = swidth; + + swidth /= 2; + regs->SWIDTH |= (swidth & 0x7ff) << 16; + + swidth = ((y_offset + width + 0x1f) >> 5) - (y_offset >> 5) - 1; + + //D_INFO("Y width is %d, swidthsw is %d\n", width, swidth); + + regs->SWIDTHSW = swidth << 2; + + swidth = ((u_offset + (width / 2) + 0x1f) >> 5) - (u_offset >> 5) - 1; + //D_INFO("UV width is %d, swidthsw is %d\n", width / 2, swidth); + + regs->SWIDTHSW |= swidth << 18; + break; + + case DSPF_UYVY: + case DSPF_YUY2: + /* XXX Check for i845 */ + + swidth = ((width + 31) & ~31) << 1; + regs->SWIDTH = swidth; + regs->SWIDTHSW = swidth >> 3; + break; + + default: + D_BUG( "unexpected format" ); + return; + } + + regs->SHEIGHT = height | ((height / 2) << 16); + +#if NOT_PORTED_YET + if (pPriv->oneLineMode) { + /* change the coordinates with panel fitting active */ + dstBox->y1 = (((dstBox->y1 - 1) * pPriv->scaleRatio) >> 16) + 1; + dstBox->y2 = ((dstBox->y2 * pPriv->scaleRatio) >> 16) + 1; + + /* Now, alter the height, so we scale to the correct size */ + drw_h = dstBox->y2 - dstBox->y1; + if (drw_h < height) drw_h = height; + } +#endif + + regs->DWINPOS = (config->dest.y << 16) | config->dest.x; + regs->DWINSZ = (config->dest.h << 16) | config->dest.w; + + //D_INFO("pos: 0x%08x, size: 0x%08x\n", regs->DWINPOS, regs->DWINSZ); + + + regs->OCMD = OVERLAY_ENABLE; + regs->OCONFIG = CC_OUT_8BIT; + + /* + * Calculate horizontal and vertical scaling factors and polyphase + * coefficients. + */ + + { + bool scaleChanged = false; + int xscaleInt, xscaleFract, yscaleInt, yscaleFract; + int xscaleIntUV, xscaleFractUV; + int yscaleIntUV, yscaleFractUV; + /* UV is half the size of Y -- YUV420 */ + int uvratio = 2; + u32 newval; + coeffRec xcoeffY[N_HORIZ_Y_TAPS * N_PHASES]; + coeffRec xcoeffUV[N_HORIZ_UV_TAPS * N_PHASES]; + int i, j, pos; + + /* + * Y down-scale factor as a multiple of 4096. + */ + xscaleFract = (config->source.w << 12) / config->dest.w; + yscaleFract = (config->source.h << 12) / config->dest.h; + + /* Calculate the UV scaling factor. */ + xscaleFractUV = xscaleFract / uvratio; + yscaleFractUV = yscaleFract / uvratio; + + /* + * To keep the relative Y and UV ratios exact, round the Y scales + * to a multiple of the Y/UV ratio. + */ + xscaleFract = xscaleFractUV * uvratio; + yscaleFract = yscaleFractUV * uvratio; + + /* Integer (un-multiplied) values. */ + xscaleInt = xscaleFract >> 12; + yscaleInt = yscaleFract >> 12; + + xscaleIntUV = xscaleFractUV >> 12; + yscaleIntUV = yscaleFractUV >> 12; + + //D_INFO("xscale: 0x%x.%03x, yscale: 0x%x.%03x\n", xscaleInt, + // xscaleFract & 0xFFF, yscaleInt, yscaleFract & 0xFFF); + //D_INFO("UV xscale: 0x%x.%03x, UV yscale: 0x%x.%03x\n", xscaleIntUV, + // xscaleFractUV & 0xFFF, yscaleIntUV, yscaleFractUV & 0xFFF); + + newval = (xscaleInt << 16) | + ((xscaleFract & 0xFFF) << 3) | ((yscaleFract & 0xFFF) << 20); + if (newval != regs->YRGBSCALE) { + scaleChanged = true; + regs->YRGBSCALE = newval; + } + + newval = (xscaleIntUV << 16) | ((xscaleFractUV & 0xFFF) << 3) | + ((yscaleFractUV & 0xFFF) << 20); + if (newval != regs->UVSCALE) { + scaleChanged = true; + regs->UVSCALE = newval; + } + + newval = yscaleInt << 16 | yscaleIntUV; + if (newval != regs->UVSCALEV) { + scaleChanged = true; + regs->UVSCALEV = newval; + } + + /* Recalculate coefficients if the scaling changed. */ + + /* + * Only Horizontal coefficients so far. + */ + if (scaleChanged) { + double fCutoffY; + double fCutoffUV; + + fCutoffY = xscaleFract / 4096.0; + fCutoffUV = xscaleFractUV / 4096.0; + + /* Limit to between 1.0 and 3.0. */ + if (fCutoffY < MIN_CUTOFF_FREQ) + fCutoffY = MIN_CUTOFF_FREQ; + if (fCutoffY > MAX_CUTOFF_FREQ) + fCutoffY = MAX_CUTOFF_FREQ; + if (fCutoffUV < MIN_CUTOFF_FREQ) + fCutoffUV = MIN_CUTOFF_FREQ; + if (fCutoffUV > MAX_CUTOFF_FREQ) + fCutoffUV = MAX_CUTOFF_FREQ; + + UpdateCoeff(N_HORIZ_Y_TAPS, fCutoffY, true, true, xcoeffY); + UpdateCoeff(N_HORIZ_UV_TAPS, fCutoffUV, true, false, xcoeffUV); + + for (i = 0; i < N_PHASES; i++) { + for (j = 0; j < N_HORIZ_Y_TAPS; j++) { + pos = i * N_HORIZ_Y_TAPS + j; + regs->Y_HCOEFS[pos] = xcoeffY[pos].sign << 15 | + xcoeffY[pos].exponent << 12 | + xcoeffY[pos].mantissa; + } + } + for (i = 0; i < N_PHASES; i++) { + for (j = 0; j < N_HORIZ_UV_TAPS; j++) { + pos = i * N_HORIZ_UV_TAPS + j; + regs->UV_HCOEFS[pos] = xcoeffUV[pos].sign << 15 | + xcoeffUV[pos].exponent << 12 | + xcoeffUV[pos].mantissa; + } + } + } + } + + switch (config->format) { + case DSPF_YV12: + case DSPF_I420: + //D_INFO("YUV420\n"); +#if 0 + /* set UV vertical phase to -0.25 */ + regs->UV_VPH = 0x30003000; +#endif + + regs->OSTRIDE = lock->pitch | (lock->pitch << 15); + regs->OCMD |= YUV_420; + break; + + case DSPF_UYVY: + case DSPF_YUY2: + //D_INFO("YUV422\n"); + + regs->OSTRIDE = lock->pitch; + regs->OCMD |= YUV_422; + + if (config->format == DSPF_UYVY) + regs->OCMD |= Y_SWAP; + break; + + default: + D_BUG( "unexpected format" ); + return; + } + + + /* + * Destination color keying. + */ + regs->DCLRKV = PIXEL_RGB32 (config->dst_key.r, config->dst_key.g, config->dst_key.b ); + + switch (DFB_COLOR_BITS_PER_PIXEL( dfb_primary_layer_pixelformat() )) { + case 8: + regs->DCLRKM = 0xffffff; + break; + case 15: + regs->DCLRKM = 0x070707; + break; + case 16: + regs->DCLRKM = 0x070307; + break; + default: + regs->DCLRKM = 0; + break; + } + + if(dfb_config->i8xx_overlay_pipe_b) + regs->OCONFIG |= OVERLAY_PIPE_B; + + if (config->options & DLOP_DST_COLORKEY) + regs->DCLRKM |= DEST_KEY_ENABLE; + + /* + * Disable source color keying if not selected + */ + if (!(config->options & DLOP_SRC_COLORKEY)) { + regs -> SCLRKVH = 0; + regs -> SCLRKVL = 0; + regs -> SCLRKEN = 0; + } + + + //D_INFO("OCMD is 0x%08x\n", regs->OCMD); +} + -- cgit