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