diff --git a/msm/dsi/dsi_ctrl.c b/msm/dsi/dsi_ctrl.c index 9106cbd5b2aa..9e2dce8d03f5 100644 --- a/msm/dsi/dsi_ctrl.c +++ b/msm/dsi/dsi_ctrl.c @@ -1339,6 +1339,25 @@ static void dsi_configure_command_scheduling(struct dsi_ctrl *dsi_ctrl, sched_line_no, window); } +static u32 calculate_schedule_line(struct dsi_ctrl *dsi_ctrl, u32 flags) +{ + u32 line_no = 0x1; + struct dsi_mode_info *timing; + + /* check if custom dma scheduling line needed */ + if ((dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE) && + (flags & DSI_CTRL_CMD_CUSTOM_DMA_SCHED)) + line_no = dsi_ctrl->host_config.common_config.dma_sched_line; + + timing = &(dsi_ctrl->host_config.video_timing); + + if (timing) + line_no += timing->v_back_porch + timing->v_sync_width + + timing->v_active; + + return line_no; +} + static void dsi_kickoff_msg_tx(struct dsi_ctrl *dsi_ctrl, const struct mipi_dsi_msg *msg, struct dsi_ctrl_cmd_dma_fifo_info *cmd, @@ -3391,6 +3410,10 @@ int dsi_ctrl_cmd_tx_trigger(struct dsi_ctrl *dsi_ctrl, u32 flags) { int rc = 0; struct dsi_ctrl_hw_ops dsi_hw_ops; + u32 v_total = 0, fps = 0, cur_line = 0, mem_latency_us = 100; + u32 line_time = 0, schedule_line = 0x1, latency_by_line = 0; + struct dsi_mode_info *timing; + unsigned long flag; if (!dsi_ctrl) { DSI_CTRL_ERR(dsi_ctrl, "Invalid params\n"); @@ -3406,6 +3429,18 @@ int dsi_ctrl_cmd_tx_trigger(struct dsi_ctrl *dsi_ctrl, u32 flags) mutex_lock(&dsi_ctrl->ctrl_lock); + timing = &(dsi_ctrl->host_config.video_timing); + + if (timing && + (dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE)) { + v_total = timing->v_sync_width + timing->v_back_porch + + timing->v_front_porch + timing->v_active; + fps = timing->refresh_rate; + schedule_line = calculate_schedule_line(dsi_ctrl, flags); + line_time = (1000000 / fps) / v_total; + latency_by_line = CEIL(mem_latency_us, line_time); + } + if (!(flags & DSI_CTRL_CMD_BROADCAST_MASTER)) { dsi_hw_ops.trigger_command_dma(&dsi_ctrl->hw); if (dsi_ctrl->enable_cmd_dma_stats) { @@ -3428,7 +3463,35 @@ int dsi_ctrl_cmd_tx_trigger(struct dsi_ctrl *dsi_ctrl, u32 flags) reinit_completion(&dsi_ctrl->irq_info.cmd_dma_done); /* trigger command */ - dsi_hw_ops.trigger_command_dma(&dsi_ctrl->hw); + if ((dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE) && + dsi_hw_ops.schedule_dma_cmd && + (dsi_ctrl->current_state.vid_engine_state == + DSI_CTRL_ENGINE_ON)) { + /* + * This change reads the video line count from + * MDP_INTF_LINE_COUNT register and checks whether + * DMA trigger happens close to the schedule line. + * If it is not close to the schedule line, then DMA + * command transfer is triggered. + */ + while (1) { + local_irq_save(flag); + cur_line = + dsi_hw_ops.log_line_count(&dsi_ctrl->hw, + dsi_ctrl->cmd_mode); + if (cur_line < + (schedule_line - latency_by_line) || + cur_line > (schedule_line + 1)) { + dsi_hw_ops.trigger_command_dma( + &dsi_ctrl->hw); + local_irq_restore(flag); + break; + } + local_irq_restore(flag); + udelay(1000); + } + } else + dsi_hw_ops.trigger_command_dma(&dsi_ctrl->hw); if (dsi_ctrl->enable_cmd_dma_stats) { u32 reg = dsi_hw_ops.log_line_count(&dsi_ctrl->hw, diff --git a/msm/dsi/dsi_ctrl_hw_cmn.c b/msm/dsi/dsi_ctrl_hw_cmn.c index 1a5aaf1cca26..040e20396df4 100644 --- a/msm/dsi/dsi_ctrl_hw_cmn.c +++ b/msm/dsi/dsi_ctrl_hw_cmn.c @@ -845,7 +845,6 @@ void dsi_ctrl_hw_cmn_reset_cmd_fifo(struct dsi_ctrl_hw *ctrl) void dsi_ctrl_hw_cmn_trigger_command_dma(struct dsi_ctrl_hw *ctrl) { DSI_W32(ctrl, DSI_CMD_MODE_DMA_SW_TRIGGER, 0x1); - DSI_CTRL_HW_DBG(ctrl, "CMD DMA triggered\n"); } /**