DISP_STATUS DISP_UpdateScreen(UINT32 x, UINT32 y, UINT32 width, UINT32 height) { LCD_CHECK_RET(LCD_WaitForNotBusy()); if ((lcm_drv->update) && ((lcm_params->type==LCM_TYPE_DBI) || ((lcm_params->type==LCM_TYPE_DSI) && (lcm_params->dsi.mode==CMD_MODE)))) { lcm_drv->update(x, y, width, height); } LCD_CHECK_RET(LCD_SetRoiWindow(x, y, width, height)); LCD_CHECK_RET(LCD_FBSetStartCoord(x, y)); LCD_CHECK_RET(LCD_StartTransfer(FALSE)); if (lcm_params->type==LCM_TYPE_DSI && lcm_params->dsi.mode==CMD_MODE) { DSI_clk_HS_mode(1); DSI_CHECK_RET(DSI_EnableClk()); } else if (lcm_params->type==LCM_TYPE_DSI && lcm_params->dsi.mode!=CMD_MODE) { DSI_clk_HS_mode(1); DPI_CHECK_RET(DPI_EnableClk()); DSI_CHECK_RET(DSI_EnableClk()); } return DISP_STATUS_OK; }
UINT32 mt65xx_disp_get_lcd_time(void) { #if 0 UINT32 time0, time1, lcd_time; mt65xx_disp_update(0, 0, CFG_DISPLAY_WIDTH, CFG_DISPLAY_HEIGHT); LCD_CHECK_RET(LCD_WaitForNotBusy()); time0 = gpt4_tick2time_us(gpt4_get_current_tick()); LCD_CHECK_RET(LCD_StartTransfer(FALSE)); if (lcm_params->type==LCM_TYPE_DSI && lcm_params->dsi.mode==CMD_MODE) { DSI_clk_HS_mode(1); DSI_CHECK_RET(DSI_EnableClk()); } else if (lcm_params->type==LCM_TYPE_DSI && lcm_params->dsi.mode!=CMD_MODE) { DSI_clk_HS_mode(1); DPI_CHECK_RET(DPI_EnableClk()); DSI_CHECK_RET(DSI_EnableClk()); } LCD_CHECK_RET(LCD_WaitForNotBusy()); time1 = gpt4_tick2time_us(gpt4_get_current_tick()); lcd_time = time1 - time0; printf("lcd one %d \n", lcd_time); if(0 != lcd_time) return (100000000/lcd_time); else #endif return (6000); }
// protected by sem_flipping, sem_early_suspend, sem_overlay_buffer, sem_update_screen static DISP_STATUS dsi_update_screen(BOOL isMuextLocked) { disp_drv_dsi_init_context(); DSI_CHECK_RET(DSI_enable_MIPI_txio(TRUE)); //DSI_CHECK_RET(DSI_handle_TE()); DSI_SetMode(lcm_params->dsi.mode); #ifndef MT65XX_NEW_DISP LCD_CHECK_RET(LCD_StartTransfer(FALSE)); #endif if (lcm_params->type==LCM_TYPE_DSI && lcm_params->dsi.mode == CMD_MODE && !DDMS_capturing) { DSI_clk_HS_mode(1); #ifdef MT65XX_NEW_DISP DSI_CHECK_RET(DSI_StartTransfer(isMuextLocked)); #else DSI_CHECK_RET(DSI_EnableClk()); #endif } else if (lcm_params->type==LCM_TYPE_DSI && lcm_params->dsi.mode != CMD_MODE && !DDMS_capturing) { DSI_clk_HS_mode(1); #ifndef MT65XX_NEW_DISP DPI_CHECK_RET(DPI_EnableClk()); DSI_CHECK_RET(DSI_EnableClk()); #else DSI_CHECK_RET(DSI_StartTransfer(isMuextLocked)); #endif #ifndef BUILD_UBOOT is_video_mode_running = true; #ifndef MT65XX_NEW_DISP if(lcm_params->dsi.noncont_clock) DSI_set_noncont_clk(true, lcm_params->dsi.noncont_clock_period); if(lcm_params->dsi.lcm_int_te_monitor) DSI_set_int_TE(true, lcm_params->dsi.lcm_int_te_period); #endif #endif } if (DDMS_capturing) DISP_LOG_PRINT(ANDROID_LOG_INFO, "DSI", "[DISP] kernel - dsi_update_screen. DDMS is capturing. Skip one frame. \n"); return DISP_STATUS_OK; }
// protected by sem_flipping, sem_early_suspend, sem_overlay_buffer, sem_update_screen static DISP_STATUS dsi_update_screen(void) { disp_drv_dsi_init_context(); DSI_CHECK_RET(DSI_enable_MIPI_txio(TRUE)); //DSI_CHECK_RET(DSI_handle_TE()); DSI_SetMode(lcm_params->dsi.mode); LCD_CHECK_RET(LCD_StartTransfer(FALSE)); if (lcm_params->type==LCM_TYPE_DSI && lcm_params->dsi.mode == CMD_MODE && !DDMS_capturing) { DSI_clk_HS_mode(1); DSI_CHECK_RET(DSI_EnableClk()); } else if (lcm_params->type==LCM_TYPE_DSI && lcm_params->dsi.mode != CMD_MODE && !DDMS_capturing) { #ifndef BUILD_UBOOT spin_lock(&g_handle_esd_lock); #endif DSI_clk_HS_mode(1); DPI_CHECK_RET(DPI_EnableClk()); DSI_CHECK_RET(DSI_EnableClk()); #ifndef BUILD_UBOOT dsi_vdo_streaming = true; if(lcm_params->dsi.noncont_clock) DSI_set_noncont_clk(true, lcm_params->dsi.noncont_clock_period); if(lcm_params->dsi.lcm_int_te_monitor) DSI_set_int_TE(true, lcm_params->dsi.lcm_int_te_period); spin_unlock(&g_handle_esd_lock); #endif } if (DDMS_capturing) DISP_LOG_PRINT(ANDROID_LOG_INFO, "DSI", "[DISP] kernel - dsi_update_screen. DDMS is capturing. Skip one frame. \n"); return DISP_STATUS_OK; }
void DSI_set_cmdq_V2(unsigned cmd, unsigned char count, unsigned char *para_list, unsigned char force_update) { UINT32 i, layer, layer_state, lane_num; UINT32 goto_addr, mask_para, set_para; UINT32 fbPhysAddr, fbVirAddr; DSI_T0_INS t0; DSI_T1_INS t1; DSI_T2_INS t2; _WaitForEngineNotBusy(); if (count > 59) { UINT32 pixel = count/3 + ((count%3) ? 1 : 0); LCD_REG_LAYER fb_layer_info; LCD_REG_DSI_DC dsi_info; // backup layer state. layer_state = AS_UINT32(&LCD_REG->WROI_CONTROL) & 0xFC000000; // backup FB layer info. memcpy((void *)&fb_layer_info, (void *)&LCD_REG->LAYER[FB_LAYER], sizeof(LCD_REG_LAYER)); // backup LCD-DSI I/F configuration. dsi_info = LCD_REG->DS_DSI_CON; // backup lane number. lane_num = DSI_REG->DSI_TXRX_CTRL.LANE_NUM; // HW limitation. // LP type-1 command can't go with 2 lanes. So we must switch to lane mode. DSI_REG->DSI_TXRX_CTRL.LANE_NUM = 1; DSI_PHY_REG->MIPITX_CON1.RG_DSI_CK_SEL = 0; // Modify LCD-DSI configuration LCD_REG->DS_DSI_CON.DC_DSI = TRUE; // Let LSB of RGB(BGR in buffer) first. LCD_REG->DS_DSI_CON.RGB_SWAP = LCD_DSI_IF_FMT_COLOR_ORDER_BGR; // Let parameters be in unit of byte. LCD_REG->DS_DSI_CON.CLR_FMT = LCD_DSI_IF_FORMAT_RGB888; // HW limitation // It makes package numbers > 1. LCD_REG->DS_DSI_CON.PACKET_SIZE = 30; // Start of Enable only one layer (FB layer) to push data to DSI LCD_CHECK_RET(LCD_LayerEnable(LCD_LAYER_ALL, FALSE)); LCD_CHECK_RET(LCD_LayerEnable(FB_LAYER, TRUE)); LCD_CHECK_RET(LCD_SetRoiWindow(0, 0, pixel, 1)); LCD_CHECK_RET(LCD_SetBackgroundColor(0)); // operates on FB layer { extern void disp_get_fb_address(UINT32 *fbVirAddr, UINT32 *fbPhysAddr); disp_get_fb_address(&fbVirAddr ,&fbPhysAddr); // copy parameters to FB layer buffer. memcpy((void *)fbVirAddr, (void *)para_list, count); LCD_REG->LAYER[FB_LAYER].ADDRESS = fbPhysAddr; } LCD_CHECK_RET(LCD_LayerSetFormat(FB_LAYER, LCD_LAYER_FORMAT_RGB888)); LCD_CHECK_RET(LCD_LayerSetPitch(FB_LAYER, pixel*3)); LCD_CHECK_RET(LCD_LayerSetOffset(FB_LAYER, 0, 0)); LCD_CHECK_RET(LCD_LayerSetSize(FB_LAYER, pixel, 1)); // End of Enable only one layer (FB layer) to push data to DSI t1.CONFG = 1; t1.Data_ID = DSI_DCS_LONG_PACKET_ID; t1.mem_start0 = (cmd&0xFF); t1.mem_start1 = (cmd>>8); OUTREG32(&DSI_CMDQ_REG->data0[0], AS_UINT32(&t1)); OUTREG32(&DSI_REG->DSI_CMDQ_SIZE, 1); DISP_LOG_PRINT(ANDROID_LOG_INFO, "DSI", "[DISP] - kernel - DSI_set_cmdq_V2. command(0x%x) parameter count = %d > 59, pixel = %d \n", cmd, count, pixel); DISP_LOG_PRINT(ANDROID_LOG_INFO, "DSI", "[DISP] - kernel - command queue only support 16 x 4 bytes. Header used 4 byte. DCS used 1 byte. If parameter > 59 byte, work around by Type-1 command. \n"); DISP_LOG_PRINT(ANDROID_LOG_INFO, "DSI", "para_list[%d] = {", count); for (i = 0; i < count; i++) DISP_LOG_PRINT(ANDROID_LOG_INFO, "DSI", "0x%02x, ", para_list[i]); DISP_LOG_PRINT(ANDROID_LOG_INFO, "DSI", "} \n"); LCD_M4U_On(0); if(force_update) { LCD_CHECK_RET(LCD_StartTransfer(FALSE)); DSI_EnableClk(); } _WaitForEngineNotBusy(); LCD_M4U_On(1); // restore FB layer info. memcpy((void *)&LCD_REG->LAYER[FB_LAYER], (void *)&fb_layer_info, sizeof(LCD_REG_LAYER)); // restore LCD-DSI I/F configuration. LCD_REG->DS_DSI_CON = dsi_info; // restore lane number. DSI_REG->DSI_TXRX_CTRL.LANE_NUM = lane_num; DSI_PHY_REG->MIPITX_CON1.RG_DSI_CK_SEL = (lane_num - 1); // restore layer state. for(layer=LCD_LAYER_0; layer<LCD_LAYER_NUM; layer++) { if(layer_state&(0x80000000>>layer)) LCD_CHECK_RET(LCD_LayerEnable(layer, TRUE)); else LCD_CHECK_RET(LCD_LayerEnable(layer, FALSE)); }
static irqreturn_t _DPI_InterruptHandler(int irq, void *dev_id) { static int counter = 0; DPI_REG_INTERRUPT status = DPI_REG->INT_STATUS; // if (status.FIFO_EMPTY) ++ counter; if(status.VSYNC) { if(dpiIntCallback) dpiIntCallback(DISP_DPI_VSYNC_INT); #ifndef BUILD_UBOOT if(atomic_read(&wait_dpi_vsync)){ if(-1 != hrtimer_try_to_cancel(&hrtimer_vsync_dpi)){ atomic_set(&wait_dpi_vsync, 0); atomic_set(&dpi_vsync, 1); wake_up_interruptible(&_vsync_wait_queue_dpi); hrtimer_start(&hrtimer_vsync_dpi, ktime_set(0, VSYNC_US_TO_NS(vsync_timer_dpi)), HRTIMER_MODE_REL); } } #endif } if (status.VSYNC && counter) { DISP_LOG_PRINT(ANDROID_LOG_ERROR, "DPI", "[Error] DPI FIFO is empty, " "received %d times interrupt !!!\n", counter); counter = 0; } if (status.FIFO_EMPTY) { int need_reset = 0; unsigned long long temp = sched_clock(); unsigned int debug_while_loop_cnt = 0; volatile unsigned int dsi_state = INREG32(DSI_BASE+0x154); if((dsi_state & 0x1ff) == 0x80) { auto_sync_reset_count++; if(auto_sync_reset_count == 10) { auto_sync_reset_count = 0; need_reset = 2; } } else { auto_sync_reset_count = 0; } //printk("gmce,0x%08x, %d\n",(INREG32(DSI_BASE+0x154))&0x1ff, (unsigned int)(temp - last_fifo_empty_stamp)); if(_fifo_empty_monitor_insert((unsigned int)(temp - last_fifo_empty_stamp))) { need_reset = 1; } last_fifo_empty_stamp = temp; if(need_reset) { unsigned int mode, suspend; mode = DSI_GetMode(); suspend = DISP_GetSuspendMode(); if ((mode != CMD_MODE) && !suspend) { DPI_DisableClk(); #if 0 while(1) { debug_while_loop_cnt++; dsi_state = INREG32(DSI_BASE+0x154); if((dsi_state &0x1ff) == 0x100) break; if(debug_while_loop_cnt > 0x1000000) { printk("FATAL Error!! dsi in vact when dpi fifo empty, and can't into vfp until 0x100000 loops!!\n"); } } #endif DSI_clk_HS_mode(0); DSI_SetMode(CMD_MODE); DSI_Reset(); DSI_SetMode(SYNC_PULSE_VDO_MODE); DSI_clk_HS_mode(1); DPI_EnableClk(); DSI_EnableClk(); } printk("[DSI/DPI]reset[%d] mode[%d], suspend[%d]\n", need_reset, mode, suspend); need_reset = 0; } } _DPI_LogRefreshRate(status); OUTREG32(&DPI_REG->INT_STATUS, 0); return IRQ_HANDLED; }
// protected by sem_early_suspend, sem_update_screen static DISP_STATUS dsi_enable_power(BOOL enable) { disp_drv_dsi_init_context(); if(lcm_params->dsi.mode == CMD_MODE) { if (enable) { #if 0 // Switch bus to MIPI TX. DSI_CHECK_RET(DSI_enable_MIPI_txio(TRUE)); DSI_PHY_clk_switch(TRUE, lcm_params); DSI_PHY_clk_setting(lcm_params->dsi.pll_div1, lcm_params->dsi.pll_div2, lcm_params->dsi.LANE_NUM); DSI_CHECK_RET(DSI_PowerOn()); DSI_WaitForNotBusy(); DSI_clk_HS_mode(0); DSI_clk_ULP_mode(0); DSI_lane0_ULP_mode(0); DSI_Reset(); LCD_CHECK_RET(LCD_PowerOn()); #else #ifndef MT65XX_NEW_DISP DSI_PHY_clk_switch(TRUE, lcm_params); DSI_CHECK_RET(DSI_PowerOn()); if(Need_Wait_ULPS()) Wait_ULPS_Mode(); DSI_PHY_clk_setting(lcm_params->dsi.pll_div1, lcm_params->dsi.pll_div2, lcm_params->dsi.LANE_NUM); #else // enable MMSYS CG DSI_CHECK_RET(DSI_PowerOn()); // initialize clock setting DSI_PHY_clk_setting(lcm_params); // initialize dsi timing DSI_PHY_TIMCONFIG(lcm_params); // restore dsi register DSI_CHECK_RET(DSI_RestoreRegisters()); // enable sleep-out mode DSI_CHECK_RET(DSI_SleepOut()); // enter HS mode DSI_PHY_clk_switch(TRUE, lcm_params); // enter wakeup DSI_CHECK_RET(DSI_Wakeup()); // enable clock DSI_CHECK_RET(DSI_EnableClk()); // engine reset DSI_Reset(); #endif DSI_CHECK_RET(DSI_enable_MIPI_txio(TRUE)); #ifndef MT65XX_NEW_DISP Wait_WakeUp(); #endif #endif } else { // backup dsi register DSI_CHECK_RET(DSI_WaitForEngineNotBusy()); DSI_CHECK_RET(DSI_BackupRegisters()); // enter ULPS mode DSI_clk_ULP_mode(1); DSI_lane0_ULP_mode(1); mdelay(1); // disable engine clock DSI_CHECK_RET(DSI_DisableClk()); // disable CG DSI_CHECK_RET(DSI_PowerOff()); // disable mipi pll DSI_PHY_clk_switch(FALSE, lcm_params); // Switch bus to GPIO, then power level will be decided by GPIO setting. DSI_CHECK_RET(DSI_enable_MIPI_txio(FALSE)); } } else { if (enable) { #if 0 // Switch bus to MIPI TX. DSI_CHECK_RET(DSI_enable_MIPI_txio(TRUE)); DSI_PHY_clk_switch(TRUE, lcm_params); DSI_PHY_clk_setting(lcm_params->dsi.pll_div1, lcm_params->dsi.pll_div2, lcm_params->dsi.LANE_NUM); DSI_CHECK_RET(DSI_PowerOn()); DSI_clk_ULP_mode(0); DSI_lane0_ULP_mode(0); DSI_clk_HS_mode(0); DSI_Reset(); DPI_CHECK_RET(DPI_PowerOn()); LCD_CHECK_RET(LCD_PowerOn()); #else #ifndef MT65XX_NEW_DISP DSI_PHY_clk_switch(TRUE, lcm_params); DSI_CHECK_RET(DSI_PowerOn()); if(Need_Wait_ULPS()) Wait_ULPS_Mode(); DSI_PHY_clk_setting(lcm_params->dsi.pll_div1, lcm_params->dsi.pll_div2, lcm_params->dsi.LANE_NUM); #else needStartDSI = true; // enable MMSYS CG DSI_CHECK_RET(DSI_PowerOn()); // initialize clock setting DSI_PHY_clk_setting(lcm_params); // initialize dsi timing DSI_PHY_TIMCONFIG(lcm_params); // restore dsi register DSI_CHECK_RET(DSI_RestoreRegisters()); // enable sleep-out mode DSI_CHECK_RET(DSI_SleepOut()); // enter HS mode DSI_PHY_clk_switch(TRUE, lcm_params); // enter wakeup DSI_CHECK_RET(DSI_Wakeup()); // enable clock DSI_CHECK_RET(DSI_EnableClk()); // engine reset DSI_Reset(); #endif DSI_CHECK_RET(DSI_enable_MIPI_txio(TRUE)); #ifndef MT65XX_NEW_DISP Wait_WakeUp(); #endif #endif } else { #ifndef BUILD_UBOOT is_video_mode_running = false; if(lcm_params->dsi.noncont_clock) DSI_set_noncont_clk(false, lcm_params->dsi.noncont_clock_period); if(lcm_params->dsi.lcm_int_te_monitor) DSI_set_int_TE(false, lcm_params->dsi.lcm_int_te_period); #endif // backup dsi register DSI_CHECK_RET(DSI_WaitForEngineNotBusy()); DSI_CHECK_RET(DSI_BackupRegisters()); // enter ULPS mode DSI_clk_ULP_mode(1); DSI_lane0_ULP_mode(1); mdelay(1); // disable engine clock DSI_CHECK_RET(DSI_DisableClk()); // disable CG DSI_CHECK_RET(DSI_PowerOff()); // disable mipi pll DSI_PHY_clk_switch(FALSE, lcm_params); // Switch bus to GPIO, then power level will be decided by GPIO setting. DSI_CHECK_RET(DSI_enable_MIPI_txio(FALSE)); } } return DISP_STATUS_OK; }
// protected by sem_early_suspend, sem_update_screen static DISP_STATUS dsi_enable_power(BOOL enable) { disp_drv_dsi_init_context(); if(lcm_params->dsi.mode == CMD_MODE) { if (enable) { // enable MMSYS CG DSI_CHECK_RET(DSI_PowerOn()); // initialize clock setting DSI_PHY_clk_setting(lcm_params); // restore dsi register DSI_CHECK_RET(DSI_RestoreRegisters()); // enable sleep-out mode DSI_CHECK_RET(DSI_SleepOut()); // enter HS mode DSI_PHY_clk_switch(1); // enter wakeup DSI_CHECK_RET(DSI_Wakeup()); // enable clock DSI_CHECK_RET(DSI_EnableClk()); DSI_CHECK_RET(DSI_enable_MIPI_txio(TRUE)); DSI_Reset(); } else { // backup dsi register DSI_CHECK_RET(DSI_WaitForNotBusy()); DSI_CHECK_RET(DSI_BackupRegisters()); // enter ULPS mode DSI_clk_ULP_mode(1); DSI_lane0_ULP_mode(1); DSI_clk_HS_mode(0); // disable clock DSI_CHECK_RET(DSI_DisableClk()); DSI_CHECK_RET(DSI_PowerOff()); // disable mipi pll DSI_PHY_clk_switch(0); // Switch bus to GPIO, then power level will be decided by GPIO setting. DSI_CHECK_RET(DSI_enable_MIPI_txio(FALSE)); } } else { if (enable) { // enable MMSYS CG DSI_CHECK_RET(DSI_PowerOn()); // initialize clock setting DSI_PHY_clk_setting(lcm_params); // restore dsi register DSI_CHECK_RET(DSI_RestoreRegisters()); // enable sleep-out mode DSI_CHECK_RET(DSI_SleepOut()); // enter HS mode DSI_PHY_clk_switch(1); // enter wakeup DSI_CHECK_RET(DSI_Wakeup()); DSI_clk_HS_mode(0); // enable clock DSI_CHECK_RET(DSI_EnableClk()); DSI_CHECK_RET(DSI_enable_MIPI_txio(TRUE)); DSI_Reset(); needStartDSI = true; } else { is_video_mode_running = false; // backup dsi register DSI_CHECK_RET(DSI_WaitForNotBusy()); DSI_CHECK_RET(DSI_BackupRegisters()); // enter ULPS mode DSI_clk_ULP_mode(1); DSI_lane0_ULP_mode(1); // disable clock DSI_CHECK_RET(DSI_DisableClk()); DSI_CHECK_RET(DSI_PowerOff()); // disable mipi pll DSI_PHY_clk_switch(0); // Switch bus to GPIO, then power level will be decided by GPIO setting. DSI_CHECK_RET(DSI_enable_MIPI_txio(FALSE)); } } return DISP_STATUS_OK; }