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