1 /*
2 * drivers/video/fbdev/sunxi/disp2/disp/de/lowlevel_v33x/disp_al_tcon/disp_al_tcon.c
3 *
4 * Copyright (c) 2007-2018 Allwinnertech Co., Ltd.
5 * Author: zhengxiaobin <zhengxiaobin@allwinnertech.com>
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17 #include "disp_al_tcon.h"
18
19
20 /*
21 * disp_al_private_data - abstract layer private data
22 * @output_type: current output type of specified device(eg. LCD/HDMI/TV)
23 * @output_mode: current output mode of specified device(eg. 720P,1080P)
24 * @output_format: current output color format of specified device
25 * @output_color_space: current output color space of specified device
26 * @tcon_id: the id of device connect to the specified de
27 * @de_id: the id of de connect to the specified tcon
28 * @disp_size: the output size of specified de
29 * @output_fps: the output fps of specified device
30 * @tcon_type: tcon type, 0: tcon0(drive panel), 1: tcon1(general drive HDMI/TV)
31 */
32 struct disp_al_private_data {
33 u32 output_type[DEVICE_NUM];
34 /* u32 output_mode[DEVICE_NUM]; */
35 u32 output_format[DEVICE_NUM];
36 /* u32 output_color_space[DEVICE_NUM]; */
37 /* u32 output_color_range[DEVICE_NUM]; */
38 /* u32 output_eotf[DEVICE_NUM]; */
39 /* u32 tcon_id[DE_NUM]; */
40 u32 de_id[DEVICE_NUM];
41 /* struct disp_rect disp_size[DE_NUM]; */
42 /* u32 output_fps[DEVICE_NUM]; */
43 u32 tcon_type[DEVICE_NUM];
44 /* u32 de_backcolor[DE_NUM]; */
45 /* bool direct_show[DE_NUM]; */
46 /* bool direct_show_toggle[DE_NUM]; */
47 u32 de_use_rcq[DEVICE_NUM];
48 };
49
50 static struct disp_al_private_data al_priv;
51
52 /* lcd */
53 /* lcd_dclk_freq * div -> lcd_clk_freq * div2 -> pll_freq */
54 /* lcd_dclk_freq * dsi_div -> lcd_dsi_freq */
disp_al_lcd_get_clk_info(u32 screen_id,struct lcd_clk_info * info,struct disp_panel_para * panel)55 int disp_al_lcd_get_clk_info(u32 screen_id,
56 struct lcd_clk_info *info, struct disp_panel_para *panel)
57 {
58 int tcon_div = 6, lcd_div = 1, dsi_div = 4, dsi_rate = 0, find = 0,
59 i = 0;
60 /* tcon_div >= 6 when
61 * lcd_dev[sel]->tcon0_dclk.bits.tcon0_dclk_en = 0xf
62 * */
63
64 #if defined(CONFIG_FPGA_V7_PLATFORM) || defined(CONFIG_FPGA_V4_PLATFORM)
65 struct lcd_clk_info clk_tbl[] = {
66 {LCD_IF_HV, 0x12, 1, 1, 0},
67 {LCD_IF_CPU, 12, 1, 1, 0},
68 {LCD_IF_LVDS, 7, 1, 1, 0},
69 #if defined (DSI_VERSION_28)
70 {LCD_IF_DSI, 4, 1, 4, 0},
71 #else
72 {LCD_IF_DSI, 4, 1, 4, 148500000},
73 #endif /*endif DSI_VERSION_28 */
74 };
75 #else
76 static struct lcd_clk_info clk_tbl[] = {
77 {LCD_IF_HV, 6, 1, 1, 0},
78 {LCD_IF_CPU, 12, 1, 1, 0},
79 {LCD_IF_LVDS, 7, 1, 1, 0},
80 #if defined (DSI_VERSION_28)
81 {LCD_IF_DSI, 4, 1, 4, 0},
82 #else
83 {LCD_IF_DSI, 4, 1, 4, 148500000},
84 #endif /*endif DSI_VERSION_28 */
85 };
86 #endif
87
88
89 if (panel == NULL) {
90 __wrn("panel is NULL\n");
91 return -1;
92 }
93
94 memset(info, 0, sizeof(struct lcd_clk_info));
95 for (i = 0; i < sizeof(clk_tbl) / sizeof(struct lcd_clk_info); i++) {
96 if (clk_tbl[i].lcd_if == panel->lcd_if) {
97 tcon_div = clk_tbl[i].tcon_div;
98 lcd_div = clk_tbl[i].lcd_div;
99 dsi_div = clk_tbl[i].dsi_div;
100 dsi_rate = clk_tbl[i].dsi_rate;
101 find = 1;
102 break;
103 }
104 }
105
106 #if !defined(DSI_VERSION_28)
107 if (panel->lcd_if == LCD_IF_DSI) {
108 u32 lane = panel->lcd_dsi_lane;
109 u32 bitwidth = 0;
110
111 switch (panel->lcd_dsi_format) {
112 case LCD_DSI_FORMAT_RGB888:
113 bitwidth = 24;
114 break;
115 case LCD_DSI_FORMAT_RGB666:
116 bitwidth = 24;
117 break;
118 case LCD_DSI_FORMAT_RGB565:
119 bitwidth = 16;
120 break;
121 case LCD_DSI_FORMAT_RGB666P:
122 bitwidth = 18;
123 break;
124 }
125
126 dsi_div = bitwidth / lane;
127 if (panel->lcd_dsi_if == LCD_DSI_IF_COMMAND_MODE) {
128 tcon_div = dsi_div;
129 }
130 }
131 #endif /*endif DSI_VERSION_28 */
132
133 if (find == 0)
134 __wrn("cant find clk info for lcd_if %d\n", panel->lcd_if);
135 if (panel->lcd_if == LCD_IF_HV &&
136 panel->lcd_hv_if == LCD_HV_IF_CCIR656_2CYC &&
137 panel->ccir_clk_div > 0)
138 tcon_div = panel->ccir_clk_div;
139 else if (panel->lcd_tcon_mode == DISP_TCON_DUAL_DSI &&
140 panel->lcd_if == LCD_IF_DSI) {
141 tcon_div = tcon_div / 2;
142 dsi_div /= 2;
143 }
144
145 #if defined(DSI_VERSION_28)
146 if (panel->lcd_if == LCD_IF_DSI &&
147 panel->lcd_dsi_if == LCD_DSI_IF_COMMAND_MODE) {
148 tcon_div = 6;
149 dsi_div = 6;
150 }
151 #endif
152
153 info->tcon_div = tcon_div;
154 info->lcd_div = lcd_div;
155 info->dsi_div = dsi_div;
156 info->dsi_rate = dsi_rate;
157
158 return 0;
159 }
160
disp_al_lcd_cfg(u32 screen_id,struct disp_panel_para * panel,struct panel_extend_para * extend_panel)161 int disp_al_lcd_cfg(u32 screen_id, struct disp_panel_para *panel,
162 struct panel_extend_para *extend_panel)
163 {
164 struct lcd_clk_info info;
165
166 memset(&info, 0, sizeof(struct lcd_clk_info));
167
168 tcon_init(screen_id);
169 disp_al_lcd_get_clk_info(screen_id, &info, panel);
170 tcon0_set_dclk_div(screen_id, info.tcon_div);
171
172 #if !defined(TCON1_DRIVE_PANEL)
173 al_priv.tcon_type[screen_id] = 0;
174 if (tcon0_cfg(screen_id, panel, al_priv.de_use_rcq[screen_id]) != 0)
175 DE_WRN("lcd cfg fail!\n");
176 else
177 DE_INF("lcd cfg ok!\n");
178
179 tcon0_cfg_ext(screen_id, extend_panel);
180 tcon0_src_select(screen_id, LCD_SRC_DE, al_priv.de_id[screen_id]);
181
182 if (panel->lcd_if == LCD_IF_DSI) {
183 #if defined(SUPPORT_DSI)
184 if (panel->lcd_if == LCD_IF_DSI) {
185 if (0 != dsi_cfg(screen_id, panel))
186 DE_WRN("dsi %d cfg fail!\n", screen_id);
187 if (panel->lcd_tcon_mode == DISP_TCON_DUAL_DSI &&
188 screen_id + 1 < DEVICE_DSI_NUM) {
189 if (0 != dsi_cfg(screen_id + 1, panel))
190 DE_WRN("dsi %d cfg fail!\n",
191 screen_id + 1);
192 }
193 }
194 #endif
195 }
196 #else
197
198 /* There is no tcon0 on this platform,
199 * At fpga period, we can use tcon1 to driver lcd pnael,
200 * so, here we need to config tcon1 here.
201 */
202 al_priv.tcon_type[screen_id] = 1;
203 if (tcon1_cfg_ex(screen_id, panel) != 0)
204 DE_WRN("lcd cfg fail!\n");
205 else
206 DE_INF("lcd cfg ok!\n");
207 #endif
208 return 0;
209 }
210
disp_al_lcd_cfg_ext(u32 screen_id,struct panel_extend_para * extend_panel)211 int disp_al_lcd_cfg_ext(u32 screen_id, struct panel_extend_para *extend_panel)
212 {
213 tcon0_cfg_ext(screen_id, extend_panel);
214
215 return 0;
216 }
217
disp_al_lcd_enable(u32 screen_id,struct disp_panel_para * panel)218 int disp_al_lcd_enable(u32 screen_id, struct disp_panel_para *panel)
219 {
220 #if !defined(TCON1_DRIVE_PANEL)
221
222 tcon0_open(screen_id, panel);
223 if (panel->lcd_if == LCD_IF_LVDS) {
224 lvds_open(screen_id, panel);
225 } else if (panel->lcd_if == LCD_IF_DSI) {
226 #if defined(SUPPORT_DSI)
227 dsi_open(screen_id, panel);
228 if (panel->lcd_tcon_mode == DISP_TCON_DUAL_DSI &&
229 screen_id + 1 < DEVICE_DSI_NUM)
230 dsi_open(screen_id + 1, panel);
231 #endif
232 }
233
234 #else
235 /* There is no tcon0 on this platform,
236 * At fpga period, we can use tcon1 to driver lcd pnael,
237 * so, here we need to open tcon1 here.
238 */
239 tcon1_open(screen_id);
240 #endif
241
242 return 0;
243 }
244
disp_al_lcd_disable(u32 screen_id,struct disp_panel_para * panel)245 int disp_al_lcd_disable(u32 screen_id, struct disp_panel_para *panel)
246 {
247
248 #if !defined(TCON1_DRIVE_PANEL)
249
250 if (panel->lcd_if == LCD_IF_LVDS) {
251 lvds_close(screen_id);
252 } else if (panel->lcd_if == LCD_IF_DSI) {
253 #if defined(SUPPORT_DSI)
254 dsi_close(screen_id);
255 if (panel->lcd_tcon_mode == DISP_TCON_DUAL_DSI &&
256 screen_id + 1 < DEVICE_DSI_NUM)
257 dsi_close(screen_id + 1);
258 #endif
259 }
260 tcon0_close(screen_id);
261 #else
262 /* There is no tcon0 on platform sun50iw2,
263 * on fpga period, we can use tcon1 to driver lcd pnael,
264 * so, here we need to close tcon1.
265 */
266 tcon1_close(screen_id);
267 #endif
268 tcon_exit(screen_id);
269
270 return 0;
271 }
272
273 /* query lcd irq, clear it when the irq queried exist
274 */
disp_al_lcd_query_irq(u32 screen_id,enum __lcd_irq_id_t irq_id,struct disp_panel_para * panel)275 int disp_al_lcd_query_irq(u32 screen_id, enum __lcd_irq_id_t irq_id,
276 struct disp_panel_para *panel)
277 {
278 #if defined(SUPPORT_DSI) && defined(DSI_VERSION_40)
279 if (panel->lcd_if == LCD_IF_DSI &&
280 panel->lcd_dsi_if != LCD_DSI_IF_COMMAND_MODE) {
281 enum __dsi_irq_id_t dsi_irq = (irq_id == LCD_IRQ_TCON0_VBLK)
282 ? DSI_IRQ_VIDEO_VBLK
283 : DSI_IRQ_VIDEO_LINE;
284
285 return dsi_irq_query(screen_id, dsi_irq);
286 } else
287 #endif
288 return tcon_irq_query(screen_id,
289 (al_priv.tcon_type[screen_id] == 0) ?
290 irq_id : LCD_IRQ_TCON1_VBLK);
291 }
292
disp_al_lcd_enable_irq(u32 screen_id,enum __lcd_irq_id_t irq_id,struct disp_panel_para * panel)293 int disp_al_lcd_enable_irq(u32 screen_id, enum __lcd_irq_id_t irq_id,
294 struct disp_panel_para *panel)
295 {
296 int ret = 0;
297
298 #if defined(SUPPORT_DSI) && defined(DSI_VERSION_40)
299 if (panel->lcd_if == LCD_IF_DSI) {
300 enum __dsi_irq_id_t dsi_irq =
301 (irq_id == LCD_IRQ_TCON0_VBLK) ?
302 DSI_IRQ_VIDEO_VBLK : DSI_IRQ_VIDEO_LINE;
303
304 ret = dsi_irq_enable(screen_id, dsi_irq);
305 }
306 #endif
307 ret =
308 tcon_irq_enable(screen_id,
309 (al_priv.tcon_type[screen_id] == 0) ?
310 irq_id : LCD_IRQ_TCON1_VBLK);
311
312 return ret;
313 }
314
disp_al_lcd_disable_irq(u32 screen_id,enum __lcd_irq_id_t irq_id,struct disp_panel_para * panel)315 int disp_al_lcd_disable_irq(u32 screen_id, enum __lcd_irq_id_t irq_id,
316 struct disp_panel_para *panel)
317 {
318 int ret = 0;
319
320 #if defined(SUPPORT_DSI) && defined(DSI_VERSION_40)
321 if (panel->lcd_if == LCD_IF_DSI) {
322 enum __dsi_irq_id_t dsi_irq =
323 (irq_id == LCD_IRQ_TCON0_VBLK) ?
324 DSI_IRQ_VIDEO_VBLK : DSI_IRQ_VIDEO_LINE;
325
326 ret = dsi_irq_disable(screen_id, dsi_irq);
327 }
328 #endif
329 ret =
330 tcon_irq_disable(screen_id,
331 (al_priv.tcon_type[screen_id] ==
332 0) ? irq_id : LCD_IRQ_TCON1_VBLK);
333
334 return ret;
335 }
336
disp_al_lcd_tri_busy(u32 screen_id,struct disp_panel_para * panel)337 int disp_al_lcd_tri_busy(u32 screen_id, struct disp_panel_para *panel)
338 {
339 int busy = 0;
340 int ret = 0;
341
342 busy |= tcon0_tri_busy(screen_id);
343 #if defined(SUPPORT_DSI)
344 busy |= dsi_inst_busy(screen_id);
345 #endif
346 ret = (busy == 0) ? 0 : 1;
347
348 return ret;
349 }
350
351 /* take dsi irq s32o account, todo? */
disp_al_lcd_tri_start(u32 screen_id,struct disp_panel_para * panel)352 int disp_al_lcd_tri_start(u32 screen_id, struct disp_panel_para *panel)
353 {
354 #if defined(SUPPORT_DSI) && defined(DSI_VERSION_40)
355 if (panel->lcd_if == LCD_IF_DSI)
356 dsi_tri_start(screen_id);
357 #endif
358 return tcon0_tri_start(screen_id);
359 }
360
disp_al_lcd_io_cfg(u32 screen_id,u32 enable,struct disp_panel_para * panel)361 int disp_al_lcd_io_cfg(u32 screen_id, u32 enable, struct disp_panel_para *panel)
362 {
363 #if defined(SUPPORT_DSI)
364 if (panel->lcd_if == LCD_IF_DSI) {
365 if (enable == 1) {
366 dsi_io_open(screen_id, panel);
367 if (panel->lcd_tcon_mode == DISP_TCON_DUAL_DSI &&
368 screen_id + 1 < DEVICE_DSI_NUM)
369 dsi_io_open(screen_id + 1, panel);
370 } else {
371 dsi_io_close(screen_id);
372 if (panel->lcd_tcon_mode == DISP_TCON_DUAL_DSI &&
373 screen_id + 1 < DEVICE_DSI_NUM)
374 dsi_io_close(screen_id + 1);
375 }
376 }
377 #endif
378
379 return 0;
380 }
381
disp_al_lcd_get_cur_line(u32 screen_id,struct disp_panel_para * panel)382 int disp_al_lcd_get_cur_line(u32 screen_id, struct disp_panel_para *panel)
383 {
384 #if defined(SUPPORT_DSI) && defined(DSI_VERSION_40)
385 if (panel->lcd_if == LCD_IF_DSI)
386 return dsi_get_cur_line(screen_id);
387 #endif
388 return tcon_get_cur_line(screen_id,
389 al_priv.tcon_type[screen_id]);
390 }
391
disp_al_lcd_get_start_delay(u32 screen_id,struct disp_panel_para * panel)392 int disp_al_lcd_get_start_delay(u32 screen_id, struct disp_panel_para *panel)
393 {
394 #if defined(SUPPORT_DSI) && defined(DSI_VERSION_40)
395 u32 lcd_start_delay = 0;
396 u32 de_clk_rate = de_get_clk_rate() / 1000000;
397 if (panel && panel->lcd_if == LCD_IF_DSI) {
398 lcd_start_delay =
399 ((tcon0_get_cpu_tri2_start_delay(screen_id) + 1) << 3) *
400 (panel->lcd_dclk_freq) / (panel->lcd_ht * de_clk_rate);
401 return dsi_get_start_delay(screen_id) + lcd_start_delay;
402 } else
403 #endif
404 return tcon_get_start_delay(screen_id,
405 al_priv.tcon_type[screen_id]);
406 }
407
408 /* hdmi */
disp_al_hdmi_pad_sel(u32 screen_id,u32 pad)409 int disp_al_hdmi_pad_sel(u32 screen_id, u32 pad)
410 {
411 tcon_pan_sel(screen_id, pad);
412
413 return 0;
414 }
415
disp_al_hdmi_enable(u32 screen_id)416 int disp_al_hdmi_enable(u32 screen_id)
417 {
418 tcon1_hdmi_clk_enable(screen_id, 1);
419
420 tcon1_open(screen_id);
421 return 0;
422 }
423
disp_al_hdmi_disable(u32 screen_id)424 int disp_al_hdmi_disable(u32 screen_id)
425 {
426 tcon1_close(screen_id);
427 tcon_exit(screen_id);
428 tcon1_hdmi_clk_enable(screen_id, 0);
429
430 return 0;
431 }
432
disp_al_hdmi_set_output_format(u32 screen_id,u32 output_format)433 int disp_al_hdmi_set_output_format(
434 u32 screen_id, u32 output_format)
435 {
436 al_priv.output_format[screen_id] = output_format;
437 return 0;
438 }
439
disp_al_hdmi_cfg(u32 screen_id,struct disp_video_timings * video_info)440 int disp_al_hdmi_cfg(u32 screen_id, struct disp_video_timings *video_info)
441 {
442 struct disp_video_timings *timings = NULL;
443
444 al_priv.tcon_type[screen_id] = 1;
445 al_priv.output_format[screen_id]
446 = bsp_disp_hdmi_get_color_format();
447
448 timings = kmalloc(sizeof(struct disp_video_timings),
449 GFP_KERNEL | __GFP_ZERO);
450 if (timings) {
451 memcpy(timings, video_info, sizeof(struct disp_video_timings));
452 if (al_priv.output_format[screen_id] == DISP_CSC_TYPE_YUV420) {
453 timings->x_res /= 2;
454 timings->hor_total_time /= 2;
455 timings->hor_back_porch /= 2;
456 timings->hor_front_porch /= 2;
457 timings->hor_sync_time /= 2;
458 }
459 } else {
460 __wrn("malloc memory for timings fail! size=0x%x\n",
461 (unsigned int)sizeof(struct disp_video_timings));
462 }
463 tcon_init(screen_id);
464
465 if (timings)
466 tcon1_set_timming(screen_id, timings);
467 else
468 tcon1_set_timming(screen_id, video_info);
469 tcon1_src_select(screen_id, LCD_SRC_DE, al_priv.de_id[screen_id]);
470 tcon1_black_src(screen_id, 0, al_priv.output_format[screen_id]);
471
472 kfree(timings);
473
474 return 0;
475 }
476
disp_al_hdmi_irq_enable(u32 screen_id)477 int disp_al_hdmi_irq_enable(u32 screen_id)
478 {
479 tcon_irq_enable(screen_id, LCD_IRQ_TCON1_VBLK);
480 return 0;
481 }
482
disp_al_hdmi_irq_disable(u32 screen_id)483 int disp_al_hdmi_irq_disable(u32 screen_id)
484 {
485 tcon_irq_disable(screen_id, LCD_IRQ_TCON1_VBLK);
486 return 0;
487 }
488
489 /* tv */
disp_al_tv_enable(u32 screen_id)490 int disp_al_tv_enable(u32 screen_id)
491 {
492 tcon1_tv_clk_enable(screen_id, 1);
493 tcon1_open(screen_id);
494
495 return 0;
496 }
497
disp_al_tv_disable(u32 screen_id)498 int disp_al_tv_disable(u32 screen_id)
499 {
500 tcon1_close(screen_id);
501 tcon_exit(screen_id);
502 tcon1_tv_clk_enable(screen_id, 0);
503
504 return 0;
505 }
506
507 #if defined(SUPPORT_EDP)
disp_al_edp_cfg(u32 screen_id,u32 fps,u32 edp_index)508 int disp_al_edp_cfg(u32 screen_id, u32 fps, u32 edp_index)
509 {
510 al_priv.tcon_type[screen_id] = 0;
511 edp_de_attach(edp_index, al_priv.de_id[screen_id]);
512 return 0;
513 }
514
disp_al_edp_disable(u32 screen_id)515 int disp_al_edp_disable(u32 screen_id)
516 {
517 return 0;
518 }
519 #endif
520
disp_al_tv_cfg(u32 screen_id,struct disp_video_timings * video_info)521 int disp_al_tv_cfg(u32 screen_id, struct disp_video_timings *video_info)
522 {
523 al_priv.tcon_type[screen_id] = 1;
524
525 tcon_init(screen_id);
526 /*#if defined(HAVE_DEVICE_COMMON_MODULE)*/
527 /*rgb_src_sel(screen_id);*/
528 /*#endif*/
529 tcon1_set_timming(screen_id, video_info);
530 #if defined (CONFIG_ARCH_SUN50IW9)
531 tcon1_yuv_range(screen_id, 0);
532 #else
533 tcon1_yuv_range(screen_id, 1);
534 #endif
535 tcon1_src_select(screen_id, LCD_SRC_DE, al_priv.de_id[screen_id]);
536
537 return 0;
538 }
539
disp_al_tv_irq_enable(u32 screen_id)540 int disp_al_tv_irq_enable(u32 screen_id)
541 {
542 tcon_irq_enable(screen_id, LCD_IRQ_TCON1_VBLK);
543
544 return 0;
545 }
546
disp_al_tv_irq_disable(u32 screen_id)547 int disp_al_tv_irq_disable(u32 screen_id)
548 {
549 tcon_irq_disable(screen_id, LCD_IRQ_TCON1_VBLK);
550
551 return 0;
552 }
553
554 #if defined(SUPPORT_VGA)
555 /* vga interface
556 */
disp_al_vga_enable(u32 screen_id)557 int disp_al_vga_enable(u32 screen_id)
558 {
559 tcon1_open(screen_id);
560
561 return 0;
562 }
563
disp_al_vga_disable(u32 screen_id)564 int disp_al_vga_disable(u32 screen_id)
565 {
566 tcon1_close(screen_id);
567 tcon_exit(screen_id);
568
569 return 0;
570 }
571
disp_al_vga_cfg(u32 screen_id,struct disp_video_timings * video_info)572 int disp_al_vga_cfg(u32 screen_id, struct disp_video_timings *video_info)
573 {
574 al_priv.tcon_type[screen_id] = 1;
575
576 tcon_init(screen_id);
577 tcon1_set_timming(screen_id, video_info);
578 tcon1_src_select(screen_id, LCD_SRC_DE, al_priv.de_id[screen_id]);
579
580 return 0;
581 }
582
disp_al_vga_irq_enable(u32 screen_id)583 int disp_al_vga_irq_enable(u32 screen_id)
584 {
585 tcon_irq_enable(screen_id, LCD_IRQ_TCON1_VBLK);
586
587 return 0;
588 }
589
disp_al_vga_irq_disable(u32 screen_id)590 int disp_al_vga_irq_disable(u32 screen_id)
591 {
592 tcon_irq_disable(screen_id, LCD_IRQ_TCON1_VBLK);
593
594 return 0;
595 }
596 #endif
597
disp_al_vdevice_cfg(u32 screen_id,struct disp_video_timings * video_info,struct disp_vdevice_interface_para * para,u8 config_tcon_only)598 int disp_al_vdevice_cfg(u32 screen_id, struct disp_video_timings *video_info,
599 struct disp_vdevice_interface_para *para,
600 u8 config_tcon_only)
601 {
602 struct lcd_clk_info clk_info;
603 struct disp_panel_para info;
604
605 al_priv.tcon_type[screen_id] = 0;
606
607 memset(&info, 0, sizeof(struct disp_panel_para));
608 info.lcd_if = para->intf;
609 info.lcd_x = video_info->x_res;
610 info.lcd_y = video_info->y_res;
611 info.lcd_hv_if = (enum disp_lcd_hv_if) para->sub_intf;
612 info.lcd_dclk_freq = video_info->pixel_clk;
613 info.lcd_ht = video_info->hor_total_time;
614 info.lcd_hbp = video_info->hor_back_porch + video_info->hor_sync_time;
615 info.lcd_hspw = video_info->hor_sync_time;
616 info.lcd_vt = video_info->ver_total_time;
617 info.lcd_vbp = video_info->ver_back_porch + video_info->ver_sync_time;
618 info.lcd_vspw = video_info->ver_sync_time;
619 info.lcd_interlace = video_info->b_interlace;
620 info.lcd_hv_syuv_fdly = para->fdelay;
621 info.lcd_hv_clk_phase = para->clk_phase;
622 info.lcd_hv_sync_polarity = para->sync_polarity;
623 info.ccir_clk_div = para->ccir_clk_div;
624 info.input_csc = para->input_csc;
625
626 if (info.lcd_hv_if == LCD_HV_IF_CCIR656_2CYC)
627 info.lcd_hv_syuv_seq = para->sequence;
628 else
629 info.lcd_hv_srgb_seq = para->sequence;
630 tcon_init(screen_id);
631 disp_al_lcd_get_clk_info(screen_id, &clk_info, &info);
632 tcon0_set_dclk_div(screen_id, clk_info.tcon_div);
633
634 if (para->sub_intf == LCD_HV_IF_CCIR656_2CYC)
635 tcon1_yuv_range(screen_id, 1);
636 if (tcon0_cfg(screen_id, &info, al_priv.de_use_rcq[screen_id]) != 0)
637 DE_WRN("lcd cfg fail!\n");
638 else
639 DE_INF("lcd cfg ok!\n");
640
641 if (!config_tcon_only)
642 tcon0_src_select(screen_id, LCD_SRC_DE,
643 al_priv.de_id[screen_id]);
644 else
645 DE_INF("%s:config_tcon_only is %d\n", __func__,
646 config_tcon_only);
647
648 return 0;
649 }
650
disp_al_vdevice_enable(u32 screen_id)651 int disp_al_vdevice_enable(u32 screen_id)
652 {
653 struct disp_panel_para panel;
654
655 memset(&panel, 0, sizeof(struct disp_panel_para));
656 panel.lcd_if = LCD_IF_HV;
657 tcon0_open(screen_id, &panel);
658
659 return 0;
660 }
661
disp_al_vdevice_disable(u32 screen_id)662 int disp_al_vdevice_disable(u32 screen_id)
663 {
664 tcon0_close(screen_id);
665 tcon_exit(screen_id);
666
667 return 0;
668 }
669
670 /* screen_id: used for index of manager */
disp_al_device_get_cur_line(u32 screen_id)671 int disp_al_device_get_cur_line(u32 screen_id)
672 {
673 u32 tcon_type = al_priv.tcon_type[screen_id];
674
675 return tcon_get_cur_line(screen_id, tcon_type);
676 }
677
disp_al_device_get_start_delay(u32 screen_id)678 int disp_al_device_get_start_delay(u32 screen_id)
679 {
680 u32 tcon_type = al_priv.tcon_type[screen_id];
681
682 tcon_type = (al_priv.tcon_type[screen_id] == 0) ? 0 : 1;
683 return tcon_get_start_delay(screen_id, tcon_type);
684 }
685
disp_al_device_query_irq(u32 screen_id)686 int disp_al_device_query_irq(u32 screen_id)
687 {
688 int ret = 0;
689 int irq_id = 0;
690
691 irq_id = (al_priv.tcon_type[screen_id] == 0) ?
692 LCD_IRQ_TCON0_VBLK : LCD_IRQ_TCON1_VBLK;
693 ret = tcon_irq_query(screen_id, irq_id);
694
695 return ret;
696 }
697
disp_al_device_enable_irq(u32 screen_id)698 int disp_al_device_enable_irq(u32 screen_id)
699 {
700 int ret = 0;
701 int irq_id = 0;
702
703 irq_id = (al_priv.tcon_type[screen_id] == 0) ?
704 LCD_IRQ_TCON0_VBLK : LCD_IRQ_TCON1_VBLK;
705 ret = tcon_irq_enable(screen_id, irq_id);
706
707 return ret;
708 }
709
disp_al_device_disable_irq(u32 screen_id)710 int disp_al_device_disable_irq(u32 screen_id)
711 {
712 int ret = 0;
713 int irq_id = 0;
714
715 irq_id = (al_priv.tcon_type[screen_id] == 0) ?
716 LCD_IRQ_TCON0_VBLK : LCD_IRQ_TCON1_VBLK;
717 ret = tcon_irq_disable(screen_id, irq_id);
718
719 return ret;
720 }
721
disp_al_lcd_get_status(u32 screen_id,struct disp_panel_para * panel)722 int disp_al_lcd_get_status(u32 screen_id, struct disp_panel_para *panel)
723 {
724 int ret = 0;
725 #if defined(DSI_VERSION_40)
726 if (panel->lcd_if == LCD_IF_DSI)
727 ret = dsi_get_status(screen_id);
728 else
729 #endif
730 ret = tcon_get_status(screen_id, al_priv.tcon_type[screen_id]);
731
732 return ret;
733 }
734
disp_al_device_get_status(u32 screen_id)735 int disp_al_device_get_status(u32 screen_id)
736 {
737 int ret = 0;
738
739 ret = tcon_get_status(screen_id, al_priv.tcon_type[screen_id]);
740
741 return ret;
742 }
743
disp_al_device_src_select(u32 screen_id,u32 src)744 int disp_al_device_src_select(u32 screen_id, u32 src)
745 {
746 int ret = 0;
747
748 return ret;
749 }
750
disp_al_device_set_de_id(u32 screen_id,u32 de_id)751 int disp_al_device_set_de_id(u32 screen_id, u32 de_id)
752 {
753 al_priv.de_id[screen_id] = de_id;
754 return 0;
755 }
756
disp_al_device_set_de_use_rcq(u32 screen_id,u32 use_rcq)757 int disp_al_device_set_de_use_rcq(u32 screen_id, u32 use_rcq)
758 {
759 al_priv.de_use_rcq[screen_id] = use_rcq;
760 return 0;
761 }
762
disp_al_device_set_output_type(u32 screen_id,u32 output_type)763 int disp_al_device_set_output_type(u32 screen_id, u32 output_type)
764 {
765 al_priv.output_type[screen_id] = output_type;
766
767 al_priv.tcon_type[screen_id] = 0;
768
769 #if defined(SUPPORT_HDMI)
770 if (output_type == DISP_OUTPUT_TYPE_HDMI) {
771 al_priv.tcon_type[screen_id] = 1;
772 }
773 #endif
774
775 #if defined(SUPPORT_TV)
776 al_priv.tcon_type[screen_id] =
777 (output_type == DISP_OUTPUT_TYPE_TV) ?
778 1 : al_priv.tcon_type[screen_id];
779 #if defined(CONFIG_DISP2_TV_AC200)
780 al_priv.tcon_type[screen_id] =
781 (output_type == DISP_OUTPUT_TYPE_TV) ?
782 0 : al_priv.tcon_type[screen_id];
783 #endif /*endif CONFIG_DISP2_TV_AC200 */
784 #endif /* defined(SUPPORT_TV) */
785
786 return 0;
787 }
788
789
790
disp_al_init_tcon(struct disp_bsp_init_para * para)791 s32 disp_al_init_tcon(struct disp_bsp_init_para *para)
792 {
793 u32 i;
794
795 for (i = 0; i < DEVICE_NUM; i++) {
796 tcon_set_reg_base(i, para->reg_base[DISP_MOD_LCD0 + i]);
797 }
798 #if defined(HAVE_DEVICE_COMMON_MODULE)
799 tcon_top_set_reg_base(0, para->reg_base[DISP_MOD_DEVICE]);
800 #endif
801
802 return 0;
803 }
804
disp_al_show_builtin_patten(u32 hwdev_index,u32 patten)805 void disp_al_show_builtin_patten(u32 hwdev_index, u32 patten)
806 {
807 tcon_show_builtin_patten(hwdev_index, patten);
808 }
809