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