1 /*
2 TI Davinci driver - Video Layer
3
4 (c) Copyright 2007 Telio AG
5
6 Written by Denis Oliver Kropp <dok@directfb.org>
7
8 Code is derived from VMWare driver.
9
10 (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
11 (c) Copyright 2000-2004 Convergence (integrated media) GmbH
12
13 All rights reserved.
14
15 This library is free software; you can redistribute it and/or
16 modify it under the terms of the GNU Lesser General Public
17 License as published by the Free Software Foundation; either
18 version 2 of the License, or (at your option) any later version.
19
20 This library is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 Lesser General Public License for more details.
24
25 You should have received a copy of the GNU Lesser General Public
26 License along with this library; if not, write to the
27 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA.
29 */
30
31 //#define DIRECT_ENABLE_DEBUG
32
33 #include <config.h>
34
35 #include <asm/types.h>
36
37 #include <stdio.h>
38 #include <sys/ioctl.h>
39
40 #include <directfb.h>
41 #include <directfb_util.h>
42
43 #include <core/layers.h>
44 #include <core/surface.h>
45 #include <core/surface_buffer.h>
46
47 #include <gfx/convert.h>
48
49 #include <direct/memcpy.h>
50 #include <direct/messages.h>
51
52 #include "davincifb.h"
53
54 #include "davinci_gfxdriver.h"
55 #include "davinci_video.h"
56
57
58 #define D_VIDERROR(x...) do {} while (0)
59
60
61 D_DEBUG_DOMAIN( Davinci_Video, "Davinci/Video", "TI Davinci Video" );
62
63 /**********************************************************************************************************************/
64
65 static DFBResult ShowBuffer( DavinciDriverData *ddrv,
66 DavinciVideoLayerData *dvid,
67 CoreSurfaceBufferLock *lock,
68 const DFBRectangle *area,
69 DFBSurfaceFlipFlags flags );
70
71 static void SetupResizerParams( vpfe_resizer_params_t *params,
72 int srcWidth, int srcHeight,
73 int outWidth, int outHeight,
74 int *ret_outWidth,
75 int *ret_outHeight );
76
77 /**********************************************************************************************************************/
78
79 static int
videoLayerDataSize(void)80 videoLayerDataSize( void )
81 {
82 return sizeof(DavinciVideoLayerData);
83 }
84
85 static DFBResult
videoInitLayer(CoreLayer * layer,void * driver_data,void * layer_data,DFBDisplayLayerDescription * description,DFBDisplayLayerConfig * config,DFBColorAdjustment * adjustment)86 videoInitLayer( CoreLayer *layer,
87 void *driver_data,
88 void *layer_data,
89 DFBDisplayLayerDescription *description,
90 DFBDisplayLayerConfig *config,
91 DFBColorAdjustment *adjustment )
92 {
93 int ret;
94 DavinciDriverData *ddrv = driver_data;
95 DavinciVideoLayerData *dvid = layer_data;
96
97 D_DEBUG_AT( Davinci_Video, "%s()\n", __FUNCTION__ );
98
99 /* Initialize with configuration from VID0 to start with a fullscreen (unscaled) layer */
100 ret = ioctl( ddrv->fb[VID0].fd, FBIOGET_VSCREENINFO, &dvid->var );
101 if (ret) {
102 D_PERROR( "Davinci/Video: FBIOGET_VSCREENINFO (fb%d) failed!\n", VID0 );
103 return DFB_INIT;
104 }
105
106 /* Disable VID0 (unused) */
107 ret = ioctl( ddrv->fb[VID0].fd, FBIO_ENABLE_DISABLE_WIN, 0 );
108 if (ret)
109 D_VIDERROR( "Davinci/Video: FBIO_ENABLE_DISABLE_WIN (fb%d - %d)!\n", VID0, 0 );
110
111 /* Disable VID1 (our layer) */
112 ret = ioctl( ddrv->fb[VID1].fd, FBIO_ENABLE_DISABLE_WIN, 0 );
113 if (ret)
114 D_VIDERROR( "Davinci/Video: FBIO_ENABLE_DISABLE_WIN (fb%d - %d)!\n", VID1, 0 );
115
116 /* set capabilities and type */
117 description->caps = DLCAPS_SURFACE | DLCAPS_SCREEN_LOCATION;
118 description->type = DLTF_VIDEO | DLTF_STILL_PICTURE;
119
120 /* set name */
121 snprintf( description->name, DFB_DISPLAY_LAYER_DESC_NAME_LENGTH, "TI Davinci Video" );
122
123 /* fill out the default configuration */
124 config->flags = DLCONF_WIDTH | DLCONF_HEIGHT |
125 DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE | DLCONF_OPTIONS;
126 config->width = dvid->var.xres;
127 config->height = dvid->var.yres;
128 config->pixelformat = DSPF_UYVY;
129 config->buffermode = DLBM_FRONTONLY;
130 config->options = DLOP_NONE;
131
132 return DFB_OK;
133 }
134
135 static DFBResult
videoTestRegion(CoreLayer * layer,void * driver_data,void * layer_data,CoreLayerRegionConfig * config,CoreLayerRegionConfigFlags * failed)136 videoTestRegion( CoreLayer *layer,
137 void *driver_data,
138 void *layer_data,
139 CoreLayerRegionConfig *config,
140 CoreLayerRegionConfigFlags *failed )
141 {
142 CoreLayerRegionConfigFlags fail = 0;
143
144 D_DEBUG_AT( Davinci_Video, "%s()\n", __FUNCTION__ );
145
146 DFB_CORE_LAYER_REGION_CONFIG_DEBUG_AT( Davinci_Video, config );
147
148 if (config->options & ~DAVINCI_VIDEO_SUPPORTED_OPTIONS)
149 fail |= CLRCF_OPTIONS;
150
151 switch (config->format) {
152 case DSPF_UYVY:
153 break;
154
155 default:
156 fail |= CLRCF_FORMAT;
157 }
158
159 if (config->width < 8 || config->width > 1920)
160 fail |= CLRCF_WIDTH;
161
162 if (config->height < 8 || config->height > 1080)
163 fail |= CLRCF_HEIGHT;
164
165 if (config->dest.x < 0 || config->dest.y < 0)
166 fail |= CLRCF_DEST;
167
168 if (config->dest.x + config->dest.w > 1920)
169 fail |= CLRCF_DEST;
170
171 if (config->dest.y + config->dest.h > 1080)
172 fail |= CLRCF_DEST;
173
174 if (failed)
175 *failed = fail;
176
177 if (fail) {
178 D_DEBUG_AT( Davinci_Video, " -> FAILED (0x%08x)\n", fail );
179 return DFB_UNSUPPORTED;
180 }
181
182 D_DEBUG_AT( Davinci_Video, " -> OK\n" );
183
184 return DFB_OK;
185 }
186
187 static DFBResult
videoSetRegion(CoreLayer * layer,void * driver_data,void * layer_data,void * region_data,CoreLayerRegionConfig * config,CoreLayerRegionConfigFlags updated,CoreSurface * surface,CorePalette * palette,CoreSurfaceBufferLock * lock)188 videoSetRegion( CoreLayer *layer,
189 void *driver_data,
190 void *layer_data,
191 void *region_data,
192 CoreLayerRegionConfig *config,
193 CoreLayerRegionConfigFlags updated,
194 CoreSurface *surface,
195 CorePalette *palette,
196 CoreSurfaceBufferLock *lock )
197 {
198 int ret;
199 DavinciDriverData *ddrv = driver_data;
200 DavinciDeviceData *ddev = ddrv->ddev;
201 DavinciVideoLayerData *dvid = layer_data;
202 CoreLayerRegionConfig *old = &dvid->config;
203
204 D_DEBUG_AT( Davinci_Video, "%s( updated 0x%08x, surface %p )\n", __FUNCTION__, updated, surface );
205
206 DFB_CORE_LAYER_REGION_CONFIG_DEBUG_AT( Davinci_Video, config );
207
208 D_ASSERT( ddrv != NULL );
209 D_ASSERT( ddev != NULL );
210 D_ASSERT( dvid != NULL );
211
212 /* Update output size? */
213 if ((updated & CLRCF_DEST) && (config->dest.w != old->dest.w || config->dest.h != old->dest.h)) {
214 vpbe_window_position_t win_pos;
215
216 D_DEBUG_AT( Davinci_Video, " => dest %4dx%4d\n", config->dest.w, config->dest.h );
217
218 ret = ioctl( ddrv->fb[VID1].fd, FBIO_ENABLE_DISABLE_WIN, 0 );
219 if (ret)
220 D_VIDERROR( "Davinci/Video: FBIO_ENABLE_DISABLE_WIN (fb%d - %d)!\n", VID1, 0 );
221
222 dvid->enabled = false;
223
224 /*********************************** Start workaround ***********************************/
225 win_pos.xpos = 0;
226 win_pos.ypos = 0;
227
228 ret = ioctl( ddrv->fb[VID1].fd, FBIO_SETPOS, &win_pos );
229 if (ret)
230 D_VIDERROR( "Davinci/Video: FBIO_SETPOS (fb%d - %d,%d) failed!\n", VID1, win_pos.xpos, win_pos.ypos );
231
232 dvid->var.yoffset = 0;
233 /*********************************** End workaround ***********************************/
234
235 /* Set output width and height. */
236 dvid->var.xres = config->dest.w;
237 dvid->var.yres = config->dest.h;
238
239 dvid->var.yres_virtual = ddrv->fb[VID1].size / lock->pitch;
240
241 ret = ioctl( ddrv->fb[VID1].fd, FBIOPUT_VSCREENINFO, &dvid->var );
242 if (ret)
243 D_PERROR( "Davinci/Video: FBIOPUT_VSCREENINFO (fb%d) failed!\n", VID1 );
244
245 /* Read back new pitch etc. */
246 ret = ioctl( ddrv->fb[VID1].fd, FBIOGET_FSCREENINFO, &ddev->fix[VID1] );
247 if (ret)
248 D_PERROR( "Davinci/Video: FBIOGET_FSCREENINFO (fb%d) failed!\n", VID1 );
249 }
250
251 /* Update output position? */
252 if (updated & CLRCF_DEST) {
253 vpbe_window_position_t win_pos;
254
255 D_DEBUG_AT( Davinci_Video, " => dest %4d,%4d\n", config->dest.x, config->dest.y );
256
257 if (dvid->enabled)
258 ioctl( ddrv->fb[VID1].fd, FBIO_WAITFORVSYNC );
259
260 /* Set horizontal and vertical offset. */
261 win_pos.xpos = config->dest.x;
262 win_pos.ypos = config->dest.y;
263
264 ret = ioctl( ddrv->fb[VID1].fd, FBIO_SETPOS, &win_pos );
265 if (ret)
266 D_VIDERROR( "Davinci/Video: FBIO_SETPOS (fb%d - %d,%d) failed!\n", VID1, config->dest.x, config->dest.y );
267 }
268
269 /* Update format? */
270 if (updated & CLRCF_FORMAT) {
271 vpbe_video_config_params_t params;
272
273 params.cb_cr_order = (config->format == DSPF_YUY2) ? 1 : 0;
274
275 params.exp_info.horizontal = VPBE_DISABLE;
276 params.exp_info.vertical = VPBE_DISABLE;
277
278 ret = ioctl( ddrv->fb[VID1].fd, FBIO_SET_VIDEO_CONFIG_PARAMS, ¶ms );
279 if (ret)
280 D_VIDERROR( "Davinci/Video: FBIO_SET_VIDEO_CONFIG_PARAMS (fb%d - %s) failed!\n",
281 VID1, params.cb_cr_order ? "CrCb" : "CbCr" );
282 }
283
284 /* Update scaling parameters? */
285 if ((updated & (CLRCF_SOURCE | CLRCF_DEST)) &&
286 (config->source.w != old->source.w || config->source.h != old->source.h ||
287 config->dest.w != old->dest.w || config->dest.h != old->dest.h) &&
288 (config->dest.w != config->source.w || config->dest.h != config->source.h))
289 {
290 D_DEBUG_AT( Davinci_Video, " => scaling %4dx%4d -> %4dx%4d\n",
291 config->source.w, config->source.h, config->dest.w, config->dest.h );
292
293 SetupResizerParams( &dvid->resizer, config->source.w, config->source.h,
294 config->dest.w, config->dest.h, &dvid->resized.w, &dvid->resized.h );
295
296 dvid->offset.x = (config->dest.w - dvid->resized.w) / 2;
297 dvid->offset.y = (config->dest.h - dvid->resized.h) / 2;
298
299 D_DEBUG_AT( Davinci_Video, " => resized %4dx%4d, centered %d,%d\n",
300 dvid->resized.w, dvid->resized.h, dvid->offset.x, dvid->offset.y );
301
302 dvid->offset.x += dvid->offset.x & 1; /* Round up to multiple of two */
303
304 D_DEBUG_AT( Davinci_Video, " => offset %4d,%4d\n", dvid->offset.x, dvid->offset.y );
305
306 davincifb_pan_display( &ddrv->fb[VID1], &dvid->var, NULL, DSFLIP_NONE, 0, 0 );
307 }
308
309 dvid->enable = true;
310 dvid->config = *config;
311
312 return DFB_OK;
313 }
314
315 static DFBResult
videoRemoveRegion(CoreLayer * layer,void * driver_data,void * layer_data,void * region_data)316 videoRemoveRegion( CoreLayer *layer,
317 void *driver_data,
318 void *layer_data,
319 void *region_data )
320 {
321 int ret;
322 DavinciDriverData *ddrv = driver_data;
323 DavinciVideoLayerData *dvid = layer_data;
324
325 D_DEBUG_AT( Davinci_Video, "%s()\n", __FUNCTION__ );
326
327 D_ASSERT( ddrv != NULL );
328
329 ret = ioctl( ddrv->fb[VID1].fd, FBIO_ENABLE_DISABLE_WIN, 0 );
330 if (ret)
331 D_VIDERROR( "Davinci/Video: FBIO_ENABLE_DISABLE_WIN (fb%d - %d)!\n", VID1, 0 );
332
333 dvid->enabled = false;
334 dvid->enable = false;
335
336 return DFB_OK;
337 }
338
339 static DFBResult
videoFlipRegion(CoreLayer * layer,void * driver_data,void * layer_data,void * region_data,CoreSurface * surface,DFBSurfaceFlipFlags flags,CoreSurfaceBufferLock * lock)340 videoFlipRegion( CoreLayer *layer,
341 void *driver_data,
342 void *layer_data,
343 void *region_data,
344 CoreSurface *surface,
345 DFBSurfaceFlipFlags flags,
346 CoreSurfaceBufferLock *lock )
347 {
348 DFBResult ret;
349 DavinciDriverData *ddrv = driver_data;
350 DavinciVideoLayerData *dvid = layer_data;
351
352 D_ASSERT( surface != NULL );
353 D_ASSERT( lock != NULL );
354 D_ASSERT( ddrv != NULL );
355 D_ASSERT( dvid != NULL );
356
357 D_DEBUG_AT( Davinci_Video, "%s( 0x%08lx [%d] 0x%04x [%4dx%4d] )\n", __FUNCTION__,
358 lock->phys, lock->pitch, flags, dvid->config.width, dvid->config.height );
359
360 ret = ShowBuffer( ddrv, dvid, lock, NULL, flags );
361 if (ret)
362 return ret;
363
364 dfb_surface_flip( surface, false );
365
366 return DFB_OK;
367 }
368
369 static DFBResult
videoUpdateRegion(CoreLayer * layer,void * driver_data,void * layer_data,void * region_data,CoreSurface * surface,const DFBRegion * update,CoreSurfaceBufferLock * lock)370 videoUpdateRegion( CoreLayer *layer,
371 void *driver_data,
372 void *layer_data,
373 void *region_data,
374 CoreSurface *surface,
375 const DFBRegion *update,
376 CoreSurfaceBufferLock *lock )
377 {
378 DavinciDriverData *ddrv = driver_data;
379 DavinciVideoLayerData *dvid = layer_data;
380
381 D_ASSERT( surface != NULL );
382 D_ASSERT( lock != NULL );
383 D_ASSERT( ddrv != NULL );
384 D_ASSERT( dvid != NULL );
385
386 if (update) {
387 DFBRectangle area = DFB_RECTANGLE_INIT_FROM_REGION( update );
388
389 D_DEBUG_AT( Davinci_Video, "%s( 0x%08lx [%d], %4d,%4d-%4dx%4d )\n", __FUNCTION__,
390 lock->phys, lock->pitch, DFB_RECTANGLE_VALS( &area ) );
391
392 if (!dfb_rectangle_intersect( &area, &dvid->config.source )) {
393 D_DEBUG_AT( Davinci_Video, " -> NO INTERSECTION with %4d,%4d-%4dx%4d\n",
394 DFB_RECTANGLE_VALS( &dvid->config.source ) );
395
396 return DFB_OK;
397 }
398
399 if (!DFB_RECTANGLE_EQUAL( area, dvid->config.source ))
400 return ShowBuffer( ddrv, dvid, lock, &area, DSFLIP_NONE );
401 }
402 else
403 D_DEBUG_AT( Davinci_Video, "%s( 0x%08lx [%d], %4dx%4d )\n", __FUNCTION__,
404 lock->phys, lock->pitch, dvid->config.width, dvid->config.height );
405
406 return ShowBuffer( ddrv, dvid, lock, NULL, DSFLIP_NONE );
407 }
408
409 const DisplayLayerFuncs davinciVideoLayerFuncs = {
410 .LayerDataSize = videoLayerDataSize,
411 .InitLayer = videoInitLayer,
412
413 .TestRegion = videoTestRegion,
414 .SetRegion = videoSetRegion,
415 .RemoveRegion = videoRemoveRegion,
416 .FlipRegion = videoFlipRegion,
417 .UpdateRegion = videoUpdateRegion,
418 };
419
420 /***********************************************************************************************************************
421 ** Frame Output
422 */
423
424 static void
enable_video(DavinciDriverData * ddrv,DavinciVideoLayerData * dvid)425 enable_video( DavinciDriverData *ddrv,
426 DavinciVideoLayerData *dvid )
427 {
428 if (dvid->enable && !dvid->enabled) {
429 ioctl( ddrv->fb[VID1].fd, FBIO_WAITFORVSYNC );
430
431 if (ioctl( ddrv->fb[VID1].fd, FBIO_ENABLE_DISABLE_WIN, 1 ))
432 D_VIDERROR( "Davinci/Video: FBIO_ENABLE_DISABLE_WIN (fb%d - %d)!\n", VID1, 1 );
433
434 dvid->enabled = true;
435 }
436 }
437
438 static DFBResult
ShowBuffer(DavinciDriverData * ddrv,DavinciVideoLayerData * dvid,CoreSurfaceBufferLock * lock,const DFBRectangle * area,DFBSurfaceFlipFlags flags)439 ShowBuffer( DavinciDriverData *ddrv,
440 DavinciVideoLayerData *dvid,
441 CoreSurfaceBufferLock *lock,
442 const DFBRectangle *area,
443 DFBSurfaceFlipFlags flags )
444 {
445 const CoreLayerRegionConfig *config = &dvid->config;
446
447 if (area)
448 D_DEBUG_AT( Davinci_Video, "%s( 0x%08lx [%d], %4d,%4d-%4dx%4d )\n", __FUNCTION__,
449 lock->phys, lock->pitch, DFB_RECTANGLE_VALS( area ) );
450 else
451 D_DEBUG_AT( Davinci_Video, "%s( 0x%08lx [%d] )\n", __FUNCTION__, lock->phys, lock->pitch );
452
453 if (config->dest.w == config->source.w && config->dest.h == config->source.h) {
454 /*
455 * Unscaled video, buffer displayed directly
456 */
457 D_DEBUG_AT( Davinci_Video, " -> unscaled %4dx%4d <- %4d,%4d [%4dx%4d]\n",
458 config->source.w, config->source.h, config->source.x, config->source.y,
459 config->width, config->height );
460
461 /* Partial update, assuming proper buffer is shown, saving system calls */
462 if (area && dvid->enabled)
463 return DFB_OK;
464
465 davincifb_pan_display( &ddrv->fb[VID1], &dvid->var, lock, flags, config->source.x, config->source.y );
466 }
467 else {
468 int ret;
469 DavinciDeviceData *ddev = ddrv->ddev;
470 CoreSurfaceBuffer *buffer = lock->buffer;
471 vpfe_resizer_params_t *params = &dvid->resizer;
472
473 /*
474 * Scaled video, buffer scaled to output buffer by resizer
475 */
476 D_DEBUG_AT( Davinci_Video, " -> scaled %4dx%4d -> %4dx%4d <- %4d,%4d [%4dx%4d]\n",
477 config->source.w, config->source.h, config->dest.w, config->dest.h,
478 config->source.x, config->source.y, config->width, config->height );
479
480 /* FIXME: Implement scaled partial updates! */
481 if (area)
482 D_UNIMPLEMENTED();
483
484 params->sdr_inoff = lock->pitch;
485 params->sdr_inadd = lock->phys + DFB_BYTES_PER_LINE( buffer->format, config->source.x )
486 + config->source.y * params->sdr_inoff;
487
488 params->sdr_outoff = ddev->fix[VID1].line_length;
489 params->sdr_outadd = ddev->fix[VID1].smem_start + dvid->offset.x * 2
490 + dvid->offset.y * params->sdr_outoff;
491
492 params->in_start = (params->sdr_outadd & 0x1f) / 2;
493 params->sdr_outadd &= ~0x1f;
494
495 D_DEBUG_AT( Davinci_Video, " -> FBIO_RESIZER running...\n" );
496
497 ret = ioctl( ddrv->fb[VID1].fd, FBIO_RESIZER, params );
498 if (ret)
499 D_VIDERROR( "Davinci/Video: FBIO_RESIZER (fb%d)!\n", VID1 );
500
501 D_DEBUG_AT( Davinci_Video, " => FBIO_RESIZER returned %d\n", ret );
502 }
503
504 enable_video( ddrv, dvid );
505
506 return DFB_OK;
507 }
508
509 /***********************************************************************************************************************
510 ** Scaling Setup
511 */
512
513 static int
limitInput(int rsz,int inSize,int outSize,int * pInSize)514 limitInput(int rsz,int inSize,int outSize,int* pInSize)
515 {
516 int phases;
517 int phaseShift;
518 int taps;
519 int phaseMask;
520 int coarseShift;
521 int halfCoarse;
522 int tmp;
523
524 do {
525 if (rsz<=512) {
526 //1/2x to 4x resize uses 8 phase, 4 taps
527 phaseShift = 3;
528 taps = 4;
529 }
530 else {
531 //4-phase, 7 taps
532 phaseShift = 2;
533 taps = 7;
534 }
535 phases = 1<<phaseShift;
536 phaseMask = phases-1;
537 coarseShift = (8-phaseShift);
538 halfCoarse = (1<<(coarseShift-1));
539 tmp = (((outSize-1)* rsz + halfCoarse)>>8) + taps;
540 if (tmp <= inSize) break;
541 rsz--;
542 } while (1);
543
544 *pInSize = tmp;
545
546 return rsz;
547 }
548
549 static void
SetupCoef(unsigned int * pCoef,int rsz)550 SetupCoef(unsigned int* pCoef,int rsz)
551 {
552 int startCoef;
553 int highCoef;
554 int c;
555 int phases;
556 int taps;
557 if (rsz<=512) {
558 //1/2x to 4x resize uses 8 phase, 4 taps
559 highCoef = 0x100;
560 c=1;
561 phases=8;
562 taps=4;
563 }
564 else {
565 //4-phase, 7 taps
566 if (rsz<=(256*3)) {
567 highCoef = 0x100/2; c=2;
568 }
569 else {
570 highCoef = 0x100/4; c=1;
571 }
572 phases=4;
573 taps=7;
574 }
575 startCoef = highCoef>>1;
576 while (phases) {
577 int prev = startCoef;
578 int tapNum=0;
579 int rem=256 - startCoef;
580 while ( tapNum < (c-1)) {
581 *pCoef++ = 0;
582 tapNum+=2;
583 }
584 if (c&1) {
585 *pCoef++ = prev<<16;
586 tapNum+=2;
587 }
588 else {
589 tapNum++;
590 }
591 while ( tapNum < taps) {
592 int min = (rem<highCoef)? rem : highCoef;
593 if (tapNum&1) *pCoef++ = (min<<16)+prev;
594 else prev = min;
595 rem -= min;
596 tapNum++;
597 }
598 if (tapNum&1) {
599 *pCoef++ = prev;
600 tapNum++;
601 }
602 while ( tapNum < taps) {
603 *pCoef++ = 0;
604 tapNum+=2;
605 }
606 if (startCoef > (highCoef>>3)) startCoef -= (highCoef>>3);
607 else {
608 startCoef = highCoef; c++;
609 }
610 phases--;
611 }
612 }
613
614 #define SDRAM_SRC (1<<28)
615 #define BILINEAR (1<<29)
616
617 static void
SetupResizerParams(vpfe_resizer_params_t * params,int srcWidth,int srcHeight,int outWidth,int outHeight,int * ret_outWidth,int * ret_outHeight)618 SetupResizerParams( vpfe_resizer_params_t *params,
619 int srcWidth, int srcHeight,
620 int outWidth, int outHeight,
621 int *ret_outWidth,
622 int *ret_outHeight )
623 {
624 int rsz;
625 int hrsz;
626 int vrsz;
627 int tmp;
628
629 D_DEBUG_AT( Davinci_Video, "%s( %4dx%4d->%4dx%4d )\n", __FUNCTION__, srcWidth, srcHeight, outWidth, outHeight );
630
631 params->sdr_inadd = 0;
632 params->sdr_inoff = 0;
633
634 params->sdr_outadd = 0;
635 params->sdr_outoff = 0;
636
637 params->in_start = (0<<16)|(0);
638 params->yenh = 0;
639
640 params->rsz_cnt = SDRAM_SRC;
641
642
643
644
645 //find scale factor
646 rsz = (srcWidth<<8)/outWidth;
647 if (rsz<64) {
648 //too much upscaling, reduce destination size
649 rsz = 64;
650 }
651 else if (rsz>1024) {
652 //too much down scaling, reduce source size
653 rsz=1024;
654 srcWidth = (outWidth * rsz)>>8;
655 }
656
657 tmp = ((srcWidth<<8)+255)/rsz;
658 if (tmp > outWidth) tmp = outWidth;
659 tmp &= ~1; //force even
660 if (rsz>256) {
661 //upsize in vertical direction requires a multiple of 16 bytes (8 pixels)
662 tmp &= ~0x7;
663 }
664 do {
665 int t;
666 hrsz = limitInput(rsz,srcWidth,tmp,&t);
667 if (hrsz>=64) {
668 srcWidth = t;
669 break;
670 }
671 tmp-=2;
672 } while (1);
673 outWidth = tmp;
674
675 if (srcWidth==outWidth) {
676 int i=0;
677 params->rsz_cnt |= ((256-1)<<0); //1 to 1
678 params->in_size = (srcWidth+3); //4 taps
679 while (i<16) {
680 params->hfilt[i] = i? 0 : 0x100; //2 coefficient written at a time
681 i++;
682 }
683 }
684 else {
685 SetupCoef(¶ms->hfilt[0],hrsz);
686 params->rsz_cnt |= ((hrsz-1)<<0) | ((hrsz<256)? BILINEAR : 0);
687 params->in_size = (srcWidth);
688 }
689
690
691
692
693 //find scale factor
694 rsz = (srcHeight<<8)/outHeight;
695 if (rsz<64) {
696 //too much upscaling, reduce destination size
697 rsz = 64;
698 }
699 else if (rsz>1024) {
700 //too much down scaling, reduce source size
701 rsz=1024;
702 srcHeight = (outHeight * rsz)>>8;
703 }
704
705 tmp = ((srcHeight<<8)+255)/rsz;
706 if (tmp > outHeight) tmp = outHeight;
707 do {
708 int t;
709 vrsz = limitInput(rsz,srcHeight,tmp,&t);
710 if (vrsz>=64) {
711 srcHeight = t;
712 break;
713 }
714 tmp--;
715 } while (1);
716 outHeight = tmp;
717
718 if (srcHeight==outHeight) {
719 int i=0;
720 params->rsz_cnt |= ((256-1)<<10); //1 to 1
721 params->in_size |= ((srcHeight+3)<<16); //4 taps
722 while (i<16) {
723 params->vfilt[i] = i? 0 : 0x100; //2 coefficient written at a time
724 i++;
725 }
726 }
727 else {
728 SetupCoef(¶ms->vfilt[0],vrsz);
729 params->rsz_cnt |= ((vrsz-1)<<10);
730 params->in_size |= (srcHeight<<16);
731 }
732
733
734 params->out_size = (outHeight<<16)|(outWidth);
735
736 D_DEBUG_AT( Davinci_Video, " => %4dx%4d->%4dx%4d\n", srcWidth, srcHeight, outWidth, outHeight );
737
738 if (ret_outWidth)
739 *ret_outWidth = outWidth;
740
741 if (ret_outHeight)
742 *ret_outHeight = outHeight;
743 }
744
745