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