1 /*
2 * Allwinner SoCs display driver.
3 *
4 * Copyright (C) 2016 Allwinner.
5 *
6 * This file is licensed under the terms of the GNU General Public
7 * License version 2. This program is licensed "as is" without any
8 * warranty of any kind, whether express or implied.
9 */
10
11 #include "disp_al.h"
12 #include "de_hal.h"
13
14 #if defined(CONFIG_ARCH_SUN8IW12)
15 #define DISP2_TCON_TV_SYNC_POL_ISSUE
16 #endif /*endif CONFIG_ARCH_SUN8IW12P1 */
17
18 /*
19 * disp_al_private_data - abstract layer private data
20 * @output_type: current output type of specified device(eg. LCD/HDMI/TV)
21 * @output_mode: current output mode of specified device(eg. 720P,1080P)
22 * @output_cs: current output color space of specified device
23 * @tcon_id: the id of device connect to the specified de
24 * @de_id: the id of de connect to the specified tcon
25 * @disp_size: the output size of specified de
26 * @output_fps: the output fps of specified device
27 * @tcon_type: tcon type, 0: tcon0(drive panel), 1: tcon1(general drive HDMI/TV)
28 * @direct_show: indicate if enable direct show function(bypass all CSCs)
29 * @direct_show_toggle: indicate if direct show state change
30 */
31 struct disp_al_private_data {
32 u32 output_type[DEVICE_NUM];
33 u32 output_mode[DEVICE_NUM];
34 u32 output_cs[DEVICE_NUM];
35 u32 output_color_range[DEVICE_NUM];
36 u32 tcon_id[DE_NUM];
37 u32 de_id[DEVICE_NUM];
38 struct disp_rect disp_size[DE_NUM];
39 u32 output_fps[DEVICE_NUM];
40 u32 tcon_type[DEVICE_NUM];
41 u32 de_backcolor[DE_NUM];
42 bool direct_show[DE_NUM];
43 bool direct_show_toggle[DE_NUM];
44 };
45
46 static struct disp_al_private_data al_priv;
47
48 #ifdef SUPPORT_WB /*DE write back function, just for eink 32bpp to 8bpp*/
disp_al_set_rtmx_base(u32 disp,unsigned int base)49 int disp_al_set_rtmx_base(u32 disp, unsigned int base)
50 {
51 return rtmx_set_base(base);
52 }
53
disp_al_rtmx_init(u32 disp,unsigned int addr0,unsigned int addr1,unsigned int addr2,unsigned int w,unsigned int h,unsigned int outw,unsigned int outh,unsigned int fmt)54 int disp_al_rtmx_init(u32 disp, unsigned int addr0, unsigned int addr1,
55 unsigned int addr2, unsigned int w, unsigned int h,
56 unsigned int outw, unsigned int outh, unsigned int fmt)
57 {
58 rt_mixer_init(disp, addr0, addr1, addr2, w, h, outw, outh, fmt);
59 return 0;
60 }
61
disp_al_rtmx_set_addr(u32 disp,unsigned int addr0)62 int disp_al_rtmx_set_addr(u32 disp, unsigned int addr0)
63 {
64 rt_mixer_set_addr(disp, addr0);
65 return 0;
66 }
67
disp_al_set_eink_wb_base(u32 disp,unsigned int base)68 int disp_al_set_eink_wb_base(u32 disp, unsigned int base)
69 {
70 return wb_eink_set_reg_base(disp, base);
71 }
72
disp_al_set_eink_wb_param(u32 disp,unsigned int w,unsigned int h,unsigned int addr)73 int disp_al_set_eink_wb_param(u32 disp, unsigned int w,
74 unsigned int h, unsigned int addr)
75 {
76 __einkwb_config_t wbcfg;
77
78 wbcfg.width = w;
79 wbcfg.height = h;
80 wbcfg.addr[0] = addr;
81 wbcfg.addr[1] = 0;
82 wbcfg.addr[2] = 0;
83 wbcfg.csc_std = 2;
84 return wb_eink_set_para(0, &wbcfg);
85 }
86
disp_al_enable_eink_wb_interrupt(u32 disp)87 int disp_al_enable_eink_wb_interrupt(u32 disp)
88 {
89 return wb_eink_enableint(disp);
90 }
91
disp_al_disable_eink_wb_interrupt(u32 disp)92 int disp_al_disable_eink_wb_interrupt(u32 disp)
93 {
94
95 return wb_eink_disableint(disp);
96 }
97
disp_al_clear_eink_wb_interrupt(u32 disp)98 int disp_al_clear_eink_wb_interrupt(u32 disp)
99 {
100 return wb_eink_clearint(disp);
101 }
102
disp_al_enable_eink_wb(u32 disp)103 int disp_al_enable_eink_wb(u32 disp)
104 {
105 return wb_eink_writeback_enable(disp);
106 }
107
disp_al_disable_eink_wb(u32 disp)108 int disp_al_disable_eink_wb(u32 disp)
109 {
110 return wb_eink_close(disp);
111 }
112
disp_al_eink_wb_reset(u32 disp)113 int disp_al_eink_wb_reset(u32 disp)
114 {
115 return wb_eink_reset(disp);
116 }
117
disp_al_eink_wb_dereset(u32 disp)118 int disp_al_eink_wb_dereset(u32 disp)
119 {
120 return wb_eink_dereset(disp);
121 }
122
123
disp_al_get_eink_wb_status(u32 disp)124 int disp_al_get_eink_wb_status(u32 disp)
125 {
126 return wb_eink_get_status(disp);
127 }
128 #endif
129
130 #if defined(CONFIG_EINK_PANEL_USED)
disp_al_set_eink_base(u32 disp,unsigned long base)131 int disp_al_set_eink_base(u32 disp, unsigned long base)
132 {
133 return eink_set_base(base);
134 }
135
disp_al_eink_irq_enable(u32 disp)136 int disp_al_eink_irq_enable(u32 disp)
137 {
138 return eink_irq_enable();
139 }
140
disp_al_eink_irq_disable(u32 disp)141 int disp_al_eink_irq_disable(u32 disp)
142 {
143 return eink_irq_disable();
144 }
145
146 /*return: 0,decode int; 1:index_calc int; -1 error*/
disp_al_eink_irq_query(u32 disp)147 int disp_al_eink_irq_query(u32 disp)
148 {
149 /*clear interrupt*/
150 return eink_irq_query();
151 }
152
153
disp_al_eink_config(u32 disp,struct eink_init_param * param)154 int disp_al_eink_config(u32 disp, struct eink_init_param *param)
155 {
156
157 eink_config(param->eink_bits, param->eink_mode);
158 return 0;
159 }
160
161
disp_al_eink_disable(u32 disp)162 int disp_al_eink_disable(u32 disp)
163 {
164 return 0;
165
166 }
167
168
disp_al_eink_start_calculate_index(u32 disp,unsigned long old_index_data_paddr,unsigned long new_index_data_paddr,struct eink_8bpp_image * last_image,struct eink_8bpp_image * current_image)169 s32 disp_al_eink_start_calculate_index(u32 disp,
170 unsigned long old_index_data_paddr,
171 unsigned long new_index_data_paddr,
172 struct eink_8bpp_image *last_image,
173 struct eink_8bpp_image *current_image)
174 {
175 struct ee_img tcurrent_img, tlast_img;
176 struct area_info update_area;
177
178 unsigned char flash_mode, win_en;
179
180 tcurrent_img.addr = (unsigned long)current_image->paddr;/*image_addr*/
181 tcurrent_img.w = current_image->size.width;
182 tcurrent_img.h = current_image->size.height;
183 tcurrent_img.pitch = DISPALIGN(current_image->size.width,
184 current_image->size.align);
185
186 tlast_img.addr = (unsigned long)last_image->paddr;
187 tlast_img.w = last_image->size.width;
188 tlast_img.h = last_image->size.height;
189 tlast_img.pitch = DISPALIGN(last_image->size.width,
190 last_image->size.align);
191
192 flash_mode = current_image->flash_mode;
193 win_en = current_image->window_calc_enable;
194
195 memcpy((void *)&update_area, (void *)¤t_image->update_area,
196 sizeof(struct area_info));
197
198 eink_start_idx(&tlast_img, &tcurrent_img, flash_mode, win_en,
199 old_index_data_paddr,
200 new_index_data_paddr, &update_area);
201
202 return 0;
203 }
204
disp_al_is_calculate_index_finish(unsigned int disp)205 int disp_al_is_calculate_index_finish(unsigned int disp)
206 {
207 #if 1
208 return eink_index_finish();
209 #else
210 int ret = eink_irq_query();
211
212 return ((ret == 1)?1:0);
213 #endif
214 }
215
disp_al_get_update_area(unsigned int disp,struct area_info * area)216 int disp_al_get_update_area(unsigned int disp, struct area_info *area)
217 {
218 return eink_get_updata_area(area);
219 }
220
221
disp_al_eink_pipe_enable(u32 disp,unsigned int pipe_no)222 int disp_al_eink_pipe_enable(u32 disp, unsigned int pipe_no)
223 {
224 return eink_pipe_enable(pipe_no);
225 }
226
disp_al_eink_pipe_disable(u32 disp,unsigned int pipe_no)227 int disp_al_eink_pipe_disable(u32 disp, unsigned int pipe_no)
228 {
229
230 return eink_pipe_disable(pipe_no);
231 }
232
disp_al_eink_pipe_config(u32 disp,unsigned int pipe_no,struct area_info area)233 int disp_al_eink_pipe_config(u32 disp, unsigned int pipe_no,
234 struct area_info area)
235 {
236 return eink_pipe_config(&area, pipe_no);
237
238 }
239
disp_al_eink_pipe_config_wavefile(u32 disp,unsigned int wav_file_addr,unsigned int pipe_no)240 int disp_al_eink_pipe_config_wavefile(u32 disp, unsigned int wav_file_addr,
241 unsigned int pipe_no)
242 {
243
244 return eink_pipe_config_wavefile(wav_file_addr, pipe_no);
245 }
246
disp_al_eink_start_decode(unsigned int disp,unsigned long new_idx_addr,unsigned long wav_data_addr,struct eink_init_param * param)247 int disp_al_eink_start_decode(unsigned int disp, unsigned long new_idx_addr,
248 unsigned long wav_data_addr,
249 struct eink_init_param *param)
250 {
251 return eink_decoder_start(new_idx_addr, wav_data_addr, param);
252 }
253
disp_al_edma_init(unsigned int disp,struct eink_init_param * param)254 int disp_al_edma_init(unsigned int disp, struct eink_init_param *param)
255 {
256
257 return eink_edma_init(param->eink_mode);
258 }
259
disp_al_eink_edma_cfg_addr(unsigned int disp,unsigned long wav_addr)260 int disp_al_eink_edma_cfg_addr(unsigned int disp, unsigned long wav_addr)
261 {
262 return eink_edma_cfg_addr(wav_addr);
263 }
264
265
disp_al_edma_config(unsigned int disp,unsigned long wave_data_addr,struct eink_init_param * param)266 int disp_al_edma_config(unsigned int disp, unsigned long wave_data_addr,
267 struct eink_init_param *param)
268 {
269
270 return eink_edma_cfg(wave_data_addr, param);
271 }
272
disp_al_edma_write(unsigned int disp,unsigned char en)273 int disp_al_edma_write(unsigned int disp, unsigned char en)
274 {
275
276 return eink_edma_en(en);
277 }
278
disp_al_dbuf_rdy(void)279 int disp_al_dbuf_rdy(void)
280 {
281 return eink_dbuf_rdy();
282 }
283
disp_al_eink_set_wb(unsigned char wb_en,unsigned int wb_addr)284 int disp_al_eink_set_wb(unsigned char wb_en, unsigned int wb_addr)
285 {
286 /* edma write back */
287 return eink_set_wb(wb_en, wb_addr);
288 }
289
disp_al_init_waveform(const char * path)290 int disp_al_init_waveform(const char *path)
291 {
292 return init_waveform(path);
293 }
294
disp_al_free_waveform(void)295 void disp_al_free_waveform(void)
296 {
297 free_waveform();
298 }
299
300
disp_al_get_waveform_data(unsigned int disp,enum eink_update_mode mode,unsigned int temp,unsigned int * total_frames,unsigned int * wf_buf)301 int disp_al_get_waveform_data(unsigned int disp, enum eink_update_mode mode,
302 unsigned int temp, unsigned int *total_frames,
303 unsigned int *wf_buf)
304 {
305 return get_waveform_data(mode, temp, total_frames, wf_buf);
306 }
307
disp_al_get_eink_panel_bit_num(unsigned int disp,enum eink_bit_num * bit_num)308 int disp_al_get_eink_panel_bit_num(unsigned int disp,
309 enum eink_bit_num *bit_num)
310 {
311 return get_eink_panel_bit_num(bit_num);
312 }
313
disp_al_init_eink_ctrl_data_8(unsigned int disp,unsigned long wavedata_buf,struct eink_timing_param * eink_timing_info,unsigned int i)314 int disp_al_init_eink_ctrl_data_8(unsigned int disp, unsigned long wavedata_buf,
315 struct eink_timing_param *eink_timing_info,
316 unsigned int i)
317 {
318 return init_eink_ctrl_data_8(wavedata_buf, eink_timing_info, i);
319
320 }
321
disp_al_init_eink_ctrl_data_16(unsigned int disp,unsigned int wavedata_buf,struct eink_timing_param * eink_timing_info)322 int disp_al_init_eink_ctrl_data_16(unsigned int disp, unsigned int wavedata_buf,
323 struct eink_timing_param *eink_timing_info)
324 {
325 return init_eink_ctrl_data_16(wavedata_buf, eink_timing_info);
326
327 }
328 #endif
329
disp_al_validate_direct_show(unsigned int disp,struct disp_layer_config_data * data,unsigned int layer_num)330 static int disp_al_validate_direct_show(unsigned int disp,
331 struct disp_layer_config_data *data,
332 unsigned int layer_num)
333 {
334 int tcon_id = al_priv.tcon_id[disp];
335 bool direct_show = true;
336 unsigned char i, vi_chn;
337
338 /*
339 * We need to check several conditions:
340 * 1, the output must be TV(PAL/NTSC) type
341 * 2, the output must be in yuv color space,
342 * 3, only video channels are used,
343 * 4, input format must be yuv format.
344 * 5, input layer size must be in the p2p limit range
345 * 6, the layer must be display on the fullscreen or non-scalely
346 */
347 if (al_priv.output_type[tcon_id] != DISP_OUTPUT_TYPE_TV) {
348 direct_show = false;
349 goto exit;
350 }
351
352 if ((al_priv.disp_size[disp].width != CVBS_PAL_WIDTH)
353 && (al_priv.disp_size[disp].width != CVBS_NTSC_WIDTH)) {
354 direct_show = false;
355 goto exit;
356 }
357
358 if ((al_priv.disp_size[disp].height != CVBS_PAL_HEIGHT)
359 && (al_priv.disp_size[disp].height != CVBS_NTSC_HEIGHT)) {
360 direct_show = false;
361 goto exit;
362 }
363
364 if (al_priv.output_cs[tcon_id] != 1) {
365 direct_show = false;
366 goto exit;
367 }
368
369 vi_chn = de_feat_get_num_vi_chns(disp);
370 for (i = 0; i < layer_num; i++, data++) {
371 struct disp_rect64 *crop64;
372 struct disp_rect crop;
373 struct disp_rect *screen_win;
374
375 if (!data->config.enable)
376 continue;
377
378 if (data->config.channel >= vi_chn) {
379 direct_show = false;
380 goto exit;
381 }
382
383 if (data->config.info.fb.format < DISP_FORMAT_YUV444_I_AYUV) {
384 direct_show = false;
385 goto exit;
386 }
387
388 crop64 = &data->config.info.fb.crop;
389 crop.x = crop64->x >> VSU_FB_FRAC_BITWIDTH;
390 crop.y = crop64->y >> VSU_FB_FRAC_BITWIDTH;
391 crop.width = crop64->width >> VSU_FB_FRAC_BITWIDTH;
392 crop.height = crop64->height >> VSU_FB_FRAC_BITWIDTH;
393 if ((crop.width < P2P_FB_MIN_WIDTH)
394 || (crop.width > P2P_FB_MAX_WIDTH)) {
395 direct_show = false;
396 goto exit;
397 }
398
399 if (crop.height != al_priv.disp_size[disp].height) {
400 direct_show = false;
401 goto exit;
402 }
403
404 screen_win = &data->config.info.screen_win;
405 if ((screen_win->width != al_priv.disp_size[disp].width)
406 && (screen_win->width != crop.width)) {
407 direct_show = false;
408 goto exit;
409 }
410
411 if ((screen_win->height != al_priv.disp_size[disp].height)
412 && (screen_win->height != crop.height)) {
413 direct_show = false;
414 goto exit;
415 }
416 }
417
418 exit:
419 if (al_priv.direct_show[disp] != direct_show)
420 al_priv.direct_show_toggle[disp] = true;
421 else
422 al_priv.direct_show_toggle[disp] = false;
423 al_priv.direct_show[disp] = direct_show;
424
425 return 0;
426 }
427
disp_al_get_direct_show_state(unsigned int disp)428 bool disp_al_get_direct_show_state(unsigned int disp)
429 {
430 return al_priv.direct_show[disp];
431 }
432
disp_al_layer_apply(unsigned int disp,struct disp_layer_config_data * data,unsigned int layer_num)433 int disp_al_layer_apply(unsigned int disp, struct disp_layer_config_data *data,
434 unsigned int layer_num)
435 {
436 bool direct_show;
437
438 disp_al_validate_direct_show(disp, data, layer_num);
439 direct_show = al_priv.direct_show[disp];
440
441 /*
442 * If direct_show_toggle, we need to update the output cs of de .
443 * When direct_show enable, we need to disable csc function,
444 * And when direct show disable, we need to enable csc function as usual
445 */
446 if (al_priv.direct_show_toggle[disp]) {
447 struct disp_csc_config csc_cfg;
448
449 memset(&csc_cfg, 0, sizeof(struct disp_csc_config));
450 if (direct_show) {
451 csc_cfg.out_fmt = DE_RGB;
452 csc_cfg.out_color_range = DISP_COLOR_RANGE_0_255;
453 csc_cfg.color = (16 << 16) | (128 << 8) | (128);
454 } else {
455 int tcon_id = al_priv.tcon_id[disp];
456
457 csc_cfg.out_fmt = al_priv.output_cs[tcon_id];
458 if ((al_priv.disp_size[disp].width < 1280)
459 && (al_priv.disp_size[disp].height < 720))
460 csc_cfg.out_mode = DE_BT601;
461 else
462 csc_cfg.out_mode = DE_BT709;
463 csc_cfg.out_color_range =
464 al_priv.output_color_range[tcon_id];
465 csc_cfg.color = al_priv.de_backcolor[disp];
466 }
467 de_al_mgr_apply_color(disp, &csc_cfg);
468 }
469 return de_al_lyr_apply(disp, data, layer_num, direct_show);
470 }
471 EXPORT_SYMBOL(disp_al_layer_apply);
472
disp_al_manager_init(unsigned int disp)473 int disp_al_manager_init(unsigned int disp)
474 {
475 return de_clk_enable(DE_CLK_CORE0 + disp);
476 }
477
disp_al_manager_exit(unsigned int disp)478 int disp_al_manager_exit(unsigned int disp)
479 {
480 return de_clk_disable(DE_CLK_CORE0 + disp);
481 }
482
disp_al_de_clk_enable(unsigned int disp)483 int disp_al_de_clk_enable(unsigned int disp)
484 {
485 return de_clk_enable(DE_CLK_CORE0 + disp);
486 }
487
disp_al_de_clk_disable(unsigned int disp)488 int disp_al_de_clk_disable(unsigned int disp)
489 {
490 return de_clk_disable(DE_CLK_CORE0 + disp);
491 }
disp_al_manager_apply(unsigned int disp,struct disp_manager_data * data)492 int disp_al_manager_apply(unsigned int disp, struct disp_manager_data *data)
493 {
494 if (data->flag & MANAGER_ENABLE_DIRTY) {
495 struct disp_color *back_color = &data->config.back_color;
496
497 al_priv.disp_size[disp].width = data->config.size.width;
498 al_priv.disp_size[disp].height = data->config.size.height;
499 al_priv.tcon_id[disp] = data->config.hwdev_index;
500 al_priv.de_id[al_priv.tcon_id[disp]] = disp;
501 al_priv.output_cs[al_priv.tcon_id[disp]] = data->config.cs;
502 al_priv.output_color_range[al_priv.tcon_id[disp]] =
503 data->config.color_range;
504 al_priv.de_backcolor[disp] =
505 (back_color->alpha << 24) | (back_color->red << 16)
506 | (back_color->green << 8) | (back_color->blue << 0);
507 }
508
509
510 printk("%s ouput_type:%d\n", __func__, al_priv.output_type[al_priv.tcon_id[disp]]);
511 if (al_priv.output_type[al_priv.tcon_id[disp]] ==
512 (u32) DISP_OUTPUT_TYPE_HDMI) {
513
514 #ifdef BYPASS_TCON_CEU
515 tcon1_hdmi_color_remap(al_priv.tcon_id[disp], 0,
516 data->config.cs);
517
518 #else
519 /*
520 * If yuv output(cs != 0), remap yuv plane to (v y u) sequency
521 * else disable color remap function
522 */
523 if (data->config.cs != 0)
524 tcon1_hdmi_color_remap(al_priv.tcon_id[disp], 1,
525 data->config.cs);
526 else
527 tcon1_hdmi_color_remap(al_priv.tcon_id[disp], 0,
528 data->config.cs);
529 #endif
530 }
531 de_update_clk_rate(data->config.de_freq);
532
533 return de_al_mgr_apply(disp, data);
534 }
535 EXPORT_SYMBOL(disp_al_manager_apply);
536
disp_al_manager_sync(unsigned int disp)537 int disp_al_manager_sync(unsigned int disp)
538 {
539 return de_al_mgr_sync(disp);
540 }
541 EXPORT_SYMBOL(disp_al_manager_sync);
542
disp_al_manager_update_regs(unsigned int disp)543 int disp_al_manager_update_regs(unsigned int disp)
544 {
545 return de_al_mgr_update_regs(disp);
546 }
547 EXPORT_SYMBOL(disp_al_manager_update_regs);
548
disp_al_manager_query_irq(unsigned int disp)549 int disp_al_manager_query_irq(unsigned int disp)
550 {
551 return de_al_query_irq(disp);
552 }
553
disp_al_manager_enable_irq(unsigned int disp)554 int disp_al_manager_enable_irq(unsigned int disp)
555 {
556 return de_al_enable_irq(disp, 1);
557 }
558
disp_al_manager_disable_irq(unsigned int disp)559 int disp_al_manager_disable_irq(unsigned int disp)
560 {
561 return de_al_enable_irq(disp, 0);
562 }
563
disp_al_enhance_apply(unsigned int disp,struct disp_enhance_config * config)564 int disp_al_enhance_apply(unsigned int disp, struct disp_enhance_config *config)
565 {
566 if (config->flags & ENH_MODE_DIRTY) {
567 struct disp_csc_config csc_config;
568
569 de_dcsc_get_config(disp, &csc_config);
570 csc_config.enhance_mode = (config->info.mode >> 16);
571 de_dcsc_apply(disp, &csc_config);
572 }
573
574 return de_enhance_apply(disp, config);
575 }
576
disp_al_enhance_update_regs(unsigned int disp)577 int disp_al_enhance_update_regs(unsigned int disp)
578 {
579 return de_enhance_update_regs(disp);
580 }
581
disp_al_enhance_sync(unsigned int disp)582 int disp_al_enhance_sync(unsigned int disp)
583 {
584 return de_enhance_sync(disp);
585 }
586
disp_al_enhance_tasklet(unsigned int disp)587 int disp_al_enhance_tasklet(unsigned int disp)
588 {
589 return de_enhance_tasklet(disp);
590 }
591
592 #if !IS_ENABLED(CONFIG_EINK200_SUNXI)
disp_al_capture_init(unsigned int disp)593 int disp_al_capture_init(unsigned int disp)
594 {
595 int ret = -1;
596
597 ret = de_clk_enable(DE_CLK_WB);
598 ret = wb_input_select(disp);
599 return ret;
600 }
601
disp_al_capture_exit(unsigned int disp)602 int disp_al_capture_exit(unsigned int disp)
603 {
604 return de_clk_disable(DE_CLK_WB);
605 }
606
disp_al_capture_sync(u32 disp)607 int disp_al_capture_sync(u32 disp)
608 {
609 wb_ebios_update_regs(disp);
610 wb_ebios_enableint(disp);
611 wb_ebios_writeback_enable(disp, 1);
612
613 return 0;
614 }
615
disp_al_capture_apply(unsigned int disp,struct disp_capture_config * cfg)616 int disp_al_capture_apply(unsigned int disp, struct disp_capture_config *cfg)
617 {
618 return wb_ebios_apply(disp, cfg);
619 }
620
disp_al_capture_get_status(unsigned int disp)621 int disp_al_capture_get_status(unsigned int disp)
622 {
623 return wb_ebios_get_status(disp);
624 }
625
disp_al_write_back_clk_init(unsigned int disp)626 int disp_al_write_back_clk_init(unsigned int disp)
627 {
628 return de_clk_enable(DE_CLK_WB);
629 }
630
disp_al_write_back_clk_exit(unsigned int disp)631 int disp_al_write_back_clk_exit(unsigned int disp)
632 {
633 return de_clk_disable(DE_CLK_WB);
634 }
635 #else
disp_al_capture_init(unsigned int disp)636 int disp_al_capture_init(unsigned int disp)
637 {
638 return 0;
639 }
640
disp_al_capture_exit(unsigned int disp)641 int disp_al_capture_exit(unsigned int disp)
642 {
643 return 0;
644 }
645
disp_al_capture_sync(u32 disp)646 int disp_al_capture_sync(u32 disp)
647 {
648 return 0;
649 }
650
disp_al_capture_apply(unsigned int disp,struct disp_capture_config * cfg)651 int disp_al_capture_apply(unsigned int disp, struct disp_capture_config *cfg)
652 {
653 return 0;
654 }
655
disp_al_capture_get_status(unsigned int disp)656 int disp_al_capture_get_status(unsigned int disp)
657 {
658 return 0;
659 }
660
disp_al_write_back_clk_init(unsigned int disp)661 int disp_al_write_back_clk_init(unsigned int disp)
662 {
663 return 0;
664 }
665
disp_al_write_back_clk_exit(unsigned int disp)666 int disp_al_write_back_clk_exit(unsigned int disp)
667 {
668 return 0;
669 }
670 #endif
671
disp_al_smbl_apply(unsigned int disp,struct disp_smbl_info * info)672 int disp_al_smbl_apply(unsigned int disp, struct disp_smbl_info *info)
673 {
674 return de_smbl_apply(disp, info);
675 }
676
disp_al_smbl_update_regs(unsigned int disp)677 int disp_al_smbl_update_regs(unsigned int disp)
678 {
679 return de_smbl_update_regs(disp);
680 }
681
disp_al_smbl_sync(unsigned int disp)682 int disp_al_smbl_sync(unsigned int disp)
683 {
684 return 0;
685 }
686
disp_al_smbl_tasklet(unsigned int disp)687 int disp_al_smbl_tasklet(unsigned int disp)
688 {
689 return de_smbl_tasklet(disp);
690 }
691
disp_al_smbl_get_status(unsigned int disp)692 int disp_al_smbl_get_status(unsigned int disp)
693 {
694 return de_smbl_get_status(disp);
695 }
696
697 #ifdef CONFIG_FPGA_V4_PLATFORM
698 static struct lcd_clk_info clk_tbl[] = {
699 {LCD_IF_HV, 0x12, 1, 1, 0},
700 {LCD_IF_CPU, 12, 1, 1, 0},
701 {LCD_IF_LVDS, 7, 1, 1, 0},
702 {LCD_IF_DSI, 4, 1, 4, 0},
703 };
704 #else
705 static struct lcd_clk_info clk_tbl[] = {
706 {LCD_IF_HV, 6, 1, 1, 0},
707 {LCD_IF_CPU, 12, 1, 1, 0},
708 {LCD_IF_LVDS, 7, 1, 1, 0},
709 #if defined(DSI_VERSION_40)
710 {LCD_IF_DSI, 4, 1, 4, 150000000},
711 #else
712 {LCD_IF_DSI, 4, 1, 4, 0},
713 #endif /*endif DSI_VERSION_40*/
714 {LCD_IF_VDPO, 4, 1, 1, 0},
715 };
716 #endif
717 /* lcd */
718 /* lcd_dclk_freq * div -> lcd_clk_freq * div2 -> pll_freq */
719 /* 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)720 int disp_al_lcd_get_clk_info(u32 screen_id, struct lcd_clk_info *info,
721 struct disp_panel_para *panel)
722 {
723 int tcon_div = 6;
724 int lcd_div = 1;
725 int dsi_div = 4;
726 int dsi_rate = 0;
727 int i;
728 int find = 0;
729
730 if (panel == NULL) {
731 __wrn("panel is NULL\n");
732 return 0;
733 }
734
735 for (i = 0; i < sizeof(clk_tbl) / sizeof(struct lcd_clk_info); i++) {
736 if (clk_tbl[i].lcd_if == panel->lcd_if) {
737 tcon_div = clk_tbl[i].tcon_div;
738 lcd_div = clk_tbl[i].lcd_div;
739 dsi_div = clk_tbl[i].dsi_div;
740 dsi_rate = clk_tbl[i].dsi_rate;
741 find = 1;
742 break;
743 }
744 }
745
746 #if defined(DSI_VERSION_40)
747 if (panel->lcd_if == LCD_IF_DSI) {
748 u32 lane = panel->lcd_dsi_lane;
749 u32 bitwidth = 0;
750
751 switch (panel->lcd_dsi_format) {
752 case LCD_DSI_FORMAT_RGB888:
753 bitwidth = 24;
754 break;
755 case LCD_DSI_FORMAT_RGB666:
756 bitwidth = 24;
757 break;
758 case LCD_DSI_FORMAT_RGB565:
759 bitwidth = 16;
760 break;
761 case LCD_DSI_FORMAT_RGB666P:
762 bitwidth = 18;
763 break;
764 }
765
766 dsi_div = bitwidth / lane;
767 #if defined(SUNXI_DSI_PASSIVE_BUG)
768 dsi_div = 6;
769 #endif
770 if (panel->lcd_dsi_if == LCD_DSI_IF_COMMAND_MODE) {
771 tcon_div = dsi_div;
772 }
773 }
774 #endif
775
776 if (find == 0)
777 __wrn("cant find clk info for lcd_if %d\n", panel->lcd_if);
778
779 #if defined(CONFIG_FPGA_V4_PLATFORM) && defined(CONFIG_EINK_PANEL_USED)
780 if (panel->lcd_dclk_freq < 10) {
781 tcon_div = 30;
782 lcd_div = 1;
783 } else if (panel->lcd_dclk_freq < 40 && panel->lcd_dclk_freq >= 10) {
784 tcon_div = 10;
785 lcd_div = 1;
786 } else {
787 tcon_div = 6;
788 lcd_div = 1;
789 }
790 #endif
791 if (panel->lcd_if == LCD_IF_HV &&
792 panel->lcd_hv_if == LCD_HV_IF_CCIR656_2CYC &&
793 panel->ccir_clk_div > 0)
794 tcon_div = panel->ccir_clk_div;
795 else if (panel->lcd_tcon_mode == DISP_TCON_DUAL_DSI &&
796 panel->lcd_if == LCD_IF_DSI) {
797 tcon_div = tcon_div / 2;
798 dsi_div /= 2;
799 }
800
801 #if defined(DSI_VERSION_28)
802 if (panel->lcd_if == LCD_IF_DSI &&
803 panel->lcd_dsi_if == LCD_DSI_IF_COMMAND_MODE) {
804 tcon_div = 6;
805 dsi_div = 6;
806 }
807 #endif
808
809 info->tcon_div = tcon_div;
810 info->lcd_div = lcd_div;
811 info->dsi_div = dsi_div;
812 info->dsi_rate = dsi_rate;
813
814 return 0;
815 }
816
disp_al_lcd_cfg(u32 screen_id,struct disp_panel_para * panel,struct panel_extend_para * extend_panel)817 int disp_al_lcd_cfg(u32 screen_id, struct disp_panel_para *panel,
818 struct panel_extend_para *extend_panel)
819 {
820 struct lcd_clk_info info;
821
822 al_priv.output_type[screen_id] = (u32) DISP_OUTPUT_TYPE_LCD;
823 al_priv.output_mode[screen_id] = (u32) panel->lcd_if;
824 al_priv.output_fps[screen_id] =
825 panel->lcd_dclk_freq * 1000000 / panel->lcd_ht / panel->lcd_vt;
826
827 #if defined(CONFIG_EINK_PANEL_USED)
828 if (al_priv.output_fps[screen_id] > 30)
829 al_priv.output_fps[screen_id] = 30;
830 #endif
831
832 de_update_device_fps(al_priv.de_id[screen_id],
833 al_priv.output_fps[screen_id]);
834
835 tcon_init(screen_id);
836 disp_al_lcd_get_clk_info(screen_id, &info, panel);
837 tcon0_set_dclk_div(screen_id, info.tcon_div);
838
839 #if !defined(TCON1_DRIVE_PANEL)
840 al_priv.tcon_type[screen_id] = 0;
841 if (tcon0_cfg(screen_id, panel) != 0)
842 DE_WRN("lcd cfg fail!\n");
843 else
844 DE_INF("lcd cfg ok!\n");
845
846 tcon0_cfg_ext(screen_id, extend_panel);
847 tcon0_src_select(screen_id, LCD_SRC_DE, al_priv.de_id[screen_id]);
848
849 if (panel->lcd_if == LCD_IF_DSI) {
850 #if defined(SUPPORT_DSI)
851 if (panel->lcd_if == LCD_IF_DSI) {
852 if (dsi_cfg(screen_id, panel) != 0)
853 DE_WRN("dsi %d cfg fail!\n", screen_id);
854 if (panel->lcd_tcon_mode == DISP_TCON_DUAL_DSI &&
855 screen_id + 1 < DEVICE_DSI_NUM) {
856 if (dsi_cfg(screen_id + 1, panel) != 0)
857 DE_WRN("dsi %d cfg fail!\n",
858 screen_id + 1);
859 }
860 }
861 #endif
862 }
863 #else
864
865 /* There is no tcon0 on this platform,
866 * At fpga period, we can use tcon1 to driver lcd pnael,
867 * so, here we need to config tcon1 here.
868 */
869 al_priv.tcon_type[screen_id] = 1;
870 if (tcon1_cfg_ex(screen_id, panel) != 0)
871 DE_WRN("lcd cfg fail!\n");
872 else
873 DE_INF("lcd cfg ok!\n");
874 #endif
875 return 0;
876 }
877
disp_al_lcd_cfg_ext(u32 screen_id,struct panel_extend_para * extend_panel)878 int disp_al_lcd_cfg_ext(u32 screen_id, struct panel_extend_para *extend_panel)
879 {
880 tcon0_cfg_ext(screen_id, extend_panel);
881
882 return 0;
883 }
884
disp_al_lcd_enable(u32 screen_id,struct disp_panel_para * panel)885 int disp_al_lcd_enable(u32 screen_id, struct disp_panel_para *panel)
886 {
887 #if !defined(TCON1_DRIVE_PANEL)
888
889 tcon0_open(screen_id, panel);
890 if (panel->lcd_if == LCD_IF_LVDS) {
891 lvds_open(screen_id, panel);
892 } else if (panel->lcd_if == LCD_IF_DSI) {
893 #if defined(SUPPORT_DSI)
894 dsi_open(screen_id, panel);
895 if (panel->lcd_tcon_mode == DISP_TCON_DUAL_DSI &&
896 screen_id + 1 < DEVICE_DSI_NUM)
897 dsi_open(screen_id + 1, panel);
898 #endif
899 }
900
901 #else
902 /* There is no tcon0 on this platform,
903 * At fpga period, we can use tcon1 to driver lcd pnael,
904 * so, here we need to open tcon1 here.
905 */
906 tcon1_open(screen_id);
907 #endif
908
909 return 0;
910 }
911
disp_al_lcd_disable(u32 screen_id,struct disp_panel_para * panel)912 int disp_al_lcd_disable(u32 screen_id, struct disp_panel_para *panel)
913 {
914 al_priv.output_type[screen_id] = (u32) DISP_OUTPUT_TYPE_NONE;
915
916 #if !defined(TCON1_DRIVE_PANEL)
917
918 if (panel->lcd_if == LCD_IF_LVDS) {
919 lvds_close(screen_id);
920 } else if (panel->lcd_if == LCD_IF_DSI) {
921 #if defined(SUPPORT_DSI)
922 dsi_close(screen_id);
923 if (panel->lcd_tcon_mode == DISP_TCON_DUAL_DSI &&
924 screen_id + 1 < DEVICE_DSI_NUM)
925 dsi_close(screen_id + 1);
926
927 #endif
928 }
929 tcon0_close(screen_id);
930 #else
931 /* There is no tcon0 on platform sun50iw2,
932 * on fpga period, we can use tcon1 to driver lcd pnael,
933 * so, here we need to close tcon1.
934 */
935 tcon1_close(screen_id);
936 #endif
937 tcon_exit(screen_id);
938
939 return 0;
940 }
941
942 /* query lcd irq, clear it when the irq queried exist
943 */
disp_al_lcd_query_irq(u32 screen_id,enum __lcd_irq_id_t irq_id,struct disp_panel_para * panel)944 int disp_al_lcd_query_irq(u32 screen_id, enum __lcd_irq_id_t irq_id,
945 struct disp_panel_para *panel)
946 {
947 int ret = 0;
948
949 #if defined(SUPPORT_DSI) && defined(DSI_VERSION_40)
950 if (panel->lcd_if == LCD_IF_DSI &&
951 panel->lcd_dsi_if != LCD_DSI_IF_COMMAND_MODE) {
952 enum __dsi_irq_id_t dsi_irq =
953 (irq_id == LCD_IRQ_TCON0_VBLK) ?
954 DSI_IRQ_VIDEO_VBLK : DSI_IRQ_VIDEO_LINE;
955
956 ret = dsi_irq_query(screen_id, dsi_irq);
957 } else
958 #endif
959 ret = tcon_irq_query(screen_id,
960 (al_priv.tcon_type[screen_id] == 0) ?
961 irq_id : LCD_IRQ_TCON1_VBLK);
962
963 return ret;
964 }
965
disp_al_lcd_enable_irq(u32 screen_id,enum __lcd_irq_id_t irq_id,struct disp_panel_para * panel)966 int disp_al_lcd_enable_irq(u32 screen_id, enum __lcd_irq_id_t irq_id,
967 struct disp_panel_para *panel)
968 {
969 int ret = 0;
970
971 #if defined(SUPPORT_DSI) && defined(DSI_VERSION_40)
972 if (panel->lcd_if == LCD_IF_DSI) {
973 enum __dsi_irq_id_t dsi_irq =
974 (irq_id == LCD_IRQ_TCON0_VBLK) ?
975 DSI_IRQ_VIDEO_VBLK : DSI_IRQ_VIDEO_LINE;
976
977 ret = dsi_irq_enable(screen_id, dsi_irq);
978 } else
979 #endif
980 ret =
981 tcon_irq_enable(screen_id,
982 (al_priv.tcon_type[screen_id] ==
983 0) ? irq_id : LCD_IRQ_TCON1_VBLK);
984
985 return ret;
986 }
987
disp_al_lcd_disable_irq(u32 screen_id,enum __lcd_irq_id_t irq_id,struct disp_panel_para * panel)988 int disp_al_lcd_disable_irq(u32 screen_id, enum __lcd_irq_id_t irq_id,
989 struct disp_panel_para *panel)
990 {
991 int ret = 0;
992
993 #if defined(SUPPORT_DSI) && defined(DSI_VERSION_40)
994 if (panel->lcd_if == LCD_IF_DSI) {
995 enum __dsi_irq_id_t dsi_irq =
996 (irq_id == LCD_IRQ_TCON0_VBLK) ?
997 DSI_IRQ_VIDEO_VBLK : DSI_IRQ_VIDEO_LINE;
998
999 ret = dsi_irq_disable(screen_id, dsi_irq);
1000 } else
1001 #endif
1002 ret =
1003 tcon_irq_disable(screen_id,
1004 (al_priv.tcon_type[screen_id] ==
1005 0) ? irq_id : LCD_IRQ_TCON1_VBLK);
1006
1007 return ret;
1008 }
1009
disp_al_lcd_tri_busy(u32 screen_id,struct disp_panel_para * panel)1010 int disp_al_lcd_tri_busy(u32 screen_id, struct disp_panel_para *panel)
1011 {
1012 int busy = 0;
1013 int ret = 0;
1014
1015 busy |= tcon0_tri_busy(screen_id);
1016 #if defined(SUPPORT_DSI)
1017 if (panel->lcd_if == LCD_IF_DSI)
1018 busy |= dsi_inst_busy(screen_id);
1019 #endif
1020 ret = (busy == 0) ? 0 : 1;
1021
1022 return ret;
1023 }
1024
1025 /* take dsi irq s32o account, todo? */
disp_al_lcd_tri_start(u32 screen_id,struct disp_panel_para * panel)1026 int disp_al_lcd_tri_start(u32 screen_id, struct disp_panel_para *panel)
1027 {
1028 #if defined(SUPPORT_DSI) && defined(DSI_VERSION_40)
1029 if (panel->lcd_if == LCD_IF_DSI)
1030 dsi_tri_start(screen_id);
1031 #endif
1032 return tcon0_tri_start(screen_id);
1033 }
1034
disp_al_lcd_io_cfg(u32 screen_id,u32 enable,struct disp_panel_para * panel)1035 int disp_al_lcd_io_cfg(u32 screen_id, u32 enable, struct disp_panel_para *panel)
1036 {
1037 #if defined(SUPPORT_DSI)
1038 if (panel->lcd_if == LCD_IF_DSI) {
1039 if (enable == 1) {
1040 dsi_io_open(screen_id, panel);
1041 if (panel->lcd_tcon_mode == DISP_TCON_DUAL_DSI &&
1042 screen_id + 1 < DEVICE_DSI_NUM)
1043 dsi_io_open(screen_id + 1, panel);
1044 } else {
1045 dsi_io_close(screen_id);
1046 if (panel->lcd_tcon_mode == DISP_TCON_DUAL_DSI &&
1047 screen_id + 1 < DEVICE_DSI_NUM)
1048 dsi_io_close(screen_id + 1);
1049 }
1050 }
1051 #endif
1052
1053 return 0;
1054 }
1055
disp_al_lcd_get_cur_line(u32 screen_id,struct disp_panel_para * panel)1056 int disp_al_lcd_get_cur_line(u32 screen_id, struct disp_panel_para *panel)
1057 {
1058 #if defined(SUPPORT_DSI) && defined(DSI_VERSION_40)
1059 if (panel->lcd_if == LCD_IF_DSI)
1060 return dsi_get_cur_line(screen_id);
1061 #endif
1062
1063 return tcon_get_cur_line(screen_id,
1064 al_priv.tcon_type[screen_id]);
1065 }
1066
disp_al_lcd_get_start_delay(u32 screen_id,struct disp_panel_para * panel)1067 int disp_al_lcd_get_start_delay(u32 screen_id, struct disp_panel_para *panel)
1068 {
1069 #if defined(SUPPORT_DSI) && defined(DSI_VERSION_40)
1070 u32 lcd_start_delay = 0;
1071 u32 de_clk_rate = de_get_clk_rate() / 1000000;
1072
1073 if (panel && panel->lcd_if == LCD_IF_DSI) {
1074 lcd_start_delay =
1075 ((tcon0_get_cpu_tri2_start_delay(screen_id) + 1) << 3) *
1076 (panel->lcd_dclk_freq) / (panel->lcd_ht * de_clk_rate);
1077 return lcd_start_delay;
1078 } else
1079 #endif
1080 return tcon_get_start_delay(screen_id,
1081 al_priv.tcon_type[screen_id]);
1082 }
1083
1084 /* hdmi */
disp_al_hdmi_enable(u32 screen_id)1085 int disp_al_hdmi_enable(u32 screen_id)
1086 {
1087 tcon1_hdmi_clk_enable(screen_id, 1);
1088
1089 tcon1_open(screen_id);
1090 return 0;
1091 }
1092
disp_al_hdmi_disable(u32 screen_id)1093 int disp_al_hdmi_disable(u32 screen_id)
1094 {
1095 al_priv.output_type[screen_id] = (u32) DISP_OUTPUT_TYPE_NONE;
1096
1097 tcon1_close(screen_id);
1098 tcon_exit(screen_id);
1099 tcon1_hdmi_clk_enable(screen_id, 0);
1100
1101 return 0;
1102 }
1103
disp_al_hdmi_cfg(u32 screen_id,struct disp_video_timings * video_info)1104 int disp_al_hdmi_cfg(u32 screen_id, struct disp_video_timings *video_info)
1105 {
1106 al_priv.output_type[screen_id] = (u32) DISP_OUTPUT_TYPE_HDMI;
1107 al_priv.output_mode[screen_id] = (u32) video_info->vic;
1108 al_priv.output_fps[screen_id] =
1109 video_info->pixel_clk / video_info->hor_total_time /
1110 video_info->ver_total_time * (video_info->b_interlace +
1111 1) / (video_info->trd_mode + 1);
1112 al_priv.tcon_type[screen_id] = 1;
1113
1114 de_update_device_fps(al_priv.de_id[screen_id],
1115 al_priv.output_fps[screen_id]);
1116
1117 tcon_init(screen_id);
1118 tcon1_set_timming(screen_id, video_info);
1119 #if defined(DISP2_TCON_TV_SYNC_POL_ISSUE)
1120 tcon_set_sync_pol(screen_id, !video_info->ver_sync_polarity,
1121 !video_info->hor_sync_polarity);
1122 #endif /*endif DISP2_TCON_TV_SYNC_POL_ISSUE */
1123
1124 #ifdef TCON_POL_CORRECT
1125 tcon1_cfg_correct(screen_id, video_info);
1126 #endif
1127
1128 printk("%s\n", __func__);
1129 #ifdef BYPASS_TCON_CEU
1130 tcon1_hdmi_color_remap(screen_id, 0,
1131 al_priv.output_cs[screen_id]);
1132 #else
1133 /*
1134 * If yuv output(cs != 0), remap yuv plane to (v y u) sequency
1135 * else disable color remap function
1136 */
1137 if (al_priv.output_cs[screen_id] != 0)
1138 tcon1_hdmi_color_remap(screen_id, 1,
1139 al_priv.output_cs[screen_id]);
1140 else
1141 tcon1_hdmi_color_remap(screen_id, 0,
1142 al_priv.output_cs[screen_id]);
1143 #endif
1144 tcon1_src_select(screen_id, LCD_SRC_DE, al_priv.de_id[screen_id]);
1145
1146 return 0;
1147 }
1148
disp_al_hdmi_irq_enable(u32 screen_id)1149 int disp_al_hdmi_irq_enable(u32 screen_id)
1150 {
1151 tcon_irq_enable(screen_id, LCD_IRQ_TCON1_VBLK);
1152
1153 return 0;
1154 }
1155
disp_al_hdmi_irq_disable(u32 screen_id)1156 int disp_al_hdmi_irq_disable(u32 screen_id)
1157 {
1158 tcon_irq_disable(screen_id, LCD_IRQ_TCON1_VBLK);
1159
1160 return 0;
1161 }
1162 #if (defined CONFIG_ARCH_SUN8IW16) \
1163 || (defined CONFIG_ARCH_SUN8IW20) \
1164 || (defined CONFIG_ARCH_SUN20IW1)
disp_al_hdmi_pad_sel(u32 screen_id,u32 pad)1165 int disp_al_hdmi_pad_sel(u32 screen_id, u32 pad)
1166 {
1167 tcon_pan_sel(screen_id, pad);
1168
1169 return 0;
1170 }
1171 #endif
1172 /* tv */
disp_al_tv_enable(u32 screen_id)1173 int disp_al_tv_enable(u32 screen_id)
1174 {
1175 tcon1_tv_clk_enable(screen_id, 1);
1176 tcon1_open(screen_id);
1177
1178 return 0;
1179 }
1180
disp_al_tv_disable(u32 screen_id)1181 int disp_al_tv_disable(u32 screen_id)
1182 {
1183 al_priv.output_type[screen_id] = (u32) DISP_OUTPUT_TYPE_NONE;
1184
1185 tcon1_close(screen_id);
1186 tcon_exit(screen_id);
1187 tcon1_tv_clk_enable(screen_id, 0);
1188
1189 return 0;
1190 }
1191
disp_al_tv_cfg(u32 screen_id,struct disp_video_timings * video_info)1192 int disp_al_tv_cfg(u32 screen_id, struct disp_video_timings *video_info)
1193 {
1194 unsigned int pixel_clk;
1195
1196 pixel_clk = video_info->pixel_clk;
1197 #if defined(TV_UGLY_CLK_RATE)
1198 pixel_clk = (pixel_clk == TV_UGLY_CLK_RATE) ?
1199 TV_COMPOSITE_CLK_RATE : pixel_clk;
1200 #endif
1201 al_priv.output_type[screen_id] = (u32) DISP_OUTPUT_TYPE_TV;
1202 al_priv.output_mode[screen_id] = (u32) video_info->tv_mode;
1203 al_priv.output_fps[screen_id] =
1204 pixel_clk / video_info->hor_total_time
1205 / video_info->ver_total_time;
1206 al_priv.tcon_type[screen_id] = 1;
1207
1208 de_update_device_fps(al_priv.de_id[screen_id],
1209 al_priv.output_fps[screen_id]);
1210
1211 tcon_init(screen_id);
1212 tcon1_set_timming(screen_id, video_info);
1213 #ifdef BYPASS_TCON_CEU
1214 tcon1_yuv_range(screen_id, 0);
1215 #else
1216 tcon1_yuv_range(screen_id, 1);
1217 #endif
1218 tcon1_src_select(screen_id, LCD_SRC_DE, al_priv.de_id[screen_id]);
1219
1220 return 0;
1221 }
1222
disp_al_tv_irq_enable(u32 screen_id)1223 int disp_al_tv_irq_enable(u32 screen_id)
1224 {
1225 tcon_irq_enable(screen_id, LCD_IRQ_TCON1_VBLK);
1226
1227 return 0;
1228 }
1229
disp_al_tv_irq_disable(u32 screen_id)1230 int disp_al_tv_irq_disable(u32 screen_id)
1231 {
1232 tcon_irq_disable(screen_id, LCD_IRQ_TCON1_VBLK);
1233
1234 return 0;
1235 }
1236
1237 #if defined(SUPPORT_VGA)
1238 /* vga interface
1239 */
disp_al_vga_enable(u32 screen_id)1240 int disp_al_vga_enable(u32 screen_id)
1241 {
1242 tcon1_tv_clk_enable(screen_id, 1);
1243 tcon1_open(screen_id);
1244 tcon1_out_to_gpio(screen_id);
1245 return 0;
1246 }
1247
disp_al_vga_disable(u32 screen_id)1248 int disp_al_vga_disable(u32 screen_id)
1249 {
1250 al_priv.output_type[screen_id] = (u32) DISP_OUTPUT_TYPE_NONE;
1251
1252 tcon1_close(screen_id);
1253 tcon_exit(screen_id);
1254 tcon1_tv_clk_enable(screen_id, 0);
1255 return 0;
1256 }
1257
disp_al_vga_cfg(u32 screen_id,struct disp_video_timings * video_info)1258 int disp_al_vga_cfg(u32 screen_id, struct disp_video_timings *video_info)
1259 {
1260 al_priv.output_type[screen_id] = (u32) DISP_OUTPUT_TYPE_VGA;
1261 al_priv.output_mode[screen_id] = (u32) video_info->tv_mode;
1262 al_priv.output_fps[screen_id] =
1263 video_info->pixel_clk / video_info->hor_total_time
1264 / video_info->ver_total_time;
1265 al_priv.tcon_type[screen_id] = 1;
1266
1267 de_update_device_fps(al_priv.de_id[screen_id],
1268 al_priv.output_fps[screen_id]);
1269
1270 tcon_init(screen_id);
1271 tcon1_set_timming(screen_id, video_info);
1272 tcon1_src_select(screen_id, LCD_SRC_DE, al_priv.de_id[screen_id]);
1273
1274 return 0;
1275 }
1276
disp_al_vga_irq_enable(u32 screen_id)1277 int disp_al_vga_irq_enable(u32 screen_id)
1278 {
1279 tcon_irq_enable(screen_id, LCD_IRQ_TCON1_VBLK);
1280
1281 return 0;
1282 }
1283
disp_al_vga_irq_disable(u32 screen_id)1284 int disp_al_vga_irq_disable(u32 screen_id)
1285 {
1286 tcon_irq_disable(screen_id, LCD_IRQ_TCON1_VBLK);
1287
1288 return 0;
1289 }
1290
1291 #endif
1292
disp_al_vdevice_cfg(u32 screen_id,struct disp_video_timings * video_info,struct disp_vdevice_interface_para * para,u8 config_tcon_only)1293 int disp_al_vdevice_cfg(u32 screen_id, struct disp_video_timings *video_info,
1294 struct disp_vdevice_interface_para *para,
1295 u8 config_tcon_only)
1296 {
1297 struct lcd_clk_info clk_info;
1298 struct disp_panel_para info;
1299
1300 if (para->sub_intf == LCD_HV_IF_CCIR656_2CYC)
1301 al_priv.output_type[screen_id] = (u32) DISP_OUTPUT_TYPE_TV;
1302 else
1303 al_priv.output_type[screen_id] = (u32) DISP_OUTPUT_TYPE_LCD;
1304 al_priv.output_mode[screen_id] = (u32) para->intf;
1305 al_priv.output_fps[screen_id] =
1306 video_info->pixel_clk / video_info->hor_total_time
1307 / video_info->ver_total_time;
1308 al_priv.tcon_type[screen_id] = 0;
1309
1310 de_update_device_fps(al_priv.de_id[screen_id],
1311 al_priv.output_fps[screen_id]);
1312
1313 memset(&info, 0, sizeof(struct disp_panel_para));
1314 info.lcd_if = para->intf;
1315 info.lcd_x = video_info->x_res;
1316 info.lcd_y = video_info->y_res;
1317 info.lcd_hv_if = (enum disp_lcd_hv_if) para->sub_intf;
1318 info.lcd_dclk_freq = video_info->pixel_clk;
1319 info.lcd_ht = video_info->hor_total_time;
1320 info.lcd_hbp = video_info->hor_back_porch + video_info->hor_sync_time;
1321 info.lcd_hspw = video_info->hor_sync_time;
1322 info.lcd_vt = video_info->ver_total_time;
1323 info.lcd_vbp = video_info->ver_back_porch + video_info->ver_sync_time;
1324 info.lcd_vspw = video_info->ver_sync_time;
1325 info.lcd_interlace = video_info->b_interlace;
1326 info.lcd_hv_syuv_fdly = para->fdelay;
1327 info.lcd_hv_clk_phase = para->clk_phase;
1328 info.lcd_hv_sync_polarity = para->sync_polarity;
1329 info.ccir_clk_div = para->ccir_clk_div;
1330 info.input_csc = para->input_csc;
1331
1332 if (info.lcd_hv_if == LCD_HV_IF_CCIR656_2CYC)
1333 info.lcd_hv_syuv_seq = para->sequence;
1334 else
1335 info.lcd_hv_srgb_seq = para->sequence;
1336 tcon_init(screen_id);
1337 disp_al_lcd_get_clk_info(screen_id, &clk_info, &info);
1338 tcon0_set_dclk_div(screen_id, clk_info.tcon_div);
1339
1340 if (para->sub_intf == LCD_HV_IF_CCIR656_2CYC)
1341 tcon1_yuv_range(screen_id, 1);
1342 if (tcon0_cfg(screen_id, &info) != 0)
1343 DE_WRN("lcd cfg fail!\n");
1344 else
1345 DE_INF("lcd cfg ok!\n");
1346
1347 if (!config_tcon_only)
1348 tcon0_src_select(screen_id, LCD_SRC_DE,
1349 al_priv.de_id[screen_id]);
1350 else
1351 DE_INF("%s:config_tcon_only is %d\n", __func__,
1352 config_tcon_only);
1353
1354 return 0;
1355 }
1356
disp_al_vdevice_enable(u32 screen_id)1357 int disp_al_vdevice_enable(u32 screen_id)
1358 {
1359 struct disp_panel_para panel;
1360
1361 memset(&panel, 0, sizeof(struct disp_panel_para));
1362 panel.lcd_if = LCD_IF_HV;
1363 tcon0_open(screen_id, &panel);
1364
1365 return 0;
1366 }
1367
disp_al_vdevice_disable(u32 screen_id)1368 int disp_al_vdevice_disable(u32 screen_id)
1369 {
1370 al_priv.output_type[screen_id] = (u32) DISP_OUTPUT_TYPE_NONE;
1371
1372 tcon0_close(screen_id);
1373 tcon_exit(screen_id);
1374
1375 return 0;
1376 }
1377
1378 /* screen_id: used for index of manager */
disp_al_device_get_cur_line(u32 screen_id)1379 int disp_al_device_get_cur_line(u32 screen_id)
1380 {
1381 u32 tcon_type = al_priv.tcon_type[screen_id];
1382
1383 return tcon_get_cur_line(screen_id, tcon_type);
1384 }
1385
disp_al_device_get_start_delay(u32 screen_id)1386 int disp_al_device_get_start_delay(u32 screen_id)
1387 {
1388 u32 tcon_type = al_priv.tcon_type[screen_id];
1389
1390 tcon_type = (al_priv.tcon_type[screen_id] == 0) ? 0 : 1;
1391 return tcon_get_start_delay(screen_id, tcon_type);
1392 }
1393
disp_al_device_query_irq(u32 screen_id)1394 int disp_al_device_query_irq(u32 screen_id)
1395 {
1396 int ret = 0;
1397 int irq_id = 0;
1398
1399 irq_id = (al_priv.tcon_type[screen_id] == 0) ?
1400 LCD_IRQ_TCON0_VBLK : LCD_IRQ_TCON1_VBLK;
1401 ret = tcon_irq_query(screen_id, irq_id);
1402
1403 return ret;
1404 }
1405
disp_al_device_enable_irq(u32 screen_id)1406 int disp_al_device_enable_irq(u32 screen_id)
1407 {
1408 int ret = 0;
1409 int irq_id = 0;
1410
1411 irq_id = (al_priv.tcon_type[screen_id] == 0) ?
1412 LCD_IRQ_TCON0_VBLK : LCD_IRQ_TCON1_VBLK;
1413 ret = tcon_irq_enable(screen_id, irq_id);
1414
1415 return ret;
1416 }
1417
disp_al_device_disable_irq(u32 screen_id)1418 int disp_al_device_disable_irq(u32 screen_id)
1419 {
1420 int ret = 0;
1421 int irq_id = 0;
1422
1423 irq_id = (al_priv.tcon_type[screen_id] == 0) ?
1424 LCD_IRQ_TCON0_VBLK : LCD_IRQ_TCON1_VBLK;
1425 ret = tcon_irq_disable(screen_id, irq_id);
1426
1427 return ret;
1428 }
1429
disp_al_lcd_get_status(u32 screen_id,struct disp_panel_para * panel)1430 int disp_al_lcd_get_status(u32 screen_id, struct disp_panel_para *panel)
1431 {
1432 int ret = 0;
1433 #if defined(DSI_VERSION_40)
1434 if (panel->lcd_if == LCD_IF_DSI)
1435 ret = dsi_get_status(screen_id);
1436 else
1437 #endif
1438 ret = tcon_get_status(screen_id, al_priv.tcon_type[screen_id]);
1439
1440 return ret;
1441 }
1442
disp_al_device_get_status(u32 screen_id)1443 int disp_al_device_get_status(u32 screen_id)
1444 {
1445 int ret = 0;
1446
1447 ret = tcon_get_status(screen_id, al_priv.tcon_type[screen_id]);
1448
1449 return ret;
1450 }
1451
disp_al_device_src_select(u32 screen_id,u32 src)1452 int disp_al_device_src_select(u32 screen_id, u32 src)
1453 {
1454 int ret = 0;
1455
1456 return ret;
1457 }
1458
disp_init_al(struct disp_bsp_init_para * para)1459 int disp_init_al(struct disp_bsp_init_para *para)
1460 {
1461 int i;
1462 u32 hwdev_index = 0;
1463
1464 memset(&al_priv, 0, sizeof(struct disp_al_private_data));
1465 de_al_init(para);
1466 de_enhance_init(para);
1467 de_ccsc_init(para);
1468 de_dcsc_init(para);
1469 #if IS_ENABLED(CONFIG_EINK_PANEL_USED) || IS_ENABLED(CONFIG_EINK200_SUNXI)
1470 #else
1471 wb_ebios_init(para);
1472 #endif
1473 de_clk_set_reg_base(para->reg_base[DISP_MOD_DE]);
1474 #if defined(CONFIG_INDEPENDENT_DE)
1475 de1_clk_set_reg_base(para->reg_base[DISP_MOD_DE1]);
1476 #endif
1477
1478
1479 for (i = 0; i < DEVICE_NUM; i++)
1480 tcon_set_reg_base(i, para->reg_base[DISP_MOD_LCD0 + i]);
1481
1482 for (i = 0; i < DE_NUM; i++) {
1483 if (de_feat_is_support_smbl(i))
1484 #if defined(CONFIG_INDEPENDENT_DE)
1485 de_smbl_init(i, para->reg_base[DISP_MOD_DE + i]);
1486 #else
1487 de_smbl_init(i, para->reg_base[DISP_MOD_DE]);
1488 #endif
1489 }
1490
1491 #if defined(HAVE_DEVICE_COMMON_MODULE)
1492 #if defined(CONFIG_INDEPENDENT_DE)
1493 for (i = 0; i < DE_NUM; i++) {
1494 tcon_top_set_reg_base(i, para->reg_base[DISP_MOD_DEVICE + i]);
1495 }
1496 #else
1497 tcon_top_set_reg_base(0, para->reg_base[DISP_MOD_DEVICE]);
1498 #endif
1499 #endif
1500 #if defined(SUPPORT_DSI)
1501 for (i = 0; i < DEVICE_DSI_NUM; ++i)
1502 dsi_set_reg_base(i, para->reg_base[DISP_MOD_DSI0 + i]);
1503 #endif
1504
1505 if (para->boot_info.sync == 1) {
1506 u32 disp = para->boot_info.disp;
1507 u32 tcon_id;
1508 struct disp_video_timings tt;
1509
1510 memset(&tt, 0, sizeof(struct disp_video_timings));
1511 i = 0;
1512 for (hwdev_index = 0; hwdev_index < DEVICE_NUM; ++hwdev_index) {
1513 if (!bsp_disp_feat_is_supported_output_types(
1514 hwdev_index, para->boot_info.type)) {
1515 continue;
1516 }
1517 if (disp != i) {
1518 ++i;
1519 continue;
1520 } else
1521 break;
1522 }
1523 if (hwdev_index == DEVICE_NUM) {
1524 __wrn("Can not find tcon index for smooth display\n");
1525 hwdev_index = 0;
1526 }
1527 #if defined(HAVE_DEVICE_COMMON_MODULE)
1528 al_priv.tcon_id[disp] = hwdev_index;
1529 #else
1530 al_priv.tcon_id[disp] = de_rtmx_get_mux(disp);
1531 #endif
1532 tcon_id = al_priv.tcon_id[disp];
1533
1534 /*
1535 * should take care about this,
1536 * extend display treated as a LCD OUTPUT
1537 */
1538 al_priv.output_type[tcon_id] = para->boot_info.type;
1539 al_priv.output_mode[tcon_id] = para->boot_info.mode;
1540 al_priv.tcon_type[tcon_id] = get_tcon_type_by_de_index(disp);
1541
1542 de_rtmx_sync_hw(disp);
1543 de_rtmx_get_display_size(disp, &al_priv.disp_size[disp].width,
1544 &al_priv.disp_size[disp].height);
1545
1546 al_priv.output_fps[tcon_id] = 60;
1547 de_update_device_fps(disp, al_priv.output_fps[tcon_id]);
1548 }
1549
1550 return 0;
1551 }
1552
disp_exit_al(void)1553 int disp_exit_al(void)
1554 {
1555
1556 #if defined(SUPPORT_SMBL)
1557 int i;
1558 #endif /*endif SUPPORT_SMBL */
1559
1560 de_al_exit();
1561 de_enhance_exit();
1562 de_ccsc_exit();
1563 de_dcsc_exit();
1564 #if IS_ENABLED(CONFIG_EINK_PANEL_USED) || IS_ENABLED(CONFIG_EINK200_SUNXI)
1565 #else
1566 wb_ebios_exit();
1567 #endif
1568
1569 #if defined(SUPPORT_SMBL)
1570 for (i = 0; i < DE_NUM; i++) {
1571 if (de_feat_is_support_smbl(i))
1572 de_smbl_exit(i);
1573 }
1574 #endif /*endif SUPPORT_SMBL */
1575
1576 return 0;
1577 }
1578
disp_al_get_display_size(unsigned int screen_id,unsigned int * width,unsigned int * height)1579 int disp_al_get_display_size(unsigned int screen_id, unsigned int *width,
1580 unsigned int *height)
1581 {
1582 *width = al_priv.disp_size[screen_id].width;
1583 *height = al_priv.disp_size[screen_id].height;
1584
1585 return 0;
1586 }
1587
1588 /**
1589 * @name :disp_al_vdpo_cfg
1590 * @brief :config tcon(tcon_lcd or tcon_tv) and other data structure
1591 * @param[IN] :screen_id:tcon index
1592 * @param[IN] :video_info:timing info
1593 * @return :0 if success else fail
1594 */
disp_al_vdpo_cfg(u32 screen_id,u32 vdpo_index,struct disp_video_timings * video_info)1595 int disp_al_vdpo_cfg(u32 screen_id, u32 vdpo_index,
1596 struct disp_video_timings *video_info)
1597 {
1598 struct lcd_clk_info clk_info;
1599 struct disp_panel_para panel;
1600
1601 al_priv.output_type[screen_id] = (u32)DISP_OUTPUT_TYPE_VDPO;
1602 al_priv.output_mode[screen_id] = LCD_IF_HV;
1603 al_priv.output_fps[screen_id] =
1604 video_info->pixel_clk / video_info->hor_total_time /
1605 video_info->ver_total_time * (video_info->b_interlace + 1) /
1606 (video_info->trd_mode + 1);
1607
1608 de_update_device_fps(al_priv.de_id[screen_id],
1609 al_priv.output_fps[screen_id]);
1610 /*judge output type:tcon_lcd or tcon_tv*/
1611 if (de_feat_is_supported_output_types(screen_id,
1612 DISP_OUTPUT_TYPE_LCD)) {
1613 al_priv.tcon_type[screen_id] = 0;
1614 memset(&panel, 0, sizeof(struct disp_panel_para));
1615
1616 panel.lcd_if = LCD_IF_VDPO;
1617 panel.lcd_x = video_info->x_res;
1618 panel.lcd_y = video_info->y_res;
1619 panel.lcd_hv_if = LCD_HV_IF_PRGB_1CYC;
1620 panel.lcd_dclk_freq = video_info->pixel_clk;
1621 panel.lcd_ht = video_info->hor_total_time;
1622 panel.lcd_hbp =
1623 video_info->hor_back_porch + video_info->hor_sync_time;
1624 panel.lcd_hspw = video_info->hor_sync_time;
1625 panel.lcd_vt = video_info->ver_total_time;
1626 panel.lcd_vbp =
1627 video_info->ver_back_porch + video_info->ver_sync_time;
1628 panel.lcd_vspw = video_info->ver_sync_time;
1629 panel.lcd_interlace = video_info->b_interlace;
1630 panel.lcd_hv_syuv_fdly = 1; /*TODO*/
1631 panel.lcd_hv_clk_phase = 0;
1632 panel.lcd_hv_sync_polarity = 0;
1633 panel.lcd_hv_srgb_seq = 0;
1634
1635 tcon_init(screen_id);
1636 disp_al_lcd_get_clk_info(screen_id, &clk_info, &panel);
1637 tcon0_set_dclk_div(screen_id, clk_info.tcon_div);
1638 if (tcon0_cfg(screen_id, &panel) != 0)
1639 DE_WRN("lcd cfg fail!\n");
1640 else
1641 DE_INF("lcd cfg ok!\n");
1642
1643 tcon0_src_select(screen_id, LCD_SRC_DE,
1644 al_priv.de_id[screen_id]);
1645 } else {
1646 tcon_init(screen_id);
1647 al_priv.tcon_type[screen_id] = 1;
1648 tcon1_set_timming(screen_id, video_info);
1649 vdpo_src_sel(vdpo_index, 1); /*use tcon_tv*/
1650 tcon1_src_select(screen_id, LCD_SRC_DE,
1651 al_priv.de_id[screen_id]);
1652 }
1653 return 0;
1654 }
1655
1656 /**
1657 * @name :disp_al_vdpo_enable
1658 * @brief :start tcon
1659 * @param[IN] :screen_id:de index
1660 * @param[OUT] :
1661 * @return :0
1662 */
disp_al_vdpo_enable(u32 screen_id,u32 vdpo_index)1663 int disp_al_vdpo_enable(u32 screen_id, u32 vdpo_index)
1664 {
1665 struct disp_panel_para panel;
1666
1667 if (de_feat_is_supported_output_types(screen_id,
1668 DISP_OUTPUT_TYPE_LCD)) {
1669 memset(&panel, 0, sizeof(struct disp_panel_para));
1670 panel.lcd_if = LCD_IF_HV;
1671 tcon_vdpo_clk_enable(vdpo_index, 1);
1672 tcon0_open(screen_id, &panel);
1673 } else {
1674 tcon_vdpo_clk_enable(vdpo_index, 1);
1675 tcon1_open(screen_id);
1676 }
1677
1678 return 0;
1679 }
1680
disp_al_vdpo_disable(u32 screen_id)1681 int disp_al_vdpo_disable(u32 screen_id)
1682 {
1683 al_priv.output_type[screen_id] = (u32)DISP_OUTPUT_TYPE_NONE;
1684 if (de_feat_is_supported_output_types(screen_id,
1685 DISP_OUTPUT_TYPE_LCD)) {
1686 tcon0_close(screen_id);
1687 tcon_exit(screen_id);
1688 } else {
1689 tcon1_close(screen_id);
1690 tcon_exit(screen_id);
1691 tcon1_tv_clk_enable(screen_id, 0);
1692 }
1693 return 0;
1694 }
1695
disp_al_show_builtin_patten(u32 hwdev_index,u32 patten)1696 void disp_al_show_builtin_patten(u32 hwdev_index, u32 patten)
1697 {
1698 tcon_show_builtin_patten(hwdev_index, patten);
1699 }
1700
disp_al_update_de_clk_rate(u32 rate)1701 void disp_al_update_de_clk_rate(u32 rate)
1702 {
1703 de_update_clk_rate(rate);
1704 }
1705
1706