static void sam_show_layer()

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.
   */
}