• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Allwinner SoCs display driver.
3  *
4  * Copyright (c) 2007-2017 Allwinnertech Co., Ltd.
5  *
6  * This software is licensed under the terms of the GNU General Public
7  * License version 2, as published by the Free Software Foundation, and
8  * may be copied, distributed, and modified under those terms.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  */
16 
17 #include "disp_hdmi.h"
18 
19 #if defined(SUPPORT_HDMI)
20 struct disp_device_private_data {
21 	u32 enabled;
22 	bool hpd;
23 	bool suspended;
24 
25 	struct disp_device_config config;
26 
27 	struct disp_device_func hdmi_func;
28 	struct disp_video_timings *video_info;
29 
30 	u32                       frame_per_sec;
31 	u32                       usec_per_line;
32 	u32                       judge_line;
33 
34 	u32 irq_no;
35 
36 	struct clk *clk;
37 	struct clk *bus_clk;
38 	struct clk *parent_clk;
39 
40 	struct reset_control *rst_bus_clk;
41 };
42 
43 static u32 hdmi_used;
44 
45 #if defined(__LINUX_PLAT__)
46 static spinlock_t hdmi_data_lock;
47 static struct mutex hdmi_mlock;
48 #else
49 static int hdmi_data_lock;
50 static int hdmi_mlock;
51 #endif
52 
53 static struct disp_device *hdmis;
54 static struct disp_device_private_data *hdmi_private;
55 s32 disp_hdmi_set_mode(struct disp_device *hdmi, u32 mode);
56 s32 disp_hdmi_enable(struct disp_device *hdmi);
57 
disp_get_hdmi(u32 disp)58 struct disp_device *disp_get_hdmi(u32 disp)
59 {
60 	u32 num_screens;
61 
62 	num_screens = bsp_disp_feat_get_num_screens();
63 	if (disp >= num_screens
64 	    || !bsp_disp_feat_is_supported_output_types(disp,
65 	    DISP_OUTPUT_TYPE_HDMI)) {
66 		DE_WRN("disp %d not support HDMI output\n", disp);
67 		return NULL;
68 	}
69 
70 	return &hdmis[disp];
71 }
72 
disp_hdmi_get_priv(struct disp_device * hdmi)73 static struct disp_device_private_data *disp_hdmi_get_priv(struct disp_device
74 							   *hdmi)
75 {
76 	if (hdmi == NULL) {
77 		DE_WRN("NULL hdl!\n");
78 		return NULL;
79 	}
80 
81 	return (struct disp_device_private_data *)hdmi->priv_data;
82 }
83 
hdmi_clk_init(struct disp_device * hdmi)84 static s32 hdmi_clk_init(struct disp_device *hdmi)
85 {
86 	struct disp_device_private_data *hdmip = disp_hdmi_get_priv(hdmi);
87 
88 	if (!hdmi || !hdmip) {
89 		DE_WRN("hdmi clk init null hdl!\n");
90 		return DIS_FAIL;
91 	}
92 
93 	if (hdmip->clk) {
94 		hdmip->parent_clk = clk_get_parent(hdmip->clk);
95 		if (IS_ERR_OR_NULL(hdmip->parent_clk))
96 			DE_WRN("get hdmi clk parent fail\n");
97 	}
98 
99 	return 0;
100 }
101 
hdmi_clk_exit(struct disp_device * hdmi)102 static s32 hdmi_clk_exit(struct disp_device *hdmi)
103 {
104 	struct disp_device_private_data *hdmip = disp_hdmi_get_priv(hdmi);
105 
106 	if (!hdmi || !hdmip) {
107 		DE_WRN("hdmi clk init null hdl!\n");
108 		return DIS_FAIL;
109 	}
110 
111 	return 0;
112 }
113 
hdmi_is_divide_by(unsigned long dividend,unsigned long divisor)114 bool hdmi_is_divide_by(unsigned long dividend,
115 			       unsigned long divisor)
116 {
117 	bool divide = false;
118 	unsigned long temp;
119 
120 	if (divisor == 0)
121 		goto exit;
122 
123 	temp = dividend / divisor;
124 	if (dividend == (temp * divisor))
125 		divide = true;
126 exit:
127 	return divide;
128 }
129 
hdmi_clk_config(struct disp_device * hdmi)130 static s32 hdmi_clk_config(struct disp_device *hdmi)
131 {
132 	struct disp_device_private_data *hdmip = disp_hdmi_get_priv(hdmi);
133 	struct clk *parent_clk;
134 	unsigned long rate = 0, round_rate = 0;
135 	long rate_diff = 0;
136 	unsigned long parent_rate = 0, parent_round_rate = 0;
137 	long parent_rate_diff = 0;
138 	unsigned int div = 1;
139 
140 	if (!hdmi || !hdmip) {
141 	    DE_WRN("hdmi clk init null hdl!\n");
142 	    return DIS_FAIL;
143 	}
144 
145 	parent_clk =  clk_get_parent(hdmip->clk);
146 	if (!parent_clk) {
147 		DE_WRN("can not get hdmi prent clk!\n");
148 		return DIS_FAIL;
149 	}
150 
151 	/*calculate rate*/
152 	rate = hdmip->video_info->pixel_clk * (hdmip->video_info->pixel_repeat + 1);
153 	if (hdmip->config.format == DISP_CSC_TYPE_YUV420)
154 		rate /= 2;
155 
156 	round_rate = clk_round_rate(hdmip->clk, rate);
157 	rate_diff = (long)(round_rate - rate);
158 	if ((rate_diff > 5000000) || (rate_diff < -5000000)) {
159 		for (div = 1; (rate * div) <= 600000000; div++) {
160 			parent_rate = rate * div;
161 			parent_round_rate = clk_round_rate(parent_clk,
162 							   parent_rate);
163 			parent_rate_diff = (long)(parent_round_rate - parent_rate);
164 			if ((parent_rate_diff < 5000000)
165 				&& (parent_rate_diff > -5000000)) {
166 				clk_set_rate(parent_clk, parent_rate);
167 				clk_set_rate(hdmip->clk, rate);
168 				break;
169 			}
170 		}
171 		if ((rate * div) > 600000000)
172 			clk_set_rate(hdmip->clk, rate);
173 	} else {
174 		clk_set_rate(hdmip->clk, rate);
175 	}
176 
177 	return 0;
178 }
179 
hdmi_clk_enable(struct disp_device * hdmi)180 static s32 hdmi_clk_enable(struct disp_device *hdmi)
181 {
182 	struct disp_device_private_data *hdmip = disp_hdmi_get_priv(hdmi);
183 	int ret = 0;
184 
185 	if (!hdmi || !hdmip) {
186 		DE_WRN("hdmi clk init null hdl!\n");
187 		return DIS_FAIL;
188 	}
189 
190 	if (hdmip->rst_bus_clk) {
191 		ret = reset_control_deassert(hdmip->rst_bus_clk);
192 		if (ret) {
193 			pr_err("[%s] deassert reset tcon tv failed!\n", __func__);
194 			return DIS_FAIL;
195 		}
196 	}
197 
198 	if (hdmip->bus_clk) {
199 		ret = clk_prepare_enable(hdmip->bus_clk);
200 		if (ret != 0)
201 			DE_WRN("fail enable hdmi's bus clock!\n");
202 	}
203 
204 	hdmi_clk_config(hdmi);
205 	if (hdmip->clk) {
206 		ret = clk_prepare_enable(hdmip->clk);
207 		if (ret != 0)
208 			DE_WRN("fail enable hdmi's clock!\n");
209 	}
210 
211 	return ret;
212 }
213 
hdmi_clk_disable(struct disp_device * hdmi)214 static s32 hdmi_clk_disable(struct disp_device *hdmi)
215 {
216 	struct disp_device_private_data *hdmip = disp_hdmi_get_priv(hdmi);
217 
218 	if (!hdmi || !hdmip) {
219 		DE_WRN("hdmi clk init null hdl!\n");
220 		return DIS_FAIL;
221 	}
222 
223 	if (hdmip->clk && (__clk_is_enabled(hdmip->clk)))
224 		clk_disable_unprepare(hdmip->clk);
225 
226 	if (hdmip->bus_clk && (__clk_is_enabled(hdmip->bus_clk)))
227 		clk_disable_unprepare(hdmip->bus_clk);
228 
229 	if (hdmip->rst_bus_clk) {
230 		if (reset_control_assert(hdmip->rst_bus_clk) != 0)
231 			pr_err("[%s] assert bus clk failed!\n", __func__);
232 			return DIS_FAIL;
233 	}
234 
235 	return 0;
236 }
237 
disp_hdmi_pad_sel(unsigned int pad_sel)238 void disp_hdmi_pad_sel(unsigned int pad_sel)
239 {
240 #ifdef USE_CEC_DDC_PAD
241 	struct disp_device_private_data *hdmip
242 				= disp_hdmi_get_priv(hdmis);
243 	if (!hdmis) {
244 		pr_err("can NOT get hdmis!\n");
245 		return;
246 	}
247 
248 	if (hdmip->clk) {
249 		if (!__clk_is_enabled(hdmip->clk))
250 			clk_prepare_enable(hdmip->clk);
251 	} else {
252 		pr_err("hdmip has null clk\n");
253 	}
254 	disp_al_hdmi_pad_sel(hdmis->hwdev_index, pad_sel);
255 #endif
256 }
257 EXPORT_SYMBOL(disp_hdmi_pad_sel);
258 
disp_hdmi_pad_release(void)259 void disp_hdmi_pad_release(void)
260 {
261 #ifdef USE_CEC_DDC_PAD
262 	/*struct disp_device_private_data *hdmip
263 		= disp_hdmi_get_priv(hdmis);*/
264 	if (!hdmis)
265 		return;
266 
267 	disp_al_hdmi_pad_sel(hdmis->hwdev_index, 0);
268 
269 	/*if (!hdmip->clk)
270 		return;
271 
272 	if (__clk_is_enabled(hdmip->clk))
273 		clk_disable_unprepare(hdmip->clk);*/
274 #endif
275 
276 }
277 EXPORT_SYMBOL(disp_hdmi_pad_release);
278 
disp_hdmi_pad_get(void)279 u32 disp_hdmi_pad_get(void)
280 {
281 	u32 ret = 0;
282 
283 #ifdef USE_CEC_DDC_PAD
284 #if defined(CONFIG_ARCH_SUN50IW9) || defined(CONFIG_ARCH_SUN8IW20)
285 	ret = tcon_pad_get(hdmis->hwdev_index);
286 #endif
287 #endif
288 	return ret;
289 }
290 EXPORT_SYMBOL(disp_hdmi_pad_get);
291 
hdmi_calc_judge_line(struct disp_device * hdmi)292 static s32 hdmi_calc_judge_line(struct disp_device *hdmi)
293 {
294 	struct disp_device_private_data *hdmip = disp_hdmi_get_priv(hdmi);
295 	int start_delay, usec_start_delay;
296 	int usec_judge_point;
297 	u64 temp;
298 
299 	if ((hdmi == NULL) || (hdmip == NULL)) {
300 		DE_WRN("null  hdl!\n");
301 		return DIS_FAIL;
302 	}
303 
304 	/*
305 	 * usec_per_line = 1 / fps / vt * 1000000
306 	 *               = 1 / (pixel_clk / vt / ht) / vt * 1000000
307 	 *               = ht / pixel_clk * 1000000
308 	 */
309 	hdmip->frame_per_sec = hdmip->video_info->pixel_clk
310 	    / hdmip->video_info->hor_total_time
311 	    / hdmip->video_info->ver_total_time
312 	    * (hdmip->video_info->b_interlace + 1)
313 	    / (hdmip->video_info->trd_mode + 1);
314 
315 	temp = hdmip->video_info->hor_total_time * 1000000ull;
316 	do_div(temp, hdmip->video_info->pixel_clk);
317 	hdmip->usec_per_line = temp;
318 
319 	start_delay = disp_al_device_get_start_delay(hdmi->hwdev_index);
320 	usec_start_delay = start_delay * hdmip->usec_per_line;
321 
322 	if (usec_start_delay <= 200)
323 		usec_judge_point = usec_start_delay * 3 / 7;
324 	else if (usec_start_delay <= 400)
325 		usec_judge_point = usec_start_delay / 2;
326 	else
327 		usec_judge_point = 200;
328 	hdmip->judge_line = usec_judge_point / hdmip->usec_per_line;
329 
330 	return 0;
331 }
332 
disp_hdmi_set_func(struct disp_device * hdmi,struct disp_device_func * func)333 static s32 disp_hdmi_set_func(struct disp_device *hdmi,
334 			      struct disp_device_func *func)
335 {
336 	struct disp_device_private_data *hdmip = disp_hdmi_get_priv(hdmi);
337 
338 	if ((hdmi == NULL) || (hdmip == NULL)) {
339 		DE_WRN("hdmi set func null  hdl!\n");
340 		return DIS_FAIL;
341 	}
342 
343 	memcpy(&hdmip->hdmi_func, func, sizeof(struct disp_device_func));
344 
345 	return 0;
346 }
347 
348 #if defined(__LINUX_PLAT__)
disp_hdmi_event_proc(int irq,void * parg)349 static s32 disp_hdmi_event_proc(int irq, void *parg)
350 #else
351 static s32 disp_hdmi_event_proc(void *parg)
352 #endif
353 {
354 	struct disp_device *hdmi = (struct disp_device *)parg;
355 	struct disp_manager *mgr = NULL;
356 	u32 hwdev_index;
357 
358 	if (hdmi == NULL)
359 		return DISP_IRQ_RETURN;
360 
361 	hwdev_index = hdmi->hwdev_index;
362 
363 	if (disp_al_device_query_irq(hwdev_index)) {
364 		int cur_line = disp_al_device_get_cur_line(hwdev_index);
365 		int start_delay = disp_al_device_get_start_delay(hwdev_index);
366 
367 		mgr = hdmi->manager;
368 		if (mgr == NULL)
369 			return DISP_IRQ_RETURN;
370 
371 		if (cur_line <= (start_delay - 4))
372 			sync_event_proc(mgr->disp, false);
373 		else
374 			sync_event_proc(mgr->disp, true);
375 	}
376 
377 	return DISP_IRQ_RETURN;
378 }
379 
disp_hdmi_init(struct disp_device * hdmi)380 static s32 disp_hdmi_init(struct disp_device *hdmi)
381 {
382 	struct disp_device_private_data *hdmip = disp_hdmi_get_priv(hdmi);
383 
384 	if (!hdmi || !hdmip) {
385 		DE_WRN("hdmi init null hdl!\n");
386 		return DIS_FAIL;
387 	}
388 
389 	hdmi_clk_init(hdmi);
390 
391 	return 0;
392 }
393 
disp_hdmi_exit(struct disp_device * hdmi)394 static s32 disp_hdmi_exit(struct disp_device *hdmi)
395 {
396 	struct disp_device_private_data *hdmip = disp_hdmi_get_priv(hdmi);
397 
398 	if (!hdmi || !hdmip) {
399 		DE_WRN("hdmi init null hdl!\n");
400 		return DIS_FAIL;
401 	}
402 
403 	hdmi_clk_exit(hdmi);
404 
405 	return 0;
406 }
407 
cal_real_frame_period(struct disp_device * hdmi)408 static s32 cal_real_frame_period(struct disp_device *hdmi)
409 {
410 	s32 ret = -1;
411 	struct disp_device_private_data *hdmip;
412 	unsigned long long temp = 0;
413 
414 	if (!hdmi) {
415 		DE_WRN("hdmi is null!\n");
416 		goto OUT;
417 	}
418 
419 	hdmip = disp_hdmi_get_priv(hdmi);
420 
421 	if (!hdmip) {
422 		DE_WRN("hdmip is null!\n");
423 		goto OUT;
424 	}
425 
426 	if (!hdmip->clk || !hdmip->video_info) {
427 		DE_WRN("hdmi clk | video_info null!\n");
428 		goto OUT;
429 	}
430 
431 	hdmi->timings.dclk_rate_set = clk_get_rate(hdmip->clk);
432 
433 	if (!hdmi->timings.dclk_rate_set) {
434 		DE_WRN("hdmi dclk_rate_set is 0!\n");
435 		goto OUT;
436 	}
437 
438 	temp = ONE_SEC * hdmip->video_info->hor_total_time *
439 	       hdmip->video_info->ver_total_time *
440 	       (hdmip->video_info->pixel_repeat + 1);
441 
442 	do_div(temp, hdmi->timings.dclk_rate_set *
443 			 (hdmip->video_info->b_interlace + 1));
444 
445 	hdmi->timings.frame_period = temp;
446 
447 	DE_INF("hdmi frame period:%llu\n", hdmi->timings.frame_period);
448 
449 	hdmi->timings.start_delay =
450 	    disp_al_device_get_start_delay(hdmi->hwdev_index);
451 	ret = 0;
452 OUT:
453 	return ret;
454 }
455 
disp_hdmi_enable(struct disp_device * hdmi)456 s32 disp_hdmi_enable(struct disp_device *hdmi)
457 {
458 	unsigned long flags;
459 	struct disp_device_private_data *hdmip = disp_hdmi_get_priv(hdmi);
460 	struct disp_manager *mgr = NULL;
461 	int ret;
462 
463 	if ((hdmi == NULL) || (hdmip == NULL)) {
464 		DE_WRN("hdmi set func null  hdl!\n");
465 		return DIS_FAIL;
466 	}
467 	DE_INF("%s, disp%d\n", __func__, hdmi->disp);
468 
469 	if (hdmip->enabled == 1) {
470 		DE_WRN("hdmi%d is already enable\n", hdmi->disp);
471 		return DIS_FAIL;
472 	}
473 
474 	mgr = hdmi->manager;
475 	if (!mgr) {
476 		DE_WRN("hdmi%d's mgr is NULL\n", hdmi->disp);
477 		return DIS_FAIL;
478 	}
479 
480 	if (hdmip->hdmi_func.get_video_timing_info == NULL) {
481 		DE_WRN("hdmi_get_video_timing_info func is null\n");
482 		return DIS_FAIL;
483 	}
484 
485 	hdmip->hdmi_func.get_video_timing_info(&(hdmip->video_info));
486 
487 	if (hdmip->video_info == NULL) {
488 		DE_WRN("video info is null\n");
489 		return DIS_FAIL;
490 	}
491 	mutex_lock(&hdmi_mlock);
492 	if (hdmip->enabled == 1)
493 		goto exit;
494 	memcpy(&hdmi->timings, hdmip->video_info,
495 	       sizeof(struct disp_video_timings));
496 	hdmi_calc_judge_line(hdmi);
497 
498 	if (mgr->enable)
499 		mgr->enable(mgr);
500 
501 	disp_sys_register_irq(hdmip->irq_no, 0, disp_hdmi_event_proc,
502 			      (void *)hdmi, 0, 0);
503 	disp_sys_enable_irq(hdmip->irq_no);
504 
505 	ret = hdmi_clk_enable(hdmi);
506 	if (ret != 0)
507 		goto exit;
508 
509 	ret = cal_real_frame_period(hdmi);
510 	if (ret)
511 		DE_WRN("cal_real_frame_period fail\n");
512 
513 	disp_al_hdmi_cfg(hdmi->hwdev_index, hdmip->video_info);
514 	disp_al_hdmi_enable(hdmi->hwdev_index);
515 
516 	if (hdmip->hdmi_func.enable != NULL)
517 		hdmip->hdmi_func.enable();
518 	else
519 		DE_WRN("hdmi_open is NULL\n");
520 
521 	spin_lock_irqsave(&hdmi_data_lock, flags);
522 	hdmip->enabled = 1;
523 	spin_unlock_irqrestore(&hdmi_data_lock, flags);
524 
525 exit:
526 	mutex_unlock(&hdmi_mlock);
527 
528 	return 0;
529 }
530 
disp_hdmi_sw_enable(struct disp_device * hdmi)531 static s32 disp_hdmi_sw_enable(struct disp_device *hdmi)
532 {
533 	unsigned long flags;
534 	struct disp_device_private_data *hdmip = disp_hdmi_get_priv(hdmi);
535 	struct disp_manager *mgr = NULL;
536 
537 	if ((hdmi == NULL) || (hdmip == NULL)) {
538 		DE_WRN("hdmi set func null  hdl!\n");
539 		return DIS_FAIL;
540 	}
541 	mgr = hdmi->manager;
542 	if (!mgr) {
543 		DE_WRN("hdmi%d's mgr is NULL\n", hdmi->disp);
544 		return DIS_FAIL;
545 	}
546 
547 	if (hdmip->hdmi_func.get_video_timing_info == NULL) {
548 		DE_WRN("hdmi_get_video_timing_info func is null\n");
549 		return DIS_FAIL;
550 	}
551 
552 	hdmip->hdmi_func.get_video_timing_info(&(hdmip->video_info));
553 
554 	if (hdmip->video_info == NULL) {
555 		DE_WRN("video info is null\n");
556 		return DIS_FAIL;
557 	}
558 	mutex_lock(&hdmi_mlock);
559 	memcpy(&hdmi->timings, hdmip->video_info,
560 	       sizeof(struct disp_video_timings));
561 	hdmi_calc_judge_line(hdmi);
562 
563 	if (mgr->sw_enable)
564 		mgr->sw_enable(mgr);
565 
566 	disp_al_hdmi_irq_disable(hdmi->hwdev_index);
567 	disp_sys_register_irq(hdmip->irq_no, 0, disp_hdmi_event_proc,
568 			      (void *)hdmi, 0, 0);
569 	disp_sys_enable_irq(hdmip->irq_no);
570 	disp_al_hdmi_irq_enable(hdmi->hwdev_index);
571 
572 #if !defined(CONFIG_COMMON_CLK_ENABLE_SYNCBOOT)
573 #ifdef CONFIG_HDMI2_FREQ_SPREAD_SPECTRUM
574 	/*if (!__clk_is_enabled(hdmip->clk)) {
575 		if (hdmi_clk_enable(hdmi) != 0)
576 			return -1;
577 	}*/
578 
579 	clk_set_rate(clk_get_parent(hdmip->clk),
580 		clk_hw_get_rate(
581 		__clk_get_hw(clk_get_parent(hdmip->clk))));
582 	clk_prepare_enable(clk_get_parent(hdmip->clk));
583 
584 	clk_set_rate(hdmip->clk,
585 		clk_hw_get_rate(
586 		__clk_get_hw(hdmip->clk)));
587 	clk_prepare_enable(hdmip->clk);
588 #else
589 	if (hdmi_clk_enable(hdmi) != 0)
590 		return -1;
591 #endif
592 #endif
593 
594 	if (0 != cal_real_frame_period(hdmi))
595 		DE_WRN("cal_real_frame_period fail\n");
596 
597 	spin_lock_irqsave(&hdmi_data_lock, flags);
598 	hdmip->enabled = 1;
599 	spin_unlock_irqrestore(&hdmi_data_lock, flags);
600 	mutex_unlock(&hdmi_mlock);
601 
602 	return 0;
603 }
604 
disp_hdmi_disable(struct disp_device * hdmi)605 static s32 disp_hdmi_disable(struct disp_device *hdmi)
606 {
607 	struct disp_device_private_data *hdmip = disp_hdmi_get_priv(hdmi);
608 	unsigned long flags;
609 	struct disp_manager *mgr = NULL;
610 
611 	if ((hdmi == NULL) || (hdmip == NULL)) {
612 		DE_WRN("hdmi set func null  hdl!\n");
613 		return DIS_FAIL;
614 	}
615 
616 	mgr = hdmi->manager;
617 	if (!mgr) {
618 		DE_WRN("hdmi%d's mgr is NULL\n", hdmi->disp);
619 		return DIS_FAIL;
620 	}
621 
622 	if (hdmip->enabled == 0) {
623 		DE_WRN("hdmi%d is already disable\n", hdmi->disp);
624 		return DIS_FAIL;
625 	}
626 
627 	if (hdmip->hdmi_func.disable == NULL)
628 		return -1;
629 
630 	mutex_lock(&hdmi_mlock);
631 	if (hdmip->enabled == 0)
632 		goto exit;
633 
634 	spin_lock_irqsave(&hdmi_data_lock, flags);
635 	hdmip->enabled = 0;
636 	spin_unlock_irqrestore(&hdmi_data_lock, flags);
637 
638 	hdmip->hdmi_func.disable();
639 
640 	disp_al_hdmi_disable(hdmi->hwdev_index);
641 	hdmi_clk_disable(hdmi);
642 
643 	if (mgr->disable)
644 		mgr->disable(mgr);
645 
646 	disp_sys_disable_irq(hdmip->irq_no);
647 	disp_sys_unregister_irq(hdmip->irq_no, disp_hdmi_event_proc,
648 				(void *)hdmi);
649 
650 exit:
651 	mutex_unlock(&hdmi_mlock);
652 
653 	return 0;
654 }
655 
disp_hdmi_is_enabled(struct disp_device * hdmi)656 static s32 disp_hdmi_is_enabled(struct disp_device *hdmi)
657 {
658 	struct disp_device_private_data *hdmip = disp_hdmi_get_priv(hdmi);
659 
660 	if ((hdmi == NULL) || (hdmip == NULL)) {
661 		DE_WRN("null hdl!\n");
662 		return DIS_FAIL;
663 	}
664 
665 	return hdmip->enabled;
666 }
667 
668 
disp_hdmi_set_mode(struct disp_device * hdmi,u32 mode)669 s32 disp_hdmi_set_mode(struct disp_device *hdmi, u32 mode)
670 {
671 	s32 ret = 0;
672 	struct disp_device_private_data *hdmip = disp_hdmi_get_priv(hdmi);
673 
674 	if ((NULL == hdmi) || (NULL == hdmip)) {
675 		DE_WRN("hdmi set func null  hdl!\n");
676 		return DIS_FAIL;
677 	}
678 
679 	if (hdmip->hdmi_func.set_mode == NULL) {
680 		DE_WRN("hdmi_set_mode is null!\n");
681 		return -1;
682 	}
683 
684 	ret = hdmip->hdmi_func.set_mode((enum disp_tv_mode)mode);
685 
686 	if (ret == 0)
687 		hdmip->config.mode = mode;
688 
689 	return ret;
690 }
691 
disp_hdmi_get_mode(struct disp_device * hdmi)692 static s32 disp_hdmi_get_mode(struct disp_device *hdmi)
693 {
694 	struct disp_device_private_data *hdmip = disp_hdmi_get_priv(hdmi);
695 
696 	if ((NULL == hdmi) || (NULL == hdmip)) {
697 		DE_WRN("hdmi set func null  hdl!\n");
698 		return DIS_FAIL;
699 	}
700 
701 	return hdmip->config.mode;
702 }
703 
disp_hdmi_detect(struct disp_device * hdmi)704 static s32 disp_hdmi_detect(struct disp_device *hdmi)
705 {
706 	struct disp_device_private_data *hdmip = disp_hdmi_get_priv(hdmi);
707 
708 	if ((NULL == hdmi) || (NULL == hdmip)) {
709 		DE_WRN("hdmi set func null  hdl!\n");
710 		return DIS_FAIL;
711 	}
712 	if (hdmip->hdmi_func.get_HPD_status)
713 		return hdmip->hdmi_func.get_HPD_status();
714 	return DIS_FAIL;
715 }
716 
disp_hdmi_set_detect(struct disp_device * hdmi,bool hpd)717 static s32 disp_hdmi_set_detect(struct disp_device *hdmi, bool hpd)
718 {
719 	struct disp_device_private_data *hdmip = disp_hdmi_get_priv(hdmi);
720 	struct disp_manager *mgr = NULL;
721 
722 	if ((NULL == hdmi) || (NULL == hdmip)) {
723 		DE_WRN("hdmi set func null  hdl!\n");
724 		return DIS_FAIL;
725 	}
726 	mgr = hdmi->manager;
727 	if (!mgr)
728 		return DIS_FAIL;
729 
730 	mutex_lock(&hdmi_mlock);
731 	if ((1 == hdmip->enabled) && (true == hpd)) {
732 		if (hdmip->hdmi_func.get_video_timing_info) {
733 			hdmip->hdmi_func.get_video_timing_info(
734 							&(hdmip->video_info));
735 			if (hdmip->video_info == NULL) {
736 				DE_WRN("video info is null\n");
737 				hdmip->hpd = hpd;
738 				mutex_unlock(&hdmi_mlock);
739 				return DIS_FAIL;
740 			}
741 		}
742 
743 		if (mgr->update_color_space)
744 			mgr->update_color_space(mgr);
745 	}
746 	hdmip->hpd = hpd;
747 	mutex_unlock(&hdmi_mlock);
748 
749 	return 0;
750 }
751 
disp_hdmi_smooth_enable(struct disp_device * hdmi)752 static s32 disp_hdmi_smooth_enable(struct disp_device *hdmi)
753 {
754 	struct disp_device_private_data *hdmip = disp_hdmi_get_priv(hdmi);
755 	struct disp_manager *mgr = NULL;
756 
757 	if ((NULL == hdmi) || (NULL == hdmip)) {
758 		DE_WRN("hdmi set func null  hdl!\n");
759 		return DIS_FAIL;
760 	}
761 	mgr = hdmi->manager;
762 	if (!mgr)
763 		return DIS_FAIL;
764 
765 	mutex_lock(&hdmi_mlock);
766 	if (mgr->smooth_switch)
767 		mgr->smooth_switch(mgr);
768 	if (hdmip->hdmi_func.smooth_enable)
769 		hdmip->hdmi_func.smooth_enable();
770 	mutex_unlock(&hdmi_mlock);
771 
772 	return 0;
773 }
774 
disp_hdmi_check_support_mode(struct disp_device * hdmi,u32 mode)775 static s32 disp_hdmi_check_support_mode(struct disp_device *hdmi, u32 mode)
776 {
777 	struct disp_device_private_data *hdmip = disp_hdmi_get_priv(hdmi);
778 
779 	if ((NULL == hdmi) || (NULL == hdmip)) {
780 		DE_WRN("hdmi set func null  hdl!\n");
781 		return DIS_FAIL;
782 	}
783 
784 	if (hdmip->hdmi_func.mode_support == NULL)
785 		return -1;
786 
787 	return hdmip->hdmi_func.mode_support(mode);
788 }
789 
disp_hdmi_get_input_csc(struct disp_device * hdmi)790 static s32 disp_hdmi_get_input_csc(struct disp_device *hdmi)
791 {
792 	struct disp_device_private_data *hdmip = disp_hdmi_get_priv(hdmi);
793 
794 	if ((NULL == hdmi) || (NULL == hdmip)) {
795 		DE_WRN("hdmi set func null  hdl!\n");
796 		return 0;
797 	}
798 
799 	if (hdmip->hdmi_func.get_input_csc == NULL)
800 		return 0;
801 
802 	return hdmip->hdmi_func.get_input_csc();
803 }
804 
disp_hdmi_get_input_color_range(struct disp_device * hdmi)805 static s32 disp_hdmi_get_input_color_range(struct disp_device *hdmi)
806 {
807 	struct disp_device_private_data *hdmip = disp_hdmi_get_priv(hdmi);
808 	if ((NULL == hdmi) || (NULL == hdmip)) {
809 		DE_WRN("hdmi set func null  hdl!\n");
810 		return DIS_FAIL;
811 	}
812 
813 	if (hdmip->hdmi_func.get_input_color_range)
814 		return hdmip->hdmi_func.get_input_color_range();
815 
816 	if (0 == disp_hdmi_get_input_csc(hdmi))
817 		return DISP_COLOR_RANGE_0_255;
818 	else
819 		return DISP_COLOR_RANGE_16_235;
820 }
821 
disp_hdmi_cec_standby_request(struct disp_device * hdmi)822 static s32 disp_hdmi_cec_standby_request(struct disp_device *hdmi)
823 {
824 	struct disp_device_private_data *hdmip = disp_hdmi_get_priv(hdmi);
825 
826 	if ((NULL == hdmi) || (NULL == hdmip)) {
827 		DE_WRN("hdmi set func null  hdl!\n");
828 		return DIS_FAIL;
829 	}
830 
831 	if (hdmip->hdmi_func.cec_standby_request == NULL)
832 		return -1;
833 
834 	return hdmip->hdmi_func.cec_standby_request();
835 }
836 
disp_hdmi_cec_send_one_touch_play(struct disp_device * hdmi)837 static s32 disp_hdmi_cec_send_one_touch_play(struct disp_device *hdmi)
838 {
839 	struct disp_device_private_data *hdmip = disp_hdmi_get_priv(hdmi);
840 
841 	if ((NULL == hdmi) || (NULL == hdmip)) {
842 		DE_WRN("hdmi set func null  hdl!\n");
843 		return DIS_FAIL;
844 	}
845 
846 	if (hdmip->hdmi_func.cec_send_one_touch_play == NULL)
847 		return -1;
848 
849 	return hdmip->hdmi_func.cec_send_one_touch_play();
850 }
851 
disp_hdmi_suspend(struct disp_device * hdmi)852 static s32 disp_hdmi_suspend(struct disp_device *hdmi)
853 {
854 	struct disp_device_private_data *hdmip = disp_hdmi_get_priv(hdmi);
855 
856 	if ((NULL == hdmi) || (NULL == hdmip)) {
857 		DE_WRN("hdmi set func null  hdl!\n");
858 		return DIS_FAIL;
859 	}
860 
861 	mutex_lock(&hdmi_mlock);
862 	if (false == hdmip->suspended) {
863 		if (hdmip->hdmi_func.suspend != NULL)
864 			hdmip->hdmi_func.suspend();
865 
866 		hdmip->suspended = true;
867 	}
868 	mutex_unlock(&hdmi_mlock);
869 
870 	return 0;
871 }
872 
disp_hdmi_resume(struct disp_device * hdmi)873 static s32 disp_hdmi_resume(struct disp_device *hdmi)
874 {
875 	struct disp_device_private_data *hdmip = disp_hdmi_get_priv(hdmi);
876 
877 	if ((NULL == hdmi) || (NULL == hdmip)) {
878 		DE_WRN("hdmi set func null  hdl!\n");
879 		return DIS_FAIL;
880 	}
881 
882 	mutex_lock(&hdmi_mlock);
883 	if (true == hdmip->suspended) {
884 		if (hdmip->hdmi_func.resume != NULL)
885 			hdmip->hdmi_func.resume();
886 
887 		hdmip->suspended = false;
888 	}
889 	mutex_unlock(&hdmi_mlock);
890 
891 	return 0;
892 }
893 
disp_hdmi_get_fps(struct disp_device * hdmi)894 static s32 disp_hdmi_get_fps(struct disp_device *hdmi)
895 {
896 	struct disp_device_private_data *hdmip = disp_hdmi_get_priv(hdmi);
897 
898 	if ((NULL == hdmi) || (NULL == hdmip)) {
899 		DE_WRN("hdmi set func null  hdl!\n");
900 		return 0;
901 	}
902 
903 	return hdmip->frame_per_sec;
904 }
905 
disp_hdmi_check_config_dirty(struct disp_device * hdmi,struct disp_device_config * config)906 static disp_config_update_t disp_hdmi_check_config_dirty(struct disp_device *hdmi,
907 					struct disp_device_config *config)
908 {
909 	int ret = DISP_NOT_UPDATE;
910 	struct disp_device_private_data *hdmip = disp_hdmi_get_priv(hdmi);
911 
912 	if ((hdmi == NULL) || (hdmip == NULL) || (config == NULL)) {
913 		DE_WRN("NULL hdl!\n");
914 		ret = DISP_NOT_UPDATE;
915 		goto exit;
916 	}
917 
918 	if (config->type != hdmi->type) {
919 		DE_WRN("something error! type(0x%x) is error\n", config->type);
920 		ret = DISP_NOT_UPDATE;
921 		goto exit;
922 	}
923 
924 	if (hdmip->enabled == 0) {
925 		ret = DISP_NORMAL_UPDATE;
926 		goto exit;
927 	}
928 
929 	if (hdmip->hdmi_func.set_static_config == NULL) {
930 		ret = (config->mode != hdmip->config.mode);
931 	} else {
932 		if ((config->mode != hdmip->config.mode) ||
933 			(config->format != hdmip->config.format) ||
934 			(config->bits != hdmip->config.bits) ||
935 			(config->dvi_hdmi != hdmip->config.dvi_hdmi))
936 			ret = DISP_NORMAL_UPDATE;
937 		else if ((config->eotf != hdmip->config.eotf) ||
938 			(config->cs != hdmip->config.cs) ||
939 			(config->range != hdmip->config.range) ||
940 			(config->scan != hdmip->config.scan) ||
941 			(config->aspect_ratio != hdmip->config.aspect_ratio))
942 			ret = DISP_SMOOTH_UPDATE;
943 	}
944 
945 exit:
946 	return ret;
947 }
948 
disp_hdmi_set_static_config(struct disp_device * hdmi,struct disp_device_config * config)949 static s32 disp_hdmi_set_static_config(struct disp_device *hdmi,
950 			       struct disp_device_config *config)
951 {
952 	int ret = true;
953 	struct disp_device_private_data *hdmip = disp_hdmi_get_priv(hdmi);
954 
955 	if ((hdmi == NULL) || (hdmip == NULL)) {
956 		DE_WRN("NULL hdl!\n");
957 		ret = false;
958 		goto exit;
959 	}
960 	if (hdmip->hdmi_func.set_static_config == NULL)
961 		return disp_hdmi_set_mode(hdmi, config->mode);
962 
963 	memcpy(&hdmip->config, config, sizeof(struct disp_device_config));
964 	return hdmip->hdmi_func.set_static_config(config);
965 
966 exit:
967 	return ret;
968 }
969 
disp_hdmi_get_static_config(struct disp_device * hdmi,struct disp_device_config * config)970 static s32 disp_hdmi_get_static_config(struct disp_device *hdmi,
971 			      struct disp_device_config *config)
972 {
973 	int ret = 0;
974 	struct disp_device_private_data *hdmip = disp_hdmi_get_priv(hdmi);
975 
976 	if ((hdmi == NULL) || (hdmip == NULL)) {
977 		DE_WRN("NULL hdl!\n");
978 		ret = -1;
979 		goto exit;
980 	}
981 
982 	if (hdmip->hdmi_func.set_static_config == NULL) {
983 		config->type = hdmi->type;
984 		config->mode = hdmip->config.mode;
985 		if (hdmip->hdmi_func.get_input_csc == NULL)
986 			config->format = DISP_CSC_TYPE_YUV444;
987 		else
988 			config->format =
989 			    hdmip->hdmi_func.get_input_csc();
990 		config->bits = DISP_DATA_8BITS;
991 		config->eotf = DISP_EOTF_GAMMA22;
992 		if ((hdmi->timings.x_res <= 736) &&
993 		   (hdmi->timings.y_res <= 576))
994 			config->cs = DISP_BT601_F;
995 		else
996 			config->cs = DISP_BT709_F;
997 	} else {
998 		memcpy(config,
999 		       &hdmip->config,
1000 		       sizeof(struct disp_device_config));
1001 	}
1002 
1003 exit:
1004 	return ret;
1005 }
1006 
disp_hdmi_set_dynamic_config(struct disp_device * hdmi,struct disp_device_dynamic_config * config)1007 static s32 disp_hdmi_set_dynamic_config(struct disp_device *hdmi,
1008 			       struct disp_device_dynamic_config *config)
1009 {
1010 	int ret = -1;
1011 	struct disp_device_private_data *hdmip = disp_hdmi_get_priv(hdmi);
1012 
1013 	if ((hdmi == NULL) || (hdmip == NULL)) {
1014 		DE_WRN("NULL hdl!\n");
1015 		ret = false;
1016 		goto exit;
1017 	}
1018 	if (hdmip->hdmi_func.set_dynamic_config != NULL)
1019 		return hdmip->hdmi_func.set_dynamic_config(config);
1020 
1021 exit:
1022 		return ret;
1023 }
1024 
disp_init_hdmi(struct disp_bsp_init_para * para)1025 s32 disp_init_hdmi(struct disp_bsp_init_para *para)
1026 {
1027 	u32 num_devices;
1028 	u32 disp = 0;
1029 	struct disp_device *hdmi;
1030 	struct disp_device_private_data *hdmip;
1031 	u32 hwdev_index = 0;
1032 	u32 num_devices_support_hdmi = 0;
1033 	char compat[32] = { 0 };
1034 	const char *str;
1035 	struct device_node *node;
1036 	int ret;
1037 
1038 	snprintf(compat, sizeof(compat), "allwinner,sunxi-hdmi");
1039 	node = of_find_compatible_node(NULL, NULL, compat);
1040 	if (!node) {
1041 		pr_err("do not get the node of hdmi\n");
1042 		goto exit;
1043 	}
1044 
1045 	ret = of_property_read_string(node, "status", &str);
1046 	if (ret || strcmp(str, "okay")) {
1047 		DE_WRN("dont support hdmi\n");
1048 		goto exit;
1049 	}
1050 	hdmi_used = 1;
1051 
1052 	DE_INF("disp_init_hdmi\n");
1053 
1054 	spin_lock_init(&hdmi_data_lock);
1055 	mutex_init(&hdmi_mlock);
1056 
1057 	num_devices = bsp_disp_feat_get_num_devices();
1058 	for (hwdev_index = 0; hwdev_index < num_devices; hwdev_index++) {
1059 		if (bsp_disp_feat_is_supported_output_types(hwdev_index,
1060 		    DISP_OUTPUT_TYPE_HDMI))
1061 			num_devices_support_hdmi++;
1062 	}
1063 	hdmis =
1064 	    kmalloc_array(num_devices_support_hdmi,
1065 			  sizeof(struct disp_device),
1066 			  GFP_KERNEL | __GFP_ZERO);
1067 	if (hdmis == NULL) {
1068 		DE_WRN("malloc memory fail!\n");
1069 		goto malloc_err;
1070 	}
1071 
1072 	hdmi_private =
1073 	    (struct disp_device_private_data *)
1074 	    kmalloc(sizeof(struct disp_device_private_data)
1075 		    * num_devices_support_hdmi,
1076 		    GFP_KERNEL | __GFP_ZERO);
1077 	if (hdmi_private == NULL) {
1078 		DE_WRN("malloc memory fail!\n");
1079 		goto malloc_err;
1080 	}
1081 
1082 	disp = 0;
1083 	for (hwdev_index = 0; hwdev_index < num_devices; hwdev_index++) {
1084 		if (!bsp_disp_feat_is_supported_output_types
1085 		    (hwdev_index, DISP_OUTPUT_TYPE_HDMI)) {
1086 			continue;
1087 		}
1088 
1089 		hdmi = &hdmis[disp];
1090 		hdmip = &hdmi_private[disp];
1091 		hdmi->priv_data = (void *)hdmip;
1092 
1093 		hdmi->disp = disp;
1094 		hdmi->hwdev_index = hwdev_index;
1095 		sprintf(hdmi->name, "hdmi%d", disp);
1096 		hdmi->type = DISP_OUTPUT_TYPE_HDMI;
1097 		hdmip->config.type = DISP_OUTPUT_TYPE_HDMI;
1098 		hdmip->config.mode = DISP_TV_MOD_720P_50HZ;
1099 		hdmip->config.format = DISP_CSC_TYPE_YUV444;
1100 		hdmip->config.bits = DISP_DATA_8BITS;
1101 		hdmip->config.eotf = DISP_EOTF_GAMMA22;
1102 		hdmip->config.cs = DISP_UNDEF;
1103 		hdmip->config.dvi_hdmi = DISP_HDMI;
1104 		hdmip->config.range = DISP_COLOR_RANGE_16_235;
1105 		hdmip->config.scan = DISP_SCANINFO_NO_DATA;
1106 		hdmip->config.aspect_ratio = 8;
1107 		hdmip->irq_no =
1108 		    para->irq_no[DISP_MOD_LCD0 + hwdev_index];
1109 		hdmip->clk = para->clk_tcon[hwdev_index];
1110 		hdmip->bus_clk = para->clk_bus_tcon[hwdev_index];
1111 		hdmip->rst_bus_clk = para->rst_bus_tcon[hwdev_index];
1112 		hdmi->set_manager = disp_device_set_manager;
1113 		hdmi->unset_manager = disp_device_unset_manager;
1114 		hdmi->get_resolution = disp_device_get_resolution;
1115 		hdmi->get_timings = disp_device_get_timings;
1116 		hdmi->is_interlace = disp_device_is_interlace;
1117 
1118 		hdmi->init = disp_hdmi_init;
1119 		hdmi->exit = disp_hdmi_exit;
1120 
1121 		hdmi->set_func = disp_hdmi_set_func;
1122 		hdmi->enable = disp_hdmi_enable;
1123 		hdmi->sw_enable = disp_hdmi_sw_enable;
1124 		hdmi->disable = disp_hdmi_disable;
1125 		hdmi->is_enabled = disp_hdmi_is_enabled;
1126 		/* hdmi->check_if_enabled = disp_hdmi_check_if_enabled; */
1127 		hdmi->set_mode = disp_hdmi_set_mode;
1128 		hdmi->get_mode = disp_hdmi_get_mode;
1129 		hdmi->check_support_mode = disp_hdmi_check_support_mode;
1130 		hdmi->set_static_config = disp_hdmi_set_static_config;
1131 		hdmi->get_static_config = disp_hdmi_get_static_config;
1132 		hdmi->set_dynamic_config = disp_hdmi_set_dynamic_config;
1133 		hdmi->check_config_dirty = disp_hdmi_check_config_dirty;
1134 		hdmi->get_input_csc = disp_hdmi_get_input_csc;
1135 		hdmi->get_input_color_range =
1136 		    disp_hdmi_get_input_color_range;
1137 		hdmi->cec_standby_request =
1138 			disp_hdmi_cec_standby_request;
1139 		hdmi->cec_send_one_touch_play =
1140 			disp_hdmi_cec_send_one_touch_play;
1141 		hdmi->suspend = disp_hdmi_suspend;
1142 		hdmi->resume = disp_hdmi_resume;
1143 		hdmi->detect = disp_hdmi_detect;
1144 		hdmi->set_detect = disp_hdmi_set_detect;
1145 		hdmi->smooth_enable = disp_hdmi_smooth_enable;
1146 		hdmi->get_status = disp_device_get_status;
1147 		hdmi->is_in_safe_period = disp_device_is_in_safe_period;
1148 		hdmi->usec_before_vblank =
1149 			disp_device_usec_before_vblank;
1150 		hdmi->get_fps = disp_hdmi_get_fps;
1151 		hdmi->show_builtin_patten = disp_device_show_builtin_patten;
1152 
1153 		hdmi->init(hdmi);
1154 		disp_device_register(hdmi);
1155 		disp++;
1156 	}
1157 
1158 	return 0;
1159 
1160 malloc_err:
1161 	kfree(hdmis);
1162 	kfree(hdmi_private);
1163 	hdmis = NULL;
1164 	hdmi_private = NULL;
1165 exit:
1166 	return -1;
1167 }
1168 
disp_exit_hdmi(void)1169 s32 disp_exit_hdmi(void)
1170 {
1171 	u32 num_devices;
1172 	u32 disp = 0;
1173 	struct disp_device *hdmi;
1174 	u32 hwdev_index = 0;
1175 
1176 	if ((hdmi_used == 0) || (!hdmis))
1177 		return 0;
1178 
1179 	num_devices = bsp_disp_feat_get_num_devices();
1180 
1181 	disp = 0;
1182 	for (hwdev_index = 0; hwdev_index < num_devices; hwdev_index++) {
1183 		if (!bsp_disp_feat_is_supported_output_types
1184 		    (hwdev_index, DISP_OUTPUT_TYPE_HDMI)) {
1185 			continue;
1186 		}
1187 
1188 		hdmi = &hdmis[disp];
1189 		disp_device_unregister(hdmi);
1190 		hdmi->exit(hdmi);
1191 		disp++;
1192 	}
1193 
1194 	kfree(hdmis);
1195 	kfree(hdmi_private);
1196 	hdmis = NULL;
1197 	hdmi_private = NULL;
1198 
1199 	return 0;
1200 }
1201 #endif
1202