int mdss_dsi_bta_status_check(struct mdss_dsi_ctrl_pdata *ctrl_pdata) { int ret = 0; unsigned long flag; if (ctrl_pdata == NULL) { pr_err("%s: Invalid input data\n", __func__); return 0; } pr_debug("%s: Checking BTA status\n", __func__); mdss_dsi_clk_ctrl(ctrl_pdata, 1); spin_lock_irqsave(&ctrl_pdata->mdp_lock, flag); INIT_COMPLETION(ctrl_pdata->bta_comp); mdss_dsi_enable_irq(ctrl_pdata, DSI_BTA_TERM); spin_unlock_irqrestore(&ctrl_pdata->mdp_lock, flag); MIPI_OUTP(ctrl_pdata->ctrl_base + 0x098, 0x01); wmb(); ret = wait_for_completion_killable_timeout(&ctrl_pdata->bta_comp, DSI_BTA_EVENT_TIMEOUT); if (ret <= 0) { mdss_dsi_disable_irq(ctrl_pdata, DSI_BTA_TERM); pr_err("%s: DSI BTA error: %i\n", __func__, ret); } mdss_dsi_clk_ctrl(ctrl_pdata, 0); pr_debug("%s: BTA done with ret: %d\n", __func__, ret); return ret; }
static int mdss_dsi_blank(struct mdss_panel_data *pdata, int power_state) { int ret = 0; struct mipi_panel_info *mipi; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; pr_info("%s+:\n", __func__); if (pdata == NULL) { pr_err("%s: Invalid input data\n", __func__); return -EINVAL; } ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); mipi = &pdata->panel_info.mipi; pr_info("%s+: ctrl=%p ndx=%d power_state=%d\n", __func__, ctrl_pdata, ctrl_pdata->ndx, power_state); mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1); if (power_state == MDSS_PANEL_POWER_DOZE) { pr_err("%s: low power state requested\n", __func__); if (ctrl_pdata->low_power_config) ret = ctrl_pdata->low_power_config(pdata, true); goto error; } if (pdata->panel_info.type == MIPI_VIDEO_PANEL && ctrl_pdata->off_cmds.link_state == DSI_LP_MODE) { mdss_dsi_sw_reset(ctrl_pdata, false); mdss_dsi_host_init(pdata); } mdss_dsi_op_mode_config(DSI_CMD_MODE, pdata); #if 0 /*It is not needed on oled cmd mode panel, The on seq has tear off cmd */ if ((pdata->panel_info.type == MIPI_CMD_PANEL) && mipi->vsync_enable && mipi->hw_vsync_mode) mdss_dsi_set_tear_off(ctrl_pdata); #endif pr_info("%s : ctrl_state(%d)\n",__func__, ctrl_pdata->ctrl_state); if (ctrl_pdata->ctrl_state & CTRL_STATE_PANEL_INIT) { ret = ctrl_pdata->off(pdata); if (ret) { pr_err("%s: Panel OFF failed\n", __func__); goto error; } ctrl_pdata->ctrl_state &= ~CTRL_STATE_PANEL_INIT; } error: mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 0); pr_info("%s-:End\n", __func__); return ret; }
static int mdss_dsi_dfps_config(struct mdss_panel_data *pdata, int new_fps) { int rc = 0; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; u32 dsi_ctrl; pr_debug("%s+:\n", __func__); if (pdata == NULL) { pr_err("%s: Invalid input data\n", __func__); return -EINVAL; } ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); if (!ctrl_pdata->panel_data.panel_info.dynamic_fps) { pr_err("%s: Dynamic fps not enabled for this panel\n", __func__); return -EINVAL; } if (new_fps != ctrl_pdata->panel_data.panel_info.mipi.frame_rate) { rc = mdss_dsi_clk_div_config (&ctrl_pdata->panel_data.panel_info, new_fps); if (rc) { pr_err("%s: unable to initialize the clk dividers\n", __func__); return rc; } ctrl_pdata->pclk_rate = ctrl_pdata->panel_data.panel_info.mipi.dsi_pclk_rate; ctrl_pdata->byte_clk_rate = ctrl_pdata->panel_data.panel_info.clk_rate / 8; if (pdata->panel_info.dfps_update == DFPS_IMMEDIATE_CLK_UPDATE_MODE) { dsi_ctrl = MIPI_INP((ctrl_pdata->ctrl_base) + 0x0004); ctrl_pdata->panel_data.panel_info.mipi.frame_rate = new_fps; dsi_ctrl &= ~0x2; MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004, dsi_ctrl); mdss_dsi_controller_cfg(true, pdata); mdss_dsi_clk_ctrl(ctrl_pdata, 0); mdss_dsi_clk_ctrl(ctrl_pdata, 1); dsi_ctrl |= 0x2; MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004, dsi_ctrl); } } else { pr_debug("%s: Panel is already at this FPS\n", __func__); } return rc; }
static int mdss_dsi_off(struct mdss_panel_data *pdata, int power_state) { int ret = 0; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; struct mdss_panel_info *panel_info = NULL; if (pdata == NULL) { pr_err("%s: Invalid input data\n", __func__); return -EINVAL; } ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); panel_info = &ctrl_pdata->panel_data.panel_info; pr_info("%s+: ctrl=%p ndx=%d power_state=%d\n", __func__, ctrl_pdata, ctrl_pdata->ndx, power_state); if (power_state == panel_info->panel_power_state) { pr_err("%s: No change in power state %d -> %d\n", __func__, panel_info->panel_power_state, power_state); goto end; } if (power_state != MDSS_PANEL_POWER_OFF) { pr_err("%s: dsi_off with panel always on\n", __func__); goto panel_power_ctrl; } if (pdata->panel_info.type == MIPI_CMD_PANEL) mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1); /* disable DSI controller */ mdss_dsi_controller_cfg(0, pdata); /* disable DSI phy */ mdss_dsi_phy_disable(ctrl_pdata); mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 0); panel_power_ctrl: ret = mdss_dsi_panel_power_ctrl(pdata, power_state); if (ret) { pr_err("%s: Panel power off failed\n", __func__); } else { if (panel_info->dynamic_fps && (panel_info->dfps_update == DFPS_SUSPEND_RESUME_MODE) && (panel_info->new_fps != panel_info->mipi.frame_rate)) panel_info->mipi.frame_rate = panel_info->new_fps; } panel_info->dsi_on_status = false; end: pr_info("%s-:\n", __func__); return ret; }
static int mdss_dsi_off(struct mdss_panel_data *pdata) { int ret = 0; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; struct mdss_panel_info *panel_info = NULL; if (pdata == NULL) { pr_err("%s: Invalid input data\n", __func__); return -EINVAL; } if (!pdata->panel_info.panel_power_on) { pr_warn("%s:%d Panel already off.\n", __func__, __LINE__); return 0; } pdata->panel_info.panel_power_on = 0; ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); mutex_lock(&ctrl_pdata->mutex); panel_info = &ctrl_pdata->panel_data.panel_info; pr_debug("%s+: ctrl=%p ndx=%d\n", __func__, ctrl_pdata, ctrl_pdata->ndx); if (pdata->panel_info.type == MIPI_CMD_PANEL) mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1); /* disable DSI controller */ mdss_dsi_controller_cfg(0, pdata); /* disable DSI phy */ mdss_dsi_phy_disable(ctrl_pdata); mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 0); #ifndef CONFIG_FB_MSM_MDSS_SPECIFIC_PANEL ret = mdss_dsi_panel_power_on(pdata, 0); #else ret = ctrl_pdata->spec_pdata->panel_power_on(pdata, 0); #endif /* CONFIG_FB_MSM_MDSS_SPECIFIC_PANEL */ if (ret) { mutex_unlock(&ctrl_pdata->mutex); pr_err("%s: Panel power off failed\n", __func__); return ret; } if (panel_info->dynamic_fps && (panel_info->dfps_update == DFPS_SUSPEND_RESUME_MODE) && (panel_info->new_fps != panel_info->mipi.frame_rate)) panel_info->mipi.frame_rate = panel_info->new_fps; mutex_unlock(&ctrl_pdata->mutex); pr_debug("%s-:\n", __func__); return ret; }
static int mdss_dsi_blank(struct mdss_panel_data *pdata) { int ret = 0; struct mipi_panel_info *mipi; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; pr_debug("%s+:\n", __func__); if (pdata == NULL) { pr_err("%s: Invalid input data\n", __func__); return -EINVAL; } ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); mipi = &pdata->panel_info.mipi; mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1); if (pdata->panel_info.type == MIPI_VIDEO_PANEL && ctrl_pdata->off_cmds.link_state == DSI_LP_MODE) { mdss_dsi_sw_reset(pdata); mdss_dsi_host_init(pdata); } mdss_dsi_op_mode_config(DSI_CMD_MODE, pdata); if (pdata->panel_info.dynamic_switch_pending) { pr_info("%s: switching to %s mode\n", __func__, (pdata->panel_info.mipi.mode ? "video" : "command")); if (pdata->panel_info.type == MIPI_CMD_PANEL) { ctrl_pdata->switch_mode(pdata, DSI_VIDEO_MODE); } else if (pdata->panel_info.type == MIPI_VIDEO_PANEL) { ctrl_pdata->switch_mode(pdata, DSI_CMD_MODE); mdss_dsi_set_tear_off(ctrl_pdata); } } if ((pdata->panel_info.type == MIPI_CMD_PANEL) && mipi->vsync_enable && mipi->hw_vsync_mode) mdss_dsi_set_tear_off(ctrl_pdata); if (ctrl_pdata->ctrl_state & CTRL_STATE_PANEL_INIT) { if (!pdata->panel_info.dynamic_switch_pending) { ret = ctrl_pdata->off(pdata); if (ret) { pr_err("%s: Panel OFF failed\n", __func__); goto error; } } ctrl_pdata->ctrl_state &= ~CTRL_STATE_PANEL_INIT; } error: mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 0); pr_debug("%s-:End\n", __func__); return ret; }
int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp) { struct dcs_cmd_req *req; int ret = -EINVAL; int rc = 0; mutex_lock(&ctrl->cmd_mutex); req = mdss_dsi_cmdlist_get(ctrl); /* make sure dsi_cmd_mdp is idle */ mdss_dsi_cmd_mdp_busy(ctrl); pr_debug("%s: from_mdp=%d pid=%d\n", __func__, from_mdp, current->pid); if (req == NULL) goto need_lock; /* * mdss interrupt is generated in mdp core clock domain * mdp clock need to be enabled to receive dsi interrupt * also, axi bus bandwidth need since dsi controller will * fetch dcs commands from axi bus */ mdss_bus_scale_set_quota(MDSS_HW_DSI0, SZ_1M, SZ_1M); mdss_bus_bandwidth_ctrl(1); pr_debug("%s: from_mdp=%d pid=%d\n", __func__, from_mdp, current->pid); mdss_dsi_clk_ctrl(ctrl, 1); rc = mdss_iommu_ctrl(1); if (IS_ERR_VALUE(rc)) { pr_err("IOMMU attach failed\n"); mutex_unlock(&ctrl->cmd_mutex); return rc; } if (req->flags & CMD_REQ_HS_MODE) mdss_dsi_set_tx_power_mode(0, &ctrl->panel_data); if (req->flags & CMD_REQ_RX) ret = mdss_dsi_cmdlist_rx(ctrl, req); else ret = mdss_dsi_cmdlist_tx(ctrl, req); if (req->flags & CMD_REQ_HS_MODE) mdss_dsi_set_tx_power_mode(1, &ctrl->panel_data); mdss_iommu_ctrl(0); mdss_dsi_clk_ctrl(ctrl, 0); mdss_bus_scale_set_quota(MDSS_HW_DSI0, 0, 0); mdss_bus_bandwidth_ctrl(0); need_lock: if (from_mdp) /* from pipe_commit */ mdss_dsi_cmd_mdp_start(ctrl); mutex_unlock(&ctrl->cmd_mutex); return ret; }
int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp) { struct dcs_cmd_req *req; int ret = -EINVAL; int rc = 0; mutex_lock(&ctrl->cmd_mutex); req = mdss_dsi_cmdlist_get(ctrl); MDSS_XLOG(ctrl->ndx, from_mdp, ctrl->mdp_busy, current->pid, XLOG_FUNC_ENTRY); /* make sure dsi_cmd_mdp is idle */ mdss_dsi_cmd_mdp_busy(ctrl); pr_debug("%s: from_mdp=%d pid=%d\n", __func__, from_mdp, current->pid); if (req == NULL) goto need_lock; MDSS_XLOG(ctrl->ndx, req->flags, req->cmds_cnt, from_mdp, current->pid); /* * mdss interrupt is generated in mdp core clock domain * mdp clock need to be enabled to receive dsi interrupt * also, axi bus bandwidth need since dsi controller will * fetch dcs commands from axi bus */ mdss_bus_bandwidth_ctrl(1); pr_debug("%s: from_mdp=%d pid=%d\n", __func__, from_mdp, current->pid); mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 1); rc = mdss_iommu_ctrl(1); if (IS_ERR_VALUE(rc)) { pr_err("IOMMU attach failed\n"); mutex_unlock(&ctrl->cmd_mutex); return rc; } if (req->flags & CMD_REQ_RX) ret = mdss_dsi_cmdlist_rx(ctrl, req); else ret = mdss_dsi_cmdlist_tx(ctrl, req); mdss_iommu_ctrl(0); mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 0); mdss_bus_bandwidth_ctrl(0); need_lock: if (from_mdp) /* from pipe_commit */ mdss_dsi_cmd_mdp_start(ctrl); MDSS_XLOG(ctrl->ndx, from_mdp, ctrl->mdp_busy, current->pid, XLOG_FUNC_EXIT); mutex_unlock(&ctrl->cmd_mutex); return ret; }
static int mdss_dsi_off(struct mdss_panel_data *pdata) { int ret = 0; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; if (pdata == NULL) { pr_err("%s: Invalid input data\n", __func__); return -EINVAL; } if (!pdata->panel_info.panel_power_on) { pr_warn("%s:%d Panel already off.\n", __func__, __LINE__); return -EPERM; } pdata->panel_info.panel_power_on = 0; ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); pr_debug("%s+: ctrl=%p ndx=%d\n", __func__, ctrl_pdata, ctrl_pdata->ndx); if (pdata->panel_info.type == MIPI_CMD_PANEL) mdss_dsi_clk_ctrl(ctrl_pdata, 1); /* disable DSI controller */ mdss_dsi_controller_cfg(0, pdata); mdss_dsi_clk_ctrl(ctrl_pdata, 0); ret = mdss_dsi_enable_bus_clocks(ctrl_pdata); if (ret) { pr_err("%s: failed to enable bus clocks. rc=%d\n", __func__, ret); mdss_dsi_panel_power_on(pdata, 0); return ret; } /* disable DSI phy */ mdss_dsi_phy_enable(ctrl_pdata, 0); mdss_dsi_disable_bus_clocks(ctrl_pdata); ret = mdss_dsi_panel_power_on(pdata, 0); if (ret) { pr_err("%s: Panel power off failed\n", __func__); return ret; } pr_debug("%s-:\n", __func__); return ret; }
static int mdss_dsi_off(struct mdss_panel_data *pdata) { int ret = 0; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; struct mdss_panel_info *panel_info = NULL; if (pdata == NULL) { pr_err("%s: Invalid input data\n", __func__); return -EINVAL; } if (!pdata->panel_info.panel_power_on) { pr_warn("%s:%d Panel already off.\n", __func__, __LINE__); return 0; } // keep reset before video off usleep(pdata->panel_info.mipi.sleep_lp00_delay); pdata->panel_info.panel_power_on = 0; ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); panel_info = &ctrl_pdata->panel_data.panel_info; pr_debug("%s+: ctrl=%p ndx=%d\n", __func__, ctrl_pdata, ctrl_pdata->ndx); if (pdata->panel_info.type == MIPI_CMD_PANEL) mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1); /* disable DSI controller */ mdss_dsi_controller_cfg(0, pdata); /* disable DSI phy */ mdss_dsi_phy_disable(ctrl_pdata); mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 0); ret = mdss_dsi_panel_power_on(pdata, 0); if (ret) { pr_err("%s: Panel power off failed\n", __func__); return ret; } if (panel_info->dynamic_fps && (panel_info->dfps_update == DFPS_SUSPEND_RESUME_MODE) && (panel_info->new_fps != panel_info->mipi.frame_rate)) panel_info->mipi.frame_rate = panel_info->new_fps; pr_debug("%s-:\n", __func__); return ret; }
int mdss_get_tx_power_mode(struct mdss_panel_data *pdata) { struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; u32 data; ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); mdss_dsi_clk_ctrl(ctrl_pdata, 1); data = MIPI_INP((ctrl_pdata->ctrl_base) + 0x3c); mdss_dsi_clk_ctrl(ctrl_pdata, 0); return !!(data & BIT(26)); }
int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp) { struct dcs_cmd_req *req; int ret = -EINVAL; int rc = 0; mutex_lock(&ctrl->cmd_mutex); req = mdss_dsi_cmdlist_get(ctrl); mdss_dsi_cmd_mdp_busy(ctrl); pr_debug("%s: from_mdp=%d pid=%d\n", __func__, from_mdp, current->pid); if (req == NULL) goto need_lock; mdss_bus_scale_set_quota(MDSS_HW_DSI0, SZ_1M, SZ_1M); mdss_bus_bandwidth_ctrl(1); pr_debug("%s: from_mdp=%d pid=%d\n", __func__, from_mdp, current->pid); mdss_dsi_clk_ctrl(ctrl, 1); rc = mdss_iommu_ctrl(1); if (IS_ERR_VALUE(rc)) { pr_err("IOMMU attach failed\n"); mutex_unlock(&ctrl->cmd_mutex); return rc; } if (req->flags & CMD_REQ_HS_MODE) mdss_dsi_set_tx_power_mode(0, &ctrl->panel_data); if (req->flags & CMD_REQ_RX) ret = mdss_dsi_cmdlist_rx(ctrl, req); else ret = mdss_dsi_cmdlist_tx(ctrl, req); if (req->flags & CMD_REQ_HS_MODE) mdss_dsi_set_tx_power_mode(1, &ctrl->panel_data); mdss_iommu_ctrl(0); mdss_dsi_clk_ctrl(ctrl, 0); mdss_bus_scale_set_quota(MDSS_HW_DSI0, 0, 0); mdss_bus_bandwidth_ctrl(0); need_lock: if (from_mdp) mdss_dsi_cmd_mdp_start(ctrl); mutex_unlock(&ctrl->cmd_mutex); return ret; }
static int mdss_dsi_unblank(struct mdss_panel_data *pdata) { int ret = 0; struct mipi_panel_info *mipi; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; if (pdata == NULL) { pr_err("%s: Invalid input data\n", __func__); return -EINVAL; } ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); mipi = &pdata->panel_info.mipi; pr_err("%s+: ctrl=%p ndx=%d cur_blank_state=%d\n", __func__, ctrl_pdata, ctrl_pdata->ndx, pdata->panel_info.blank_state); mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1); if (pdata->panel_info.blank_state == MDSS_PANEL_BLANK_LOW_POWER) { pr_debug("%s: dsi_unblank with panel always on\n", __func__); if (ctrl_pdata->low_power_config) ret = ctrl_pdata->low_power_config(pdata, false); goto error; } pr_info("ctrl_state = (%d)\n",ctrl_pdata->ctrl_state); if (!(ctrl_pdata->ctrl_state & CTRL_STATE_PANEL_INIT)) { ret = ctrl_pdata->on(pdata); if (ret) { pr_err("%s: unable to initialize the panel\n", __func__); goto error; } ctrl_pdata->ctrl_state |= CTRL_STATE_PANEL_INIT; } #if 0 /*It is not needed on oled cmd mode panel, The on seq has tear on cmd */ if ((pdata->panel_info.type == MIPI_CMD_PANEL) && mipi->vsync_enable && mipi->hw_vsync_mode) mdss_dsi_set_tear_on(ctrl_pdata); #endif error: mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 0); pr_err("%s-:\n", __func__); return ret; }
void mdss_dsi_pll_relock(struct mdss_dsi_ctrl_pdata *ctrl) { int i, cnt; cnt = ctrl->clk_cnt; for (i = 0; i < cnt; i++) mdss_dsi_clk_ctrl(ctrl, 0); for (i = 0; i < cnt; i++) mdss_dsi_clk_ctrl(ctrl, 1); }
void mdss_dsi_pll_relock(struct mdss_dsi_ctrl_pdata *ctrl) { int i, cnt; cnt = ctrl->clk_cnt; /* disable dsi clk */ for (i = 0; i < cnt; i++) mdss_dsi_clk_ctrl(ctrl, 0); /* enable dsi clk */ for (i = 0; i < cnt; i++) mdss_dsi_clk_ctrl(ctrl, 1); }
int mdss_dsi_bta_status_check(struct mdss_dsi_ctrl_pdata *ctrl_pdata) { int ret = 0; unsigned long flag; if (ctrl_pdata == NULL) { pr_err("%s: Invalid input data\n", __func__); /* * This should not return error otherwise * BTA status thread will treat it as dead panel scenario * and request for blank/unblank */ return 0; } pr_debug("%s: Checking BTA status\n", __func__); #ifdef CONFIG_HUAWEI_KERNEL mutex_lock(&ctrl_pdata->cmd_mutex); #endif mdss_dsi_clk_ctrl(ctrl_pdata, 1); spin_lock_irqsave(&ctrl_pdata->mdp_lock, flag); INIT_COMPLETION(ctrl_pdata->bta_comp); mdss_dsi_enable_irq(ctrl_pdata, DSI_BTA_TERM); spin_unlock_irqrestore(&ctrl_pdata->mdp_lock, flag); MIPI_OUTP(ctrl_pdata->ctrl_base + 0x098, 0x01); /* trigger */ wmb(); ret = wait_for_completion_killable_timeout(&ctrl_pdata->bta_comp, DSI_BTA_EVENT_TIMEOUT); if (ret <= 0) { mdss_dsi_disable_irq(ctrl_pdata, DSI_BTA_TERM); pr_err("%s: DSI BTA error: %i\n", __func__, ret); } mdss_dsi_clk_ctrl(ctrl_pdata, 0); #ifdef CONFIG_HUAWEI_KERNEL mutex_unlock(&ctrl_pdata->cmd_mutex); #endif pr_debug("%s: BTA done with ret: %d\n", __func__, ret); #ifdef CONFIG_HUAWEI_LCD if(ret > 0) { /*if panel check error and enable the esd check bit in dtsi,report the event to hal layer*/ if(ctrl_pdata->esd_check_enable) ret = panel_check_live_status(ctrl_pdata); } #endif return ret; }
static int prepare_for_reg_access(struct msm_fb_data_type *mfd) { struct mdss_panel_data *pdata; int ret = 0; struct mdss_mdp_ctl *ctl; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; ctl = mfd_to_ctl(mfd); if (!ctl) return -ENODEV; pdata = dev_get_platdata(&mfd->pdev->dev); if (!pdata) { pr_err("%s: no panel connected\n", __func__); return -ENODEV; } ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false); mdss_dsi_cmd_mdp_busy(ctrl_pdata); mdss_bus_bandwidth_ctrl(1); mdss_dsi_clk_ctrl(ctrl_pdata, 1); mdss_dsi_op_mode_config(DSI_CMD_MODE, pdata); return ret; }
static int mdss_dsi_unblank(struct mdss_panel_data *pdata) { int ret = 0; struct mipi_panel_info *mipi; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; pr_debug("%s+:\n", __func__); if (pdata == NULL) { pr_err("%s: Invalid input data\n", __func__); return -EINVAL; } ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); mipi = &pdata->panel_info.mipi; mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1); if (!(ctrl_pdata->ctrl_state & CTRL_STATE_PANEL_INIT)) { if (!pdata->panel_info.dynamic_switch_pending) { ret = ctrl_pdata->on(pdata); if (ret) { pr_err("%s: unable to initialize the panel\n", __func__); goto error; } } ctrl_pdata->ctrl_state |= CTRL_STATE_PANEL_INIT; } //+++ #ifdef CONFIG_ZTEMT_LCD_DISP_ENHANCE zte_disp_enhance(); #endif //--- if ((pdata->panel_info.type == MIPI_CMD_PANEL) && mipi->vsync_enable && mipi->hw_vsync_mode) mdss_dsi_set_tear_on(ctrl_pdata); error: mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 0); pr_debug("%s-:\n", __func__); return ret; }
void mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp) { struct dcs_cmd_req *req; u32 data; mutex_lock(&ctrl->cmd_mutex); req = mdss_dsi_cmdlist_get(ctrl); /* make sure dsi_cmd_mdp is idle */ mdss_dsi_cmd_mdp_busy(ctrl); if (req == NULL) goto need_lock; pr_debug("%s: from_mdp=%d pid=%d\n", __func__, from_mdp, current->pid); mdss_dsi_clk_ctrl(ctrl, 1); data = MIPI_INP((ctrl->ctrl_base) + 0x0004); if (data & 0x02) { /* video mode, make sure video engine is busy * so dcs command will be sent at start of BLLP */ mdss_dsi_wait4video_eng_busy(ctrl); } else { /* command mode */ if (!from_mdp) { /* cmdlist_put */ /* make sure dsi_cmd_mdp is idle */ mdss_dsi_cmd_mdp_busy(ctrl); } } if (req->flags & CMD_REQ_RX) mdss_dsi_cmdlist_rx(ctrl, req); else mdss_dsi_cmdlist_tx(ctrl, req); mdss_dsi_clk_ctrl(ctrl, 0); need_lock: if (from_mdp) /* from pipe_commit */ mdss_dsi_cmd_mdp_start(ctrl); mutex_unlock(&ctrl->cmd_mutex); }
void mdss_dsi_pll_relock(struct mdss_dsi_ctrl_pdata *ctrl) { int i, cnt; /* * todo: this code does not work very well with dual * dsi use cases. Need to fix this eventually. */ cnt = ctrl->link_clk_cnt; /* disable dsi clk */ for (i = 0; i < cnt; i++) mdss_dsi_clk_ctrl(ctrl, DSI_LINK_CLKS, 0); /* enable dsi clk */ for (i = 0; i < cnt; i++) mdss_dsi_clk_ctrl(ctrl, DSI_LINK_CLKS, 1); }
int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp) { struct dcs_cmd_req *req; int ret = -EINVAL; mutex_lock(&ctrl->cmd_mutex); req = mdss_dsi_cmdlist_get(ctrl); /* make sure dsi_cmd_mdp is idle */ mdss_dsi_cmd_mdp_busy(ctrl); pr_debug("%s: from_mdp=%d pid=%d\n", __func__, from_mdp, current->pid); if (req == NULL) goto need_lock; /* * mdss interrupt is generated in mdp core clock domain * mdp clock need to be enabled to receive dsi interrupt * also, axi bus bandwidth need since dsi controller will * fetch dcs commands from axi bus */ mdss_bus_bandwidth_ctrl(1); pr_debug("%s: from_mdp=%d pid=%d\n", __func__, from_mdp, current->pid); mdss_dsi_clk_ctrl(ctrl, 1); if (req->flags & CMD_REQ_RX) { mdss_dsi_cmdlist_rx(ctrl, req); ret = ctrl->rx_buf.len; } else ret = mdss_dsi_cmdlist_tx(ctrl, req); mdss_dsi_clk_ctrl(ctrl, 0); mdss_bus_bandwidth_ctrl(0); need_lock: if (from_mdp) /* from pipe_commit */ mdss_dsi_cmd_mdp_start(ctrl); mutex_unlock(&ctrl->cmd_mutex); return ret; }
void mdss_dsi_clk_req(struct mdss_dsi_ctrl_pdata *ctrl, int enable) { if (enable == 0) { mutex_lock(&ctrl->cmd_mutex); mdss_dsi_cmd_mdp_busy(ctrl); mutex_unlock(&ctrl->cmd_mutex); } mdss_dsi_clk_ctrl(ctrl, enable); }
void mdss_dsi_clk_req(struct mdss_dsi_ctrl_pdata *ctrl, int enable) { MDSS_XLOG(ctrl->ndx, enable, ctrl->mdp_busy, current->pid); if (enable == 0) { /* need wait before disable */ mutex_lock(&ctrl->cmd_mutex); mdss_dsi_cmd_mdp_busy(ctrl); mutex_unlock(&ctrl->cmd_mutex); } MDSS_XLOG(ctrl->ndx, enable, ctrl->mdp_busy, current->pid); mdss_dsi_clk_ctrl(ctrl, enable); }
/** * mdss_dsi_reg_status_check() - Check dsi panel status through reg read * @ctrl_pdata: pointer to the dsi controller structure * * This function can be used to check the panel status through reading the * status register from the panel. * * Return: positive value if the panel is in good state, negative value or * zero otherwise. */ int mdss_dsi_reg_status_check(struct mdss_dsi_ctrl_pdata *ctrl_pdata) { int ret = 0; if (ctrl_pdata == NULL) { pr_err("%s: Invalid input data\n", __func__); return 0; } pr_debug("%s: Checking Register status\n", __func__); mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1); if (ctrl_pdata->status_cmds.link_state == DSI_HS_MODE) mdss_dsi_set_tx_power_mode(0, &ctrl_pdata->panel_data); ret = mdss_dsi_read_status(ctrl_pdata); if (ctrl_pdata->status_cmds.link_state == DSI_HS_MODE) mdss_dsi_set_tx_power_mode(1, &ctrl_pdata->panel_data); if (ret == 0) { if (ctrl_pdata->status_buf.data[0] != ctrl_pdata->status_value) { pr_err("%s: Read back value from panel is incorrect\n", __func__); ret = -EINVAL; } else { ret = 1; } } else { pr_err("%s: Read status register returned error\n", __func__); } mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 0); pr_debug("%s: Read register done with ret: %d\n", __func__, ret); return ret; }
/** * mdss_dsi_bta_status_check() - Check dsi panel status through bta check * @ctrl_pdata: pointer to the dsi controller structure * * This function can be used to check status of the panel using bta check * for the panel. * * Return: positive value if the panel is in good state, negative value or * zero otherwise. */ int mdss_dsi_bta_status_check(struct mdss_dsi_ctrl_pdata *ctrl_pdata) { int ret = 0; unsigned long flag; if (ctrl_pdata == NULL) { pr_err("%s: Invalid input data\n", __func__); /* * This should not return error otherwise * BTA status thread will treat it as dead panel scenario * and request for blank/unblank */ return 0; } pr_debug("%s: Checking BTA status\n", __func__); mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1); spin_lock_irqsave(&ctrl_pdata->mdp_lock, flag); INIT_COMPLETION(ctrl_pdata->bta_comp); mdss_dsi_enable_irq(ctrl_pdata, DSI_BTA_TERM); spin_unlock_irqrestore(&ctrl_pdata->mdp_lock, flag); MIPI_OUTP(ctrl_pdata->ctrl_base + 0x098, 0x01); /* trigger */ wmb(); ret = wait_for_completion_killable_timeout(&ctrl_pdata->bta_comp, DSI_BTA_EVENT_TIMEOUT); if (ret <= 0) { mdss_dsi_disable_irq(ctrl_pdata, DSI_BTA_TERM); pr_err("%s: DSI BTA error: %i\n", __func__, ret); } mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 0); pr_debug("%s: BTA done with ret: %d\n", __func__, ret); return ret; }
void mdss_set_tx_power_mode(int mode, struct mdss_panel_data *pdata) { struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; u32 data; if (pdata == NULL) { pr_err("%s: Invalid input data\n", __func__); return; } ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); mdss_dsi_clk_ctrl(ctrl_pdata, 1); data = MIPI_INP((ctrl_pdata->ctrl_base) + 0x3c); if (mode == 0) data &= ~BIT(26); else data |= BIT(26); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x3c, data); mdss_dsi_clk_ctrl(ctrl_pdata, 0); }
void mdss_dsi_clk_req(struct mdss_dsi_ctrl_pdata *ctrl, int enable) { #if defined (CONFIG_FB_MSM_MDSS_DSI_DBG) xlog(__func__,ctrl->ndx, enable, ctrl->mdp_busy, 0x111, 0, current->pid); #endif if (enable == 0) { /* need wait before disable */ mutex_lock(&ctrl->cmd_mutex); mdss_dsi_cmd_mdp_busy(ctrl); mutex_unlock(&ctrl->cmd_mutex); } #if defined (CONFIG_FB_MSM_MDSS_DSI_DBG) xlog(__func__,ctrl->ndx, enable, ctrl->mdp_busy, 0x222, 0, current->pid); #endif mdss_dsi_clk_ctrl(ctrl, enable); }
static int post_reg_access(struct msm_fb_data_type *mfd) { struct mdss_panel_data *pdata; int ret = 0; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; pdata = dev_get_platdata(&mfd->pdev->dev); if (!pdata) { pr_err("%s: no panel connected\n", __func__); return -ENODEV; } ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); mdss_dsi_clk_ctrl(ctrl_pdata, 0); mdss_bus_bandwidth_ctrl(0); mdss_dsi_op_mode_config(pdata->panel_info.mipi.mode, pdata); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false); return ret; }
static int mdss_dsi_dfps_config(struct mdss_panel_data *pdata, int new_fps) { int rc = 0; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; u32 dsi_ctrl; pr_debug("%s+:\n", __func__); if (pdata == NULL) { pr_err("%s: Invalid input data\n", __func__); return -EINVAL; } ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); if (!ctrl_pdata->panel_data.panel_info.dynamic_fps) { pr_err("%s: Dynamic fps not enabled for this panel\n", __func__); return -EINVAL; } if (new_fps != ctrl_pdata->panel_data.panel_info.mipi.frame_rate) { if (pdata->panel_info.dfps_update == DFPS_IMMEDIATE_PORCH_UPDATE_MODE) { u32 hsync_period, vsync_period; u32 new_dsi_v_total, current_dsi_v_total; vsync_period = mdss_panel_get_vtotal(&pdata->panel_info); hsync_period = mdss_panel_get_htotal(&pdata->panel_info); current_dsi_v_total = MIPI_INP((ctrl_pdata->ctrl_base) + 0x2C); new_dsi_v_total = ((vsync_period - 1) << 16) | (hsync_period - 1); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x2C, (current_dsi_v_total | 0x8000000)); if (new_dsi_v_total & 0x8000000) { MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x2C, new_dsi_v_total); } else { MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x2C, (new_dsi_v_total | 0x8000000)); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x2C, (new_dsi_v_total & 0x7ffffff)); } pdata->panel_info.mipi.frame_rate = new_fps; } else { rc = mdss_dsi_clk_div_config (&ctrl_pdata->panel_data.panel_info, new_fps); if (rc) { pr_err("%s: unable to initialize the clk dividers\n", __func__); return rc; } ctrl_pdata->pclk_rate = pdata->panel_info.mipi.dsi_pclk_rate; ctrl_pdata->byte_clk_rate = pdata->panel_info.clk_rate / 8; if (pdata->panel_info.dfps_update == DFPS_IMMEDIATE_CLK_UPDATE_MODE) { dsi_ctrl = MIPI_INP((ctrl_pdata->ctrl_base) + 0x0004); pdata->panel_info.mipi.frame_rate = new_fps; dsi_ctrl &= ~0x2; MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004, dsi_ctrl); mdss_dsi_controller_cfg(true, pdata); mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 0); mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1); dsi_ctrl |= 0x2; MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004, dsi_ctrl); } } } else { pr_debug("%s: Panel is already at this FPS\n", __func__); } return rc; }
int mdss_dsi_on(struct mdss_panel_data *pdata) { int ret = 0; struct mdss_panel_info *pinfo; struct mipi_panel_info *mipi; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; struct mdss_data_type *mdata = mdss_mdp_get_mdata(); if (pdata == NULL) { pr_err("%s: Invalid input data\n", __func__); return -EINVAL; } if (pdata->panel_info.panel_power_on) { pr_warn("%s:%d Panel already on.\n", __func__, __LINE__); return 0; } ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); pr_info("%s+: ctrl=%p ndx=%d\n", __func__, ctrl_pdata, ctrl_pdata->ndx); pinfo = &pdata->panel_info; mipi = &pdata->panel_info.mipi; if (ctrl_pdata->partial_mode_enabled && !pdata->panel_info.panel_dead) { mdss_dsi_ulps_config_sub(ctrl_pdata, 0, 1); mdata->ulps = false; pdata->panel_info.panel_power_on = 1; mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1); } else { if (ctrl_pdata->partial_mode_enabled && pdata->panel_info.panel_dead) pr_warn("%s: Panel is dead, bring up DSI\n", __func__); ret = mdss_dsi_panel_power_on(pdata, 1); if (ret) { pr_err("%s:Panel power on failed. rc=%d\n", __func__, ret); return ret; } mdss_dsi_clk_ctrl(ctrl_pdata, DSI_BUS_CLKS, 1); if (ret) { pr_err("%s: failed to enable bus clocks. rc=%d\n", __func__, ret); ret = mdss_dsi_panel_power_on(pdata, 0); if (ret) { pr_err("%s: Panel reset failed. rc=%d\n", __func__, ret); return ret; } pdata->panel_info.panel_power_on = 0; return ret; } pdata->panel_info.panel_power_on = 1; mdss_dsi_phy_sw_reset((ctrl_pdata->ctrl_base)); mdss_dsi_phy_init(pdata); mdss_dsi_clk_ctrl(ctrl_pdata, DSI_BUS_CLKS, 0); mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1); __mdss_dsi_ctrl_setup(pdata); mdss_dsi_sw_reset(pdata); mdss_dsi_host_init(pdata); } /* * Issue hardware reset line after enabling the DSI clocks and data * data lanes for LP11 init */ if (mipi->lp11_init) mdss_dsi_panel_reset(pdata, 1); if (mipi->init_delay) usleep(mipi->init_delay); if (mipi->force_clk_lane_hs) { u32 tmp; tmp = MIPI_INP((ctrl_pdata->ctrl_base) + 0xac); tmp |= (1<<28); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0xac, tmp); wmb(); } if (pdata->panel_info.type == MIPI_CMD_PANEL) mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 0); pr_info("%s-:\n", __func__); return 0; }