diff --git a/msm/dsi/dsi_catalog.c b/msm/dsi/dsi_catalog.c index 37a790cc65..495b4b180e 100644 --- a/msm/dsi/dsi_catalog.c +++ b/msm/dsi/dsi_catalog.c @@ -30,6 +30,7 @@ static void dsi_catalog_cmn_init(struct dsi_ctrl_hw *ctrl, ctrl->ops.reset_cmd_fifo = dsi_ctrl_hw_cmn_reset_cmd_fifo; ctrl->ops.trigger_command_dma = dsi_ctrl_hw_cmn_trigger_command_dma; ctrl->ops.get_interrupt_status = dsi_ctrl_hw_cmn_get_interrupt_status; + ctrl->ops.poll_dma_status = dsi_ctrl_hw_cmn_poll_dma_status; ctrl->ops.get_error_status = dsi_ctrl_hw_cmn_get_error_status; ctrl->ops.clear_error_status = dsi_ctrl_hw_cmn_clear_error_status; ctrl->ops.clear_interrupt_status = diff --git a/msm/dsi/dsi_catalog.h b/msm/dsi/dsi_catalog.h index 7ca0dac0b2..1e02beb50c 100644 --- a/msm/dsi/dsi_catalog.h +++ b/msm/dsi/dsi_catalog.h @@ -128,6 +128,7 @@ void dsi_phy_hw_v4_0_commit_phy_timing(struct dsi_phy_hw *phy, /* DSI controller common ops */ u32 dsi_ctrl_hw_cmn_get_interrupt_status(struct dsi_ctrl_hw *ctrl); +u32 dsi_ctrl_hw_cmn_poll_dma_status(struct dsi_ctrl_hw *ctrl); void dsi_ctrl_hw_cmn_clear_interrupt_status(struct dsi_ctrl_hw *ctrl, u32 ints); void dsi_ctrl_hw_cmn_enable_status_interrupts(struct dsi_ctrl_hw *ctrl, u32 ints); diff --git a/msm/dsi/dsi_ctrl.c b/msm/dsi/dsi_ctrl.c index adf4c6ccc3..fc2e8b362d 100644 --- a/msm/dsi/dsi_ctrl.c +++ b/msm/dsi/dsi_ctrl.c @@ -410,24 +410,48 @@ static void dsi_ctrl_dma_cmd_wait_for_done(struct dsi_ctrl *dsi_ctrl) } +/** + * dsi_ctrl_clear_dma_status - API to clear DMA status + * @dsi_ctrl: DSI controller handle. + */ +static void dsi_ctrl_clear_dma_status(struct dsi_ctrl *dsi_ctrl) +{ + struct dsi_ctrl_hw_ops dsi_hw_ops; + u32 status = 0; + + if (!dsi_ctrl) { + DSI_CTRL_ERR(dsi_ctrl, "Invalid params\n"); + return; + } + + + dsi_hw_ops = dsi_ctrl->hw.ops; + + status = dsi_hw_ops.poll_dma_status(&dsi_ctrl->hw); + SDE_EVT32(dsi_ctrl->cell_index, SDE_EVTLOG_FUNC_ENTRY, status); + + status |= (DSI_CMD_MODE_DMA_DONE | DSI_BTA_DONE); + dsi_hw_ops.clear_interrupt_status(&dsi_ctrl->hw, status); + +} + static void dsi_ctrl_post_cmd_transfer(struct dsi_ctrl *dsi_ctrl) { int rc = 0; struct dsi_clk_ctrl_info clk_info; - bool skip_wait_for_done = false; u32 mask = BIT(DSI_FIFO_OVERFLOW); mutex_lock(&dsi_ctrl->ctrl_lock); SDE_EVT32(SDE_EVTLOG_FUNC_ENTRY, dsi_ctrl->cell_index, dsi_ctrl->pending_cmd_flags); - /* In case of broadcast messages, we needn't wait on the slave controller */ + /* In case of broadcast messages, we poll on the slave controller. */ if ((dsi_ctrl->pending_cmd_flags & DSI_CTRL_CMD_BROADCAST) && - !(dsi_ctrl->pending_cmd_flags & DSI_CTRL_CMD_BROADCAST_MASTER)) - skip_wait_for_done = true; - - if (!skip_wait_for_done) + !(dsi_ctrl->pending_cmd_flags & DSI_CTRL_CMD_BROADCAST_MASTER)) { + dsi_ctrl_clear_dma_status(dsi_ctrl); + } else { dsi_ctrl_dma_cmd_wait_for_done(dsi_ctrl); + } /* Command engine disable, unmask overflow, remove vote on clocks and gdsc */ rc = dsi_ctrl_set_cmd_engine_state(dsi_ctrl, DSI_CTRL_ENGINE_OFF, false); diff --git a/msm/dsi/dsi_ctrl_hw.h b/msm/dsi/dsi_ctrl_hw.h index a1a7cf1bc9..ea50619612 100644 --- a/msm/dsi/dsi_ctrl_hw.h +++ b/msm/dsi/dsi_ctrl_hw.h @@ -643,6 +643,12 @@ struct dsi_ctrl_hw_ops { */ void (*clear_interrupt_status)(struct dsi_ctrl_hw *ctrl, u32 ints); + /** + * poll_dma_status()- API to poll DMA status + * @ctrl: Pointer to the controller host hardware. + */ + u32 (*poll_dma_status)(struct dsi_ctrl_hw *ctrl); + /** * enable_status_interrupts() - enable the specified interrupts * @ctrl: Pointer to the controller host hardware. diff --git a/msm/dsi/dsi_ctrl_hw_cmn.c b/msm/dsi/dsi_ctrl_hw_cmn.c index f48c35d909..ef39458947 100644 --- a/msm/dsi/dsi_ctrl_hw_cmn.c +++ b/msm/dsi/dsi_ctrl_hw_cmn.c @@ -945,6 +945,29 @@ u32 dsi_ctrl_hw_cmn_get_cmd_read_data(struct dsi_ctrl_hw *ctrl, return rx_byte; } +/** + * poll_dma_status() - API to poll DMA status + * @ctrl: Pointer to the controller host hardware. + * + * Return: DMA status. + */ +u32 dsi_ctrl_hw_cmn_poll_dma_status(struct dsi_ctrl_hw *ctrl) +{ + int rc = 0; + u32 status; + u32 const delay_us = 10; + u32 const timeout_us = 5000; + + rc = readl_poll_timeout_atomic(ctrl->base + DSI_INT_CTRL, status, + ((status & DSI_CMD_MODE_DMA_DONE) > 0), delay_us, timeout_us); + if (rc) { + DSI_CTRL_HW_DBG(ctrl, "CMD_MODE_DMA_DONE failed\n"); + status = 0; + } + + return status; +} + /** * get_interrupt_status() - returns the interrupt status * @ctrl: Pointer to the controller host hardware.