nuttx/arch/arm/src/stm32/stm32_dma2d.c

2303 lines
63 KiB
C
Raw Normal View History

/******************************************************************************
* arch/arm/src/stm32/stm32_dma2d.c
*
Defines a second interface for the dma2d controller. Controlling both LTDC and DMA2D was unpractical from the programmers view because both controllers are to different. LTDC only controls the display visibility but the DMA2D controller changes the content of the frame buffer (buffer of the layer). The main features are: 1. DMA2D interface Supports the nuttx pixel formats: - FB_FMT_RGB8 - FB_FMT_RGB24 - FB_FMT_RGB16_565 Dynamic layer allocation during runtime for the supported formats - The number of allocatable layer can be configured. Supported dma2d operation: - blit (Copy content from source to destination layer) also works with selectable area. - blend (Blend two layer and copy the result to a destination layer wich can be a third layer or one of the source layer) also works with selectable area. - fillarea (Fill a defined area of the whole layer with a specific color) As a result of that the dma2d controller can't transfer data from the core coupled memory, CCM is disabled but usable by the ccm allocator. Currently the ccm allocator is used for allocating the layer structurei only. For the dma memory (layers frame buffer) memory is allocated from heap 2 and 3. 2. LTDC interface I have changed the api for the currently non implemented operations: - blit (Copy content from a dma2d layer to an ltdc layer) also works with selectable area. - blend (Blend two dma2d layer and copy the result to a destination ltdc layer) also works with selectable area. Note! ltdc layer is a layer referenced by the ltdc interface. dma2d layer is a layer referenced by the dma2d interface. One of the most important questions for me was, How can i flexible use an ltdc layer with the dma2d interface, e.g. as source layer for dma2d operations? Get the layer id of the related dma2d layer by a special flag when using getlid() function of the ltdc interface and use the layer id to reference the specific dma2d layer by the dma2d interface. The ltdc coupled dma2d layers are predefined and can't be dynamically allocated of freed. They use the same frame buffer memory and the same color lookup table. Changes: - layer internal format of the clut table - interrupt handling for register reload (vertical vblank) instead using waiting loop - small fixes and refactoring From Marco Krahl.
2015-04-16 16:50:23 +02:00
* Copyright (C) 2014-2015 Marco Krahl. All rights reserved.
* Author: Marco Krahl <ocram.lhark@gmail.com>
*
* References:
* STM32F429 Technical Reference Manual
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************/
/******************************************************************************
* Included Files
******************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <debug.h>
Defines a second interface for the dma2d controller. Controlling both LTDC and DMA2D was unpractical from the programmers view because both controllers are to different. LTDC only controls the display visibility but the DMA2D controller changes the content of the frame buffer (buffer of the layer). The main features are: 1. DMA2D interface Supports the nuttx pixel formats: - FB_FMT_RGB8 - FB_FMT_RGB24 - FB_FMT_RGB16_565 Dynamic layer allocation during runtime for the supported formats - The number of allocatable layer can be configured. Supported dma2d operation: - blit (Copy content from source to destination layer) also works with selectable area. - blend (Blend two layer and copy the result to a destination layer wich can be a third layer or one of the source layer) also works with selectable area. - fillarea (Fill a defined area of the whole layer with a specific color) As a result of that the dma2d controller can't transfer data from the core coupled memory, CCM is disabled but usable by the ccm allocator. Currently the ccm allocator is used for allocating the layer structurei only. For the dma memory (layers frame buffer) memory is allocated from heap 2 and 3. 2. LTDC interface I have changed the api for the currently non implemented operations: - blit (Copy content from a dma2d layer to an ltdc layer) also works with selectable area. - blend (Blend two dma2d layer and copy the result to a destination ltdc layer) also works with selectable area. Note! ltdc layer is a layer referenced by the ltdc interface. dma2d layer is a layer referenced by the dma2d interface. One of the most important questions for me was, How can i flexible use an ltdc layer with the dma2d interface, e.g. as source layer for dma2d operations? Get the layer id of the related dma2d layer by a special flag when using getlid() function of the ltdc interface and use the layer id to reference the specific dma2d layer by the dma2d interface. The ltdc coupled dma2d layers are predefined and can't be dynamically allocated of freed. They use the same frame buffer memory and the same color lookup table. Changes: - layer internal format of the clut table - interrupt handling for register reload (vertical vblank) instead using waiting loop - small fixes and refactoring From Marco Krahl.
2015-04-16 16:50:23 +02:00
#include <semaphore.h>
Defines a second interface for the dma2d controller. Controlling both LTDC and DMA2D was unpractical from the programmers view because both controllers are to different. LTDC only controls the display visibility but the DMA2D controller changes the content of the frame buffer (buffer of the layer). The main features are: 1. DMA2D interface Supports the nuttx pixel formats: - FB_FMT_RGB8 - FB_FMT_RGB24 - FB_FMT_RGB16_565 Dynamic layer allocation during runtime for the supported formats - The number of allocatable layer can be configured. Supported dma2d operation: - blit (Copy content from source to destination layer) also works with selectable area. - blend (Blend two layer and copy the result to a destination layer wich can be a third layer or one of the source layer) also works with selectable area. - fillarea (Fill a defined area of the whole layer with a specific color) As a result of that the dma2d controller can't transfer data from the core coupled memory, CCM is disabled but usable by the ccm allocator. Currently the ccm allocator is used for allocating the layer structurei only. For the dma memory (layers frame buffer) memory is allocated from heap 2 and 3. 2. LTDC interface I have changed the api for the currently non implemented operations: - blit (Copy content from a dma2d layer to an ltdc layer) also works with selectable area. - blend (Blend two dma2d layer and copy the result to a destination ltdc layer) also works with selectable area. Note! ltdc layer is a layer referenced by the ltdc interface. dma2d layer is a layer referenced by the dma2d interface. One of the most important questions for me was, How can i flexible use an ltdc layer with the dma2d interface, e.g. as source layer for dma2d operations? Get the layer id of the related dma2d layer by a special flag when using getlid() function of the ltdc interface and use the layer id to reference the specific dma2d layer by the dma2d interface. The ltdc coupled dma2d layers are predefined and can't be dynamically allocated of freed. They use the same frame buffer memory and the same color lookup table. Changes: - layer internal format of the clut table - interrupt handling for register reload (vertical vblank) instead using waiting loop - small fixes and refactoring From Marco Krahl.
2015-04-16 16:50:23 +02:00
#include <nuttx/irq.h>
#include <nuttx/video/fb.h>
#include <nuttx/kmalloc.h>
Defines a second interface for the dma2d controller. Controlling both LTDC and DMA2D was unpractical from the programmers view because both controllers are to different. LTDC only controls the display visibility but the DMA2D controller changes the content of the frame buffer (buffer of the layer). The main features are: 1. DMA2D interface Supports the nuttx pixel formats: - FB_FMT_RGB8 - FB_FMT_RGB24 - FB_FMT_RGB16_565 Dynamic layer allocation during runtime for the supported formats - The number of allocatable layer can be configured. Supported dma2d operation: - blit (Copy content from source to destination layer) also works with selectable area. - blend (Blend two layer and copy the result to a destination layer wich can be a third layer or one of the source layer) also works with selectable area. - fillarea (Fill a defined area of the whole layer with a specific color) As a result of that the dma2d controller can't transfer data from the core coupled memory, CCM is disabled but usable by the ccm allocator. Currently the ccm allocator is used for allocating the layer structurei only. For the dma memory (layers frame buffer) memory is allocated from heap 2 and 3. 2. LTDC interface I have changed the api for the currently non implemented operations: - blit (Copy content from a dma2d layer to an ltdc layer) also works with selectable area. - blend (Blend two dma2d layer and copy the result to a destination ltdc layer) also works with selectable area. Note! ltdc layer is a layer referenced by the ltdc interface. dma2d layer is a layer referenced by the dma2d interface. One of the most important questions for me was, How can i flexible use an ltdc layer with the dma2d interface, e.g. as source layer for dma2d operations? Get the layer id of the related dma2d layer by a special flag when using getlid() function of the ltdc interface and use the layer id to reference the specific dma2d layer by the dma2d interface. The ltdc coupled dma2d layers are predefined and can't be dynamically allocated of freed. They use the same frame buffer memory and the same color lookup table. Changes: - layer internal format of the clut table - interrupt handling for register reload (vertical vblank) instead using waiting loop - small fixes and refactoring From Marco Krahl.
2015-04-16 16:50:23 +02:00
#include <arch/chip/dma2d.h>
#include <arch/board/board.h>
#include "up_arch.h"
#include "up_internal.h"
#include "stm32.h"
#include "chip/stm32_ltdc.h"
Defines a second interface for the dma2d controller. Controlling both LTDC and DMA2D was unpractical from the programmers view because both controllers are to different. LTDC only controls the display visibility but the DMA2D controller changes the content of the frame buffer (buffer of the layer). The main features are: 1. DMA2D interface Supports the nuttx pixel formats: - FB_FMT_RGB8 - FB_FMT_RGB24 - FB_FMT_RGB16_565 Dynamic layer allocation during runtime for the supported formats - The number of allocatable layer can be configured. Supported dma2d operation: - blit (Copy content from source to destination layer) also works with selectable area. - blend (Blend two layer and copy the result to a destination layer wich can be a third layer or one of the source layer) also works with selectable area. - fillarea (Fill a defined area of the whole layer with a specific color) As a result of that the dma2d controller can't transfer data from the core coupled memory, CCM is disabled but usable by the ccm allocator. Currently the ccm allocator is used for allocating the layer structurei only. For the dma memory (layers frame buffer) memory is allocated from heap 2 and 3. 2. LTDC interface I have changed the api for the currently non implemented operations: - blit (Copy content from a dma2d layer to an ltdc layer) also works with selectable area. - blend (Blend two dma2d layer and copy the result to a destination ltdc layer) also works with selectable area. Note! ltdc layer is a layer referenced by the ltdc interface. dma2d layer is a layer referenced by the dma2d interface. One of the most important questions for me was, How can i flexible use an ltdc layer with the dma2d interface, e.g. as source layer for dma2d operations? Get the layer id of the related dma2d layer by a special flag when using getlid() function of the ltdc interface and use the layer id to reference the specific dma2d layer by the dma2d interface. The ltdc coupled dma2d layers are predefined and can't be dynamically allocated of freed. They use the same frame buffer memory and the same color lookup table. Changes: - layer internal format of the clut table - interrupt handling for register reload (vertical vblank) instead using waiting loop - small fixes and refactoring From Marco Krahl.
2015-04-16 16:50:23 +02:00
#include "chip/stm32_dma2d.h"
#include "chip/stm32_ccm.h"
#include "stm32_dma2d.h"
/******************************************************************************
* Pre-processor Definitions
******************************************************************************/
Defines a second interface for the dma2d controller. Controlling both LTDC and DMA2D was unpractical from the programmers view because both controllers are to different. LTDC only controls the display visibility but the DMA2D controller changes the content of the frame buffer (buffer of the layer). The main features are: 1. DMA2D interface Supports the nuttx pixel formats: - FB_FMT_RGB8 - FB_FMT_RGB24 - FB_FMT_RGB16_565 Dynamic layer allocation during runtime for the supported formats - The number of allocatable layer can be configured. Supported dma2d operation: - blit (Copy content from source to destination layer) also works with selectable area. - blend (Blend two layer and copy the result to a destination layer wich can be a third layer or one of the source layer) also works with selectable area. - fillarea (Fill a defined area of the whole layer with a specific color) As a result of that the dma2d controller can't transfer data from the core coupled memory, CCM is disabled but usable by the ccm allocator. Currently the ccm allocator is used for allocating the layer structurei only. For the dma memory (layers frame buffer) memory is allocated from heap 2 and 3. 2. LTDC interface I have changed the api for the currently non implemented operations: - blit (Copy content from a dma2d layer to an ltdc layer) also works with selectable area. - blend (Blend two dma2d layer and copy the result to a destination ltdc layer) also works with selectable area. Note! ltdc layer is a layer referenced by the ltdc interface. dma2d layer is a layer referenced by the dma2d interface. One of the most important questions for me was, How can i flexible use an ltdc layer with the dma2d interface, e.g. as source layer for dma2d operations? Get the layer id of the related dma2d layer by a special flag when using getlid() function of the ltdc interface and use the layer id to reference the specific dma2d layer by the dma2d interface. The ltdc coupled dma2d layers are predefined and can't be dynamically allocated of freed. They use the same frame buffer memory and the same color lookup table. Changes: - layer internal format of the clut table - interrupt handling for register reload (vertical vblank) instead using waiting loop - small fixes and refactoring From Marco Krahl.
2015-04-16 16:50:23 +02:00
/* output, foreground and background layer */
#define DMA2D_NLAYERS 3
/* DMA2D PFC value definitions */
#define DMA2D_PF_ARGB8888 0
#define DMA2D_PF_RGB888 1
#define DMA2D_PF_RGB565 2
#define DMA2D_PF_ARGB1555 3
#define DMA2D_PF_ARGB14444 4
#define DMA2D_PF_L8 5
#define DMA2D_PF_AL44 6
#define DMA2D_PF_AL88 7
#define DMA2D_PF_L4 8
#define DMA2D_PF_A8 9
#define DMA2D_PF_A4 10
/* DMA2D blender control */
#define STM32_DMA2D_CR_MODE_BLIT DMA2D_CR_MODE(0)
#define STM32_DMA2D_CR_MODE_BLITPFC DMA2D_CR_MODE(1)
#define STM32_DMA2D_CR_MODE_BLEND DMA2D_CR_MODE(2)
#define STM32_DMA2D_CR_MODE_COLOR DMA2D_CR_MODE(3)
#define STM32_DMA2D_CR_MODE_CLEAR STM32_DMA2D_CR_MODE_COLOR
/* DMA2D PFC alpha mode */
#define STM32_DMA2D_PFCCR_AM_NONE 0
#define STM32_DMA2D_PFCCR_AM_CONST 1
#define STM32_DMA2D_PFCCR_AM_PIXEL 10
/* Only 8 bit per pixel overal supported */
#define DMA2D_PF_BYPP(n) ((n) / 8)
#define DMA2D_CLUT_SIZE STM32_LTDC_NCLUT - 1
/* Layer argb cmap conversion */
#define DMA2D_CLUT_ALPHA(n) ((uint32_t)(n) << 24)
#define DMA2D_CLUT_RED(n) ((uint32_t)(n) << 16)
#define DMA2D_CLUT_GREEN(n) ((uint32_t)(n) << 8)
#define DMA2D_CLUT_BLUE(n) ((uint32_t)(n) << 0)
#define DMA2D_CMAP_ALPHA(n) ((uint32_t)(n) >> 24)
#define DMA2D_CMAP_RED(n) ((uint32_t)(n) >> 16)
#define DMA2D_CMAP_GREEN(n) ((uint32_t)(n) >> 8)
#define DMA2D_CMAP_BLUE(n) ((uint32_t)(n) >> 0)
/* Define shadow layer for ltdc interface */
#ifdef CONFIG_STM32_LTDC_INTERFACE
# ifdef CONFIG_STM32_LTDC_L2
# define DMA2D_SHADOW_LAYER 2
# define DMA2D_SHADOW_LAYER_L1 0
# define DMA2D_SHADOW_LAYER_L2 1
# else
# define DMA2D_SHADOW_LAYER 1
# define DMA2D_SHADOW_LAYER_L1 0
# endif
# define DMA2D_LAYER_NSIZE CONFIG_STM32_DMA2D_NLAYERS + DMA2D_SHADOW_LAYER
#else
# define DMA2D_LAYER_NSIZE CONFIG_STM32_DMA2D_NLAYERS
# define DMA2D_SHADOW_LAYER 0
#endif
/* Debug option */
#ifdef CONFIG_STM32_DMA2D_REGDEBUG
# define regdbg dbg
# define regvdbg vdbg
#else
# define regdbg(x...)
# define regvdbg(x...)
#endif
/* check clut support */
#ifdef CONFIG_STM32_DMA2D_L8
# ifndef CONFIG_FB_CMAP
# error "Enable cmap to support the configured layer formats!"
# endif
#endif
/* check ccm heap allocation */
#ifndef CONFIG_STM32_CCMEXCLUDE
# error "Enable CONFIG_STM32_CCMEXCLUDE from the heap allocation"
#endif
/******************************************************************************
* Private Types
******************************************************************************/
Defines a second interface for the dma2d controller. Controlling both LTDC and DMA2D was unpractical from the programmers view because both controllers are to different. LTDC only controls the display visibility but the DMA2D controller changes the content of the frame buffer (buffer of the layer). The main features are: 1. DMA2D interface Supports the nuttx pixel formats: - FB_FMT_RGB8 - FB_FMT_RGB24 - FB_FMT_RGB16_565 Dynamic layer allocation during runtime for the supported formats - The number of allocatable layer can be configured. Supported dma2d operation: - blit (Copy content from source to destination layer) also works with selectable area. - blend (Blend two layer and copy the result to a destination layer wich can be a third layer or one of the source layer) also works with selectable area. - fillarea (Fill a defined area of the whole layer with a specific color) As a result of that the dma2d controller can't transfer data from the core coupled memory, CCM is disabled but usable by the ccm allocator. Currently the ccm allocator is used for allocating the layer structurei only. For the dma memory (layers frame buffer) memory is allocated from heap 2 and 3. 2. LTDC interface I have changed the api for the currently non implemented operations: - blit (Copy content from a dma2d layer to an ltdc layer) also works with selectable area. - blend (Blend two dma2d layer and copy the result to a destination ltdc layer) also works with selectable area. Note! ltdc layer is a layer referenced by the ltdc interface. dma2d layer is a layer referenced by the dma2d interface. One of the most important questions for me was, How can i flexible use an ltdc layer with the dma2d interface, e.g. as source layer for dma2d operations? Get the layer id of the related dma2d layer by a special flag when using getlid() function of the ltdc interface and use the layer id to reference the specific dma2d layer by the dma2d interface. The ltdc coupled dma2d layers are predefined and can't be dynamically allocated of freed. They use the same frame buffer memory and the same color lookup table. Changes: - layer internal format of the clut table - interrupt handling for register reload (vertical vblank) instead using waiting loop - small fixes and refactoring From Marco Krahl.
2015-04-16 16:50:23 +02:00
/* DMA2D General layer information */
struct stm32_dma2d_s
{
struct dma2d_layer_s dma2d; /* public dma2d interface */
/* Fixed settings */
int lid; /* Layer identifier */
struct fb_videoinfo_s vinfo; /* Layer videoinfo */
struct fb_planeinfo_s pinfo; /* Layer planeinfo */
/* Blending */
uint32_t blendmode; /* the interface blendmode */
uint8_t alpha; /* the alpha value */
/* Coloring */
#ifdef CONFIG_STM32_DMA2D_L8
uint32_t *clut; /* Color lookup table */
#endif
/* Operation */
uint8_t fmt; /* the controller pixel format */
sem_t *lock; /* Ensure mutually exclusive access */
};
#ifdef CONFIG_STM32_LTDC_INTERFACE
/* This structures provides the DMA2D layer for each LTDC layer */
struct stm32_ltdc_dma2d_s
{
struct stm32_dma2d_s dma2ddev;
#ifdef CONFIG_STM32_DMA2D_L8
FAR struct ltdc_layer_s *ltdc;
#endif
};
struct stm32_ltdc_layer_s
{
/* Layer state */
struct stm32_ltdc_dma2d_s layer[DMA2D_SHADOW_LAYER];
};
#endif
/* Interrupt handling */
struct stm32_interrupt_s
{
bool wait; /* Informs that the task is waiting for the irq */
bool handled; /* Informs that an irq was handled */
int irq; /* irq number */
sem_t *sem; /* Semaphore for waiting for irq */
};
/* This enumeration foreground and background layer supported by the dma2d
* controller
*/
enum stm32_layer_e
{
DMA2D_LAYER_LFORE = 0, /* Foreground Layer */
DMA2D_LAYER_LBACK, /* Background Layer */
DMA2D_LAYER_LOUT, /* Output Layer */
};
/* DMA2D memory address register */
static const uintptr_t stm32_mar_layer_t[DMA2D_NLAYERS] =
{
STM32_DMA2D_FGMAR,
STM32_DMA2D_BGMAR,
STM32_DMA2D_OMAR
};
/* DMA2D offset register */
static const uintptr_t stm32_or_layer_t[DMA2D_NLAYERS] =
{
STM32_DMA2D_FGOR,
STM32_DMA2D_BGOR,
STM32_DMA2D_OOR
};
/* DMA2D pfc control register */
static const uintptr_t stm32_pfccr_layer_t[DMA2D_NLAYERS] =
{
STM32_DMA2D_FGPFCCR,
STM32_DMA2D_BGPFCCR,
STM32_DMA2D_OPFCCR
};
/* DMA2D color register */
static const uintptr_t stm32_color_layer_t[DMA2D_NLAYERS] =
{
STM32_DMA2D_FGCOLR,
STM32_DMA2D_BGCOLR,
STM32_DMA2D_OCOLR
};
/* DMA2D clut memory address register */
static const uintptr_t stm32_cmar_layer_t[DMA2D_NLAYERS - 1] =
{
STM32_DMA2D_FGCMAR,
STM32_DMA2D_BGCMAR
};
/******************************************************************************
* Private Function Prototypes
******************************************************************************/
/* Private functions */
static int stm32_dma2d_pixelformat(uint8_t fmt, uint8_t *fmtmap);
static int stm32_dma2d_bpp(uint8_t fmt, uint8_t *bpp);
static void stm32_dma2d_control(uint32_t setbits, uint32_t clrbits);
static int stm32_dma2dirq(int irq, void *context);
static int stm32_dma2d_waitforirq(void);
static int stm32_dma2d_start(void);
#ifdef CONFIG_STM32_DMA2D_L8
static int stm32_dma2d_loadclut(uintptr_t reg);
#endif
static uint32_t stm32_dma2d_memaddress(FAR const struct stm32_dma2d_s *layer,
fb_coord_t xpos, fb_coord_t ypos);
static fb_coord_t stm32_dma2d_lineoffset(FAR const struct stm32_dma2d_s *layer,
FAR const struct ltdc_area_s *area);
static int stm32_dma2d_lfreelid(void);
static FAR struct stm32_dma2d_s * stm32_dma2d_lalloc(void);
static void stm32_dma2d_lfree(FAR struct stm32_dma2d_s *layer);
static void stm32_dma2d_llayerscleanup(void);
static bool stm32_dma2d_lvalidate(FAR const struct stm32_dma2d_s *layer);
static bool stm32_dma2d_lvalidatesize(FAR const struct stm32_dma2d_s *layer,
fb_coord_t xpos, fb_coord_t ypos,
FAR const struct ltdc_area_s *area);
static void stm32_dma2d_linit(FAR struct stm32_dma2d_s *layer,
int lid, uint8_t fmt);
static void stm32_dma2d_lfifo(FAR const struct stm32_dma2d_s *layer, int lid,
fb_coord_t xpos, fb_coord_t ypos,
FAR const struct ltdc_area_s *area);
static void stm32_dma2d_lcolor(FAR const struct stm32_dma2d_s *layer,
int lid, uint32_t color);
static void stm32_dma2d_llnr(FAR struct stm32_dma2d_s *layer,
FAR const struct ltdc_area_s *area);
static int stm32_dma2d_loutpfc(FAR const struct stm32_dma2d_s *layer);
static void stm32_dma2d_lpfc(FAR const struct stm32_dma2d_s *layer,
int lid, uint32_t blendmode);
/* Public functions */
static int stm32_dma2dgetvideoinfo(FAR struct dma2d_layer_s *layer,
FAR struct fb_videoinfo_s *vinfo);
static int stm32_dma2dgetplaneinfo(FAR struct dma2d_layer_s *layer, int planeno,
FAR struct fb_planeinfo_s *pinfo);
static int stm32_dma2dgetlid(FAR struct dma2d_layer_s *layer, int *lid);
#ifdef CONFIG_STM32_DMA2D_L8
static int stm32_dma2dsetclut(FAR struct dma2d_layer_s *layer,
const FAR struct fb_cmap_s *cmap);
static int stm32_dma2dgetclut(FAR struct dma2d_layer_s *layer,
FAR struct fb_cmap_s *cmap);
#endif
static int stm32_dma2dsetalpha(FAR struct dma2d_layer_s *layer, uint8_t alpha);
static int stm32_dma2dgetalpha(FAR struct dma2d_layer_s *layer, uint8_t *alpha);
static int stm32_dma2dsetblendmode(FAR struct dma2d_layer_s *layer,
uint32_t mode);
static int stm32_dma2dgetblendmode(FAR struct dma2d_layer_s *layer,
uint32_t *mode);
static int stm32_dma2dblit(FAR struct dma2d_layer_s *dest,
fb_coord_t destxpos, fb_coord_t destypos,
FAR const struct dma2d_layer_s *src,
FAR const struct ltdc_area_s *srcarea);
static int stm32_dma2dblend(FAR struct dma2d_layer_s *dest,
fb_coord_t destxpos, fb_coord_t destypos,
FAR const struct dma2d_layer_s *fore,
fb_coord_t forexpos, fb_coord_t foreypos,
FAR const struct dma2d_layer_s *back,
FAR const struct ltdc_area_s *backarea);
static int stm32_dma2dfillarea(FAR struct dma2d_layer_s *layer,
FAR const struct ltdc_area_s *area, uint32_t color);
/******************************************************************************
* Private Data
******************************************************************************/
/* Remember the layer references for alloc/deallocation */
static struct stm32_dma2d_s *g_layers[DMA2D_LAYER_NSIZE];
/* The DMA2D semaphore that enforces mutually exclusive access */
static sem_t g_lock;
#ifdef CONFIG_STM32_LTDC_INTERFACE
/* This structure provides the DMA2D layer for each LTDC layer */
static struct stm32_ltdc_layer_s g_ltdc_layer;
#endif
/* The initalized state of the driver */
static bool g_initialized;
/* Semaphore for interrupt handling */
static sem_t g_semirq;
/* This structure provides irq handling */
static struct stm32_interrupt_s g_interrupt =
{
.wait = false,
.handled = true,
.irq = STM32_IRQ_DMA2D,
.sem = &g_semirq
};
/******************************************************************************
* Public Data
******************************************************************************/
/******************************************************************************
* Private Functions
******************************************************************************/
/******************************************************************************
* Name: stm32_dma2d_control
*
* Description:
* Change the DMA2D control register
*
* Parameter:
* setbits - The bits to set
* clrbits - The bits to clear
*
****************************************************************************/
static void stm32_dma2d_control(uint32_t setbits, uint32_t clrbits)
{
uint32_t cr;
gvdbg("setbits=%08x, clrbits=%08x\n", setbits, clrbits);
cr = getreg32(STM32_DMA2D_CR);
cr &= ~clrbits;
cr |= setbits;
putreg32(cr, STM32_DMA2D_CR);
}
/****************************************************************************
* Name: stm32_dma2dirq
*
* Description:
* DMA2D interrupt handler
*
****************************************************************************/
static int stm32_dma2dirq(int irq, void *context)
{
uint32_t regval = getreg32(STM32_DMA2D_ISR);
FAR struct stm32_interrupt_s *priv = &g_interrupt;
regvdbg("irq = %d, regval = %08x\n", irq, regval);
if (regval & DMA2D_ISR_TCIF)
{
/* Transfer complete interrupt */
/* Clear the interrupt status register */
putreg32(DMA2D_IFCR_CTCIF, STM32_DMA2D_IFCR);
}
#ifdef CONFIG_STM32_DMA2D_L8
else if (regval & DMA2D_ISR_CTCIF)
{
/* CLUT transfer complete interrupt */
/* Clear the interrupt status register */
putreg32(DMA2D_IFCR_CCTCIF, STM32_DMA2D_IFCR);
}
#endif
else
{
/* Unknown irq, should not occur */
return OK;
}
/* Update the handled flag */
priv->handled = true;
/* Unlock the semaphore if locked */
if (priv->wait)
{
int ret = sem_post(priv->sem);
if (ret != OK)
{
dbg("sem_post() failed\n");
return ret;
}
}
return OK;
}
/******************************************************************************
* Name: stm32_dma2d_waitforirq
*
* Description:
* Helper waits until the dma2d irq occurs. That means that an ongoing clut
* loading or dma transfer was completed.
* Note! The caller must use this function within irqsave state.
*
* Return:
* On success OK otherwise ERROR
*
****************************************************************************/
static int stm32_dma2d_waitforirq(void)
{
FAR struct stm32_interrupt_s *priv = &g_interrupt;
/* Only waits if last enabled interrupt is currently not handled */
if (!priv->handled)
{
int ret;
/* Inform the irq handler the task is able to wait for the irq */
priv->wait = true;
ret = sem_wait(priv->sem);
/* irq or an error occurs, reset the wait flag */
priv->wait = false;
if (ret != OK)
{
dbg("sem_wait() failed\n");
return ret;
}
}
return OK;
}
#ifdef CONFIG_STM32_DMA2D_L8
/******************************************************************************
* Name: stm32_dma2d_loadclut
*
* Description:
* Starts clut loading but doesn't wait until loading is complete!
*
* Parameter:
* pfcreg - PFC control Register
*
* Return:
* On success - OK
* On error - -EINVAL
*
****************************************************************************/
static int stm32_dma2d_loadclut(uintptr_t pfcreg)
{
int ret;
uint32_t regval;
irqstate_t flags;
flags = irqsave();
ret = stm32_dma2d_waitforirq();
if (ret == OK)
{
FAR struct stm32_interrupt_s *priv = &g_interrupt;
/* Reset the handled flag */
priv->handled = false;
/* Start clut loading */
regval = getreg32(pfcreg);
regval |= DMA2D_xGPFCCR_START;
regvdbg("set regval=%08x\n", regval);
putreg32(regval, pfcreg);
regvdbg("configured regval=%08x\n", getreg32(pfcreg));
}
irqrestore(flags);
return OK;
}
#endif
/******************************************************************************
* Name: stm32_dma2d_start
*
* Description:
* Starts the dma transfer and waits until completed.
*
* Parameter:
* reg - Register to set the start
* startflag - The related flag to start the dma transfer
* irqflag - The interrupt enable flag in the DMA2D_CR register
*
****************************************************************************/
static int stm32_dma2d_start(void)
{
int ret;
irqstate_t flags;
flags = irqsave();
ret = stm32_dma2d_waitforirq();
if (ret == OK)
{
FAR struct stm32_interrupt_s *priv = &g_interrupt;
/* Reset the handled flag */
priv->handled = false;
/* Start clut loading */
stm32_dma2d_control(DMA2D_CR_START, 0);
/* wait until transfer is complete */
ret = stm32_dma2d_waitforirq();
}
irqrestore(flags);
return ret;
}
/******************************************************************************
* Name: stm32_dma2d_memaddress
*
* Description:
* Helper to calculate the layer memory address
*
* Parameter:
* layer - Reference to the common layer state structure
*
* Return:
* memory address
*
*****************************************************************************/
static uint32_t stm32_dma2d_memaddress(FAR const struct stm32_dma2d_s *layer,
fb_coord_t xpos, fb_coord_t ypos)
{
FAR const struct fb_planeinfo_s *pinfo = &layer->pinfo;
uint32_t offset;
offset = xpos * DMA2D_PF_BYPP(layer->pinfo.bpp) + layer->pinfo.stride * ypos;
gvdbg("%p\n", ((uint32_t) pinfo->fbmem) + offset);
return ((uint32_t) pinfo->fbmem) + offset;
}
/******************************************************************************
* Name: stm32_dma2d_lineoffset
*
* Description:
* Helper to calculate the layer line offset
*
* Parameter:
* layer - Reference to the common layer state structure
*
* Return:
* line offset
*
*****************************************************************************/
static fb_coord_t stm32_dma2d_lineoffset(FAR const struct stm32_dma2d_s *layer,
FAR const struct ltdc_area_s *area)
{
/* offset at the end of each line in the context to the area layer */
gvdbg("%d\n", layer->vinfo.xres - area->xres);
return layer->vinfo.xres - area->xres;
}
/******************************************************************************
* Name: stm32_dma2d_pixelformat
*
* Description:
* Helper to map to dma2d controller pixel format
*
* Parameter:
* layer - Reference to the common layer state structure
* fmt - Reference to the location to store the pixel format
*
* Return:
* On success - OK
* On error - -EINVAL
*
*****************************************************************************/
static int stm32_dma2d_pixelformat(uint8_t fmt, uint8_t *fmtmap)
{
gvdbg("fmt=%d, fmtmap=%p\n", fmt, fmtmap);
/* Map to the controller known format
*
* Not supported by NuttX:
* ARGB8888
* ARGB1555
* ARGB4444
* AL44
* AL88
* L8 (non output layer only)
* L4
* A8
* A4
*/
switch(fmt)
{
#ifdef CONFIG_STM32_DMA2D_RGB565
case FB_FMT_RGB16_565:
*fmtmap = DMA2D_PF_RGB565;
break;
#endif
#ifdef CONFIG_STM32_DMA2D_RGB888
case FB_FMT_RGB24:
*fmtmap = DMA2D_PF_RGB888;
break;
#endif
#ifdef CONFIG_STM32_DMA2D_L8
case FB_FMT_RGB8:
*fmtmap = DMA2D_PF_L8;
break;
#endif
default:
gdbg("ERROR: Returning EINVAL\n");
return -EINVAL;
}
return OK;
}
/******************************************************************************
* Name: stm32_dma2d_bpp
*
* Description:
* Helper to get the bits per pixel
*
* Parameter:
* layer - Reference to the common layer state structure
* bpp - Reference to the location to store the pixel format
*
* Return:
* On success - OK
* On error - -EINVAL
*
*****************************************************************************/
static int stm32_dma2d_bpp(uint8_t fmt, uint8_t *bpp)
{
gvdbg("fmt=%d, bpp=%p\n", fmt, bpp);
switch(fmt)
{
#ifdef CONFIG_STM32_DMA2D_RGB565
case FB_FMT_RGB16_565:
*bpp = 16;
break;
#endif
#ifdef CONFIG_STM32_DMA2D_RGB888
case FB_FMT_RGB24:
*bpp = 24;
break;
#endif
#ifdef CONFIG_STM32_DMA2D_L8
case FB_FMT_RGB8:
*bpp = 8;
break;
#endif
default:
gdbg("ERROR: Returning EINVAL\n");
return -EINVAL;
}
return OK;
}
/******************************************************************************
* Name: stm32_dma2d_lfreelid
*
* Description:
* Get a free layer id
*
* Return:
* The number of the free layer
* -1 if no free layer is available
*
******************************************************************************/
static int stm32_dma2d_lfreelid(void)
{
int n;
for (n = DMA2D_SHADOW_LAYER; n < DMA2D_LAYER_NSIZE; n++)
{
if (g_layers[n] == NULL)
{
return n;
}
}
return -1;
}
/******************************************************************************
* Name: stm32_dma2d_lalloc
*
* Description:
* Allocate a new layer structure
*
* Return:
* A new allocated layer structure or NULL on error.
*
******************************************************************************/
static FAR struct stm32_dma2d_s * stm32_dma2d_lalloc(void)
{
FAR struct stm32_dma2d_s *layer;
#ifdef HAVE_CCM_HEAP
/* First try to allocate from the ccm heap */
layer = ccm_malloc(sizeof(struct stm32_dma2d_s));
if (!layer)
{
/* Use default allocator */
layer = kmm_malloc(sizeof(struct stm32_dma2d_s));
}
#else
layer = kmm_malloc(sizeof(struct stm32_dma2d_s));
#endif
return layer;
}
/******************************************************************************
* Name: stm32_dma2d_lfree
*
* Description:
* Deallocate the dynamic allocated layer structure
*
* Input Parameters:
* A previous allocated layer structure
*
******************************************************************************/
static void stm32_dma2d_lfree(FAR struct stm32_dma2d_s *layer)
{
if (layer)
{
#ifdef HAVE_CCM_HEAP
if (((uint32_t)layer & 0xf0000000) == 0x10000000)
{
ccm_free(layer);
}
else
{
kmm_free(layer);
}
#else
kmm_free(layer);
#endif
}
}
/******************************************************************************
* Name: stm32_dma2d_llayerscleanup
*
* Description:
* Cleanup all allocated layers
*
******************************************************************************/
static void stm32_dma2d_llayerscleanup(void)
{
int n;
/* Do not uninitialize the ltdc related dma2d layer */
for (n = DMA2D_SHADOW_LAYER; n < DMA2D_LAYER_NSIZE; n++)
{
FAR struct stm32_dma2d_s *priv = g_layers[n];
if (priv)
{
kmm_free(priv->pinfo.fbmem);
stm32_dma2d_lfree(priv);
g_layers[n] = NULL;
}
}
}
/******************************************************************************
* Name: stm32_dma2d_lvalidate
*
* Description:
* Helper to validate if the layer is valid
*
* Return:
* true if validates otherwise false
*
******************************************************************************/
static inline bool stm32_dma2d_lvalidate(FAR const struct stm32_dma2d_s *layer)
{
return layer && layer->lid < DMA2D_LAYER_NSIZE;
}
/****************************************************************************
* Name: stm32_dma2d_lvalidatesize
*
* Description:
* Helper to check if area is outside the whole layer.
*
* Parameter:
* layer - Reference to the layer control structure
* xpos - The x position inside the whole layer
* ypos - The y position inside the whole layer
* area - the area inside the whole layer
*
* Return:
* true if area is inside the whole layer otherwise false
*
****************************************************************************/
static bool stm32_dma2d_lvalidatesize(FAR const struct stm32_dma2d_s *layer,
fb_coord_t xpos, fb_coord_t ypos,
FAR const struct ltdc_area_s *area)
{
return stm32_dma2d_lvalidate(layer) &&
((layer->vinfo.xres - xpos) * (layer->vinfo.yres - ypos) >=
area->xres * area->yres);
}
/******************************************************************************
* Name: stm32_dma2d_linit
*
* Description:
* Initialize the internal layer structure
*
* Parameter:
*
*
******************************************************************************/
static void stm32_dma2d_linit(FAR struct stm32_dma2d_s *layer,
int lid, uint8_t fmt)
{
FAR struct dma2d_layer_s *priv = &layer->dma2d;
gvdbg("layer=%p, lid=%d, fmt=%02x\n", layer, lid, fmt);
/* initialize the layer interface */
priv->getvideoinfo = stm32_dma2dgetvideoinfo;
priv->getplaneinfo = stm32_dma2dgetplaneinfo;
priv->getlid = stm32_dma2dgetlid;
#ifdef CONFIG_STM32_DMA2D_L8
priv->setclut = stm32_dma2dsetclut;
priv->getclut = stm32_dma2dgetclut;
#endif
priv->setalpha = stm32_dma2dsetalpha;
priv->getalpha = stm32_dma2dgetalpha;
priv->setblendmode = stm32_dma2dsetblendmode;
priv->getblendmode = stm32_dma2dgetblendmode;
priv->blit = stm32_dma2dblit;
priv->blend = stm32_dma2dblend;
priv->fillarea = stm32_dma2dfillarea;
/* Initialize the layer structure */
layer->lid = lid;
#ifdef CONFIG_STM32_DMA2D_L8
layer->clut = 0;
#endif
layer->blendmode = DMA2D_BLEND_NONE;
layer->alpha = 255;
layer->fmt = fmt;
layer->lock = &g_lock;
}
/******************************************************************************
* Name: stm32_dma2d_lfifo
*
* Description:
* Set the fifo for the foreground, background and output layer
* Configures the memory address register
* Configures the line offset register
*
* Parameter:
* layer - Reference to the common layer state structure
*
****************************************************************************/
static void stm32_dma2d_lfifo(FAR const struct stm32_dma2d_s *layer, int lid,
fb_coord_t xpos, fb_coord_t ypos,
FAR const struct ltdc_area_s *area)
{
gvdbg("layer=%p, lid=%d, xpos=%d, ypos=%d, area=%p\n",
layer, lid, xpos, ypos, area);
putreg32(stm32_dma2d_memaddress(layer, xpos, ypos), stm32_mar_layer_t[lid]);
putreg32(stm32_dma2d_lineoffset(layer, area), stm32_or_layer_t[lid]);
}
/******************************************************************************
* Name: stm32_dma2d_lcolor
*
* Description:
* Set the color for the layer
*
* Parameter:
* layer - Reference to the common layer state structure
*
****************************************************************************/
static void stm32_dma2d_lcolor(FAR const struct stm32_dma2d_s *layer,
int lid, uint32_t color)
{
gvdbg("layer=%p, lid=%d, color=%08x\n", layer, lid, color);
putreg32(color, stm32_color_layer_t[lid]);
}
/******************************************************************************
* Name: stm32_dma2d_llnr
*
* Description:
* Set the number of line register
*
* Parameter:
* layer - Reference to the common layer state structure
* area - Reference to the area to copy
*
****************************************************************************/
static void stm32_dma2d_llnr(FAR struct stm32_dma2d_s *layer,
FAR const struct ltdc_area_s *area)
{
uint32_t nlrreg;
gvdbg("pixel per line: %d, number of lines: %d\n", area->xres, area->yres);
nlrreg = getreg32(STM32_DMA2D_NLR);
nlrreg = (DMA2D_NLR_PL(area->xres)|DMA2D_NLR_NL(area->yres));
putreg32(nlrreg, STM32_DMA2D_NLR);
}
/******************************************************************************
* Name: stm32_dma2d_loutpfc
*
* Description:
* Set the output PFC control register
*
* Parameter:
* layer - Reference to the common layer state structure
*
****************************************************************************/
static int stm32_dma2d_loutpfc(FAR const struct stm32_dma2d_s *layer)
{
gvdbg("layer=%p\n", layer);
/* CLUT format isn't supported by the dma2d controller */
if (layer->fmt == DMA2D_PF_L8)
{
/* Destination layer doesn't support CLUT output */
gdbg("ERROR: Returning ENOSYS, "
"output to layer with CLUT format not supported.\n");
return -ENOSYS;
}
/* Set the mapped pixel format of source layer */
putreg32(DMA2D_OPFCCR_CM(layer->fmt), STM32_DMA2D_OPFCCR);
return OK;
}
/******************************************************************************
* Name: stm32_dma2d_lpfc
*
* Description:
* Configure foreground and background layer PFC control register
*
* Parameter:
* layer - Reference to the common layer state structure
*
****************************************************************************/
static void stm32_dma2d_lpfc(FAR const struct stm32_dma2d_s *layer,
int lid, uint32_t blendmode)
{
uint32_t pfccrreg;
gvdbg("layer=%p, lid=%d, blendmode=%08x\n", layer, lid, blendmode);
/* Set color format */
pfccrreg = DMA2D_xGPFCCR_CM(layer->fmt);
#ifdef CONFIG_STM32_DMA2D_L8
if (layer->fmt == DMA2D_PF_L8)
{
/* Load CLUT automatically */
pfccrreg |= DMA2D_xGPFCCR_START;
/* Set the CLUT color mode */
#ifndef CONFIG_FB_TRANSPARENCY
pfccrreg |= DMA2D_xGPFCCR_CCM;
#endif
/* Set CLUT size */
pfccrreg |= DMA2D_xGPFCCR_CS(DMA2D_CLUT_SIZE);
/* Set the CLUT memory address */
putreg32((uint32_t) layer->clut, stm32_cmar_layer_t[lid]);
/* Start async clut loading */
stm32_dma2d_loadclut(stm32_pfccr_layer_t[lid]);
}
#endif
if (blendmode & DMA2D_BLEND_NONE)
{
/* No blend operation */
pfccrreg |= DMA2D_xGPFCCR_AM(STM32_DMA2D_PFCCR_AM_NONE);
}
else
{
/* Set alpha value */
pfccrreg |= DMA2D_xGPFCCR_ALPHA(layer->alpha);
/* Set alpha mode */
if (layer->blendmode & DMA2D_BLEND_ALPHA)
{
/* Blend with constant alpha */
pfccrreg |= DMA2D_xGPFCCR_AM(STM32_DMA2D_PFCCR_AM_CONST);
}
else if (layer->blendmode & DMA2D_BLEND_PIXELALPHA)
{
/* Blend with pixel alpha value */
pfccrreg |= DMA2D_xGPFCCR_AM(STM32_DMA2D_PFCCR_AM_PIXEL);
}
}
putreg32(pfccrreg, stm32_pfccr_layer_t[lid]);
}
/******************************************************************************
* Public Functions
******************************************************************************/
/******************************************************************************
* Name: stm32_dma2dgetvideoinfo
*
* Description:
* Get video information about the layer
*
* Parameter:
* layer - Reference to the layer control structure
* vinfo - Reference to the video info structure
*
* Return:
* On success - OK
* On error - -EINVAL
*
******************************************************************************/
static int stm32_dma2dgetvideoinfo(FAR struct dma2d_layer_s *layer,
FAR struct fb_videoinfo_s *vinfo)
{
FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer;
gvdbg("layer=%p, vinfo=%p\n", layer, vinfo);
if (stm32_dma2d_lvalidate(priv) && vinfo)
{
sem_wait(priv->lock);
memcpy(vinfo, &priv->vinfo, sizeof(struct fb_videoinfo_s));
sem_post(priv->lock);
return OK;
}
gdbg("ERROR: Returning EINVAL\n");
return -ENOSYS;
}
/******************************************************************************
* Name: stm32_dma2dgetplaneinfo
*
* Description:
* Get plane information about the layer
*
* Parameter:
* layer - Reference to the layer control structure
* planeno - Number of the plane
* pinfo - Reference to the plane info structure
*
* Return:
* On success - OK
* On error - -EINVAL
*
******************************************************************************/
static int stm32_dma2dgetplaneinfo(FAR struct dma2d_layer_s *layer, int planeno,
FAR struct fb_planeinfo_s *pinfo)
{
FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer;
gvdbg("layer=%p, planeno=%d, pinfo=%p\n", layer, planeno, pinfo);
if (stm32_dma2d_lvalidate(priv) && pinfo && planeno == 0)
{
sem_wait(priv->lock);
memcpy(pinfo, &priv->pinfo, sizeof(struct fb_planeinfo_s));
sem_post(priv->lock);
return OK;
}
gdbg("ERROR: Returning EINVAL\n");
return -EINVAL;
}
/******************************************************************************
* Name: stm32_dma2dgetlid
*
* Description:
* Get a specific layer identifier.
*
* Parameter:
* layer - Reference to the layer structure
* lid - Reference to store the layer id
*
* Return:
* On success - OK
* On error - -EINVAL
*
******************************************************************************/
static int stm32_dma2dgetlid(FAR struct dma2d_layer_s *layer, int *lid)
{
FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer;
gvdbg("layer=%p, lid=%p\n", layer, lid);
if (stm32_dma2d_lvalidate(priv) && lid)
{
sem_wait(priv->lock);
*lid = priv->lid;
sem_post(priv->lock);
return OK;
}
gdbg("ERROR: Returning EINVAL\n");
return -EINVAL;
}
#ifdef CONFIG_STM32_DMA2D_L8
/******************************************************************************
* Name: stm32_dma2dsetclut
*
* Description:
* Configure layer clut (color lookup table).
* Non clut is defined during initializing.
*
* Parameter:
* layer - Reference to the layer structure
* cmap - color lookup table with up the 256 entries
*
* Return:
* On success - OK
* On error - -EINVAL
*
******************************************************************************/
static int stm32_dma2dsetclut(FAR struct dma2d_layer_s *layer,
const FAR struct fb_cmap_s *cmap)
{
int ret;
FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer;
gvdbg("layer=%p, cmap=%p\n", layer, cmap);
if (stm32_dma2d_lvalidate(priv) && cmap)
{
sem_wait(priv->lock);
#ifdef CONFIG_STM32_LTDC_INTERFACE
if (priv->lid < DMA2D_SHADOW_LAYER)
{
/* Update the shared color lookup table.
*
* Background:
*
* We share the same memory region of the clut table with the LTDC
* driver. (see stm32_dma2dinitltdc). This is important because any
* changes to the framebuffer and color lookup table by the ltdc
* related dma2d layer should also effects to the ltdc visibility,
* except operation settings, alpha and blendmode.
*
* But we can not only update the clut memory region. The LTDC driver
* also must update they own LTDC clut register to make the changes
* visible. Using the LTDC interface to update the clut table will
* also update the clut table of the related dma2d layer.
*/
FAR struct ltdc_layer_s *ltdc =
g_ltdc_layer.layer[DMA2D_SHADOW_LAYER_L1].ltdc;
ret = ltdc->setclut(ltdc, cmap);
sem_post(priv->lock);
return ret;
}
#endif
if (priv->fmt != DMA2D_PF_L8)
{
gdbg("Error: CLUT is not supported for the pixel format: %d\n",
priv->vinfo.fmt);
ret = -EINVAL;
}
else if (cmap->first >= STM32_DMA2D_NCLUT)
{
gdbg("Error: only %d color table entries supported\n",
STM32_DMA2D_NCLUT);
ret = -EINVAL;
}
else
{
uint32_t *clut;
int n;
clut = priv->clut;
for (n = cmap->first; n < cmap->len && n < STM32_DMA2D_NCLUT; n++)
{
/* Update the layer clut entry */
#ifndef CONFIG_FB_TRANSPARENCY
uint8_t *clut888 = (uint8_t*)clut;
uint16_t offset = 3 * n;
clut888[offset] = cmap->blue[n];
clut888[offset + 1] = cmap->green[n];
clut888[offset + 2] = cmap->red[n];
regvdbg("n=%d, red=%02x, green=%02x, blue=%02x\n", n,
clut888[offset], clut888[offset + 1],
clut888[offset + 2]);
#else
clut[n] = (uint32_t)DMA2D_CLUT_RED(cmap->transp[n]) |
(uint32_t)DMA2D_CLUT_GREEN(cmap->red[n]) |
(uint32_t)DMA2D_CLUT_GREEN(cmap->green[n]) |
(uint32_t)DMA2D_CLUT_BLUE(cmap->blue[n]);
regvdbg("n=%d, alpha=%02x, red=%02x, green=%02x, blue=%02x\n", n,
DMA2D_CLUT_ALPHA(cmap->alpha[n]),
DMA2D_CLUT_RED(cmap->red[n]),
DMA2D_CLUT_GREEN(cmap->green[n]),
DMA2D_CLUT_BLUE(cmap->blue[n]));
#endif
}
ret = OK;
}
sem_post(priv->lock);
return ret;
}
gdbg("ERROR: Returning EINVAL\n");
return -EINVAL;
}
/******************************************************************************
* Name: stm32_dma2dgetclut
*
* Description:
* Get configured layer clut (color lookup table).
*
* Parameter:
* layer - Reference to the layer structure
* cmap - Reference to valid color lookup table accept up the 256 color
* entries
*
* Return:
* On success - OK
* On error - -EINVAL
*
******************************************************************************/
static int stm32_dma2dgetclut(FAR struct dma2d_layer_s *layer,
FAR struct fb_cmap_s *cmap)
{
int ret;
FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer;
gvdbg("layer=%p, cmap=%p\n", layer, cmap);
if (stm32_dma2d_lvalidate(priv) && cmap)
{
sem_wait(priv->lock);
if (priv->fmt != DMA2D_PF_L8)
{
gdbg("Error: CLUT is not supported for the pixel format: %d\n",
priv->vinfo.fmt);
ret = -EINVAL;
}
else if (cmap->first >= STM32_DMA2D_NCLUT)
{
gdbg("Error: only %d color table entries supported\n",
STM32_DMA2D_NCLUT);
ret = -EINVAL;
}
else
{
/* Copy from the layer clut */
uint32_t *clut;
int n;
clut = priv->clut;
for (n = cmap->first; n < cmap->len && n < STM32_DMA2D_NCLUT; n++)
{
#ifndef CONFIG_FB_TRANSPARENCY
uint8_t *clut888 = (uint8_t*)clut;
uint16_t offset = 3 * n;
cmap->blue[n] = clut888[offset];
cmap->green[n] = clut888[offset + 1];
cmap->red[n] = clut888[offset + 2];
regvdbg("n=%d, red=%02x, green=%02x, blue=%02x\n", n,
clut888[offset], clut888[offset + 1],
clut888[offset + 2]);
#else
cmap->transp[n] = (uint8_t)DMA2D_CMAP_ALPHA(clut[n]);
cmap->red[n] = (uint8_t)DMA2D_CMAP_RED(clut[n]);
cmap->green[n] = (uint8_t)DMA2D_CMAP_GREEN(clut[n]);
cmap->blue[n] = (uint8_t)DMA2D_CMAP_BLUE(clut[n]);
regvdbg("n=%d, alpha=%02x, red=%02x, green=%02x, blue=%02x\n", n,
DMA2D_CMAP_ALPHA(clut[n]), DMA2D_CMAP_RED(clut[n]),
DMA2D_CMAP_GREEN(clut[n]), DMA2D_CMAP_BLUE(clut[n]));
#endif
}
ret = OK;
}
sem_post(priv->lock);
return ret;
}
gdbg("ERROR: Returning EINVAL\n");
return -EINVAL;
}
#endif
/******************************************************************************
* Name: stm32_dma2dsetalpha
*
* Description:
* Configure layer alpha value factor into blend operation.
* During the layer blend operation the source alpha value is multiplied
* with this alpha value. If the source color format doesn't support alpha
* channel (e.g. non ARGB8888) this alpha value will be used as constant
* alpha value for blend operation.
* Default value during initializing: 0xff
*
* Parameter:
* layer - Reference to the layer structure
* alpha - Alpha value
*
* Return:
* On success - OK
* On error - -EINVAL
*
******************************************************************************/
static int stm32_dma2dsetalpha(FAR struct dma2d_layer_s *layer, uint8_t alpha)
{
FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer;
gvdbg("layer=%p, alpha=%02x\n", layer, alpha);
if (stm32_dma2d_lvalidate(priv))
{
sem_wait(priv->lock);
priv->alpha = alpha;
sem_post(priv->lock);
return OK;
}
gdbg("ERROR: Returning EINVAL\n");
return -EINVAL;
}
/******************************************************************************
Defines a second interface for the dma2d controller. Controlling both LTDC and DMA2D was unpractical from the programmers view because both controllers are to different. LTDC only controls the display visibility but the DMA2D controller changes the content of the frame buffer (buffer of the layer). The main features are: 1. DMA2D interface Supports the nuttx pixel formats: - FB_FMT_RGB8 - FB_FMT_RGB24 - FB_FMT_RGB16_565 Dynamic layer allocation during runtime for the supported formats - The number of allocatable layer can be configured. Supported dma2d operation: - blit (Copy content from source to destination layer) also works with selectable area. - blend (Blend two layer and copy the result to a destination layer wich can be a third layer or one of the source layer) also works with selectable area. - fillarea (Fill a defined area of the whole layer with a specific color) As a result of that the dma2d controller can't transfer data from the core coupled memory, CCM is disabled but usable by the ccm allocator. Currently the ccm allocator is used for allocating the layer structurei only. For the dma memory (layers frame buffer) memory is allocated from heap 2 and 3. 2. LTDC interface I have changed the api for the currently non implemented operations: - blit (Copy content from a dma2d layer to an ltdc layer) also works with selectable area. - blend (Blend two dma2d layer and copy the result to a destination ltdc layer) also works with selectable area. Note! ltdc layer is a layer referenced by the ltdc interface. dma2d layer is a layer referenced by the dma2d interface. One of the most important questions for me was, How can i flexible use an ltdc layer with the dma2d interface, e.g. as source layer for dma2d operations? Get the layer id of the related dma2d layer by a special flag when using getlid() function of the ltdc interface and use the layer id to reference the specific dma2d layer by the dma2d interface. The ltdc coupled dma2d layers are predefined and can't be dynamically allocated of freed. They use the same frame buffer memory and the same color lookup table. Changes: - layer internal format of the clut table - interrupt handling for register reload (vertical vblank) instead using waiting loop - small fixes and refactoring From Marco Krahl.
2015-04-16 16:50:23 +02:00
* Name: stm32_dma2dgetalpha
*
* Description:
* Get configured layer alpha value factor for blend operation.
*
* Parameter:
* layer - Reference to the layer structure
* alpha - Reference to store the alpha value
*
* Return:
* On success - OK
* On error - -EINVAL
*
*****************************************************************************/
Defines a second interface for the dma2d controller. Controlling both LTDC and DMA2D was unpractical from the programmers view because both controllers are to different. LTDC only controls the display visibility but the DMA2D controller changes the content of the frame buffer (buffer of the layer). The main features are: 1. DMA2D interface Supports the nuttx pixel formats: - FB_FMT_RGB8 - FB_FMT_RGB24 - FB_FMT_RGB16_565 Dynamic layer allocation during runtime for the supported formats - The number of allocatable layer can be configured. Supported dma2d operation: - blit (Copy content from source to destination layer) also works with selectable area. - blend (Blend two layer and copy the result to a destination layer wich can be a third layer or one of the source layer) also works with selectable area. - fillarea (Fill a defined area of the whole layer with a specific color) As a result of that the dma2d controller can't transfer data from the core coupled memory, CCM is disabled but usable by the ccm allocator. Currently the ccm allocator is used for allocating the layer structurei only. For the dma memory (layers frame buffer) memory is allocated from heap 2 and 3. 2. LTDC interface I have changed the api for the currently non implemented operations: - blit (Copy content from a dma2d layer to an ltdc layer) also works with selectable area. - blend (Blend two dma2d layer and copy the result to a destination ltdc layer) also works with selectable area. Note! ltdc layer is a layer referenced by the ltdc interface. dma2d layer is a layer referenced by the dma2d interface. One of the most important questions for me was, How can i flexible use an ltdc layer with the dma2d interface, e.g. as source layer for dma2d operations? Get the layer id of the related dma2d layer by a special flag when using getlid() function of the ltdc interface and use the layer id to reference the specific dma2d layer by the dma2d interface. The ltdc coupled dma2d layers are predefined and can't be dynamically allocated of freed. They use the same frame buffer memory and the same color lookup table. Changes: - layer internal format of the clut table - interrupt handling for register reload (vertical vblank) instead using waiting loop - small fixes and refactoring From Marco Krahl.
2015-04-16 16:50:23 +02:00
static int stm32_dma2dgetalpha(FAR struct dma2d_layer_s *layer, uint8_t *alpha)
{
FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer;
Defines a second interface for the dma2d controller. Controlling both LTDC and DMA2D was unpractical from the programmers view because both controllers are to different. LTDC only controls the display visibility but the DMA2D controller changes the content of the frame buffer (buffer of the layer). The main features are: 1. DMA2D interface Supports the nuttx pixel formats: - FB_FMT_RGB8 - FB_FMT_RGB24 - FB_FMT_RGB16_565 Dynamic layer allocation during runtime for the supported formats - The number of allocatable layer can be configured. Supported dma2d operation: - blit (Copy content from source to destination layer) also works with selectable area. - blend (Blend two layer and copy the result to a destination layer wich can be a third layer or one of the source layer) also works with selectable area. - fillarea (Fill a defined area of the whole layer with a specific color) As a result of that the dma2d controller can't transfer data from the core coupled memory, CCM is disabled but usable by the ccm allocator. Currently the ccm allocator is used for allocating the layer structurei only. For the dma memory (layers frame buffer) memory is allocated from heap 2 and 3. 2. LTDC interface I have changed the api for the currently non implemented operations: - blit (Copy content from a dma2d layer to an ltdc layer) also works with selectable area. - blend (Blend two dma2d layer and copy the result to a destination ltdc layer) also works with selectable area. Note! ltdc layer is a layer referenced by the ltdc interface. dma2d layer is a layer referenced by the dma2d interface. One of the most important questions for me was, How can i flexible use an ltdc layer with the dma2d interface, e.g. as source layer for dma2d operations? Get the layer id of the related dma2d layer by a special flag when using getlid() function of the ltdc interface and use the layer id to reference the specific dma2d layer by the dma2d interface. The ltdc coupled dma2d layers are predefined and can't be dynamically allocated of freed. They use the same frame buffer memory and the same color lookup table. Changes: - layer internal format of the clut table - interrupt handling for register reload (vertical vblank) instead using waiting loop - small fixes and refactoring From Marco Krahl.
2015-04-16 16:50:23 +02:00
gvdbg("layer=%p, alpha=%p\n", layer, alpha);
if (stm32_dma2d_lvalidate(priv))
{
sem_wait(priv->lock);
*alpha = priv->alpha;
sem_post(priv->lock);
return OK;
}
gdbg("ERROR: Returning EINVAL\n");
return -EINVAL;
}
/******************************************************************************
Defines a second interface for the dma2d controller. Controlling both LTDC and DMA2D was unpractical from the programmers view because both controllers are to different. LTDC only controls the display visibility but the DMA2D controller changes the content of the frame buffer (buffer of the layer). The main features are: 1. DMA2D interface Supports the nuttx pixel formats: - FB_FMT_RGB8 - FB_FMT_RGB24 - FB_FMT_RGB16_565 Dynamic layer allocation during runtime for the supported formats - The number of allocatable layer can be configured. Supported dma2d operation: - blit (Copy content from source to destination layer) also works with selectable area. - blend (Blend two layer and copy the result to a destination layer wich can be a third layer or one of the source layer) also works with selectable area. - fillarea (Fill a defined area of the whole layer with a specific color) As a result of that the dma2d controller can't transfer data from the core coupled memory, CCM is disabled but usable by the ccm allocator. Currently the ccm allocator is used for allocating the layer structurei only. For the dma memory (layers frame buffer) memory is allocated from heap 2 and 3. 2. LTDC interface I have changed the api for the currently non implemented operations: - blit (Copy content from a dma2d layer to an ltdc layer) also works with selectable area. - blend (Blend two dma2d layer and copy the result to a destination ltdc layer) also works with selectable area. Note! ltdc layer is a layer referenced by the ltdc interface. dma2d layer is a layer referenced by the dma2d interface. One of the most important questions for me was, How can i flexible use an ltdc layer with the dma2d interface, e.g. as source layer for dma2d operations? Get the layer id of the related dma2d layer by a special flag when using getlid() function of the ltdc interface and use the layer id to reference the specific dma2d layer by the dma2d interface. The ltdc coupled dma2d layers are predefined and can't be dynamically allocated of freed. They use the same frame buffer memory and the same color lookup table. Changes: - layer internal format of the clut table - interrupt handling for register reload (vertical vblank) instead using waiting loop - small fixes and refactoring From Marco Krahl.
2015-04-16 16:50:23 +02:00
* Name: stm32_dma2dsetblendmode
*
* Description:
* Configure blend mode of the layer.
* Default mode during initializing: DMA2D_BLEND_NONE
* Blendmode is active after next update.
*
* Parameter:
* layer - Reference to the layer structure
* mode - Blend mode (see DMA2D_BLEND_*)
*
* Return:
* On success - OK
* On error - -EINVAL
*
* Procedure information:
* DMA2D_BLEND_NONE:
* Informs the driver to disable all blend operation for the given layer.
* That means the layer is opaque.
*
* DMA2D_BLEND_ALPHA:
* Informs the driver to enable alpha blending for the given layer.
*
* DMA2D_BLEND_PIXELALPHA:
* Informs the driver to use the pixel alpha value of the layer instead
* the constant alpha value. This is only useful for ARGB8888
* color format.
*
******************************************************************************/
Defines a second interface for the dma2d controller. Controlling both LTDC and DMA2D was unpractical from the programmers view because both controllers are to different. LTDC only controls the display visibility but the DMA2D controller changes the content of the frame buffer (buffer of the layer). The main features are: 1. DMA2D interface Supports the nuttx pixel formats: - FB_FMT_RGB8 - FB_FMT_RGB24 - FB_FMT_RGB16_565 Dynamic layer allocation during runtime for the supported formats - The number of allocatable layer can be configured. Supported dma2d operation: - blit (Copy content from source to destination layer) also works with selectable area. - blend (Blend two layer and copy the result to a destination layer wich can be a third layer or one of the source layer) also works with selectable area. - fillarea (Fill a defined area of the whole layer with a specific color) As a result of that the dma2d controller can't transfer data from the core coupled memory, CCM is disabled but usable by the ccm allocator. Currently the ccm allocator is used for allocating the layer structurei only. For the dma memory (layers frame buffer) memory is allocated from heap 2 and 3. 2. LTDC interface I have changed the api for the currently non implemented operations: - blit (Copy content from a dma2d layer to an ltdc layer) also works with selectable area. - blend (Blend two dma2d layer and copy the result to a destination ltdc layer) also works with selectable area. Note! ltdc layer is a layer referenced by the ltdc interface. dma2d layer is a layer referenced by the dma2d interface. One of the most important questions for me was, How can i flexible use an ltdc layer with the dma2d interface, e.g. as source layer for dma2d operations? Get the layer id of the related dma2d layer by a special flag when using getlid() function of the ltdc interface and use the layer id to reference the specific dma2d layer by the dma2d interface. The ltdc coupled dma2d layers are predefined and can't be dynamically allocated of freed. They use the same frame buffer memory and the same color lookup table. Changes: - layer internal format of the clut table - interrupt handling for register reload (vertical vblank) instead using waiting loop - small fixes and refactoring From Marco Krahl.
2015-04-16 16:50:23 +02:00
static int stm32_dma2dsetblendmode(FAR struct dma2d_layer_s *layer,
uint32_t mode)
{
FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer;
gvdbg("layer=%p, mode=%08x\n", layer, mode);
if (stm32_dma2d_lvalidate(priv))
{
sem_wait(priv->lock);
priv->blendmode = mode;
sem_post(priv->lock);
return OK;
}
gdbg("ERROR: Returning EINVAL\n");
return -EINVAL;
}
/******************************************************************************
Defines a second interface for the dma2d controller. Controlling both LTDC and DMA2D was unpractical from the programmers view because both controllers are to different. LTDC only controls the display visibility but the DMA2D controller changes the content of the frame buffer (buffer of the layer). The main features are: 1. DMA2D interface Supports the nuttx pixel formats: - FB_FMT_RGB8 - FB_FMT_RGB24 - FB_FMT_RGB16_565 Dynamic layer allocation during runtime for the supported formats - The number of allocatable layer can be configured. Supported dma2d operation: - blit (Copy content from source to destination layer) also works with selectable area. - blend (Blend two layer and copy the result to a destination layer wich can be a third layer or one of the source layer) also works with selectable area. - fillarea (Fill a defined area of the whole layer with a specific color) As a result of that the dma2d controller can't transfer data from the core coupled memory, CCM is disabled but usable by the ccm allocator. Currently the ccm allocator is used for allocating the layer structurei only. For the dma memory (layers frame buffer) memory is allocated from heap 2 and 3. 2. LTDC interface I have changed the api for the currently non implemented operations: - blit (Copy content from a dma2d layer to an ltdc layer) also works with selectable area. - blend (Blend two dma2d layer and copy the result to a destination ltdc layer) also works with selectable area. Note! ltdc layer is a layer referenced by the ltdc interface. dma2d layer is a layer referenced by the dma2d interface. One of the most important questions for me was, How can i flexible use an ltdc layer with the dma2d interface, e.g. as source layer for dma2d operations? Get the layer id of the related dma2d layer by a special flag when using getlid() function of the ltdc interface and use the layer id to reference the specific dma2d layer by the dma2d interface. The ltdc coupled dma2d layers are predefined and can't be dynamically allocated of freed. They use the same frame buffer memory and the same color lookup table. Changes: - layer internal format of the clut table - interrupt handling for register reload (vertical vblank) instead using waiting loop - small fixes and refactoring From Marco Krahl.
2015-04-16 16:50:23 +02:00
* Name: stm32_getblendmode
*
* Description:
* Get configured blend mode of the layer.
*
* Parameter:
* layer - Reference to the layer structure
* mode - Reference to store the blend mode
*
* Return:
* On success - OK
* On error - -EINVAL
*
*****************************************************************************/
static int stm32_dma2dgetblendmode(FAR struct dma2d_layer_s *layer,
uint32_t *mode)
{
FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer;
gvdbg("layer=%p, mode=%p\n", layer, mode);
if (stm32_dma2d_lvalidate(priv) && mode)
{
sem_wait(priv->lock);
*mode = priv->blendmode;
sem_post(priv->lock);
return OK;
}
gdbg("ERROR: Returning EINVAL\n");
return -EINVAL;
}
/******************************************************************************
* Name: stm32_dma2dblit
*
* Description:
Defines a second interface for the dma2d controller. Controlling both LTDC and DMA2D was unpractical from the programmers view because both controllers are to different. LTDC only controls the display visibility but the DMA2D controller changes the content of the frame buffer (buffer of the layer). The main features are: 1. DMA2D interface Supports the nuttx pixel formats: - FB_FMT_RGB8 - FB_FMT_RGB24 - FB_FMT_RGB16_565 Dynamic layer allocation during runtime for the supported formats - The number of allocatable layer can be configured. Supported dma2d operation: - blit (Copy content from source to destination layer) also works with selectable area. - blend (Blend two layer and copy the result to a destination layer wich can be a third layer or one of the source layer) also works with selectable area. - fillarea (Fill a defined area of the whole layer with a specific color) As a result of that the dma2d controller can't transfer data from the core coupled memory, CCM is disabled but usable by the ccm allocator. Currently the ccm allocator is used for allocating the layer structurei only. For the dma memory (layers frame buffer) memory is allocated from heap 2 and 3. 2. LTDC interface I have changed the api for the currently non implemented operations: - blit (Copy content from a dma2d layer to an ltdc layer) also works with selectable area. - blend (Blend two dma2d layer and copy the result to a destination ltdc layer) also works with selectable area. Note! ltdc layer is a layer referenced by the ltdc interface. dma2d layer is a layer referenced by the dma2d interface. One of the most important questions for me was, How can i flexible use an ltdc layer with the dma2d interface, e.g. as source layer for dma2d operations? Get the layer id of the related dma2d layer by a special flag when using getlid() function of the ltdc interface and use the layer id to reference the specific dma2d layer by the dma2d interface. The ltdc coupled dma2d layers are predefined and can't be dynamically allocated of freed. They use the same frame buffer memory and the same color lookup table. Changes: - layer internal format of the clut table - interrupt handling for register reload (vertical vblank) instead using waiting loop - small fixes and refactoring From Marco Krahl.
2015-04-16 16:50:23 +02:00
* Copy selected area from a source layer to selected position of the
* destination layer.
*
* Parameter:
* dest - Valid reference to the destination layer
Defines a second interface for the dma2d controller. Controlling both LTDC and DMA2D was unpractical from the programmers view because both controllers are to different. LTDC only controls the display visibility but the DMA2D controller changes the content of the frame buffer (buffer of the layer). The main features are: 1. DMA2D interface Supports the nuttx pixel formats: - FB_FMT_RGB8 - FB_FMT_RGB24 - FB_FMT_RGB16_565 Dynamic layer allocation during runtime for the supported formats - The number of allocatable layer can be configured. Supported dma2d operation: - blit (Copy content from source to destination layer) also works with selectable area. - blend (Blend two layer and copy the result to a destination layer wich can be a third layer or one of the source layer) also works with selectable area. - fillarea (Fill a defined area of the whole layer with a specific color) As a result of that the dma2d controller can't transfer data from the core coupled memory, CCM is disabled but usable by the ccm allocator. Currently the ccm allocator is used for allocating the layer structurei only. For the dma memory (layers frame buffer) memory is allocated from heap 2 and 3. 2. LTDC interface I have changed the api for the currently non implemented operations: - blit (Copy content from a dma2d layer to an ltdc layer) also works with selectable area. - blend (Blend two dma2d layer and copy the result to a destination ltdc layer) also works with selectable area. Note! ltdc layer is a layer referenced by the ltdc interface. dma2d layer is a layer referenced by the dma2d interface. One of the most important questions for me was, How can i flexible use an ltdc layer with the dma2d interface, e.g. as source layer for dma2d operations? Get the layer id of the related dma2d layer by a special flag when using getlid() function of the ltdc interface and use the layer id to reference the specific dma2d layer by the dma2d interface. The ltdc coupled dma2d layers are predefined and can't be dynamically allocated of freed. They use the same frame buffer memory and the same color lookup table. Changes: - layer internal format of the clut table - interrupt handling for register reload (vertical vblank) instead using waiting loop - small fixes and refactoring From Marco Krahl.
2015-04-16 16:50:23 +02:00
* destxpos - Valid selected x position of the destination layer
* destypos - Valid selected y position of the destination layer
* src - Valid reference to the source layer
* srcarea - Valid reference to the selected area of the source layer
*
* Return:
Defines a second interface for the dma2d controller. Controlling both LTDC and DMA2D was unpractical from the programmers view because both controllers are to different. LTDC only controls the display visibility but the DMA2D controller changes the content of the frame buffer (buffer of the layer). The main features are: 1. DMA2D interface Supports the nuttx pixel formats: - FB_FMT_RGB8 - FB_FMT_RGB24 - FB_FMT_RGB16_565 Dynamic layer allocation during runtime for the supported formats - The number of allocatable layer can be configured. Supported dma2d operation: - blit (Copy content from source to destination layer) also works with selectable area. - blend (Blend two layer and copy the result to a destination layer wich can be a third layer or one of the source layer) also works with selectable area. - fillarea (Fill a defined area of the whole layer with a specific color) As a result of that the dma2d controller can't transfer data from the core coupled memory, CCM is disabled but usable by the ccm allocator. Currently the ccm allocator is used for allocating the layer structurei only. For the dma memory (layers frame buffer) memory is allocated from heap 2 and 3. 2. LTDC interface I have changed the api for the currently non implemented operations: - blit (Copy content from a dma2d layer to an ltdc layer) also works with selectable area. - blend (Blend two dma2d layer and copy the result to a destination ltdc layer) also works with selectable area. Note! ltdc layer is a layer referenced by the ltdc interface. dma2d layer is a layer referenced by the dma2d interface. One of the most important questions for me was, How can i flexible use an ltdc layer with the dma2d interface, e.g. as source layer for dma2d operations? Get the layer id of the related dma2d layer by a special flag when using getlid() function of the ltdc interface and use the layer id to reference the specific dma2d layer by the dma2d interface. The ltdc coupled dma2d layers are predefined and can't be dynamically allocated of freed. They use the same frame buffer memory and the same color lookup table. Changes: - layer internal format of the clut table - interrupt handling for register reload (vertical vblank) instead using waiting loop - small fixes and refactoring From Marco Krahl.
2015-04-16 16:50:23 +02:00
* OK - On success
* -EINVAL - If one of the parameter invalid or if the size of the selected
* source area outside the visible area of the destination layer.
* (The visible area usually represents the display size)
* -ECANCELED - Operation cancelled, something goes wrong.
*
****************************************************************************/
Defines a second interface for the dma2d controller. Controlling both LTDC and DMA2D was unpractical from the programmers view because both controllers are to different. LTDC only controls the display visibility but the DMA2D controller changes the content of the frame buffer (buffer of the layer). The main features are: 1. DMA2D interface Supports the nuttx pixel formats: - FB_FMT_RGB8 - FB_FMT_RGB24 - FB_FMT_RGB16_565 Dynamic layer allocation during runtime for the supported formats - The number of allocatable layer can be configured. Supported dma2d operation: - blit (Copy content from source to destination layer) also works with selectable area. - blend (Blend two layer and copy the result to a destination layer wich can be a third layer or one of the source layer) also works with selectable area. - fillarea (Fill a defined area of the whole layer with a specific color) As a result of that the dma2d controller can't transfer data from the core coupled memory, CCM is disabled but usable by the ccm allocator. Currently the ccm allocator is used for allocating the layer structurei only. For the dma memory (layers frame buffer) memory is allocated from heap 2 and 3. 2. LTDC interface I have changed the api for the currently non implemented operations: - blit (Copy content from a dma2d layer to an ltdc layer) also works with selectable area. - blend (Blend two dma2d layer and copy the result to a destination ltdc layer) also works with selectable area. Note! ltdc layer is a layer referenced by the ltdc interface. dma2d layer is a layer referenced by the dma2d interface. One of the most important questions for me was, How can i flexible use an ltdc layer with the dma2d interface, e.g. as source layer for dma2d operations? Get the layer id of the related dma2d layer by a special flag when using getlid() function of the ltdc interface and use the layer id to reference the specific dma2d layer by the dma2d interface. The ltdc coupled dma2d layers are predefined and can't be dynamically allocated of freed. They use the same frame buffer memory and the same color lookup table. Changes: - layer internal format of the clut table - interrupt handling for register reload (vertical vblank) instead using waiting loop - small fixes and refactoring From Marco Krahl.
2015-04-16 16:50:23 +02:00
static int stm32_dma2dblit(FAR struct dma2d_layer_s *dest,
fb_coord_t destxpos, fb_coord_t destypos,
FAR const struct dma2d_layer_s *src,
FAR const struct ltdc_area_s *srcarea)
{
Defines a second interface for the dma2d controller. Controlling both LTDC and DMA2D was unpractical from the programmers view because both controllers are to different. LTDC only controls the display visibility but the DMA2D controller changes the content of the frame buffer (buffer of the layer). The main features are: 1. DMA2D interface Supports the nuttx pixel formats: - FB_FMT_RGB8 - FB_FMT_RGB24 - FB_FMT_RGB16_565 Dynamic layer allocation during runtime for the supported formats - The number of allocatable layer can be configured. Supported dma2d operation: - blit (Copy content from source to destination layer) also works with selectable area. - blend (Blend two layer and copy the result to a destination layer wich can be a third layer or one of the source layer) also works with selectable area. - fillarea (Fill a defined area of the whole layer with a specific color) As a result of that the dma2d controller can't transfer data from the core coupled memory, CCM is disabled but usable by the ccm allocator. Currently the ccm allocator is used for allocating the layer structurei only. For the dma memory (layers frame buffer) memory is allocated from heap 2 and 3. 2. LTDC interface I have changed the api for the currently non implemented operations: - blit (Copy content from a dma2d layer to an ltdc layer) also works with selectable area. - blend (Blend two dma2d layer and copy the result to a destination ltdc layer) also works with selectable area. Note! ltdc layer is a layer referenced by the ltdc interface. dma2d layer is a layer referenced by the dma2d interface. One of the most important questions for me was, How can i flexible use an ltdc layer with the dma2d interface, e.g. as source layer for dma2d operations? Get the layer id of the related dma2d layer by a special flag when using getlid() function of the ltdc interface and use the layer id to reference the specific dma2d layer by the dma2d interface. The ltdc coupled dma2d layers are predefined and can't be dynamically allocated of freed. They use the same frame buffer memory and the same color lookup table. Changes: - layer internal format of the clut table - interrupt handling for register reload (vertical vblank) instead using waiting loop - small fixes and refactoring From Marco Krahl.
2015-04-16 16:50:23 +02:00
uint32_t mode;
int ret;
FAR struct stm32_dma2d_s * destlayer = (FAR struct stm32_dma2d_s *)dest;
FAR struct stm32_dma2d_s * srclayer = (FAR struct stm32_dma2d_s *)src;
gvdbg("dest=%p, destxpos=%d, destypos=%d, src=%p, srcarea=%p\n",
dest, destxpos, destypos, src, srcarea);
if (stm32_dma2d_lvalidatesize(destlayer, destxpos, destypos, srcarea) &&
stm32_dma2d_lvalidatesize(srclayer, srcarea->xpos,
srcarea->ypos, srcarea))
{
sem_wait(destlayer->lock);
/* Set output pfc */
ret = stm32_dma2d_loutpfc(destlayer);
if (ret == OK)
{
/* Set foreground pfc */
stm32_dma2d_lpfc(srclayer, DMA2D_LAYER_LFORE, DMA2D_BLEND_NONE);
/* Set foreground fifo */
stm32_dma2d_lfifo(srclayer, DMA2D_LAYER_LFORE,
srcarea->xpos, srcarea->ypos, srcarea);
/* Set output fifo */
stm32_dma2d_lfifo(destlayer, DMA2D_LAYER_LOUT,
destxpos, destypos, srcarea);
/* Set number of lines and pixel per line */
stm32_dma2d_llnr(destlayer, srcarea);
/* Set dma2d mode for blit operation */
if (destlayer->fmt == srclayer->fmt)
{
/* Blit without pfc */
mode = STM32_DMA2D_CR_MODE_BLIT;
}
else
{
/* Blit with pfc */
mode = STM32_DMA2D_CR_MODE_BLITPFC;
}
stm32_dma2d_control(mode, STM32_DMA2D_CR_MODE_CLEAR);
/* Start DMA2D and wait until completed */
ret = stm32_dma2d_start();
if (ret != OK)
{
ret = -ECANCELED;
gdbg("ERROR: Returning ECANCELED\n");
}
}
sem_post(destlayer->lock);
}
else
{
ret = -EINVAL;
gdbg("ERROR: Returning EINVAL\n");
}
return ret;
}
/****************************************************************************
* Name: stm32_dma2dblend
*
* Description:
Defines a second interface for the dma2d controller. Controlling both LTDC and DMA2D was unpractical from the programmers view because both controllers are to different. LTDC only controls the display visibility but the DMA2D controller changes the content of the frame buffer (buffer of the layer). The main features are: 1. DMA2D interface Supports the nuttx pixel formats: - FB_FMT_RGB8 - FB_FMT_RGB24 - FB_FMT_RGB16_565 Dynamic layer allocation during runtime for the supported formats - The number of allocatable layer can be configured. Supported dma2d operation: - blit (Copy content from source to destination layer) also works with selectable area. - blend (Blend two layer and copy the result to a destination layer wich can be a third layer or one of the source layer) also works with selectable area. - fillarea (Fill a defined area of the whole layer with a specific color) As a result of that the dma2d controller can't transfer data from the core coupled memory, CCM is disabled but usable by the ccm allocator. Currently the ccm allocator is used for allocating the layer structurei only. For the dma memory (layers frame buffer) memory is allocated from heap 2 and 3. 2. LTDC interface I have changed the api for the currently non implemented operations: - blit (Copy content from a dma2d layer to an ltdc layer) also works with selectable area. - blend (Blend two dma2d layer and copy the result to a destination ltdc layer) also works with selectable area. Note! ltdc layer is a layer referenced by the ltdc interface. dma2d layer is a layer referenced by the dma2d interface. One of the most important questions for me was, How can i flexible use an ltdc layer with the dma2d interface, e.g. as source layer for dma2d operations? Get the layer id of the related dma2d layer by a special flag when using getlid() function of the ltdc interface and use the layer id to reference the specific dma2d layer by the dma2d interface. The ltdc coupled dma2d layers are predefined and can't be dynamically allocated of freed. They use the same frame buffer memory and the same color lookup table. Changes: - layer internal format of the clut table - interrupt handling for register reload (vertical vblank) instead using waiting loop - small fixes and refactoring From Marco Krahl.
2015-04-16 16:50:23 +02:00
* Blends the selected area from a background layer with selected position
* of the foreground layer. Copies the result to the selected position of
* the destination layer. Note! The content of the foreground and background
* layer keeps unchanged as long destination layer is unequal to the
* foreground and background layer.
*
* Parameter:
Defines a second interface for the dma2d controller. Controlling both LTDC and DMA2D was unpractical from the programmers view because both controllers are to different. LTDC only controls the display visibility but the DMA2D controller changes the content of the frame buffer (buffer of the layer). The main features are: 1. DMA2D interface Supports the nuttx pixel formats: - FB_FMT_RGB8 - FB_FMT_RGB24 - FB_FMT_RGB16_565 Dynamic layer allocation during runtime for the supported formats - The number of allocatable layer can be configured. Supported dma2d operation: - blit (Copy content from source to destination layer) also works with selectable area. - blend (Blend two layer and copy the result to a destination layer wich can be a third layer or one of the source layer) also works with selectable area. - fillarea (Fill a defined area of the whole layer with a specific color) As a result of that the dma2d controller can't transfer data from the core coupled memory, CCM is disabled but usable by the ccm allocator. Currently the ccm allocator is used for allocating the layer structurei only. For the dma memory (layers frame buffer) memory is allocated from heap 2 and 3. 2. LTDC interface I have changed the api for the currently non implemented operations: - blit (Copy content from a dma2d layer to an ltdc layer) also works with selectable area. - blend (Blend two dma2d layer and copy the result to a destination ltdc layer) also works with selectable area. Note! ltdc layer is a layer referenced by the ltdc interface. dma2d layer is a layer referenced by the dma2d interface. One of the most important questions for me was, How can i flexible use an ltdc layer with the dma2d interface, e.g. as source layer for dma2d operations? Get the layer id of the related dma2d layer by a special flag when using getlid() function of the ltdc interface and use the layer id to reference the specific dma2d layer by the dma2d interface. The ltdc coupled dma2d layers are predefined and can't be dynamically allocated of freed. They use the same frame buffer memory and the same color lookup table. Changes: - layer internal format of the clut table - interrupt handling for register reload (vertical vblank) instead using waiting loop - small fixes and refactoring From Marco Krahl.
2015-04-16 16:50:23 +02:00
* dest - Reference to the destination layer
* fore - Reference to the foreground layer
* forexpos - Selected x target position of the foreground layer
* foreypos - Selected y target position of the foreground layer
* back - Reference to the background layer
* backarea - Reference to the selected area of the background layer
*
* Return:
Defines a second interface for the dma2d controller. Controlling both LTDC and DMA2D was unpractical from the programmers view because both controllers are to different. LTDC only controls the display visibility but the DMA2D controller changes the content of the frame buffer (buffer of the layer). The main features are: 1. DMA2D interface Supports the nuttx pixel formats: - FB_FMT_RGB8 - FB_FMT_RGB24 - FB_FMT_RGB16_565 Dynamic layer allocation during runtime for the supported formats - The number of allocatable layer can be configured. Supported dma2d operation: - blit (Copy content from source to destination layer) also works with selectable area. - blend (Blend two layer and copy the result to a destination layer wich can be a third layer or one of the source layer) also works with selectable area. - fillarea (Fill a defined area of the whole layer with a specific color) As a result of that the dma2d controller can't transfer data from the core coupled memory, CCM is disabled but usable by the ccm allocator. Currently the ccm allocator is used for allocating the layer structurei only. For the dma memory (layers frame buffer) memory is allocated from heap 2 and 3. 2. LTDC interface I have changed the api for the currently non implemented operations: - blit (Copy content from a dma2d layer to an ltdc layer) also works with selectable area. - blend (Blend two dma2d layer and copy the result to a destination ltdc layer) also works with selectable area. Note! ltdc layer is a layer referenced by the ltdc interface. dma2d layer is a layer referenced by the dma2d interface. One of the most important questions for me was, How can i flexible use an ltdc layer with the dma2d interface, e.g. as source layer for dma2d operations? Get the layer id of the related dma2d layer by a special flag when using getlid() function of the ltdc interface and use the layer id to reference the specific dma2d layer by the dma2d interface. The ltdc coupled dma2d layers are predefined and can't be dynamically allocated of freed. They use the same frame buffer memory and the same color lookup table. Changes: - layer internal format of the clut table - interrupt handling for register reload (vertical vblank) instead using waiting loop - small fixes and refactoring From Marco Krahl.
2015-04-16 16:50:23 +02:00
* OK - On success
* -EINVAL - If one of the parameter invalid or if the size of the selected
* source area outside the visible area of the destination layer.
* (The visible area usually represents the display size)
* -ECANCELED - Operation cancelled, something goes wrong.
*
****************************************************************************/
Defines a second interface for the dma2d controller. Controlling both LTDC and DMA2D was unpractical from the programmers view because both controllers are to different. LTDC only controls the display visibility but the DMA2D controller changes the content of the frame buffer (buffer of the layer). The main features are: 1. DMA2D interface Supports the nuttx pixel formats: - FB_FMT_RGB8 - FB_FMT_RGB24 - FB_FMT_RGB16_565 Dynamic layer allocation during runtime for the supported formats - The number of allocatable layer can be configured. Supported dma2d operation: - blit (Copy content from source to destination layer) also works with selectable area. - blend (Blend two layer and copy the result to a destination layer wich can be a third layer or one of the source layer) also works with selectable area. - fillarea (Fill a defined area of the whole layer with a specific color) As a result of that the dma2d controller can't transfer data from the core coupled memory, CCM is disabled but usable by the ccm allocator. Currently the ccm allocator is used for allocating the layer structurei only. For the dma memory (layers frame buffer) memory is allocated from heap 2 and 3. 2. LTDC interface I have changed the api for the currently non implemented operations: - blit (Copy content from a dma2d layer to an ltdc layer) also works with selectable area. - blend (Blend two dma2d layer and copy the result to a destination ltdc layer) also works with selectable area. Note! ltdc layer is a layer referenced by the ltdc interface. dma2d layer is a layer referenced by the dma2d interface. One of the most important questions for me was, How can i flexible use an ltdc layer with the dma2d interface, e.g. as source layer for dma2d operations? Get the layer id of the related dma2d layer by a special flag when using getlid() function of the ltdc interface and use the layer id to reference the specific dma2d layer by the dma2d interface. The ltdc coupled dma2d layers are predefined and can't be dynamically allocated of freed. They use the same frame buffer memory and the same color lookup table. Changes: - layer internal format of the clut table - interrupt handling for register reload (vertical vblank) instead using waiting loop - small fixes and refactoring From Marco Krahl.
2015-04-16 16:50:23 +02:00
static int stm32_dma2dblend(FAR struct dma2d_layer_s *dest,
fb_coord_t destxpos, fb_coord_t destypos,
FAR const struct dma2d_layer_s *fore,
fb_coord_t forexpos, fb_coord_t foreypos,
FAR const struct dma2d_layer_s *back,
FAR const struct ltdc_area_s *backarea)
{
Defines a second interface for the dma2d controller. Controlling both LTDC and DMA2D was unpractical from the programmers view because both controllers are to different. LTDC only controls the display visibility but the DMA2D controller changes the content of the frame buffer (buffer of the layer). The main features are: 1. DMA2D interface Supports the nuttx pixel formats: - FB_FMT_RGB8 - FB_FMT_RGB24 - FB_FMT_RGB16_565 Dynamic layer allocation during runtime for the supported formats - The number of allocatable layer can be configured. Supported dma2d operation: - blit (Copy content from source to destination layer) also works with selectable area. - blend (Blend two layer and copy the result to a destination layer wich can be a third layer or one of the source layer) also works with selectable area. - fillarea (Fill a defined area of the whole layer with a specific color) As a result of that the dma2d controller can't transfer data from the core coupled memory, CCM is disabled but usable by the ccm allocator. Currently the ccm allocator is used for allocating the layer structurei only. For the dma memory (layers frame buffer) memory is allocated from heap 2 and 3. 2. LTDC interface I have changed the api for the currently non implemented operations: - blit (Copy content from a dma2d layer to an ltdc layer) also works with selectable area. - blend (Blend two dma2d layer and copy the result to a destination ltdc layer) also works with selectable area. Note! ltdc layer is a layer referenced by the ltdc interface. dma2d layer is a layer referenced by the dma2d interface. One of the most important questions for me was, How can i flexible use an ltdc layer with the dma2d interface, e.g. as source layer for dma2d operations? Get the layer id of the related dma2d layer by a special flag when using getlid() function of the ltdc interface and use the layer id to reference the specific dma2d layer by the dma2d interface. The ltdc coupled dma2d layers are predefined and can't be dynamically allocated of freed. They use the same frame buffer memory and the same color lookup table. Changes: - layer internal format of the clut table - interrupt handling for register reload (vertical vblank) instead using waiting loop - small fixes and refactoring From Marco Krahl.
2015-04-16 16:50:23 +02:00
int ret;
FAR struct stm32_dma2d_s * destlayer = (FAR struct stm32_dma2d_s *)dest;
FAR struct stm32_dma2d_s * forelayer = (FAR struct stm32_dma2d_s *)fore;
FAR struct stm32_dma2d_s * backlayer = (FAR struct stm32_dma2d_s *)back;
gvdbg("dest=%p, destxpos=%d, destypos=%d, "
"fore=%p, forexpos=%d, foreypos=%d, "
"back=%p, backarea=%p\n",
dest, destxpos, destypos, fore, forexpos, foreypos, back, backarea);
if (stm32_dma2d_lvalidatesize(destlayer, destxpos, destypos, backarea) &&
stm32_dma2d_lvalidatesize(forelayer, forexpos, foreypos, backarea) &&
stm32_dma2d_lvalidatesize(backlayer, backarea->xpos,
backarea->ypos, backarea))
{
sem_wait(destlayer->lock);
/* Set output pfc */
ret = stm32_dma2d_loutpfc(destlayer);
if (ret == OK)
{
/* Set background pfc */
stm32_dma2d_lpfc(backlayer, DMA2D_LAYER_LBACK, backlayer->blendmode);
/* Set foreground pfc */
stm32_dma2d_lpfc(forelayer, DMA2D_LAYER_LFORE, forelayer->blendmode);
/* Set background fifo */
stm32_dma2d_lfifo(backlayer, DMA2D_LAYER_LBACK,
backarea->xpos, backarea->ypos, backarea);
/* Set foreground fifo */
stm32_dma2d_lfifo(forelayer, DMA2D_LAYER_LFORE,
forexpos, foreypos, backarea);
/* Set output fifo */
stm32_dma2d_lfifo(destlayer, DMA2D_LAYER_LOUT,
destxpos, destypos, backarea);
/* Set number of lines and pixel per line */
stm32_dma2d_llnr(destlayer, backarea);
/* Set watermark */
/* Enable DMA2D blender */
stm32_dma2d_control(STM32_DMA2D_CR_MODE_BLEND,
STM32_DMA2D_CR_MODE_CLEAR);
/* Start DMA2D and wait until completed */
ret = stm32_dma2d_start();
if (ret != OK)
{
ret = -ECANCELED;
gdbg("ERROR: Returning ECANCELED\n");
}
}
sem_post(destlayer->lock);
}
else
{
ret = -EINVAL;
gdbg("ERROR: Returning EINVAL\n");
}
return ret;
}
/****************************************************************************
* Name: stm32_dma2dfillarea
*
* Description:
* Fill the selected area of the whole layer with a specific color.
*
* Parameter:
* layer - Reference to the layer structure
* area - Reference to the valid area structure select the area
* color - Color to fill the selected area. Color must be formatted
* according to the layer pixel format.
*
* Return:
* OK - On success
* -EINVAL - If one of the parameter invalid or if the size of the selected
* area outside the visible area of the layer.
* -ECANCELED - Operation cancelled, something goes wrong.
*
****************************************************************************/
static int stm32_dma2dfillarea(FAR struct dma2d_layer_s *layer,
FAR const struct ltdc_area_s *area,
uint32_t color)
{
int ret;
FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer;
gvdbg("layer=%p, area=%p, color=%08x\n", layer, area, color);
if (stm32_dma2d_lvalidatesize(priv, area->xpos, area->ypos, area))
{
sem_wait(priv->lock);
/* Set output pfc */
ret = stm32_dma2d_loutpfc(priv);
if (ret == OK)
{
/* Set output fifo */
stm32_dma2d_lfifo(priv, DMA2D_LAYER_LOUT,
area->xpos, area->ypos, area);
/* Set the output color register */
stm32_dma2d_lcolor(priv, DMA2D_LAYER_LOUT, color);
/* Set number of lines and pixel per line */
stm32_dma2d_llnr(priv, area);
/* Set register to memory transfer */
stm32_dma2d_control(STM32_DMA2D_CR_MODE_COLOR,
STM32_DMA2D_CR_MODE_CLEAR);
/* Start DMA2D and wait until completed */
ret = stm32_dma2d_start();
if (ret != OK)
{
ret = -ECANCELED;
gdbg("ERROR: Returning ECANCELED\n");
}
}
sem_post(priv->lock);
}
else
{
ret = -EINVAL;
gdbg("ERROR: Returning EINVAL\n");
}
return ret;
}
/*******************************************************************************
* Name: up_dma2dgetlayer
*
* Description:
* Get a dma2d layer structure by the layer identifier
*
* Parameter:
* lid - Layer identifier
*
* Return:
* Reference to the dma2d layer control structure on success or Null if no
* related exist.
*
******************************************************************************/
FAR struct dma2d_layer_s * up_dma2dgetlayer(int lid)
{
if (lid < DMA2D_LAYER_NSIZE)
{
FAR struct stm32_dma2d_s *priv;
sem_wait(&g_lock);
priv = g_layers[lid];
sem_post(&g_lock);
return &priv->dma2d;
}
gdbg("ERROR: EINVAL, Unknown layer identifier\n");
errno = EINVAL;
return NULL;
}
/******************************************************************************
* Name: up_dma2dcreatelayer
*
* Description:
* Create a new dma2d layer object to interact with the dma2d controller
*
* Parameter:
* width - Layer width
* height - Layer height
* fmt - Pixel format of the layer
*
* Return:
* On success - A valid dma2d layer reference
* On error - NULL and errno is set to
* -EINVAL if one of the parameter is invalid
* -ENOMEM if no memory available or exceeds
* CONFIG_STM32_DMA2D_NLAYERS
*
******************************************************************************/
FAR struct dma2d_layer_s *up_dma2dcreatelayer(fb_coord_t width,
fb_coord_t height,
uint8_t fmt)
{
int ret;
int lid;
uint8_t fmtmap;
uint8_t bpp = 0;
FAR struct stm32_dma2d_s *layer = NULL;
gvdbg("width=%d, height=%d, fmt=%02x \n", width, height, fmt);
/* Validate if pixel format supported */
ret = stm32_dma2d_pixelformat(fmt, &fmtmap);
if (ret != OK)
{
errno = ret;
return NULL;
}
ret = stm32_dma2d_bpp(fmt, &bpp);
sem_wait(&g_lock);
/* Get a free layer identifier */
lid = stm32_dma2d_lfreelid();
if (lid >= 0)
{
layer = stm32_dma2d_lalloc();
if (layer)
{
uint32_t fblen;
void *fbmem;
fb_coord_t stride;
/* Stride calculation for the supported formats */
stride = width * bpp / 8;
/* Calculate buffer size */
fblen = stride * height;
/* Allocate 32-bit aligned memory for the layer buffer. As reported in
* mm_memalign 8-byte alignment is guaranteed by normal malloc calls.
* We have also ensure memory is allocated from the SRAM1/2/3 block.
* The CCM block is only accessible through the D-BUS but not by
* the AHB-BUS. Ensure that CONFIG_STM32_CCMEXCLUDE is set!
*/
fbmem = kmm_zalloc(fblen);
if (fbmem)
{
FAR struct fb_videoinfo_s *vinfo = &layer->vinfo;
FAR struct fb_planeinfo_s *pinfo = &layer->pinfo;
/* Initialize dma2d structure */
stm32_dma2d_linit(layer, lid, fmtmap);
/* Initialize the videoinfo structure */
vinfo->fmt = fmt;
vinfo->xres = width;
vinfo->yres = height;
vinfo->nplanes = 1;
/* Initialize the planeinfo structure */
pinfo->fbmem = fbmem;
pinfo->fblen = fblen;
pinfo->stride = stride;
pinfo->bpp = bpp;
/* Bind the layer to the identifier */
g_layers[lid] = layer;
}
else
{
/* free the layer struture */
kmm_free(layer);
gdbg("ERROR: ENOMEM, Unable to allocate layer buffer\n");
errno = ENOMEM;
}
}
else
{
gdbg("ERROR: ENOMEM, unable to allocate layer structure\n");
errno = ENOMEM;
}
}
else
{
gdbg("ERROR: EINVAL, no free layer available\n");
errno = EINVAL;
}
sem_post(&g_lock);
return (FAR struct dma2d_layer_s *)layer;
}
/******************************************************************************
* Name: up_dma2dremovelayer
*
* Description:
* Remove and deallocate the dma2d layer
*
* Parameter:
* layer - Reference to the layer to remove
*
* Return:
* On success - OK
* On error - -EINVAL
*
*****************************************************************************/
int up_dma2dremovelayer(FAR struct dma2d_layer_s *layer)
{
int ret = -EINVAL;
FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer;
/* Check if the layer is valid and unlike a ltdc related layer */
if (stm32_dma2d_lvalidate(priv) && priv->lid >= DMA2D_SHADOW_LAYER)
{
sem_wait(priv->lock);
/* Check also if the layer id is valid to the layer reference */
if (priv == g_layers[priv->lid])
{
int lid = priv->lid;
kmm_free(priv->pinfo.fbmem);
stm32_dma2d_lfree(priv);
Defines a second interface for the dma2d controller. Controlling both LTDC and DMA2D was unpractical from the programmers view because both controllers are to different. LTDC only controls the display visibility but the DMA2D controller changes the content of the frame buffer (buffer of the layer). The main features are: 1. DMA2D interface Supports the nuttx pixel formats: - FB_FMT_RGB8 - FB_FMT_RGB24 - FB_FMT_RGB16_565 Dynamic layer allocation during runtime for the supported formats - The number of allocatable layer can be configured. Supported dma2d operation: - blit (Copy content from source to destination layer) also works with selectable area. - blend (Blend two layer and copy the result to a destination layer wich can be a third layer or one of the source layer) also works with selectable area. - fillarea (Fill a defined area of the whole layer with a specific color) As a result of that the dma2d controller can't transfer data from the core coupled memory, CCM is disabled but usable by the ccm allocator. Currently the ccm allocator is used for allocating the layer structurei only. For the dma memory (layers frame buffer) memory is allocated from heap 2 and 3. 2. LTDC interface I have changed the api for the currently non implemented operations: - blit (Copy content from a dma2d layer to an ltdc layer) also works with selectable area. - blend (Blend two dma2d layer and copy the result to a destination ltdc layer) also works with selectable area. Note! ltdc layer is a layer referenced by the ltdc interface. dma2d layer is a layer referenced by the dma2d interface. One of the most important questions for me was, How can i flexible use an ltdc layer with the dma2d interface, e.g. as source layer for dma2d operations? Get the layer id of the related dma2d layer by a special flag when using getlid() function of the ltdc interface and use the layer id to reference the specific dma2d layer by the dma2d interface. The ltdc coupled dma2d layers are predefined and can't be dynamically allocated of freed. They use the same frame buffer memory and the same color lookup table. Changes: - layer internal format of the clut table - interrupt handling for register reload (vertical vblank) instead using waiting loop - small fixes and refactoring From Marco Krahl.
2015-04-16 16:50:23 +02:00
g_layers[lid] = NULL;
ret = OK;
}
sem_post(priv->lock);
}
return ret;
}
/******************************************************************************
* Name: up_dma2dinitialize
*
* Description:
* Initialize the dma2d controller
*
* Return:
* OK - On success
* An error if initializing failed.
*
******************************************************************************/
int up_dma2dinitialize(void)
{
Defines a second interface for the dma2d controller. Controlling both LTDC and DMA2D was unpractical from the programmers view because both controllers are to different. LTDC only controls the display visibility but the DMA2D controller changes the content of the frame buffer (buffer of the layer). The main features are: 1. DMA2D interface Supports the nuttx pixel formats: - FB_FMT_RGB8 - FB_FMT_RGB24 - FB_FMT_RGB16_565 Dynamic layer allocation during runtime for the supported formats - The number of allocatable layer can be configured. Supported dma2d operation: - blit (Copy content from source to destination layer) also works with selectable area. - blend (Blend two layer and copy the result to a destination layer wich can be a third layer or one of the source layer) also works with selectable area. - fillarea (Fill a defined area of the whole layer with a specific color) As a result of that the dma2d controller can't transfer data from the core coupled memory, CCM is disabled but usable by the ccm allocator. Currently the ccm allocator is used for allocating the layer structurei only. For the dma memory (layers frame buffer) memory is allocated from heap 2 and 3. 2. LTDC interface I have changed the api for the currently non implemented operations: - blit (Copy content from a dma2d layer to an ltdc layer) also works with selectable area. - blend (Blend two dma2d layer and copy the result to a destination ltdc layer) also works with selectable area. Note! ltdc layer is a layer referenced by the ltdc interface. dma2d layer is a layer referenced by the dma2d interface. One of the most important questions for me was, How can i flexible use an ltdc layer with the dma2d interface, e.g. as source layer for dma2d operations? Get the layer id of the related dma2d layer by a special flag when using getlid() function of the ltdc interface and use the layer id to reference the specific dma2d layer by the dma2d interface. The ltdc coupled dma2d layers are predefined and can't be dynamically allocated of freed. They use the same frame buffer memory and the same color lookup table. Changes: - layer internal format of the clut table - interrupt handling for register reload (vertical vblank) instead using waiting loop - small fixes and refactoring From Marco Krahl.
2015-04-16 16:50:23 +02:00
dbg("Initialize DMA2D driver\n");
if (g_initialized == false)
{
/* Abort current dma2d data transfer */
up_dma2duninitialize();
/* Enable dma2d is done in rcc_enableahb1, see
* arch/arm/src/stm32/stm32f40xxx_rcc.c
*/
/* Initialize the DMA2D semaphore that enforces mutually exclusive access
* to the driver
*/
sem_init(&g_lock, 0, 1);
/* Initialize the semaphore for interrupt handling */
sem_init(g_interrupt.sem, 0, 0);
#ifdef CONFIG_STM32_DMA2D_L8
/* Enable dma2d transfer and clut loading interrupts only */
stm32_dma2d_control(DMA2D_CR_TCIE|DMA2D_CR_CTCIE, DMA2D_CR_TEIE|
DMA2D_CR_TWIE|DMA2D_CR_CAEIE||DMA2D_CR_CEIE);
#else
/* Enable dma transfer interrupt only */
stm32_dma2d_control(DMA2D_CR_TCIE, DMA2D_CR_TEIE|DMA2D_CR_TWIE|
DMA2D_CR_CAEIE|DMA2D_CR_CTCIE|DMA2D_CR_CEIE);
#endif
/* Attach DMA2D interrupt vector */
(void)irq_attach(g_interrupt.irq, stm32_dma2dirq);
/* Enable the IRQ at the NVIC */
up_enable_irq(g_interrupt.irq);
/* Initialize the dma2d layer for ltdc binding */
#ifdef DMA2D_SHADOW_LAYER_L1
g_layers[DMA2D_SHADOW_LAYER_L1] =
&g_ltdc_layer.layer[DMA2D_SHADOW_LAYER_L1].dma2ddev;
#endif
#ifdef DMA2D_SHADOW_LAYER_L2
g_layers[DMA2D_SHADOW_LAYER_L2] =
&g_ltdc_layer.layer[DMA2D_SHADOW_LAYER_L2].dma2ddev;
#endif
/* Set initialized state */
g_initialized = true;
}
return OK;
}
/******************************************************************************
* Name: up_dma2duninitialize
*
* Description:
* Uninitialize the dma2d controller
*
******************************************************************************/
void up_dma2duninitialize(void)
{
Defines a second interface for the dma2d controller. Controlling both LTDC and DMA2D was unpractical from the programmers view because both controllers are to different. LTDC only controls the display visibility but the DMA2D controller changes the content of the frame buffer (buffer of the layer). The main features are: 1. DMA2D interface Supports the nuttx pixel formats: - FB_FMT_RGB8 - FB_FMT_RGB24 - FB_FMT_RGB16_565 Dynamic layer allocation during runtime for the supported formats - The number of allocatable layer can be configured. Supported dma2d operation: - blit (Copy content from source to destination layer) also works with selectable area. - blend (Blend two layer and copy the result to a destination layer wich can be a third layer or one of the source layer) also works with selectable area. - fillarea (Fill a defined area of the whole layer with a specific color) As a result of that the dma2d controller can't transfer data from the core coupled memory, CCM is disabled but usable by the ccm allocator. Currently the ccm allocator is used for allocating the layer structurei only. For the dma memory (layers frame buffer) memory is allocated from heap 2 and 3. 2. LTDC interface I have changed the api for the currently non implemented operations: - blit (Copy content from a dma2d layer to an ltdc layer) also works with selectable area. - blend (Blend two dma2d layer and copy the result to a destination ltdc layer) also works with selectable area. Note! ltdc layer is a layer referenced by the ltdc interface. dma2d layer is a layer referenced by the dma2d interface. One of the most important questions for me was, How can i flexible use an ltdc layer with the dma2d interface, e.g. as source layer for dma2d operations? Get the layer id of the related dma2d layer by a special flag when using getlid() function of the ltdc interface and use the layer id to reference the specific dma2d layer by the dma2d interface. The ltdc coupled dma2d layers are predefined and can't be dynamically allocated of freed. They use the same frame buffer memory and the same color lookup table. Changes: - layer internal format of the clut table - interrupt handling for register reload (vertical vblank) instead using waiting loop - small fixes and refactoring From Marco Krahl.
2015-04-16 16:50:23 +02:00
/* Disable DMA2D interrupts */
up_disable_irq(g_interrupt.irq);
irq_detach(g_interrupt.irq);
/* Cleanup all layers */
stm32_dma2d_llayerscleanup();
/* Abort current dma2d transfer */
stm32_dma2d_control(DMA2D_CR_ABORT, 0);
/* Set initialized state */
g_initialized = false;
}
#ifdef CONFIG_STM32_LTDC_INTERFACE
/******************************************************************************
* Name: stm32_dma2dinitltdc
*
* Description:
* Get a reference to the dma2d layer coupled with the ltdc layer.
* It not intends to use this by user space applications.
* It resolves the following requirements:
* 1. Share the color lookup table
* 2. Share the planeinfo information
* 3. Share the videoinfo information
*
* Parameter:
* layer - a valid reference to the low level ltdc layer structure
* clut - a pointer to a valid memory region to hold 256 clut colors
*
* Return:
* On success - A valid dma2d layer reference
* On error - NULL and errno is set to
* -EINVAL if one of the parameter is invalid
*
******************************************************************************/
FAR struct dma2d_layer_s * stm32_dma2dinitltdc(FAR struct stm32_ltdc_s *layer)
{
int ret;
uint8_t fmt = 0;
FAR struct stm32_ltdc_dma2d_s *priv;
gvdbg("layer=%p\n", layer);
DEBUGASSERT(layer && layer->lid >= 0 && layer->lid < DMA2D_SHADOW_LAYER);
ret = stm32_dma2d_pixelformat(layer->vinfo.fmt, &fmt);
if (ret != OK)
{
dbg("Returning -EINVAL, unsupported pixel format: %d\n",
layer->vinfo.fmt);
errno = -EINVAL;
return NULL;
}
priv = &g_ltdc_layer.layer[layer->lid];
stm32_dma2d_linit(&priv->dma2ddev, layer->lid, fmt);
memcpy(&priv->dma2ddev.vinfo, &layer->vinfo, sizeof(struct fb_videoinfo_s));
memcpy(&priv->dma2ddev.pinfo, &layer->pinfo, sizeof(struct fb_planeinfo_s));
#ifdef CONFIG_STM32_DMA2D_L8
/* Verifies that the ltdc layer has a clut. This ensures that DMA2D driver can
* support clut format but the LTDC driver does not and vice versa.
*/
if (layer->vinfo.fmt == FB_FMT_RGB8)
{
priv->dma2ddev.clut = layer->clut;
priv->ltdc = stm32_ltdcgetlayer(layer->lid);
DEBUGASSERT(priv->ltdc != NULL);
}
#endif
return &priv->dma2ddev.dma2d;
}
Defines a second interface for the dma2d controller. Controlling both LTDC and DMA2D was unpractical from the programmers view because both controllers are to different. LTDC only controls the display visibility but the DMA2D controller changes the content of the frame buffer (buffer of the layer). The main features are: 1. DMA2D interface Supports the nuttx pixel formats: - FB_FMT_RGB8 - FB_FMT_RGB24 - FB_FMT_RGB16_565 Dynamic layer allocation during runtime for the supported formats - The number of allocatable layer can be configured. Supported dma2d operation: - blit (Copy content from source to destination layer) also works with selectable area. - blend (Blend two layer and copy the result to a destination layer wich can be a third layer or one of the source layer) also works with selectable area. - fillarea (Fill a defined area of the whole layer with a specific color) As a result of that the dma2d controller can't transfer data from the core coupled memory, CCM is disabled but usable by the ccm allocator. Currently the ccm allocator is used for allocating the layer structurei only. For the dma memory (layers frame buffer) memory is allocated from heap 2 and 3. 2. LTDC interface I have changed the api for the currently non implemented operations: - blit (Copy content from a dma2d layer to an ltdc layer) also works with selectable area. - blend (Blend two dma2d layer and copy the result to a destination ltdc layer) also works with selectable area. Note! ltdc layer is a layer referenced by the ltdc interface. dma2d layer is a layer referenced by the dma2d interface. One of the most important questions for me was, How can i flexible use an ltdc layer with the dma2d interface, e.g. as source layer for dma2d operations? Get the layer id of the related dma2d layer by a special flag when using getlid() function of the ltdc interface and use the layer id to reference the specific dma2d layer by the dma2d interface. The ltdc coupled dma2d layers are predefined and can't be dynamically allocated of freed. They use the same frame buffer memory and the same color lookup table. Changes: - layer internal format of the clut table - interrupt handling for register reload (vertical vblank) instead using waiting loop - small fixes and refactoring From Marco Krahl.
2015-04-16 16:50:23 +02:00
#endif /* CONFIG_STM32_LTDC_INTERFACE */