summaryrefslogtreecommitdiff
path: root/Source/DirectFB/gfxdrivers/davinci/davinci_video.c
diff options
context:
space:
mode:
Diffstat (limited to 'Source/DirectFB/gfxdrivers/davinci/davinci_video.c')
-rwxr-xr-xSource/DirectFB/gfxdrivers/davinci/davinci_video.c744
1 files changed, 744 insertions, 0 deletions
diff --git a/Source/DirectFB/gfxdrivers/davinci/davinci_video.c b/Source/DirectFB/gfxdrivers/davinci/davinci_video.c
new file mode 100755
index 0000000..1a284a0
--- /dev/null
+++ b/Source/DirectFB/gfxdrivers/davinci/davinci_video.c
@@ -0,0 +1,744 @@
+/*
+ TI Davinci driver - Video Layer
+
+ (c) Copyright 2007 Telio AG
+
+ Written by Denis Oliver Kropp <dok@directfb.org>
+
+ Code is derived from VMWare driver.
+
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ 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.
+*/
+
+//#define DIRECT_ENABLE_DEBUG
+
+#include <config.h>
+
+#include <asm/types.h>
+
+#include <stdio.h>
+#include <sys/ioctl.h>
+
+#include <directfb.h>
+#include <directfb_util.h>
+
+#include <core/layers.h>
+#include <core/surface.h>
+#include <core/surface_buffer.h>
+
+#include <gfx/convert.h>
+
+#include <direct/memcpy.h>
+#include <direct/messages.h>
+
+#include "davincifb.h"
+
+#include "davinci_gfxdriver.h"
+#include "davinci_video.h"
+
+
+#define D_VIDERROR(x...) do {} while (0)
+
+
+D_DEBUG_DOMAIN( Davinci_Video, "Davinci/Video", "TI Davinci Video" );
+
+/**********************************************************************************************************************/
+
+static DFBResult ShowBuffer( DavinciDriverData *ddrv,
+ DavinciVideoLayerData *dvid,
+ CoreSurfaceBufferLock *lock,
+ const DFBRectangle *area,
+ DFBSurfaceFlipFlags flags );
+
+static void SetupResizerParams( vpfe_resizer_params_t *params,
+ int srcWidth, int srcHeight,
+ int outWidth, int outHeight,
+ int *ret_outWidth,
+ int *ret_outHeight );
+
+/**********************************************************************************************************************/
+
+static int
+videoLayerDataSize( void )
+{
+ return sizeof(DavinciVideoLayerData);
+}
+
+static DFBResult
+videoInitLayer( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ DFBDisplayLayerDescription *description,
+ DFBDisplayLayerConfig *config,
+ DFBColorAdjustment *adjustment )
+{
+ int ret;
+ DavinciDriverData *ddrv = driver_data;
+ DavinciVideoLayerData *dvid = layer_data;
+
+ D_DEBUG_AT( Davinci_Video, "%s()\n", __FUNCTION__ );
+
+ /* Initialize with configuration from VID0 to start with a fullscreen (unscaled) layer */
+ ret = ioctl( ddrv->fb[VID0].fd, FBIOGET_VSCREENINFO, &dvid->var );
+ if (ret) {
+ D_PERROR( "Davinci/Video: FBIOGET_VSCREENINFO (fb%d) failed!\n", VID0 );
+ return DFB_INIT;
+ }
+
+ /* Disable VID0 (unused) */
+ ret = ioctl( ddrv->fb[VID0].fd, FBIO_ENABLE_DISABLE_WIN, 0 );
+ if (ret)
+ D_VIDERROR( "Davinci/Video: FBIO_ENABLE_DISABLE_WIN (fb%d - %d)!\n", VID0, 0 );
+
+ /* Disable VID1 (our layer) */
+ ret = ioctl( ddrv->fb[VID1].fd, FBIO_ENABLE_DISABLE_WIN, 0 );
+ if (ret)
+ D_VIDERROR( "Davinci/Video: FBIO_ENABLE_DISABLE_WIN (fb%d - %d)!\n", VID1, 0 );
+
+ /* set capabilities and type */
+ description->caps = DLCAPS_SURFACE | DLCAPS_SCREEN_LOCATION;
+ description->type = DLTF_VIDEO | DLTF_STILL_PICTURE;
+
+ /* set name */
+ snprintf( description->name, DFB_DISPLAY_LAYER_DESC_NAME_LENGTH, "TI Davinci Video" );
+
+ /* fill out the default configuration */
+ config->flags = DLCONF_WIDTH | DLCONF_HEIGHT |
+ DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE | DLCONF_OPTIONS;
+ config->width = dvid->var.xres;
+ config->height = dvid->var.yres;
+ config->pixelformat = DSPF_UYVY;
+ config->buffermode = DLBM_FRONTONLY;
+ config->options = DLOP_NONE;
+
+ return DFB_OK;
+}
+
+static DFBResult
+videoTestRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ CoreLayerRegionConfig *config,
+ CoreLayerRegionConfigFlags *failed )
+{
+ CoreLayerRegionConfigFlags fail = 0;
+
+ D_DEBUG_AT( Davinci_Video, "%s()\n", __FUNCTION__ );
+
+ DFB_CORE_LAYER_REGION_CONFIG_DEBUG_AT( Davinci_Video, config );
+
+ if (config->options & ~DAVINCI_VIDEO_SUPPORTED_OPTIONS)
+ fail |= CLRCF_OPTIONS;
+
+ switch (config->format) {
+ case DSPF_UYVY:
+ break;
+
+ default:
+ fail |= CLRCF_FORMAT;
+ }
+
+ if (config->width < 8 || config->width > 1920)
+ fail |= CLRCF_WIDTH;
+
+ if (config->height < 8 || config->height > 1080)
+ fail |= CLRCF_HEIGHT;
+
+ if (config->dest.x < 0 || config->dest.y < 0)
+ fail |= CLRCF_DEST;
+
+ if (config->dest.x + config->dest.w > 1920)
+ fail |= CLRCF_DEST;
+
+ if (config->dest.y + config->dest.h > 1080)
+ fail |= CLRCF_DEST;
+
+ if (failed)
+ *failed = fail;
+
+ if (fail) {
+ D_DEBUG_AT( Davinci_Video, " -> FAILED (0x%08x)\n", fail );
+ return DFB_UNSUPPORTED;
+ }
+
+ D_DEBUG_AT( Davinci_Video, " -> OK\n" );
+
+ return DFB_OK;
+}
+
+static DFBResult
+videoSetRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data,
+ CoreLayerRegionConfig *config,
+ CoreLayerRegionConfigFlags updated,
+ CoreSurface *surface,
+ CorePalette *palette,
+ CoreSurfaceBufferLock *lock )
+{
+ int ret;
+ DavinciDriverData *ddrv = driver_data;
+ DavinciDeviceData *ddev = ddrv->ddev;
+ DavinciVideoLayerData *dvid = layer_data;
+ CoreLayerRegionConfig *old = &dvid->config;
+
+ D_DEBUG_AT( Davinci_Video, "%s( updated 0x%08x, surface %p )\n", __FUNCTION__, updated, surface );
+
+ DFB_CORE_LAYER_REGION_CONFIG_DEBUG_AT( Davinci_Video, config );
+
+ D_ASSERT( ddrv != NULL );
+ D_ASSERT( ddev != NULL );
+ D_ASSERT( dvid != NULL );
+
+ /* Update output size? */
+ if ((updated & CLRCF_DEST) && (config->dest.w != old->dest.w || config->dest.h != old->dest.h)) {
+ vpbe_window_position_t win_pos;
+
+ D_DEBUG_AT( Davinci_Video, " => dest %4dx%4d\n", config->dest.w, config->dest.h );
+
+ ret = ioctl( ddrv->fb[VID1].fd, FBIO_ENABLE_DISABLE_WIN, 0 );
+ if (ret)
+ D_VIDERROR( "Davinci/Video: FBIO_ENABLE_DISABLE_WIN (fb%d - %d)!\n", VID1, 0 );
+
+ dvid->enabled = false;
+
+/*********************************** Start workaround ***********************************/
+ win_pos.xpos = 0;
+ win_pos.ypos = 0;
+
+ ret = ioctl( ddrv->fb[VID1].fd, FBIO_SETPOS, &win_pos );
+ if (ret)
+ D_VIDERROR( "Davinci/Video: FBIO_SETPOS (fb%d - %d,%d) failed!\n", VID1, win_pos.xpos, win_pos.ypos );
+
+ dvid->var.yoffset = 0;
+/*********************************** End workaround ***********************************/
+
+ /* Set output width and height. */
+ dvid->var.xres = config->dest.w;
+ dvid->var.yres = config->dest.h;
+
+ dvid->var.yres_virtual = ddrv->fb[VID1].size / lock->pitch;
+
+ ret = ioctl( ddrv->fb[VID1].fd, FBIOPUT_VSCREENINFO, &dvid->var );
+ if (ret)
+ D_PERROR( "Davinci/Video: FBIOPUT_VSCREENINFO (fb%d) failed!\n", VID1 );
+
+ /* Read back new pitch etc. */
+ ret = ioctl( ddrv->fb[VID1].fd, FBIOGET_FSCREENINFO, &ddev->fix[VID1] );
+ if (ret)
+ D_PERROR( "Davinci/Video: FBIOGET_FSCREENINFO (fb%d) failed!\n", VID1 );
+ }
+
+ /* Update output position? */
+ if (updated & CLRCF_DEST) {
+ vpbe_window_position_t win_pos;
+
+ D_DEBUG_AT( Davinci_Video, " => dest %4d,%4d\n", config->dest.x, config->dest.y );
+
+ if (dvid->enabled)
+ ioctl( ddrv->fb[VID1].fd, FBIO_WAITFORVSYNC );
+
+ /* Set horizontal and vertical offset. */
+ win_pos.xpos = config->dest.x;
+ win_pos.ypos = config->dest.y;
+
+ ret = ioctl( ddrv->fb[VID1].fd, FBIO_SETPOS, &win_pos );
+ if (ret)
+ D_VIDERROR( "Davinci/Video: FBIO_SETPOS (fb%d - %d,%d) failed!\n", VID1, config->dest.x, config->dest.y );
+ }
+
+ /* Update format? */
+ if (updated & CLRCF_FORMAT) {
+ vpbe_video_config_params_t params;
+
+ params.cb_cr_order = (config->format == DSPF_YUY2) ? 1 : 0;
+
+ params.exp_info.horizontal = VPBE_DISABLE;
+ params.exp_info.vertical = VPBE_DISABLE;
+
+ ret = ioctl( ddrv->fb[VID1].fd, FBIO_SET_VIDEO_CONFIG_PARAMS, &params );
+ if (ret)
+ D_VIDERROR( "Davinci/Video: FBIO_SET_VIDEO_CONFIG_PARAMS (fb%d - %s) failed!\n",
+ VID1, params.cb_cr_order ? "CrCb" : "CbCr" );
+ }
+
+ /* Update scaling parameters? */
+ if ((updated & (CLRCF_SOURCE | CLRCF_DEST)) &&
+ (config->source.w != old->source.w || config->source.h != old->source.h ||
+ config->dest.w != old->dest.w || config->dest.h != old->dest.h) &&
+ (config->dest.w != config->source.w || config->dest.h != config->source.h))
+ {
+ D_DEBUG_AT( Davinci_Video, " => scaling %4dx%4d -> %4dx%4d\n",
+ config->source.w, config->source.h, config->dest.w, config->dest.h );
+
+ SetupResizerParams( &dvid->resizer, config->source.w, config->source.h,
+ config->dest.w, config->dest.h, &dvid->resized.w, &dvid->resized.h );
+
+ dvid->offset.x = (config->dest.w - dvid->resized.w) / 2;
+ dvid->offset.y = (config->dest.h - dvid->resized.h) / 2;
+
+ D_DEBUG_AT( Davinci_Video, " => resized %4dx%4d, centered %d,%d\n",
+ dvid->resized.w, dvid->resized.h, dvid->offset.x, dvid->offset.y );
+
+ dvid->offset.x += dvid->offset.x & 1; /* Round up to multiple of two */
+
+ D_DEBUG_AT( Davinci_Video, " => offset %4d,%4d\n", dvid->offset.x, dvid->offset.y );
+
+ davincifb_pan_display( &ddrv->fb[VID1], &dvid->var, NULL, DSFLIP_NONE, 0, 0 );
+ }
+
+ dvid->enable = true;
+ dvid->config = *config;
+
+ return DFB_OK;
+}
+
+static DFBResult
+videoRemoveRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data )
+{
+ int ret;
+ DavinciDriverData *ddrv = driver_data;
+ DavinciVideoLayerData *dvid = layer_data;
+
+ D_DEBUG_AT( Davinci_Video, "%s()\n", __FUNCTION__ );
+
+ D_ASSERT( ddrv != NULL );
+
+ ret = ioctl( ddrv->fb[VID1].fd, FBIO_ENABLE_DISABLE_WIN, 0 );
+ if (ret)
+ D_VIDERROR( "Davinci/Video: FBIO_ENABLE_DISABLE_WIN (fb%d - %d)!\n", VID1, 0 );
+
+ dvid->enabled = false;
+ dvid->enable = false;
+
+ return DFB_OK;
+}
+
+static DFBResult
+videoFlipRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data,
+ CoreSurface *surface,
+ DFBSurfaceFlipFlags flags,
+ CoreSurfaceBufferLock *lock )
+{
+ DFBResult ret;
+ DavinciDriverData *ddrv = driver_data;
+ DavinciVideoLayerData *dvid = layer_data;
+
+ D_ASSERT( surface != NULL );
+ D_ASSERT( lock != NULL );
+ D_ASSERT( ddrv != NULL );
+ D_ASSERT( dvid != NULL );
+
+ D_DEBUG_AT( Davinci_Video, "%s( 0x%08lx [%d] 0x%04x [%4dx%4d] )\n", __FUNCTION__,
+ lock->phys, lock->pitch, flags, dvid->config.width, dvid->config.height );
+
+ ret = ShowBuffer( ddrv, dvid, lock, NULL, flags );
+ if (ret)
+ return ret;
+
+ dfb_surface_flip( surface, false );
+
+ return DFB_OK;
+}
+
+static DFBResult
+videoUpdateRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data,
+ CoreSurface *surface,
+ const DFBRegion *update,
+ CoreSurfaceBufferLock *lock )
+{
+ DavinciDriverData *ddrv = driver_data;
+ DavinciVideoLayerData *dvid = layer_data;
+
+ D_ASSERT( surface != NULL );
+ D_ASSERT( lock != NULL );
+ D_ASSERT( ddrv != NULL );
+ D_ASSERT( dvid != NULL );
+
+ if (update) {
+ DFBRectangle area = DFB_RECTANGLE_INIT_FROM_REGION( update );
+
+ D_DEBUG_AT( Davinci_Video, "%s( 0x%08lx [%d], %4d,%4d-%4dx%4d )\n", __FUNCTION__,
+ lock->phys, lock->pitch, DFB_RECTANGLE_VALS( &area ) );
+
+ if (!dfb_rectangle_intersect( &area, &dvid->config.source )) {
+ D_DEBUG_AT( Davinci_Video, " -> NO INTERSECTION with %4d,%4d-%4dx%4d\n",
+ DFB_RECTANGLE_VALS( &dvid->config.source ) );
+
+ return DFB_OK;
+ }
+
+ if (!DFB_RECTANGLE_EQUAL( area, dvid->config.source ))
+ return ShowBuffer( ddrv, dvid, lock, &area, DSFLIP_NONE );
+ }
+ else
+ D_DEBUG_AT( Davinci_Video, "%s( 0x%08lx [%d], %4dx%4d )\n", __FUNCTION__,
+ lock->phys, lock->pitch, dvid->config.width, dvid->config.height );
+
+ return ShowBuffer( ddrv, dvid, lock, NULL, DSFLIP_NONE );
+}
+
+const DisplayLayerFuncs davinciVideoLayerFuncs = {
+ .LayerDataSize = videoLayerDataSize,
+ .InitLayer = videoInitLayer,
+
+ .TestRegion = videoTestRegion,
+ .SetRegion = videoSetRegion,
+ .RemoveRegion = videoRemoveRegion,
+ .FlipRegion = videoFlipRegion,
+ .UpdateRegion = videoUpdateRegion,
+};
+
+/***********************************************************************************************************************
+** Frame Output
+*/
+
+static void
+enable_video( DavinciDriverData *ddrv,
+ DavinciVideoLayerData *dvid )
+{
+ if (dvid->enable && !dvid->enabled) {
+ ioctl( ddrv->fb[VID1].fd, FBIO_WAITFORVSYNC );
+
+ if (ioctl( ddrv->fb[VID1].fd, FBIO_ENABLE_DISABLE_WIN, 1 ))
+ D_VIDERROR( "Davinci/Video: FBIO_ENABLE_DISABLE_WIN (fb%d - %d)!\n", VID1, 1 );
+
+ dvid->enabled = true;
+ }
+}
+
+static DFBResult
+ShowBuffer( DavinciDriverData *ddrv,
+ DavinciVideoLayerData *dvid,
+ CoreSurfaceBufferLock *lock,
+ const DFBRectangle *area,
+ DFBSurfaceFlipFlags flags )
+{
+ const CoreLayerRegionConfig *config = &dvid->config;
+
+ if (area)
+ D_DEBUG_AT( Davinci_Video, "%s( 0x%08lx [%d], %4d,%4d-%4dx%4d )\n", __FUNCTION__,
+ lock->phys, lock->pitch, DFB_RECTANGLE_VALS( area ) );
+ else
+ D_DEBUG_AT( Davinci_Video, "%s( 0x%08lx [%d] )\n", __FUNCTION__, lock->phys, lock->pitch );
+
+ if (config->dest.w == config->source.w && config->dest.h == config->source.h) {
+ /*
+ * Unscaled video, buffer displayed directly
+ */
+ D_DEBUG_AT( Davinci_Video, " -> unscaled %4dx%4d <- %4d,%4d [%4dx%4d]\n",
+ config->source.w, config->source.h, config->source.x, config->source.y,
+ config->width, config->height );
+
+ /* Partial update, assuming proper buffer is shown, saving system calls */
+ if (area && dvid->enabled)
+ return DFB_OK;
+
+ davincifb_pan_display( &ddrv->fb[VID1], &dvid->var, lock, flags, config->source.x, config->source.y );
+ }
+ else {
+ int ret;
+ DavinciDeviceData *ddev = ddrv->ddev;
+ CoreSurfaceBuffer *buffer = lock->buffer;
+ vpfe_resizer_params_t *params = &dvid->resizer;
+
+ /*
+ * Scaled video, buffer scaled to output buffer by resizer
+ */
+ D_DEBUG_AT( Davinci_Video, " -> scaled %4dx%4d -> %4dx%4d <- %4d,%4d [%4dx%4d]\n",
+ config->source.w, config->source.h, config->dest.w, config->dest.h,
+ config->source.x, config->source.y, config->width, config->height );
+
+ /* FIXME: Implement scaled partial updates! */
+ if (area)
+ D_UNIMPLEMENTED();
+
+ params->sdr_inoff = lock->pitch;
+ params->sdr_inadd = lock->phys + DFB_BYTES_PER_LINE( buffer->format, config->source.x )
+ + config->source.y * params->sdr_inoff;
+
+ params->sdr_outoff = ddev->fix[VID1].line_length;
+ params->sdr_outadd = ddev->fix[VID1].smem_start + dvid->offset.x * 2
+ + dvid->offset.y * params->sdr_outoff;
+
+ params->in_start = (params->sdr_outadd & 0x1f) / 2;
+ params->sdr_outadd &= ~0x1f;
+
+ D_DEBUG_AT( Davinci_Video, " -> FBIO_RESIZER running...\n" );
+
+ ret = ioctl( ddrv->fb[VID1].fd, FBIO_RESIZER, params );
+ if (ret)
+ D_VIDERROR( "Davinci/Video: FBIO_RESIZER (fb%d)!\n", VID1 );
+
+ D_DEBUG_AT( Davinci_Video, " => FBIO_RESIZER returned %d\n", ret );
+ }
+
+ enable_video( ddrv, dvid );
+
+ return DFB_OK;
+}
+
+/***********************************************************************************************************************
+** Scaling Setup
+*/
+
+static int
+limitInput(int rsz,int inSize,int outSize,int* pInSize)
+{
+ int phases;
+ int phaseShift;
+ int taps;
+ int phaseMask;
+ int coarseShift;
+ int halfCoarse;
+ int tmp;
+
+ do {
+ if (rsz<=512) {
+ //1/2x to 4x resize uses 8 phase, 4 taps
+ phaseShift = 3;
+ taps = 4;
+ }
+ else {
+ //4-phase, 7 taps
+ phaseShift = 2;
+ taps = 7;
+ }
+ phases = 1<<phaseShift;
+ phaseMask = phases-1;
+ coarseShift = (8-phaseShift);
+ halfCoarse = (1<<(coarseShift-1));
+ tmp = (((outSize-1)* rsz + halfCoarse)>>8) + taps;
+ if (tmp <= inSize) break;
+ rsz--;
+ } while (1);
+
+ *pInSize = tmp;
+
+ return rsz;
+}
+
+static void
+SetupCoef(unsigned int* pCoef,int rsz)
+{
+ int startCoef;
+ int highCoef;
+ int c;
+ int phases;
+ int taps;
+ if (rsz<=512) {
+ //1/2x to 4x resize uses 8 phase, 4 taps
+ highCoef = 0x100;
+ c=1;
+ phases=8;
+ taps=4;
+ }
+ else {
+ //4-phase, 7 taps
+ if (rsz<=(256*3)) {
+ highCoef = 0x100/2; c=2;
+ }
+ else {
+ highCoef = 0x100/4; c=1;
+ }
+ phases=4;
+ taps=7;
+ }
+ startCoef = highCoef>>1;
+ while (phases) {
+ int prev = startCoef;
+ int tapNum=0;
+ int rem=256 - startCoef;
+ while ( tapNum < (c-1)) {
+ *pCoef++ = 0;
+ tapNum+=2;
+ }
+ if (c&1) {
+ *pCoef++ = prev<<16;
+ tapNum+=2;
+ }
+ else {
+ tapNum++;
+ }
+ while ( tapNum < taps) {
+ int min = (rem<highCoef)? rem : highCoef;
+ if (tapNum&1) *pCoef++ = (min<<16)+prev;
+ else prev = min;
+ rem -= min;
+ tapNum++;
+ }
+ if (tapNum&1) {
+ *pCoef++ = prev;
+ tapNum++;
+ }
+ while ( tapNum < taps) {
+ *pCoef++ = 0;
+ tapNum+=2;
+ }
+ if (startCoef > (highCoef>>3)) startCoef -= (highCoef>>3);
+ else {
+ startCoef = highCoef; c++;
+ }
+ phases--;
+ }
+}
+
+#define SDRAM_SRC (1<<28)
+#define BILINEAR (1<<29)
+
+static void
+SetupResizerParams( vpfe_resizer_params_t *params,
+ int srcWidth, int srcHeight,
+ int outWidth, int outHeight,
+ int *ret_outWidth,
+ int *ret_outHeight )
+{
+ int rsz;
+ int hrsz;
+ int vrsz;
+ int tmp;
+
+ D_DEBUG_AT( Davinci_Video, "%s( %4dx%4d->%4dx%4d )\n", __FUNCTION__, srcWidth, srcHeight, outWidth, outHeight );
+
+ params->sdr_inadd = 0;
+ params->sdr_inoff = 0;
+
+ params->sdr_outadd = 0;
+ params->sdr_outoff = 0;
+
+ params->in_start = (0<<16)|(0);
+ params->yenh = 0;
+
+ params->rsz_cnt = SDRAM_SRC;
+
+
+
+
+ //find scale factor
+ rsz = (srcWidth<<8)/outWidth;
+ if (rsz<64) {
+ //too much upscaling, reduce destination size
+ rsz = 64;
+ }
+ else if (rsz>1024) {
+ //too much down scaling, reduce source size
+ rsz=1024;
+ srcWidth = (outWidth * rsz)>>8;
+ }
+
+ tmp = ((srcWidth<<8)+255)/rsz;
+ if (tmp > outWidth) tmp = outWidth;
+ tmp &= ~1; //force even
+ if (rsz>256) {
+ //upsize in vertical direction requires a multiple of 16 bytes (8 pixels)
+ tmp &= ~0x7;
+ }
+ do {
+ int t;
+ hrsz = limitInput(rsz,srcWidth,tmp,&t);
+ if (hrsz>=64) {
+ srcWidth = t;
+ break;
+ }
+ tmp-=2;
+ } while (1);
+ outWidth = tmp;
+
+ if (srcWidth==outWidth) {
+ int i=0;
+ params->rsz_cnt |= ((256-1)<<0); //1 to 1
+ params->in_size = (srcWidth+3); //4 taps
+ while (i<16) {
+ params->hfilt[i] = i? 0 : 0x100; //2 coefficient written at a time
+ i++;
+ }
+ }
+ else {
+ SetupCoef(&params->hfilt[0],hrsz);
+ params->rsz_cnt |= ((hrsz-1)<<0) | ((hrsz<256)? BILINEAR : 0);
+ params->in_size = (srcWidth);
+ }
+
+
+
+
+ //find scale factor
+ rsz = (srcHeight<<8)/outHeight;
+ if (rsz<64) {
+ //too much upscaling, reduce destination size
+ rsz = 64;
+ }
+ else if (rsz>1024) {
+ //too much down scaling, reduce source size
+ rsz=1024;
+ srcHeight = (outHeight * rsz)>>8;
+ }
+
+ tmp = ((srcHeight<<8)+255)/rsz;
+ if (tmp > outHeight) tmp = outHeight;
+ do {
+ int t;
+ vrsz = limitInput(rsz,srcHeight,tmp,&t);
+ if (vrsz>=64) {
+ srcHeight = t;
+ break;
+ }
+ tmp--;
+ } while (1);
+ outHeight = tmp;
+
+ if (srcHeight==outHeight) {
+ int i=0;
+ params->rsz_cnt |= ((256-1)<<10); //1 to 1
+ params->in_size |= ((srcHeight+3)<<16); //4 taps
+ while (i<16) {
+ params->vfilt[i] = i? 0 : 0x100; //2 coefficient written at a time
+ i++;
+ }
+ }
+ else {
+ SetupCoef(&params->vfilt[0],vrsz);
+ params->rsz_cnt |= ((vrsz-1)<<10);
+ params->in_size |= (srcHeight<<16);
+ }
+
+
+ params->out_size = (outHeight<<16)|(outWidth);
+
+ D_DEBUG_AT( Davinci_Video, " => %4dx%4d->%4dx%4d\n", srcWidth, srcHeight, outWidth, outHeight );
+
+ if (ret_outWidth)
+ *ret_outWidth = outWidth;
+
+ if (ret_outHeight)
+ *ret_outHeight = outHeight;
+}
+