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