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_eink.h"
11
12 #ifdef SUPPORT_EINK
13
14 #define PIPELINE_NUM 16
15 static int op_skip;
16 static struct mutex mlock;
17
__overlap_judge_skip(struct pipeline_manager * manager,u32 skip)18 static int __overlap_judge_skip(struct pipeline_manager *manager, u32 skip)
19 {
20 mutex_lock(&mlock);
21 op_skip = skip;
22 mutex_unlock(&mlock);
23 return 0;
24 }
25
26 /* return 0, no overlap, 1 overlap.*/
__overlap_judge(struct area_info pipeline_area,struct area_info update_area)27 static int __overlap_judge(struct area_info pipeline_area,
28 struct area_info update_area)
29 {
30 struct area_info *left_area;
31 struct area_info *right_area;
32
33 struct area_info *top_area;
34 struct area_info *bottom_area;
35
36 mutex_lock(&mlock);
37 if (op_skip) {
38 mutex_unlock(&mlock);
39 return 0;
40 }
41 mutex_unlock(&mlock);
42
43 if (update_area.x_top > pipeline_area.x_top) {
44 right_area = &update_area;
45 left_area = &pipeline_area;
46 } else {
47 right_area = &pipeline_area;
48 left_area = &update_area;
49 }
50
51 /* x not overlap, two area could not be overlay,
52 * if equal,is also not overlap.
53 */
54 if (right_area->x_top >= left_area->x_bottom)
55 return 0;
56
57 if (update_area.y_top > pipeline_area.y_top) {
58 top_area = &update_area;
59 bottom_area = &pipeline_area;
60 } else {
61 top_area = &pipeline_area;
62 bottom_area = &update_area;
63 }
64
65 /* y not overlap, two area could not be overlay */
66 if (top_area->y_top >= bottom_area->y_bottom)
67 return 0;
68
69 __debug("xtop=%u ,ytop=%u ,x_bo=%u ,y_bo=%u\n",
70 update_area.x_top, update_area.y_top,
71 update_area.x_bottom, update_area.y_bottom);
72
73 return 1;
74
75 }
76
77 /* return 0: empty, return 1: full*/
__free_list_status(struct pipeline_manager * manager)78 int __free_list_status(struct pipeline_manager *manager)
79 {
80 struct pipeline_info *pipeline, *tpipeline;
81 int num = 0;
82 int ret = 0;
83
84 mutex_lock(&manager->list.mlock);
85 if (list_empty(&manager->list.used_list)) {
86 ret = 0;
87 goto out;
88 }
89
90 list_for_each_entry_safe(pipeline, tpipeline, &manager->list.free_list,
91 node) {
92 num++;
93 }
94 if (num == PIPELINE_NUM) {
95 ret = 1;
96 goto out;
97 } else if (num > PIPELINE_NUM) {
98 ret = -1;
99 }
100
101 out:
102 mutex_unlock(&manager->list.mlock);
103
104 return ret;
105 }
106
107 /* return 0: empty, return 1: full,
108 * return 2: not full,not empty,
109 * return -1: err
110 */
__used_list_status(struct pipeline_manager * manager)111 int __used_list_status(struct pipeline_manager *manager)
112 {
113 struct pipeline_info *pipeline, *tpipeline;
114 int ret = 0;
115 int used_num = 0;
116
117 mutex_lock(&manager->list.mlock);
118
119 if (list_empty(&manager->list.used_list)) {
120 ret = 0;
121 goto out;
122 }
123
124 list_for_each_entry_safe(pipeline, tpipeline,
125 &manager->list.used_list, node)
126 used_num++;
127
128 if (used_num == PIPELINE_NUM)
129 ret = 1;
130 else if (used_num > PIPELINE_NUM)
131 ret = -1;
132 else
133 ret = 2;
134
135 out:
136 mutex_unlock(&manager->list.mlock);
137
138 return ret;
139 }
140
__check_overlap(struct pipeline_manager * manager,struct area_info area)141 int __check_overlap(struct pipeline_manager *manager, struct area_info area)
142 {
143 int ret = 0;
144 struct pipeline_info *pipeline, *tpipeline;
145
146 mutex_lock(&manager->list.mlock);
147
148 list_for_each_entry_safe(pipeline, tpipeline, &manager->list.used_list,
149 node) {
150 if (__overlap_judge(pipeline->area, area)) {
151 pipeline->overlap_flag = 1;
152 mutex_lock(&manager->mlock);
153 manager->overlap_num++;
154 mutex_unlock(&manager->mlock);
155 }
156 }
157
158 mutex_unlock(&manager->list.mlock);
159
160 return ret;
161 }
162
__check_overlap_num(struct pipeline_manager * manager)163 int __check_overlap_num(struct pipeline_manager *manager)
164 {
165 int ret;
166
167 mutex_lock(&manager->mlock);
168
169 if (manager->overlap_num != 0)
170 ret = 1;
171 else
172 ret = 0;
173
174 mutex_unlock(&manager->mlock);
175
176 return ret;
177 }
178
__clear_pipeline_list(struct pipeline_manager * manager)179 int __clear_pipeline_list(struct pipeline_manager *manager)
180 {
181 int ret = 0;
182 struct pipeline_info *pipeline, *tpipeline;
183
184 mutex_lock(&manager->mlock);
185
186 list_for_each_entry_safe(pipeline, tpipeline,
187 &manager->list.used_list, node) {
188
189 list_move_tail(&pipeline->node, &manager->list.free_list);
190
191 pipeline->overlap_flag = 0;
192 pipeline->frame_index = 0;
193 pipeline->total_frames = 0;
194 pipeline->enable_flag = 0;
195
196 }
197 manager->overlap_num = 0;
198
199 mutex_unlock(&manager->mlock);
200 return ret;
201 }
202
203 /* return 0:no new pipeline insert
204 * return 1:one new pipeline insert
205 * return -1:more than one pipeline insert,something is wrong.
206 */
__update_pipeline_list(struct pipeline_manager * manager,unsigned int temperature,unsigned int * tframes)207 int __update_pipeline_list(struct pipeline_manager *manager,
208 unsigned int temperature, unsigned int *tframes)
209 {
210 int ret = 0;
211 struct pipeline_info *pipeline, *tpipeline;
212 unsigned int cur_wave_paddr;
213 unsigned int new_pipelin_num = 0;
214
215 mutex_lock(&manager->list.mlock);
216 list_for_each_entry_safe(pipeline, tpipeline, &manager->list.used_list,
217 node) {
218 if ((pipeline->frame_index == pipeline->total_frames)
219 && (pipeline->total_frames != 0)) {
220 disp_al_eink_pipe_disable(manager->disp,
221 pipeline->pipeline_no);
222 pipeline->frame_index = 0;
223 pipeline->total_frames = 0;
224 pipeline->enable_flag = 0;
225
226 list_move_tail(&pipeline->node,
227 &manager->list.free_list);
228
229 mutex_lock(&manager->mlock);
230
231 if (pipeline->overlap_flag)
232 manager->overlap_num--;
233 if (manager->overlap_num < 0)
234 __wrn("overlap_num is wrong.");
235
236 pipeline->overlap_flag = 0;
237
238 mutex_unlock(&manager->mlock);
239 continue;
240 }
241
242 if (pipeline->frame_index < 1) {
243 ret =
244 disp_al_get_eink_panel_bit_num(manager->disp,
245 &pipeline->bit_num);
246 ret =
247 disp_al_get_waveform_data(manager->disp,
248 pipeline->mode,
249 temperature,
250 &pipeline->total_frames,
251 &pipeline->
252 wave_file_addr);
253 }
254 cur_wave_paddr =
255 pipeline->wave_file_addr +
256 (1 << (pipeline->bit_num << 1)) * pipeline->frame_index;
257
258 disp_al_eink_pipe_config_wavefile(manager->disp, cur_wave_paddr,
259 pipeline->pipeline_no);
260
261 pipeline->frame_index++;
262 if (!pipeline->enable_flag) {
263 disp_al_eink_pipe_enable(manager->disp,
264 pipeline->pipeline_no);
265 pipeline->enable_flag = true;
266 new_pipelin_num++;
267 *tframes = pipeline->total_frames;
268 ret = 1;
269 }
270 if (new_pipelin_num > 1) {
271 __wrn
272 ("more than one new pipelines have been inserted!");
273 ret = -1;
274 }
275 }
276
277 mutex_unlock(&manager->list.mlock);
278
279 return ret;
280 }
281
__config_and_enable_one_pipeline(struct pipeline_manager * manager,struct area_info update_area,enum eink_update_mode mode,unsigned int temperature,unsigned int * tframes)282 int __config_and_enable_one_pipeline(struct pipeline_manager *manager,
283 struct area_info update_area,
284 enum eink_update_mode mode,
285 unsigned int temperature,
286 unsigned int *tframes)
287 {
288 struct pipeline_info *pipeline, *tpipeline;
289 int ret = 0;
290 unsigned int cur_wave_paddr;
291
292 mutex_lock(&manager->list.mlock);
293
294 list_for_each_entry_safe(pipeline, tpipeline, &manager->list.free_list,
295 node) {
296 pipeline->overlap_flag = 0;
297 pipeline->frame_index = 0;
298 pipeline->mode = mode;
299 memcpy((void *)&pipeline->area, (void *)&update_area,
300 (unsigned int)sizeof(struct area_info));
301
302 if (pipeline->enable_flag)
303 __wrn("free pipeline list have enable pipeline!");
304
305 pipeline->enable_flag = true;
306
307 ret =
308 disp_al_get_eink_panel_bit_num(manager->disp,
309 &pipeline->bit_num);
310
311 ret = disp_al_get_waveform_data(manager->disp, pipeline->mode,
312 temperature,
313 &pipeline->total_frames,
314 &pipeline->wave_file_addr);
315 *tframes = pipeline->total_frames;
316 cur_wave_paddr = pipeline->wave_file_addr
317 + (1 << (pipeline->bit_num << 1)) * pipeline->frame_index;
318
319 ret =
320 disp_al_eink_pipe_config(manager->disp,
321 pipeline->pipeline_no,
322 pipeline->area);
323 ret =
324 disp_al_eink_pipe_config_wavefile(manager->disp,
325 cur_wave_paddr,
326 pipeline->pipeline_no);
327 ret =
328 disp_al_eink_pipe_enable(manager->disp,
329 pipeline->pipeline_no);
330
331 pipeline->frame_index++;
332
333 list_move_tail(&pipeline->node, &manager->list.used_list);
334
335 break;
336 }
337
338 mutex_unlock(&manager->list.mlock);
339
340 return ret;
341 }
342
__config_one_pipeline(struct pipeline_manager * manager,struct area_info update_area,enum eink_update_mode mode)343 int __config_one_pipeline(struct pipeline_manager *manager,
344 struct area_info update_area,
345 enum eink_update_mode mode)
346 {
347 struct pipeline_info *pipeline, *tpipeline;
348 int ret = 0;
349
350 mutex_lock(&manager->list.mlock);
351
352 list_for_each_entry_safe(pipeline, tpipeline, &manager->list.free_list,
353 node) {
354 pipeline->overlap_flag = 0;
355 pipeline->frame_index = 0;
356 pipeline->mode = mode;
357
358 if (pipeline->enable_flag) {
359 pipeline->enable_flag = false;
360 __wrn("free pipeline list have used pipeline!");
361 }
362
363 memcpy((void *)&pipeline->area, (void *)&update_area,
364 sizeof(struct area_info));
365
366 /*
367 * no need config wave file addr,
368 * it will config when next decode task.
369 */
370 disp_al_eink_pipe_config(manager->disp, pipeline->pipeline_no,
371 pipeline->area);
372 list_move_tail(&pipeline->node, &manager->list.used_list);
373 break;
374 }
375
376 mutex_unlock(&manager->list.mlock);
377
378 return ret;
379 }
380
pipeline_manager_init(struct disp_eink_manager * eink_manager)381 int pipeline_manager_init(struct disp_eink_manager *eink_manager)
382 {
383 int ret = 0;
384 int i;
385 struct pipeline_manager *pipeline_manager;
386 struct pipeline_info *pipeline[PIPELINE_NUM];
387
388 pipeline_manager =
389 (struct pipeline_manager *)disp_sys_malloc(
390 sizeof(struct pipeline_manager));
391 if (!pipeline_manager) {
392 __wrn("malloc eink pipeline manager memory fail!\n");
393 ret = -ENOMEM;
394 goto pipeline_mgr_err;
395 }
396 memset((void *)pipeline_manager, 0, sizeof(struct pipeline_manager));
397
398 pipeline_manager->disp = eink_manager->disp;
399 pipeline_manager->overlap_num = 0;
400
401 INIT_LIST_HEAD(&pipeline_manager->list.free_list);
402 INIT_LIST_HEAD(&pipeline_manager->list.used_list);
403
404 mutex_init(&pipeline_manager->mlock);
405 mutex_init(&pipeline_manager->list.mlock);
406 mutex_init(&mlock);
407
408 for (i = 0; i < PIPELINE_NUM; i++) {
409 pipeline[i] =
410 (struct pipeline_info *)disp_sys_malloc(
411 sizeof(struct pipeline_info));
412 if (!pipeline[i]) {
413 __wrn("malloc eink pipeline memory fail!\n");
414 ret = -ENOMEM;
415 goto pipeline_err;
416 }
417 memset((void *)pipeline[i], 0, sizeof(struct pipeline_info));
418 pipeline[i]->pipeline_no = i;
419 list_add_tail(&pipeline[i]->node,
420 &pipeline_manager->list.free_list);
421 }
422
423 pipeline_manager->check_overlap = __check_overlap;
424 pipeline_manager->op_skip = __overlap_judge_skip;
425 pipeline_manager->config_one_pipeline = __config_one_pipeline;
426 pipeline_manager->config_and_enable_one_pipeline =
427 __config_and_enable_one_pipeline;
428 pipeline_manager->update_pipeline_list = __update_pipeline_list;
429 pipeline_manager->used_list_status = __used_list_status;
430 pipeline_manager->free_list_status = __free_list_status;
431 pipeline_manager->check_overlap_num = __check_overlap_num;
432 pipeline_manager->clear_pipeline_list = __clear_pipeline_list;
433 eink_manager->pipeline_mgr = pipeline_manager;
434
435 return ret;
436
437 pipeline_err:
438 for (i = 0; i < PIPELINE_NUM; i++)
439 kfree(pipeline[i]);
440
441 pipeline_mgr_err:
442 kfree(pipeline_manager);
443
444 return ret;
445 }
446
pipeline_manager_exit(struct disp_eink_manager * eink_manager)447 int pipeline_manager_exit(struct disp_eink_manager *eink_manager)
448 {
449 int i = 0;
450 struct pipeline_manager *pipeline_manager;
451 struct pipeline_info *pipeline = NULL, *pipelinetmp = NULL;
452
453 pipeline_manager = eink_manager->pipeline_mgr;
454 list_add_tail(&pipeline[i].node,
455 &pipeline_manager->list.free_list);
456 list_for_each_entry_safe(pipeline, pipelinetmp,
457 &pipeline_manager->list.free_list,
458 node) {
459 list_del(&pipeline->node);
460 kfree((void *)pipeline);
461 }
462
463 kfree(pipeline_manager);
464 eink_manager->pipeline_mgr = NULL;
465
466 return 0;
467 }
468 #endif
469
470