• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Bestechnic (Shanghai) Co., Ltd. All rights reserved.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "plat_addr_map.h"
16 #if defined(DSI_BASE) && defined(LCDC_BASE)
17 #include "plat_types.h"
18 #include "hal_cmu.h"
19 #include "hal_timer.h"
20 #include "hal_trace.h"
21 #include "hal_dsi.h"
22 #include "reg_dsi.h"
23 #include "reg_lcdc.h"
24 #include "mipiphy.h"
25 #include "cmsis_nvic.h"
26 #include CHIP_SPECIFIC_HDR(pmu)
27 
28 static bool dsi_init_v2 = false;
29 static enum DSI_MODE_T dsi_mode = DSI_MODE_CMD;
30 static HAL_DSI_XFER_COMPLETE_CALLBACK_T dsi_callback;
31 
32 static struct LCDC_REG_T * const lcdc = (struct LCDC_REG_T *)LCDC_BASE;
33 
34 static struct DSI_REG_T * const dsi = (struct DSI_REG_T *)DSI_BASE;
35 
36 static uint8_t  lane_num = 0;
37 
38 enum DSI_CMD_TYPE_T {
39     CLN_ENT_LP = 0,
40     CLN_EXIT_LP = 1,
41     CLN_ENT_ULPS = 2,
42     CLN_EXIT_ULPS = 3,
43     DLN_LPT = 4,
44     DLN_HST = 5,
45     DLN_LPT_BTA = 6,
46     DLN_HST_BTA = 7,
47 };
48 
49 enum DSI_CMD_T {
50     DSC_SHORT_WRITE = 0x05,
51     DSC_SHORT_WRITE_1PAR = 0x15,
52     DSC_LONG_WRITE = 0x39
53 };
54 
55 #define mode_rgb565          0x0
56 #define mode_rgb1555         0x1
57 #define mode_rgb888packed    0x2
58 #define mode_rgb888unpacked  0x3
59 #define mode_rgbA888         0x4
60 #define mode_yuv422packed    0x5
61 #define mode_yuv422planar    0x6
62 #define mode_yuv420planar    0x7
63 #define mode_smpncmd         0x8
64 #define mode_palette4bit     0x9
65 #define mode_palette8bit     0xa
66 #define mode_rgb888A         0xb
67 #define mode_alpha_dma       0x0
68 #define mode_alpha_gra       0x1
69 #define mode_alpha_cfg       0x2
70 #define mode_alpha_non       0x3
71 #define mode_low16of24       0x0
72 #define mode_high16of24      0x1
73 #define mode_low18of24       0x2
74 #define mode_high18of24      0x3
75 #define mode_low12of24       0x4
76 #define mode_high12of24      0x5
77 #define mode_allof24         0x6
78 #define mode_smpn3cyc888     0x0
79 #define mode_smpn3cyc666     0x1
80 #define mode_smpn2cyc565     0x2
81 #define mode_smpn1cyc888     0x3
82 #define mode_smpn1cyc666     0x4
83 #define mode_smpn1cyc565     0x5
84 #define smpn8dual_swap       0xf
85 #define axim_axiconfig	     0x20
86 #define mode_dumb24          0x0 | axim_axiconfig
87 #define mode_dumb18spi       0x1 | axim_axiconfig
88 #define mode_dumb18gpio      0x2 | axim_axiconfig
89 #define mode_dumb16spi       0x3 | axim_axiconfig
90 #define mode_dumb16gpio      0x4 | axim_axiconfig
91 #define mode_dumb12all       0x5 | axim_axiconfig
92 #define mode_smpn18spi       0x6 | axim_axiconfig
93 #define mode_smpn16spi       0x7 | axim_axiconfig
94 #define mode_smpn8all        0x8 | axim_axiconfig
95 #define mode_dumb18smpn8     0x9 | axim_axiconfig
96 #define mode_dumb16smpn8spi  0xa | axim_axiconfig
97 #define mode_dumb16smpn8gpio 0xb | axim_axiconfig
98 #define mode_pn16tv16        0xc | axim_axiconfig
99 #define mode_hwc_pass        0x0
100 #define mode_hwc_color1      0x1
101 #define mode_hwc_color2      0x2
102 #define mode_hwc_inv         0x3
103 #define SRAMID_gamma_yr      0x0
104 #define SRAMID_gamma_ug      0x1
105 #define SRAMID_gamma_vb      0x2
106 #define SRAMID_palette       0x3
107 #define SRAMID_hwc           0xc
108 #define SRTVID_gamma_yr      0x4
109 #define SRTVID_gamma_ug      0x5
110 #define SRTVID_gamma_vb      0x6
111 #define SRTVID_palette       0x7
112 #define SRTVID_tvc           0xb
113 
hal_display_irq_handler(uint32_t irq_stats)114 void hal_display_irq_handler(uint32_t irq_stats)
115 {
116     if (irq_stats & (LCD_TXC_FRAMEDONE | LCD_DUMB_FRAMEDONE)) {
117         if ((irq_stats & (LCD_DMA_FRAME_IRQ0|LCD_DMA_FRAME_IRQ1)) ==
118             (LCD_DMA_FRAME_IRQ0|LCD_DMA_FRAME_IRQ1)) {
119             TRACE(0, "Warning: lcdc lost frame");
120         }
121         if ((irq_stats & (LCD_GRA_FRAME_IRQ0|LCD_GRA_FRAME_IRQ1)) ==
122             (LCD_GRA_FRAME_IRQ0|LCD_GRA_FRAME_IRQ1)) {
123             TRACE(0, "Warning: lcdc lost frame");
124         }
125         if ((irq_stats & (LCD_TVG_FRAME_IRQ0|LCD_TVG_FRAME_IRQ1)) ==
126             (LCD_TVG_FRAME_IRQ0|LCD_TVG_FRAME_IRQ1)) {
127             TRACE(0, "Warning: lcdc lost frame");
128         }
129         if (irq_stats & LCD_DMA_FRAME_IRQ0) {
130             if (dsi_callback)
131                 dsi_callback(0, 0, lcdc->REG_0C0);
132             else
133                 hal_lcdc_start();
134         }
135         if (irq_stats & LCD_DMA_FRAME_IRQ1) {
136             if (dsi_callback)
137                 dsi_callback(0, 1, lcdc->REG_0D0);
138             else
139                 hal_lcdc_start();
140         }
141 
142         if (irq_stats & LCD_GRA_FRAME_IRQ0) {
143             if (dsi_callback)
144                 dsi_callback(1, 0, lcdc->REG_0F4);
145             else
146                 hal_lcdc_start();
147         }
148         if (irq_stats & LCD_GRA_FRAME_IRQ1) {
149             if (dsi_callback)
150                 dsi_callback(1, 1, lcdc->REG_0F8);
151             else
152                 hal_lcdc_start();
153         }
154 
155         if (irq_stats & LCD_TVG_FRAME_IRQ0) {
156             uint32_t addr = lcdc->REG_034 + 368*4*2;
157             if (addr >= 0x50000000+368*448*4)
158                 addr = 0x50000000;
159             lcdc->REG_034 = addr;
160             hal_lcdc_start();
161         }
162         if (irq_stats & LCD_TVG_FRAME_IRQ1) {
163             uint32_t addr = lcdc->REG_038 + 368*4*2;
164             if (addr >= 0x50000000+368*448*4)
165                 addr = 0x50000000;
166             lcdc->REG_038 = addr;
167             hal_lcdc_start();
168         }
169     }
170 }
171 
hal_dsi0_irq_handler(uint32_t irq_stats)172 void hal_dsi0_irq_handler(uint32_t irq_stats)
173 {
174 }
175 
176 //TE irq
hal_dsi1_irq_handler(uint32_t irq_stats)177 void hal_dsi1_irq_handler(uint32_t irq_stats)
178 {
179 }
180 
hal_dsi_unified_irq_handler()181 void hal_dsi_unified_irq_handler()
182 {
183     uint32_t irq_stats;
184 #if 0
185     void dsiphy_clock_restore(void);
186     static uint64_t irq_count = 0;
187     if (irq_count++ == 2)
188         dsiphy_clock_restore();
189 #endif
190     //TRACE(0, "irq:%u ms", FAST_TICKS_TO_MS(hal_fast_sys_timer_get()));
191     irq_stats = lcdc->REG_1C4;
192     //TRACE(0, "lcdc->REG_1C4:0x%x", irq_stats);
193     if (irq_stats & 0xffffff00) {
194         lcdc->REG_1C4 = 0; //clear irq
195         hal_display_irq_handler(irq_stats);
196     }
197 
198 #if 0 //doesn't handler dsi irq
199     irq_stats = dsi->REG_010;
200     //TRACE(0, "dsi->REG_010:0x%x", irq_stats);
201     dsi->REG_010 = irq_stats;//clear irq
202     if (irq_stats & DSI_TE_INTR)
203         hal_dsi1_irq_handler(irq_stats);
204     if (irq_stats & (DSI_HS_CMD_RD_EN | DSI_LPRX_RD_EN | DSI_CMD_DONE_FLAG | DSI_BTA_DONE_FLAG |
205         DSI_BTA_FAIL_FLAG | DSI_LP_RX_DONE_FLAG | DSI_RX_ERR_FLAG | DSI_LPCD_FLAG | DSI_RX_TIMEOUT_FLAG))
206         hal_dsi0_irq_handler(irq_stats);
207 #endif
208 }
209 
210 /**
211  * @brief hal_dsi_read_cmd - read data by lp mode
212  * packet format:
213  * ShortPacket: DI DATA0 DATA1 ECC
214  * LongPacket:  DI WC0   WC1   ECC DATA[0]-DATA[WC-1] CS0 CS1
215  * e.g. read id: hal_dsi_read_cmd(0x04, buf, 3)
216  * @param cmd : cmd
217  * @param read_buf : read buffer
218  * @param len : read len
219  * @return int
220  */
hal_dsi_read_cmd(uint8_t cmd,uint8_t * recv_buf,uint8_t len)221 int hal_dsi_read_cmd(uint8_t cmd, uint8_t *recv_buf, uint8_t len)
222 {
223     volatile uint32_t temp;
224     uint8_t fifo_len;
225     uint8_t buf[32];
226     uint8_t buf_len = 0;
227     uint32_t time;
228 
229     dsi->REG_010 |= DSI_LP_RX_DONE_FLAG;
230 
231     dsi->REG_018 = (len << 8) | 0x37;
232     dsi->REG_014 =  (5 << 16) | (0xe1 << 8) | DLN_LPT;
233     hal_sys_timer_delay_us(20);
234     dsi->REG_018 = (cmd << 8)| 0x06;
235     dsi->REG_014 = (5 << 16) | (0xe1 << 8) | DLN_LPT_BTA;
236     hal_sys_timer_delay_us(10);
237 
238     time = hal_sys_timer_get();
239     while (1) {
240         temp = dsi->REG_010;
241         if (temp & DSI_LPRX_SIZE_MASK) {
242             buf[buf_len ++] = temp;
243         } else if (temp & (DSI_RX_ERR_FLAG | DSI_RX_TIMEOUT_FLAG)) {
244             dsi->REG_010 |= (DSI_RX_ERR_FLAG | DSI_RX_TIMEOUT_FLAG);
245             TRACE(0, "rx error:0x%x", temp);
246             return -1;
247         } else if ((temp & DSI_LP_RX_DONE_FLAG) && (temp & DSI_LPRX_SIZE_MASK) == 0) {
248             //TRACE(0, "rx done:0x%x", temp);
249             break;
250         } else if (hal_sys_timer_get() - time > MS_TO_TICKS(1000)) {
251             TRACE(0, "rx timerout:0x%x", temp);
252             return -2;
253         }
254         hal_sys_timer_delay_us(1);
255     }
256 
257     fifo_len = GET_BITFIELD(temp, DSI_LPRX_SIZE);
258     if (fifo_len > 1) {
259         TRACE(0, "warning: fifo is not empty");
260         while (fifo_len > 1) {
261             temp = dsi->REG_010;
262             fifo_len --;
263         }
264     }
265 
266     if (buf_len >= 2 && buf[1] == 0x02) {
267         TRACE(0, "Acknowledge error report");
268         return -1;
269     } else if (len == 1 && buf_len >= 3 && buf[1] == 0x21) { //short packet
270         recv_buf[0] = buf[2];
271         return 1;
272     } else if (len == 2 && buf_len >= 4 && buf[1] == 0x22) { //short packet
273         recv_buf[0] = buf[2];
274         recv_buf[1] = buf[3];
275         return 2;
276     } else if (buf_len >= 10 && buf[1] == 0x1c) { //long packet
277         uint16_t word_cnt = (buf[3] >> 8) | buf[2];
278         uint16_t i;
279         if (word_cnt < len) {
280             TRACE(0, "warning: word_cnt:%d < len:%d", word_cnt, len);
281             len = word_cnt;
282         }
283         for (i = 0; i < len; ++i)
284             recv_buf[i] = buf[5 + i];
285         return len;
286     } else {
287         TRACE(0, "error, buf_len:%d, len:%d", buf_len, len);
288         DUMP8("%02x ", buf, buf_len);
289         return -3;
290     }
291 
292     return 0;
293 }
294 
295 
296 /**
297  * @brief hal_dsi_send_cmd - send cmd by lp mode
298  *
299  * @param cmd
300  */
hal_dsi_send_cmd(uint8_t cmd)301 void hal_dsi_send_cmd(uint8_t cmd)
302 {
303     dsi->REG_018 = (cmd << 8) | DSC_SHORT_WRITE;
304     dsi->REG_014 = (5 << 16) | (0xe1 << 8) | DLN_LPT;
305 #ifndef SIMU
306     hal_sys_timer_delay(MS_TO_TICKS(1));
307 #endif
308 }
309 
310 /**
311  * @brief hal_dsi_send_cmd_data - send cmd with data by lp mode
312  *
313  * @param cmd : cmd
314  * @param len : send param num
315  * @param p0 : param0
316  * @param p1 : param1
317  * @param p2 : param2
318  * @param p3 : param3
319  */
hal_dsi_send_cmd_data(uint8_t cmd,uint32_t len,uint8_t p0,uint8_t p1,uint8_t p2,uint8_t p3)320 void hal_dsi_send_cmd_data(uint8_t cmd, uint32_t len, uint8_t p0,
321                            uint8_t p1, uint8_t p2, uint8_t p3)
322 {
323     if (len == 1) {
324         dsi->REG_018 = (p0 << 16) | (cmd << 8) | DSC_SHORT_WRITE_1PAR;
325         dsi->REG_014 = (5 << 16) | (0xe1 << 8) | DLN_LPT;
326     } else if (len == 2) {
327         dsi->REG_018 = ((len+1) << 8) | DSC_LONG_WRITE;
328         dsi->REG_01C = cmd |
329                        (p0 << 8) |
330                        (p1 << 16);
331         dsi->REG_014 = ((len+1+4+3) << 16) | (0xe1 << 8) | DLN_LPT;
332     } else if (len == 3) {
333         dsi->REG_018 = ((len+1) << 8) | DSC_LONG_WRITE;
334         dsi->REG_01C = cmd |
335                        (p0 << 8) |
336                        (p1 << 16) |
337                        (p2 << 24);
338         dsi->REG_014 = ((len+1+4+3) << 16) | (0xe1 << 8) | DLN_LPT;
339     } else if (len == 4) {
340         dsi->REG_018 = ((len+1) << 8) | DSC_LONG_WRITE;
341         dsi->REG_01C = cmd |
342                        (p0 << 8) |
343                        (p1 << 16) |
344                        (p2 << 24);
345         dsi->REG_020 = p3;
346         dsi->REG_014 = ((len+1+4+3) << 16) | (0xe1 << 8) | DLN_LPT;
347     }
348 #ifndef SIMU
349     hal_sys_timer_delay(US_TO_TICKS(len * 20 + 10));
350 #endif
351 }
352 
353 /**
354  * @brief hal_dsi_send_long_array - send cmd with data with array
355  *
356  * @param len : array len
357  * @param data : array data
358  */
hal_dsi_send_long_array(uint32_t len,uint32_t * data)359 void hal_dsi_send_long_array(uint32_t len, uint32_t *data)
360 {
361     int i;
362     dsi->REG_018 = (len << 8) | DSC_LONG_WRITE;
363     for(i=0;i<len/4;i++)
364         dsi->REG_01C = data[i];
365     int remain = len%4;
366     if (remain == 1)
367         dsi->REG_020 = data[i];
368     else if (remain == 2)
369         dsi->REG_024 = data[i];
370     else if (remain == 3)
371         dsi->REG_028 = data[i];
372     dsi->REG_014 = ((len+4+3) << 16) | (0xe1 << 8) | DLN_LPT;
373 #ifndef SIMU
374     hal_sys_timer_delay(US_TO_TICKS(len * 20 + 10));
375 #endif
376 }
377 
378 /**
379  * @brief hal_dsi_send_cmd_list - send cmd with data list
380  *
381  * @param cmd
382  * @param para_count
383  * @param para_list
384  */
hal_dsi_send_cmd_list(unsigned cmd,unsigned char para_count,unsigned char * para_list)385 void hal_dsi_send_cmd_list(unsigned cmd, unsigned char para_count,
386                            unsigned char *para_list)
387 {
388     unsigned int item[16]={0};
389     unsigned char dsi_cmd = (unsigned char)cmd;
390     unsigned char dc;
391     int index = 0;
392     if (para_count + 1 > 60)
393             return;
394 
395     if (para_count == 0) {
396             hal_dsi_send_cmd(dsi_cmd);
397     } else if (para_count == 1) {
398             hal_dsi_send_cmd_data(dsi_cmd, 1, para_list[0], 0x0, 0x0, 0x0);
399     } else if (para_count == 2) {
400             hal_dsi_send_cmd_data(dsi_cmd, 2, para_list[0], para_list[1], 0x0, 0x0);
401     } else if (para_count == 3) {
402             hal_dsi_send_cmd_data(dsi_cmd, 3, para_list[0], para_list[1], para_list[2], 0x0);
403     } else if (para_count == 4) {
404             hal_dsi_send_cmd_data(dsi_cmd, 4, para_list[0], para_list[1], para_list[2], para_list[3]);
405     } else {
406         while (1) {
407             if (index == para_count + 1){
408                 break;
409             }
410             if (index == 0)
411                 dc = cmd;
412             else
413                 dc = para_list[index - 1];
414             item[index / 4 ] |= (dc << (8 * (index % 4)));
415             ++index;
416         }
417         hal_dsi_send_long_array(index,item);
418     }
419 }
420 
hal_dsi_init(uint16_t h_res,uint8_t lane_number)421 void hal_dsi_init(uint16_t h_res ,uint8_t lane_number)
422 {
423     if (!dsi_init_v2) {
424         hal_iomux_set_dsi_te();
425         hal_cmu_dsi_clock_enable();
426     }
427     hal_cmu_dsi_reset_set();
428     hal_sys_timer_delay_us(10);
429     hal_cmu_dsi_reset_clear();
430     hal_sys_timer_delay_us(10);
431 
432 #ifndef FPGA
433     dsiphy_open(0);
434 #endif
435     if (lane_number <= 2) {
436         lane_num = lane_number;
437     }
438     //DSI init-1
439     if (dsi_mode == DSI_MODE_VIDEO) {
440         dsi->REG_000 = DSI_R_LANE_NUM(lane_num - 1) | DSI_R_LPCD_DLY(1) | DSI_R_VIDEO_MODE|
441             DSI_R_EOTP_EN |DSI_R_HSA_LP | DSI_R_HSE_EN | DSI_R_HFP_LP |
442             DSI_R_T_LPX(0x6) | DSI_R_CLK_PRE(0x3) | DSI_R_CLK_POST(0x7);
443     } else {
444         dsi->REG_000 = DSI_R_LANE_NUM(lane_num - 1) | DSI_R_LPCD_DLY(1) |
445             DSI_R_HSA_LP | DSI_R_HSE_EN | DSI_R_HFP_LP | DSI_R_EOTP_EN |
446             DSI_R_T_LPX(0x6) | DSI_R_CLK_PRE(0x3) | DSI_R_CLK_POST(0x7);
447     }
448     dsi->REG_004 = DSI_R_HS_EXIT_TIME(0xb) | DSI_R_HS_PRPR_TIME(0xc) |
449         DSI_R_HS_ZERO_TIME(0x2) | DSI_R_HS_TRAIL_TIME(0xa) |
450         DSI_R_T_WAKEUP(0x27);
451     dsi->REG_008 = DSI_R_CLK_EXIT_TIME(1) | DSI_R_CLK_PRPR_TIME(0) |
452         DSI_R_CLK_ZERO_TIME(7) | DSI_R_CLK_TRAIL_TIME(0) |
453         DSI_R_CLK_T_WAKEUP(0x48);
454     if (dsi_mode == DSI_MODE_VIDEO) {
455         dsi->REG_00C = DSI_R_DTYPE(0x3e) | DSI_R_VC_CH_ID(0x0) |
456             DSI_R_VIDEO_PACKET_LENTH(h_res*3+6) | DSI_R_INPUT_TYPE(0x0) |
457             DSI_R_DLANE_AD_TIME(0x12);
458     } else {
459         dsi->REG_00C = DSI_R_DTYPE(0x39) | DSI_R_VC_CH_ID(0x0) |
460             DSI_R_VIDEO_PACKET_LENTH(h_res*3+6+1) | DSI_R_INPUT_TYPE(0x0) |
461             DSI_R_DLANE_AD_TIME(0x12);
462     }
463     dsi->REG_048 = DSI_R_COLOR_BAR_WIDTH(0x100) | DSI_R_HSYNC_DLY_NUM(0x96a);
464     //dsi->REG_048 = DSI_R_HSYNC_DLY_NUM(0x96a);
465 #ifndef SIMU
466     hal_sys_timer_delay(MS_TO_TICKS(2));
467 #endif
468 
469     //MASK(disable) all irq
470     dsi->REG_010 &= ~(DSI_INTR_MASK_MASK | //cisalbe all irq
471         DSI_HS_CMD_RD_EN | DSI_LPRX_RD_EN | DSI_CMD_DONE_FLAG | DSI_BTA_DONE_FLAG |
472         DSI_BTA_FAIL_FLAG | DSI_LP_RX_DONE_FLAG | DSI_RX_ERR_FLAG | DSI_LPCD_FLAG |
473         DSI_RX_TIMEOUT_FLAG | DSI_TE_INTR); //clear irq status
474     dsi->REG_010 |= DSI_LPRX_RD_EN;//for DCS read cmd
475 
476     hal_cmu_reset_set(HAL_CMU_MOD_Q_DSI_PIX);
477     hal_cmu_reset_set(HAL_CMU_MOD_Q_DSI_DSI);
478     hal_cmu_reset_clear(HAL_CMU_MOD_Q_DSI_PIX);
479     hal_cmu_reset_clear(HAL_CMU_MOD_Q_DSI_DSI);
480 }
481 
hal_dsi_init_v2(uint16_t h_res,enum DSI_MODE_T mode,uint8_t lane_number,uint32_t dsi_bitclk,uint32_t dsi_pclk)482 void hal_dsi_init_v2(uint16_t h_res, enum DSI_MODE_T mode, uint8_t lane_number, uint32_t dsi_bitclk, uint32_t dsi_pclk)
483 {
484     // TODO: add more dsi_clk configurations
485     uint32_t dsi_clk = 200;
486     if (dsi_bitclk <= 400) {
487         dsi_clk = 200;
488     } else {
489         dsi_clk = 250;
490     }
491     uint8_t pixel_div = (uint8_t)(dsi_clk * 1000 / dsi_pclk) - 2;
492     if (pixel_div > 0x1F) {
493         TRACE(0, "invalid pixel_div %u", pixel_div);
494         return;
495     }
496     if (lane_number < 1 || lane_number > 2) {
497         TRACE(0, "invalid lane_number %d", lane_number);
498         return;
499     }
500     dsi_mode = mode;
501     dsi_init_v2 = true;
502     TRACE(0, "dsi_clk %u, pixel_div %u, dsi_mode %u", dsi_clk, pixel_div, dsi_mode);
503     pmu_set_dsi_clk(dsi_clk);
504     hal_cmu_dsi_clock_enable_v2(pixel_div);
505     hal_dsi_init(h_res, lane_number);
506 }
507 
hal_dsi_start(void)508 void hal_dsi_start(void)
509 {
510     if (dsi_mode == DSI_MODE_VIDEO) {
511         dsi->REG_000 = DSI_R_LPCD_DLY(1) | DSI_R_HSA_LP |DSI_R_HBP_LP| DSI_R_HSE_EN | DSI_R_HFP_LP |
512             DSI_R_EOTP_EN |DSI_R_VIDEO_MODE| DSI_R_T_LPX(0x4) | DSI_R_CLK_PRE(0x3)|
513             DSI_R_CLK_POST(0x7) | DSI_R_LANE_NUM(lane_num - 1);
514         dsi->REG_000 &=  ~(DSI_R_EOTP_EN |DSI_R_HSA_LP|DSI_R_HBP_LP);
515     } else {
516         dsi->REG_000 = DSI_R_LPCD_DLY(1) | DSI_R_HSA_LP | DSI_R_HSE_EN | DSI_R_HFP_LP | DSI_R_EOTP_EN |
517                         DSI_R_T_LPX(0x4) | DSI_R_CLK_PRE(0x3) | DSI_R_CLK_POST(0x7);
518     }
519 
520     dsi->REG_004 = DSI_R_HS_EXIT_TIME(0xb) | DSI_R_HS_PRPR_TIME(0x4) | DSI_R_HS_ZERO_TIME(0xb) |
521                     DSI_R_HS_TRAIL_TIME(0x9) | DSI_R_T_WAKEUP(0x207);
522     dsi->REG_008 = DSI_R_CLK_EXIT_TIME(0xb) | DSI_R_CLK_PRPR_TIME(0x8) | DSI_R_CLK_ZERO_TIME(0x1f) |
523                     DSI_R_CLK_TRAIL_TIME(0x8) | DSI_R_CLK_T_WAKEUP(0x66);
524     if (dsi_mode == DSI_MODE_VIDEO) {
525         dsi->REG_048 = DSI_R_HSYNC_DLY_NUM(0x4b4);
526         dsi->REG_048 &= ~(DSI_R_VIDEO_BIST_EN);
527     } else {
528         dsi->REG_048 = DSI_R_HSYNC_DLY_NUM(0x320);
529     }
530 #ifndef SIMU
531     hal_sys_timer_delay(MS_TO_TICKS(100));
532 #endif
533 }
534 
hal_lcdc_addr_check(uint32_t addr)535 uint32_t hal_lcdc_addr_check(uint32_t addr)
536 {
537 #ifdef CHIP_BEST2003
538     //2003 LCDC don't support ROM and MCU SRAM(0x20000000).
539     if (addr >= DSP_RAM_BASE && addr <= DSP_RAM_BASE + DSP_RAM_SIZE)
540         return 1;
541 #ifdef PSRAM_ENABLE
542     //2003 LCDC access psram die bypas psram'cache
543     //App should invalid framebuffer cache before lcdc_start, if it's located in psram
544     if (addr >= PSRAM_BASE && addr <= PSRAM_BASE + PSRAM_SIZE)
545         return 1;
546 #endif
547 #ifdef PSRAMUHS_ENABLE
548     if (addr >= PSRAMUHS_BASE && addr <= PSRAMUHS_BASE + PSRAMUHS_SIZE)
549         return 1;
550 #endif
551     return 0;
552 #else
553     return 1;
554 #endif
555 }
556 
hal_lcdc_init(const struct HAL_DSI_CFG_T * cfg,const uint8_t * layer0,const uint8_t * layer1,const uint8_t * layer2)557 void hal_lcdc_init(const struct HAL_DSI_CFG_T *cfg, const uint8_t *layer0,
558     const uint8_t *layer1, const uint8_t *layer2)
559 {
560     hal_cmu_lcdc_clock_enable();
561 
562     hal_cmu_lcdc_reset_clear();
563 
564     lcdc->REG_200 = BITFIELD_VAL(LCD_WDMA_IMG_PITCH, cfg->active_width*4);
565     lcdc->REG_208 = LCD_WDMA_BASE_ADDR(0x20000000+0x80000000);
566     lcdc->REG_1A8 = LCD_CLK_INT_DIV(1);
567 
568     lcdc->REG_0E0 = LCD_CFG_DMA_PITCH_Y(cfg->y_mem_pitch) | LCD_CFG_DMA_PITCH_C(cfg->c_mem_pitch);
569     lcdc->REG_0E4 = LCD_CFG_DMA_PITCH_U(cfg->uv_mem_pitch) | LCD_CFG_DMA_PITCH_V(cfg->uv_mem_pitch);
570     lcdc->REG_0E8 = LCD_CFG_DMA_OVSA_HPXL(cfg->image_h_sa) | LCD_CFG_DMA_OVSA_VLN(cfg->image_v_sa);
571     lcdc->REG_0EC = LCD_CFG_DMA_H_PIXEL(cfg->image_width) | LCD_CFG_DMA_V_LINE(cfg->image_height);
572     lcdc->REG_0F0 = LCD_CFG_DMAZM_H_PIXEL(cfg->zm_image_width) | LCD_CFG_DMAZM_V_LINE(cfg->zm_image_height);
573     lcdc->REG_0FC = LCD_CFG_GRA_PITCH(cfg->g_mem_pitch) | LCD_CFG_PN_BKLIGHTDIV(0x4);
574     lcdc->REG_100 = LCD_CFG_GRA_OVSA_HPXL(cfg->graphic_h_sa) | LCD_CFG_GRA_OVSA_VLN(cfg->graphic_v_sa);
575     lcdc->REG_104 = LCD_CFG_GRA_H_PIXEL(cfg->graphic_width) | LCD_CFG_GRA_V_LINE(cfg->graphic_height);
576     lcdc->REG_108 = LCD_CFG_GRAZM_H_PIXEL(cfg->zm_graphic_width) | LCD_CFG_GRAZM_V_LINE(cfg->zm_graphic_height);
577     lcdc->REG_10C = LCD_CFG_HWC_OVSA_HPXL(cfg->cursor_h_sa) | LCD_CFG_HWC_OVSA_VLN(cfg->cursor_v_sa);
578     lcdc->REG_110 = LCD_CFG_HWC_HPXL(cfg->cursor_width) | LCD_CFG_HWC_VLN(cfg->cursor_height);
579     lcdc->REG_114 = LCD_CFG_PN_H_TOTAL(cfg->total_width) | LCD_CFG_PN_V_TOTAL(cfg->total_height);
580     lcdc->REG_118 = LCD_CFG_PN_H_ACTIVE(cfg->active_width) | LCD_CFG_PN_V_ACTIVE(cfg->active_height);
581     lcdc->REG_11C = LCD_CFG_PN_H_FPORCH(cfg->h_front_porch) | LCD_CFG_PN_H_BPORCH(cfg->h_back_porch);
582     lcdc->REG_120 = LCD_CFG_PN_V_FPORCH(cfg->v_front_porch) | LCD_CFG_PN_V_BPORCH(cfg->v_back_porch);
583     //The REG_13C config value should < cfg->total_width.Don't set to a fixed value.
584     lcdc->REG_13C = LCD_CFG_PN_V_SPXLCNT(cfg->total_width -1) | LCD_CFG_PN_V_EPXLCNT(cfg->total_width -1);
585     // lcdc->REG_124 = LCD_CFG_PN_BLANKCOLOR(cfg->blankcolor);
586     lcdc->REG_124 = 0; // FIXME
587     lcdc->REG_1DC = 1 << 24; // fix red/blue mirror
588 
589     lcdc->REG_128 = LCD_CFG_HWC_COLOR1(cfg->hwc_color1);
590     lcdc->REG_12C = LCD_CFG_HWC_COLOR2(cfg->hwc_color2);
591     lcdc->REG_130 = LCD_CFG_PN_ALPHA_Y(cfg->cfg_alpha_y) | LCD_CFG_PN_CKEY_Y(cfg->cfg_ckey_y) |
592         LCD_CFG_PN_CKEY_Y1(cfg->cfg_ckey_y1) | LCD_CFG_PN_CKEY_Y2(cfg->cfg_ckey_y2);
593     lcdc->REG_134 = LCD_CFG_PN_ALPHA_U(cfg->cfg_alpha_u) | LCD_CFG_PN_CKEY_U(cfg->cfg_ckey_u) |
594         LCD_CFG_PN_CKEY_U1(cfg->cfg_ckey_u1) | LCD_CFG_PN_CKEY_U2(cfg->cfg_ckey_u2);
595     lcdc->REG_138 = LCD_CFG_PN_ALPHA_V(cfg->cfg_alpha_v) | LCD_CFG_PN_CKEY_V(cfg->cfg_ckey_v) |
596         LCD_CFG_PN_CKEY_V1(cfg->cfg_ckey_v1) | LCD_CFG_PN_CKEY_V2(cfg->cfg_ckey_v2);
597     lcdc->REG_1AC = LCD_CFG_PN_CONTRAST(cfg->contrast) | LCD_CFG_PN_BRIGHTNESS(cfg->brightness);
598     lcdc->REG_1B0 = LCD_CFG_PN_SATURATION(cfg->saturation) | LCD_CFG_PN_C_MULT_S(cfg->c_mult_s);
599     lcdc->REG_1B4 = LCD_CFG_PN_COS0(cfg->cos0) | LCD_CFG_PN_SIN0(cfg->sin0);
600     lcdc->REG_11C = LCD_CFG_PN_H_FPORCH(cfg->h_front_porch) | LCD_CFG_PN_H_BPORCH(cfg->h_back_porch);
601 
602     lcdc->REG_020 = LCD_CFG_TVD_PITCH_Y(cfg->y_mem_pitch) | LCD_CFG_TVD_PITCH_C(cfg->c_mem_pitch);
603     lcdc->REG_024 = LCD_CFG_TVD_PITCH_U(cfg->uv_mem_pitch) | LCD_CFG_TVD_PITCH_V(cfg->uv_mem_pitch);
604     lcdc->REG_028 = LCD_CFG_TVD_OVSA_HPXL(cfg->image_h_sa) | LCD_CFG_TVD_OVSA_VLN(cfg->image_v_sa);
605     lcdc->REG_02C = LCD_CFG_TVD_H_PIXEL(cfg->image_width) | LCD_CFG_TVD_V_LINE(cfg->image_height);
606     lcdc->REG_030 = LCD_CFG_TVDZM_H_PIXEL(cfg->zm_image_width) | LCD_CFG_TVDZM_V_LINE(cfg->zm_image_height);
607 
608     lcdc->REG_03C = LCD_CFG_TVG_PITCH(cfg->g_tv_mem_pitch);
609     lcdc->REG_040 = LCD_CFG_TVG_OVSA_HPXL(cfg->tvg_h_sa) | LCD_CFG_TVG_OVSA_VLN(cfg->tvg_v_sa);
610     lcdc->REG_044 = LCD_CFG_TVG_H_PIXEL(cfg->tvg_width) | LCD_CFG_TVG_V_LINE(cfg->tvg_height);
611     lcdc->REG_048 = LCD_CFG_TVGZM_H_PIXEL(cfg->zm_tvg_width) | LCD_CFG_TVGZM_V_LINE(cfg->zm_tvg_height);
612     if (layer0) {
613         ASSERT(hal_lcdc_addr_check((uint32_t)layer0), "invalid memory addr:%p", layer0);
614         lcdc->REG_0C0 = LCD_CFG_DMA_SA_Y0((uint32_t)layer0);
615         lcdc->REG_0C4 = LCD_CFG_DMA_SA_U0(0x30000+0x7e000000);
616         lcdc->REG_0C8 = LCD_CFG_DMA_SA_V0(0x400000+0x7e000000);
617         lcdc->REG_0D0 = LCD_CFG_DMA_SA_Y1((uint32_t)layer0);
618 		///TODO: yuv422 from camera
619         if (0) {
620             lcdc->REG_190 = LCD_CFG_YUV2RGB_DMA | LCD_CFG_DMA_SWAPYU | LCD_CFG_DMA_SWAPUV |
621                 LCD_CFG_DMA_ENA | LCD_CFG_DMA_FTOGGLE |
622                 LCD_CFG_DMAFORMAT(mode_yuv422packed);
623         } else {
624             lcdc->REG_190 = LCD_CFG_DMA_ENA | LCD_CFG_DMA_FTOGGLE |
625                 LCD_CFG_DMAFORMAT(mode_rgb888unpacked);
626         }
627     }
628 
629     if (layer1) {
630         ASSERT(hal_lcdc_addr_check((uint32_t)layer1), "invalid memory addr:%p", layer1);
631         lcdc->REG_0F4 = LCD_CFG_GRA_SA0((uint32_t)layer1);
632         lcdc->REG_0F8 = LCD_CFG_GRA_SA1((uint32_t)layer1);
633         lcdc->REG_264 = LCD_CFG_GRA_ENA | LCD_CFG_GRAFORMAT(mode_rgb888unpacked) |
634             LCD_CFG_GRA_FTOGGLE;
635     }
636 
637     if (layer2) {
638         ASSERT(hal_lcdc_addr_check((uint32_t)layer2), "invalid memory addr:%p", layer2);
639         lcdc->REG_034 = LCD_CFG_TVG_SA0((uint32_t)layer2);
640         lcdc->REG_038 = LCD_CFG_TVG_SA1((uint32_t)layer2+368*4);
641         lcdc->REG_080 = LCD_CFG_TVG_ENA | LCD_CFG_YUV2RGB_TVG |
642             LCD_CFG_TVGFORMAT(mode_rgb888unpacked) | LCD_CFG_TVG_FTOGGLE;
643     }
644 
645     //lcdc->REG_260 = LCD_CFG_TVD_ENA | LCD_CFG_ARBFAST_ENA | LCD_CFG_PN_CBSH_ENA | LCD_CFG_ARBFAST_ENA | LCD_CFG_PN_CBSH_ENA;
646 
647     lcdc->REG_1E8 = 0;
648     lcdc->REG_210 = LCD_CFG_VSYNC_TRIG_DISABLE_S | LCD_CFG_VSYNC_TRIG_DISABLE_A |
649         LCD_CFG_BACKLIGHT_EN | LCD_CFG_REG_GEN_FRAME | LCD_CFG_DSI_RD_MEM;
650     if (dsi_mode == DSI_MODE_VIDEO) {
651         lcdc->REG_188 = LCD_CFG_SLV_ENA | LCD_CFG_SMPNMODE(0x3) | LCD_CFG_SLV_ONLY;//disable smart panel
652         lcdc->REG_1B8 |= LCD_CFG_DUMB_ENA;//enable dumb panel
653     } else {
654         lcdc->REG_188 = LCD_CFG_SMPN_ENA | LCD_CFG_SLV_ENA | LCD_CFG_SMPNMODE(0x3) | LCD_CFG_SLV_ONLY;
655     }
656     lcdc->REG_218 = LCD_CFG_STBY_LENGTH(0x80) | LCD_CFG_VSYNC_START_LINE(0x1) | LCD_CFG_VSYNC_END_LINE(0x5);
657     lcdc->REG_21C = LCD_CFG_H_FRONT_PORCH_SMPN(0x20) | LCD_CFG_H_BACK_PORCH_SMPN(0x20) | LCD_CFG_VSYNC_NLINE(0xa);
658     lcdc->REG_220 = LCD_CFG_VSYNC_START_PIX(0x1e) | LCD_CFG_VSYNC_END_PIX(0x1f);
659 
660     lcdc->REG_1C0 = LCD_TVIF_FRAMEDONE_ENA | LCD_TVG_FF_UNDERFLOW_ENA | LCD_TVG_FRAME_IRQ1_ENA |
661         LCD_TVG_FRAME_IRQ0_ENA | LCD_TVSYN_IRQ_ENA | LCD_TVD_FF_UNDERFLOW_ENA |
662         LCD_TVD_FRAME_IRQ1_ENA | LCD_TVD_FRAME_IRQ0_ENA | LCD_ERR_IRQ_ENA |
663         LCD_PWRND_IRQ_ENA | LCD_SPI_IRQ_ENA | LCD_SLV_IRQ_ENA |
664         LCD_HWC_FRAMEDONE_ENA | LCD_TWC_FRAMEDONE_ENA | LCD_DUMB_FRAMEDONE_ENA |
665         LCD_VSYNC_IRQ_ENA | LCD_TVC_FRAMEDONE_ENA | LCD_GRA_FF_UNDERFLOW_ENA |
666         LCD_GRA_FRAME_IRQ1_ENA | LCD_GRA_FRAME_IRQ0_ENA | LCD_M2A_IRQ_ENA |
667         LCD_DMA_FF_UNDERFLOW_ENA | LCD_DMA_FRAME_IRQ1_ENA | LCD_DMA_FRAME_IRQ0_ENA;
668 
669     lcdc->REG_194 = LCD_CFG_PXLMD(0x81) | LCD_CFG_PN_ALPHA(0x9f) | LCD_CFG_PWRDN_ENA |
670         LCD_CFG_GATED_ENA | LCD_CFG_FRAME_TRIG;
671     if (dsi_mode == DSI_MODE_VIDEO) {
672         lcdc->REG_194 |= LCD_CFG_PN_VSYNC_MODE(2);//enable VSYNC signal on dumb panel lane
673     }
674     lcdc->REG_1A8 = LCD_CLK_INT_DIV(1) | LCD_SCLK_SOURCE_SELECT(1);
675 
676     //TE trigger
677     lcdc->REG_188 = SET_BITFIELD(lcdc->REG_188, LCD_CFG_SMPNVSYNC, 1);
678     lcdc->REG_214 = LCD_CFG_HSYNC_LENGTH(5) | LCD_CFG_DEL_NLINE(2);
679     lcdc->REG_210 = SET_BITFIELD(lcdc->REG_210, LCD_CFG_EXTRA_DELAY, 4);
680     if (dsi_mode == DSI_MODE_VIDEO) {
681         lcdc->REG_210 |= LCD_CFG_DSI_SOURCE_SEL;//switch the dumb panel as source
682     }
683     //lcdc->REG_210 &= ~LCD_CFG_NFRAME_ACTIVE(1);//SET_BITFIELD(lcdc->REG_210, LCD_CFG_NFRAME_ACTIVE, 1);
684 
685     //use TE, use 258 as star
686     lcdc->REG_210 &= ~LCD_CFG_REG_GEN_FRAME;
687     //lcdc->REG_210 |= LCD_CFG_REG_GEN_FRAME;	//manual update
688     lcdc->REG_254 |= LCD_CFG_TE_USE_SW;
689 
690     //enable irq whether ther is a TE signal or not
691     lcdc->REG_1C0 = LCD_TWC_FRAMEDONE_ENA | LCD_DUMB_FRAMEDONE_ENA;
692     lcdc->REG_1C4 = 0; //clear
693 
694     NVIC_SetVector(DISPLAY_IRQn, (uint32_t)hal_dsi_unified_irq_handler);
695     NVIC_SetPriority(DISPLAY_IRQn, IRQ_PRIORITY_NORMAL);
696     NVIC_ClearPendingIRQ(DISPLAY_IRQn);
697     NVIC_EnableIRQ(DISPLAY_IRQn);
698 
699 #ifndef SIMU
700     hal_sys_timer_delay(MS_TO_TICKS(10));
701 #endif
702 }
703 
hal_lcdc_update_addr(uint8_t layerId,uint8_t channel,uint32_t addr)704 void hal_lcdc_update_addr(uint8_t layerId, uint8_t channel, uint32_t addr)
705 {
706     ASSERT(hal_lcdc_addr_check(addr), "invalid memory addr:0x%x", addr);
707     switch (layerId)
708     {
709     case 0:
710         if (channel == 0) {
711             lcdc->REG_0C0 = LCD_CFG_DMA_SA_Y0(addr);
712         } else {
713             lcdc->REG_0D0 = LCD_CFG_DMA_SA_Y1(addr);
714         }
715         break;
716     case 1:
717         if (channel == 0) {
718             lcdc->REG_0F4 = LCD_CFG_GRA_SA0(addr);
719         } else {
720             lcdc->REG_0F8 = LCD_CFG_GRA_SA1(addr);
721         }
722         break;
723     case 2:
724         if (channel == 0) {
725             lcdc->REG_034 = LCD_CFG_TVG_SA0(addr);
726         } else {
727             lcdc->REG_038 = LCD_CFG_TVG_SA1(addr);
728         }
729         break;
730     default:
731         TRACE(0, "unknown layer %d", layerId);
732         break;
733     }
734 }
735 
hal_lcdc_set_callback(HAL_DSI_XFER_COMPLETE_CALLBACK_T callback)736 void hal_lcdc_set_callback(HAL_DSI_XFER_COMPLETE_CALLBACK_T callback)
737 {
738     dsi_callback = callback;
739 }
740 
hal_lcdc_gamma_enable(const uint8_t * config_R,const uint8_t * config_G,const uint8_t * config_B)741 void hal_lcdc_gamma_enable(const uint8_t *config_R, const uint8_t *config_G, const uint8_t *config_B)
742 {
743     return ;
744     uint32_t i;
745 
746     lcdc->REG_260 |= LCD_CFG_PN_GAMMA_ENA;
747     for (i = 0; i < 256; ++i) {
748         lcdc->REG_198 = LCD_SRAM_INIT_WR_RD(3) |
749             LCD_CFG_SRAM_ADDR(i) | LCD_CFG_SRAM_ADDR_LCDID(0x0);//R
750         lcdc->REG_19C = LCD_CFG_SRAM_WRDAT(config_R[i]);
751 
752         lcdc->REG_198 = LCD_SRAM_INIT_WR_RD(3) |
753             LCD_CFG_SRAM_ADDR(i) | LCD_CFG_SRAM_ADDR_LCDID(0x1);//G
754         lcdc->REG_19C = LCD_CFG_SRAM_WRDAT(config_G[i]);
755 
756         lcdc->REG_198 = LCD_SRAM_INIT_WR_RD(3) |
757             LCD_CFG_SRAM_ADDR(i) | LCD_CFG_SRAM_ADDR_LCDID(0x2);//B
758         lcdc->REG_19C = LCD_CFG_SRAM_WRDAT(config_B[i]);
759     }
760 }
761 
hal_lcdc_gamma_disable(void)762 void hal_lcdc_gamma_disable(void)
763 {
764     lcdc->REG_260 &= ~LCD_CFG_PN_GAMMA_ENA;
765 }
766 
hal_lcdc_start(void)767 void hal_lcdc_start(void)
768 {
769     //TRACE(0, "START:%u ms", FAST_TICKS_TO_MS(hal_fast_sys_timer_get()));
770     //lcdc->REG_224 = LCD_GEN_FRAME_START(0);
771     lcdc->REG_258 = LCD_CFG_FRAME_VALID(0);
772 }
773 
hal_lcdc_frame_done_irq_disable(void)774 void hal_lcdc_frame_done_irq_disable(void)
775 {
776     lcdc->REG_188 = SET_BITFIELD(lcdc->REG_188, LCD_CFG_SMPNVSYNC, 3);
777 }
778 
hal_lcdc_frame_done_irq_enable(void)779 void hal_lcdc_frame_done_irq_enable(void)
780 {
781     lcdc->REG_188 = SET_BITFIELD(lcdc->REG_188, LCD_CFG_SMPNVSYNC, 1);
782 }
783 
hal_dsi_sleep()784 void hal_dsi_sleep()
785 {
786     dsiphy_sleep();
787     hal_cmu_dsi_sleep();
788 }
789 
hal_dsi_wakeup()790 void hal_dsi_wakeup()
791 {
792     hal_cmu_dsi_wakeup();
793     dsiphy_wakeup();
794 }
795 
hal_dsi_start_hs_clock()796 void hal_dsi_start_hs_clock()
797 {
798     dsi->REG_014 = 1;
799 }
800 
hal_dsi_stop_hs_clock()801 void hal_dsi_stop_hs_clock()
802 {
803     dsi->REG_014 = 0;
804 }
805 
806 #endif
807