1 /*
2 * g2d_wb/g2d_wb.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_wb.h"
19
wb_rcq_setup(struct wb_submodule * p_wb,u8 * base,struct g2d_rcq_mem_info * p_rcq_info)20 static int wb_rcq_setup(struct wb_submodule *p_wb, u8 *base,
21 struct g2d_rcq_mem_info *p_rcq_info)
22 {
23 u8 *reg_base = base + G2D_WB;
24 int ret = -1;
25
26 if (!p_wb) {
27 G2D_ERR_MSG("Null pointer!\n");
28 goto OUT;
29 }
30
31 p_wb->reg_info->size = sizeof(struct g2d_mixer_write_back_reg);
32 p_wb->reg_info->vir_addr = (u8 *)g2d_top_reg_memory_alloc(
33 p_wb->reg_info->size, (void *)&(p_wb->reg_info->phy_addr),
34 p_rcq_info);
35
36 if (!p_wb->reg_info->vir_addr) {
37 G2D_ERR_MSG("Malloc writeback reg rcq memory fail!\n");
38 goto OUT;
39 }
40
41 p_wb->reg_blks->vir_addr = p_wb->reg_info->vir_addr;
42 p_wb->reg_blks->phy_addr = p_wb->reg_info->phy_addr;
43 p_wb->reg_blks->size = p_wb->reg_info->size;
44 p_wb->reg_blks->reg_addr = reg_base;
45 ret = 0;
46
47 OUT:
48 return ret;
49 }
50
wb_get_reg_block_num(struct wb_submodule * p_wb)51 static __u32 wb_get_reg_block_num(struct wb_submodule *p_wb)
52 {
53 if (p_wb)
54 return p_wb->reg_blk_num;
55 return 0;
56 }
57
wb_get_reg_block(struct wb_submodule * p_wb,struct g2d_reg_block ** blks)58 static __s32 wb_get_reg_block(struct wb_submodule *p_wb,
59 struct g2d_reg_block **blks)
60 {
61 __s32 i = 0, ret = -1;
62
63 if (p_wb) {
64 for (i = 0; i < p_wb->reg_blk_num; ++i)
65 blks[i] = p_wb->reg_blks + i;
66 ret = 0;
67 }
68
69 return ret;
70 }
71
wb_get_reg(struct wb_submodule * p_wb)72 static struct g2d_mixer_write_back_reg *wb_get_reg(struct wb_submodule *p_wb)
73 {
74 #if G2D_MIXER_RCQ_USED == 1
75 return (struct g2d_mixer_write_back_reg *)(p_wb->reg_blks
76 ->vir_addr);
77 #else
78 return (struct g2d_mixer_write_back_reg *)(p_wb->reg_blks
79 ->reg_addr);
80 #endif
81 return NULL;
82 }
83
84
wb_set_block_dirty(struct wb_submodule * p_wb,__u32 blk_id,__u32 dirty)85 static void wb_set_block_dirty(struct wb_submodule *p_wb, __u32 blk_id, __u32 dirty)
86 {
87 #if G2D_MIXER_RCQ_USED == 1
88 if (p_wb && p_wb->reg_blks->rcq_hd)
89 p_wb->reg_blks->rcq_hd->dirty.bits.dirty = dirty;
90 else
91 G2D_ERR_MSG("Null pointer!\n");
92 #else
93
94 if (p_wb)
95 p_wb->reg_blks->dirty = dirty;
96 else
97 G2D_ERR_MSG("Null pointer!\n");
98 #endif
99 }
100
g2d_wb_set(struct wb_submodule * p_wb,g2d_image_enh * p_image)101 __s32 g2d_wb_set(struct wb_submodule *p_wb, g2d_image_enh *p_image)
102 {
103 struct g2d_mixer_write_back_reg *p_reg = NULL;
104 __u64 addr0, addr1, addr2;
105 __u32 ycnt, ucnt, vcnt;
106 __u32 pitch0, pitch1, pitch2;
107 __u32 ch, cw, cy, cx;
108 __s32 ret = -1;
109
110 if (p_wb && p_image) {
111 p_reg = p_wb->get_reg(p_wb);
112 if (!p_reg)
113 goto OUT;
114 p_reg->wb_attr.bits.fmt = p_image->format;
115 p_reg->data_size.bits.height =
116 (!p_image->clip_rect.h) ? 0 : p_image->clip_rect.h - 1;
117 p_reg->data_size.bits.width =
118 (!p_image->clip_rect.w) ? 0 : p_image->clip_rect.w - 1;
119
120 if ((p_image->format >= G2D_FORMAT_YUV422UVC_V1U1V0U0) &&
121 (p_image->format <= G2D_FORMAT_YUV422_PLANAR)) {
122 cw = p_image->width >> 1;
123 ch = p_image->height;
124 cx = p_image->clip_rect.x >> 1;
125 cy = p_image->clip_rect.y;
126 } else if ((p_image->format >= G2D_FORMAT_YUV420UVC_V1U1V0U0) &&
127 (p_image->format <= G2D_FORMAT_YUV420_PLANAR)) {
128 cw = p_image->width >> 1;
129 ch = p_image->height >> 1;
130 cx = p_image->clip_rect.x >> 1;
131 cy = p_image->clip_rect.y >> 1;
132 } else if ((p_image->format >= G2D_FORMAT_YUV411UVC_V1U1V0U0) &&
133 (p_image->format <= G2D_FORMAT_YUV411_PLANAR)) {
134 cw = p_image->width >> 2;
135 ch = p_image->height;
136 cx = p_image->clip_rect.x >> 2;
137 cy = p_image->clip_rect.y;
138 } else {
139 cw = 0;
140 ch = 0;
141 cx = 0;
142 cy = 0;
143 }
144
145 g2d_byte_cal(p_image->format, &ycnt, &ucnt, &vcnt);
146 pitch0 = cal_align(ycnt * p_image->width, p_image->align[0]);
147 p_reg->pitch0 = pitch0;
148 pitch1 = cal_align(ucnt * cw, p_image->align[1]);
149 p_reg->pitch1 = pitch1;
150 pitch2 = cal_align(vcnt * cw, p_image->align[2]);
151 p_reg->pitch2 = pitch2;
152
153 addr0 = p_image->laddr[0] + ((__u64)p_image->haddr[0] << 32) +
154 pitch0 * p_image->clip_rect.y +
155 ycnt * p_image->clip_rect.x;
156 p_reg->laddr0 = addr0 & 0xffffffff;
157 p_reg->haddr0 = (addr0 >> 32) & 0xff;
158 addr1 = p_image->laddr[1] + ((__u64)p_image->haddr[1] << 32) +
159 pitch1 * cy + ucnt * cx;
160 p_reg->laddr1 = addr1 & 0xffffffff;
161 p_reg->haddr1 = (addr1 >> 32) & 0xff;
162 addr2 = p_image->laddr[2] + ((__u64)p_image->haddr[2] << 32) +
163 pitch2 * cy + vcnt * cx;
164 p_reg->laddr2 = addr2 & 0xffffffff;
165 p_reg->haddr2 = (addr1 >> 32) & 0xff;
166 p_wb->set_block_dirty(p_wb, 0, 1);
167 }
168
169 OUT:
170 return ret;
171 }
172
wb_get_rcq_mem_size(struct wb_submodule * p_wb)173 static __u32 wb_get_rcq_mem_size(struct wb_submodule *p_wb)
174 {
175 return G2D_RCQ_BYTE_ALIGN(sizeof(struct g2d_mixer_write_back_reg));
176 }
177
wb_destory(struct wb_submodule * p_wb)178 static __s32 wb_destory(struct wb_submodule *p_wb)
179 {
180 __s32 ret = -1;
181
182 if (p_wb) {
183 free(p_wb->reg_blks);
184 p_wb->reg_blks = NULL;
185
186 free(p_wb->reg_info);
187 p_wb->reg_info = NULL;
188 ret = 0;
189 free(p_wb);
190 }
191
192 return ret;
193 }
194
g2d_wb_submodule_setup(struct g2d_mixer_frame * p_frame)195 struct wb_submodule *g2d_wb_submodule_setup(struct g2d_mixer_frame *p_frame)
196 {
197 struct wb_submodule *p_wb = NULL;
198
199 p_wb = hal_malloc(sizeof(struct wb_submodule));
200
201 if (!p_wb) {
202 G2D_ERR_MSG("malloc wb submodule fail!\n");
203 return NULL;
204 }
205 memset(p_wb, 0, sizeof(struct wb_submodule));
206 p_wb->rcq_setup = wb_rcq_setup;
207 p_wb->reg_blk_num = 1;
208 p_wb->get_reg_block_num = wb_get_reg_block_num;
209 p_wb->get_reg_block = wb_get_reg_block;
210 p_wb->get_reg = wb_get_reg;
211 p_wb->set_block_dirty = wb_set_block_dirty;
212 p_wb->get_rcq_mem_size = wb_get_rcq_mem_size;
213 p_wb->destory = wb_destory;
214
215 p_wb->reg_blks =
216 hal_malloc(sizeof(struct g2d_reg_block) * p_wb->reg_blk_num);
217 p_wb->reg_info =
218 hal_malloc(sizeof(struct g2d_reg_mem_info));
219
220 if (!p_wb->reg_blks || !p_wb->reg_info) {
221 G2D_ERR_MSG("Kmalloc wb reg info fail!\n");
222 goto FREE_WB;
223 }
224 memset(p_wb->reg_blks, 0, sizeof(struct g2d_reg_block) * p_wb->reg_blk_num);
225 memset(p_wb->reg_info, 0, sizeof(struct g2d_reg_mem_info));
226
227 return p_wb;
228 FREE_WB:
229 free(p_wb->reg_blks);
230 free(p_wb->reg_info);
231 free(p_wb);
232
233 return NULL;
234 }
235