/* * mdss_check_dsi_ctrl_status() - Check MDP5 DSI controller status periodically. * @work : dsi controller status data * @interval : duration in milliseconds to schedule work queue * * This function calls check_status API on DSI controller to send the BTA * command. If DSI controller fails to acknowledge the BTA command, it sends * the PANEL_ALIVE=0 status to HAL layer. */ void mdss_check_dsi_ctrl_status(struct work_struct *work, uint32_t interval) { struct dsi_status_data *pstatus_data = NULL; struct mdss_panel_data *pdata = NULL; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; struct mdss_overlay_private *mdp5_data = NULL; struct mdss_mdp_ctl *ctl = NULL; int ret = 0; pstatus_data = container_of(to_delayed_work(work), struct dsi_status_data, check_status); if (!pstatus_data || !(pstatus_data->mfd)) { pr_err("%s: mfd not available\n", __func__); return; } pdata = dev_get_platdata(&pstatus_data->mfd->pdev->dev); if (!pdata) { pr_err("%s: Panel data not available\n", __func__); return; } ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); if (!ctrl_pdata || (!ctrl_pdata->check_status && (ctrl_pdata->status_mode != ESD_TE))) { pr_err("%s: DSI ctrl or status_check callback not available\n", __func__); return; } mdp5_data = mfd_to_mdp5_data(pstatus_data->mfd); ctl = mfd_to_ctl(pstatus_data->mfd); if (!ctl) { pr_err("%s: Display is off\n", __func__); return; } if (ctl->power_state == MDSS_PANEL_POWER_OFF) { schedule_delayed_work(&pstatus_data->check_status, msecs_to_jiffies(interval)); pr_debug("%s: ctl not powered on\n", __func__); return; } if (ctrl_pdata->status_mode == ESD_TE) { mdss_check_te_status(ctrl_pdata, pstatus_data, interval); return; } mutex_lock(&ctrl_pdata->mutex); if (ctl->shared_lock) mutex_lock(ctl->shared_lock); mutex_lock(&mdp5_data->ov_lock); if (pstatus_data->mfd->shutdown_pending) { mutex_unlock(&mdp5_data->ov_lock); if (ctl->shared_lock) mutex_unlock(ctl->shared_lock); mutex_unlock(&ctrl_pdata->mutex); pr_err("%s: DSI turning off, avoiding panel status check\n", __func__); return; } /* * For the command mode panels, we return pan display * IOCTL on vsync interrupt. So, after vsync interrupt comes * and when DMA_P is in progress, if the panel stops responding * and if we trigger BTA before DMA_P finishes, then the DSI * FIFO will not be cleared since the DSI data bus control * doesn't come back to the host after BTA. This may cause the * display reset not to be proper. Hence, wait for DMA_P done * for command mode panels before triggering BTA. */ if (ctl->wait_pingpong) ctl->wait_pingpong(ctl, NULL); pr_debug("%s: DSI ctrl wait for ping pong done\n", __func__); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON); ret = ctrl_pdata->check_status(ctrl_pdata); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF); mutex_unlock(&mdp5_data->ov_lock); if (ctl->shared_lock) mutex_unlock(ctl->shared_lock); mutex_unlock(&ctrl_pdata->mutex); if ((pstatus_data->mfd->panel_power_state == MDSS_PANEL_POWER_ON)) { if (ret > 0) schedule_delayed_work(&pstatus_data->check_status, msecs_to_jiffies(interval)); else mdss_report_panel_dead(pstatus_data); } }
void mdss_check_dsi_ctrl_status(struct work_struct *work, uint32_t interval) { struct dsi_status_data *pstatus_data = NULL; struct mdss_panel_data *pdata = NULL; struct mipi_panel_info *mipi = NULL; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; struct mdss_overlay_private *mdp5_data = NULL; struct mdss_mdp_ctl *ctl = NULL; int ret = 0; pstatus_data = container_of(to_delayed_work(work), struct dsi_status_data, check_status); if (!pstatus_data || !(pstatus_data->mfd)) { pr_err("%s: mfd not available\n", __func__); return; } pdata = dev_get_platdata(&pstatus_data->mfd->pdev->dev); if (!pdata) { pr_err("%s: Panel data not available\n", __func__); return; } mipi = &pdata->panel_info.mipi; ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); if (!ctrl_pdata || (!ctrl_pdata->check_status && (ctrl_pdata->status_mode != ESD_TE))) { pr_err("%s: DSI ctrl or status_check callback not available\n", __func__); return; } mdp5_data = mfd_to_mdp5_data(pstatus_data->mfd); ctl = mfd_to_ctl(pstatus_data->mfd); if (!ctl) { pr_err("%s: Display is off\n", __func__); return; } if (ctl->power_state == MDSS_PANEL_POWER_OFF) { schedule_delayed_work(&pstatus_data->check_status, msecs_to_jiffies(interval)); pr_debug("%s: ctl not powered on\n", __func__); return; } if (ctrl_pdata->status_mode == ESD_TE) { mdss_check_te_status(ctrl_pdata, pstatus_data, interval); return; } mutex_lock(&ctl->offlock); if (mipi->mode == DSI_CMD_MODE) mutex_lock(&mdp5_data->ov_lock); if (mdss_panel_is_power_off(pstatus_data->mfd->panel_power_state) || pstatus_data->mfd->shutdown_pending) { if (mipi->mode == DSI_CMD_MODE) mutex_unlock(&mdp5_data->ov_lock); mutex_unlock(&ctl->offlock); pr_err("%s: DSI turning off, avoiding panel status check\n", __func__); return; } if (ctl->wait_pingpong) ctl->wait_pingpong(ctl, NULL); pr_debug("%s: DSI ctrl wait for ping pong done\n", __func__); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON); ret = ctrl_pdata->check_status(ctrl_pdata); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF); if (mipi->mode == DSI_CMD_MODE) mutex_unlock(&mdp5_data->ov_lock); mutex_unlock(&ctl->offlock); if ((pstatus_data->mfd->panel_power_state == MDSS_PANEL_POWER_ON)) { if (ret > 0) schedule_delayed_work(&pstatus_data->check_status, msecs_to_jiffies(interval)); else mdss_report_panel_dead(pstatus_data); } }
/* * mdss_check_dsi_ctrl_status() - Check MDP5 DSI controller status periodically. * @work : dsi controller status data * @interval : duration in milliseconds to schedule work queue * * This function calls check_status API on DSI controller to send the BTA * command. If DSI controller fails to acknowledge the BTA command, it sends * the PANEL_ALIVE=0 status to HAL layer. */ void mdss_check_dsi_ctrl_status(struct work_struct *work, uint32_t interval) { struct dsi_status_data *pstatus_data = NULL; struct mdss_panel_data *pdata = NULL; struct mipi_panel_info *mipi = NULL; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; struct mdss_overlay_private *mdp5_data = NULL; struct mdss_mdp_ctl *ctl = NULL; int ret = 0; pstatus_data = container_of(to_delayed_work(work), struct dsi_status_data, check_status); if (!pstatus_data || !(pstatus_data->mfd)) { pr_err("%s: mfd not available\n", __func__); return; } pdata = dev_get_platdata(&pstatus_data->mfd->pdev->dev); if (!pdata) { pr_err("%s: Panel data not available\n", __func__); return; } mipi = &pdata->panel_info.mipi; ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); if (!ctrl_pdata || (!ctrl_pdata->check_status && (ctrl_pdata->status_mode != ESD_TE))) { pr_err("%s: DSI ctrl or status_check callback not available\n", __func__); return; } mdp5_data = mfd_to_mdp5_data(pstatus_data->mfd); ctl = mfd_to_ctl(pstatus_data->mfd); if (!ctl) { pr_err("%s: Display is off\n", __func__); return; } if (ctl->power_state == MDSS_PANEL_POWER_OFF) { schedule_delayed_work(&pstatus_data->check_status, msecs_to_jiffies(interval)); pr_debug("%s: ctl not powered on\n", __func__); return; } if (ctrl_pdata->status_mode == ESD_TE) { mdss_check_te_status(ctrl_pdata, pstatus_data, interval); return; } mutex_lock(&ctrl_pdata->mutex); /* * TODO: Because mdss_dsi_cmd_mdp_busy has made sure DMA to * be idle in mdss_dsi_cmdlist_commit, it is not necessary * to acquire ov_lock in case of video mode. Removing this * lock to fix issues so that ESD thread would not block other * overlay operations. Need refine this lock for command mode */ if (mipi->mode == DSI_CMD_MODE) mutex_lock(&mdp5_data->ov_lock); if (mdss_panel_is_power_off(pstatus_data->mfd->panel_power_state)) { if (mipi->mode == DSI_CMD_MODE) mutex_unlock(&mdp5_data->ov_lock); mutex_unlock(&ctrl_pdata->mutex); pr_err("%s: DSI turning off, avoiding panel status check\n", __func__); return; } /* * For the command mode panels, we return pan display * IOCTL on vsync interrupt. So, after vsync interrupt comes * and when DMA_P is in progress, if the panel stops responding * and if we trigger BTA before DMA_P finishes, then the DSI * FIFO will not be cleared since the DSI data bus control * doesn't come back to the host after BTA. This may cause the * display reset not to be proper. Hence, wait for DMA_P done * for command mode panels before triggering BTA. */ if (ctl->wait_pingpong) ctl->wait_pingpong(ctl, NULL); pr_debug("%s: DSI ctrl wait for ping pong done\n", __func__); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON); ret = ctrl_pdata->check_status(ctrl_pdata); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF); if (mipi->mode == DSI_CMD_MODE) mutex_unlock(&mdp5_data->ov_lock); mutex_unlock(&ctrl_pdata->mutex); if ((pstatus_data->mfd->panel_power_state == MDSS_PANEL_POWER_ON)) { if (ret > 0) schedule_delayed_work(&pstatus_data->check_status, msecs_to_jiffies(interval)); else mdss_report_panel_dead(pstatus_data); } }