1 /*
2 * g2d_ovl_v.c
3 *
4 * Copyright (c) 2007-2019 Allwinnertech Co., Ltd.
5 * Author: zhengxiaobin <zhengxiaobin@allwinnertech.com>
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17 #include <stdlib.h>
18 #include "g2d_ovl_v.h"
19
g2d_ovl_v_calc_coarse(struct ovl_v_submodule * p_ovl_v,__u32 format,__u32 inw,__u32 inh,__u32 outw,__u32 outh,__u32 * midw,__u32 * midh)20 __s32 g2d_ovl_v_calc_coarse(struct ovl_v_submodule *p_ovl_v, __u32 format, __u32 inw,
21 __u32 inh, __u32 outw, __u32 outh, __u32 *midw,
22 __u32 *midh)
23 {
24 __u32 tmp;
25 __s32 ret = -1;
26 struct g2d_mixer_ovl_v_reg *p_reg = p_ovl_v->get_reg(p_ovl_v);
27
28 if (!p_reg)
29 goto OUT;
30
31 switch (format) {
32 case G2D_FORMAT_IYUV422_V0Y1U0Y0:
33 case G2D_FORMAT_IYUV422_Y1V0Y0U0:
34 case G2D_FORMAT_IYUV422_U0Y1V0Y0:
35 case G2D_FORMAT_IYUV422_Y1U0Y0V0: {
36 /* interleaved YUV422 format */
37 *midw = inw;
38 *midh = inh;
39 break;
40 }
41 case G2D_FORMAT_YUV422UVC_V1U1V0U0:
42 case G2D_FORMAT_YUV422UVC_U1V1U0V0:
43 case G2D_FORMAT_YUV422_PLANAR: {
44 if (inw >= (outw << 3)) {
45 *midw = outw << 3;
46 tmp = (*midw << 16) | inw;
47 p_reg->hor_down_sample0.dwval = tmp;
48 tmp = (*midw << 15) | ((inw + 1) >> 1);
49 p_reg->hor_down_sample1.dwval = tmp;
50 } else
51 *midw = inw;
52 if (inh >= (outh << 2)) {
53 *midh = (outh << 2);
54 tmp = (*midh << 16) | inh;
55 p_reg->ver_down_sample0.dwval = tmp;
56 p_reg->ver_down_sample1.dwval = tmp;
57 } else
58 *midh = inh;
59 break;
60 }
61 case G2D_FORMAT_Y8:
62 case G2D_FORMAT_YUV420_PLANAR:
63 case G2D_FORMAT_YUV420UVC_V1U1V0U0:
64 case G2D_FORMAT_YUV420UVC_U1V1U0V0: {
65 if (inw >= (outw << 3)) {
66 *midw = outw << 3;
67 tmp = (*midw << 16) | inw;
68 p_reg->hor_down_sample0.dwval = tmp;
69 tmp = (*midw << 15) | ((inw + 1) >> 1);
70 p_reg->hor_down_sample1.dwval = tmp;
71 } else
72 *midw = inw;
73 if (inh >= (outh << 2)) {
74 *midh = (outh << 2);
75 tmp = (*midh << 16) | inh;
76 p_reg->ver_down_sample0.dwval = tmp;
77 tmp = (*midh << 15) | ((inh + 1) >> 1);
78 p_reg->ver_down_sample1.dwval = tmp;
79 } else
80 *midh = inh;
81 break;
82 }
83 case G2D_FORMAT_YUV411_PLANAR:
84 case G2D_FORMAT_YUV411UVC_V1U1V0U0:
85 case G2D_FORMAT_YUV411UVC_U1V1U0V0: {
86 if (inw >= (outw << 3)) {
87 *midw = outw << 3;
88 tmp = ((*midw) << 16) | inw;
89 p_reg->hor_down_sample0.dwval = tmp;
90 tmp = ((*midw) << 14) | ((inw + 3) >> 2);
91 p_reg->hor_down_sample1.dwval = tmp;
92 } else
93 *midw = inw;
94 if (inh >= (outh << 2)) {
95 *midh = (outh << 2);
96 tmp = ((*midh) << 16) | inh;
97 p_reg->ver_down_sample0.dwval = tmp;
98 p_reg->ver_down_sample1.dwval = tmp;
99 } else
100 *midh = inh;
101 break;
102 }
103 default:
104 if (inw >= (outw << 3)) {
105 *midw = outw << 3;
106 tmp = ((*midw) << 16) | inw;
107 p_reg->hor_down_sample0.dwval = tmp;
108 p_reg->hor_down_sample1.dwval = tmp;
109 } else
110 *midw = inw;
111 if (inh >= (outh << 2)) {
112 *midh = (outh << 2);
113 tmp = ((*midh) << 16) | inh;
114 p_reg->ver_down_sample0.dwval = tmp;
115 p_reg->ver_down_sample1.dwval = tmp;
116 } else
117 *midh = inh;
118 break;
119 }
120 p_ovl_v->set_block_dirty(p_ovl_v, 0, 1);
121 ret = 0;
122 OUT:
123 return ret;
124 }
125
126 /**
127 * fillcolor set
128 * @color_value:fill color value
129 */
g2d_ovl_v_fc_set(struct ovl_v_submodule * p_ovl_v,__u32 color_value)130 __s32 g2d_ovl_v_fc_set(struct ovl_v_submodule *p_ovl_v, __u32 color_value)
131 {
132 __s32 ret = -1;
133 struct g2d_mixer_ovl_v_reg *p_reg = p_ovl_v->get_reg(p_ovl_v);
134 if (!p_reg)
135 goto OUT;
136
137 p_reg->ovl_attr.bits.lay_fillcolor_en = 1;
138 p_reg->ovl_fill_color = color_value;
139 p_ovl_v->set_block_dirty(p_ovl_v, 0, 1);
140 ret = 0;
141
142 OUT:
143 return ret;
144 }
145
146 /**
147 * @sel:layer no.
148 * @para avoid_flag is a sign of whether or not to avoid the black point bug cause by g2d
149 */
g2d_vlayer_set(struct ovl_v_submodule * p_ovl_v,__u32 sel,g2d_image_enh * p_image,u8 avoid_flag)150 __s32 g2d_vlayer_set(struct ovl_v_submodule *p_ovl_v, __u32 sel, g2d_image_enh *p_image, u8 avoid_flag)
151 {
152 unsigned long long addr0, addr1, addr2;
153 __u32 tmp;
154 __u32 ycnt, ucnt, vcnt;
155 __u32 pitch0, pitch1, pitch2;
156 __u32 ch, cw, cy, cx;
157 __s32 ret = -1;
158 struct g2d_mixer_ovl_v_reg *p_reg = p_ovl_v->get_reg(p_ovl_v);
159
160 if (!p_reg)
161 goto OUT;
162
163 p_reg->ovl_attr.bits.lay_fbfmt = p_image->format;
164 p_reg->ovl_attr.bits.alpha_mode = p_image->mode;
165
166 /**
167 * except for the scaler function, bpremul is equal to 0,
168 * the code under if is only used by the scaler function
169 */
170 if (p_image->bpremul)
171 p_reg->ovl_attr.bits.lay_premul_ctl = 1;
172 if (avoid_flag)
173 p_reg->ovl_attr.bits.lay_premul_ctl = 0;
174 p_reg->ovl_attr.bits.lay_glbalpha = p_image->alpha & 0xff;
175 p_reg->ovl_attr.bits.lay_en = 1;
176
177 p_reg->ovl_mem.bits.lay_width =
178 (p_image->clip_rect.w == 0 ? 0 : p_image->clip_rect.w - 1) & 0x1fff;
179 p_reg->ovl_mem.bits.lay_height =
180 (p_image->clip_rect.h == 0 ? 0 : p_image->clip_rect.h - 1) & 0x1fff;
181
182 p_reg->ovl_winsize.bits.width =
183 (p_image->clip_rect.w == 0 ? 0 : p_image->clip_rect.w - 1) & 0x1fff;
184 p_reg->ovl_winsize.bits.height =
185 (p_image->clip_rect.h == 0 ? 0 : p_image->clip_rect.h - 1) & 0x1fff;
186
187 /* offset is set to 0, ovl size is set to layer size */
188 p_reg->ovl_mem_coor.dwval = 0;
189 if ((p_image->format >= G2D_FORMAT_YUV422UVC_V1U1V0U0)
190 && (p_image->format <= G2D_FORMAT_YUV422_PLANAR)) {
191 cw = p_image->width >> 1;
192 ch = p_image->height;
193 cx = p_image->clip_rect.x >> 1;
194 cy = p_image->clip_rect.y;
195 }
196
197 else if ((p_image->format >= G2D_FORMAT_YUV420UVC_V1U1V0U0)
198 && (p_image->format <= G2D_FORMAT_YUV420_PLANAR)) {
199 cw = p_image->width >> 1;
200 ch = p_image->height >> 1;
201 cx = p_image->clip_rect.x >> 1;
202 cy = p_image->clip_rect.y >> 1;
203 }
204
205 else if ((p_image->format >= G2D_FORMAT_YUV411UVC_V1U1V0U0)
206 && (p_image->format <= G2D_FORMAT_YUV411_PLANAR)) {
207 cw = p_image->width >> 2;
208 ch = p_image->height;
209 cx = p_image->clip_rect.x >> 2;
210 cy = p_image->clip_rect.y;
211 }
212
213 else {
214 cw = 0;
215 ch = 0;
216 cx = 0;
217 cy = 0;
218 }
219 g2d_byte_cal(p_image->format, &ycnt, &ucnt, &vcnt);
220 pitch0 = cal_align(ycnt * p_image->width, p_image->align[0]);
221 p_reg->ovl_mem_pitch0 = pitch0;
222 pitch1 = cal_align(ucnt * cw, p_image->align[1]);
223 p_reg->ovl_mem_pitch1 = pitch1;
224 pitch2 = cal_align(vcnt * cw, p_image->align[2]);
225 p_reg->ovl_mem_pitch2 = pitch2;
226 addr0 =
227 p_image->laddr[0] + ((__u64) p_image->haddr[0] << 32) +
228 pitch0 * p_image->clip_rect.y + ycnt * p_image->clip_rect.x;
229 p_reg->ovl_mem_low_addr0 = addr0 & 0xffffffff;
230 addr1 =
231 p_image->laddr[1] + ((__u64) p_image->haddr[1] << 32) + pitch1 * cy +
232 ucnt * cx;
233 p_reg->ovl_mem_low_addr1 = addr1 & 0xffffffff;
234 addr2 =
235 p_image->laddr[2] + ((__u64) p_image->haddr[2] << 32) + pitch2 * cy +
236 vcnt * cx;
237 p_reg->ovl_mem_low_addr2 = addr2 & 0xffffffff;
238 tmp = ((addr0 >> 32) & 0xff) | ((addr1 >> 32) & 0xff) << 8 |
239 ((addr2 >> 32) & 0xff) << 16;
240 p_reg->ovl_mem_high_addr.dwval = tmp;
241 if (p_image->bbuff == 0)
242 g2d_ovl_v_fc_set(p_ovl_v, p_image->color);
243 p_ovl_v->set_block_dirty(p_ovl_v, 0, 1);
244 ret = 0;
245 OUT:
246 return ret;
247 }
248
g2d_vlayer_overlay_set(struct ovl_v_submodule * p_ovl_v,__u32 sel,g2d_coor * coor,__u32 w,__u32 h)249 __s32 g2d_vlayer_overlay_set(struct ovl_v_submodule *p_ovl_v, __u32 sel,
250 g2d_coor *coor, __u32 w, __u32 h)
251 {
252 __s32 ret = -1;
253 struct g2d_mixer_ovl_v_reg *p_reg = p_ovl_v->get_reg(p_ovl_v);
254
255 if (!p_reg)
256 goto OUT;
257
258 p_reg->ovl_winsize.bits.width = (w - 1) & 0x1fff;
259 p_reg->ovl_winsize.bits.height = (h - 1) & 0x1fff;
260
261 p_reg->ovl_mem_coor.bits.lay_xcoor = coor->x;
262 p_reg->ovl_mem_coor.bits.lay_ycoor = coor->y;
263 ret = 0;
264 OUT:
265 return ret;
266 }
267
ovl_v_rcq_setup(struct ovl_v_submodule * p_ovl_v,u8 * base,struct g2d_rcq_mem_info * p_rcq_info)268 static int ovl_v_rcq_setup(struct ovl_v_submodule *p_ovl_v, u8 *base,
269 struct g2d_rcq_mem_info *p_rcq_info)
270 {
271 u8 *reg_base = base + G2D_V0;
272 int ret = -1;
273
274 if (!p_ovl_v) {
275 G2D_ERR_MSG("Null pointer!\n");
276 goto OUT;
277 }
278
279 p_ovl_v->reg_info->size = sizeof(struct g2d_mixer_ovl_v_reg);
280 p_ovl_v->reg_info->vir_addr = (u8 *)g2d_top_reg_memory_alloc(
281 p_ovl_v->reg_info->size, (void *)&(p_ovl_v->reg_info->phy_addr),
282 p_rcq_info);
283
284 if (!p_ovl_v->reg_info->vir_addr) {
285 G2D_ERR_MSG("Malloc writeback reg rcq memory fail!\n");
286 goto OUT;
287 }
288
289 p_ovl_v->reg_blks->vir_addr = p_ovl_v->reg_info->vir_addr;
290 p_ovl_v->reg_blks->phy_addr = p_ovl_v->reg_info->phy_addr;
291 p_ovl_v->reg_blks->size = p_ovl_v->reg_info->size;
292 p_ovl_v->reg_blks->reg_addr = reg_base;
293 ret = 0;
294
295 OUT:
296 return ret;
297 }
298
ovl_v_get_reg_block_num(struct ovl_v_submodule * p_ovl_v)299 static __u32 ovl_v_get_reg_block_num(struct ovl_v_submodule *p_ovl_v)
300 {
301 if (p_ovl_v)
302 return p_ovl_v->reg_blk_num;
303 return 0;
304 }
305
ovl_v_get_reg_block(struct ovl_v_submodule * p_ovl_v,struct g2d_reg_block ** blks)306 static __s32 ovl_v_get_reg_block(struct ovl_v_submodule *p_ovl_v,
307 struct g2d_reg_block **blks)
308 {
309 int i = 0;
310 if (p_ovl_v) {
311 for (i = 0; i < p_ovl_v->reg_blk_num; ++i)
312 blks[i] = p_ovl_v->reg_blks + i;
313 }
314 return 0;
315 }
316
ovl_v_get_reg(struct ovl_v_submodule * p_ovl_v)317 static struct g2d_mixer_ovl_v_reg *ovl_v_get_reg(struct ovl_v_submodule *p_ovl_v)
318 {
319 #if G2D_MIXER_RCQ_USED == 1
320 return (struct g2d_mixer_ovl_v_reg *)(p_ovl_v->reg_blks
321 ->vir_addr);
322 #else
323 return (struct g2d_mixer_ovl_v_reg *)(p_ovl_v->reg_blks
324 ->reg_addr);
325 #endif
326 return NULL;
327 }
328
ovl_v_set_block_dirty(struct ovl_v_submodule * p_ovl_v,__u32 blk_id,__u32 dirty)329 static void ovl_v_set_block_dirty(struct ovl_v_submodule *p_ovl_v, __u32 blk_id, __u32 dirty)
330 {
331 #if G2D_MIXER_RCQ_USED == 1
332 if (p_ovl_v && p_ovl_v->reg_blks->rcq_hd)
333 p_ovl_v->reg_blks->rcq_hd->dirty.bits.dirty = dirty;
334 else
335 G2D_ERR_MSG("Null pointer!\n");
336 #else
337
338 if (p_ovl_v)
339 p_ovl_v->reg_blks->dirty = dirty;
340 else
341 G2D_ERR_MSG("Null pointer!\n");
342 #endif
343 }
344
345
ovl_v_get_rcq_mem_size(struct ovl_v_submodule * p_ovl_v)346 static __u32 ovl_v_get_rcq_mem_size(struct ovl_v_submodule *p_ovl_v)
347 {
348 return G2D_RCQ_BYTE_ALIGN(sizeof(struct g2d_mixer_ovl_v_reg));
349 }
350
ovl_v_destory(struct ovl_v_submodule * p_ovl_v)351 static __s32 ovl_v_destory(struct ovl_v_submodule *p_ovl_v)
352 {
353 if (p_ovl_v) {
354 free(p_ovl_v->reg_blks);
355 p_ovl_v->reg_blks = NULL;
356
357 free(p_ovl_v->reg_info);
358 p_ovl_v->reg_info = NULL;
359 free(p_ovl_v);
360 }
361
362 return 0;
363 }
364
365 struct ovl_v_submodule *
g2d_ovl_v_submodule_setup(struct g2d_mixer_frame * p_frame)366 g2d_ovl_v_submodule_setup(struct g2d_mixer_frame *p_frame)
367 {
368 struct ovl_v_submodule *p_ovl_v = NULL;
369
370 p_ovl_v = hal_malloc(sizeof(struct ovl_v_submodule));
371
372 if (!p_ovl_v) {
373 G2D_ERR_MSG("malloc wb submodule fail!\n");
374 return NULL;
375 }
376 memset(p_ovl_v, 0, sizeof(struct ovl_v_submodule));
377 p_ovl_v->rcq_setup = ovl_v_rcq_setup;
378 p_ovl_v->reg_blk_num = VI_LAYER_NUMBER;
379 p_ovl_v->get_reg_block_num = ovl_v_get_reg_block_num;
380 p_ovl_v->get_reg_block = ovl_v_get_reg_block;
381 p_ovl_v->get_reg = ovl_v_get_reg;
382 p_ovl_v->set_block_dirty = ovl_v_set_block_dirty;
383 p_ovl_v->get_rcq_mem_size = ovl_v_get_rcq_mem_size;
384 p_ovl_v->destory = ovl_v_destory;
385
386 p_ovl_v->reg_blks =
387 hal_malloc(sizeof(struct g2d_reg_block) * p_ovl_v->reg_blk_num);
388 p_ovl_v->reg_info =
389 hal_malloc(sizeof(struct g2d_reg_mem_info));
390
391 if (!p_ovl_v->reg_blks || !p_ovl_v->reg_info) {
392 G2D_ERR_MSG("malloc wb reg info fail!\n");
393 goto FREE_WB;
394 }
395 memset(p_ovl_v->reg_blks, 0, sizeof(struct g2d_reg_block) * p_ovl_v->reg_blk_num);
396 memset(p_ovl_v->reg_info, 0, sizeof(struct g2d_reg_mem_info));
397
398 return p_ovl_v;
399 FREE_WB:
400 free(p_ovl_v->reg_blks);
401 free(p_ovl_v->reg_info);
402 free(p_ovl_v);
403
404 return NULL;
405 }
406