• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 HPMicro
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include "hpm_common.h"
9 #include "hpm_pdma_drv.h"
10 
11 #define PDMA_SCALE_FRAC_BITS 12
12 /* x_offset might need to be adjusted when scaling YUV format */
13 #define PDMA_YUV_SCALE_DEFAULT_X_OFFSET (0x800)
14 
pdma_set_block_size(PDMA_Type * ptr,pdma_blocksize_t size)15 void pdma_set_block_size(PDMA_Type *ptr, pdma_blocksize_t size)
16 {
17     ptr->CTRL = (ptr->CTRL & ~PDMA_CTRL_BS16_MASK)
18         | ((size == pdma_blocksize_16x16) ? PDMA_CTRL_BS16_MASK : 0);
19 }
20 
pdma_enable_plane(PDMA_Type * ptr,pdma_plane_t enable_plane,bool enable)21 void pdma_enable_plane(PDMA_Type *ptr, pdma_plane_t enable_plane, bool enable)
22 {
23     uint32_t mask;
24     switch (enable_plane) {
25     case pdma_plane_both:
26         mask = (PDMA_CTRL_P0_EN_MASK | PDMA_CTRL_P1_EN_MASK);
27         break;
28     case pdma_plane_src:
29         mask = PDMA_CTRL_P0_EN_MASK;
30         break;
31     case pdma_plane_dst:
32         mask = PDMA_CTRL_P1_EN_MASK;
33         break;
34     default:
35         mask = 0;
36         break;
37     }
38     if (!mask) {
39         return;
40     }
41     if (enable) {
42         ptr->CTRL |= mask;
43     } else {
44         ptr->CTRL &= ~mask;
45     }
46 }
47 
pdma_enable_irq(PDMA_Type * ptr,uint32_t mask,bool enable)48 void pdma_enable_irq(PDMA_Type *ptr, uint32_t mask, bool enable)
49 {
50     mask &= PDMA_CTRL_AXIERR_IRQ_EN_MASK | PDMA_CTRL_PDMA_DONE_IRQ_EN_MASK;
51     if (enable) {
52         ptr->CTRL |= mask | PDMA_CTRL_IRQ_EN_MASK;
53     } else {
54         ptr->CTRL &= ~mask;
55     }
56 }
57 
pdma_get_default_config(PDMA_Type * ptr,pdma_config_t * config,display_pixel_format_t pixel_format)58 void pdma_get_default_config(PDMA_Type *ptr, pdma_config_t *config, display_pixel_format_t pixel_format)
59 {
60     (void) ptr;
61     config->block_size = pdma_blocksize_16x16;
62     config->enable_plane = pdma_plane_src;
63 
64     if (display_pixel_format_is_yuv_format(pixel_format)) {
65         if (pixel_format == display_pixel_format_ycbcr422) {
66             config->byteorder = display_byteorder_a2a3a0a1;
67         } else {
68             config->byteorder = display_byteorder_a0a1a2a3;
69         }
70     } else {
71         config->byteorder = display_byteorder_a3a2a1a0;
72     }
73 }
74 
pdma_get_default_plane_config(PDMA_Type * ptr,pdma_plane_config_t * config,display_pixel_format_t pixel_format)75 void pdma_get_default_plane_config(PDMA_Type *ptr, pdma_plane_config_t *config, display_pixel_format_t pixel_format)
76 {
77     (void) ptr;
78     config->swap_byte3_byte1 = false;
79     config->byteorder = display_byteorder_a3a2a1a0;
80     config->use_background_as_clear = true;
81     config->flip = pdma_flip_none;
82     config->rotate = pdma_rotate_0_degree;
83     config->x_dec = pdma_decimation_by_1;
84     config->y_dec = pdma_decimation_by_1;
85     config->byte_swap = false;
86     config->pixel_format = pixel_format;
87     config->buffer = 0;
88     config->background = 0xFFFFFFFF;
89     config->x_scale = PDMA_MAKE_SCALE_SET(1, 0);
90     config->y_scale = PDMA_MAKE_SCALE_SET(1, 0);
91     config->x_offset = 0;
92     config->y_offset = 0;
93     config->colorkey_high = 0;
94     config->colorkey_low = 0xFFFFFF;
95     config->width = 0;
96     config->height = 0;
97     config->pitch = 0;
98 
99     switch (pixel_format) {
100     case display_pixel_format_yuv422:
101         config->ycbcr_mode = false;
102         config->bypass_colorspace_conversion = false;
103         break;
104     case display_pixel_format_ycbcr422:
105         config->ycbcr_mode = true;
106         config->bypass_colorspace_conversion = false;
107         break;
108     default:
109         config->ycbcr_mode = false;
110         config->bypass_colorspace_conversion = true;
111         break;
112     }
113 }
114 
pdma_get_default_yuv2rgb_coef_config(PDMA_Type * ptr,display_yuv2rgb_coef_t * yuv2rgb_coef,display_pixel_format_t source_format)115 void pdma_get_default_yuv2rgb_coef_config(PDMA_Type *ptr, display_yuv2rgb_coef_t *yuv2rgb_coef, display_pixel_format_t source_format)
116 {
117     (void) ptr;
118     /* Two plane share one YUV2RGB_COEF, not support one plane format is yuv422 and another is ycbcr422 */
119 
120     switch (source_format) {
121     case display_pixel_format_yuv422:
122         yuv2rgb_coef->c0 = 0x100;
123         yuv2rgb_coef->uv_offset = 0;
124         yuv2rgb_coef->y_offset = 0;
125         yuv2rgb_coef->c1 = 0x123;
126         yuv2rgb_coef->c2 = 0x76B;
127         yuv2rgb_coef->c3 = 0x79C;
128         yuv2rgb_coef->c4 = 0x208;
129         break;
130     case display_pixel_format_ycbcr422:
131         yuv2rgb_coef->c0 = 0x12A;
132         yuv2rgb_coef->uv_offset = 0x180;
133         yuv2rgb_coef->y_offset = 0x1F0;
134         yuv2rgb_coef->c1 = 0x198;
135         yuv2rgb_coef->c2 = 0x730;
136         yuv2rgb_coef->c3 = 0x79C;
137         yuv2rgb_coef->c4 = 0x204;
138         break;
139     default:
140         yuv2rgb_coef->c0 = 0;
141         yuv2rgb_coef->uv_offset = 0;
142         yuv2rgb_coef->y_offset = 0;
143         yuv2rgb_coef->c1 = 0;
144         yuv2rgb_coef->c2 = 0;
145         yuv2rgb_coef->c3 = 0;
146         yuv2rgb_coef->c4 = 0;
147         break;
148     }
149 }
150 
pdma_get_default_output_config(PDMA_Type * ptr,pdma_output_config_t * config,display_pixel_format_t pixel_format)151 void pdma_get_default_output_config(PDMA_Type *ptr, pdma_output_config_t *config, display_pixel_format_t pixel_format)
152 {
153     (void) ptr;
154     uint8_t i;
155     config->alphablend.dst_alpha = 0x0;
156     config->alphablend.src_alpha = 0x0;
157     config->alphablend.src_alpha_op = display_alpha_op_invalid;
158     config->alphablend.dst_alpha_op = display_alpha_op_invalid;
159     config->alphablend.mode = display_alphablend_mode_plus;
160     config->pixel_format = pixel_format;
161     config->buffer = 0;
162     for (i = 0; i < PDMA_SOC_PS_MAX_COUNT; i++) {
163         config->plane[i].x = 0;
164         config->plane[i].y = 0;
165         config->plane[i].width = 0;
166         config->plane[i].height = 0;
167     }
168     config->width = 0;
169     config->height = 0;
170     config->pitch = 0;
171 
172     switch (pixel_format) {
173     case display_pixel_format_yuv422:
174         config->rgb2yuv_config.enable = true;
175         config->rgb2yuv_config.ycbcr_mode = false;
176         config->rgb2yuv_config.c0 = 0x4D;
177         config->rgb2yuv_config.uv_offset = 0;
178         config->rgb2yuv_config.y_offset = 0;
179         config->rgb2yuv_config.c1 = 0x96;
180         config->rgb2yuv_config.c2 = 0x1D;
181         config->rgb2yuv_config.c3 = 0x7DA;
182         config->rgb2yuv_config.c4 = 0x7B6;
183         config->rgb2yuv_config.c5 = 0x70;
184         config->rgb2yuv_config.c6 = 0x9D;
185         config->rgb2yuv_config.c7 = 0x77C;
186         config->rgb2yuv_config.c8 = 0x7E6;
187         break;
188     case display_pixel_format_ycbcr422:
189         config->rgb2yuv_config.enable = true;
190         config->rgb2yuv_config.ycbcr_mode = true;
191         config->rgb2yuv_config.c0 = 0x42;
192         config->rgb2yuv_config.uv_offset = 0x80;
193         config->rgb2yuv_config.y_offset = 0x10;
194         config->rgb2yuv_config.c1 = 0x81;
195         config->rgb2yuv_config.c2 = 0x19;
196         config->rgb2yuv_config.c3 = 0x7DA;
197         config->rgb2yuv_config.c4 = 0x7B5;
198         config->rgb2yuv_config.c5 = 0x70;
199         config->rgb2yuv_config.c6 = 0x70;
200         config->rgb2yuv_config.c7 = 0x7A2;
201         config->rgb2yuv_config.c8 = 0x7EE;
202         break;
203     default:
204         config->rgb2yuv_config.enable = false;
205         config->rgb2yuv_config.ycbcr_mode = false;
206         config->rgb2yuv_config.c0 = 0;
207         config->rgb2yuv_config.uv_offset = 0;
208         config->rgb2yuv_config.y_offset = 0;
209         config->rgb2yuv_config.c1 = 0;
210         config->rgb2yuv_config.c2 = 0;
211         config->rgb2yuv_config.c3 = 0;
212         config->rgb2yuv_config.c4 = 0;
213         config->rgb2yuv_config.c5 = 0;
214         config->rgb2yuv_config.c6 = 0;
215         config->rgb2yuv_config.c7 = 0;
216         config->rgb2yuv_config.c8 = 0;
217         break;
218     }
219 }
220 
pdma_stop(PDMA_Type * ptr)221 void pdma_stop(PDMA_Type *ptr)
222 {
223     ptr->CTRL &= ~PDMA_CTRL_PDMA_EN_MASK;
224     pdma_software_reset(ptr);
225     ptr->STAT = 0x21F;
226 }
227 
pdma_init(PDMA_Type * ptr,pdma_config_t * config)228 void pdma_init(PDMA_Type *ptr, pdma_config_t *config)
229 {
230     uint32_t mask;
231     pdma_stop(ptr);
232     switch (config->enable_plane) {
233     case pdma_plane_both:
234         mask = (PDMA_CTRL_P0_EN_MASK | PDMA_CTRL_P1_EN_MASK);
235         break;
236     case pdma_plane_dst:
237         mask = PDMA_CTRL_P1_EN_MASK;
238         break;
239     case pdma_plane_src:
240         mask = PDMA_CTRL_P0_EN_MASK;
241         break;
242     default:
243         mask = 0;
244         break;
245     }
246 #if defined(PDMA_SOC_SUPPORT_BS16) && (PDMA_SOC_SUPPORT_BS16 == 1)
247     if (config->block_size == pdma_blocksize_16x16) {
248         mask |= PDMA_CTRL_BS16_MASK;
249     }
250 #endif
251 
252     ptr->CTRL = PDMA_CTRL_PACK_DIR_SET(config->byteorder) | mask;
253 }
254 
pdma_pixel_format(display_pixel_format_t display_format,bool is_out_plane)255 static uint32_t pdma_pixel_format(display_pixel_format_t display_format, bool is_out_plane)
256 {
257     switch (display_format) {
258     case display_pixel_format_rgb565:
259         return 0xE;
260     case display_pixel_format_argb8888:
261         return 0;
262     case display_pixel_format_yuv422:
263         return 0x13;
264     case display_pixel_format_ycbcr422:
265         return is_out_plane ? 0x12 : 0x13;
266     default:
267         return 0;
268     }
269 }
270 
pdma_config_planes(PDMA_Type * ptr,void * plane_src_config,void * plane_dst_config,void * yuv2rgb_coef)271 void pdma_config_planes(PDMA_Type *ptr, void *plane_src_config, void *plane_dst_config, void *yuv2rgb_coef)
272 {
273     uint32_t pitch;
274     uint32_t format;
275 
276     assert((plane_src_config != NULL) || (plane_dst_config != NULL));
277 
278     pdma_plane_config_t *plane_src = (pdma_plane_config_t *)plane_src_config;
279     pdma_plane_config_t *plane_dst = (pdma_plane_config_t *)plane_dst_config;
280     display_yuv2rgb_coef_t *yuv2rgb = (display_yuv2rgb_coef_t *)yuv2rgb_coef;
281 
282     if (plane_src != NULL) {
283         assert((plane_src->bypass_colorspace_conversion) || (yuv2rgb != NULL));
284     }
285     if (plane_dst != NULL) {
286         assert((plane_dst->bypass_colorspace_conversion) || (yuv2rgb != NULL));
287     }
288     if ((plane_src != NULL) && (plane_dst != NULL)) {
289         assert(!(display_pixel_format_is_yuv_format(plane_src->pixel_format) && display_pixel_format_is_yuv_format(plane_dst->pixel_format))
290                 || (plane_src->pixel_format == plane_dst->pixel_format));
291     }
292 
293     if (plane_src != NULL) {
294         if (plane_src->pitch == 0) {
295             pitch = display_get_pitch_length_in_byte(plane_src->pixel_format, plane_src->width);
296         } else {
297             pitch = plane_src->pitch;
298         }
299         format = pdma_pixel_format(plane_src->pixel_format, false);
300         ptr->PS[pdma_plane_src].BUF = PDMA_PS_BUF_ADDR_SET((uint32_t) plane_src->buffer);
301         ptr->PS[pdma_plane_src].PITCH = PDMA_PS_PITCH_BYTELEN_SET(pitch);
302         ptr->PS[pdma_plane_src].BKGD = PDMA_PS_BKGD_COLOR_SET(plane_src->background);
303         ptr->PS[pdma_plane_src].SCALE = PDMA_PS_SCALE_X_SET(plane_src->x_scale)
304             | PDMA_PS_SCALE_Y_SET(plane_src->y_scale);
305         ptr->PS[pdma_plane_src].OFFSET = PDMA_PS_OFFSET_X_SET(plane_src->x_offset)
306             | PDMA_PS_OFFSET_Y_SET(plane_src->y_offset);
307         ptr->PS[pdma_plane_src].CLRKEY_LOW = PDMA_PS_CLRKEY_LOW_LIMIT_SET(plane_src->colorkey_low);
308         ptr->PS[pdma_plane_src].CLRKEY_HIGH = PDMA_PS_CLRKEY_HIGH_LIMIT_SET(plane_src->colorkey_high);
309         ptr->PS[pdma_plane_src].ORG = PDMA_PS_ORG_HIGHT_SET(plane_src->height)
310             | PDMA_PS_ORG_WIDTH_SET(plane_src->width);
311         ptr->PS[pdma_plane_src].CTRL = PDMA_PS_CTRL_INB13_SWAP_SET(plane_src->swap_byte3_byte1)
312             | PDMA_PS_CTRL_PACK_DIR_SET(plane_src->byteorder)
313             | PDMA_PS_CTRL_BKGCL4CLR_SET(plane_src->use_background_as_clear)
314             | PDMA_PS_CTRL_YCBCR_MODE_SET(plane_src->ycbcr_mode)
315             | PDMA_PS_CTRL_BYPASS_SET(plane_src->bypass_colorspace_conversion)
316             | ((plane_src->flip << PDMA_PS_CTRL_HFLIP_SHIFT)
317                     & (PDMA_PS_CTRL_VFLIP_MASK | PDMA_PS_CTRL_HFLIP_MASK))
318             | PDMA_PS_CTRL_ROTATE_SET(plane_src->rotate)
319             | PDMA_PS_CTRL_DECY_SET(plane_src->y_dec)
320             | PDMA_PS_CTRL_DECX_SET(plane_src->x_dec)
321             | PDMA_PS_CTRL_HW_BYTE_SWAP_SET(plane_src->byte_swap)
322             | PDMA_PS_CTRL_FORMAT_SET(format);
323     }
324 
325     if (plane_dst != NULL) {
326         if (plane_dst->pitch == 0) {
327             pitch = display_get_pitch_length_in_byte(plane_src->pixel_format, plane_src->width);
328         } else {
329             pitch = plane_dst->pitch;
330         }
331         format = pdma_pixel_format(plane_dst->pixel_format, false);
332         ptr->PS[pdma_plane_dst].BUF = PDMA_PS_BUF_ADDR_SET((uint32_t) plane_dst->buffer);
333         ptr->PS[pdma_plane_dst].PITCH = PDMA_PS_PITCH_BYTELEN_SET(pitch);
334         ptr->PS[pdma_plane_dst].BKGD = PDMA_PS_BKGD_COLOR_SET(plane_dst->background);
335         ptr->PS[pdma_plane_dst].SCALE = PDMA_PS_SCALE_X_SET(plane_dst->x_scale)
336             | PDMA_PS_SCALE_Y_SET(plane_dst->y_scale);
337         ptr->PS[pdma_plane_dst].OFFSET = PDMA_PS_OFFSET_X_SET(plane_dst->x_offset)
338             | PDMA_PS_OFFSET_Y_SET(plane_dst->y_offset);
339         ptr->PS[pdma_plane_dst].CLRKEY_LOW = PDMA_PS_CLRKEY_LOW_LIMIT_SET(plane_dst->colorkey_low);
340         ptr->PS[pdma_plane_dst].CLRKEY_HIGH = PDMA_PS_CLRKEY_HIGH_LIMIT_SET(plane_dst->colorkey_high);
341         ptr->PS[pdma_plane_dst].ORG = PDMA_PS_ORG_HIGHT_SET(plane_dst->height)
342             | PDMA_PS_ORG_WIDTH_SET(plane_dst->width);
343         ptr->PS[pdma_plane_dst].CTRL = PDMA_PS_CTRL_INB13_SWAP_SET(plane_dst->swap_byte3_byte1)
344             | PDMA_PS_CTRL_PACK_DIR_SET(plane_dst->byteorder)
345             | PDMA_PS_CTRL_BKGCL4CLR_SET(plane_dst->use_background_as_clear)
346             | PDMA_PS_CTRL_YCBCR_MODE_SET(plane_dst->ycbcr_mode)
347             | PDMA_PS_CTRL_BYPASS_SET(plane_dst->bypass_colorspace_conversion)
348             | ((plane_dst->flip << PDMA_PS_CTRL_HFLIP_SHIFT)
349                     & (PDMA_PS_CTRL_VFLIP_MASK | PDMA_PS_CTRL_HFLIP_MASK))
350             | PDMA_PS_CTRL_ROTATE_SET(plane_dst->rotate)
351             | PDMA_PS_CTRL_DECY_SET(plane_dst->y_dec)
352             | PDMA_PS_CTRL_DECX_SET(plane_dst->x_dec)
353             | PDMA_PS_CTRL_HW_BYTE_SWAP_SET(plane_dst->byte_swap)
354             | PDMA_PS_CTRL_FORMAT_SET(format);
355     }
356 
357     if (yuv2rgb != NULL) {
358         ptr->YUV2RGB_COEF0 = PDMA_YUV2RGB_COEF0_C0_SET(yuv2rgb->c0)
359             | PDMA_YUV2RGB_COEF0_UV_OFFSET_SET(yuv2rgb->uv_offset)
360             | PDMA_YUV2RGB_COEF0_Y_OFFSET_SET(yuv2rgb->y_offset);
361         ptr->YUV2RGB_COEF1 = PDMA_YUV2RGB_COEF1_C1_SET(yuv2rgb->c1)
362             | PDMA_YUV2RGB_COEF1_C4_SET(yuv2rgb->c4);
363         ptr->YUV2RGB_COEF2 = PDMA_YUV2RGB_COEF2_C2_SET(yuv2rgb->c2)
364             | PDMA_YUV2RGB_COEF2_C3_SET(yuv2rgb->c3);
365     }
366 }
367 
pdma_config_output(PDMA_Type * ptr,pdma_output_config_t * config)368 void pdma_config_output(PDMA_Type *ptr, pdma_output_config_t *config)
369 {
370     uint32_t pitch;
371     uint32_t format;
372 
373     if (config->pitch == 0) {
374         pitch = display_get_pitch_length_in_byte(config->pixel_format,
375                                                     config->width);
376     } else {
377         pitch = config->pitch;
378     }
379     format = pdma_pixel_format(config->pixel_format, true);
380     ptr->OUT_BUF = PDMA_OUT_BUF_ADDR_SET((uint32_t) config->buffer);
381     ptr->OUT_PITCH = PDMA_OUT_PITCH_BYTELEN_SET(pitch);
382     ptr->OUT_LRC = PDMA_OUT_LRC_X_SET(config->width)
383         | PDMA_OUT_LRC_Y_SET(config->height);
384     ptr->OUT_PS[0].ULC = PDMA_OUT_PS_ULC_X_SET(config->plane[0].x)
385         | PDMA_OUT_PS_ULC_Y_SET(config->plane[0].y);
386     ptr->OUT_PS[0].LRC = PDMA_OUT_PS_LRC_X_SET(config->plane[0].width)
387         | PDMA_OUT_PS_LRC_Y_SET(config->plane[0].height);
388     ptr->OUT_PS[1].ULC = PDMA_OUT_PS_ULC_X_SET(config->plane[1].x)
389         | PDMA_OUT_PS_ULC_Y_SET(config->plane[1].y);
390     ptr->OUT_PS[1].LRC = PDMA_OUT_PS_LRC_X_SET(config->plane[1].width)
391         | PDMA_OUT_PS_LRC_Y_SET(config->plane[1].height);
392     ptr->OUT_CTRL = PDMA_OUT_CTRL_DSTALPHA_SET(config->alphablend.dst_alpha)
393         | PDMA_OUT_CTRL_SRCALPHA_SET(config->alphablend.src_alpha)
394         | PDMA_OUT_CTRL_DSTALPHA_OP_SET(config->alphablend.dst_alpha_op)
395         | PDMA_OUT_CTRL_SRCALPHA_OP_SET(config->alphablend.src_alpha_op)
396         | PDMA_OUT_CTRL_ABLEND_MODE_SET(config->alphablend.mode)
397         | PDMA_OUT_CTRL_FORMAT_SET(format);
398 
399     ptr->RGB2YUV_COEF0 = PDMA_RGB2YUV_COEF0_ENABLE_SET(config->rgb2yuv_config.enable)
400         | PDMA_RGB2YUV_COEF0_YCBCR_MODE_SET(config->rgb2yuv_config.ycbcr_mode)
401         | PDMA_RGB2YUV_COEF0_C0_SET(config->rgb2yuv_config.c0)
402         | PDMA_RGB2YUV_COEF0_UV_OFFSET_SET(config->rgb2yuv_config.uv_offset)
403         | PDMA_RGB2YUV_COEF0_Y_OFFSET_SET(config->rgb2yuv_config.y_offset);
404     ptr->RGB2YUV_COEF1 = PDMA_RGB2YUV_COEF1_C1_SET(config->rgb2yuv_config.c1)
405         | PDMA_RGB2YUV_COEF1_C4_SET(config->rgb2yuv_config.c4);
406     ptr->RGB2YUV_COEF2 = PDMA_RGB2YUV_COEF2_C2_SET(config->rgb2yuv_config.c2)
407         | PDMA_RGB2YUV_COEF2_C3_SET(config->rgb2yuv_config.c3);
408     ptr->RGB2YUV_COEF3 = PDMA_RGB2YUV_COEF3_C6_SET(config->rgb2yuv_config.c6)
409         | PDMA_RGB2YUV_COEF3_C5_SET(config->rgb2yuv_config.c5);
410     ptr->RGB2YUV_COEF4 = PDMA_RGB2YUV_COEF4_C8_SET(config->rgb2yuv_config.c8)
411         | PDMA_RGB2YUV_COEF4_C7_SET(config->rgb2yuv_config.c7);
412 }
413 
414 #define PDMA_ERROR_STATUS_MASK (PDMA_STAT_AXI_0_WRITE_ERR_MASK \
415                               | PDMA_STAT_AXI_1_READ_ERR_MASK \
416                               | PDMA_STAT_AXI_0_READ_ERR_MASK)
417 #define PDMA_BUSY_STATUS_MASK (PDMA_STAT_BLOCKY_MASK \
418                               | PDMA_STAT_BLOCKX_MASK)
419 
pdma_check_status(PDMA_Type * ptr,uint32_t * status)420 hpm_stat_t pdma_check_status(PDMA_Type *ptr, uint32_t *status)
421 {
422     uint32_t stat = ptr->STAT;
423     if (stat & PDMA_BUSY_STATUS_MASK) {
424         if (status) {
425             *status = stat;
426         }
427         return status_pdma_busy;
428     }
429     if (stat & PDMA_ERROR_STATUS_MASK) {
430         if (status) {
431             *status = stat;
432         }
433         ptr->STAT = PDMA_ERROR_STATUS_MASK;
434         return status_pdma_error;
435     }
436     if ((stat & PDMA_STAT_PDMA_DONE_MASK) == PDMA_STAT_PDMA_DONE_MASK) {
437         return status_pdma_done;
438     }
439     return status_pdma_idle;
440 }
441 
pdma_fill_color(PDMA_Type * ptr,uint32_t dst,uint32_t dst_width,uint32_t width,uint32_t height,uint32_t color,uint8_t alpha,display_pixel_format_t format,bool wait,uint32_t * status)442 hpm_stat_t pdma_fill_color(PDMA_Type *ptr, uint32_t dst, uint32_t dst_width,
443                            uint32_t width, uint32_t height,
444                            uint32_t color, uint8_t alpha,
445                            display_pixel_format_t format,
446                            bool wait, uint32_t *status)
447 {
448     pdma_config_t config;
449     pdma_plane_config_t plane_src;
450     pdma_plane_config_t plane_dst;
451     display_yuv2rgb_coef_t yuv2rgb_coef;
452     pdma_output_config_t output;
453 
454     if (((display_pixel_format_is_yuv_format(format)) && (width & 1))
455         || !(width > 8 || height > 8)) {
456         return status_invalid_argument;
457     }
458 
459     pdma_get_default_config(ptr, &config, format);
460     pdma_get_default_plane_config(ptr, &plane_src, format);
461     pdma_get_default_plane_config(ptr, &plane_dst, format);
462     pdma_get_default_yuv2rgb_coef_config(ptr, &yuv2rgb_coef, format);
463     pdma_get_default_output_config(ptr, &output, format);
464 
465     config.enable_plane = pdma_plane_both;
466     if (width <= 16) {
467         config.block_size = pdma_blocksize_8x8;
468     } else {
469         config.block_size = pdma_blocksize_16x16;
470     }
471     pdma_init(ptr, &config);
472 
473     plane_src.buffer = dst;
474     plane_src.width = 1;
475     plane_src.height = 1;
476     plane_src.background = 0;
477 
478     plane_dst.buffer = dst;
479     plane_dst.width = 1;
480     plane_dst.height = 1;
481     plane_dst.background = (alpha << 24) | (color & ~(0xFF << 24));
482     pdma_config_planes(ptr, &plane_src, &plane_dst, &yuv2rgb_coef);
483 
484     output.buffer = dst;
485     output.plane[pdma_plane_dst].x = 0;
486     output.plane[pdma_plane_dst].y = 0;
487     output.plane[pdma_plane_dst].width = width;
488     output.plane[pdma_plane_dst].height = height;
489     output.pitch = display_get_pitch_length_in_byte(format, dst_width);
490 
491     output.alphablend.mode = display_alphablend_mode_clear;
492 
493     output.width = width;
494     output.height = height;
495 
496     pdma_config_output(ptr, &output);
497     pdma_start(ptr);
498     if (wait) {
499         hpm_stat_t stat;
500         do {
501             stat = pdma_check_status(ptr, status);
502         } while ((stat != status_pdma_done) && (stat != status_pdma_error));
503         pdma_stop(ptr);
504         return stat;
505     }
506     return status_success;
507 }
508 
pdma_flip_rotate(PDMA_Type * ptr,uint32_t dst,uint32_t dst_width,uint32_t src,uint32_t src_width,uint32_t x,uint32_t y,uint32_t width,uint32_t height,pdma_flip_t flip,pdma_rotate_t rotate,uint8_t alpha,display_pixel_format_t format,bool wait,uint32_t * status)509 hpm_stat_t pdma_flip_rotate(PDMA_Type *ptr, uint32_t dst, uint32_t dst_width,
510                     uint32_t src, uint32_t src_width, uint32_t x, uint32_t y,
511                     uint32_t width, uint32_t height,
512                     pdma_flip_t flip, pdma_rotate_t rotate, uint8_t alpha,
513                     display_pixel_format_t format,
514                     bool wait, uint32_t *status)
515 {
516     pdma_config_t config;
517     pdma_plane_config_t plane_src;
518     pdma_plane_config_t plane_dst;
519     display_yuv2rgb_coef_t yuv2rgb_coef;
520     pdma_output_config_t output;
521 
522     if ((width + x > dst_width)
523         /* YUV422 requires width to be 2-pixel aligned */
524         || ((display_pixel_format_is_yuv_format(format)) && (width & 1))
525         || !(width > 8 || height > 8)) {
526         return status_invalid_argument;
527     }
528 
529     pdma_get_default_config(ptr, &config, format);
530     pdma_get_default_plane_config(ptr, &plane_src, format);
531     pdma_get_default_plane_config(ptr, &plane_dst, format);
532     pdma_get_default_yuv2rgb_coef_config(ptr, &yuv2rgb_coef, format);
533     pdma_get_default_output_config(ptr, &output, format);
534 
535     config.enable_plane = pdma_plane_both;
536     if (width <= 16) {
537         config.block_size = pdma_blocksize_8x8;
538     } else {
539         config.block_size = pdma_blocksize_16x16;
540     }
541     pdma_init(ptr, &config);
542 
543     plane_src.buffer = src;
544     plane_src.height = height;
545     plane_src.width = width;
546     plane_src.pitch = display_get_pitch_length_in_byte(format, src_width);
547     plane_src.flip = flip;
548     plane_src.rotate = rotate;
549 
550     plane_dst.buffer = src;
551     plane_dst.height = 1;
552     plane_dst.width = 1;
553     plane_dst.pitch = display_get_pitch_length_in_byte(format, dst_width);
554     plane_dst.flip = pdma_flip_none;
555     plane_dst.rotate = pdma_rotate_0_degree;
556     pdma_config_planes(ptr, &plane_src, &plane_dst, &yuv2rgb_coef);
557 
558     output.buffer = dst + (y * dst_width + x) * display_get_pixel_size_in_byte(format);
559 
560     output.alphablend.src_alpha = alpha;
561     output.alphablend.src_alpha_op = display_alpha_op_override;
562     output.alphablend.mode = display_alphablend_mode_src_over;
563 
564     output.plane[pdma_plane_src].x = 0;
565     output.plane[pdma_plane_src].y = 0;
566     output.pitch = display_get_pitch_length_in_byte(format, dst_width);
567 
568     if ((rotate == pdma_rotate_90_degree)
569             || (rotate == pdma_rotate_270_degree)) {
570         output.width = height;
571         output.height = width;
572         output.plane[pdma_plane_src].width = height;
573         output.plane[pdma_plane_src].height = width;
574     } else {
575         output.plane[pdma_plane_src].width = width;
576         output.plane[pdma_plane_src].height = height;
577         output.width = width;
578         output.height = height;
579     }
580 
581     pdma_config_output(ptr, &output);
582     pdma_start(ptr);
583     if (wait) {
584         hpm_stat_t stat;
585         do {
586             stat = pdma_check_status(ptr, status);
587         } while ((stat != status_pdma_done) && (stat != status_pdma_error));
588         pdma_stop(ptr);
589         return stat;
590     }
591     return status_success;
592 }
593 
pdma_blit(PDMA_Type * ptr,uint32_t dst,uint32_t dst_width,uint32_t src,uint32_t src_width,uint32_t x,uint32_t y,uint32_t width,uint32_t height,uint8_t alpha,display_pixel_format_t format,bool wait,uint32_t * status)594 hpm_stat_t pdma_blit(PDMA_Type *ptr,
595                      uint32_t dst, uint32_t dst_width,
596                      uint32_t src, uint32_t src_width,
597                      uint32_t x, uint32_t y, uint32_t width, uint32_t height,
598                      uint8_t alpha,
599                      display_pixel_format_t format,
600                      bool wait, uint32_t *status)
601 {
602     pdma_config_t config;
603     pdma_plane_config_t plane_src;
604     pdma_plane_config_t plane_dst;
605     display_yuv2rgb_coef_t yuv2rgb_coef;
606     pdma_output_config_t output;
607 
608     if ((width + x > dst_width)
609         /* YUV422 requires width to be 2-pixel aligned */
610         || ((display_pixel_format_is_yuv_format(format)) && (width & 1))
611         || !(width > 8 || height > 8)) {
612         return status_invalid_argument;
613     }
614 
615     pdma_get_default_config(ptr, &config, format);
616     pdma_get_default_plane_config(ptr, &plane_src, format);
617     pdma_get_default_plane_config(ptr, &plane_dst, format);
618     pdma_get_default_yuv2rgb_coef_config(ptr, &yuv2rgb_coef, format);
619     pdma_get_default_output_config(ptr, &output, format);
620 
621     config.enable_plane = pdma_plane_both;
622     if (width <= 16) {
623         config.block_size = pdma_blocksize_8x8;
624     } else {
625         config.block_size = pdma_blocksize_16x16;
626     }
627     pdma_init(ptr, &config);
628 
629     plane_src.buffer = src;
630     plane_src.width = width;
631     plane_src.height = height;
632     plane_src.pitch = display_get_pitch_length_in_byte(format, src_width);
633     plane_src.background = 0x00FFFFFF;
634 
635     plane_dst.buffer = dst + (y * dst_width + x) * display_get_pixel_size_in_byte(format);
636     plane_dst.width = width;
637     plane_dst.height = height;
638     plane_dst.pitch = display_get_pitch_length_in_byte(format, dst_width);
639     pdma_config_planes(ptr, &plane_src, &plane_dst, &yuv2rgb_coef);
640 
641     output.buffer = dst + (y * dst_width + x) * display_get_pixel_size_in_byte(format);
642 
643     output.plane[pdma_plane_src].x = 0;
644     output.plane[pdma_plane_src].y = 0;
645     output.plane[pdma_plane_src].width = width;
646     output.plane[pdma_plane_src].height = height;
647 
648     output.plane[pdma_plane_dst].x = 0;
649     output.plane[pdma_plane_dst].y = 0;
650     output.plane[pdma_plane_dst].width = width;
651     output.plane[pdma_plane_dst].height = height;
652 
653     output.alphablend.src_alpha = alpha;
654     output.alphablend.src_alpha_op = display_alpha_op_override;
655     output.alphablend.mode = display_alphablend_mode_src_over;
656 
657     output.width = width;
658     output.height = height;
659     output.pitch = display_get_pitch_length_in_byte(format, dst_width);
660 
661     pdma_config_output(ptr, &output);
662     pdma_start(ptr);
663     if (wait) {
664         hpm_stat_t stat;
665         do {
666             stat = pdma_check_status(ptr, status);
667         } while ((stat != status_pdma_done) && (stat != status_pdma_error));
668         pdma_stop(ptr);
669         return stat;
670     }
671     return status_success;
672 }
673 
pdma_calculate_scale(uint32_t t,uint32_t target_t,pdma_decimation_t * dec,uint32_t * scale)674 static void pdma_calculate_scale(uint32_t t, uint32_t target_t,
675                                 pdma_decimation_t *dec, uint32_t *scale)
676 {
677     uint32_t tmp;
678     tmp = ((t << PDMA_SCALE_FRAC_BITS) / target_t) >> PDMA_SCALE_FRAC_BITS;
679     if (tmp >= 16) {
680         *dec = pdma_decimation_by_8;
681         *scale = 2U << PDMA_SCALE_FRAC_BITS;
682         return;
683     }
684     if (tmp > 8) {
685         *dec = pdma_decimation_by_8;
686     } else if (tmp > 4) {
687         *dec = pdma_decimation_by_4;
688     } else if (tmp > 2) {
689         *dec = pdma_decimation_by_2;
690     } else {
691         *dec = pdma_decimation_by_1;
692     }
693 
694     *scale = (((t >> *dec) << PDMA_SCALE_FRAC_BITS) / target_t);
695     return;
696 }
697 
pdma_scale(PDMA_Type * ptr,uint32_t dst,uint32_t dst_width,uint32_t src,uint32_t src_width,uint32_t x,uint32_t y,uint32_t width,uint32_t height,uint32_t target_width,uint32_t target_height,uint8_t alpha,display_pixel_format_t format,bool wait,uint32_t * status)698 hpm_stat_t pdma_scale(PDMA_Type *ptr,
699                      uint32_t dst, uint32_t dst_width,
700                      uint32_t src, uint32_t src_width,
701                      uint32_t x, uint32_t y, uint32_t width, uint32_t height,
702                      uint32_t target_width, uint32_t target_height,
703                      uint8_t alpha,
704                      display_pixel_format_t format,
705                      bool wait, uint32_t *status)
706 {
707     uint32_t scale;
708     pdma_decimation_t dec;
709 
710     pdma_config_t config;
711     pdma_plane_config_t plane_src;
712     pdma_plane_config_t plane_dst;
713     display_yuv2rgb_coef_t yuv2rgb_coef;
714     pdma_output_config_t output;
715 
716     if ((target_width + x > dst_width)
717         /* YUV422 requires width to be 2-pixel aligned */
718         || ((display_pixel_format_is_yuv_format(format)) && (width & 1))
719         || !(width > 8 || height > 8)) {
720         return status_invalid_argument;
721     }
722 
723     pdma_get_default_config(ptr, &config, format);
724     pdma_get_default_plane_config(ptr, &plane_src, format);
725     pdma_get_default_plane_config(ptr, &plane_dst, format);
726     pdma_get_default_yuv2rgb_coef_config(ptr, &yuv2rgb_coef, format);
727     pdma_get_default_output_config(ptr, &output, format);
728 
729     config.enable_plane = pdma_plane_both;
730     if (width <= 16) {
731         config.block_size = pdma_blocksize_8x8;
732     } else {
733         config.block_size = pdma_blocksize_16x16;
734     }
735     pdma_init(ptr, &config);
736 
737     plane_src.buffer = src;
738     plane_src.width = width;
739     plane_src.height = height;
740     plane_src.pitch = display_get_pitch_length_in_byte(format, src_width);
741 
742     pdma_calculate_scale(width, target_width, &dec, &scale);
743     plane_src.x_scale = scale;
744     plane_src.x_dec = dec;
745     pdma_calculate_scale(height, target_height, &dec, &scale);
746     plane_src.y_scale = scale;
747     plane_src.y_dec = dec;
748     plane_src.background = 0x00FFFFFF;
749 
750     if (display_pixel_format_is_yuv_format(format)) {
751         plane_src.x_offset = PDMA_YUV_SCALE_DEFAULT_X_OFFSET;
752     }
753 
754     plane_dst.buffer = dst + (y * dst_width + x) * display_get_pixel_size_in_byte(format);
755     plane_dst.width = width;
756     plane_dst.height = height;
757     plane_dst.pitch = display_get_pitch_length_in_byte(format, dst_width);
758     pdma_config_planes(ptr, &plane_src, &plane_dst, &yuv2rgb_coef);
759 
760     output.buffer = dst + (y * dst_width + x) * display_get_pixel_size_in_byte(format);
761 
762     output.plane[pdma_plane_src].x = 0;
763     output.plane[pdma_plane_src].y = 0;
764     output.plane[pdma_plane_src].width = target_width;
765     output.plane[pdma_plane_src].height = target_height;
766 
767     output.plane[pdma_plane_dst].x = 0;
768     output.plane[pdma_plane_dst].y = 0;
769     output.plane[pdma_plane_dst].width = target_width;
770     output.plane[pdma_plane_dst].height = target_height;
771 
772     output.alphablend.src_alpha = alpha;
773     output.alphablend.src_alpha_op = display_alpha_op_override;
774     output.alphablend.mode = display_alphablend_mode_src_over;
775 
776     output.width = target_width;
777     output.height = target_height;
778     output.pitch = display_get_pitch_length_in_byte(format, dst_width);
779 
780     pdma_config_output(ptr, &output);
781     pdma_start(ptr);
782     if (wait) {
783         hpm_stat_t stat;
784         do {
785             stat = pdma_check_status(ptr, status);
786         } while ((stat != status_pdma_done) && (stat != status_pdma_error));
787         pdma_stop(ptr);
788         return stat;
789     }
790     return status_success;
791 
792 }
793