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