1 /*
2  * g2d_ovl_u.c
3  *
4  * Copyright (c) 2007-2019 Allwinnertech Co., Ltd.
5  * Author: zhengxiaobin <zhengxiaobin@allwinnertech.com>
6  *
7  *
8  * This software is licensed under the terms of the GNU General Public
9  * License version 2, as published by the Free Software Foundation, and
10  * may be copied, distributed, and modified under those terms.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  */
18 #include <stdlib.h>
19 
20 #include "g2d_ovl_u.h"
21 
g2d_ovl_u_fc_set(struct ovl_u_submodule * p_ovl_u,__u32 sel,__u32 color_value)22 __s32 g2d_ovl_u_fc_set(struct ovl_u_submodule *p_ovl_u, __u32 sel,
23 		       __u32 color_value)
24 {
25 	__s32 ret = -1;
26 	struct g2d_mixer_ovl_u_reg *p_reg = p_ovl_u->get_reg(p_ovl_u, sel);
27 
28 	if (!p_reg)
29 		goto OUT;
30 
31 	p_reg->ovl_attr.bits.lay_fillcolor_en = 1;
32 	p_reg->ovl_fill_color = color_value;
33 
34 	p_ovl_u->set_block_dirty(p_ovl_u, sel, 1);
35 
36 	ret = 0;
37 OUT:
38 	return ret;
39 }
40 
g2d_uilayer_set(struct ovl_u_submodule * p_ovl_u,__u32 sel,g2d_image_enh * p_img)41 __s32 g2d_uilayer_set(struct ovl_u_submodule *p_ovl_u, __u32 sel,
42 		      g2d_image_enh *p_img)
43 {
44 	__u64 addr0;
45 	__u32 ycnt, ucnt, vcnt;
46 	__u32 pitch0;
47 	__s32 ret = -1;
48 	struct g2d_mixer_ovl_u_reg *p_reg = p_ovl_u->get_reg(p_ovl_u, sel);
49 
50 	if (!p_reg)
51 		goto OUT;
52 
53 	p_reg->ovl_attr.bits.lay_glbalpha = p_img->alpha & 0xff;
54 	if (p_img->bpremul)
55 		p_reg->ovl_attr.bits.lay_premul_ctl = 1;
56 	p_reg->ovl_attr.bits.lay_fbfmt = p_img->format;
57 	p_reg->ovl_attr.bits.alpha_mode = p_img->mode;
58 	p_reg->ovl_attr.bits.lay_en = 1;
59 
60 	p_reg->ovl_mem.bits.lay_width =
61 	    (p_img->clip_rect.w == 0 ? 0 : p_img->clip_rect.w - 1) & 0x1fff;
62 	p_reg->ovl_mem.bits.lay_height =
63 	    (p_img->clip_rect.h == 0 ? 0 : p_img->clip_rect.h - 1) & 0x1fff;
64 	p_reg->ovl_winsize.bits.width =
65 	    (p_img->clip_rect.w == 0 ? 0 : p_img->clip_rect.w - 1) & 0x1fff;
66 	p_reg->ovl_winsize.bits.height =
67 	    (p_img->clip_rect.h == 0 ? 0 : p_img->clip_rect.h - 1) & 0x1fff;
68 
69 	p_reg->ovl_mem_coor.dwval = 0;
70 	g2d_byte_cal(p_img->format, &ycnt, &ucnt, &vcnt);
71 	pitch0 = cal_align(ycnt * p_img->width, p_img->align[0]);
72 	p_reg->ovl_mem_pitch0 = pitch0;
73 
74 	addr0 =
75 	    p_img->laddr[0] + ((__u64) p_img->haddr[0] << 32) +
76 	    pitch0 * p_img->clip_rect.y + ycnt * p_img->clip_rect.x;
77 	p_reg->ovl_mem_low_addr0 = addr0 & 0xffffffff;
78 	p_reg->ovl_mem_high_addr = (addr0 >> 32) & 0xff;
79 
80 	if (p_img->bbuff == 0)
81 		g2d_ovl_u_fc_set(p_ovl_u, sel, p_img->color);
82 
83 	p_ovl_u->set_block_dirty(p_ovl_u, sel, 1);
84 	ret = 0;
85 OUT:
86 	return ret;
87 }
88 
g2d_uilayer_overlay_set(struct ovl_u_submodule * p_ovl_u,__u32 sel,g2d_coor * coor,__u32 w,__u32 h)89 __s32 g2d_uilayer_overlay_set(struct ovl_u_submodule *p_ovl_u, __u32 sel,
90 					g2d_coor *coor,  __u32 w, __u32 h)
91 {
92 	__s32 ret = -1;
93 	struct g2d_mixer_ovl_u_reg *p_reg = p_ovl_u->get_reg(p_ovl_u, sel);
94 
95 	if (!p_reg)
96 		goto OUT;
97 
98 	p_reg->ovl_winsize.bits.width = (w - 1) & 0x1fff;
99 	p_reg->ovl_winsize.bits.height = (h - 1) & 0x1fff;
100 
101 	p_reg->ovl_mem_coor.bits.lay_xcoor = coor->x;
102 	p_reg->ovl_mem_coor.bits.lay_ycoor = coor->y;
103 	ret = 0;
104 OUT:
105 	return ret;
106 }
107 
ovl_u_rcq_setup(struct ovl_u_submodule * p_ovl_u,u8 * base,struct g2d_rcq_mem_info * p_rcq_info)108 static int ovl_u_rcq_setup(struct ovl_u_submodule *p_ovl_u, u8 *base,
109 			   struct g2d_rcq_mem_info *p_rcq_info)
110 {
111 	u8 *reg_base = base + G2D_UI0;
112 	__s32 ret = -1;
113 
114 	if (!p_ovl_u) {
115 		G2D_ERR_MSG("Null pointer!\n");
116 		goto OUT;
117 	}
118 
119 	p_ovl_u->reg_info->size = sizeof(struct g2d_mixer_ovl_v_reg);
120 	p_ovl_u->reg_info->vir_addr = (u8 *)g2d_top_reg_memory_alloc(
121 	    p_ovl_u->reg_info->size,
122 	    (void *)&(p_ovl_u->reg_info->phy_addr), p_rcq_info);
123 
124 	if (!p_ovl_u->reg_info->vir_addr) {
125 		G2D_ERR_MSG("Malloc writeback reg rcq memory fail!\n");
126 		goto OUT;
127 	}
128 	p_ovl_u->reg_blks[0].vir_addr = p_ovl_u->reg_info->vir_addr;
129 	p_ovl_u->reg_blks[0].phy_addr = p_ovl_u->reg_info->phy_addr;
130 	p_ovl_u->reg_blks[0].size = p_ovl_u->reg_info->size;
131 	p_ovl_u->reg_blks[0].reg_addr = reg_base;
132 
133 	p_ovl_u->reg_info->size = sizeof(struct g2d_mixer_ovl_v_reg);
134 	p_ovl_u->reg_info->vir_addr = (u8 *)g2d_top_reg_memory_alloc(
135 	    p_ovl_u->reg_info->size,
136 	    (void *)&(p_ovl_u->reg_info->phy_addr), p_rcq_info);
137 
138 	if (!p_ovl_u->reg_info->vir_addr) {
139 		G2D_ERR_MSG("Malloc writeback reg rcq memory fail!\n");
140 		goto OUT;
141 	}
142 	p_ovl_u->reg_blks[1].vir_addr = p_ovl_u->reg_info->vir_addr;
143 	p_ovl_u->reg_blks[1].phy_addr = p_ovl_u->reg_info->phy_addr;
144 	p_ovl_u->reg_blks[1].size = p_ovl_u->reg_info->size;
145 	p_ovl_u->reg_blks[1].reg_addr = base + G2D_UI1;
146 
147 	p_ovl_u->reg_info->size = sizeof(struct g2d_mixer_ovl_v_reg);
148 	p_ovl_u->reg_info->vir_addr = (u8 *)g2d_top_reg_memory_alloc(
149 	    p_ovl_u->reg_info->size,
150 	    (void *)&(p_ovl_u->reg_info->phy_addr), p_rcq_info);
151 
152 	if (!p_ovl_u->reg_info->vir_addr) {
153 		G2D_ERR_MSG("Malloc writeback reg rcq memory fail!\n");
154 		goto OUT;
155 	}
156 	p_ovl_u->reg_blks[2].vir_addr = p_ovl_u->reg_info->vir_addr;
157 	p_ovl_u->reg_blks[2].phy_addr = p_ovl_u->reg_info->phy_addr;
158 	p_ovl_u->reg_blks[2].size = p_ovl_u->reg_info->size;
159 	p_ovl_u->reg_blks[2].reg_addr = base + G2D_UI2;
160 	ret = 0;
161 
162 OUT:
163 	return ret;
164 }
165 
ovl_v_get_reg_block_num(struct ovl_u_submodule * p_ovl_u)166 static __u32 ovl_v_get_reg_block_num(struct ovl_u_submodule *p_ovl_u)
167 {
168 	if (p_ovl_u)
169 		return p_ovl_u->reg_blk_num;
170 	return 0;
171 }
172 
ovl_v_get_reg_block(struct ovl_u_submodule * p_ovl_u,struct g2d_reg_block ** blks)173 static __s32 ovl_v_get_reg_block(struct ovl_u_submodule *p_ovl_u,
174 			    struct g2d_reg_block **blks)
175 {
176 	__s32 i = 0, ret = -1;
177 
178 	if (p_ovl_u) {
179 		for (i = 0; i < p_ovl_u->reg_blk_num; ++i)
180 			blks[i] = p_ovl_u->reg_blks + i;
181 		ret = 0;
182 	}
183 
184 	return ret;
185 }
186 
ovl_v_get_reg(struct ovl_u_submodule * p_ovl_u,__u32 sel)187 static struct g2d_mixer_ovl_u_reg *ovl_v_get_reg(struct ovl_u_submodule *p_ovl_u, __u32 sel)
188 {
189 	if (sel > p_ovl_u->reg_blk_num - 1)
190 		goto OUT;
191 
192 #if G2D_MIXER_RCQ_USED == 1
193 	return (struct g2d_mixer_ovl_u_reg *)(p_ovl_u->reg_blks[sel]
194 						   .vir_addr);
195 #else
196 	return (struct g2d_mixer_ovl_u_reg *)(p_ovl_u->reg_blks[sel]
197 						   .reg_addr);
198 #endif
199 OUT:
200 	return NULL;
201 }
202 
203 
ovl_v_set_block_dirty(struct ovl_u_submodule * p_ovl_u,__u32 blk_id,__u32 dirty)204 static void ovl_v_set_block_dirty(struct ovl_u_submodule *p_ovl_u, __u32 blk_id, __u32 dirty)
205 {
206 
207 	if (blk_id > p_ovl_u->reg_blk_num - 1)
208 		return;
209 
210 #if G2D_MIXER_RCQ_USED == 1
211 	if (p_ovl_u && p_ovl_u->reg_blks->rcq_hd)
212 		p_ovl_u->reg_blks[blk_id].rcq_hd->dirty.bits.dirty = dirty;
213 	else
214 		G2D_ERR_MSG("Null pointer!\n");
215 #else
216 
217 	if (p_ovl_u)
218 		p_ovl_u->reg_blks[blk_id].dirty = dirty;
219 	else
220 		G2D_ERR_MSG("Null pointer!\n");
221 #endif
222 }
223 
ovl_v_get_rcq_mem_size(struct ovl_u_submodule * p_ovl_u)224 static __u32 ovl_v_get_rcq_mem_size(struct ovl_u_submodule *p_ovl_u)
225 {
226 	return G2D_RCQ_BYTE_ALIGN(sizeof(struct g2d_mixer_ovl_v_reg)) *
227 	       p_ovl_u->reg_blk_num;
228 }
229 
ovl_u_destory(struct ovl_u_submodule * p_ovl_u)230 static __s32 ovl_u_destory(struct ovl_u_submodule *p_ovl_u)
231 {
232 	__s32 ret = -1;
233 
234 	if (p_ovl_u) {
235 		free(p_ovl_u->reg_blks);
236 		p_ovl_u->reg_blks = NULL;
237 
238 		free(p_ovl_u->reg_info);
239 		p_ovl_u->reg_info = NULL;
240 		ret = 0;
241 		free(p_ovl_u);
242 	}
243 
244 	return ret;
245 }
246 
247 struct ovl_u_submodule *
g2d_ovl_u_submodule_setup(struct g2d_mixer_frame * p_frame)248 g2d_ovl_u_submodule_setup(struct g2d_mixer_frame *p_frame)
249 {
250 	struct ovl_u_submodule *p_ovl_u = NULL;
251 
252 	p_ovl_u = hal_malloc(sizeof(struct ovl_u_submodule));
253 
254 	if (!p_ovl_u) {
255 		G2D_ERR_MSG("malloc wb submodule fail!\n");
256 		return NULL;
257 	}
258 	memset(p_ovl_u, 0, sizeof(struct ovl_u_submodule));
259 	p_ovl_u->rcq_setup = ovl_u_rcq_setup;
260 	p_ovl_u->reg_blk_num = UI_LAYER_NUMBER;
261 	p_ovl_u->get_reg_block_num = ovl_v_get_reg_block_num;
262 	p_ovl_u->get_reg_block = ovl_v_get_reg_block;
263 	p_ovl_u->get_reg = ovl_v_get_reg;
264 	p_ovl_u->set_block_dirty = ovl_v_set_block_dirty;
265 	p_ovl_u->get_rcq_mem_size = ovl_v_get_rcq_mem_size;
266 	p_ovl_u->destory = ovl_u_destory;
267 
268 	p_ovl_u->reg_blks =
269 	    hal_malloc(sizeof(struct g2d_reg_block) * p_ovl_u->reg_blk_num);
270 	p_ovl_u->reg_info =
271 	    hal_malloc(sizeof(struct g2d_reg_mem_info));
272 
273 	if (!p_ovl_u->reg_blks || !p_ovl_u->reg_info) {
274 		G2D_ERR_MSG("malloc wb reg info fail!\n");
275 		goto FREE_WB;
276 	}
277 	memset(p_ovl_u->reg_blks, 0, sizeof(struct g2d_reg_block) * p_ovl_u->reg_blk_num);
278 	memset(p_ovl_u->reg_info, 0, sizeof(struct g2d_reg_mem_info));
279 
280 	return p_ovl_u;
281 FREE_WB:
282 	free(p_ovl_u->reg_blks);
283 	free(p_ovl_u->reg_info);
284 	free(p_ovl_u);
285 
286 	return NULL;
287 }
288