Loading Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt +41 −0 Original line number Diff line number Diff line Loading @@ -384,6 +384,8 @@ Optional properties: go blank during transition. "dynamic-switch-immediate"= Switch on next frame update. Panel will not go blank for this transition. "dynamic-resolution-switch-immediate"= Switch the panel resolution. Panel will not go blank for this transition. - qcom,mdss-dsi-post-mode-switch-on-command: Multiple dcs packets used for turning on DSI panel after panel has switch modes. Refer to "qcom,mdss-dsi-on-command" section for adding commands. Loading Loading @@ -453,6 +455,20 @@ Optional properites: - qcom,adjust-timer-wakeup-ms: An integer value to indicate the timer delay(in ms) to accommodate s/w delay while configuring the event timer wakeup logic. - qcom,mdss-dsi-display-timings: Parent node that lists the different resolutions that the panel supports. Each child represents timings settings for a specific resolution. Additional properties added to the second level nodes that represent timings properties: - qcom,mdss-dsi-timing-default: Property that specifies the current child as the default timing configuration that will be used. - qcom,mdss-dsi-timing-switch-command: List of commands that need to be sent to panel when the resolution/timing switch happens dynamically. Refer to "qcom,mdss-dsi-on-command" section for adding commands. - qcom,mdss-dsi-timing-switch-command-state: String that specifies the ctrl state for sending resolution switch commands. "dsi_lp_mode" = DSI low power mode (default) "dsi_hs_mode" = DSI high speed mode Note, if a given optional qcom,* binding is not present, then the driver will configure the default values specified. Loading Loading @@ -594,6 +610,31 @@ Example: qcom,mdss-dsi-force-clock-lane-hs; qcom,compression-mode = "dsc"; qcom,adjust-timer-wakeup-ms = <1>; qcom,mdss-dsi-display-timings { wqhd { qcom,mdss-dsi-timing-default; qcom,mdss-dsi-panel-width = <720>; qcom,mdss-dsi-panel-height = <2560>; qcom,mdss-dsi-h-front-porch = <20>; qcom,mdss-dsi-h-back-porch = <8>; qcom,mdss-dsi-h-pulse-width = <8>; qcom,mdss-dsi-h-sync-skew = <0>; qcom,mdss-dsi-v-back-porch = <4>; qcom,mdss-dsi-v-front-porch = <728>; qcom,mdss-dsi-v-pulse-width = <4>; qcom,mdss-dsi-panel-framerate = <60>; qcom,mdss-dsi-panel-timings = [E6 38 26 00 68 6E 2A 3C 2C 03 04 00]; qcom,mdss-dsi-t-clk-post = <0x02>; qcom,mdss-dsi-t-clk-pre = <0x2a>; qcom,mdss-dsi-on-command = [05 01 00 00 a0 00 02 11 00 05 01 00 00 02 00 02 29 00]; qcom,mdss-dsi-on-command-state = "dsi_lp_mode"; qcom,mdss-dsi-timing-switch-command = [ 29 00 00 00 00 00 02 B0 04 29 00 00 00 00 00 02 F1 00]; qcom,mdss-dsi-timing-switch-command-state = "dsi_lp_mode"; }; }; qcom,panel-supply-entries { #address-cells = <1>; #size-cells = <0>; Loading drivers/video/msm/mdss/mdss_dsi.c +15 −47 Original line number Diff line number Diff line Loading @@ -1099,15 +1099,18 @@ int mdss_dsi_switch_mode(struct mdss_panel_data *pdata, int mode) ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); if (pinfo->dms_mode != DYNAMIC_MODE_SWITCH_IMMEDIATE) { if ((pinfo->dms_mode != DYNAMIC_MODE_RESOLUTION_SWITCH_IMMEDIATE) && (pinfo->dms_mode != DYNAMIC_MODE_SWITCH_IMMEDIATE)) { pr_debug("%s: Dynamic mode switch not enabled.\n", __func__); return -EPERM; } if (mode == MIPI_VIDEO_PANEL) { mode = DSI_VIDEO_MODE; mode = SWITCH_TO_VIDEO_MODE; } else if (mode == MIPI_CMD_PANEL) { mode = DSI_CMD_MODE; mode = SWITCH_TO_CMD_MODE; } else if (mode == SWITCH_RESOLUTION) { pr_debug("Resolution switch mode selected\n"); } else { pr_err("Invalid mode selected, mode=%d\n", mode); return -EINVAL; Loading @@ -1115,6 +1118,7 @@ int mdss_dsi_switch_mode(struct mdss_panel_data *pdata, int mode) mdss_dsi_clk_ctrl(ctrl_pdata, ctrl_pdata->dsi_clk_handle, MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_ON); mdss_dsi_ctrl_setup(ctrl_pdata); ctrl_pdata->switch_mode(pdata, mode); mdss_dsi_clk_ctrl(ctrl_pdata, ctrl_pdata->dsi_clk_handle, MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_OFF); Loading Loading @@ -1353,8 +1357,9 @@ static int mdss_dsi_unblank(struct mdss_panel_data *pdata) panel_data); mipi = &pdata->panel_info.mipi; pr_debug("%s+: ctrl=%p ndx=%d cur_blank_state=%d\n", __func__, ctrl_pdata, ctrl_pdata->ndx, pdata->panel_info.blank_state); pr_debug("%s+: ctrl=%p ndx=%d cur_blank_state=%d ctrl_state=%x\n", __func__, ctrl_pdata, ctrl_pdata->ndx, pdata->panel_info.blank_state, ctrl_pdata->ctrl_state); if (mdss_dsi_is_ctrl_clk_master(ctrl_pdata)) sctrl = mdss_dsi_get_ctrl_clk_slave(); Loading Loading @@ -1442,9 +1447,9 @@ static int mdss_dsi_blank(struct mdss_panel_data *pdata, int power_state) 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); ctrl_pdata->switch_mode(pdata, SWITCH_TO_VIDEO_MODE); } else if (pdata->panel_info.type == MIPI_VIDEO_PANEL) { ctrl_pdata->switch_mode(pdata, DSI_CMD_MODE); ctrl_pdata->switch_mode(pdata, SWITCH_TO_CMD_MODE); mdss_dsi_set_tear_off(ctrl_pdata); } } Loading Loading @@ -1989,46 +1994,6 @@ int mdss_dsi_register_recovery_handler(struct mdss_dsi_ctrl_pdata *ctrl, return 0; } static int mdss_dsi_clk_refresh(struct mdss_panel_data *pdata) { struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; int rc = 0; ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); rc = mdss_dsi_clk_div_config(&pdata->panel_info, pdata->panel_info.mipi.frame_rate); if (rc) { pr_err("%s: unable to initialize the clk dividers\n", __func__); return rc; } ctrl_pdata->refresh_clk_rate = false; ctrl_pdata->pclk_rate = pdata->panel_info.mipi.dsi_pclk_rate; ctrl_pdata->byte_clk_rate = pdata->panel_info.clk_rate / 8; pr_debug("%s ctrl_pdata->byte_clk_rate=%d ctrl_pdata->pclk_rate=%d\n", __func__, ctrl_pdata->byte_clk_rate, ctrl_pdata->pclk_rate); rc = mdss_dsi_clk_set_link_rate(ctrl_pdata->dsi_clk_handle, MDSS_DSI_LINK_BYTE_CLK, ctrl_pdata->byte_clk_rate, MDSS_DSI_CLK_UPDATE_CLK_RATE_AT_ON); if (rc) { pr_err("%s: dsi_byte_clk - clk_set_rate failed\n", __func__); return rc; } rc = mdss_dsi_clk_set_link_rate(ctrl_pdata->dsi_clk_handle, MDSS_DSI_LINK_PIX_CLK, ctrl_pdata->pclk_rate, MDSS_DSI_CLK_UPDATE_CLK_RATE_AT_ON); if (rc) { pr_err("%s: dsi_pixel_clk - clk_set_rate failed\n", __func__); return rc; } return rc; } static int mdss_dsi_event_handler(struct mdss_panel_data *pdata, int event, void *arg) { Loading Loading @@ -2143,6 +2108,9 @@ static int mdss_dsi_event_handler(struct mdss_panel_data *pdata, if (ctrl_pdata->check_status) rc = ctrl_pdata->check_status(ctrl_pdata); break; case MDSS_EVENT_PANEL_TIMING_SWITCH: rc = mdss_dsi_panel_timing_switch(ctrl_pdata, arg); break; case MDSS_EVENT_FB_REGISTERED: mdss_dsi_debugfs_init(ctrl_pdata); break; Loading drivers/video/msm/mdss/mdss_dsi.h +18 −2 Original line number Diff line number Diff line Loading @@ -310,6 +310,18 @@ struct dsi_panel_cmds { int link_state; }; struct dsi_panel_timing { struct mdss_panel_timing timing; uint32_t phy_timing[12]; uint32_t phy_timing_8996[40]; /* DSI_CLKOUT_TIMING_CTRL */ char t_clk_post; char t_clk_pre; struct dsi_panel_cmds on_cmds; struct dsi_panel_cmds post_panel_on_cmds; struct dsi_panel_cmds switch_cmds; }; struct dsi_kickoff_action { struct list_head act_entry; void (*action) (void *); Loading Loading @@ -491,10 +503,10 @@ int dsi_panel_device_register(struct platform_device *ctrl_pdev, struct device_node *pan_node, struct mdss_dsi_ctrl_pdata *ctrl_pdata); int mdss_dsi_cmds_tx(struct mdss_dsi_ctrl_pdata *ctrl, struct dsi_cmd_desc *cmds, int cnt); struct dsi_cmd_desc *cmds, int cnt, int use_dma_tpg); int mdss_dsi_cmds_rx(struct mdss_dsi_ctrl_pdata *ctrl, struct dsi_cmd_desc *cmds, int rlen); struct dsi_cmd_desc *cmds, int rlen, int use_dma_tpg); void mdss_dsi_host_init(struct mdss_panel_data *pdata); void mdss_dsi_op_mode_config(int mode, Loading @@ -520,6 +532,7 @@ void mdss_dsi_irq_handler_config(struct mdss_dsi_ctrl_pdata *ctrl_pdata); void mdss_dsi_set_tx_power_mode(int mode, struct mdss_panel_data *pdata); int mdss_dsi_clk_div_config(struct mdss_panel_info *panel_info, int frame_rate); int mdss_dsi_clk_refresh(struct mdss_panel_data *pdata); int mdss_dsi_link_clk_init(struct platform_device *pdev, struct mdss_dsi_ctrl_pdata *ctrl_pdata); void mdss_dsi_link_clk_deinit(struct device *dev, Loading Loading @@ -570,6 +583,9 @@ u32 mdss_dsi_panel_cmd_read(struct mdss_dsi_ctrl_pdata *ctrl, char cmd0, int mdss_dsi_panel_init(struct device_node *node, struct mdss_dsi_ctrl_pdata *ctrl_pdata, bool cmd_cfg_cont_splash); int mdss_dsi_panel_timing_switch(struct mdss_dsi_ctrl_pdata *ctrl_pdata, struct mdss_panel_timing *timing); int mdss_panel_parse_bl_settings(struct device_node *np, struct mdss_dsi_ctrl_pdata *ctrl_pdata); int mdss_panel_get_dst_fmt(u32 bpp, char mipi_mode, u32 pixel_packing, Loading drivers/video/msm/mdss/mdss_dsi_cmd.h +1 −0 Original line number Diff line number Diff line Loading @@ -100,6 +100,7 @@ struct dsi_cmd_desc { #define CMD_REQ_COMMIT 0x0002 #define CMD_CLK_CTRL 0x0004 #define CMD_REQ_UNICAST 0x0008 #define CMD_REQ_DMA_TPG 0x0040 #define CMD_REQ_NO_MAX_PKT_SIZE 0x0008 #define CMD_REQ_LP_MODE 0x0010 #define CMD_REQ_HS_MODE 0x0020 Loading drivers/video/msm/mdss/mdss_dsi_host.c +163 −42 Original line number Diff line number Diff line Loading @@ -30,6 +30,8 @@ #include "mdss_smmu.h" #define VSYNC_PERIOD 17 #define DMA_TX_TIMEOUT 200 #define DMA_TPG_FIFO_LEN 64 struct mdss_dsi_ctrl_pdata *ctrl_list[DSI_CTRL_MAX]; Loading Loading @@ -1076,7 +1078,6 @@ static void mdss_dsi_mode_setup(struct mdss_panel_data *pdata) struct mdss_panel_info *pinfo; struct mipi_panel_info *mipi; struct dsc_desc *dsc = NULL; u64 clk_rate; u32 hbp, hfp, vbp, vfp, hspw, vspw, width, height; u32 ystride, bpp, dst_bpp, byte_num; u32 stream_ctrl, stream_total; Loading @@ -1090,9 +1091,6 @@ static void mdss_dsi_mode_setup(struct mdss_panel_data *pdata) if (pinfo->compression_mode == COMPRESSION_DSC) dsc = &pinfo->dsc; clk_rate = pdata->panel_info.clk_rate; clk_rate = min(clk_rate, pdata->panel_info.clk_max); dst_bpp = pdata->panel_info.fbc.enabled ? (pdata->panel_info.fbc.target_bpp) : (pinfo->bpp); Loading @@ -1105,6 +1103,8 @@ static void mdss_dsi_mode_setup(struct mdss_panel_data *pdata) width = mult_frac(pdata->panel_info.xres, dst_bpp, pdata->panel_info.bpp); height = pdata->panel_info.yres; pr_debug("%s: fbc=%d width=%d height=%d dst_bpp=%d\n", __func__, pdata->panel_info.fbc.enabled, width, height, dst_bpp); if (dsc) /* compressed */ width = dsc->pclk_per_line; Loading @@ -1117,11 +1117,11 @@ static void mdss_dsi_mode_setup(struct mdss_panel_data *pdata) pdata->panel_info.lcdc.border_bottom; } mipi = &pdata->panel_info.mipi; if (pdata->panel_info.type == MIPI_VIDEO_PANEL) { vsync_period = vspw + vbp + height + dummy_yres + vfp; hsync_period = hspw + hbp + width + dummy_xres + hfp; mipi = &pdata->panel_info.mipi; if (pdata->panel_info.type == MIPI_VIDEO_PANEL) { if (ctrl_pdata->shared_data->timing_db_mode) MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x1e8, 0x1); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x24, Loading Loading @@ -1287,8 +1287,107 @@ static int mdss_dsi_cmd_dma_tx(struct mdss_dsi_ctrl_pdata *ctrl, static int mdss_dsi_cmd_dma_rx(struct mdss_dsi_ctrl_pdata *ctrl, struct dsi_buf *rp, int rlen); static int mdss_dsi_cmd_dma_tpg_tx(struct mdss_dsi_ctrl_pdata *ctrl, struct dsi_buf *tp) { int len, i, ret = 0, data = 0; u32 *bp, ctrl_rev; struct mdss_dsi_ctrl_pdata *mctrl = NULL; if (tp->len > DMA_TPG_FIFO_LEN) { pr_debug("command length more than FIFO length\n"); return -EINVAL; } ctrl_rev = MIPI_INP(ctrl->ctrl_base); if (ctrl_rev < MDSS_DSI_HW_REV_103) { pr_err("CMD DMA TPG not supported for this DSI version\n"); return -EINVAL; } bp = (u32 *)tp->data; len = ALIGN(tp->len, 4); reinit_completion(&ctrl->dma_comp); if (mdss_dsi_sync_wait_trigger(ctrl)) mctrl = mdss_dsi_get_other_ctrl(ctrl); data = BIT(16) | BIT(17); /* select CMD_DMA_PATTERN_SEL to 3 */ data |= BIT(2); /* select CMD_DMA_FIFO_MODE to 1 */ data |= BIT(1); /* enable CMD_DMA_TPG */ MIPI_OUTP(ctrl->ctrl_base + 0x15c, data); if (mctrl) MIPI_OUTP(mctrl->ctrl_base + 0x15c, data); /* * The DMA command parameters need to be programmed to the DMA_INIT_VAL * register in the proper order. The 'len' value will be a multiple * of 4, the padding bytes to make sure of this will be taken care of in * mdss_dsi_cmd_dma_add API. */ for (i = 0; i < len; i += 4) { MIPI_OUTP(ctrl->ctrl_base + 0x17c, *bp); if (mctrl) MIPI_OUTP(mctrl->ctrl_base + 0x17c, *bp); wmb(); /* make sure write happens before writing next command */ bp++; } /* * The number of writes to the DMA_INIT_VAL register should be an even * number of dwords (32 bits). In case 'len' is not a multiple of 8, * we need to do make an extra write to the register with 0x00 to * satisfy this condition. */ if ((len % 8) != 0) { MIPI_OUTP(ctrl->ctrl_base + 0x17c, 0x00); if (mctrl) MIPI_OUTP(mctrl->ctrl_base + 0x17c, 0x00); } if (mctrl) { MIPI_OUTP(mctrl->ctrl_base + 0x04c, len); MIPI_OUTP(mctrl->ctrl_base + 0x090, 0x01); /* trigger */ } MIPI_OUTP(ctrl->ctrl_base + 0x04c, len); wmb(); /* make sure DMA length is programmed */ MIPI_OUTP(ctrl->ctrl_base + 0x090, 0x01); /* trigger */ wmb(); /* make sure DMA trigger happens */ ret = wait_for_completion_timeout(&ctrl->dma_comp, msecs_to_jiffies(DMA_TX_TIMEOUT)); if (ret == 0) ret = -ETIMEDOUT; else ret = tp->len; /* Reset the DMA TPG FIFO */ MIPI_OUTP(ctrl->ctrl_base + 0x1ec, 0x1); wmb(); /* make sure FIFO reset happens */ MIPI_OUTP(ctrl->ctrl_base + 0x1ec, 0x0); wmb(); /* make sure FIFO reset happens */ /* Disable CMD_DMA_TPG */ MIPI_OUTP(ctrl->ctrl_base + 0x15c, 0x0); if (mctrl) { /* Reset the DMA TPG FIFO */ MIPI_OUTP(mctrl->ctrl_base + 0x1ec, 0x1); wmb(); /* make sure FIFO reset happens */ MIPI_OUTP(mctrl->ctrl_base + 0x1ec, 0x0); wmb(); /* make sure FIFO reset happens */ /* Disable CMD_DMA_TPG */ MIPI_OUTP(mctrl->ctrl_base + 0x15c, 0x0); } return ret; } static int mdss_dsi_cmds2buf_tx(struct mdss_dsi_ctrl_pdata *ctrl, struct dsi_cmd_desc *cmds, int cnt) struct dsi_cmd_desc *cmds, int cnt, int use_dma_tpg) { struct dsi_buf *tp; struct dsi_cmd_desc *cm; Loading @@ -1315,13 +1414,18 @@ static int mdss_dsi_cmds2buf_tx(struct mdss_dsi_ctrl_pdata *ctrl, wait = mdss_dsi_wait4video_eng_busy(ctrl); mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM); if (use_dma_tpg) len = mdss_dsi_cmd_dma_tpg_tx(ctrl, tp); else len = mdss_dsi_cmd_dma_tx(ctrl, tp); if (IS_ERR_VALUE(len)) { mdss_dsi_disable_irq(ctrl, DSI_CMD_TERM); pr_err("%s: failed to call cmd_dma_tx for cmd = 0x%x\n", __func__, cmds->payload[0]); __func__, cm->payload[0]); return 0; } pr_debug("%s: cmd_dma_tx for cmd = 0x%x, len = %d\n", __func__, cm->payload[0], len); if (!wait || dchdr->wait > VSYNC_PERIOD) usleep_range(dchdr->wait * 1000, dchdr->wait * 1000); Loading Loading @@ -1373,7 +1477,7 @@ static inline bool __mdss_dsi_cmd_mode_config( * thread context only */ int mdss_dsi_cmds_tx(struct mdss_dsi_ctrl_pdata *ctrl, struct dsi_cmd_desc *cmds, int cnt) struct dsi_cmd_desc *cmds, int cnt, int use_dma_tpg) { int len = 0; struct mdss_dsi_ctrl_pdata *mctrl = NULL; Loading Loading @@ -1408,7 +1512,7 @@ int mdss_dsi_cmds_tx(struct mdss_dsi_ctrl_pdata *ctrl, do_send: ctrl->cmd_cfg_restore = __mdss_dsi_cmd_mode_config(ctrl, 1); len = mdss_dsi_cmds2buf_tx(ctrl, cmds, cnt); len = mdss_dsi_cmds2buf_tx(ctrl, cmds, cnt, use_dma_tpg); if (!len) pr_err("%s: failed to call\n", __func__); Loading Loading @@ -1449,7 +1553,7 @@ static struct dsi_cmd_desc pkt_size_cmd = { * */ int mdss_dsi_cmds_rx(struct mdss_dsi_ctrl_pdata *ctrl, struct dsi_cmd_desc *cmds, int rlen) struct dsi_cmd_desc *cmds, int rlen, int use_dma_tpg) { int data_byte, rx_byte, dlen, end; int short_response, diff, pkt_size, ret = 0; Loading Loading @@ -1531,6 +1635,9 @@ do_send: mdss_dsi_wait4video_eng_busy(ctrl); mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM); if (use_dma_tpg) ret = mdss_dsi_cmd_dma_tpg_tx(ctrl, tp); else ret = mdss_dsi_cmd_dma_tx(ctrl, tp); if (IS_ERR_VALUE(ret)) { mdss_dsi_disable_irq(ctrl, DSI_CMD_TERM); Loading Loading @@ -1564,6 +1671,9 @@ do_send: mdss_dsi_wait4video_eng_busy(ctrl); /* video mode only */ mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM); /* transmit read comamnd to client */ if (use_dma_tpg) ret = mdss_dsi_cmd_dma_tpg_tx(ctrl, tp); else ret = mdss_dsi_cmd_dma_tx(ctrl, tp); if (IS_ERR_VALUE(ret)) { mdss_dsi_disable_irq(ctrl, DSI_CMD_TERM); Loading Loading @@ -1665,8 +1775,6 @@ end: return rp->read_cnt; } #define DMA_TX_TIMEOUT 200 static int mdss_dsi_cmd_dma_tx(struct mdss_dsi_ctrl_pdata *ctrl, struct dsi_buf *tp) { Loading Loading @@ -2096,7 +2204,8 @@ int mdss_dsi_cmdlist_tx(struct mdss_dsi_ctrl_pdata *ctrl, ctrl->do_unicast = true; } len = mdss_dsi_cmds_tx(ctrl, req->cmds, req->cmds_cnt); len = mdss_dsi_cmds_tx(ctrl, req->cmds, req->cmds_cnt, (req->flags & CMD_REQ_DMA_TPG)); if (req->cb) req->cb(len); Loading @@ -2112,7 +2221,8 @@ int mdss_dsi_cmdlist_rx(struct mdss_dsi_ctrl_pdata *ctrl, if (req->rbuf) { rp = &ctrl->rx_buf; len = mdss_dsi_cmds_rx(ctrl, req->cmds, req->rlen); len = mdss_dsi_cmds_rx(ctrl, req->cmds, req->rlen, (req->flags & CMD_REQ_DMA_TPG)); memcpy(req->rbuf, rp->data, rp->len); ctrl->rx_len = len; } else { Loading @@ -2133,6 +2243,7 @@ int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp) int ret = -EINVAL; int rc = 0; bool hs_req = false; u32 ctrl_rev; if (mdss_get_sd_client_cnt()) return -EPERM; Loading @@ -2155,6 +2266,12 @@ int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp) /* make sure dsi_cmd_mdp is idle */ mdss_dsi_cmd_mdp_busy(ctrl); ctrl_rev = MIPI_INP(ctrl->ctrl_base); /* For DSI versions less than 1.3.0, CMD DMA TPG is not supported */ if (req && (ctrl_rev < MDSS_DSI_HW_REV_103)) req->flags &= ~CMD_REQ_DMA_TPG; pr_debug("%s: ctrl=%d from_mdp=%d pid=%d\n", __func__, ctrl->ndx, from_mdp, current->pid); Loading @@ -2181,6 +2298,9 @@ int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp) MDSS_XLOG(ctrl->ndx, req->flags, req->cmds_cnt, from_mdp, current->pid); pr_debug("%s: from_mdp=%d pid=%d\n", __func__, from_mdp, current->pid); if (!(req->flags & CMD_REQ_DMA_TPG)) { /* * mdss interrupt is generated in mdp core clock domain * mdp clock need to be enabled to receive dsi interrupt Loading @@ -2195,8 +2315,6 @@ int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp) return rc; } pr_debug("%s: from_mdp=%d pid=%d\n", __func__, from_mdp, current->pid); if (ctrl->mdss_util->iommu_ctrl) { rc = ctrl->mdss_util->iommu_ctrl(1); if (IS_ERR_VALUE(rc)) { Loading @@ -2205,6 +2323,7 @@ int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp) return rc; } } } mdss_dsi_clk_ctrl(ctrl, ctrl->dsi_clk_handle, MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_ON); Loading @@ -2220,13 +2339,15 @@ int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp) if (req->flags & CMD_REQ_HS_MODE) mdss_dsi_set_tx_power_mode(1, &ctrl->panel_data); if (!(req->flags & CMD_REQ_DMA_TPG)) { if (ctrl->mdss_util->iommu_ctrl) ctrl->mdss_util->iommu_ctrl(0); (void)mdss_dsi_bus_bandwidth_vote(ctrl->shared_data, false); mdss_dsi_clk_ctrl(ctrl, ctrl->dsi_clk_handle, MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_OFF); } (void)mdss_dsi_bus_bandwidth_vote(ctrl->shared_data, false); need_lock: MDSS_XLOG(ctrl->ndx, from_mdp, ctrl->mdp_busy, current->pid, Loading Loading
Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt +41 −0 Original line number Diff line number Diff line Loading @@ -384,6 +384,8 @@ Optional properties: go blank during transition. "dynamic-switch-immediate"= Switch on next frame update. Panel will not go blank for this transition. "dynamic-resolution-switch-immediate"= Switch the panel resolution. Panel will not go blank for this transition. - qcom,mdss-dsi-post-mode-switch-on-command: Multiple dcs packets used for turning on DSI panel after panel has switch modes. Refer to "qcom,mdss-dsi-on-command" section for adding commands. Loading Loading @@ -453,6 +455,20 @@ Optional properites: - qcom,adjust-timer-wakeup-ms: An integer value to indicate the timer delay(in ms) to accommodate s/w delay while configuring the event timer wakeup logic. - qcom,mdss-dsi-display-timings: Parent node that lists the different resolutions that the panel supports. Each child represents timings settings for a specific resolution. Additional properties added to the second level nodes that represent timings properties: - qcom,mdss-dsi-timing-default: Property that specifies the current child as the default timing configuration that will be used. - qcom,mdss-dsi-timing-switch-command: List of commands that need to be sent to panel when the resolution/timing switch happens dynamically. Refer to "qcom,mdss-dsi-on-command" section for adding commands. - qcom,mdss-dsi-timing-switch-command-state: String that specifies the ctrl state for sending resolution switch commands. "dsi_lp_mode" = DSI low power mode (default) "dsi_hs_mode" = DSI high speed mode Note, if a given optional qcom,* binding is not present, then the driver will configure the default values specified. Loading Loading @@ -594,6 +610,31 @@ Example: qcom,mdss-dsi-force-clock-lane-hs; qcom,compression-mode = "dsc"; qcom,adjust-timer-wakeup-ms = <1>; qcom,mdss-dsi-display-timings { wqhd { qcom,mdss-dsi-timing-default; qcom,mdss-dsi-panel-width = <720>; qcom,mdss-dsi-panel-height = <2560>; qcom,mdss-dsi-h-front-porch = <20>; qcom,mdss-dsi-h-back-porch = <8>; qcom,mdss-dsi-h-pulse-width = <8>; qcom,mdss-dsi-h-sync-skew = <0>; qcom,mdss-dsi-v-back-porch = <4>; qcom,mdss-dsi-v-front-porch = <728>; qcom,mdss-dsi-v-pulse-width = <4>; qcom,mdss-dsi-panel-framerate = <60>; qcom,mdss-dsi-panel-timings = [E6 38 26 00 68 6E 2A 3C 2C 03 04 00]; qcom,mdss-dsi-t-clk-post = <0x02>; qcom,mdss-dsi-t-clk-pre = <0x2a>; qcom,mdss-dsi-on-command = [05 01 00 00 a0 00 02 11 00 05 01 00 00 02 00 02 29 00]; qcom,mdss-dsi-on-command-state = "dsi_lp_mode"; qcom,mdss-dsi-timing-switch-command = [ 29 00 00 00 00 00 02 B0 04 29 00 00 00 00 00 02 F1 00]; qcom,mdss-dsi-timing-switch-command-state = "dsi_lp_mode"; }; }; qcom,panel-supply-entries { #address-cells = <1>; #size-cells = <0>; Loading
drivers/video/msm/mdss/mdss_dsi.c +15 −47 Original line number Diff line number Diff line Loading @@ -1099,15 +1099,18 @@ int mdss_dsi_switch_mode(struct mdss_panel_data *pdata, int mode) ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); if (pinfo->dms_mode != DYNAMIC_MODE_SWITCH_IMMEDIATE) { if ((pinfo->dms_mode != DYNAMIC_MODE_RESOLUTION_SWITCH_IMMEDIATE) && (pinfo->dms_mode != DYNAMIC_MODE_SWITCH_IMMEDIATE)) { pr_debug("%s: Dynamic mode switch not enabled.\n", __func__); return -EPERM; } if (mode == MIPI_VIDEO_PANEL) { mode = DSI_VIDEO_MODE; mode = SWITCH_TO_VIDEO_MODE; } else if (mode == MIPI_CMD_PANEL) { mode = DSI_CMD_MODE; mode = SWITCH_TO_CMD_MODE; } else if (mode == SWITCH_RESOLUTION) { pr_debug("Resolution switch mode selected\n"); } else { pr_err("Invalid mode selected, mode=%d\n", mode); return -EINVAL; Loading @@ -1115,6 +1118,7 @@ int mdss_dsi_switch_mode(struct mdss_panel_data *pdata, int mode) mdss_dsi_clk_ctrl(ctrl_pdata, ctrl_pdata->dsi_clk_handle, MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_ON); mdss_dsi_ctrl_setup(ctrl_pdata); ctrl_pdata->switch_mode(pdata, mode); mdss_dsi_clk_ctrl(ctrl_pdata, ctrl_pdata->dsi_clk_handle, MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_OFF); Loading Loading @@ -1353,8 +1357,9 @@ static int mdss_dsi_unblank(struct mdss_panel_data *pdata) panel_data); mipi = &pdata->panel_info.mipi; pr_debug("%s+: ctrl=%p ndx=%d cur_blank_state=%d\n", __func__, ctrl_pdata, ctrl_pdata->ndx, pdata->panel_info.blank_state); pr_debug("%s+: ctrl=%p ndx=%d cur_blank_state=%d ctrl_state=%x\n", __func__, ctrl_pdata, ctrl_pdata->ndx, pdata->panel_info.blank_state, ctrl_pdata->ctrl_state); if (mdss_dsi_is_ctrl_clk_master(ctrl_pdata)) sctrl = mdss_dsi_get_ctrl_clk_slave(); Loading Loading @@ -1442,9 +1447,9 @@ static int mdss_dsi_blank(struct mdss_panel_data *pdata, int power_state) 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); ctrl_pdata->switch_mode(pdata, SWITCH_TO_VIDEO_MODE); } else if (pdata->panel_info.type == MIPI_VIDEO_PANEL) { ctrl_pdata->switch_mode(pdata, DSI_CMD_MODE); ctrl_pdata->switch_mode(pdata, SWITCH_TO_CMD_MODE); mdss_dsi_set_tear_off(ctrl_pdata); } } Loading Loading @@ -1989,46 +1994,6 @@ int mdss_dsi_register_recovery_handler(struct mdss_dsi_ctrl_pdata *ctrl, return 0; } static int mdss_dsi_clk_refresh(struct mdss_panel_data *pdata) { struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; int rc = 0; ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); rc = mdss_dsi_clk_div_config(&pdata->panel_info, pdata->panel_info.mipi.frame_rate); if (rc) { pr_err("%s: unable to initialize the clk dividers\n", __func__); return rc; } ctrl_pdata->refresh_clk_rate = false; ctrl_pdata->pclk_rate = pdata->panel_info.mipi.dsi_pclk_rate; ctrl_pdata->byte_clk_rate = pdata->panel_info.clk_rate / 8; pr_debug("%s ctrl_pdata->byte_clk_rate=%d ctrl_pdata->pclk_rate=%d\n", __func__, ctrl_pdata->byte_clk_rate, ctrl_pdata->pclk_rate); rc = mdss_dsi_clk_set_link_rate(ctrl_pdata->dsi_clk_handle, MDSS_DSI_LINK_BYTE_CLK, ctrl_pdata->byte_clk_rate, MDSS_DSI_CLK_UPDATE_CLK_RATE_AT_ON); if (rc) { pr_err("%s: dsi_byte_clk - clk_set_rate failed\n", __func__); return rc; } rc = mdss_dsi_clk_set_link_rate(ctrl_pdata->dsi_clk_handle, MDSS_DSI_LINK_PIX_CLK, ctrl_pdata->pclk_rate, MDSS_DSI_CLK_UPDATE_CLK_RATE_AT_ON); if (rc) { pr_err("%s: dsi_pixel_clk - clk_set_rate failed\n", __func__); return rc; } return rc; } static int mdss_dsi_event_handler(struct mdss_panel_data *pdata, int event, void *arg) { Loading Loading @@ -2143,6 +2108,9 @@ static int mdss_dsi_event_handler(struct mdss_panel_data *pdata, if (ctrl_pdata->check_status) rc = ctrl_pdata->check_status(ctrl_pdata); break; case MDSS_EVENT_PANEL_TIMING_SWITCH: rc = mdss_dsi_panel_timing_switch(ctrl_pdata, arg); break; case MDSS_EVENT_FB_REGISTERED: mdss_dsi_debugfs_init(ctrl_pdata); break; Loading
drivers/video/msm/mdss/mdss_dsi.h +18 −2 Original line number Diff line number Diff line Loading @@ -310,6 +310,18 @@ struct dsi_panel_cmds { int link_state; }; struct dsi_panel_timing { struct mdss_panel_timing timing; uint32_t phy_timing[12]; uint32_t phy_timing_8996[40]; /* DSI_CLKOUT_TIMING_CTRL */ char t_clk_post; char t_clk_pre; struct dsi_panel_cmds on_cmds; struct dsi_panel_cmds post_panel_on_cmds; struct dsi_panel_cmds switch_cmds; }; struct dsi_kickoff_action { struct list_head act_entry; void (*action) (void *); Loading Loading @@ -491,10 +503,10 @@ int dsi_panel_device_register(struct platform_device *ctrl_pdev, struct device_node *pan_node, struct mdss_dsi_ctrl_pdata *ctrl_pdata); int mdss_dsi_cmds_tx(struct mdss_dsi_ctrl_pdata *ctrl, struct dsi_cmd_desc *cmds, int cnt); struct dsi_cmd_desc *cmds, int cnt, int use_dma_tpg); int mdss_dsi_cmds_rx(struct mdss_dsi_ctrl_pdata *ctrl, struct dsi_cmd_desc *cmds, int rlen); struct dsi_cmd_desc *cmds, int rlen, int use_dma_tpg); void mdss_dsi_host_init(struct mdss_panel_data *pdata); void mdss_dsi_op_mode_config(int mode, Loading @@ -520,6 +532,7 @@ void mdss_dsi_irq_handler_config(struct mdss_dsi_ctrl_pdata *ctrl_pdata); void mdss_dsi_set_tx_power_mode(int mode, struct mdss_panel_data *pdata); int mdss_dsi_clk_div_config(struct mdss_panel_info *panel_info, int frame_rate); int mdss_dsi_clk_refresh(struct mdss_panel_data *pdata); int mdss_dsi_link_clk_init(struct platform_device *pdev, struct mdss_dsi_ctrl_pdata *ctrl_pdata); void mdss_dsi_link_clk_deinit(struct device *dev, Loading Loading @@ -570,6 +583,9 @@ u32 mdss_dsi_panel_cmd_read(struct mdss_dsi_ctrl_pdata *ctrl, char cmd0, int mdss_dsi_panel_init(struct device_node *node, struct mdss_dsi_ctrl_pdata *ctrl_pdata, bool cmd_cfg_cont_splash); int mdss_dsi_panel_timing_switch(struct mdss_dsi_ctrl_pdata *ctrl_pdata, struct mdss_panel_timing *timing); int mdss_panel_parse_bl_settings(struct device_node *np, struct mdss_dsi_ctrl_pdata *ctrl_pdata); int mdss_panel_get_dst_fmt(u32 bpp, char mipi_mode, u32 pixel_packing, Loading
drivers/video/msm/mdss/mdss_dsi_cmd.h +1 −0 Original line number Diff line number Diff line Loading @@ -100,6 +100,7 @@ struct dsi_cmd_desc { #define CMD_REQ_COMMIT 0x0002 #define CMD_CLK_CTRL 0x0004 #define CMD_REQ_UNICAST 0x0008 #define CMD_REQ_DMA_TPG 0x0040 #define CMD_REQ_NO_MAX_PKT_SIZE 0x0008 #define CMD_REQ_LP_MODE 0x0010 #define CMD_REQ_HS_MODE 0x0020 Loading
drivers/video/msm/mdss/mdss_dsi_host.c +163 −42 Original line number Diff line number Diff line Loading @@ -30,6 +30,8 @@ #include "mdss_smmu.h" #define VSYNC_PERIOD 17 #define DMA_TX_TIMEOUT 200 #define DMA_TPG_FIFO_LEN 64 struct mdss_dsi_ctrl_pdata *ctrl_list[DSI_CTRL_MAX]; Loading Loading @@ -1076,7 +1078,6 @@ static void mdss_dsi_mode_setup(struct mdss_panel_data *pdata) struct mdss_panel_info *pinfo; struct mipi_panel_info *mipi; struct dsc_desc *dsc = NULL; u64 clk_rate; u32 hbp, hfp, vbp, vfp, hspw, vspw, width, height; u32 ystride, bpp, dst_bpp, byte_num; u32 stream_ctrl, stream_total; Loading @@ -1090,9 +1091,6 @@ static void mdss_dsi_mode_setup(struct mdss_panel_data *pdata) if (pinfo->compression_mode == COMPRESSION_DSC) dsc = &pinfo->dsc; clk_rate = pdata->panel_info.clk_rate; clk_rate = min(clk_rate, pdata->panel_info.clk_max); dst_bpp = pdata->panel_info.fbc.enabled ? (pdata->panel_info.fbc.target_bpp) : (pinfo->bpp); Loading @@ -1105,6 +1103,8 @@ static void mdss_dsi_mode_setup(struct mdss_panel_data *pdata) width = mult_frac(pdata->panel_info.xres, dst_bpp, pdata->panel_info.bpp); height = pdata->panel_info.yres; pr_debug("%s: fbc=%d width=%d height=%d dst_bpp=%d\n", __func__, pdata->panel_info.fbc.enabled, width, height, dst_bpp); if (dsc) /* compressed */ width = dsc->pclk_per_line; Loading @@ -1117,11 +1117,11 @@ static void mdss_dsi_mode_setup(struct mdss_panel_data *pdata) pdata->panel_info.lcdc.border_bottom; } mipi = &pdata->panel_info.mipi; if (pdata->panel_info.type == MIPI_VIDEO_PANEL) { vsync_period = vspw + vbp + height + dummy_yres + vfp; hsync_period = hspw + hbp + width + dummy_xres + hfp; mipi = &pdata->panel_info.mipi; if (pdata->panel_info.type == MIPI_VIDEO_PANEL) { if (ctrl_pdata->shared_data->timing_db_mode) MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x1e8, 0x1); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x24, Loading Loading @@ -1287,8 +1287,107 @@ static int mdss_dsi_cmd_dma_tx(struct mdss_dsi_ctrl_pdata *ctrl, static int mdss_dsi_cmd_dma_rx(struct mdss_dsi_ctrl_pdata *ctrl, struct dsi_buf *rp, int rlen); static int mdss_dsi_cmd_dma_tpg_tx(struct mdss_dsi_ctrl_pdata *ctrl, struct dsi_buf *tp) { int len, i, ret = 0, data = 0; u32 *bp, ctrl_rev; struct mdss_dsi_ctrl_pdata *mctrl = NULL; if (tp->len > DMA_TPG_FIFO_LEN) { pr_debug("command length more than FIFO length\n"); return -EINVAL; } ctrl_rev = MIPI_INP(ctrl->ctrl_base); if (ctrl_rev < MDSS_DSI_HW_REV_103) { pr_err("CMD DMA TPG not supported for this DSI version\n"); return -EINVAL; } bp = (u32 *)tp->data; len = ALIGN(tp->len, 4); reinit_completion(&ctrl->dma_comp); if (mdss_dsi_sync_wait_trigger(ctrl)) mctrl = mdss_dsi_get_other_ctrl(ctrl); data = BIT(16) | BIT(17); /* select CMD_DMA_PATTERN_SEL to 3 */ data |= BIT(2); /* select CMD_DMA_FIFO_MODE to 1 */ data |= BIT(1); /* enable CMD_DMA_TPG */ MIPI_OUTP(ctrl->ctrl_base + 0x15c, data); if (mctrl) MIPI_OUTP(mctrl->ctrl_base + 0x15c, data); /* * The DMA command parameters need to be programmed to the DMA_INIT_VAL * register in the proper order. The 'len' value will be a multiple * of 4, the padding bytes to make sure of this will be taken care of in * mdss_dsi_cmd_dma_add API. */ for (i = 0; i < len; i += 4) { MIPI_OUTP(ctrl->ctrl_base + 0x17c, *bp); if (mctrl) MIPI_OUTP(mctrl->ctrl_base + 0x17c, *bp); wmb(); /* make sure write happens before writing next command */ bp++; } /* * The number of writes to the DMA_INIT_VAL register should be an even * number of dwords (32 bits). In case 'len' is not a multiple of 8, * we need to do make an extra write to the register with 0x00 to * satisfy this condition. */ if ((len % 8) != 0) { MIPI_OUTP(ctrl->ctrl_base + 0x17c, 0x00); if (mctrl) MIPI_OUTP(mctrl->ctrl_base + 0x17c, 0x00); } if (mctrl) { MIPI_OUTP(mctrl->ctrl_base + 0x04c, len); MIPI_OUTP(mctrl->ctrl_base + 0x090, 0x01); /* trigger */ } MIPI_OUTP(ctrl->ctrl_base + 0x04c, len); wmb(); /* make sure DMA length is programmed */ MIPI_OUTP(ctrl->ctrl_base + 0x090, 0x01); /* trigger */ wmb(); /* make sure DMA trigger happens */ ret = wait_for_completion_timeout(&ctrl->dma_comp, msecs_to_jiffies(DMA_TX_TIMEOUT)); if (ret == 0) ret = -ETIMEDOUT; else ret = tp->len; /* Reset the DMA TPG FIFO */ MIPI_OUTP(ctrl->ctrl_base + 0x1ec, 0x1); wmb(); /* make sure FIFO reset happens */ MIPI_OUTP(ctrl->ctrl_base + 0x1ec, 0x0); wmb(); /* make sure FIFO reset happens */ /* Disable CMD_DMA_TPG */ MIPI_OUTP(ctrl->ctrl_base + 0x15c, 0x0); if (mctrl) { /* Reset the DMA TPG FIFO */ MIPI_OUTP(mctrl->ctrl_base + 0x1ec, 0x1); wmb(); /* make sure FIFO reset happens */ MIPI_OUTP(mctrl->ctrl_base + 0x1ec, 0x0); wmb(); /* make sure FIFO reset happens */ /* Disable CMD_DMA_TPG */ MIPI_OUTP(mctrl->ctrl_base + 0x15c, 0x0); } return ret; } static int mdss_dsi_cmds2buf_tx(struct mdss_dsi_ctrl_pdata *ctrl, struct dsi_cmd_desc *cmds, int cnt) struct dsi_cmd_desc *cmds, int cnt, int use_dma_tpg) { struct dsi_buf *tp; struct dsi_cmd_desc *cm; Loading @@ -1315,13 +1414,18 @@ static int mdss_dsi_cmds2buf_tx(struct mdss_dsi_ctrl_pdata *ctrl, wait = mdss_dsi_wait4video_eng_busy(ctrl); mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM); if (use_dma_tpg) len = mdss_dsi_cmd_dma_tpg_tx(ctrl, tp); else len = mdss_dsi_cmd_dma_tx(ctrl, tp); if (IS_ERR_VALUE(len)) { mdss_dsi_disable_irq(ctrl, DSI_CMD_TERM); pr_err("%s: failed to call cmd_dma_tx for cmd = 0x%x\n", __func__, cmds->payload[0]); __func__, cm->payload[0]); return 0; } pr_debug("%s: cmd_dma_tx for cmd = 0x%x, len = %d\n", __func__, cm->payload[0], len); if (!wait || dchdr->wait > VSYNC_PERIOD) usleep_range(dchdr->wait * 1000, dchdr->wait * 1000); Loading Loading @@ -1373,7 +1477,7 @@ static inline bool __mdss_dsi_cmd_mode_config( * thread context only */ int mdss_dsi_cmds_tx(struct mdss_dsi_ctrl_pdata *ctrl, struct dsi_cmd_desc *cmds, int cnt) struct dsi_cmd_desc *cmds, int cnt, int use_dma_tpg) { int len = 0; struct mdss_dsi_ctrl_pdata *mctrl = NULL; Loading Loading @@ -1408,7 +1512,7 @@ int mdss_dsi_cmds_tx(struct mdss_dsi_ctrl_pdata *ctrl, do_send: ctrl->cmd_cfg_restore = __mdss_dsi_cmd_mode_config(ctrl, 1); len = mdss_dsi_cmds2buf_tx(ctrl, cmds, cnt); len = mdss_dsi_cmds2buf_tx(ctrl, cmds, cnt, use_dma_tpg); if (!len) pr_err("%s: failed to call\n", __func__); Loading Loading @@ -1449,7 +1553,7 @@ static struct dsi_cmd_desc pkt_size_cmd = { * */ int mdss_dsi_cmds_rx(struct mdss_dsi_ctrl_pdata *ctrl, struct dsi_cmd_desc *cmds, int rlen) struct dsi_cmd_desc *cmds, int rlen, int use_dma_tpg) { int data_byte, rx_byte, dlen, end; int short_response, diff, pkt_size, ret = 0; Loading Loading @@ -1531,6 +1635,9 @@ do_send: mdss_dsi_wait4video_eng_busy(ctrl); mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM); if (use_dma_tpg) ret = mdss_dsi_cmd_dma_tpg_tx(ctrl, tp); else ret = mdss_dsi_cmd_dma_tx(ctrl, tp); if (IS_ERR_VALUE(ret)) { mdss_dsi_disable_irq(ctrl, DSI_CMD_TERM); Loading Loading @@ -1564,6 +1671,9 @@ do_send: mdss_dsi_wait4video_eng_busy(ctrl); /* video mode only */ mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM); /* transmit read comamnd to client */ if (use_dma_tpg) ret = mdss_dsi_cmd_dma_tpg_tx(ctrl, tp); else ret = mdss_dsi_cmd_dma_tx(ctrl, tp); if (IS_ERR_VALUE(ret)) { mdss_dsi_disable_irq(ctrl, DSI_CMD_TERM); Loading Loading @@ -1665,8 +1775,6 @@ end: return rp->read_cnt; } #define DMA_TX_TIMEOUT 200 static int mdss_dsi_cmd_dma_tx(struct mdss_dsi_ctrl_pdata *ctrl, struct dsi_buf *tp) { Loading Loading @@ -2096,7 +2204,8 @@ int mdss_dsi_cmdlist_tx(struct mdss_dsi_ctrl_pdata *ctrl, ctrl->do_unicast = true; } len = mdss_dsi_cmds_tx(ctrl, req->cmds, req->cmds_cnt); len = mdss_dsi_cmds_tx(ctrl, req->cmds, req->cmds_cnt, (req->flags & CMD_REQ_DMA_TPG)); if (req->cb) req->cb(len); Loading @@ -2112,7 +2221,8 @@ int mdss_dsi_cmdlist_rx(struct mdss_dsi_ctrl_pdata *ctrl, if (req->rbuf) { rp = &ctrl->rx_buf; len = mdss_dsi_cmds_rx(ctrl, req->cmds, req->rlen); len = mdss_dsi_cmds_rx(ctrl, req->cmds, req->rlen, (req->flags & CMD_REQ_DMA_TPG)); memcpy(req->rbuf, rp->data, rp->len); ctrl->rx_len = len; } else { Loading @@ -2133,6 +2243,7 @@ int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp) int ret = -EINVAL; int rc = 0; bool hs_req = false; u32 ctrl_rev; if (mdss_get_sd_client_cnt()) return -EPERM; Loading @@ -2155,6 +2266,12 @@ int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp) /* make sure dsi_cmd_mdp is idle */ mdss_dsi_cmd_mdp_busy(ctrl); ctrl_rev = MIPI_INP(ctrl->ctrl_base); /* For DSI versions less than 1.3.0, CMD DMA TPG is not supported */ if (req && (ctrl_rev < MDSS_DSI_HW_REV_103)) req->flags &= ~CMD_REQ_DMA_TPG; pr_debug("%s: ctrl=%d from_mdp=%d pid=%d\n", __func__, ctrl->ndx, from_mdp, current->pid); Loading @@ -2181,6 +2298,9 @@ int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp) MDSS_XLOG(ctrl->ndx, req->flags, req->cmds_cnt, from_mdp, current->pid); pr_debug("%s: from_mdp=%d pid=%d\n", __func__, from_mdp, current->pid); if (!(req->flags & CMD_REQ_DMA_TPG)) { /* * mdss interrupt is generated in mdp core clock domain * mdp clock need to be enabled to receive dsi interrupt Loading @@ -2195,8 +2315,6 @@ int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp) return rc; } pr_debug("%s: from_mdp=%d pid=%d\n", __func__, from_mdp, current->pid); if (ctrl->mdss_util->iommu_ctrl) { rc = ctrl->mdss_util->iommu_ctrl(1); if (IS_ERR_VALUE(rc)) { Loading @@ -2205,6 +2323,7 @@ int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp) return rc; } } } mdss_dsi_clk_ctrl(ctrl, ctrl->dsi_clk_handle, MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_ON); Loading @@ -2220,13 +2339,15 @@ int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp) if (req->flags & CMD_REQ_HS_MODE) mdss_dsi_set_tx_power_mode(1, &ctrl->panel_data); if (!(req->flags & CMD_REQ_DMA_TPG)) { if (ctrl->mdss_util->iommu_ctrl) ctrl->mdss_util->iommu_ctrl(0); (void)mdss_dsi_bus_bandwidth_vote(ctrl->shared_data, false); mdss_dsi_clk_ctrl(ctrl, ctrl->dsi_clk_handle, MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_OFF); } (void)mdss_dsi_bus_bandwidth_vote(ctrl->shared_data, false); need_lock: MDSS_XLOG(ctrl->ndx, from_mdp, ctrl->mdp_busy, current->pid, Loading