acid-drop

- Hacking the planet from a LilyGo T-Deck using custom firmware
git clone git://git.acid.vegas/acid-drop.git
Log | Files | Refs | Archive | README | LICENSE

lv_gpu_stm32_dma2d.c (8458B)

      1 /**
      2  * @file lv_gpu_stm32_dma2d.c
      3  *
      4  */
      5 
      6 /*********************
      7  *      INCLUDES
      8  *********************/
      9 #include "lv_gpu_stm32_dma2d.h"
     10 #include "../../core/lv_refr.h"
     11 
     12 #if LV_USE_GPU_STM32_DMA2D
     13 
     14 #include LV_GPU_DMA2D_CMSIS_INCLUDE
     15 
     16 /*********************
     17  *      DEFINES
     18  *********************/
     19 
     20 #if LV_COLOR_16_SWAP
     21     // TODO: F7 has red blue swap bit in control register for all layers and output
     22     #error "Can't use DMA2D with LV_COLOR_16_SWAP 1"
     23 #endif
     24 
     25 #if LV_COLOR_DEPTH == 8
     26     #error "Can't use DMA2D with LV_COLOR_DEPTH == 8"
     27 #endif
     28 
     29 #if LV_COLOR_DEPTH == 16
     30     #define LV_DMA2D_COLOR_FORMAT LV_DMA2D_RGB565
     31 #elif LV_COLOR_DEPTH == 32
     32     #define LV_DMA2D_COLOR_FORMAT LV_DMA2D_ARGB8888
     33 #else
     34     /*Can't use GPU with other formats*/
     35 #endif
     36 
     37 /**********************
     38  *      TYPEDEFS
     39  **********************/
     40 
     41 /**********************
     42  *  STATIC PROTOTYPES
     43  **********************/
     44 
     45 static void lv_draw_stm32_dma2d_blend_fill(lv_color_t * dest_buf, lv_coord_t dest_stride, const lv_area_t * fill_area,
     46                                            lv_color_t color);
     47 
     48 
     49 static void lv_draw_stm32_dma2d_blend_map(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
     50                                           const lv_color_t * src_buf, lv_coord_t src_stride, lv_opa_t opa);
     51 
     52 static void lv_draw_stm32_dma2d_img_decoded(lv_draw_ctx_t * draw, const lv_draw_img_dsc_t * dsc,
     53                                             const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t color_format);
     54 
     55 
     56 static void invalidate_cache(void);
     57 
     58 /**********************
     59  *  STATIC VARIABLES
     60  **********************/
     61 
     62 /**********************
     63  *      MACROS
     64  **********************/
     65 
     66 /**********************
     67  *   GLOBAL FUNCTIONS
     68  **********************/
     69 
     70 /**
     71  * Turn on the peripheral and set output color mode, this only needs to be done once
     72  */
     73 void lv_draw_stm32_dma2d_init(void)
     74 {
     75     /*Enable DMA2D clock*/
     76 #if defined(STM32F4) || defined(STM32F7)
     77     RCC->AHB1ENR |= RCC_AHB1ENR_DMA2DEN;
     78 #elif defined(STM32H7)
     79     RCC->AHB3ENR |= RCC_AHB3ENR_DMA2DEN;
     80 #else
     81 # warning "LVGL can't enable the clock of DMA2D"
     82 #endif
     83 
     84     /*Wait for hardware access to complete*/
     85     __asm volatile("DSB\n");
     86 
     87     /*Delay after setting peripheral clock*/
     88     volatile uint32_t temp = RCC->AHB1ENR;
     89     LV_UNUSED(temp);
     90 
     91     /*set output colour mode*/
     92     DMA2D->OPFCCR = LV_DMA2D_COLOR_FORMAT;
     93 }
     94 
     95 
     96 void lv_draw_stm32_dma2d_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
     97 {
     98 
     99     lv_draw_sw_init_ctx(drv, draw_ctx);
    100 
    101     lv_draw_stm32_dma2d_ctx_t * dma2d_draw_ctx = (lv_draw_sw_ctx_t *)draw_ctx;
    102 
    103     dma2d_draw_ctx->blend = lv_draw_stm32_dma2d_blend;
    104     //    dma2d_draw_ctx->base_draw.draw_img_decoded = lv_draw_stm32_dma2d_img_decoded;
    105     dma2d_draw_ctx->base_draw.wait_for_finish = lv_gpu_stm32_dma2d_wait_cb;
    106     dma2d_draw_ctx->base_draw.buffer_copy = lv_draw_stm32_dma2d_buffer_copy;
    107 
    108 }
    109 
    110 void lv_draw_stm32_dma2d_ctx_deinit(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
    111 {
    112     LV_UNUSED(drv);
    113     LV_UNUSED(draw_ctx);
    114 }
    115 
    116 
    117 void lv_draw_stm32_dma2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc)
    118 {
    119     lv_area_t blend_area;
    120     if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area)) return;
    121 
    122     bool done = false;
    123 
    124     if(dsc->mask_buf == NULL && dsc->blend_mode == LV_BLEND_MODE_NORMAL && lv_area_get_size(&blend_area) > 100) {
    125         lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area);
    126 
    127         lv_color_t * dest_buf = draw_ctx->buf;
    128         dest_buf += dest_stride * (blend_area.y1 - draw_ctx->buf_area->y1) + (blend_area.x1 - draw_ctx->buf_area->x1);
    129 
    130         const lv_color_t * src_buf = dsc->src_buf;
    131         if(src_buf) {
    132             lv_draw_sw_blend_basic(draw_ctx, dsc);
    133             lv_coord_t src_stride;
    134             src_stride = lv_area_get_width(dsc->blend_area);
    135             src_buf += src_stride * (blend_area.y1 - dsc->blend_area->y1) + (blend_area.x1 -  dsc->blend_area->x1);
    136             lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
    137             lv_draw_stm32_dma2d_blend_map(dest_buf, &blend_area, dest_stride, src_buf, src_stride, dsc->opa);
    138             done = true;
    139         }
    140         else if(dsc->opa >= LV_OPA_MAX) {
    141             lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
    142             lv_draw_stm32_dma2d_blend_fill(dest_buf, dest_stride, &blend_area, dsc->color);
    143             done = true;
    144         }
    145     }
    146 
    147     if(!done) lv_draw_sw_blend_basic(draw_ctx, dsc);
    148 }
    149 
    150 void lv_draw_stm32_dma2d_buffer_copy(lv_draw_ctx_t * draw_ctx,
    151                                      void * dest_buf, lv_coord_t dest_stride, const lv_area_t * dest_area,
    152                                      void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area)
    153 {
    154     LV_UNUSED(draw_ctx);
    155     lv_draw_stm32_dma2d_blend_map(dest_buf, dest_area, dest_stride, src_buf, src_stride, LV_OPA_MAX);
    156 }
    157 
    158 
    159 static void lv_draw_stm32_dma2d_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc,
    160                                             const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t color_format)
    161 {
    162     /*TODO basic ARGB8888 image can be handles here*/
    163 
    164     lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, color_format);
    165 }
    166 
    167 static void lv_draw_stm32_dma2d_blend_fill(lv_color_t * dest_buf, lv_coord_t dest_stride, const lv_area_t * fill_area,
    168                                            lv_color_t color)
    169 {
    170     /*Simply fill an area*/
    171     int32_t area_w = lv_area_get_width(fill_area);
    172     int32_t area_h = lv_area_get_height(fill_area);
    173     invalidate_cache();
    174 
    175     DMA2D->CR = 0x30000;
    176     DMA2D->OMAR = (uint32_t)dest_buf;
    177     /*as input color mode is same as output we don't need to convert here do we?*/
    178     DMA2D->OCOLR = color.full;
    179     DMA2D->OOR = dest_stride - area_w;
    180     DMA2D->NLR = (area_w << DMA2D_NLR_PL_Pos) | (area_h << DMA2D_NLR_NL_Pos);
    181 
    182     /*start transfer*/
    183     DMA2D->CR |= DMA2D_CR_START_Msk;
    184 
    185 }
    186 
    187 
    188 static void lv_draw_stm32_dma2d_blend_map(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
    189                                           const lv_color_t * src_buf, lv_coord_t src_stride, lv_opa_t opa)
    190 {
    191 
    192     /*Simple copy*/
    193     int32_t dest_w = lv_area_get_width(dest_area);
    194     int32_t dest_h = lv_area_get_height(dest_area);
    195 
    196     invalidate_cache();
    197     if(opa >= LV_OPA_MAX) {
    198         DMA2D->CR = 0;
    199         /*copy output colour mode, this register controls both input and output colour format*/
    200         DMA2D->FGPFCCR = LV_DMA2D_COLOR_FORMAT;
    201         DMA2D->FGMAR = (uint32_t)src_buf;
    202         DMA2D->FGOR = src_stride - dest_w;
    203         DMA2D->OMAR = (uint32_t)dest_buf;
    204         DMA2D->OOR = dest_stride - dest_w;
    205         DMA2D->NLR = (dest_w << DMA2D_NLR_PL_Pos) | (dest_h << DMA2D_NLR_NL_Pos);
    206 
    207         /*start transfer*/
    208         DMA2D->CR |= DMA2D_CR_START_Msk;
    209     }
    210     else {
    211         DMA2D->CR = 0x20000;
    212 
    213         DMA2D->BGPFCCR = LV_DMA2D_COLOR_FORMAT;
    214         DMA2D->BGMAR = (uint32_t)dest_buf;
    215         DMA2D->BGOR = dest_stride - dest_w;
    216 
    217         DMA2D->FGPFCCR = (uint32_t)LV_DMA2D_COLOR_FORMAT
    218                          /*alpha mode 2, replace with foreground * alpha value*/
    219                          | (2 << DMA2D_FGPFCCR_AM_Pos)
    220                          /*alpha value*/
    221                          | (opa << DMA2D_FGPFCCR_ALPHA_Pos);
    222         DMA2D->FGMAR = (uint32_t)src_buf;
    223         DMA2D->FGOR = src_stride - dest_w;
    224 
    225         DMA2D->OMAR = (uint32_t)src_buf;
    226         DMA2D->OOR = src_stride - dest_w;
    227         DMA2D->NLR = (dest_w << DMA2D_NLR_PL_Pos) | (dest_h << DMA2D_NLR_NL_Pos);
    228 
    229         /*start transfer*/
    230         DMA2D->CR |= DMA2D_CR_START_Msk;
    231     }
    232 }
    233 
    234 void lv_gpu_stm32_dma2d_wait_cb(lv_draw_ctx_t * draw_ctx)
    235 {
    236     lv_disp_t * disp = _lv_refr_get_disp_refreshing();
    237     if(disp->driver && disp->driver->wait_cb) {
    238         while(DMA2D->CR & DMA2D_CR_START_Msk) {
    239             disp->driver->wait_cb(disp->driver);
    240         }
    241     }
    242     else {
    243         while(DMA2D->CR & DMA2D_CR_START_Msk);
    244     }
    245     lv_draw_sw_wait_for_finish(draw_ctx);
    246 
    247 }
    248 
    249 /**********************
    250  *   STATIC FUNCTIONS
    251  **********************/
    252 
    253 static void invalidate_cache(void)
    254 {
    255     lv_disp_t * disp = _lv_refr_get_disp_refreshing();
    256     if(disp->driver->clean_dcache_cb) disp->driver->clean_dcache_cb(disp->driver);
    257     else {
    258 #if __CORTEX_M >= 0x07
    259         if((SCB->CCR) & (uint32_t)SCB_CCR_DC_Msk)
    260             SCB_CleanInvalidateDCache();
    261 #endif
    262     }
    263 }
    264 
    265 #endif