• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 Allwinnertech, z.q <zengqi@allwinnertech.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  */
9 
10 #include "disp_format_convert.h"
11 
12 #if defined SUPPORT_WB
13 #include "include.h"
14 
15 #define FORMAT_MANAGER_NUM 1
16 
17 static struct format_manager fmt_mgr[FORMAT_MANAGER_NUM];
18 
disp_get_format_manager(unsigned int id)19 struct format_manager *disp_get_format_manager(unsigned int id)
20 {
21 	return &fmt_mgr[id];
22 }
23 
24 #if defined(__LINUX_PLAT__)
disp_format_convert_finish_proc(int irq,void * parg)25 s32 disp_format_convert_finish_proc(int irq, void *parg)
26 #else
27 s32 disp_format_convert_finish_proc(void *parg)
28 #endif
29 {
30 	struct format_manager *mgr = (struct format_manager *)parg;
31 
32 	if (mgr == NULL)
33 		return DISP_IRQ_RETURN;
34 
35 	if (disp_al_get_eink_wb_status(mgr->disp) == 0) {
36 		mgr->write_back_finish = 1;
37 		wake_up_interruptible(&(mgr->write_back_queue));
38 	} else
39 		__wrn("convert err!\n");
40 	disp_al_clear_eink_wb_interrupt(mgr->disp);
41 
42 	return DISP_IRQ_RETURN;
43 }
44 
disp_format_convert_enable(unsigned int id)45 static s32 disp_format_convert_enable(unsigned int id)
46 {
47 	struct format_manager *mgr = &fmt_mgr[id];
48 	s32 ret = -1;
49 	static int first = 1;
50 
51 	if (mgr == NULL) {
52 		__wrn("input param is null\n");
53 		return -1;
54 	}
55 
56 	ret =
57 	    disp_sys_register_irq(mgr->irq_num, 0,
58 				  disp_format_convert_finish_proc, (void *)mgr,
59 				  0, 0);
60 	if (ret != 0) {
61 		__wrn("fail to format convert irq\n");
62 		return ret;
63 	}
64 
65 	disp_sys_enable_irq(mgr->irq_num);
66 	if (first) {
67 		clk_disable_unprepare(mgr->clk);
68 		first = 0;
69 	}
70 
71 	ret = reset_control_deassert(mgr->rst);
72 	if (ret) {
73 		DE_WRN("reset_control_deassert for rst failed, ret=%d\n", ret);
74 		return ret;
75 	}
76 
77 	ret = clk_prepare_enable(mgr->clk);
78 	if (ret) {
79 		DE_WRN("%s(%d): clk_prepare_enable for clk failed, ret=%d\n", __func__, __LINE__, ret);
80 		return ret;
81 	}
82 
83 	ret = clk_prepare_enable(mgr->clk_parent);
84 	if (ret) {
85 		DE_WRN("%s(%d): clk_prepare_enable for clk_parent failed, ret=%d\n", __func__, __LINE__, ret);
86 		return ret;
87 	}
88 
89 	ret = clk_prepare_enable(mgr->clk_bus);
90 	if (ret) {
91 		DE_WRN("%s(%d): clk_prepare_enable for clk_bus failed\n", __func__, __LINE__);
92 		return ret;
93 	}
94 
95 	/* enable de clk, enable write back clk */
96 	disp_al_de_clk_enable(mgr->disp);
97 	disp_al_write_back_clk_init(mgr->disp);
98 
99 	return 0;
100 }
101 
disp_format_convert_disable(unsigned int id)102 static s32 disp_format_convert_disable(unsigned int id)
103 {
104 	struct format_manager *mgr = &fmt_mgr[id];
105 	s32 ret = -1;
106 
107 	if (mgr == NULL) {
108 		__wrn("%s: input param is null\n", __func__);
109 		return -1;
110 	}
111 
112 	/* disable write back clk, disable de clk */
113 	disp_al_write_back_clk_exit(mgr->disp);
114 	ret = disp_al_de_clk_disable(mgr->disp);
115 	if (ret != 0)
116 		return ret;
117 
118 	clk_disable_unprepare(mgr->clk_bus);
119 	clk_disable_unprepare(mgr->clk);
120 	ret = reset_control_assert(mgr->rst);
121 	if (ret)
122 		DE_WRN("%s(%d): reset_control_assert for rst failed\n", __func__, __LINE__);
123 
124 	disp_sys_disable_irq(mgr->irq_num);
125 	disp_sys_unregister_irq(mgr->irq_num, disp_format_convert_finish_proc,
126 				(void *)mgr);
127 
128 	return 0;
129 }
130 
131 struct disp_manager_data mdata;
132 struct disp_layer_config_data ldata[16];
133 
disp_format_convert_start(unsigned int id,struct disp_layer_config_inner * config,unsigned int layer_num,struct image_format * dest)134 static s32 disp_format_convert_start(unsigned int id,
135 				     struct disp_layer_config_inner *config,
136 				     unsigned int layer_num,
137 				     struct image_format *dest)
138 {
139 	struct format_manager *mgr = &fmt_mgr[id];
140 #ifdef EINK_DMABUF_USED
141 	struct dmabuf_item *item[16] = {NULL};
142 	struct fb_address_transfer fb;
143 #endif
144 	s32 ret = -1, k = 0;
145 	u32 lay_total_num = 0;
146 
147 	long timerout = (100 * HZ) / 1000;	/*100ms */
148 
149 	if ((dest == NULL) || (mgr == NULL)) {
150 		__wrn(KERN_WARNING "input param is null\n");
151 		return -1;
152 	}
153 
154 	if (dest->format == DISP_FORMAT_8BIT_GRAY) {
155 		__debug("dest_addr = 0x%p\n", (void *)dest->addr1);
156 
157 		lay_total_num = de_feat_get_num_layers(mgr->disp);
158 		memset((void *)&mdata, 0, sizeof(struct disp_manager_data));
159 		memset((void *)ldata, 0, 16 * sizeof(ldata[0]));
160 
161 		mdata.flag = MANAGER_ALL_DIRTY;
162 		mdata.config.enable = 1;
163 		mdata.config.interlace = 0;
164 		mdata.config.blank = 0;
165 		mdata.config.size.x = 0;
166 		mdata.config.size.y = 0;
167 		mdata.config.size.width = dest->width;
168 		mdata.config.size.height = dest->height;
169 		mdata.config.de_freq = clk_get_rate(mgr->clk);
170 
171 		for (k = 0; k < layer_num; k++) {
172 			ldata[k].flag = LAYER_ALL_DIRTY;
173 
174 			memcpy((void *)&ldata[k].config, (void *)&config[k],
175 					sizeof(*config));
176 
177 #ifdef EINK_DMABUF_USED
178 			item[k] = NULL;
179 			if (ldata[k].config.info.fb.fd && (true == config[k].enable)) {
180 				item[k] = disp_dma_map(ldata[k].config.info.fb.fd);
181 				if (item[k] == NULL) {
182 					DE_WRN("disp wb map fd %d fail!\n", ldata[k].config.info.fb.fd);
183 					return -1;
184 				}
185 
186 				__debug("layer%d map ok, fd=%d, addr=0x%08x\n",
187 					k,
188 					ldata[k].config.info.fb.fd,
189 					item[k]->dma_addr);
190 
191 				fb.format = ldata[k].config.info.fb.format;
192 				memcpy(fb.size, ldata[k].config.info.fb.size,
193 						sizeof(struct disp_rectsz) * 3);
194 
195 				memcpy(fb.align, ldata[k].config.info.fb.align,
196 						sizeof(int) * 3);
197 				fb.depth = ldata[k].config.info.fb.depth;
198 				fb.dma_addr = item[k]->dma_addr;
199 				disp_set_fb_info(&fb, true);
200 				memcpy(ldata[k].config.info.fb.addr, fb.addr,
201 						sizeof(long long) * 3);
202 			}
203 #endif
204 		}
205 		disp_al_manager_apply(mgr->disp, &mdata);
206 		disp_al_layer_apply(mgr->disp, ldata, layer_num);
207 		disp_al_manager_sync(mgr->disp);
208 		disp_al_manager_update_regs(mgr->disp);
209 		disp_al_eink_wb_reset(mgr->disp);
210 		disp_al_eink_wb_dereset(mgr->disp);
211 		disp_al_set_eink_wb_param(mgr->disp, dest->width, dest->height,
212 				(unsigned int)dest->addr1);
213 
214 		/* enable inttrrupt */
215 		disp_al_enable_eink_wb_interrupt(mgr->disp);
216 		disp_al_enable_eink_wb(mgr->disp);
217 
218 #ifdef __UBOOT_PLAT__
219 		/* wait write back complete */
220 		while (disp_al_get_eink_wb_status(mgr->disp) != EWB_OK)
221 			mdelay(1);
222 #else
223 		timerout =
224 			wait_event_interruptible_timeout(mgr->write_back_queue,
225 					(mgr->write_back_finish == 1),
226 					timerout);
227 		mgr->write_back_finish = 0;
228 		if (timerout == 0) {
229 			__wrn("wait write back timeout!\n");
230 			disp_al_disable_eink_wb_interrupt(mgr->disp);
231 			disp_al_disable_eink_wb(mgr->disp);
232 			ret = -1;
233 			goto EXIT;
234 		}
235 
236 		disp_al_disable_eink_wb_interrupt(mgr->disp);
237 #endif
238 		disp_al_disable_eink_wb(mgr->disp);
239 		ret = 0;
240 	} else
241 		__wrn("src_format(), dest_format(0x%x) is not support\n",
242 				dest->format);
243 
244 EXIT:
245 #ifdef EINK_DMABUF_USED
246 	for (k = 0; k < layer_num; k++) {
247 		if (NULL != item[k])
248 			disp_dma_unmap(item[k]);
249 	}
250 #endif
251 	return ret;
252 }
253 
disp_init_format_convert_manager(struct disp_bsp_init_para * para)254 s32 disp_init_format_convert_manager(struct disp_bsp_init_para *para)
255 {
256 	s32 ret = -1;
257 	unsigned int i = 0;
258 	struct format_manager *mgr;
259 
260 	for (i = 0; i < FORMAT_MANAGER_NUM; i++) {
261 		mgr = &fmt_mgr[i];
262 		memset(mgr, 0, sizeof(struct format_manager));
263 
264 		mgr->disp = i;
265 		init_waitqueue_head(&(mgr->write_back_queue));
266 		mgr->write_back_finish = 0;
267 		mgr->irq_num = para->irq_no[DISP_MOD_DE];
268 		mgr->enable = disp_format_convert_enable;
269 		mgr->disable = disp_format_convert_disable;
270 		mgr->start_convert = disp_format_convert_start;
271 		mgr->clk = para->clk_de[i];
272 		mgr->clk_bus = para->clk_bus_de[i];
273 		mgr->rst = para->reset_bus_de[i];
274 		disp_al_set_eink_wb_base(i, para->reg_base[DISP_MOD_DE]);
275 	}
276 
277 	return ret;
278 }
279 
disp_exit_format_convert_manager(void)280 void disp_exit_format_convert_manager(void)
281 {
282 	unsigned int i = 0;
283 	struct format_manager *mgr = NULL;
284 
285 	for (i = 0; i < FORMAT_MANAGER_NUM; i++) {
286 		if (mgr->disable)
287 			mgr->disable(i);
288 	}
289 	return;
290 }
291 
292 #endif
293