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