stm32: implements ltdc frambuffer and support for ltdc layer operation

This implements the framebuffer support for the generic nuttx framebuffer
interface, (see nuttx/video/fb.h)

This also implements the interface to perform hardware accelerated layer
operation by the ltdc controller and dma2d controller later (see
nuttx/video/ltdc.h).

The following methods are supported by the ltdc interface:

- getvideoinfo
  Get video information of the layer

- getplaneinfo
  Get plane information of the layer

- getlid
  Handle specific layer identifier. This allows to detect to current layer
  state (e.g. important for layer flipping)

- setclut
  Set the layer color lookup table. Up to 256 color entries supported.

- getclut
  Get the layer color lookup table

- setcolor
  Set the default layer color. In the context of the ltdc layer this means set
  the default color outside the active area or if the layer is disabled.

- getcolor
  Get the default layer color

- setcolorkey
  Set the layer colorkey (chromakey). Colorkey is enabled by blendmode
  LTDC_BLEND_COLORKEY

- getcolorkey
  Get the layer colorkey

- setalpha
  Set the constant alpha value. If blend mode LTDC_BLEND_SRCPIXELALPHA or
  LTDC_BLEND_DESTPIXELALPHA is defined than the blended color is calculated
  by the formel:
    Cdest = Pixelalpha * Constalpha * Csrc.
  Otherwise:
    Cest = Constalpha * Csrc

- getalpha
  get the alpha value

- setblendmode
  Set the layer blendmode.
  Supported blendmodes:
    non blendmode (do not perform blend operation independent on the layers
                   alpha and colorkey)
    alpha          alpha blending (transparency)
    destpixelalpha use pixel alpha value for the top layer (Layer2)
    srcpixelalpha  use pixel alpha value for the subjacent layer (Layer1)
    colorkey       enable colorkey

- getblendmode
  Get the layer blendmode

- setarea
  Set the active layer area, the visible rectangle inside the whole layer.
  This also allows to change the position of the whole layer which is visible in
  the selected area independent on the area position.

- getarea
  Get the active layer area

- update
  Reload the layer shadow register and make changes visible. Also supports
  layer flipping.

Note! Dithering and background color are static parameter and can only changed
at build time.

Implementation details:

The implementation of ltdc interface was inspired by SDL and DirectFB.
All layer settings are shadowed before they become active (except setclut).
They are still inactive until the layer is updated. This is done by the update
method. Should clut only active after an update or not? Clut is used for drawing
while the other settings usually used for blend or blit operations. So i think
this should be the right way.

The implementation of ltdc interface was inspired by SDL and DirectFB.
All layer settings shadowed before they become active (except clut).
They are still inactive until the layer is updated. This is done by the update
call. Should clut only activated after an update or not? Clut is used for draw
operation while the other settings usually used for blend or blit operations.
So i think this should be the right way.

Deviations from the ltdc hardware implementation:

- Shadow register update of both layer (Layer1 or Layer2) is independent as long
  LTDC_UPDATE_SIM is not set. This flag allows to update both layer simultaneous.
  Otherwise only the desired layer is updated.

Layer operation:

Keep in mind, both layer are allways active (of course if both enabled by the
configuration). First the Layer 1 is blended with the background color and the
result is blended with the Layer2. To avoid blend effects, set the Layer2 in non
blend mode. This is equal to blend with alpha = 255. Enable blending of Layer2
with the background color by enable blending of Layer1 and disable the opacity
by setting the alpha value to 0.

Layer flip:

A layer flip usual mean swapping two framebuffer. So the current inactive buffer
can refreshed with data while the active framebuffer is visible. A flip
operation changes the inactive layer to the active one and vice versa.

The ltdc implementation supports layer flip. This can be done by the update call
and the flag LTDC_UPDATE_FLIP. In this case ltdc makes the inactive layer
invisible. In detail, the inactive layer is disabled and the blendmode reset.
Detection of the current layer state (e.g. active or inactive) is supported
by the getlid method combined with one of the LTDC_LAYER_* flags.
Maybe an additional method "flip" for flip operation should be added to the ltdc
interface? But this make no sence from my view if the layer is a non LTDC layer,
e.g. playing with dma2d only.

Supported and tested nuttx pixel formats:

Single Layer without LTDC interface support:
- FB_FMT_RGB8 (cmap support required)
- FB_FMT_RGB16_565
- FB_FMT_RGB24

Single Layer with LTDC interface support:
- FB_FMT_RGB8 (cmap support required)
- FB_FMT_RGB16_565
- FB_FMT_RGB24

Dual Layer with LTDC interface support:
- FB_FMT_RGB8 (cmap support required)
- FB_FMT_RGB16_565
- FB_FMT_RGB24

Why is FB_FMT_ARGB8888 missing?

Changes:
- Remove unused register debug method.

Todo:
- Add support for backlight, currently not neccessary

Did i forgot something? Take a look in the ltdc example or the interface
description (see nuttx/include/video/ltdc.h).

Thanks to Ken for the base layout. ;)

Signed-off-by: Marco Krahl <ocram.lhark@gmail.com>
This commit is contained in:
Gregory Nutt 2014-12-19 13:48:53 -06:00
parent 3ce3b168f8
commit 4ac49f514d
1 changed files with 2824 additions and 375 deletions

File diff suppressed because it is too large Load Diff