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