Beispiel #1
0
DFBResult
pxa3xxEngineSync( void *drv, void *dev )
{
     DFBResult            ret    = DFB_OK;
     PXA3XXDriverData    *pdrv   = drv;
     PXA3XXGfxSharedArea *shared = pdrv->gfx_shared;

     D_DEBUG_AT( PXA3XX_BLT, "%s()\n", __FUNCTION__ );

     DUMP_INFO();

     while (shared->hw_running && ioctl( pdrv->gfx_fd, PXA3XX_GCU_IOCTL_WAIT_IDLE ) < 0) {
          if (errno == EINTR)
               continue;

          ret = errno2result( errno );
          D_PERROR( "PXA3XX/BLT: PXA3XX_GCU_IOCTL_WAIT_IDLE failed!\n" );

          direct_log_printf( NULL, "  -> %srunning, hw %d-%d, next %d-%d - %svalid\n",     \
                             pdrv->gfx_shared->hw_running ? "" : "not ",             \
                             pdrv->gfx_shared->hw_start,                             \
                             pdrv->gfx_shared->hw_end,                               \
                             pdrv->gfx_shared->next_start,                           \
                             pdrv->gfx_shared->next_end,                             \
                             pdrv->gfx_shared->next_valid ? "" : "not " );

          break;
     }

     if (ret == DFB_OK) {
          D_ASSERT( !shared->hw_running );
     }

     return ret;
}
Beispiel #2
0
/*
 * Blend a rectangle using the alpha value from the color using the current hardware state.
 */
static bool
pxa3xxBlitBlendColorAlpha( void *drv, void *dev, DFBRectangle *rect, int x, int y )
{
     PXA3XXDriverData *pdrv = drv;
     PXA3XXDeviceData *pdev = dev;
     u32              *prep = start_buffer( pdrv, 9 );

     D_DEBUG_AT( PXA3XX_BLT, "%s( %d, %d - %dx%d  -> %d, %d )\n",
                 __FUNCTION__, DFB_RECTANGLE_VALS( rect ), x, y );
     DUMP_INFO();

     prep[0] = 0x47000138;
     prep[1] = x;
     prep[2] = y;
     prep[3] = rect->x;
     prep[4] = rect->y;
     prep[5] = x;
     prep[6] = y;
     prep[7] = PXA3XX_WH( rect->w, rect->h );
     prep[8] = (pdev->color.a << 24) | (pdev->color.a << 16);

     submit_buffer( pdrv, 9 );

     return true;
}
Beispiel #3
0
static DFBResult
flush_prepared( PXA3XXDriverData *pdrv )
{
     int result;

     D_DEBUG_AT( PXA3XX_BLT, "%s()\n", __FUNCTION__ );

     DUMP_INFO();

     D_ASSERT( pdrv->prep_num < PXA3XX_GCU_BUFFER_WORDS );
     D_ASSERT( pdrv->prep_num <= D_ARRAY_SIZE(pdrv->prep_buf) );

     /* Something prepared? */
     if (pdrv->prep_num) {
          result = write( pdrv->gfx_fd, pdrv->prep_buf, pdrv->prep_num * 4 );
          if (result < 0) {
               D_PERROR( "PXA3XX/BLT: write() failed!\n" );
               return DFB_IO;
          }

          pdrv->prep_num = 0;
     }

     return DFB_OK;
}
Beispiel #4
0
static inline DFBResult
start_hardware( PXA3XXDriverData *pdrv )
{
     PXA3XXGfxSharedArea *shared = pdrv->gfx_shared;

     D_DEBUG_AT( PXA3XX_BLT, "%s()\n", __FUNCTION__ );

     DUMP_INFO();

     D_ASSERT( shared->next_valid );

     if (shared->hw_running || shared->next_end == shared->next_start)
          return DFB_FAILURE;

     shared->hw_running = true;
     shared->hw_start   = shared->next_start;
     shared->hw_end     = shared->next_end;

     shared->next_start = shared->next_end = (shared->hw_end + 63) & ~0x3f;

     shared->num_words += shared->hw_end - shared->hw_start;

     shared->num_starts++;

     DUMP_INFO();

     D_ASSERT( shared->buffer[shared->hw_end] == 0x08000000 );

#ifdef PXA3XX_GCU_REG_USE_IOCTLS
     ioctl( pdrv->gfx_fd, PXA3XX_GCU_IOCTL_START );
#else
     mb();

     PXA_GCRBLR = 0;

     PXA_GCRBBR = shared->buffer_phys + shared->hw_start*4;
     PXA_GCRBTR = shared->buffer_phys + shared->hw_end*4;
     PXA_GCRBLR = ((shared->hw_end - shared->hw_start + 63) & ~0x3f) * 4;

     mb();
#endif

     return DFB_OK;
}
Beispiel #5
0
void
pxa3xxEngineReset( void *drv, void *dev )
{
     PXA3XXDriverData *pdrv = drv;

     D_DEBUG_AT( PXA3XX_BLT, "%s()\n", __FUNCTION__ );

     DUMP_INFO();

     ioctl( pdrv->gfx_fd, PXA3XX_GCU_IOCTL_RESET );
}
Beispiel #6
0
/*
 * Render a blended rectangle using the current hardware state.
 *
 * As the hardware does not directly support this, we blit a single
 * pixel with blending.
 */
static bool
pxa3xxFillRectangleBlend( void *drv, void *dev, DFBRectangle *rect )
{
     PXA3XXDriverData *pdrv   = drv;
     PXA3XXDeviceData *pdev   = dev;
     u32              *prep   = start_buffer( pdrv, 22 );
     const u32         format = pixel_formats[DFB_PIXELFORMAT_INDEX( DSPF_ARGB )];

     D_DEBUG_AT( PXA3XX_BLT, "%s( %d, %d - %dx%d )\n", __FUNCTION__,
                 DFB_RECTANGLE_VALS( rect ) );
     DUMP_INFO();

     /* Set fake destination. */
     prep[0]  = 0x020000A2;
     prep[1]  = pdev->fake_phys;
     prep[2]  = (format << 19) | 4;

     /* Fill rectangle. */
     prep[3]  = 0x40000014 | (format << 8);
     prep[4]  = 0;
     prep[5]  = 0;
     prep[6]  = PXA3XX_WH( rect->w, 1 );
     prep[7]  = PIXEL_ARGB( pdev->color.a, pdev->color.r, pdev->color.g, pdev->color.b );

     /* Restore destination. */
     prep[8]  = 0x020000A2;
     prep[9]  = pdev->dst_phys;
     prep[10] = (pixel_formats[pdev->dst_index] << 19) | (pdev->dst_pitch << 5) | pdev->dst_bpp;

     /* Set fake buffer as source. */
     prep[11] = 0x02000002;
     prep[12] = pdev->fake_phys;
     prep[13] = (format << 19) | 4;

     /* Blit with blending. */
     prep[14] = 0x47000107;
     prep[15] = rect->x;
     prep[16] = rect->y;
     prep[17] = 0;
     prep[18] = 0;
     prep[19] = rect->x;
     prep[20] = rect->y;
     prep[21] = PXA3XX_WH( rect->w, rect->h );

     submit_buffer( pdrv, 22 );

     /* Clear the flag. */
     PXA3XX_INVALIDATE( SOURCE );

     return true;
}
Beispiel #7
0
/*
 * Render a filled rectangle using the current hardware state.
 */
static bool
pxa3xxFillRectangle( void *drv, void *dev, DFBRectangle *rect )
{
     PXA3XXDriverData *pdrv = drv;
     u32              *prep = start_buffer( pdrv, 4 );

     D_DEBUG_AT( PXA3XX_BLT, "%s( %d, %d - %dx%d )\n", __FUNCTION__,
                 DFB_RECTANGLE_VALS( rect ) );
     DUMP_INFO();

     prep[0] = 0x40000003;
     prep[1] = rect->x;
     prep[2] = rect->y;
     prep[3] = PXA3XX_WH( rect->w, rect->h );

     submit_buffer( pdrv, 4 );

     return true;
}
Beispiel #8
0
/*
 * Blit a glyph with alpha blending and colorizing using the current hardware state.
 */
static bool
pxa3xxBlitGlyph( void *drv, void *dev, DFBRectangle *rect, int x, int y )
{
     PXA3XXDriverData *pdrv   = drv;
     PXA3XXDeviceData *pdev   = dev;
     u32              *prep   = start_buffer( pdrv, 40 );
     const u32         format = pixel_formats[DFB_PIXELFORMAT_INDEX( DSPF_ARGB )];

     D_DEBUG_AT( PXA3XX_BLT, "%s( %d, %d - %dx%d )\n", __FUNCTION__,
                 DFB_RECTANGLE_VALS( rect ) );
     DUMP_INFO();

     if (rect->w * (rect->h + 1) * 4 > pdev->fake_size)
          return false;

     /* Set fake destination. */
     prep[0]  = 0x020000A2;
     prep[1]  = pdev->fake_phys;
     prep[2]  = (format << 19) | ((rect->w << 2) << 5) | 4;

     /* Fill first row of fake buffer. */
     prep[3]  = 0x40000014 | (format << 8);
     prep[4]  = 0;
     prep[5]  = 0;
     prep[6]  = PXA3XX_WH( rect->w, 1 );
     prep[7]  = PIXEL_ARGB( pdev->color.a, pdev->color.r, pdev->color.g, pdev->color.b );

     /* Set first row of fake buffer as source1. */
     prep[8]  = 0x02000012;
     prep[9]  = pdev->fake_phys;
     prep[10] = (format << 19) | 4;

     /* Blit with blending. */
     prep[11] = 0x47000118;
     prep[12] = 0;
     prep[13] = 1;
     prep[14] = rect->x;
     prep[15] = rect->y;
     prep[16] = 0;
     prep[17] = 0;
     prep[18] = PXA3XX_WH( rect->w, rect->h );
     prep[19] = 0;

     /* Restore destination. */
     prep[20] = 0x020000A2;
     prep[21] = pdev->dst_phys;
     prep[22] = (pixel_formats[pdev->dst_index] << 19) | (pdev->dst_pitch << 5) | pdev->dst_bpp;

     /* Restore source1 to destination. */
     prep[23] = 0x02000012;
     prep[24] = prep[21];
     prep[25] = prep[22];

     /* Set fake buffer as source0. */
     prep[26] = 0x02000002;
     prep[27] = pdev->fake_phys;
     prep[28] = (format << 19) | ((rect->w << 2) << 5) | 4;

     /* Blit with blending. */
     prep[29] = 0x47000107;
     prep[30] = x;
     prep[31] = y;
     prep[32] = 0;
     prep[33] = 1;
     prep[34] = x;
     prep[35] = y;
     prep[36] = PXA3XX_WH( rect->w, rect->h );

     /* Restore source0. */
     prep[37] = 0x02000002;
     prep[38] = pdev->src_phys;
     prep[39] = (pixel_formats[pdev->src_index] << 19) | (pdev->src_pitch << 5) | pdev->src_bpp;

     submit_buffer( pdrv, 40 );

     return true;
}
Beispiel #9
0
/*
 * Blit a rectangle using the current hardware state.
 */
static bool
pxa3xxBlit( void *drv, void *dev, DFBRectangle *rect, int x, int y )
{
     PXA3XXDriverData *pdrv     = drv;
     PXA3XXDeviceData *pdev     = dev;
     u32               rotation = 0;
     u32              *prep     = start_buffer( pdrv, 6 );

     D_DEBUG_AT( PXA3XX_BLT, "%s( %d, %d - %dx%d  -> %d, %d )\n",
                 __FUNCTION__, DFB_RECTANGLE_VALS( rect ), x, y );
     DUMP_INFO();

     if (pdev->bflags & DSBLIT_ROTATE90)
           rotation = 3;
     else if (pdev->bflags & DSBLIT_ROTATE180)
           rotation = 2;
     else if (pdev->bflags & DSBLIT_ROTATE270)
           rotation = 1;

     prep[0] = 0x4A000005 | (rotation << 4); // FIXME: use 32byte alignment hint
     prep[1] = x;
     prep[2] = y;
     prep[3] = rect->x;
     prep[4] = rect->y;
     prep[5] = PXA3XX_WH( rect->w, rect->h );

     submit_buffer( pdrv, 6 );

/* RASTER

     prep[0] = 0x4BCC0007;
     prep[1] = x;
     prep[2] = y;
     prep[3] = rect->x;
     prep[4] = rect->y;
     prep[5] = rect->x;
     prep[6] = rect->y;
     prep[7] = PXA3XX_WH( rect->w, rect->h );

     submit_buffer( pdrv, 8 );
 */

/* PATTERN

     prep[0] = 0x4C000006;
     prep[1] = x;
     prep[2] = y;
     prep[3] = rect->x;
     prep[4] = rect->y;
     prep[5] = PXA3XX_WH( rect->w, rect->h );
     prep[6] = PXA3XX_WH( rect->w, rect->h );

     submit_buffer( pdrv, 7 );
 */

/* BIAS

     prep[0] = 0x49000016;
     prep[1] = x;
     prep[2] = y;
     prep[3] = rect->x;
     prep[4] = rect->y;
     prep[5] = PXA3XX_WH( rect->w, rect->h );
     prep[6] = 0;

     submit_buffer( pdrv, 7 );
 */

     return true;
}
Beispiel #10
0
/*
 * Make sure that the hardware is programmed for execution of 'accel' according to the 'state'.
 */
void
pxa3xxSetState( void                *drv,
                void                *dev,
                GraphicsDeviceFuncs *funcs,
                CardState           *state,
                DFBAccelerationMask  accel )
{
     PXA3XXDriverData       *pdrv     = drv;
     PXA3XXDeviceData       *pdev     = dev;
     StateModificationFlags  modified = state->mod_hw;

     D_DEBUG_AT( PXA3XX_BLT, "%s( %p, 0x%08x ) <- modified 0x%08x\n",
                 __FUNCTION__, state, accel, modified );
     DUMP_INFO();

     /*
      * 1) Invalidate hardware states
      *
      * Each modification to the hw independent state invalidates one or more hardware states.
      */

     /* Simply invalidate all? */
     if (modified == SMF_ALL) {
          PXA3XX_INVALIDATE( ALL );
     }
     else if (modified) {
          /* Invalidate destination registers. */
          if (modified & SMF_DESTINATION)
               PXA3XX_INVALIDATE( DEST | COLOR );

          /* Invalidate source registers. */
          if (modified & SMF_SOURCE)
               PXA3XX_INVALIDATE( SOURCE );

          /* Invalidate color registers. */
          if (modified & SMF_COLOR)
               PXA3XX_INVALIDATE( COLOR );
     }

     /*
      * 2) Validate hardware states
      *
      * Each function has its own set of states that need to be validated.
      */

     /* Always requiring valid destination. */
     PXA3XX_CHECK_VALIDATE( DEST );

     /* Depending on the function... */
     switch (accel) {
          case DFXL_FILLRECTANGLE:
               /* ...require valid color. */
               PXA3XX_CHECK_VALIDATE( COLOR );

               if (state->drawingflags & DSDRAW_BLEND)
                    funcs->FillRectangle = pxa3xxFillRectangleBlend;
               else
                    funcs->FillRectangle = pxa3xxFillRectangle;

               /*
                * 3) Tell which functions can be called without further validation, i.e. SetState()
                *
                * When the hw independent state is changed, this collection is reset.
                */
               state->set = PXA3XX_SUPPORTED_DRAWINGFUNCTIONS;
               break;

          case DFXL_BLIT:
          case DFXL_STRETCHBLIT:
               /* ...require valid source. */
               PXA3XX_CHECK_VALIDATE( SOURCE );

               if (state->blittingflags & DSBLIT_BLEND_ALPHACHANNEL && pdev->src_alpha) {
                    if (state->blittingflags & DSBLIT_COLORIZE)
                         funcs->Blit = pxa3xxBlitGlyph;
                    else
                         funcs->Blit = pxa3xxBlitBlend;
               }
               else {
                    if (state->blittingflags & DSBLIT_BLEND_COLORALPHA)
                         funcs->Blit = pxa3xxBlitBlendColorAlpha;
                    else
                         funcs->Blit = pxa3xxBlit;
               }

               /*
                * 3) Tell which functions can be called without further validation, i.e. SetState()
                *
                * When the hw independent state is changed, this collection is reset.
                */
               state->set = PXA3XX_SUPPORTED_BLITTINGFUNCTIONS;
               break;

          default:
               D_BUG( "unexpected drawing/blitting function" );
               break;
     }

     pdev->dflags         = state->drawingflags;
     pdev->bflags         = state->blittingflags;
     pdev->render_options = state->render_options;
     pdev->color          = state->color;

     /*
      * 4) Clear modification flags
      *
      * All flags have been evaluated in 1) and remembered for further validation.
      * If the hw independent state is not modified, this function won't get called
      * for subsequent rendering functions, unless they aren't defined by 3).
      */
     state->mod_hw = 0;
}
Beispiel #11
0
static DFBResult
flush_prepared( PXA3XXDriverData *pdrv )
{
     PXA3XXGfxSharedArea *shared  = pdrv->gfx_shared;

     D_DEBUG_AT( PXA3XX_BLT, "%s()\n", __FUNCTION__ );

     DUMP_INFO();

     D_ASSERT( pdrv->prep_num < PXA3XX_GCU_BUFFER_WORDS );
     D_ASSERT( pdrv->prep_num <= D_ARRAY_SIZE(pdrv->prep_buf) );

     /* Something prepared? */
     while (pdrv->prep_num) {
          int timeout = 2;
          int next_end;

          /* Mark shared information as invalid. From this point on the interrupt handler
           * will not continue with the next block, and we'll start the hardware ourself. */
          shared->next_valid = false;

          mb();

          /* Check if there's enough space at the end.
           * Wait until hardware has started next block before it gets too big. */
          if (shared->next_end + pdrv->prep_num >= PXA3XX_GCU_BUFFER_WORDS ||
              shared->next_end - shared->next_start >= PXA3XX_GCU_BUFFER_WORDS/4)
          {
               /* If there's no next block waiting, start at the beginning. */
               if (shared->next_start == shared->next_end)
                    shared->next_start = shared->next_end = 0;
               else {
                    D_ASSERT( shared->buffer[shared->hw_end] == 0x08000000 );

                    /* Mark area as valid again. */
                    shared->next_valid = true;

                    mb();

                    /* Start in case it got idle while doing the checks. */
                    if (start_hardware( pdrv )) {
                         /*
                          * Hardware has not been started (still running).
                          * Check for timeout. */
                         if (!timeout--) {
                              D_ERROR( "PXA3XX/Blt: Timeout waiting for processing!\n" );
                              direct_log_printf( NULL, "  -> %srunning, hw %d-%d, next %d-%d - %svalid\n",     \
                                                 pdrv->gfx_shared->hw_running ? "" : "not ",             \
                                                 pdrv->gfx_shared->hw_start,                             \
                                                 pdrv->gfx_shared->hw_end,                               \
                                                 pdrv->gfx_shared->next_start,                           \
                                                 pdrv->gfx_shared->next_end,                             \
                                                 pdrv->gfx_shared->next_valid ? "" : "not " );
                              D_ASSERT( shared->buffer[shared->hw_end] == 0x08000000 );
//                              pxa3xxEngineReset( pdrv, pdrv->dev );

                              return DFB_TIMEOUT;
                         }

                         /* Wait til next block is started. */
                         ioctl( pdrv->gfx_fd, PXA3XX_GCU_IOCTL_WAIT_NEXT );
                    }

                    /* Start over with the checks. */
                    continue;
               }
          }

          /* We are appending in case there was already a next block. */
          next_end = shared->next_end + pdrv->prep_num;

          /* Reset the timeout counter. */
          timeout = 20;

          /* While the hardware is running... */
          while (shared->hw_running) {
               D_ASSERT( shared->buffer[shared->hw_end] == 0x08000000 );

               /* ...make sure we don't over lap with its current buffer, otherwise wait. */
               if (shared->hw_start > next_end || shared->hw_end < shared->next_start)
                    break;

               /* Check for timeout. */
               if (!timeout--) {
                    D_ERROR( "PXA3XX/Blt: Timeout waiting for space!\n" );
                    direct_log_printf( NULL, "  -> %srunning, hw %d-%d, next %d-%d - %svalid\n",     \
                                       pdrv->gfx_shared->hw_running ? "" : "not ",             \
                                       pdrv->gfx_shared->hw_start,                             \
                                       pdrv->gfx_shared->hw_end,                               \
                                       pdrv->gfx_shared->next_start,                           \
                                       pdrv->gfx_shared->next_end,                             \
                                       pdrv->gfx_shared->next_valid ? "" : "not " );
                    D_ASSERT( shared->buffer[shared->hw_end] == 0x08000000 );
//                    pxa3xxEngineReset( pdrv, pdrv->dev );

                    return DFB_TIMEOUT;
               }

               /* Wait til next block is started. */
               ioctl( pdrv->gfx_fd, PXA3XX_GCU_IOCTL_WAIT_NEXT );
          }

          /* Copy from local to shared buffer. */
          direct_memcpy( (void*) &shared->buffer[shared->next_end], &pdrv->prep_buf[0], pdrv->prep_num * sizeof(u32) );

          /* Terminate the block. */
          shared->buffer[next_end] = 0x08000000;

          /* Update next block information and mark valid. */
          shared->next_end   = next_end;

          mb();

          shared->next_valid = true;

          /* Reset local counter. */
          pdrv->prep_num = 0;

          /* Start in case it is idle. */
          return start_hardware( pdrv );
     }

     return DFB_OK;
}
Beispiel #12
0
void comm_error(uint16_t errnr, uint16_t param) {
	// FIXME: embed sender id to error number, we got dem bits
	struct { uint16_t nr, sender, arg; } x = {errnr, MY_ID, param};
	DUMP_INFO(MSG_ERR, x);
}