in arch/arm/src/sama5/sam_lcd.c [2455:2901]
static void sam_show_layer(struct sam_layer_s *layer,
uint32_t dispx, uint32_t dispy,
uint32_t dispw, uint32_t disph,
uint32_t imgw, uint32_t imgh)
{
struct sam_dscr_s *dscr;
uint8_t *buffer;
uintptr_t cfgaddr;
uintptr_t regaddr;
uint32_t padding = 0;
uint32_t regval;
uint32_t bytesprow;
uint32_t bytespp;
uint32_t bprow;
bool bottomup;
bool rightleft;
int lid;
DEBUGASSERT(layer && layer->dscr);
/* Windows position & size check */
if (dispx + dispw > BOARD_LCDC_WIDTH)
{
dispw = BOARD_LCDC_WIDTH - dispx;
}
if (dispy + disph > BOARD_LCDC_HEIGHT)
{
disph = BOARD_LCDC_HEIGHT - dispy;
}
if (dispw <= 0)
{
dispw = 1;
}
if (disph <= 0)
{
disph = 1;
}
if (imgw <= 0)
{
imgw = 1;
}
if (imgh <= 0)
{
imgh = 1;
}
/* Set display buffer and mode setup */
bytespp = (uint32_t)layer->bpp >> 3;
bprow = imgw * (uint32_t)layer->bpp;
bytesprow = bprow >> 3;
if ((bprow & 7) != 0)
{
bytesprow++;
}
padding = 0;
if ((bytesprow & 3) != 0)
{
padding = 4 - (bytesprow & 0x3);
}
/* Bottom-up and Right-to-left mode setup */
bottomup = (layer->flags & LCDC_FLAG_BOTTOMUP) != 0;
rightleft = (layer->flags & LCDC_FLAG_RIGHTLEFT) != 0;
/* No X mirror supported layer, no Right->Left scan */
#ifdef SAMA5_HAVE_PSTRIDE
regaddr = g_layerpstride[lid];
if (regaddr)
{
rightleft = false;
}
#endif
dscr = layer->dscr;
lid = layer->lid;
buffer = layer->framebuffer;
cfgaddr = g_layercfg[lid];
/* Normal direction: Left,Top -> Right,Down */
if ((!rightleft && !bottomup && layer->rotation == LCDC_ROT_0) ||
(rightleft && bottomup && layer->rotation == LCDC_ROT_180))
{
/* No rotation optimization */
regval = sam_getreg(cfgaddr);
regval |= LCDC_HEOCFG0_ROTDIS;
sam_putreg(cfgaddr, regval);
/* X0 ++ */
#ifdef SAMA5_HAVE_PSTRIDE
regaddr = g_layerpstride[lid];
if (regaddr)
{
sam_putreg(regaddr, 0);
}
#endif
/* Y0 ++ */
regaddr = g_layerstride[lid];
sam_putreg(regaddr, padding);
/* Pointer to Left,Top (x0,y0) */
}
/* X mirror: Right,Top -> Left,Down */
else if ((rightleft && !bottomup && layer->rotation == LCDC_ROT_0) ||
(!rightleft && bottomup && layer->rotation == LCDC_ROT_180))
{
/* No rotation optimization */
regval = sam_getreg(cfgaddr);
regval |= LCDC_HEOCFG0_ROTDIS;
sam_putreg(cfgaddr, regval);
/* X1 -- */
#ifdef SAMA5_HAVE_PSTRIDE
regaddr = g_layerpstride[lid];
if (regaddr)
{
sam_putreg(regaddr, 0 - 2*bytespp);
}
#endif
/* Y0 ++ */
regaddr = g_layerstride[lid];
sam_putreg(regaddr, 2*bytesprow + padding - 2*bytespp);
/* Pointer to Right,Top (x1,y0) */
buffer = (uint8_t *)
((uint32_t)layer->framebuffer + bytespp * (imgw - 1));
}
/* Y mirror: Left,Down -> Right,Top */
else if ((!rightleft && bottomup && layer->rotation == LCDC_ROT_0) ||
(rightleft && !bottomup && layer->rotation == LCDC_ROT_180))
{
/* No rotation optimization */
regval = sam_getreg(cfgaddr);
regval |= LCDC_HEOCFG0_ROTDIS;
sam_putreg(cfgaddr, regval);
/* X0 ++ */
#ifdef SAMA5_HAVE_PSTRIDE
regaddr = g_layerpstride[lid];
if (regaddr)
{
sam_putreg(regaddr, 0);
}
#endif
/* Y1 -- */
regaddr = g_layerstride[lid];
sam_putreg(regaddr, 0 - (2*bytesprow + padding));
/* Pointer to Left,Down (x0,y1) */
buffer = (uint8_t *)
((uintptr_t)layer->framebuffer + (bytesprow + padding) * (imgh - 1));
}
/* X,Y mirror: Right,Top -> Left,Down */
else if ((rightleft && bottomup && layer->rotation == LCDC_ROT_0) ||
(!rightleft && !bottomup && layer->rotation == LCDC_ROT_180))
{
/* No rotation optimization */
regval = sam_getreg(cfgaddr);
regval |= LCDC_HEOCFG0_ROTDIS;
sam_putreg(cfgaddr, regval);
/* X1 -- */
#ifdef SAMA5_HAVE_PSTRIDE
regaddr = g_layerpstride[lid];
if (regaddr)
{
sam_putreg(regaddr, 0 - 2*bytespp;
}
#endif
/* Y1 -- */
regaddr = g_layerstride[lid];
sam_putreg(regaddr, 0 - (2*bytespp + padding));
/* Pointer to Left,Down (x1,y1) */
buffer = (uint8_t *)
((uint32_t)layer->framebuffer +
(bytesprow + padding) * (imgh - 1) +
bytespp * (imgw - 1));
}
/* Rotate 90: Down,Left -> Top,Right (with w,h swap) */
else if ((!rightleft && !bottomup && layer->rotation == LCDC_ROT_90) ||
(rightleft && bottomup && layer->rotation == LCDC_ROT_270))
{
/* No rotation optimization */
regval = sam_getreg(cfgaddr);
regval |= LCDC_HEOCFG0_ROTDIS;
sam_putreg(cfgaddr, regval);
/* Y -- as pixels in row */
#ifdef SAMA5_HAVE_PSTRIDE
regaddr = g_layerpstride[lid];
if (regaddr)
{
sam_putreg(regaddr, 0 - (bytespp + bytesprow + padding));
}
#endif
/* X ++ as rows */
regaddr = g_layerstride[lid];
sam_putreg(regaddr, (bytesprow + padding) * (imgh - 1));
/* Pointer to Bottom,Left */
buffer = (uint8_t *)
((uint32_t)layer->framebuffer +
(bytesprow + padding) * (imgh - 1));
}
/* Rotate 270: Top,Right -> Down,Left (with w,h swap) */
else if ((!rightleft && !bottomup && layer->rotation == LCDC_ROT_270) ||
(rightleft && bottomup && layer->rotation == LCDC_ROT_90))
{
/* No rotation optimization */
regval = sam_getreg(cfgaddr);
regval |= LCDC_HEOCFG0_ROTDIS;
sam_putreg(cfgaddr, regval);
/* Y ++ as pixels in row */
#ifdef SAMA5_HAVE_PSTRIDE
regaddr = g_layerpstride[lid];
if (regaddr)
{
sam_putreg(regaddr, bytesprow + padding - bytespp);
}
#endif
/* X -- as rows */
regaddr = g_layerstride[lid];
sam_putreg(regaddr,
0 - 2 * bytespp - (bytesprow + padding) * (imgh - 1));
/* Pointer to top right */
buffer = (uint8_t *)
((uintptr_t)layer->framebuffer + bytespp * (imgw - 1));
}
/* Mirror X then Rotate 90: Down,Right -> Top,Left */
else if ((rightleft && !bottomup && layer->rotation == LCDC_ROT_90) ||
(!rightleft && bottomup && layer->rotation == LCDC_ROT_270))
{
/* No rotation optimization */
regval = sam_getreg(cfgaddr);
regval |= LCDC_HEOCFG0_ROTDIS;
sam_putreg(cfgaddr, regval);
/* Y -- as pixels in row */
#ifdef SAMA5_HAVE_PSTRIDE
regaddr = g_layerpstride[lid];
if (regaddr)
{
sam_putreg(regaddr, 0 - (bytespp + bytesprow + padding));
}
#endif
/* X -- as rows */
regaddr = g_layerstride[lid];
sam_putreg(regaddr,
0 - 2 * bytespp + (bytesprow + padding) * (imgh - 1));
/* Pointer to down right (x1,y1) */
buffer = (uint8_t *)
((uintptr_t)layer->framebuffer +
(bytesprow + padding) * (imgh - 1) +
(bytespp) * (imgw - 1));
}
/* Mirror Y then Rotate 90: Top,Left -> Down,Right */
else if ((!rightleft && bottomup && layer->rotation == 90) ||
(rightleft && !bottomup && layer->rotation == LCDC_ROT_270))
{
/* No rotation optimization */
regval = sam_getreg(cfgaddr);
regval |= LCDC_HEOCFG0_ROTDIS;
sam_putreg(cfgaddr, regval);
/* Y ++ as pixels in row */
#ifdef SAMA5_HAVE_PSTRIDE
regaddr = g_layerpstride[lid];
if (regaddr)
{
sam_putreg(regaddr, bytesprow + padding - bytespp);
}
#endif
/* X ++ as rows */
regaddr = g_layerstride[lid];
sam_putreg(regaddr, 0 - (bytesprow + padding) * (imgh - 1));
/* Pointer to top left (x0,y0) */
}
/* Configure DMA */
/* DMA is running, just add new descriptor to queue */
sam_dmasetup(lid, dscr, buffer);
/* Set layer position and size */
#ifdef SAMA5_HAVE_POSITION
regaddr = g_layerpos[lid];
if (regaddr)
{
sam_putreg(regaddr,
LCDC_HEOCFG2_XPOS(dispx) | LCDC_HEOCFG2_YPOS(dispy));
}
#endif
#ifdef SAMA5_HAVE_SIZE
regaddr = g_layersize[lid];
if (regaddr)
{
sam_putreg(regaddr,
LCDC_HEOCFG3_XSIZE(dispw - 1) |
LCDC_HEOCFG3_YSIZE(disph - 1);
}
#endif
#ifdef CONFIG_SAMA5_LCDC_HEO
/* Scaling setup */
if (lid == LCDC_HEO)
{
uint32_t srcw;
uint32_t srch;
/* Image size only used in scaling */
/* Scaling target */
if (layer->rotation == LCDC_ROT_90 || layer->rotation == LCDC_ROT_270)
{
srcw = imgh;
srch = imgw;
}
else
{
srcw = imgw;
srch = imgh;
}
sam_putreg(SAM_LCDC_HEOCFG4,
LCDC_HEOCFG4_XMEM_SIZE(srcw - 1) |
LCDC_HEOCFG4_YMEM_SIZE(srch - 1));
/* Scaled */
if (dispw != srcw || disph != srch)
{
uint16_t xfactor;
uint16_t yfactor;
xfactor = sam_scalefactor(dispw, srcw);
yfactor = sam_scalefactor(disph, srch);
sam_putreg(LCDC_HEOCFG13,
LCDC_HEOCFG13_YFACTOR(yfactor) |
LCDC_HEOCFG13_XFACTOR(xfactor) |
LCDC_HEOCFG13_SCALEN;
}
/* Disable scaling */
else
{
sam_putreg(LCDC_HEOCFG13, 0);
}
}
#endif
/* Enable DMA */
if (buffer)
{
regaddr = g_layerblend[lid];
regval = sam_getreg(regaddr);
regval |= LCDC_HEOCFG12_DMA | LCDC_HEOCFG12_OVR;
sam_putreg(regaddr, regval);
}
/* 5. Enable the relevant channel by writing one to the CHEN field of the
* CHXCHER register.
*/
regaddr = g_layerenable[lid];
sam_putreg(regaddr, LCDC_HEOCHER_UPDATE | LCDC_HEOCHER_CH);
/* 6. An interrupt may be raised if unmasked when the descriptor has been
* loaded.
*/
}