• 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_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