1 /*
2    TI Davinci driver - Graphics 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_osd.h"
56 
57 
58 #define D_OSDERROR(x...) do {} while (0)
59 
60 
61 D_DEBUG_DOMAIN( Davinci_OSD, "Davinci/OSD", "TI Davinci OSD" );
62 
63 /**********************************************************************************************************************/
64 
65 static int
osdLayerDataSize(void)66 osdLayerDataSize( void )
67 {
68      return sizeof(DavinciOSDLayerData);
69 }
70 
71 static DFBResult
osdInitLayer(CoreLayer * layer,void * driver_data,void * layer_data,DFBDisplayLayerDescription * description,DFBDisplayLayerConfig * config,DFBColorAdjustment * adjustment)72 osdInitLayer( CoreLayer                  *layer,
73               void                       *driver_data,
74               void                       *layer_data,
75               DFBDisplayLayerDescription *description,
76               DFBDisplayLayerConfig      *config,
77               DFBColorAdjustment         *adjustment )
78 {
79      int                  ret;
80      DavinciDriverData   *ddrv = driver_data;
81      DavinciOSDLayerData *dosd = layer_data;
82 
83      D_DEBUG_AT( Davinci_OSD, "%s()\n", __FUNCTION__ );
84 
85      ret = ioctl( ddrv->fb[OSD0].fd, FBIOGET_VSCREENINFO, &dosd->var0 );
86      if (ret) {
87           D_PERROR( "Davinci/OSD: FBIOGET_VSCREENINFO (fb%d) failed!\n", OSD0 );
88           return DFB_INIT;
89      }
90 
91      ret = ioctl( ddrv->fb[OSD1].fd, FBIOGET_VSCREENINFO, &dosd->var1 );
92      if (ret) {
93           D_PERROR( "Davinci/OSD: FBIOGET_VSCREENINFO (fb%d) failed!\n", OSD1 );
94           return DFB_INIT;
95      }
96 
97      ret = ioctl( ddrv->fb[OSD0].fd, FBIO_ENABLE_DISABLE_WIN, 0 );
98      if (ret)
99           D_OSDERROR( "Davinci/OSD: FBIO_ENABLE_DISABLE_WIN (fb%d - %d)!\n", OSD0, 0 );
100 
101      ret = ioctl( ddrv->fb[OSD1].fd, FBIO_ENABLE_DISABLE_WIN, 0 );
102      if (ret)
103           D_OSDERROR( "Davinci/OSD: FBIO_ENABLE_DISABLE_WIN (fb%d - %d)!\n", OSD1, 0 );
104 
105      /* set capabilities and type */
106      description->caps = DLCAPS_SURFACE | DLCAPS_ALPHACHANNEL | DLCAPS_OPACITY | DLCAPS_SCREEN_POSITION |
107                          DLCAPS_SRC_COLORKEY;
108      description->type = DLTF_GRAPHICS;
109 
110      /* set name */
111      snprintf( description->name, DFB_DISPLAY_LAYER_DESC_NAME_LENGTH, "TI Davinci OSD" );
112 
113      /* fill out the default configuration */
114      config->flags       = DLCONF_WIDTH       | DLCONF_HEIGHT |
115                            DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE | DLCONF_OPTIONS;
116      config->width       = 640;
117      config->height      = 480;
118      config->pixelformat = DSPF_RGB16;
119      config->buffermode  = DLBM_FRONTONLY;
120      config->options     = DLOP_ALPHACHANNEL;
121 
122      return DFB_OK;
123 }
124 
125 static DFBResult
osdTestRegion(CoreLayer * layer,void * driver_data,void * layer_data,CoreLayerRegionConfig * config,CoreLayerRegionConfigFlags * failed)126 osdTestRegion( CoreLayer                  *layer,
127                void                       *driver_data,
128                void                       *layer_data,
129                CoreLayerRegionConfig      *config,
130                CoreLayerRegionConfigFlags *failed )
131 {
132      CoreLayerRegionConfigFlags fail = 0;
133 
134      D_DEBUG_AT( Davinci_OSD, "%s()\n", __FUNCTION__ );
135 
136      if (config->options & ~DAVINCI_OSD_SUPPORTED_OPTIONS)
137           fail |= CLRCF_OPTIONS;
138 
139      switch (config->format) {
140           case DSPF_RGB444:
141           case DSPF_RGB555:
142           case DSPF_RGB16:
143           case DSPF_RGB32:
144           case DSPF_ARGB4444:
145           case DSPF_ARGB1555:
146           case DSPF_ARGB:
147                break;
148 
149           default:
150                fail |= CLRCF_FORMAT;
151      }
152 
153      if (config->width  < 8 || config->width  > 1920)
154           fail |= CLRCF_WIDTH;
155 
156      if (config->height < 8 || config->height > 1080)
157           fail |= CLRCF_HEIGHT;
158 
159      if (config->dest.x < 0 || config->dest.y < 0)
160           fail |= CLRCF_DEST;
161 
162      if (config->dest.x + config->dest.w > 1920)
163           fail |= CLRCF_DEST;
164 
165      if (config->dest.y + config->dest.h > 1080)
166           fail |= CLRCF_DEST;
167 
168      if (failed)
169           *failed = fail;
170 
171      if (fail)
172           return DFB_UNSUPPORTED;
173 
174      return DFB_OK;
175 }
176 
177 static DFBResult
osdSetRegion(CoreLayer * layer,void * driver_data,void * layer_data,void * region_data,CoreLayerRegionConfig * config,CoreLayerRegionConfigFlags updated,CoreSurface * surface,CorePalette * palette,CoreSurfaceBufferLock * lock)178 osdSetRegion( CoreLayer                  *layer,
179               void                       *driver_data,
180               void                       *layer_data,
181               void                       *region_data,
182               CoreLayerRegionConfig      *config,
183               CoreLayerRegionConfigFlags  updated,
184               CoreSurface                *surface,
185               CorePalette                *palette,
186               CoreSurfaceBufferLock      *lock )
187 {
188      int                  ret;
189      DavinciDriverData   *ddrv = driver_data;
190      DavinciDeviceData   *ddev = ddrv->ddev;
191      DavinciOSDLayerData *dosd = layer_data;
192 
193      D_DEBUG_AT( Davinci_OSD, "%s()\n", __FUNCTION__ );
194 
195      D_ASSERT( ddrv != NULL );
196      D_ASSERT( ddev != NULL );
197      D_ASSERT( dosd != NULL );
198 
199      ret = ioctl( ddrv->fb[OSD0].fd, FBIO_ENABLE_DISABLE_WIN, 0 );
200      if (ret)
201           D_OSDERROR( "Davinci/OSD: FBIO_ENABLE_DISABLE_WIN (fb%d - %d)!\n", OSD0, 0 );
202 
203      ret = ioctl( ddrv->fb[OSD1].fd, FBIO_ENABLE_DISABLE_WIN, 0 );
204      if (ret)
205           D_OSDERROR( "Davinci/OSD: FBIO_ENABLE_DISABLE_WIN (fb%d - %d)!\n", OSD1, 0 );
206 
207      ioctl( ddrv->fb[OSD0].fd, FBIO_WAITFORVSYNC );
208 
209      /* Update blend parameters? */
210      if (updated & (CLRCF_OPTIONS | CLRCF_OPACITY | CLRCF_SRCKEY | CLRCF_FORMAT)) {
211           vpbe_blink_option_t        blink = {0};
212           vpbe_bitmap_blend_params_t blend = {0};
213 
214           D_DEBUG_AT( Davinci_OSD, "  -> %s\n", dfb_pixelformat_name( config->format ) );
215 
216           if (config->options & DLOP_SRC_COLORKEY) {
217                blend.enable_colorkeying = 1;
218                blend.colorkey           = dfb_color_to_pixel( DSPF_RGB16,
219                                                               config->src_key.r,
220                                                               config->src_key.g,
221                                                               config->src_key.b );
222 
223                D_DEBUG_AT( Davinci_OSD, "  -> color key 0x%02x (%02x %02x %02x)\n",
224                            blend.colorkey, config->src_key.r, config->src_key.g, config->src_key.b );
225           }
226           else if (config->options & DLOP_OPACITY) {
227                blend.bf = config->opacity >> 5;
228 
229                D_DEBUG_AT( Davinci_OSD, "  -> opacity %d/7\n", blend.bf );
230           }
231           else
232                blend.bf = 7;
233 
234           ret = ioctl( ddrv->fb[OSD0].fd, FBIO_SET_BITMAP_BLEND_FACTOR, &blend );
235           if (ret)
236                D_PERROR( "Davinci/OSD: FBIO_SET_BITMAP_BLEND_FACTOR (fb%d)!\n", OSD0 );
237 
238           if (config->options & DLOP_ALPHACHANNEL)
239                dosd->alpha = DFB_PIXELFORMAT_HAS_ALPHA( config->format );
240           else
241                dosd->alpha = 0;
242 
243           D_DEBUG_AT( Davinci_OSD, "  -> %salpha channel\n", dosd->alpha ? "" : "no " );
244 
245           if (dosd->alpha) {
246                if (ioctl( ddrv->fb[OSD0].fd, FBIO_ENABLE_DISABLE_ATTRIBUTE_WIN, dosd->alpha ))
247                     D_OSDERROR( "Davinci/OSD: FBIO_ENABLE_DISABLE_ATTRIBUTE_WIN (fb%d - %d)!\n", OSD0, dosd->alpha );
248           }
249 
250           if (ioctl( ddrv->fb[OSD1].fd, FBIO_SET_BLINK_INTERVAL, &blink ))
251                D_OSDERROR( "Davinci/OSD: FBIO_SET_BLINK_INTERVAL (fb%d - disable)!\n", OSD1 );
252      }
253 
254      /* Update size? */
255      if (updated & (CLRCF_WIDTH | CLRCF_HEIGHT | CLRCF_BUFFERMODE)) {
256           vpbe_window_position_t win_pos;
257 
258           D_DEBUG_AT( Davinci_OSD, "  -> %dx%d\n", config->width, config->height );
259 
260 /*********************************** Start workaround ***********************************/
261           win_pos.xpos = 0;
262           win_pos.ypos = 0;
263 
264           ret = ioctl( ddrv->fb[OSD0].fd, FBIO_SETPOS, &win_pos );
265           if (ret)
266                D_OSDERROR( "Davinci/OSD: FBIO_SETPOS (fb%d - %d,%d) failed!\n", OSD0, win_pos.xpos, win_pos.ypos );
267 
268           ret = ioctl( ddrv->fb[OSD1].fd, FBIO_SETPOS, &win_pos );
269           if (ret)
270                D_OSDERROR( "Davinci/OSD: FBIO_SETPOS (fb%d - %d,%d) failed!\n", OSD1, win_pos.xpos, win_pos.ypos );
271 
272           updated |= CLRCF_DEST;
273 
274           dosd->var0.yoffset = dosd->var1.yoffset = 0;
275 /*********************************** End workaround ***********************************/
276 
277           /* Set width and height. */
278           dosd->var0.xres = config->width;
279           dosd->var0.yres = config->height;
280           dosd->var1.xres = config->width;
281           dosd->var1.yres = config->height;
282 
283           dosd->var0.yres_virtual = ddrv->fb[OSD0].size / ddev->fix[OSD0].line_length;
284 
285           ret = ioctl( ddrv->fb[OSD0].fd, FBIOPUT_VSCREENINFO, &dosd->var0 );
286           if (ret)
287                D_PERROR( "Davinci/OSD: FBIOPUT_VSCREENINFO (fb%d) failed!\n", OSD0 );
288 
289           ret = ioctl( ddrv->fb[OSD1].fd, FBIOPUT_VSCREENINFO, &dosd->var1 );
290           if (ret)
291                D_PERROR( "Davinci/OSD: FBIOPUT_VSCREENINFO (fb%d) failed!\n", OSD1 );
292      }
293 
294      /* Update position? */
295      if (updated & CLRCF_DEST) {
296           vpbe_window_position_t win_pos;
297 
298           D_DEBUG_AT( Davinci_OSD, "  -> %d, %d\n", config->dest.x, config->dest.y );
299 
300           /* Set horizontal and vertical offset. */
301           win_pos.xpos = config->dest.x;
302           win_pos.ypos = config->dest.y;
303 
304           ret = ioctl( ddrv->fb[OSD0].fd, FBIO_SETPOS, &win_pos );
305           if (ret)
306                D_OSDERROR( "Davinci/OSD: FBIO_SETPOS (fb%d - %d,%d) failed!\n", OSD0, config->dest.x, config->dest.y );
307 
308           ret = ioctl( ddrv->fb[OSD1].fd, FBIO_SETPOS, &win_pos );
309           if (ret)
310                D_OSDERROR( "Davinci/OSD: FBIO_SETPOS (fb%d - %d,%d) failed!\n", OSD1, config->dest.x, config->dest.y );
311      }
312 
313      davincifb_pan_display( &ddrv->fb[OSD0], &dosd->var0,
314                             (config->format == DSPF_RGB16) ? lock : NULL, DSFLIP_NONE, 0, 0 );
315 
316      ret = ioctl( ddrv->fb[OSD0].fd, FBIOGET_FSCREENINFO, &ddev->fix[OSD0] );
317      if (ret)
318           D_PERROR( "Davinci/OSD: FBIOGET_FSCREENINFO (fb%d) failed!\n", OSD0 );
319 
320      ret = ioctl( ddrv->fb[OSD1].fd, FBIOGET_FSCREENINFO, &ddev->fix[OSD1] );
321      if (ret)
322           D_PERROR( "Davinci/OSD: FBIOGET_FSCREENINFO (fb%d) failed!\n", OSD1 );
323 
324      dosd->enable = true;
325 
326      if (ioctl( ddrv->fb[OSD0].fd, FBIO_ENABLE_DISABLE_ATTRIBUTE_WIN, 0 ))
327           D_OSDERROR( "Davinci/OSD: FBIO_ENABLE_DISABLE_ATTRIBUTE_WIN (fb%d - %d)!\n", OSD0, 0 );
328 
329      return DFB_OK;
330 }
331 
332 static DFBResult
osdRemoveRegion(CoreLayer * layer,void * driver_data,void * layer_data,void * region_data)333 osdRemoveRegion( CoreLayer *layer,
334                  void      *driver_data,
335                  void      *layer_data,
336                  void      *region_data )
337 {
338      int                  ret;
339      DavinciDriverData   *ddrv = driver_data;
340      DavinciOSDLayerData *dosd = layer_data;
341 
342      D_DEBUG_AT( Davinci_OSD, "%s()\n", __FUNCTION__ );
343 
344      D_ASSERT( ddrv != NULL );
345 
346      ret = ioctl( ddrv->fb[OSD0].fd, FBIO_ENABLE_DISABLE_WIN, 0 );
347      if (ret)
348           D_OSDERROR( "Davinci/OSD: FBIO_ENABLE_DISABLE_WIN (fb%d - %d)!\n", OSD0, 0 );
349 
350      ret = ioctl( ddrv->fb[OSD1].fd, FBIO_ENABLE_DISABLE_WIN, 0 );
351      if (ret)
352           D_OSDERROR( "Davinci/OSD: FBIO_ENABLE_DISABLE_WIN (fb%d - %d)!\n", OSD1, 0 );
353 
354      dosd->enable = false;
355 
356      return DFB_OK;
357 }
358 
359 static void
update_buffers(DavinciDriverData * ddrv,DavinciDeviceData * ddev,CoreSurface * surface,CoreSurfaceBufferLock * lock,const DFBRegion * update)360 update_buffers( DavinciDriverData     *ddrv,
361                 DavinciDeviceData     *ddev,
362                 CoreSurface           *surface,
363                 CoreSurfaceBufferLock *lock,
364                 const DFBRegion       *update )
365 {
366      DFBRectangle       rect;
367      CoreSurfaceBuffer *buffer;
368 
369      D_ASSERT( ddrv != NULL );
370      D_ASSERT( ddev != NULL );
371      D_ASSERT( surface != NULL );
372      D_ASSERT( lock != NULL );
373      DFB_REGION_ASSERT_IF( update );
374 
375      buffer = lock->buffer;
376      D_ASSERT( buffer != NULL );
377 
378      if (update) {
379           rect = DFB_RECTANGLE_INIT_FROM_REGION( update );
380 
381           if (rect.x & 1) {
382                rect.x &= ~1;
383                rect.w++;
384           }
385 
386           if (rect.w & 1)
387                rect.w++;
388      }
389      else {
390           rect.x = 0;
391           rect.y = 0;
392           rect.w = surface->config.size.w;
393           rect.h = surface->config.size.h;
394      }
395 
396      /* Can we use the DSP? */
397      if (ddrv->c64x_present) {
398           int           i;
399           int           lines = ddev->fix[OSD0].line_length == ddev->fix[OSD1].line_length ? rect.h : 1;
400           unsigned long rgb   = ddev->fix[OSD0].smem_start + rect.x * 2 + rect.y * ddev->fix[OSD0].line_length;
401           unsigned long alpha = ddev->fix[OSD1].smem_start + rect.x / 2 + rect.y * ddev->fix[OSD1].line_length;
402           unsigned long src   = lock->phys                 + rect.x * 4 + rect.y * lock->pitch;
403 
404           //D_ASSUME( ddev->fix[OSD0].line_length == ddev->fix[OSD1].line_length );
405 
406           dfb_gfxcard_lock( GDLF_NONE );
407 
408           /* Dither ARGB to RGB16+A3 using the DSP. */
409           for (i=0; i<rect.h; i+=lines) {
410                if (lines > rect.h - i)
411                     lines = rect.h - i;
412 
413                davinci_c64x_dither_argb__L( &ddrv->tasks, rgb, alpha,
414                                          ddev->fix[OSD0].line_length, src, lock->pitch, rect.w, lines );
415 
416                if (ddev->fix[OSD0].line_length != ddev->fix[OSD1].line_length && lines > 1) {
417                     davinci_c64x_blit_32__L( &ddrv->tasks,
418                                           alpha + ddev->fix[OSD1].line_length, ddev->fix[OSD1].line_length,
419                                           alpha + ddev->fix[OSD0].line_length, ddev->fix[OSD0].line_length,
420                                           rect.w/2, lines - 1 );
421                }
422 
423                rgb   += lines * ddev->fix[OSD0].line_length;
424                alpha += lines * ddev->fix[OSD1].line_length;
425                src   += lines * lock->pitch;
426           }
427 
428           /* Flush the write cache. */
429           davinci_c64x_write_back_all( &ddrv->c64x );
430 
431 
432           davinci_c64x_emit_tasks( &ddrv->c64x, &ddrv->tasks, C64X_TEF_RESET );
433 
434 
435           dfb_gfxcard_unlock();
436      }
437      else {
438           u32  *src32 = lock->addr + rect.y * lock->pitch + DFB_BYTES_PER_LINE( buffer->format, rect.x );
439           int   sp4   = lock->pitch / 4;
440           u32  *dst32 = ddrv->fb[OSD0].mem + rect.y * ddev->fix[OSD0].line_length + rect.x * 2;
441           int   dp4   = ddev->fix[OSD0].line_length / 4;
442           u8   *dst8  = ddrv->fb[OSD1].mem + rect.y * ddev->fix[OSD1].line_length + rect.x / 2;
443           int   dp    = ddev->fix[OSD1].line_length;
444           int   w2    = rect.w / 2;
445           u32   z     = 0;
446 
447           switch (buffer->format) {
448                case DSPF_ARGB4444:
449                     while (rect.h--) {
450                          int x;
451 
452                          for (x=0; x<w2; x++) {
453                               dst32[x] = ((src32[x] & 0x0f000f00) << 4) | ((src32[x] & 0x08000800)     ) |
454                                          ((src32[x] & 0x00f000f0) << 3) | ((src32[x] & 0x00c000c0) >> 1) |
455                                          ((src32[x] & 0x000f000f) << 1) | ((src32[x] & 0x00080008) >> 3);
456 
457                               dst8[x] = ((src32[x] & 0xe0000000) >> 29) | ((src32[x] & 0x0000e000) >> 9);
458                          }
459 
460                          src32 += sp4;
461                          dst32 += dp4;
462                          dst8  += dp;
463                     }
464                     break;
465 
466                case DSPF_ARGB1555:
467                     while (rect.h--) {
468                          int x;
469 
470                          for (x=0; x<w2; x++) {
471                               dst32[x] = ((src32[x] & 0x7c007c00) << 1) |
472                                          ((src32[x] & 0x03e003e0) << 1) |
473                                           (src32[x] & 0x003f003f);
474 
475                               dst8[x] = ((src32[x] & 0x80000000) ? 0x70 : 0x00) |
476                                         ((src32[x] & 0x00008000) ? 0x07 : 0x00);
477                          }
478 
479                          src32 += sp4;
480                          dst32 += dp4;
481                          dst8  += dp;
482                     }
483                     break;
484 
485                case DSPF_ARGB:
486                     while (rect.h--) {
487                          int x;
488 
489                          for (x=0; x<w2; x++) {
490                               register u32 s0 = src32[(x<<1)+0];
491                               register u32 s1 = src32[(x<<1)+1];
492 
493                               dst32[x] = ((s0 & 0x00f80000) >>  8) |
494                                          ((s0 & 0x0000fc00) >>  5) |
495                                          ((s0 & 0x000000f8) >>  3) |
496                                          ((s1 & 0x00f80000) <<  8) |
497                                          ((s1 & 0x0000fc00) << 11) |
498                                          ((s1 & 0x000000f8) << 13) ;
499 
500 #ifndef DAVINCI_NO_DITHER
501                               if ((s0 & s1) >> 24 == 0xff)
502                                    dst8[x] = 0x77;
503                               else {
504                                    register int pt, da;
505 
506                                    z ^= ((z << 13) | (z >> 19));
507                                    z += 0x87654321;
508                                    pt = s0 - ((s0 & 0xf8000000) >> 3);
509                                    da = (((pt >> 29) & 0x07)  + ( ((z&0x1f) - ((pt >> 24) & 0x1f))>>31 )) << 4;
510 
511                                    z ^= ((z << 13) | (z >> 19));
512                                    z += 0x87654321;
513                                    pt = s1 - ((s1 & 0xf8000000) >> 3);
514                                    da |= (((pt >> 29) & 0x07) + ( ((z&0x1f) - ((pt >> 24) & 0x1f))>>31 ));
515 
516 
517                                    dst8[x] = da;
518                               }
519 #else
520                               dst8[x] = ((s0 & 0xe0000000) >> 25) |
521                                         ((s1 & 0xe0000000) >> 29) ;
522 #endif
523                          }
524 
525                          src32 += sp4;
526                          dst32 += dp4;
527                          dst8  += dp;
528                     }
529                     break;
530 
531                default:
532                     D_ONCE( "unsupported format" );
533           }
534      }
535 }
536 
537 static void
update_rgb(DavinciDriverData * ddrv,DavinciDeviceData * ddev,CoreSurface * surface,CoreSurfaceBufferLock * lock,const DFBRegion * update)538 update_rgb( DavinciDriverData     *ddrv,
539             DavinciDeviceData     *ddev,
540             CoreSurface           *surface,
541             CoreSurfaceBufferLock *lock,
542             const DFBRegion       *update )
543 {
544      DFBRectangle       rect;
545      CoreSurfaceBuffer *buffer;
546 
547      D_ASSERT( ddrv != NULL );
548      D_ASSERT( ddev != NULL );
549      D_ASSERT( surface != NULL );
550      D_ASSERT( lock != NULL );
551      DFB_REGION_ASSERT_IF( update );
552 
553      buffer = lock->buffer;
554      D_ASSERT( buffer != NULL );
555 
556      if (update)
557           rect = DFB_RECTANGLE_INIT_FROM_REGION( update );
558      else {
559           rect.x = 0;
560           rect.y = 0;
561           rect.w = surface->config.size.w;
562           rect.h = surface->config.size.h;
563      }
564 
565      dfb_convert_to_rgb16( buffer->format,
566                            lock->addr + rect.y * lock->pitch + DFB_BYTES_PER_LINE( buffer->format, rect.x ),
567                            lock->pitch,
568                            surface->config.size.h,
569                            ddrv->fb[OSD0].mem + rect.y * ddev->fix[OSD0].line_length + rect.x * 2,
570                            ddev->fix[OSD0].line_length,
571                            rect.w, rect.h );
572 }
573 
574 static void
enable_osd(DavinciDriverData * ddrv,DavinciOSDLayerData * dosd)575 enable_osd( DavinciDriverData   *ddrv,
576             DavinciOSDLayerData *dosd )
577 {
578      if (!dosd->enable)
579           return;
580 
581      ioctl( ddrv->fb[OSD0].fd, FBIO_WAITFORVSYNC );
582 
583      if (ioctl( ddrv->fb[OSD0].fd, FBIO_ENABLE_DISABLE_ATTRIBUTE_WIN, dosd->alpha ))
584           D_OSDERROR( "Davinci/OSD: FBIO_ENABLE_DISABLE_ATTRIBUTE_WIN (fb%d - %d)!\n", OSD0, dosd->alpha );
585 
586      if (ioctl( ddrv->fb[OSD0].fd, FBIO_ENABLE_DISABLE_WIN, 1 ))
587           D_OSDERROR( "Davinci/OSD: FBIO_ENABLE_DISABLE_WIN (fb%d - %d)!\n", OSD0, 1 );
588 
589      if (ioctl( ddrv->fb[OSD1].fd, FBIO_ENABLE_DISABLE_WIN, dosd->alpha ))
590           D_OSDERROR( "Davinci/OSD: FBIO_ENABLE_DISABLE_WIN (fb%d - %d)!\n", OSD1, dosd->alpha );
591 
592      dosd->enable = false;
593 }
594 
595 static DFBResult
osdFlipRegion(CoreLayer * layer,void * driver_data,void * layer_data,void * region_data,CoreSurface * surface,DFBSurfaceFlipFlags flags,CoreSurfaceBufferLock * lock)596 osdFlipRegion( CoreLayer             *layer,
597                void                  *driver_data,
598                void                  *layer_data,
599                void                  *region_data,
600                CoreSurface           *surface,
601                DFBSurfaceFlipFlags    flags,
602                CoreSurfaceBufferLock *lock )
603 {
604      CoreSurfaceBuffer   *buffer;
605      DavinciDriverData   *ddrv = driver_data;
606      DavinciDeviceData   *ddev = ddrv->ddev;
607      DavinciOSDLayerData *dosd = layer_data;
608 
609      D_DEBUG_AT( Davinci_OSD, "%s()\n", __FUNCTION__ );
610 
611      D_ASSERT( surface != NULL );
612      D_ASSERT( lock != NULL );
613      D_ASSERT( ddrv != NULL );
614      D_ASSERT( ddev != NULL );
615 
616      buffer = lock->buffer;
617      D_ASSERT( buffer != NULL );
618 
619      if (buffer->format != DSPF_RGB16) {
620           if (DFB_PIXELFORMAT_HAS_ALPHA( buffer->format ))
621                update_buffers( ddrv, ddev, surface, lock, NULL );
622           else
623                update_rgb( ddrv, ddev, surface, lock, NULL );
624      }
625      else
626           davincifb_pan_display( &ddrv->fb[OSD0], &dosd->var0, lock, flags, 0, 0 );
627 
628      dfb_surface_flip( surface, false );
629 
630      enable_osd( ddrv, dosd );
631 
632      return DFB_OK;
633 }
634 
635 static DFBResult
osdUpdateRegion(CoreLayer * layer,void * driver_data,void * layer_data,void * region_data,CoreSurface * surface,const DFBRegion * update,CoreSurfaceBufferLock * lock)636 osdUpdateRegion( CoreLayer             *layer,
637                  void                  *driver_data,
638                  void                  *layer_data,
639                  void                  *region_data,
640                  CoreSurface           *surface,
641                  const DFBRegion       *update,
642                  CoreSurfaceBufferLock *lock )
643 {
644      CoreSurfaceBuffer   *buffer;
645      DavinciDriverData   *ddrv = driver_data;
646      DavinciDeviceData   *ddev = ddrv->ddev;
647      DavinciOSDLayerData *dosd = layer_data;
648 
649      D_DEBUG_AT( Davinci_OSD, "%s()\n", __FUNCTION__ );
650 
651      D_ASSERT( surface != NULL );
652      D_ASSERT( lock != NULL );
653      D_ASSERT( ddrv != NULL );
654      D_ASSERT( ddev != NULL );
655 
656      buffer = lock->buffer;
657      D_ASSERT( buffer != NULL );
658 
659      if (buffer->format != DSPF_RGB16) {
660           if (DFB_PIXELFORMAT_HAS_ALPHA( buffer->format ))
661                update_buffers( ddrv, ddev, surface, lock, update );
662           else
663                update_rgb( ddrv, ddev, surface, lock, update );
664      }
665 
666      enable_osd( ddrv, dosd );
667 
668      return DFB_OK;
669 }
670 
671 const DisplayLayerFuncs davinciOSDLayerFuncs = {
672      .LayerDataSize = osdLayerDataSize,
673      .InitLayer     = osdInitLayer,
674 
675      .TestRegion    = osdTestRegion,
676      .SetRegion     = osdSetRegion,
677      .RemoveRegion  = osdRemoveRegion,
678      .FlipRegion    = osdFlipRegion,
679      .UpdateRegion  = osdUpdateRegion,
680 };
681 
682