1 /**
2  * @file lv_gpu_swm341_dma2d.c
3  *
4  */
5 
6 /*********************
7  *      INCLUDES
8  *********************/
9 #include "lv_gpu_swm341_dma2d.h"
10 #include "../../core/lv_refr.h"
11 
12 #if LV_USE_GPU_SWM341_DMA2D
13 
14 #include LV_GPU_SWM341_DMA2D_INCLUDE
15 
16 /*********************
17  *      DEFINES
18  *********************/
19 
20 #if LV_COLOR_16_SWAP
21     #error "Can't use DMA2D with LV_COLOR_16_SWAP 1"
22 #endif
23 
24 #if LV_COLOR_DEPTH == 8
25     #error "Can't use DMA2D with LV_COLOR_DEPTH == 8"
26 #endif
27 
28 #if LV_COLOR_DEPTH == 16
29     #define LV_DMA2D_COLOR_FORMAT LV_SWM341_DMA2D_RGB565
30 #elif LV_COLOR_DEPTH == 32
31     #define LV_DMA2D_COLOR_FORMAT LV_SWM341_DMA2D_ARGB8888
32 #else
33     /*Can't use GPU with other formats*/
34 #endif
35 
36 /**********************
37  *      TYPEDEFS
38  **********************/
39 
40 /**********************
41  *  STATIC PROTOTYPES
42  **********************/
43 
44 static void lv_draw_swm341_dma2d_blend_fill(lv_color_t * dest_buf, lv_coord_t dest_stride, const lv_area_t * fill_area,
45                                             lv_color_t color);
46 
47 static void lv_draw_swm341_dma2d_blend_map(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
48                                            const lv_color_t * src_buf, lv_coord_t src_stride, lv_opa_t opa);
49 
50 static void lv_draw_swm341_dma2d_img_decoded(lv_draw_ctx_t * draw, const lv_draw_img_dsc_t * dsc,
51                                              const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t color_format);
52 
53 /**********************
54  *  STATIC VARIABLES
55  **********************/
56 
57 /**********************
58  *      MACROS
59  **********************/
60 
61 /**********************
62  *   GLOBAL FUNCTIONS
63  **********************/
64 
65 /**
66  * Turn on the peripheral and set output color mode, this only needs to be done once
67  */
lv_draw_swm341_dma2d_init(void)68 void lv_draw_swm341_dma2d_init(void)
69 {
70     /*Enable DMA2D clock*/
71     SYS->CLKEN0 |= (1 << SYS_CLKEN0_DMA2D_Pos);
72 
73     DMA2D->CR &= ~DMA2D_CR_WAIT_Msk;
74     DMA2D->CR |= (CyclesPerUs << DMA2D_CR_WAIT_Pos);
75 
76     DMA2D->IF = 0xFF;
77     DMA2D->IE = (0 << DMA2D_IE_DONE_Pos);
78 
79     /*set output colour mode*/
80     DMA2D->L[DMA2D_LAYER_OUT].PFCCR = (LV_DMA2D_COLOR_FORMAT << DMA2D_PFCCR_CFMT_Pos);
81 }
82 
lv_draw_swm341_dma2d_ctx_init(lv_disp_drv_t * drv,lv_draw_ctx_t * draw_ctx)83 void lv_draw_swm341_dma2d_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
84 {
85 
86     lv_draw_sw_init_ctx(drv, draw_ctx);
87 
88     lv_draw_swm341_dma2d_ctx_t * dma2d_draw_ctx = (lv_draw_sw_ctx_t *)draw_ctx;
89 
90     dma2d_draw_ctx->blend = lv_draw_swm341_dma2d_blend;
91     //    dma2d_draw_ctx->base_draw.draw_img_decoded = lv_draw_swm341_dma2d_img_decoded;
92     dma2d_draw_ctx->base_draw.wait_for_finish = lv_gpu_swm341_dma2d_wait_cb;
93 }
94 
lv_draw_swm341_dma2d_ctx_deinit(lv_disp_drv_t * drv,lv_draw_ctx_t * draw_ctx)95 void lv_draw_swm341_dma2d_ctx_deinit(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
96 {
97     LV_UNUSED(drv);
98     LV_UNUSED(draw_ctx);
99 }
100 
lv_draw_swm341_dma2d_blend(lv_draw_ctx_t * draw_ctx,const lv_draw_sw_blend_dsc_t * dsc)101 void lv_draw_swm341_dma2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc)
102 {
103     lv_area_t blend_area;
104     if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area))
105         return;
106 
107     bool done = false;
108 
109     if(dsc->mask_buf == NULL && dsc->blend_mode == LV_BLEND_MODE_NORMAL && lv_area_get_size(&blend_area) > 100) {
110         lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area);
111 
112         lv_color_t * dest_buf = draw_ctx->buf;
113         dest_buf += dest_stride * (blend_area.y1 - draw_ctx->buf_area->y1) + (blend_area.x1 - draw_ctx->buf_area->x1);
114 
115         const lv_color_t * src_buf = dsc->src_buf;
116         if(src_buf) {
117             lv_draw_sw_blend_basic(draw_ctx, dsc);
118             lv_coord_t src_stride;
119             src_stride = lv_area_get_width(dsc->blend_area);
120             src_buf += src_stride * (blend_area.y1 - dsc->blend_area->y1) + (blend_area.x1 - dsc->blend_area->x1);
121             lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
122             lv_draw_swm341_dma2d_blend_map(dest_buf, &blend_area, dest_stride, src_buf, src_stride, dsc->opa);
123             done = true;
124         }
125         else if(dsc->opa >= LV_OPA_MAX) {
126             lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
127             lv_draw_swm341_dma2d_blend_fill(dest_buf, dest_stride, &blend_area, dsc->color);
128             done = true;
129         }
130     }
131 
132     if(!done) lv_draw_sw_blend_basic(draw_ctx, dsc);
133 }
134 
lv_draw_swm341_dma2d_img_decoded(lv_draw_ctx_t * draw_ctx,const lv_draw_img_dsc_t * dsc,const lv_area_t * coords,const uint8_t * map_p,lv_img_cf_t color_format)135 static void lv_draw_swm341_dma2d_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc,
136                                              const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t color_format)
137 {
138     /*TODO basic ARGB8888 image can be handles here*/
139 
140     lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, color_format);
141 }
142 
lv_draw_swm341_dma2d_blend_fill(lv_color_t * dest_buf,lv_coord_t dest_stride,const lv_area_t * fill_area,lv_color_t color)143 static void lv_draw_swm341_dma2d_blend_fill(lv_color_t * dest_buf, lv_coord_t dest_stride, const lv_area_t * fill_area,
144                                             lv_color_t color)
145 {
146     /*Simply fill an area*/
147     int32_t area_w = lv_area_get_width(fill_area);
148     int32_t area_h = lv_area_get_height(fill_area);
149 
150 #if 1
151     DMA2D->L[DMA2D_LAYER_OUT].COLOR = color.full;
152 
153     DMA2D->L[DMA2D_LAYER_OUT].MAR = (uint32_t)dest_buf;
154     DMA2D->L[DMA2D_LAYER_OUT].OR = dest_stride - area_w;
155     DMA2D->NLR = ((area_w - 1) << DMA2D_NLR_NPIXEL_Pos) | ((area_h - 1) << DMA2D_NLR_NLINE_Pos);
156 
157     /*start transfer*/
158     DMA2D->CR &= ~DMA2D_CR_MODE_Msk;
159     DMA2D->CR |= (3 << DMA2D_CR_MODE_Pos) |
160                  (1 << DMA2D_CR_START_Pos);
161 #else
162     for(uint32_t y = 0; y < area_h; y++) {
163         for(uint32_t x = 0; x < area_w; x++) {
164             dest_buf[y * dest_stride + x] = color;
165         }
166     }
167 #endif
168 }
169 
lv_draw_swm341_dma2d_blend_map(lv_color_t * dest_buf,const lv_area_t * dest_area,lv_coord_t dest_stride,const lv_color_t * src_buf,lv_coord_t src_stride,lv_opa_t opa)170 static void lv_draw_swm341_dma2d_blend_map(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
171                                            const lv_color_t * src_buf, lv_coord_t src_stride, lv_opa_t opa)
172 {
173 
174     /*Simple copy*/
175     int32_t dest_w = lv_area_get_width(dest_area);
176     int32_t dest_h = lv_area_get_height(dest_area);
177 
178     if(opa >= LV_OPA_MAX) {
179 #if 1
180         /*copy output colour mode, this register controls both input and output colour format*/
181         DMA2D->L[DMA2D_LAYER_FG].MAR = (uint32_t)src_buf;
182         DMA2D->L[DMA2D_LAYER_FG].OR = src_stride - dest_w;
183         DMA2D->L[DMA2D_LAYER_FG].PFCCR = (LV_DMA2D_COLOR_FORMAT << DMA2D_PFCCR_CFMT_Pos);
184 
185         DMA2D->L[DMA2D_LAYER_OUT].MAR = (uint32_t)dest_buf;
186         DMA2D->L[DMA2D_LAYER_OUT].OR = dest_stride - dest_w;
187 
188         DMA2D->NLR = ((dest_w - 1) << DMA2D_NLR_NPIXEL_Pos) | ((dest_h - 1) << DMA2D_NLR_NLINE_Pos);
189 
190         /*start transfer*/
191         DMA2D->CR &= ~DMA2D_CR_MODE_Msk;
192         DMA2D->CR |= (0 << DMA2D_CR_MODE_Pos) |
193                      (1 << DMA2D_CR_START_Pos);
194 #else
195         lv_color_t temp_buf[1024];
196         for(uint32_t y = 0; y < dest_h; y++) {
197             memcpy(temp_buf, &src_buf[y * src_stride], dest_w * sizeof(lv_color_t));
198             memcpy(&dest_buf[y * dest_stride], temp_buf, dest_w * sizeof(lv_color_t));
199         }
200 #endif
201     }
202     else {
203         DMA2D->L[DMA2D_LAYER_FG].MAR = (uint32_t)src_buf;
204         DMA2D->L[DMA2D_LAYER_FG].OR = src_stride - dest_w;
205         DMA2D->L[DMA2D_LAYER_FG].PFCCR = (LV_DMA2D_COLOR_FORMAT << DMA2D_PFCCR_CFMT_Pos)
206                                          /*alpha mode 2, replace with foreground * alpha value*/
207                                          | (2 << DAM2D_PFCCR_AMODE_Pos)
208                                          /*alpha value*/
209                                          | (opa << DMA2D_PFCCR_ALPHA_Pos);
210 
211         DMA2D->L[DMA2D_LAYER_BG].MAR = (uint32_t)dest_buf;
212         DMA2D->L[DMA2D_LAYER_BG].OR = dest_stride - dest_w;
213         DMA2D->L[DMA2D_LAYER_BG].PFCCR = (LV_DMA2D_COLOR_FORMAT << DMA2D_PFCCR_CFMT_Pos);
214 
215         DMA2D->L[DMA2D_LAYER_OUT].MAR = (uint32_t)dest_buf;
216         DMA2D->L[DMA2D_LAYER_OUT].OR = dest_stride - dest_w;
217 
218         DMA2D->NLR = ((dest_w - 1) << DMA2D_NLR_NPIXEL_Pos) | ((dest_h - 1) << DMA2D_NLR_NLINE_Pos);
219 
220         /*start transfer*/
221         DMA2D->CR &= ~DMA2D_CR_MODE_Msk;
222         DMA2D->CR |= (2 << DMA2D_CR_MODE_Pos) |
223                      (1 << DMA2D_CR_START_Pos);
224     }
225 }
226 
lv_gpu_swm341_dma2d_wait_cb(lv_draw_ctx_t * draw_ctx)227 void lv_gpu_swm341_dma2d_wait_cb(lv_draw_ctx_t * draw_ctx)
228 {
229     lv_disp_t * disp = _lv_refr_get_disp_refreshing();
230     if(disp->driver && disp->driver->wait_cb) {
231         while(DMA2D->CR & DMA2D_CR_START_Msk) {
232             disp->driver->wait_cb(disp->driver);
233         }
234     }
235     else {
236         while(DMA2D->CR & DMA2D_CR_START_Msk);
237     }
238     lv_draw_sw_wait_for_finish(draw_ctx);
239 }
240 
241 #endif
242