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