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