• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Allwinner SoCs display driver.
3  *
4  * Copyright (C) 2016 Allwinner.
5  *
6  * This file is licensed under the terms of the GNU General Public
7  * License version 2.  This program is licensed "as is" without any
8  * warranty of any kind, whether express or implied.
9  */
10 
11 #include <linux/reset.h>
12 #include "disp_capture.h"
13 
14 struct disp_capture_info_list {
15 	struct disp_capture_info_inner info;
16 	struct list_head list;
17 	bool done;
18 	struct dmabuf_item *item;
19 };
20 
21 struct disp_capture_private_data {
22 	u32 reg_base;
23 	u32 enabled;
24 	u32 applied;
25 	s32 status; /* 0: finish; other: fail&err */
26 
27 	u32 done_sum;
28 	struct list_head req_list;
29 	u32 req_cnt;
30 	struct list_head runing_list;
31 	u32 runing_cnt;
32 	struct list_head done_list;
33 	u32 done_cnt;
34 	s32 (*shadow_protect)(u32 sel, bool protect);
35 
36 	struct clk *clk;
37 	struct clk *clk_bus;
38 	struct reset_control *rst;
39 
40 #if defined(__LINUX_PLAT__)
41 	struct mutex mlock;
42 	spinlock_t data_lock;
43 #else
44 	int mlock;
45 	int data_lock;
46 #endif
47 	struct disp_capture_info_list *cur_info;
48 	struct disp_irq_info irq_info;
49 	spinlock_t reg_lock;
50 	u32 reg_protect_cnt; /* protect reg for user's writing */
51 	u8 reg_access; /* access reg for clearing */
52 };
53 
54 static struct disp_capture *captures;
55 static struct disp_capture_private_data *capture_private;
56 struct cptr_wq_t {
57 	struct work_struct wq;
58 	struct disp_capture *cptr;
59 	u32 rcq_state;
60 };
61 
62 static struct cptr_wq_t rcq_cptr_wq;
63 
disp_get_capture(u32 disp)64 struct disp_capture *disp_get_capture(u32 disp)
65 {
66 	u32 num_screens;
67 
68 	num_screens = bsp_disp_feat_get_num_screens();
69 	if (disp >= num_screens) {
70 		DE_WRN("disp %d out of range\n", disp);
71 		return NULL;
72 	}
73 
74 	if (!bsp_disp_feat_is_support_capture(disp)) {
75 		DE_INF("screen %d not support capture\n", disp);
76 		return NULL;
77 	}
78 
79 	return &captures[disp];
80 }
81 
disp_capture_get_priv(struct disp_capture * cptr)82 static struct disp_capture_private_data *disp_capture_get_priv(struct
83 							       disp_capture
84 							       *cptr)
85 {
86 	if (cptr == NULL) {
87 		DE_WRN("NULL hdl!\n");
88 		return NULL;
89 	}
90 
91 	if (!bsp_disp_feat_is_support_capture(cptr->disp)) {
92 		DE_WRN("screen %d not support capture\n", cptr->disp);
93 		return NULL;
94 	}
95 
96 	return &capture_private[cptr->disp];
97 }
98 
disp_capture_shadow_protect(struct disp_capture * capture,bool protect)99 s32 disp_capture_shadow_protect(struct disp_capture *capture, bool protect)
100 {
101 	struct disp_capture_private_data *capturep =
102 	    disp_capture_get_priv(capture);
103 
104 	if ((capture == NULL) || (capturep == NULL)) {
105 		DE_WRN("NULL hdl!\n");
106 		return -1;
107 	}
108 
109 	if (capturep->shadow_protect)
110 		return capturep->shadow_protect(capture->disp, protect);
111 
112 	return -1;
113 }
114 
disp_capture_protect_reg_for_rcq(struct disp_capture * capture,bool protect)115 static s32 disp_capture_protect_reg_for_rcq(
116 	struct disp_capture *capture, bool protect)
117 {
118 	struct disp_capture_private_data *capturep = disp_capture_get_priv(capture);
119 	unsigned long flags;
120 
121 	if ((NULL == capture) || (NULL == capturep)) {
122 		__wrn("NULL hdl!\n");
123 		return -1;
124 	}
125 
126 	if (protect) {
127 		u32 irq_state = 0;
128 		u32 cnt = 0;
129 		u32 max_cnt = 50;
130 		u32 delay = 10;
131 
132 		do {
133 			spin_lock_irqsave(&capturep->reg_lock, flags);
134 			if (capturep->reg_access == 0) {
135 				capturep->reg_protect_cnt++;
136 				disp_al_capture_set_rcq_update(capture->disp, 0);
137 				irq_state = disp_al_capture_query_irq_state(capture->disp,
138 					DISP_AL_CAPTURE_IRQ_STATE_RCQ_ACCEPT
139 					| DISP_AL_CAPTURE_IRQ_STATE_RCQ_FINISH);
140 				spin_unlock_irqrestore(&capturep->reg_lock, flags);
141 				break;
142 			}
143 			spin_unlock_irqrestore(&capturep->reg_lock, flags);
144 
145 			cnt++;
146 			disp_delay_us(delay);
147 		} while (cnt < max_cnt);
148 
149 		if (capturep->reg_access != 0) {
150 			spin_lock_irqsave(&capturep->reg_lock, flags);
151 			capturep->reg_protect_cnt++;
152 			disp_al_capture_set_rcq_update(capture->disp, 0);
153 			irq_state = disp_al_capture_query_irq_state(capture->disp,
154 				DISP_AL_CAPTURE_IRQ_STATE_RCQ_ACCEPT
155 				| DISP_AL_CAPTURE_IRQ_STATE_RCQ_FINISH);
156 			spin_unlock_irqrestore(&capturep->reg_lock, flags);
157 		}
158 
159 		if (irq_state & DISP_AL_CAPTURE_IRQ_STATE_RCQ_ACCEPT) {
160 			u32 cnt = 0;
161 			u32 max_cnt = 500;
162 			u32 delay = 1;
163 
164 			while (!(irq_state & DISP_AL_CAPTURE_IRQ_STATE_RCQ_FINISH)
165 				&& (cnt < max_cnt)) {
166 				cnt++;
167 				disp_delay_us(delay);
168 				irq_state = disp_al_capture_query_irq_state(capture->disp,
169 					DISP_AL_CAPTURE_IRQ_STATE_RCQ_FINISH);
170 			}
171 			disp_al_capture_set_all_rcq_head_dirty(capture->disp, 0);
172 		}
173 
174 	} else {
175 		spin_lock_irqsave(&capturep->reg_lock, flags);
176 		if (capturep->reg_protect_cnt > 0)
177 			capturep->reg_protect_cnt--;
178 		if (capturep->reg_protect_cnt == 0)
179 			disp_al_capture_set_rcq_update(capture->disp, 1);
180 		spin_unlock_irqrestore(&capturep->reg_lock, flags);
181 	}
182 
183 	return 0;
184 }
185 
rcq_cptr_sync(struct work_struct * work)186 static void rcq_cptr_sync(struct work_struct *work)
187 {
188 	struct cptr_wq_t *cpwq = NULL;
189 
190 	if (!work)
191 		return;
192 	cpwq = container_of(work, struct cptr_wq_t, wq);
193 	if (!cpwq || !cpwq->cptr)
194 		return;
195 	disp_capture_sync(cpwq->cptr);
196 }
197 
disp_capture_rcq_finish_irq_handler(struct disp_capture * capture)198 static s32 disp_capture_rcq_finish_irq_handler(
199 	struct disp_capture *capture)
200 {
201 	struct disp_capture_private_data *capturep =
202 		disp_capture_get_priv(capture);
203 	unsigned long flags;
204 	u32 irq_state = 0;
205 
206 	if ((capture == NULL) || (capturep == NULL)) {
207 		__wrn("NULL hdl!\n");
208 		return -1;
209 	}
210 
211 	spin_lock_irqsave(&capturep->reg_lock, flags);
212 	if (capturep->reg_protect_cnt > 0) {
213 		spin_unlock_irqrestore(&capturep->reg_lock, flags);
214 		return 0;
215 	}
216 	capturep->reg_access = 1;
217 	irq_state = disp_al_capture_query_irq_state(capture->disp,
218 		DISP_AL_CAPTURE_IRQ_STATE_RCQ_ACCEPT
219 		| DISP_AL_CAPTURE_IRQ_STATE_RCQ_FINISH);
220 	capturep->reg_access = 0;
221 	spin_unlock_irqrestore(&capturep->reg_lock, flags);
222 
223 	if (irq_state & DISP_AL_CAPTURE_IRQ_STATE_RCQ_FINISH) {
224 		if (rcq_cptr_wq.rcq_state == 1) {
225 			rcq_cptr_wq.cptr = capture;
226 			schedule_work(&rcq_cptr_wq.wq);
227 		} else if (rcq_cptr_wq.rcq_state == 2) {
228 			disp_al_capture_set_all_rcq_head_dirty(capture->disp,
229 					0);
230 			disp_al_capture_sync(capture->disp);
231 			rcq_cptr_wq.rcq_state = 0;
232 		}
233 	}
234 	if (rcq_cptr_wq.rcq_state < 1) {
235 		rcq_cptr_wq.rcq_state = 1;
236 		rcq_cptr_wq.cptr = capture;
237 		schedule_work(&rcq_cptr_wq.wq);
238 	}
239 
240 	return 0;
241 }
242 
243 
disp_capture_irq_handler(u32 sel,u32 irq_flag,void * ptr)244 s32 disp_capture_irq_handler(u32 sel, u32 irq_flag, void *ptr)
245 {
246 	if (irq_flag & DISP_AL_CAPTURE_IRQ_FLAG_RCQ_FINISH)
247 		disp_capture_rcq_finish_irq_handler((struct disp_capture *)ptr);
248 
249 	return 0;
250 }
251 
disp_capture_clk_init(struct disp_capture * cptr)252 static s32 disp_capture_clk_init(struct disp_capture *cptr)
253 {
254 	struct disp_capture_private_data *cptrp = disp_capture_get_priv(cptr);
255 
256 	if ((cptr == NULL) || (cptrp == NULL)) {
257 		DE_WRN("NULL hdl!\n");
258 		return 0;
259 	}
260 	/* todo: int the clock */
261 
262 	return 0;
263 }
264 
disp_capture_clk_exit(struct disp_capture * cptr)265 static s32 disp_capture_clk_exit(struct disp_capture *cptr)
266 {
267 	struct disp_capture_private_data *cptrp = disp_capture_get_priv(cptr);
268 
269 	if ((cptr == NULL) || (cptrp == NULL)) {
270 		DE_WRN("NULL hdl!\n");
271 		return 0;
272 	}
273 
274 	/* todo: colse the clock */
275 
276 	return 0;
277 }
278 
disp_capture_clk_enable(struct disp_capture * cptr)279 static s32 disp_capture_clk_enable(struct disp_capture *cptr)
280 {
281 	int ret;
282 	struct disp_capture_private_data *cptrp = disp_capture_get_priv(cptr);
283 
284 	if ((cptr == NULL) || (cptrp == NULL)) {
285 		DE_WRN("NULL hdl!\n");
286 		return 0;
287 	}
288 
289 	ret = reset_control_deassert(cptrp->rst);
290 	if (ret) {
291 		DE_WRN("%s: reset_control_deassert for rst failed\n", __func__);
292 		return ret;
293 	}
294 
295 	ret = clk_prepare_enable(cptrp->clk);
296 	if (ret) {
297 		DE_WRN("%s: clk_prepare_enable for clk failed\n", __func__);
298 		return ret;
299 	}
300 
301 	ret = clk_prepare_enable(cptrp->clk_bus);
302 	if (ret) {
303 		DE_WRN("%s: clk_prepare_enable for clk_bus failed\n", __func__);
304 		return ret;;
305 	}
306 
307 	return 0;
308 }
309 
disp_capture_clk_disable(struct disp_capture * cptr)310 static s32 disp_capture_clk_disable(struct disp_capture *cptr)
311 {
312 	int ret;
313 	struct disp_capture_private_data *cptrp = disp_capture_get_priv(cptr);
314 
315 	if ((cptr == NULL) || (cptrp == NULL)) {
316 		DE_WRN("NULL hdl!\n");
317 		return 0;
318 	}
319 
320 	clk_disable_unprepare(cptrp->clk_bus);
321 	clk_disable_unprepare(cptrp->clk);
322 
323 	ret = reset_control_assert(cptrp->rst);
324 	if (ret) {
325 		DE_WRN("%s: reset_control_assert for rst failed\n", __func__);
326 		return ret;
327 	}
328 
329 	return 0;
330 }
331 
disp_capture_apply(struct disp_capture * cptr)332 s32 disp_capture_apply(struct disp_capture *cptr)
333 {
334 	return 0;
335 }
336 
disp_capture_force_apply(struct disp_capture * cptr)337 s32 disp_capture_force_apply(struct disp_capture *cptr)
338 {
339 	return 0;
340 }
341 
disp_capture_start(struct disp_capture * cptr)342 s32 disp_capture_start(struct disp_capture *cptr)
343 {
344 	struct disp_capture_private_data *cptrp = disp_capture_get_priv(cptr);
345 
346 	if ((cptr == NULL) || (cptrp == NULL)) {
347 		DE_WRN("NULL hdl!\n");
348 		return -1;
349 	}
350 	rcq_cptr_wq.rcq_state = 0;
351 	DE_INF("cap %d\n", cptr->disp);
352 
353 	mutex_lock(&cptrp->mlock);
354 	if (cptrp->enabled == 1) {
355 		DE_WRN("capture %d already started!\n", cptr->disp);
356 		mutex_unlock(&cptrp->mlock);
357 		return -1;
358 	}
359 	if (cptrp->irq_info.irq_flag)
360 		disp_register_irq(cptr->disp + DISP_SCREEN_NUM,
361 				  &cptrp->irq_info);
362 	disp_capture_clk_enable(cptr);
363 	disp_al_capture_init(cptr->disp);
364 	//TODO:move this function to disp_al_capture_init
365 	disp_al_capture_set_irq_enable(cptr->disp,
366 		cptrp->irq_info.irq_flag, 1);
367 	cptrp->enabled = 1;
368 	mutex_unlock(&cptrp->mlock);
369 
370 	return 0;
371 }
372 
disp_capture_stop(struct disp_capture * cptr)373 s32 disp_capture_stop(struct disp_capture *cptr)
374 {
375 	struct disp_capture_private_data *cptrp = disp_capture_get_priv(cptr);
376 	unsigned long flags;
377 	struct disp_capture_info_list *info_list = NULL, *temp = NULL;
378 	struct list_head drop_list;
379 
380 	if ((cptr == NULL) || (cptrp == NULL)) {
381 		DE_WRN("NULL hdl!\n");
382 		return -1;
383 	}
384 	DE_INF("cap %d\n", cptr->disp);
385 
386 	INIT_LIST_HEAD(&drop_list);
387 
388 	mutex_lock(&cptrp->mlock);
389 	if (cptrp->enabled == 1) {
390 		disp_al_capture_set_irq_enable(cptr->disp,
391 			cptrp->irq_info.irq_flag, 0);
392 		disp_al_capture_query_irq_state(cptr->disp,
393 			DISP_AL_CAPTURE_IRQ_STATE_MASK);
394 		disp_al_capture_exit(cptr->disp);
395 		disp_capture_clk_disable(cptr);
396 		if (cptrp->irq_info.irq_flag)
397 			disp_unregister_irq(cptr->disp + DISP_SCREEN_NUM,
398 				&cptrp->irq_info);
399 		cptrp->enabled = 0;
400 	}
401 	spin_lock_irqsave(&cptrp->data_lock, flags);
402 	list_for_each_entry_safe(info_list, temp, &cptrp->runing_list, list) {
403 		list_del(&info_list->list);
404 		list_add_tail(&info_list->list, &drop_list);
405 		cptrp->runing_cnt--;
406 	}
407 	list_for_each_entry_safe(info_list, temp, &cptrp->done_list, list) {
408 		list_del(&info_list->list);
409 		list_add_tail(&info_list->list, &drop_list);
410 		cptrp->done_cnt--;
411 	}
412 	list_for_each_entry_safe(info_list, temp, &cptrp->req_list, list) {
413 		list_del(&info_list->list);
414 		list_add_tail(&info_list->list, &drop_list);
415 		cptrp->req_cnt--;
416 	}
417 	spin_unlock_irqrestore(&cptrp->data_lock, flags);
418 	list_for_each_entry_safe(info_list, temp, &drop_list, list) {
419 		list_del(&info_list->list);
420 		if (info_list->item)
421 			disp_dma_unmap(info_list->item);
422 		kfree(info_list);
423 	}
424 	mutex_unlock(&cptrp->mlock);
425 
426 	return 0;
427 }
428 
429 static void
__disp_capture_info_transfer(struct disp_capture_info_inner * info_inner,struct disp_capture_info * info)430 __disp_capture_info_transfer(struct disp_capture_info_inner *info_inner,
431 			    struct disp_capture_info *info)
432 {
433 	memcpy(&info_inner->window, &info->window, sizeof(struct disp_rect));
434 	info_inner->out_frame.format = info->out_frame.format;
435 	memcpy(info_inner->out_frame.size,
436 	       info->out_frame.size,
437 	       sizeof(struct disp_rectsz) * 3);
438 	memcpy(&info_inner->out_frame.crop,
439 	       &info->out_frame.crop,
440 	       sizeof(struct disp_rect));
441 	memcpy(info_inner->out_frame.addr,
442 	       info->out_frame.addr,
443 	       sizeof(long long) * 3);
444 }
445 
446 static void
__disp_capture_info2_transfer(struct disp_capture_info_inner * info_inner,struct disp_capture_info2 * info)447 __disp_capture_info2_transfer(struct disp_capture_info_inner *info_inner,
448 			    struct disp_capture_info2 *info)
449 {
450 	memcpy(&info_inner->window, &info->window, sizeof(struct disp_rect));
451 	info_inner->out_frame.format = info->out_frame.format;
452 	memcpy(info_inner->out_frame.size,
453 	       info->out_frame.size,
454 	       sizeof(struct disp_rectsz) * 3);
455 	memcpy(&info_inner->out_frame.crop,
456 	       &info->out_frame.crop,
457 	       sizeof(struct disp_rect));
458 	info_inner->out_frame.fd = info->out_frame.fd;
459 }
460 
disp_capture_commit(struct disp_capture * cptr,struct disp_capture_info * info)461 s32 disp_capture_commit(struct disp_capture *cptr,
462 			struct disp_capture_info *info)
463 {
464 	struct disp_capture_private_data *cptrp = disp_capture_get_priv(cptr);
465 	struct disp_manager *mgr;
466 	struct disp_device *dispdev = NULL;
467 	struct disp_capture_info_list *info_list, *temp;
468 	unsigned long flags;
469 	enum disp_csc_type cs = DISP_CSC_TYPE_RGB;
470 	struct list_head done_list;
471 	int ret = -1;
472 
473 	if (NULL == cptr || NULL == cptrp) {
474 		DE_WRN("NULL hdl!\n");
475 		return -1;
476 	}
477 	INIT_LIST_HEAD(&done_list);
478 	DE_INF("cap %d\n", cptr->disp);
479 
480 	mgr = cptr->manager;
481 	if ((mgr == NULL) || (mgr->is_enabled(mgr) == 0)) {
482 		DE_WRN("manager disable!\n");
483 		return -1;
484 	}
485 
486 	dispdev = mgr->device;
487 	if (NULL == dispdev) {
488 		DE_WRN("disp device is NULL!\n");
489 		return -1;
490 	}
491 
492 	if (dispdev->get_input_csc)
493 		cs = dispdev->get_input_csc(dispdev);
494 #ifdef SUPPORT_YUV_BLEND
495 	if ((DISP_CSC_TYPE_RGB != cs) &&
496 	    ((info->out_frame.format == DISP_FORMAT_ARGB_8888) ||
497 	     (info->out_frame.format == DISP_FORMAT_ABGR_8888) ||
498 	     (info->out_frame.format == DISP_FORMAT_RGBA_8888) ||
499 	     (info->out_frame.format == DISP_FORMAT_BGRA_8888) ||
500 	     (info->out_frame.format == DISP_FORMAT_RGB_888) ||
501 	     (info->out_frame.format == DISP_FORMAT_BGR_888))) {
502 		DE_WRN("in_fmt and out_fmt not match!\n");
503 		return -1;
504 	}
505 #endif
506 
507 #ifndef WB_HAS_CSC
508 	if ((DISP_CSC_TYPE_YUV444 == cs) || (DISP_CSC_TYPE_YUV422 == cs) ||
509 	    (DISP_CSC_TYPE_YUV420 == cs)) {
510 		if ((info->out_frame.format != DISP_FORMAT_YUV420_P) &&
511 		    (info->out_frame.format != DISP_FORMAT_YUV420_SP_UVUV) &&
512 		    (info->out_frame.format != DISP_FORMAT_YUV420_SP_VUVU) &&
513 		    (info->out_frame.format != DISP_FORMAT_YUV444_I_AYUV)) {
514 			DE_WRN("out_format is not support!\n");
515 			return -1;
516 		}
517 	}
518 #endif
519 
520 	DE_INF
521 	    ("disp%d,fmt %d,pitch<%d,%d,%d>,crop<%d,%d,%d,%d>,addr<0x%llx,0x%llx,0x%llx>\n",
522 	     cptr->disp, info->out_frame.format, info->out_frame.size[0].width,
523 	     info->out_frame.size[1].width, info->out_frame.size[2].width,
524 	     info->out_frame.crop.x, info->out_frame.crop.y,
525 	     info->out_frame.crop.width, info->out_frame.crop.height,
526 	     info->out_frame.addr[0], info->out_frame.addr[1],
527 	     info->out_frame.addr[2]);
528 
529 	mutex_lock(&cptrp->mlock);
530 	if (cptrp->enabled == 0) {
531 		DE_WRN("capture %d is disabled!\n", cptr->disp);
532 		goto EXIT;
533 	}
534 	if (disp_feat_is_using_wb_rcq(cptr->disp)) {
535 		struct disp_capture_config config;
536 		u32 width = 0, height = 0;
537 
538 		memset(&config, 0, sizeof(struct disp_capture_config));
539 
540 		config.disp = cptr->disp;
541 
542 		config.out_frame.format = info->out_frame.format;
543 		memcpy(config.out_frame.size,
544 			   info->out_frame.size,
545 			   sizeof(struct disp_rectsz) * 3);
546 		memcpy(&config.out_frame.crop,
547 			   &info->out_frame.crop,
548 			   sizeof(struct disp_rect));
549 		memcpy(config.out_frame.addr,
550 			   info->out_frame.addr,
551 			   sizeof(long long) * 3);
552 
553 		memcpy(&config.in_frame.crop,
554 			&info->window,
555 			sizeof(struct disp_rect));
556 		if (DISP_CSC_TYPE_RGB == cs)
557 			config.in_frame.format = DISP_FORMAT_ARGB_8888;
558 		else if (DISP_CSC_TYPE_YUV444  == cs)
559 			config.in_frame.format = DISP_FORMAT_YUV444_P;
560 		else if (DISP_CSC_TYPE_YUV422 == cs)
561 			config.in_frame.format = DISP_FORMAT_YUV422_P;
562 		else
563 			config.in_frame.format = DISP_FORMAT_YUV420_P;
564 
565 		if (dispdev->get_resolution) {
566 			dispdev->get_resolution(dispdev, &width, &height);
567 		}
568 		config.in_frame.size[0].width = width;
569 		config.in_frame.size[1].width = width;
570 		config.in_frame.size[2].width = width;
571 		config.in_frame.size[0].height = height;
572 		config.in_frame.size[1].height = height;
573 		config.in_frame.size[2].height = height;
574 		if ((0 == config.in_frame.crop.width)
575 			|| (0 == config.in_frame.crop.height)) {
576 			config.in_frame.crop.width = width;
577 			config.in_frame.crop.height = height;
578 		}
579 
580 		DE_INF(
581 		    "disp:%d flag:%d in_fmt:%d in_fd:%d in_crop[%d %d %d "
582 		    "%d],in_size[%u %u, %u %u, %u "
583 		    "%u],in_addr[0x%llx,0x%llx,0x%llx],out_fmt:%d out_fd:%d "
584 		    "out_crop[%d %d %d %d],out_size[%u %u, %u %u, %u "
585 		    "%u],out_addr[0x%llx,0x%llx,0x%llx]\n",
586 		    config.disp, config.flags, config.in_frame.format,
587 		    config.in_frame.fd, config.in_frame.crop.x,
588 		    config.in_frame.crop.y, config.in_frame.crop.width,
589 		    config.in_frame.crop.height, config.in_frame.size[0].width,
590 		    config.in_frame.size[0].height,
591 		    config.in_frame.size[1].width,
592 		    config.in_frame.size[1].height,
593 		    config.in_frame.size[2].width,
594 		    config.in_frame.size[2].height, config.in_frame.addr[0],
595 		    config.in_frame.addr[1], config.in_frame.addr[2],
596 		    config.out_frame.format, config.out_frame.fd,
597 		    config.out_frame.crop.x, config.out_frame.crop.y,
598 		    config.out_frame.crop.width, config.out_frame.crop.height,
599 		    config.out_frame.size[0].width,
600 		    config.out_frame.size[0].height,
601 		    config.out_frame.size[1].width,
602 		    config.out_frame.size[1].height,
603 		    config.out_frame.size[2].width,
604 		    config.out_frame.size[2].height, config.out_frame.addr[0],
605 		    config.out_frame.addr[1], config.out_frame.addr[2]);
606 
607 		rcq_cptr_wq.rcq_state = 2;
608 		disp_capture_protect_reg_for_rcq(cptr, 1);
609 		disp_al_capture_apply(cptr->disp, &config);
610 		disp_capture_protect_reg_for_rcq(cptr, 0);
611 
612 		ret = 0;
613 		goto EXIT;
614 	}
615 	info_list =
616 	    kmalloc(sizeof(struct disp_capture_info_list),
617 		    GFP_KERNEL | __GFP_ZERO);
618 	if (info_list == NULL) {
619 		DE_WRN("malloc fail!\n");
620 		goto EXIT;
621 	}
622 	__disp_capture_info_transfer(&info_list->info, info);
623 	spin_lock_irqsave(&cptrp->data_lock, flags);
624 	list_add_tail(&info_list->list, &cptrp->req_list);
625 	cptrp->req_cnt++;
626 
627 	list_for_each_entry_safe(info_list, temp, &cptrp->done_list, list) {
628 		list_del(&info_list->list);
629 		list_add_tail(&info_list->list, &done_list);
630 		cptrp->done_cnt--;
631 	}
632 	spin_unlock_irqrestore(&cptrp->data_lock, flags);
633 	list_for_each_entry_safe(info_list, temp, &done_list, list) {
634 		list_del(&info_list->list);
635 		if (info_list->item)
636 			disp_dma_unmap(info_list->item);
637 		kfree(info_list);
638 	}
639 	ret = 0;
640 EXIT:
641 	mutex_unlock(&cptrp->mlock);
642 
643 	return ret;
644 }
645 
disp_capture_commit2(struct disp_capture * cptr,struct disp_capture_info2 * info)646 static s32 disp_capture_commit2(struct disp_capture *cptr,
647 				struct disp_capture_info2 *info)
648 {
649 	struct disp_capture_private_data *cptrp = disp_capture_get_priv(cptr);
650 	struct disp_manager *mgr;
651 	struct disp_capture_info_list *info_list, *temp;
652 	unsigned long flags;
653 	struct dmabuf_item *item;
654 	struct disp_device *dispdev = NULL;
655 	int ret = -1;
656 	struct list_head done_list;
657 	enum disp_csc_type cs = DISP_CSC_TYPE_RGB;
658 	struct fb_address_transfer fb;
659 
660 	INIT_LIST_HEAD(&done_list);
661 	if (NULL == cptr || NULL == cptrp) {
662 		DE_WRN("NULL hdl!\n");
663 		return -1;
664 	}
665 	DE_INF("cap %d\n", cptr->disp);
666 
667 	mgr = cptr->manager;
668 	if ((NULL == mgr) || (0 == mgr->is_enabled(mgr))) {
669 		DE_WRN("manager disable!\n");
670 		return -1;
671 	}
672 
673 	mutex_lock(&cptrp->mlock);
674 	if (0 == cptrp->enabled) {
675 		DE_WRN("capture %d is disabled!\n", cptr->disp);
676 		goto exit;
677 	}
678 	info_list = kmalloc(sizeof(struct disp_capture_info_list),
679 			    GFP_KERNEL | __GFP_ZERO);
680 	if (NULL == info_list) {
681 		DE_WRN("malloc fail!\n");
682 		goto exit;
683 	}
684 	__disp_capture_info2_transfer(&info_list->info, info);
685 	item = disp_dma_map(info_list->info.out_frame.fd);
686 	if (item == NULL) {
687 		DE_WRN("disp dma map fail!\n");
688 		kfree(info_list);
689 		goto exit;
690 	}
691 	fb.format = info_list->info.out_frame.format;
692 	memcpy(fb.size, info_list->info.out_frame.size,
693 	       sizeof(struct disp_rectsz) * 3);
694 	fb.dma_addr = item->dma_addr;
695 	fb.align[0] = 0;
696 	fb.align[1] = 0;
697 	fb.align[2] = 0;
698 	disp_set_fb_info(&fb, true);
699 	memcpy(info_list->info.out_frame.addr, fb.addr, sizeof(long long) * 3);
700 
701 	info_list->item = item;
702 	/*
703 	info_list->info.out_frame.addr[0] = item->dma_addr;
704 	info_list->info.out_frame.addr[1] =
705 	    item->dma_addr +
706 	    info_list->info.out_frame.size[0].width *
707 		info_list->info.out_frame.size[0].height;
708 	info_list->info.out_frame.addr[2] =
709 	    info_list->info.out_frame.addr[1] +
710 	    info_list->info.out_frame.size[0].width *
711 		info_list->info.out_frame.size[0].height / 4;
712 	*/
713 
714 	if (disp_feat_is_using_wb_rcq(cptr->disp)) {
715 		struct disp_capture_config config;
716 		u32 width = 0, height = 0;
717 
718 		memset(&config, 0, sizeof(struct disp_capture_config));
719 
720 		config.disp = cptr->disp;
721 
722 		memcpy(&config.out_frame,
723 		       &info_list->info.out_frame,
724 		       sizeof(struct disp_s_frame_inner));
725 
726 		memcpy(&config.in_frame.crop,
727 			&info_list->info.window,
728 			sizeof(struct disp_rect));
729 		dispdev = mgr->device;
730 		if (!dispdev) {
731 			DE_WRN("disp device is NULL!\n");
732 			return -1;
733 		}
734 		if (dispdev->get_input_csc)
735 			cs = dispdev->get_input_csc(dispdev);
736 		if (DISP_CSC_TYPE_RGB == cs)
737 			config.in_frame.format = DISP_FORMAT_ARGB_8888;
738 		else if (DISP_CSC_TYPE_YUV444  == cs)
739 			config.in_frame.format = DISP_FORMAT_YUV444_P;
740 		else if (DISP_CSC_TYPE_YUV422 == cs)
741 			config.in_frame.format = DISP_FORMAT_YUV422_P;
742 		else
743 			config.in_frame.format = DISP_FORMAT_YUV420_P;
744 
745 		if (dispdev->get_resolution)
746 			dispdev->get_resolution(dispdev, &width, &height);
747 		config.in_frame.size[0].width = width;
748 		config.in_frame.size[1].width = width;
749 		config.in_frame.size[2].width = width;
750 		config.in_frame.size[0].height = height;
751 		config.in_frame.size[1].height = height;
752 		config.in_frame.size[2].height = height;
753 		if ((0 == config.in_frame.crop.width)
754 			|| (0 == config.in_frame.crop.height)) {
755 			config.in_frame.crop.width = width;
756 			config.in_frame.crop.height = height;
757 		}
758 
759 		DE_INF(
760 		    "disp:%d flag:%d in_fmt:%d in_fd:%d in_crop[%d %d %d "
761 		    "%d],in_size[%u %u, %u %u, %u "
762 		    "%u],in_addr[0x%llx,0x%llx,0x%llx],out_fmt:%d out_fd:%d "
763 		    "out_crop[%d %d %d %d],out_size[%u %u, %u %u, %u "
764 		    "%u],out_addr[0x%llx,0x%llx,0x%llx]\n",
765 		    config.disp, config.flags, config.in_frame.format,
766 		    config.in_frame.fd, config.in_frame.crop.x,
767 		    config.in_frame.crop.y, config.in_frame.crop.width,
768 		    config.in_frame.crop.height, config.in_frame.size[0].width,
769 		    config.in_frame.size[0].height,
770 		    config.in_frame.size[1].width,
771 		    config.in_frame.size[1].height,
772 		    config.in_frame.size[2].width,
773 		    config.in_frame.size[2].height, config.in_frame.addr[0],
774 		    config.in_frame.addr[1], config.in_frame.addr[2],
775 		    config.out_frame.format, config.out_frame.fd,
776 		    config.out_frame.crop.x, config.out_frame.crop.y,
777 		    config.out_frame.crop.width, config.out_frame.crop.height,
778 		    config.out_frame.size[0].width,
779 		    config.out_frame.size[0].height,
780 		    config.out_frame.size[1].width,
781 		    config.out_frame.size[1].height,
782 		    config.out_frame.size[2].width,
783 		    config.out_frame.size[2].height, config.out_frame.addr[0],
784 		    config.out_frame.addr[1], config.out_frame.addr[2]);
785 
786 		/*
787 		disp_capture_protect_reg_for_rcq(cptr, 1);
788 		disp_al_capture_apply(cptr->disp, &config);
789 		disp_capture_protect_reg_for_rcq(cptr, 0);
790 		list_add_tail(&info_list->list, &cptrp->done_list);
791 
792 		cptrp->done_sum++;
793 
794 		ret = 0;
795 		goto exit;
796 		*/
797 	}
798 
799 	spin_lock_irqsave(&cptrp->data_lock, flags);
800 	list_add_tail(&info_list->list, &cptrp->req_list);
801 	cptrp->req_cnt++;
802 
803 	list_for_each_entry_safe(info_list, temp, &cptrp->done_list, list) {
804 		if (cptrp->done_cnt >= 2) {
805 			list_del(&info_list->list);
806 			list_add_tail(&info_list->list, &done_list);
807 			cptrp->done_cnt--;
808 		}
809 	}
810 	spin_unlock_irqrestore(&cptrp->data_lock, flags);
811 
812 	list_for_each_entry_safe(info_list, temp, &done_list, list) {
813 		list_del(&info_list->list);
814 		if (info_list->item)
815 			disp_dma_unmap(info_list->item);
816 		kfree(info_list);
817 	}
818 	ret = 0;
819 exit:
820 	mutex_unlock(&cptrp->mlock);
821 	return ret;
822 }
823 
disp_capture_query(struct disp_capture * cptr)824 s32 disp_capture_query(struct disp_capture *cptr)
825 {
826 	struct disp_capture_private_data *cptrp = disp_capture_get_priv(cptr);
827 
828 	if ((cptr == NULL) || (cptrp == NULL)) {
829 		DE_WRN("NULL hdl!\n");
830 		return 0;
831 	}
832 
833 	return cptrp->status;
834 }
835 
disp_capture_sync(struct disp_capture * cptr)836 s32 disp_capture_sync(struct disp_capture *cptr)
837 {
838 	struct disp_capture_private_data *cptrp = disp_capture_get_priv(cptr);
839 	struct disp_manager *mgr = NULL;
840 	struct disp_device *dispdev = NULL;
841 	s32 ret = 0;
842 	unsigned long flags;
843 
844 	if ((NULL == cptr) || (NULL == cptrp)) {
845 		DE_WRN("NULL hdl!\n");
846 		return 0;
847 	}
848 
849 	/*
850 	if (disp_feat_is_using_wb_rcq(cptr->disp))
851 		disp_delay_us(2 * 50);
852 	*/
853 
854 	mgr = cptr->manager;
855 	if ((NULL == mgr) || (0 == mgr->is_enabled(mgr))) {
856 		rcq_cptr_wq.rcq_state = 0;
857 		/*DE_WRN("mgr is disable!\n");*/
858 		return 0;
859 	}
860 	dispdev = mgr->device;
861 	if (NULL == dispdev) {
862 		DE_WRN("disp device is NULL!\n");
863 		return 0;
864 	}
865 
866 	if (1 == cptrp->enabled) {
867 		struct disp_capture_info_list *info_list = NULL, *temp;
868 		struct disp_capture_info_list *running = NULL;
869 		bool find = false;
870 		bool run = false;
871 
872 		spin_lock_irqsave(&cptrp->data_lock, flags);
873 		list_for_each_entry_safe(running, temp, &cptrp->runing_list,
874 					 list) {
875 			list_del(&running->list);
876 			cptrp->runing_cnt--;
877 
878 			list_add_tail(&running->list, &cptrp->done_list);
879 			cptrp->done_cnt++;
880 			cptrp->done_sum++;
881 			run = true;
882 			break;
883 		}
884 
885 		list_for_each_entry_safe(info_list, temp, &cptrp->req_list,
886 					 list) {
887 			list_del(&info_list->list);
888 			cptrp->req_cnt--;
889 
890 			list_add_tail(&info_list->list, &cptrp->runing_list);
891 			cptrp->runing_cnt++;
892 			find = true;
893 			break;
894 		}
895 		spin_unlock_irqrestore(&cptrp->data_lock, flags);
896 
897 		ret = disp_al_capture_get_status(cptr->disp);
898 		cptrp->status = ret;
899 		if (run)
900 			running->done = (ret == 0) ? true : false;
901 
902 		if (find) {
903 			struct disp_capture_config config;
904 			enum disp_csc_type cs = DISP_CSC_TYPE_RGB;
905 			u32 width = 0, height = 0;
906 
907 			memset(&config, 0, sizeof(struct disp_capture_config));
908 			memcpy(&config.out_frame, &info_list->info.out_frame,
909 			       sizeof(struct disp_s_frame_inner));
910 			config.disp = cptr->disp;
911 			memcpy(&config.in_frame.crop, &info_list->info.window,
912 			       sizeof(struct disp_rect));
913 			if (dispdev->get_input_csc) {
914 				cs = dispdev->get_input_csc(dispdev);
915 			}
916 			if (DISP_CSC_TYPE_RGB == cs)
917 				config.in_frame.format = DISP_FORMAT_ARGB_8888;
918 			else if (DISP_CSC_TYPE_YUV444 == cs)
919 				config.in_frame.format = DISP_FORMAT_YUV444_P;
920 			else if (DISP_CSC_TYPE_YUV422 == cs)
921 				config.in_frame.format = DISP_FORMAT_YUV422_P;
922 			else
923 				config.in_frame.format = DISP_FORMAT_YUV420_P;
924 			if (dispdev->get_resolution) {
925 				dispdev->get_resolution(dispdev, &width,
926 							&height);
927 			}
928 			config.in_frame.size[0].width = width;
929 			config.in_frame.size[1].width = width;
930 			config.in_frame.size[2].width = width;
931 			config.in_frame.size[0].height = height;
932 			config.in_frame.size[1].height = height;
933 			config.in_frame.size[2].height = height;
934 			if ((0 == config.in_frame.crop.width) ||
935 			    (0 == config.in_frame.crop.height)) {
936 				config.in_frame.crop.width = width;
937 				config.in_frame.crop.height = height;
938 			}
939 
940 			if (disp_feat_is_using_wb_rcq(cptr->disp)) {
941 				disp_capture_protect_reg_for_rcq(cptr, 1);
942 				disp_al_capture_apply(cptr->disp, &config);
943 				disp_al_capture_sync(cptr->disp);
944 				//disp_al_capture_set_rcq_update(cptr->disp, 1);
945 				disp_capture_protect_reg_for_rcq(cptr, 0);
946 			} else {
947 				disp_al_capture_apply(cptr->disp, &config);
948 				disp_al_capture_sync(cptr->disp);
949 			}
950 		} else {
951 			rcq_cptr_wq.rcq_state = 0;
952 		}
953 	}
954 
955 	return 0;
956 }
957 
disp_capture_set_manager(struct disp_capture * cptr,struct disp_manager * mgr)958 s32 disp_capture_set_manager(struct disp_capture *cptr,
959 			     struct disp_manager *mgr)
960 {
961 	struct disp_capture_private_data *cptrp = disp_capture_get_priv(cptr);
962 
963 	if ((cptr == NULL) || (mgr == NULL)) {
964 		DE_WRN("NULL hdl!\n");
965 		return -1;
966 	}
967 	mutex_lock(&cptrp->mlock);
968 	cptr->manager = mgr;
969 	if (mgr)
970 		mgr->cptr = cptr;
971 	mutex_unlock(&cptrp->mlock);
972 	return 0;
973 }
974 
disp_capture_unset_manager(struct disp_capture * cptr)975 s32 disp_capture_unset_manager(struct disp_capture *cptr)
976 {
977 	struct disp_capture_private_data *cptrp = disp_capture_get_priv(cptr);
978 
979 	if (cptr == NULL) {
980 		DE_WRN("NULL hdl!\n");
981 		return -1;
982 	}
983 	mutex_lock(&cptrp->mlock);
984 	if (cptr->manager)
985 		cptr->manager->cptr = NULL;
986 	cptr->manager = NULL;
987 	mutex_unlock(&cptrp->mlock);
988 	return 0;
989 }
990 
disp_capture_suspend(struct disp_capture * cptr)991 s32 disp_capture_suspend(struct disp_capture *cptr)
992 {
993 	struct disp_capture_private_data *cptrp = disp_capture_get_priv(cptr);
994 
995 	if ((cptr == NULL) || (cptrp == NULL)) {
996 		DE_WRN("capture NULL hdl!\n");
997 		return -1;
998 	}
999 
1000 	return 0;
1001 }
1002 
disp_capture_resume(struct disp_capture * cptr)1003 s32 disp_capture_resume(struct disp_capture *cptr)
1004 {
1005 	struct disp_capture_private_data *cptrp = disp_capture_get_priv(cptr);
1006 
1007 	if ((cptr == NULL) || (cptrp == NULL)) {
1008 		DE_WRN("capture NULL hdl!\n");
1009 		return -1;
1010 	}
1011 
1012 	return 0;
1013 
1014 }
1015 
disp_capture_dump(struct disp_capture * cptr,char * buf)1016 static s32 disp_capture_dump(struct disp_capture *cptr, char *buf)
1017 {
1018 	struct disp_capture_private_data *cptrp = disp_capture_get_priv(cptr);
1019 	unsigned int count = 0;
1020 
1021 	if ((NULL == cptr) || (NULL == cptrp)) {
1022 		DE_WRN("capture NULL hdl!\n");
1023 		return -1;
1024 	}
1025 
1026 	count += sprintf(buf + count,
1027 			 "capture: %3s req[%u] runing[%u] done[%d,%u]\n",
1028 			 (cptrp->enabled == 1) ? "en" : "dis", cptrp->req_cnt,
1029 			 cptrp->runing_cnt, cptrp->done_cnt, cptrp->done_sum);
1030 
1031 	return count;
1032 }
1033 
disp_capture_init(struct disp_capture * cptr)1034 s32 disp_capture_init(struct disp_capture *cptr)
1035 {
1036 	struct disp_capture_private_data *capturep =
1037 	    disp_capture_get_priv(cptr);
1038 
1039 	if ((cptr == NULL) || (capturep == NULL)) {
1040 		DE_WRN("capture NULL hdl!\n");
1041 		return -1;
1042 	}
1043 
1044 	if (!bsp_disp_feat_is_support_capture(cptr->disp)) {
1045 		DE_WRN("capture %d is not support\n", cptr->disp);
1046 		return -1;
1047 	}
1048 
1049 	disp_capture_clk_init(cptr);
1050 	return 0;
1051 }
1052 
disp_capture_exit(struct disp_capture * cptr)1053 s32 disp_capture_exit(struct disp_capture *cptr)
1054 {
1055 	if (!bsp_disp_feat_is_support_capture(cptr->disp)) {
1056 		DE_WRN("capture %d is not support\n", cptr->disp);
1057 		return -1;
1058 	}
1059 	disp_capture_clk_exit(cptr);
1060 
1061 	return 0;
1062 }
1063 
disp_init_capture(struct disp_bsp_init_para * para)1064 s32 disp_init_capture(struct disp_bsp_init_para *para)
1065 {
1066 	u32 num_screens;
1067 	u32 disp;
1068 	struct disp_capture *capture;
1069 	struct disp_capture_private_data *capturep;
1070 
1071 	num_screens = bsp_disp_feat_get_num_screens();
1072 	captures =
1073 	    kmalloc_array(num_screens, sizeof(struct disp_capture),
1074 			  GFP_KERNEL | __GFP_ZERO);
1075 	if (!captures) {
1076 		DE_WRN("malloc memory fail!\n");
1077 		goto malloc_err;
1078 	}
1079 	capture_private =
1080 	    kmalloc(sizeof(struct disp_capture_private_data)
1081 		    * num_screens, GFP_KERNEL | __GFP_ZERO);
1082 	if (!capture_private) {
1083 		DE_WRN("malloc memory fail!\n");
1084 		goto malloc_err;
1085 	}
1086 
1087 	INIT_WORK(&rcq_cptr_wq.wq, rcq_cptr_sync);
1088 	for (disp = 0; disp < num_screens; disp++) {
1089 		if (!bsp_disp_feat_is_support_capture(disp))
1090 			continue;
1091 
1092 		capture = &captures[disp];
1093 		capturep = &capture_private[disp];
1094 		mutex_init(&capturep->mlock);
1095 		spin_lock_init(&(capturep->data_lock));
1096 		spin_lock_init(&(capturep->reg_lock));
1097 
1098 		capturep->clk = para->clk_de[disp];
1099 		capturep->clk_bus = para->clk_bus_de[disp];
1100 		capturep->rst = para->rst_bus_de[disp];
1101 
1102 		capture->disp = disp;
1103 		sprintf(capture->name, "capture%d", disp);
1104 
1105 		capturep->irq_info.sel = disp;
1106 		capturep->irq_info.irq_flag =
1107 			disp_feat_is_using_wb_rcq(disp) ?
1108 				DISP_AL_CAPTURE_IRQ_FLAG_RCQ_FINISH : 0;
1109 		capturep->irq_info.ptr = (void *)capture;
1110 		capturep->irq_info.irq_handler = disp_capture_irq_handler;
1111 
1112 		capturep->shadow_protect = para->shadow_protect;
1113 		capture->set_manager = disp_capture_set_manager;
1114 		capture->unset_manager = disp_capture_unset_manager;
1115 		capture->start = disp_capture_start;
1116 		capture->stop = disp_capture_stop;
1117 		capture->sync = disp_capture_sync;
1118 		capture->init = disp_capture_init;
1119 		capture->exit = disp_capture_exit;
1120 		capture->commmit = disp_capture_commit;
1121 		capture->commmit2 = disp_capture_commit2;
1122 		capture->query = disp_capture_query;
1123 		capture->dump = disp_capture_dump;
1124 		INIT_LIST_HEAD(&capturep->req_list);
1125 		INIT_LIST_HEAD(&capturep->runing_list);
1126 		INIT_LIST_HEAD(&capturep->done_list);
1127 
1128 		capture->init(capture);
1129 	}
1130 	return 0;
1131 
1132 malloc_err:
1133 	kfree(capture_private);
1134 	kfree(captures);
1135 	capture_private = NULL;
1136 	captures = NULL;
1137 
1138 	return -1;
1139 }
1140 
disp_exit_capture(void)1141 s32 disp_exit_capture(void)
1142 {
1143 	u32 num_screens;
1144 	struct disp_capture *capture;
1145 	u32 disp;
1146 
1147 	if (!captures)
1148 		return 0;
1149 
1150 	num_screens = bsp_disp_feat_get_num_screens();
1151 	for (disp = 0; disp < num_screens; disp++) {
1152 		if (!bsp_disp_feat_is_support_capture(disp))
1153 			continue;
1154 
1155 		capture = &captures[disp];
1156 		capture->exit(capture);
1157 	}
1158 
1159 	kfree(capture_private);
1160 	kfree(captures);
1161 	capture_private = NULL;
1162 	captures = NULL;
1163 
1164 	return 0;
1165 }
1166