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