irqreturn_t mdss_dsi_isr(int irq, void *ptr) { u32 isr; u32 isr0 = 0; struct mdss_dsi_ctrl_pdata *ctrl = (struct mdss_dsi_ctrl_pdata *)ptr; if (!ctrl) { pr_err("%s unable to access ctrl\n", __func__); return IRQ_HANDLED; } if (!ctrl->ctrl_base) { pr_err("%s:%d DSI base adr no Initialized", __func__, __LINE__); return IRQ_HANDLED; } isr = MIPI_INP(ctrl->ctrl_base + 0x0110);/* DSI_INTR_CTRL */ MIPI_OUTP(ctrl->ctrl_base + 0x0110, isr); if (ctrl->shared_pdata.broadcast_enable) if ((ctrl->panel_data.panel_info.pdest == DISPLAY_2) && (left_ctrl_pdata != NULL)) { isr0 = MIPI_INP(left_ctrl_pdata->ctrl_base + 0x0110);/* DSI_INTR_CTRL */ MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0110, isr0 & (~DSI_INTR_CMD_MDP_DONE)); } pr_debug("%s: isr=%x, isr0=%x", __func__, isr, isr0); if (isr & DSI_INTR_ERROR) { #if defined (CONFIG_FB_MSM_MDSS_DSI_DBG) xlog(__func__, ctrl->ndx, ctrl->mdp_busy, isr, 0, 0, 0x97); #endif pr_err("%s: isr[%d]=%x %x", __func__, ctrl->ndx, isr, (int)DSI_INTR_ERROR); mdss_dsi_error(ctrl); } if (isr & DSI_INTR_VIDEO_DONE) { spin_lock(&ctrl->mdp_lock); mdss_dsi_disable_irq_nosync(ctrl, DSI_VIDEO_TERM); complete(&ctrl->video_comp); spin_unlock(&ctrl->mdp_lock); } if (isr & DSI_INTR_CMD_DMA_DONE) { spin_lock(&ctrl->mdp_lock); #if defined (CONFIG_FB_MSM_MDSS_DSI_DBG) xlog(__func__,ctrl->ndx, ctrl->mdp_busy, isr, 0, 0, 0x98); #endif mdss_dsi_disable_irq_nosync(ctrl, DSI_CMD_TERM); complete(&ctrl->dma_comp); spin_unlock(&ctrl->mdp_lock); } if (isr & DSI_INTR_CMD_MDP_DONE) { spin_lock(&ctrl->mdp_lock); #if defined (CONFIG_FB_MSM_MDSS_DSI_DBG) xlog(__func__, ctrl->ndx, ctrl->mdp_busy, isr, 0, 0, 0x99); #endif ctrl->mdp_busy = false; mdss_dsi_disable_irq_nosync(ctrl, DSI_MDP_TERM); complete(&ctrl->mdp_comp); spin_unlock(&ctrl->mdp_lock); } if (isr & DSI_INTR_BTA_DONE) { spin_lock(&ctrl->mdp_lock); mdss_dsi_disable_irq_nosync(ctrl, DSI_BTA_TERM); complete(&ctrl->bta_comp); spin_unlock(&ctrl->mdp_lock); } return IRQ_HANDLED; }
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; }
static int mdss_dsi_ulps_config_sub(struct mdss_dsi_ctrl_pdata *ctrl_pdata, int enable) { int ret = 0; struct mdss_panel_data *pdata = NULL; struct mipi_panel_info *pinfo = NULL; u32 lane_status = 0; u32 active_lanes = 0; if (!ctrl_pdata) { pr_err("%s: invalid input\n", __func__); return -EINVAL; } pdata = &ctrl_pdata->panel_data; if (!pdata) { pr_err("%s: Invalid panel data\n", __func__); return -EINVAL; } pinfo = &pdata->panel_info.mipi; if (!__mdss_dsi_ulps_feature_enabled(pdata)) { pr_debug("%s: ULPS feature not supported. enable=%d\n", __func__, enable); return -ENOTSUPP; } if (enable && !ctrl_pdata->ulps) { /* No need to configure ULPS mode when entering suspend state */ if (!pdata->panel_info.panel_power_on) { pr_err("%s: panel off. returning\n", __func__); goto error; } if (__mdss_dsi_clk_enabled(ctrl_pdata, DSI_LINK_CLKS)) { pr_err("%s: cannot enter ulps mode if dsi clocks are on\n", __func__); ret = -EPERM; goto error; } ret = mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1); if (ret) { pr_err("%s: Failed to enable clocks. rc=%d\n", __func__, ret); goto error; } /* * ULPS Entry Request. * Wait for a short duration to ensure that the lanes * enter ULP state. */ MIPI_OUTP(ctrl_pdata->ctrl_base + 0x0AC, 0x01F); usleep(100); /* Check to make sure that all active data lanes are in ULPS */ if (pinfo->data_lane3) active_lanes |= BIT(11); if (pinfo->data_lane2) active_lanes |= BIT(10); if (pinfo->data_lane1) active_lanes |= BIT(9); if (pinfo->data_lane0) active_lanes |= BIT(8); active_lanes |= BIT(12); /* clock lane */ lane_status = MIPI_INP(ctrl_pdata->ctrl_base + 0xA8); if (lane_status & active_lanes) { pr_err("%s: ULPS entry req failed. Lane status=0x%08x\n", __func__, lane_status); ret = -EINVAL; mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 0); goto error; } /* Enable MMSS DSI Clamps */ MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x14, 0x3FF); MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x14, 0x83FF); wmb(); MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x108, 0x1); /* disable DSI controller */ mdss_dsi_controller_cfg(0, pdata); mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 0); ctrl_pdata->ulps = true; } else if (ctrl_pdata->ulps) { 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); goto error; } MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x108, 0x0); mdss_dsi_phy_init(pdata); __mdss_dsi_ctrl_setup(pdata); mdss_dsi_sw_reset(pdata); mdss_dsi_host_init(pdata); mdss_dsi_op_mode_config(pdata->panel_info.mipi.mode, pdata); /* * ULPS Entry Request. This is needed because, after power * collapse and reset, the DSI controller resets back to * idle state and not ULPS. * Wait for a short duration to ensure that the lanes * enter ULP state. */ MIPI_OUTP(ctrl_pdata->ctrl_base + 0x0AC, 0x01F); usleep(100); /* Disable MMSS DSI Clamps */ MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x14, 0x3FF); MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x14, 0x0); ret = mdss_dsi_clk_ctrl(ctrl_pdata, DSI_LINK_CLKS, 1); if (ret) { pr_err("%s: Failed to enable link clocks. rc=%d\n", __func__, ret); mdss_dsi_clk_ctrl(ctrl_pdata, DSI_BUS_CLKS, 0); goto error; } /* * ULPS Exit Request * Hardware requirement is to wait for at least 1ms */ MIPI_OUTP(ctrl_pdata->ctrl_base + 0x0AC, 0x1F00); usleep(1000); MIPI_OUTP(ctrl_pdata->ctrl_base + 0x0AC, 0x0); /* * Wait for a short duration before enabling * data transmission */ usleep(100); lane_status = MIPI_INP(ctrl_pdata->ctrl_base + 0xA8); mdss_dsi_clk_ctrl(ctrl_pdata, DSI_LINK_CLKS, 0); mdss_dsi_clk_ctrl(ctrl_pdata, DSI_BUS_CLKS, 0); ctrl_pdata->ulps = false; } pr_debug("%s: DSI lane status = 0x%08x. Ulps %s\n", __func__, lane_status, enable ? "enabled" : "disabled"); error: return ret; }
void mdss_dsi_op_mode_config(int mode, struct mdss_panel_data *pdata) { u32 dsi_ctrl, intr_ctrl; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; struct mdss_dsi_ctrl_pdata *mctrl = NULL; if (pdata == NULL) { pr_err("%s: Invalid input data\n", __func__); return; } ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); /* * In broadcast mode, the configuration for master controller * would be done when the slave controller is configured */ if (mdss_dsi_is_master_ctrl(ctrl_pdata)) { pr_debug("%s: Broadcast mode enabled. skipping config for ctrl%d\n", __func__, ctrl_pdata->ndx); return; } dsi_ctrl = MIPI_INP((ctrl_pdata->ctrl_base) + 0x0004); /*If Video enabled, Keep Video and Cmd mode ON */ if (dsi_ctrl & 0x02) dsi_ctrl &= ~0x05; else dsi_ctrl &= ~0x07; if (mode == DSI_VIDEO_MODE) { dsi_ctrl |= 0x03; intr_ctrl = DSI_INTR_CMD_DMA_DONE_MASK | DSI_INTR_BTA_DONE_MASK; } else { /* command mode */ dsi_ctrl |= 0x05; if (pdata->panel_info.type == MIPI_VIDEO_PANEL) dsi_ctrl |= 0x02; intr_ctrl = DSI_INTR_CMD_DMA_DONE_MASK | DSI_INTR_ERROR_MASK | DSI_INTR_CMD_MDP_DONE_MASK | DSI_INTR_BTA_DONE_MASK; } /* Ensure that for slave controller, master is also configured */ if (mdss_dsi_is_slave_ctrl(ctrl_pdata)) { mctrl = mdss_dsi_get_master_ctrl(); if (mctrl) { pr_debug("%s: configuring ctrl%d\n", __func__, mctrl->ndx); MIPI_OUTP(mctrl->ctrl_base + 0x0110, intr_ctrl); MIPI_OUTP(mctrl->ctrl_base + 0x0004, dsi_ctrl); } else { pr_warn("%s: Unable to get master control\n", __func__); } } pr_debug("%s: configuring ctrl%d\n", __func__, ctrl_pdata->ndx); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0110, intr_ctrl); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004, dsi_ctrl); wmb(); }
static void mipi_dsi_configure_serdes(void) { void __iomem *cc; /* PHY registers programemd thru S2P interface */ if (periph_base) { MIPI_OUTP(periph_base + 0x2c, 0x000000b6); MIPI_OUTP(periph_base + 0x2c, 0x000001b5); MIPI_OUTP(periph_base + 0x2c, 0x000001b4); MIPI_OUTP(periph_base + 0x2c, 0x000003b3); MIPI_OUTP(periph_base + 0x2c, 0x000003a2); MIPI_OUTP(periph_base + 0x2c, 0x000002a1); MIPI_OUTP(periph_base + 0x2c, 0x000008a0); MIPI_OUTP(periph_base + 0x2c, 0x00000d9f); MIPI_OUTP(periph_base + 0x2c, 0x0000109e); MIPI_OUTP(periph_base + 0x2c, 0x0000209d); MIPI_OUTP(periph_base + 0x2c, 0x0000109c); MIPI_OUTP(periph_base + 0x2c, 0x0000079a); MIPI_OUTP(periph_base + 0x2c, 0x00000c99); MIPI_OUTP(periph_base + 0x2c, 0x00002298); MIPI_OUTP(periph_base + 0x2c, 0x000000a7); MIPI_OUTP(periph_base + 0x2c, 0x000000a6); MIPI_OUTP(periph_base + 0x2c, 0x000000a5); MIPI_OUTP(periph_base + 0x2c, 0x00007fa4); MIPI_OUTP(periph_base + 0x2c, 0x0000eea8); MIPI_OUTP(periph_base + 0x2c, 0x000006aa); MIPI_OUTP(periph_base + 0x2c, 0x00002095); MIPI_OUTP(periph_base + 0x2c, 0x00000493); MIPI_OUTP(periph_base + 0x2c, 0x00001092); MIPI_OUTP(periph_base + 0x2c, 0x00000691); MIPI_OUTP(periph_base + 0x2c, 0x00005490); MIPI_OUTP(periph_base + 0x2c, 0x0000038d); MIPI_OUTP(periph_base + 0x2c, 0x0000148c); MIPI_OUTP(periph_base + 0x2c, 0x0000058b); MIPI_OUTP(periph_base + 0x2c, 0x0000078a); MIPI_OUTP(periph_base + 0x2c, 0x00001f89); MIPI_OUTP(periph_base + 0x2c, 0x00003388); MIPI_OUTP(periph_base + 0x2c, 0x00006387); MIPI_OUTP(periph_base + 0x2c, 0x00004886); MIPI_OUTP(periph_base + 0x2c, 0x00005085); MIPI_OUTP(periph_base + 0x2c, 0x00000084); MIPI_OUTP(periph_base + 0x2c, 0x0000da83); MIPI_OUTP(periph_base + 0x2c, 0x0000b182); MIPI_OUTP(periph_base + 0x2c, 0x00002f81); MIPI_OUTP(periph_base + 0x2c, 0x00004080); MIPI_OUTP(periph_base + 0x2c, 0x00004180); MIPI_OUTP(periph_base + 0x2c, 0x000006aa); } cc = MIPI_DSI_BASE + 0x0130; MIPI_OUTP(cc, 0x806c11c8); MIPI_OUTP(cc, 0x804c11c8); MIPI_OUTP(cc, 0x806d0080); MIPI_OUTP(cc, 0x804d0080); MIPI_OUTP(cc, 0x00000000); MIPI_OUTP(cc, 0x807b1597); MIPI_OUTP(cc, 0x805b1597); MIPI_OUTP(cc, 0x807c0080); MIPI_OUTP(cc, 0x805c0080); MIPI_OUTP(cc, 0x00000000); MIPI_OUTP(cc, 0x807911c8); MIPI_OUTP(cc, 0x805911c8); MIPI_OUTP(cc, 0x807a0080); MIPI_OUTP(cc, 0x805a0080); MIPI_OUTP(cc, 0x00000000); MIPI_OUTP(cc, 0x80721555); MIPI_OUTP(cc, 0x80521555); MIPI_OUTP(cc, 0x80730000); MIPI_OUTP(cc, 0x80530000); MIPI_OUTP(cc, 0x00000000); }
int mdss_dsi_cmds_rx(struct mdss_dsi_ctrl_pdata *ctrl, struct dsi_cmd_desc *cmds, int rlen) { int cnt, len, diff, pkt_size, ret = 0; struct dsi_buf *tp, *rp; int no_max_pkt_size; char cmd; u32 dsi_ctrl, data; int video_mode; u32 left_dsi_ctrl = 0; bool left_ctrl_restore = false; int rx_flags = 0; bool long_rd_rsp_chk = false; if (ctrl->shared_pdata.broadcast_enable) { if (ctrl->ndx == DSI_CTRL_0) { pr_debug("%s: Broadcast mode. 1st ctrl\n", __func__); return 0; } } if (ctrl->shared_pdata.broadcast_enable) { if ((ctrl->ndx == DSI_CTRL_1) && (left_ctrl_pdata != NULL)) { left_dsi_ctrl = MIPI_INP(left_ctrl_pdata->ctrl_base + 0x0004); video_mode = left_dsi_ctrl & 0x02; /* VIDEO_MODE_EN */ if (video_mode) { data = left_dsi_ctrl | 0x04; /* CMD_MODE_EN */ MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004, data); left_ctrl_restore = true; } } } /* turn on cmd mode * for video mode, do not send cmds more than * one pixel line, since it only transmit it * during BLLP. */ dsi_ctrl = MIPI_INP((ctrl->ctrl_base) + 0x0004); video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */ if (video_mode) { data = dsi_ctrl | 0x04; /* CMD_MODE_EN */ MIPI_OUTP((ctrl->ctrl_base) + 0x0004, data); } no_max_pkt_size = rx_flags & CMD_REQ_NO_MAX_PKT_SIZE; if (no_max_pkt_size) rlen = ALIGN(rlen, 4); /* Only support rlen = 4*n */ len = rlen; diff = 0; if (len < 2) cnt = 4; /* short read */ else if (len == 2) { /* Response could be a short or long read */ cnt = 8; long_rd_rsp_chk = true; } else { if (len > MDSS_DSI_LEN) len = MDSS_DSI_LEN; /* 8 bytes at most */ len = ALIGN(len, 4); /* len 4 bytes align */ diff = len - rlen; /* * add extra 2 bytes to len to have overall * packet size is multipe by 4. This also make * sure 4 bytes dcs headerlocates within a * 32 bits register after shift in. * after all, len should be either 6 or 10. */ len += 2; cnt = len + 6; /* 4 bytes header + 2 bytes crc */ } tp = &ctrl->tx_buf; rp = &ctrl->rx_buf; if (!no_max_pkt_size) { /* packet size need to be set at every read */ pkt_size = len; max_pktsize[0] = pkt_size; mdss_dsi_buf_init(tp); ret = mdss_dsi_cmd_dma_add(tp, &pkt_size_cmd); if (!ret) { pr_err("%s: failed to call\n", __func__); rp->len = 0; goto end; } mdss_dsi_wait4video_eng_busy(ctrl); mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM); ret = mdss_dsi_cmd_dma_tx(ctrl, tp); if (IS_ERR_VALUE(ret)) { mdss_dsi_disable_irq(ctrl, DSI_CMD_TERM); pr_err("%s: failed to call\n", __func__); rp->len = 0; goto end; } pr_debug("%s: Max packet size sent\n", __func__); } mdss_dsi_buf_init(tp); ret = mdss_dsi_cmd_dma_add(tp, cmds); if (!ret) { pr_err("%s: failed to call cmd_dma_add for cmd = 0x%x\n", __func__, cmds->payload[0]); rp->len = 0; goto end; } mdss_dsi_wait4video_eng_busy(ctrl); mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM); /* transmit read comamnd to client */ ret = mdss_dsi_cmd_dma_tx(ctrl, tp); if (IS_ERR_VALUE(ret)) { mdss_dsi_disable_irq(ctrl, DSI_CMD_TERM); pr_err("%s: failed to call\n", __func__); rp->len = 0; goto end; } /* * once cmd_dma_done interrupt received, * return data from client is ready and stored * at RDBK_DATA register already */ mdss_dsi_buf_init(rp); if (no_max_pkt_size) { /* * expect rlen = n * 4 * short alignement for start addr */ rp->data += 2; } mdss_dsi_cmd_dma_rx(ctrl, rp, cnt); if (no_max_pkt_size) { /* * remove extra 2 bytes from previous * rx transaction at shift register * which was inserted during copy * shift registers to rx buffer * rx payload start from long alignment addr */ rp->data += 2; } if (long_rd_rsp_chk && rp->data[0] != DTYPE_GEN_LREAD_RESP && rp->data[0] != DTYPE_DCS_LREAD_RESP) rp->data += 4; cmd = rp->data[0]; switch (cmd) { case DTYPE_ACK_ERR_RESP: pr_debug("%s: rx ACK_ERR_PACLAGE\n", __func__); rp->len = 0; case DTYPE_GEN_READ1_RESP: case DTYPE_DCS_READ1_RESP: mdss_dsi_short_read1_resp(rp); break; case DTYPE_GEN_READ2_RESP: case DTYPE_DCS_READ2_RESP: mdss_dsi_short_read2_resp(rp); break; case DTYPE_GEN_LREAD_RESP: case DTYPE_DCS_LREAD_RESP: mdss_dsi_long_read_resp(rp); if (!long_rd_rsp_chk) { rp->len -= 2; /* extra 2 bytes added */ rp->len -= diff; /* align bytes */ } break; default: pr_warning("%s:Invalid response cmd\n", __func__); rp->len = 0; } end: if (left_ctrl_restore) MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004, left_dsi_ctrl); /*restore */ if (video_mode) MIPI_OUTP((ctrl->ctrl_base) + 0x0004, dsi_ctrl); /* restore */ return rp->len; }
irqreturn_t mdss_dsi_isr(int irq, void *ptr) { u32 isr; struct mdss_dsi_ctrl_pdata *ctrl = (struct mdss_dsi_ctrl_pdata *)ptr; struct mdss_dsi_ctrl_pdata *mctrl = NULL; if (!ctrl->ctrl_base) { pr_err("%s:%d DSI base adr no Initialized", __func__, __LINE__); return IRQ_HANDLED; } isr = MIPI_INP(ctrl->ctrl_base + 0x0110);/* DSI_INTR_CTRL */ MIPI_OUTP(ctrl->ctrl_base + 0x0110, isr); if (mdss_dsi_is_slave_ctrl(ctrl)) { mctrl = mdss_dsi_get_master_ctrl(); if (mctrl) { u32 isr0; isr0 = MIPI_INP(mctrl->ctrl_base + 0x0110); if (isr0 & DSI_INTR_CMD_DMA_DONE) MIPI_OUTP(mctrl->ctrl_base + 0x0110, DSI_INTR_CMD_DMA_DONE); } else { pr_warn("%s: Unable to get master control\n", __func__); } } pr_debug("%s: ndx=%d isr=%x\n", __func__, ctrl->ndx, isr); if (isr & DSI_INTR_ERROR) { MDSS_XLOG(ctrl->ndx, ctrl->mdp_busy, isr, 0x97); pr_err("%s: ndx=%d isr=%x\n", __func__, ctrl->ndx, isr); mdss_dsi_error(ctrl); } if (isr & DSI_INTR_VIDEO_DONE) { spin_lock(&ctrl->mdp_lock); mdss_dsi_disable_irq_nosync(ctrl, DSI_VIDEO_TERM); complete(&ctrl->video_comp); spin_unlock(&ctrl->mdp_lock); } if (isr & DSI_INTR_CMD_DMA_DONE) { MDSS_XLOG(ctrl->ndx, ctrl->mdp_busy, isr, 0x98); spin_lock(&ctrl->mdp_lock); mdss_dsi_disable_irq_nosync(ctrl, DSI_CMD_TERM); complete(&ctrl->dma_comp); spin_unlock(&ctrl->mdp_lock); } if (isr & DSI_INTR_CMD_MDP_DONE) { MDSS_XLOG(ctrl->ndx, ctrl->mdp_busy, isr, 0x99); spin_lock(&ctrl->mdp_lock); ctrl->mdp_busy = false; mdss_dsi_disable_irq_nosync(ctrl, DSI_MDP_TERM); complete(&ctrl->mdp_comp); spin_unlock(&ctrl->mdp_lock); } if (isr & DSI_INTR_BTA_DONE) { spin_lock(&ctrl->mdp_lock); mdss_dsi_disable_irq_nosync(ctrl, DSI_BTA_TERM); complete(&ctrl->bta_comp); spin_unlock(&ctrl->mdp_lock); } return IRQ_HANDLED; }
int mdss_dsi_cmds_rx(struct mdss_dsi_ctrl_pdata *ctrl, struct dsi_cmd_desc *cmds, int rlen, u32 rx_flags) { int cnt, len, diff, pkt_size; struct dsi_buf *tp, *rp; int no_max_pkt_size; char cmd; u32 dsi_ctrl; u32 data; int video_mode; no_max_pkt_size = rx_flags & CMD_REQ_NO_MAX_PKT_SIZE; if (no_max_pkt_size) rlen = ALIGN(rlen, 4); /* Only support rlen = 4*n */ len = rlen; diff = 0; if (len <= 2) cnt = 4; /* short read */ else { if (len > MDSS_DSI_LEN) len = MDSS_DSI_LEN; /* 8 bytes at most */ len = ALIGN(len, 4); /* len 4 bytes align */ diff = len - rlen; /* * add extra 2 bytes to len to have overall * packet size is multipe by 4. This also make * sure 4 bytes dcs headerlocates within a * 32 bits register after shift in. * after all, len should be either 6 or 10. */ len += 2; cnt = len + 6; /* 4 bytes header + 2 bytes crc */ } dsi_ctrl = MIPI_INP((ctrl->ctrl_base) + 0x0004); video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */ if (video_mode) { data = dsi_ctrl | 0x04; /* CMD_MODE_EN */ MIPI_OUTP((ctrl->ctrl_base) + 0x0004, data); } tp = &ctrl->tx_buf; rp = &ctrl->rx_buf; if (!no_max_pkt_size) { /* packet size need to be set at every read */ pkt_size = len; max_pktsize[0] = pkt_size; mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM); mdss_dsi_buf_init(tp); mdss_dsi_cmd_dma_add(tp, &pkt_size_cmd); mdss_dsi_cmd_dma_tx(ctrl, tp); pr_debug("%s: Max packet size sent\n", __func__); } mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM); mdss_dsi_buf_init(tp); mdss_dsi_cmd_dma_add(tp, cmds); /* transmit read comamnd to client */ mdss_dsi_cmd_dma_tx(ctrl, tp); /* * once cmd_dma_done interrupt received, * return data from client is ready and stored * at RDBK_DATA register already */ mdss_dsi_buf_init(rp); if (no_max_pkt_size) { /* * expect rlen = n * 4 * short alignement for start addr */ rp->data += 2; } mdss_dsi_cmd_dma_rx(ctrl, rp, cnt); if (video_mode) MIPI_OUTP((ctrl->ctrl_base) + 0x0004, dsi_ctrl); /* restore */ if (no_max_pkt_size) { /* * remove extra 2 bytes from previous * rx transaction at shift register * which was inserted during copy * shift registers to rx buffer * rx payload start from long alignment addr */ rp->data += 2; } cmd = rp->data[0]; switch (cmd) { case DTYPE_ACK_ERR_RESP: pr_debug("%s: rx ACK_ERR_PACLAGE\n", __func__); break; case DTYPE_GEN_READ1_RESP: case DTYPE_DCS_READ1_RESP: mdss_dsi_short_read1_resp(rp); break; case DTYPE_GEN_READ2_RESP: case DTYPE_DCS_READ2_RESP: mdss_dsi_short_read2_resp(rp); break; case DTYPE_GEN_LREAD_RESP: case DTYPE_DCS_LREAD_RESP: mdss_dsi_long_read_resp(rp); rp->len -= 2; /* extra 2 bytes added */ rp->len -= diff; /* align bytes */ break; default: pr_debug("%s: Unknown cmd received\n", __func__); break; } return rp->len; }
static int mipi_dsi_off(struct platform_device *pdev) { int ret = 0; struct msm_fb_data_type *mfd; struct msm_panel_info *pinfo; uint32 dsi_ctrl; #ifdef CONFIG_FB_MSM_LCD_NOTIFY lcd_notifier_call_chain(LCD_EVENT_OFF_START, NULL); #endif pr_debug("%s+:\n", __func__); mfd = platform_get_drvdata(pdev); pinfo = &mfd->panel_info; if (mdp_rev >= MDP_REV_41) mutex_lock(&mfd->dma->ov_mutex); else down(&mfd->dma->mutex); if (mfd->panel_info.type == MIPI_CMD_PANEL) { mipi_dsi_prepare_clocks(); mipi_dsi_ahb_ctrl(1); mipi_dsi_clk_enable(); /* make sure dsi_cmd_mdp is idle */ mipi_dsi_cmd_mdp_busy(); } /* * Desctiption: change to DSI_CMD_MODE since it needed to * tx DCS dsiplay off comamnd to panel * mipi_dsi_op_mode_config(DSI_CMD_MODE); */ if (mfd->panel_info.type == MIPI_CMD_PANEL) { if (pinfo->lcd.vsync_enable) { if (pinfo->lcd.hw_vsync_mode && vsync_gpio >= 0) { if (MDP_REV_303 != mdp_rev) gpio_free(vsync_gpio); } mipi_dsi_set_tear_off(mfd); } } ret = panel_next_off(pdev); spin_lock_bh(&dsi_clk_lock); mipi_dsi_clk_disable(); /* disbale dsi engine */ dsi_ctrl = MIPI_INP(MIPI_DSI_BASE + 0x0000); dsi_ctrl &= ~0x01; MIPI_OUTP(MIPI_DSI_BASE + 0x0000, dsi_ctrl); MIPI_OUTP(MIPI_DSI_BASE + 0x010c, 0); /* DSI_INTL_CTRL */ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 0); mipi_dsi_phy_ctrl(0); mipi_dsi_ahb_ctrl(0); spin_unlock_bh(&dsi_clk_lock); mipi_dsi_unprepare_clocks(); usleep(5000); #if defined (CONFIG_MIPI_DSI_RESET_LP11) if (mipi_dsi_pdata && mipi_dsi_pdata->active_reset) mipi_dsi_pdata->active_reset(0); /* low */ #endif usleep(2000); /*1ms delay(minimum) required between reset low and AVDD off*/ #if defined(CONFIG_SUPPORT_SECOND_POWER) if (mipi_dsi_pdata && mipi_dsi_pdata->panel_power_save) mipi_dsi_pdata->panel_power_save(0); #endif if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_power_save) mipi_dsi_pdata->dsi_power_save(0); if (mdp_rev >= MDP_REV_41) mutex_unlock(&mfd->dma->ov_mutex); else up(&mfd->dma->mutex); #ifdef CONFIG_FB_MSM_LCD_NOTIFY lcd_notifier_call_chain(LCD_EVENT_OFF_END, NULL); #endif pr_debug("%s-:\n", __func__); return ret; }
static int mipi_dsi_off(struct platform_device *pdev) { int ret = 0; struct msm_fb_data_type *mfd; struct msm_panel_info *pinfo; mfd = platform_get_drvdata(pdev); pinfo = &mfd->panel_info; if (mdp_rev >= MDP_REV_41) mutex_lock(&mfd->dma->ov_mutex); else down(&mfd->dma->mutex); mdp4_overlay_dsi_state_set(ST_DSI_SUSPEND); /* * Description: dsi clock is need to perform shutdown. * mdp4_dsi_cmd_dma_busy_wait() will enable dsi clock if disabled. * also, wait until dma (overlay and dmap) finish. */ if (mfd->panel_info.type == MIPI_CMD_PANEL) { if (mdp_rev >= MDP_REV_41) { mdp4_dsi_cmd_dma_busy_wait(mfd); mdp4_dsi_blt_dmap_busy_wait(mfd); } else { mdp3_dsi_cmd_dma_busy_wait(mfd); } } /* * Desctiption: change to DSI_CMD_MODE since it needed to * tx DCS dsiplay off comamnd to panel */ mipi_dsi_op_mode_config(DSI_CMD_MODE); if (mfd->panel_info.type == MIPI_CMD_PANEL) { if (pinfo->lcd.vsync_enable) { if (pinfo->lcd.hw_vsync_mode && vsync_gpio > 0) { if (MDP_REV_303 != mdp_rev) gpio_free(vsync_gpio); } mipi_dsi_set_tear_off(mfd); } } ret = panel_next_off(pdev); #ifdef CONFIG_MSM_BUS_SCALING mdp_bus_scale_update_request(0); #endif /* disbale dsi engine */ MIPI_OUTP(MIPI_DSI_BASE + 0x0000, 0); mipi_dsi_phy_ctrl(0); local_bh_disable(); mipi_dsi_clk_disable(); local_bh_enable(); if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_power_save) mipi_dsi_pdata->dsi_power_save(0); if (mdp_rev >= MDP_REV_41) mutex_unlock(&mfd->dma->ov_mutex); else up(&mfd->dma->mutex); pr_debug("%s:\n", __func__); return ret; }
/* * mdss_dsi_cmds_tx: * thread context only */ int mdss_dsi_cmds_tx(struct mdss_dsi_ctrl_pdata *ctrl, struct dsi_cmd_desc *cmds, int cnt) { struct dsi_buf *tp; struct dsi_cmd_desc *cm; struct dsi_ctrl_hdr *dchdr; u32 dsi_ctrl, data; int i, video_mode; #ifdef CONFIG_OLED_SUPPORT struct timeval tv_start, tv_end; long tv_diff; int delay_count; #endif if (ctrl->shared_pdata.broadcast_enable) { if (ctrl->ndx == DSI_CTRL_0) { pr_debug("%s: Broadcast mode. 1st ctrl\n", __func__); return 0; } } if (ctrl->shared_pdata.broadcast_enable) { if ((ctrl->ndx == DSI_CTRL_1) && (left_ctrl_pdata != NULL)) { dsi_ctrl = MIPI_INP(left_ctrl_pdata->ctrl_base + 0x0004); video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */ if (video_mode) { data = dsi_ctrl | 0x04; /* CMD_MODE_EN */ MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004, data); } } } /* turn on cmd mode * for video mode, do not send cmds more than * one pixel line, since it only transmit it * during BLLP. */ dsi_ctrl = MIPI_INP((ctrl->ctrl_base) + 0x0004); video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */ if (video_mode) { data = dsi_ctrl | 0x04; /* CMD_MODE_EN */ MIPI_OUTP((ctrl->ctrl_base) + 0x0004, data); } tp = &ctrl->tx_buf; cm = cmds; for (i = 0; i < cnt; i++) { mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM); mdss_dsi_buf_init(tp); mdss_dsi_cmd_dma_add(tp, cm); mdss_dsi_cmd_dma_tx(ctrl, tp); dchdr = &cm->dchdr; #ifdef CONFIG_OLED_SUPPORT if(dchdr->wait) { delay_count = 0; do_gettimeofday(&tv_start); do { mdelay(1); do_gettimeofday(&tv_end); tv_diff = ((tv_end.tv_sec - tv_start.tv_sec) * 1000000) // sec + (tv_end.tv_usec - tv_start.tv_usec); // usec delay_count++; } while(dchdr->wait * 1000 > tv_diff); pr_info("%s: 0x%X needs %d(ms) delay and real delay is %ld(us), delay_count(%d).\n", __func__, cm->payload[0], (int)dchdr->wait, tv_diff, delay_count); } #else if (dchdr->wait) usleep(dchdr->wait * 1000); #endif cm++; } if (video_mode) MIPI_OUTP((ctrl->ctrl_base) + 0x0004, dsi_ctrl); /* restore */ return cnt; }
static int mipi_dsi_on(struct platform_device *pdev) { int ret = 0; u32 clk_rate; struct msm_fb_data_type *mfd; struct fb_info *fbi; struct fb_var_screeninfo *var; struct msm_panel_info *pinfo; struct mipi_panel_info *mipi; u32 hbp, hfp, vbp, vfp, hspw, vspw, width, height; u32 ystride, bpp, data; u32 dummy_xres, dummy_yres; int target_type = 0; mfd = platform_get_drvdata(pdev); fbi = mfd->fbi; var = &fbi->var; pinfo = &mfd->panel_info; if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_power_save) mipi_dsi_pdata->dsi_power_save(1); clk_rate = mfd->fbi->var.pixclock; clk_rate = min(clk_rate, mfd->panel_info.clk_max); local_bh_disable(); mipi_dsi_clk_enable(); local_bh_enable(); #ifndef CONFIG_FB_MSM_MDP303 mdp4_overlay_dsi_state_set(ST_DSI_RESUME); #endif MIPI_OUTP(MIPI_DSI_BASE + 0x114, 1); MIPI_OUTP(MIPI_DSI_BASE + 0x114, 0); mfd->dma->busy = FALSE;//add by Wenke Ma, as zygote died and restart then the isr cannot enter and this flag doesnot set false hbp = var->left_margin; hfp = var->right_margin; vbp = var->upper_margin; vfp = var->lower_margin; hspw = var->hsync_len; vspw = var->vsync_len; width = mfd->panel_info.xres; height = mfd->panel_info.yres; mipi_dsi_phy_ctrl(1); if (mdp_rev == MDP_REV_42 && mipi_dsi_pdata) target_type = mipi_dsi_pdata->target_type; mipi_dsi_phy_init(0, &(mfd->panel_info), target_type); mipi = &mfd->panel_info.mipi; if (mfd->panel_info.type == MIPI_VIDEO_PANEL) { dummy_xres = mfd->panel_info.mipi.xres_pad; dummy_yres = mfd->panel_info.mipi.yres_pad; if (mdp_rev >= MDP_REV_41) { MIPI_OUTP(MIPI_DSI_BASE + 0x20, ((hspw + hbp + width + dummy_xres) << 16 | (hspw + hbp))); MIPI_OUTP(MIPI_DSI_BASE + 0x24, ((vspw + vbp + height + dummy_yres) << 16 | (vspw + vbp))); MIPI_OUTP(MIPI_DSI_BASE + 0x28, (vspw + vbp + height + dummy_yres + vfp - 1) << 16 | (hspw + hbp + width + dummy_xres + hfp - 1)); } else { /* DSI_LAN_SWAP_CTRL */ MIPI_OUTP(MIPI_DSI_BASE + 0x00ac, mipi->dlane_swap); MIPI_OUTP(MIPI_DSI_BASE + 0x20, ((hbp + width + dummy_xres) << 16 | (hbp))); MIPI_OUTP(MIPI_DSI_BASE + 0x24, ((vbp + height + dummy_yres) << 16 | (vbp))); MIPI_OUTP(MIPI_DSI_BASE + 0x28, (vbp + height + dummy_yres + vfp) << 16 | (hbp + width + dummy_xres + hfp)); } MIPI_OUTP(MIPI_DSI_BASE + 0x2c, (hspw << 16)); MIPI_OUTP(MIPI_DSI_BASE + 0x30, 0); MIPI_OUTP(MIPI_DSI_BASE + 0x34, (vspw << 16)); } else { /* command mode */ if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB888) bpp = 3; else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB666) bpp = 3; else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB565) bpp = 2; else bpp = 3; /* Default format set to RGB888 */ ystride = width * bpp + 1; /* DSI_COMMAND_MODE_MDP_STREAM_CTRL */ data = (ystride << 16) | (mipi->vc << 8) | DTYPE_DCS_LWRITE; MIPI_OUTP(MIPI_DSI_BASE + 0x5c, data); MIPI_OUTP(MIPI_DSI_BASE + 0x54, data); /* DSI_COMMAND_MODE_MDP_STREAM_TOTAL */ data = height << 16 | width; MIPI_OUTP(MIPI_DSI_BASE + 0x60, data); MIPI_OUTP(MIPI_DSI_BASE + 0x58, data); } mipi_dsi_host_init(mipi); ret = panel_next_on(pdev); mipi_dsi_op_mode_config(mipi->mode); if (mfd->panel_info.type == MIPI_CMD_PANEL) { if (pinfo->lcd.vsync_enable) { if (pinfo->lcd.hw_vsync_mode && vsync_gpio > 0) { if (mdp_rev >= MDP_REV_41) { if (gpio_request(vsync_gpio, "MDP_VSYNC") == 0) gpio_direction_input( vsync_gpio); else pr_err("%s: unable to \ request gpio=%d\n", __func__, vsync_gpio); } else if (mdp_rev == MDP_REV_303) { if (!tlmm_settings && gpio_request( vsync_gpio, "MDP_VSYNC") == 0) { ret = gpio_tlmm_config( GPIO_CFG( vsync_gpio, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), GPIO_CFG_ENABLE); if (ret) { pr_err( "%s: unable to config \ tlmm = %d\n", __func__, vsync_gpio); } tlmm_settings = TRUE; gpio_direction_input( vsync_gpio); } else { if (!tlmm_settings) { pr_err( "%s: unable to request \ gpio=%d\n", __func__, vsync_gpio); } } }
int mdss_dsi_ulps_config(struct mdss_dsi_ctrl_pdata *ctrl_pdata, int enable) { int ret = 0; struct mdss_panel_data *pdata = NULL; struct mdss_panel_info *pinfo; struct mipi_panel_info *mipi; u32 lane_status = 0, regval; u32 active_lanes = 0, clamp_reg; if (!ctrl_pdata) { pr_err("%s: invalid input\n", __func__); return -EINVAL; } if (&ctrl_pdata->mmss_misc_io == NULL) { pr_err("%s: mmss_misc_io is NULL. ULPS not valid\n", __func__); return -EINVAL; } pdata = &ctrl_pdata->panel_data; if (!pdata) { pr_err("%s: Invalid panel data\n", __func__); return -EINVAL; } pinfo = &pdata->panel_info; mipi = &pinfo->mipi; if (!mdss_dsi_ulps_feature_enabled(pdata)) { pr_debug("%s: ULPS feature not supported. enable=%d\n", __func__, enable); return -ENOTSUPP; } if (pinfo->cont_splash_enabled) { pr_debug("%s: skip ULPS config with splash screen enabled\n", __func__); return 0; } active_lanes = BIT(4); clamp_reg = BIT(8) | BIT(9); if (mipi->data_lane0) { active_lanes |= BIT(0); clamp_reg |= (BIT(0) | BIT(1)); } if (mipi->data_lane1) { active_lanes |= BIT(1); clamp_reg |= (BIT(2) | BIT(3)); } if (mipi->data_lane2) { active_lanes |= BIT(2); clamp_reg |= (BIT(4) | BIT(5)); } if (mipi->data_lane3) { active_lanes |= BIT(3); clamp_reg |= (BIT(6) | BIT(7)); } pr_debug("%s: configuring ulps (%s) for ctrl%d, active lanes=0x%08x\n", __func__, (enable ? "on" : "off"), ctrl_pdata->ndx, active_lanes); if (enable && !ctrl_pdata->ulps) { MIPI_OUTP(ctrl_pdata->ctrl_base + 0x0AC, active_lanes); usleep(100); lane_status = MIPI_INP(ctrl_pdata->ctrl_base + 0xA8); if (lane_status & (active_lanes << 8)) { pr_err("%s: ULPS entry req failed for ctrl%d. Lane status=0x%08x\n", __func__, ctrl_pdata->ndx, lane_status); ret = -EINVAL; goto error; } if (ctrl_pdata->ndx == DSI_CTRL_0) { regval = MIPI_INP(ctrl_pdata->mmss_misc_io.base + 0x14); MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x14, regval | clamp_reg); MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x14, regval | (clamp_reg | BIT(15))); } else if (ctrl_pdata->ndx == DSI_CTRL_1) { regval = MIPI_INP(ctrl_pdata->mmss_misc_io.base + 0x14); MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x14, regval | (clamp_reg << 16)); MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x14, regval | ((clamp_reg << 16) | BIT(31))); } wmb(); MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x108, 0x1); ctrl_pdata->ulps = true; } else if (ctrl_pdata->ulps) { MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x108, 0x0); mdss_dsi_phy_init(pdata); __mdss_dsi_ctrl_setup(pdata); mdss_dsi_sw_reset(pdata); mdss_dsi_host_init(pdata); mdss_dsi_op_mode_config(pdata->panel_info.mipi.mode, pdata); MIPI_OUTP(ctrl_pdata->ctrl_base + 0x0AC, active_lanes); usleep(100); if (ctrl_pdata->ndx == DSI_CTRL_0) { regval = MIPI_INP(ctrl_pdata->mmss_misc_io.base + 0x14); MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x14, regval & ~(clamp_reg | BIT(15))); } else if (ctrl_pdata->ndx == DSI_CTRL_1) { regval = MIPI_INP(ctrl_pdata->mmss_misc_io.base + 0x14); MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x14, regval & ~((clamp_reg << 16) | BIT(31))); } MIPI_OUTP(ctrl_pdata->ctrl_base + 0x0AC, active_lanes << 8); usleep(1000); MIPI_OUTP(ctrl_pdata->ctrl_base + 0x0AC, 0x0); usleep(100); lane_status = MIPI_INP(ctrl_pdata->ctrl_base + 0xA8); ctrl_pdata->ulps = false; } pr_debug("%s: DSI lane status = 0x%08x. Ulps %s\n", __func__, lane_status, enable ? "enabled" : "disabled"); error: return ret; }
/* * mdss_dsi_cmds_tx: * thread context only */ int mdss_dsi_cmds_tx(struct mdss_dsi_ctrl_pdata *ctrl, struct dsi_cmd_desc *cmds, int cnt) { u32 dsi_ctrl, data; int video_mode, ret = 0; u32 left_dsi_ctrl = 0; bool left_ctrl_restore = false; pr_debug("%s : ++ ctrl->ndx (%d) cmd cnt (%d)\n",__func__,ctrl->ndx,cnt); if (ctrl->shared_pdata.broadcast_enable) { if (ctrl->ndx == DSI_CTRL_0) { pr_debug("%s: Broadcast mode. 1st ctrl\n", __func__); return 0; } } if (ctrl->shared_pdata.broadcast_enable) { if ((ctrl->ndx == DSI_CTRL_1) && (left_ctrl_pdata != NULL)) { left_dsi_ctrl = MIPI_INP(left_ctrl_pdata->ctrl_base + 0x0004); video_mode = left_dsi_ctrl & 0x02; /* VIDEO_MODE_EN */ if (video_mode) { data = left_dsi_ctrl | 0x04; /* CMD_MODE_EN */ MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004, data); left_ctrl_restore = true; } } else { pr_err("%s no left_ctrl_pdata...\n",__func__); } } /* turn on cmd mode * for video mode, do not send cmds more than * one pixel line, since it only transmit it * during BLLP. */ dsi_ctrl = MIPI_INP((ctrl->ctrl_base) + 0x0004); video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */ if (video_mode) { data = dsi_ctrl | 0x04; /* CMD_MODE_EN */ MIPI_OUTP((ctrl->ctrl_base) + 0x0004, data); } ret = mdss_dsi_cmds2buf_tx(ctrl, cmds, cnt); if (IS_ERR_VALUE(ret)) { pr_err("%s: failed to call\n", __func__); cnt = -EINVAL; } if (left_ctrl_restore) MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004, left_dsi_ctrl); /*restore */ if (video_mode) MIPI_OUTP((ctrl->ctrl_base) + 0x0004, dsi_ctrl); /* restore */ return cnt; }
/* * mdss_dsi_cmds_rx() - dcs read from panel * @ctrl: dsi controller * @cmds: read command descriptor * @len: number of bytes to read back * * controller have 4 registers can hold 16 bytes of rxed data * dcs packet: 4 bytes header + payload + 2 bytes crc * 2 padding bytes add to payload to have payload length is mutipled by 4 * 1st read: 4 bytes header + 8 bytes payload + 2 padding + 2 crc * 2nd read: 12 bytes payload + 2 padding + 2 crc * 3rd read: 12 bytes payload + 2 padding + 2 crc * */ int mdss_dsi_cmds_rx(struct mdss_dsi_ctrl_pdata *ctrl, struct dsi_cmd_desc *cmds, int rlen) { int data_byte, rx_byte, dlen, end; int short_response, diff, pkt_size, ret = 0; struct dsi_buf *tp, *rp; char cmd; u32 dsi_ctrl, data; int video_mode; u32 left_dsi_ctrl = 0; bool left_ctrl_restore = false; if (ctrl->shared_pdata.broadcast_enable) { if (ctrl->ndx == DSI_CTRL_0) { pr_debug("%s: Broadcast mode. 1st ctrl\n", __func__); return 0; } } if (ctrl->shared_pdata.broadcast_enable) { if ((ctrl->ndx == DSI_CTRL_1) && (left_ctrl_pdata != NULL)) { left_dsi_ctrl = MIPI_INP(left_ctrl_pdata->ctrl_base + 0x0004); video_mode = left_dsi_ctrl & 0x02; /* VIDEO_MODE_EN */ if (video_mode) { data = left_dsi_ctrl | 0x04; /* CMD_MODE_EN */ MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004, data); left_ctrl_restore = true; } } } /* turn on cmd mode * for video mode, do not send cmds more than * one pixel line, since it only transmit it * during BLLP. */ dsi_ctrl = MIPI_INP((ctrl->ctrl_base) + 0x0004); video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */ if (video_mode) { data = dsi_ctrl | 0x04; /* CMD_MODE_EN */ MIPI_OUTP((ctrl->ctrl_base) + 0x0004, data); } if (rlen == 0) { short_response = 1; rx_byte = 4; } else { short_response = 0; data_byte = 8; /* first read */ /* * add extra 2 padding bytes to have overall * packet size is multipe by 4. This also make * sure 4 bytes dcs headerlocates within a * 32 bits register after shift in. */ pkt_size = data_byte + 2; rx_byte = data_byte + 8; /* 4 header + 2 crc + 2 padding*/ } tp = &ctrl->tx_buf; rp = &ctrl->rx_buf; end = 0; mdss_dsi_buf_init(rp); while (!end) { pr_debug("%s: rlen=%d pkt_size=%d rx_byte=%d\n", __func__, rlen, pkt_size, rx_byte); if (!short_response) { max_pktsize[0] = pkt_size; mdss_dsi_buf_init(tp); ret = mdss_dsi_cmd_dma_add(tp, &pkt_size_cmd); if (!ret) { pr_err("%s: failed to add max_pkt_size\n", __func__); rp->len = 0; goto end; } mdss_dsi_wait4video_eng_busy(ctrl); mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM); ret = mdss_dsi_cmd_dma_tx(ctrl, tp); if (IS_ERR_VALUE(ret)) { mdss_dsi_disable_irq(ctrl, DSI_CMD_TERM); pr_err("%s: failed to tx max_pkt_size\n", __func__); rp->len = 0; goto end; } pr_debug("%s: max_pkt_size=%d sent\n", __func__, pkt_size); } mdss_dsi_buf_init(tp); ret = mdss_dsi_cmd_dma_add(tp, cmds); if (!ret) { pr_err("%s: failed to add cmd = 0x%x\n", __func__, cmds->payload[0]); rp->len = 0; goto end; } mdss_dsi_wait4video_eng_busy(ctrl); /* video mode only */ mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM); /* transmit read comamnd to client */ ret = mdss_dsi_cmd_dma_tx(ctrl, tp); if (IS_ERR_VALUE(ret)) { mdss_dsi_disable_irq(ctrl, DSI_CMD_TERM); pr_err("%s: failed to tx cmd = 0x%x\n", __func__, cmds->payload[0]); rp->len = 0; goto end; } /* * once cmd_dma_done interrupt received, * return data from client is ready and stored * at RDBK_DATA register already * since rx fifo is 16 bytes, dcs header is kept at first loop, * after that dcs header lost during shift into registers */ dlen = mdss_dsi_cmd_dma_rx(ctrl, rp, rx_byte); if (short_response) break; if (rlen <= data_byte) { diff = data_byte - rlen; end = 1; } else { diff = 0; rlen -= data_byte; } dlen -= 2; /* 2 padding bytes */ dlen -= 2; /* 2 crc */ dlen -= diff; rp->data += dlen; /* next start position */ rp->len += dlen; data_byte = 12; /* NOT first read */ pkt_size += data_byte; pr_debug("%s: rp data=%x len=%d dlen=%d diff=%d\n", __func__, (int)rp->data, rp->len, dlen, diff); } rp->data = rp->start; /* move back to start position */ cmd = rp->data[0]; switch (cmd) { case DTYPE_ACK_ERR_RESP: pr_debug("%s: rx ACK_ERR_PACLAGE\n", __func__); rp->len = 0; case DTYPE_GEN_READ1_RESP: case DTYPE_DCS_READ1_RESP: mdss_dsi_short_read1_resp(rp); break; case DTYPE_GEN_READ2_RESP: case DTYPE_DCS_READ2_RESP: mdss_dsi_short_read2_resp(rp); break; case DTYPE_GEN_LREAD_RESP: case DTYPE_DCS_LREAD_RESP: mdss_dsi_long_read_resp(rp); break; default: pr_warning("%s:Invalid response cmd\n", __func__); rp->len = 0; } end: if (left_ctrl_restore) MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004, left_dsi_ctrl); /*restore */ if (video_mode) MIPI_OUTP((ctrl->ctrl_base) + 0x0004, dsi_ctrl); /* restore */ return rp->len; }
static int mipi_dsi_on(struct platform_device *pdev) { int ret = 0; u32 clk_rate; struct msm_fb_data_type *mfd; struct fb_info *fbi; struct fb_var_screeninfo *var; struct msm_panel_info *pinfo; struct mipi_panel_info *mipi; u32 hbp, hfp, vbp, vfp, hspw, vspw, width, height; u32 ystride, bpp, data; u32 dummy_xres, dummy_yres; int target_type = 0; u32 tmp; #if defined(CONFIG_FB_MSM_MIPI_RENESAS_TFT_VIDEO_FULL_HD_PT_PANEL) static int is_booting = 1; #endif #ifdef CONFIG_FB_MSM_LCD_NOTIFY lcd_notifier_call_chain(LCD_EVENT_ON_START, NULL); #endif pr_debug("%s+:\n", __func__); #if defined(CONFIG_MIPI_SAMSUNG_ESD_REFRESH) || defined(CONFIG_ESD_ERR_FG_RECOVERY) pdev_for_esd = pdev; #endif #if defined (CONFIG_FB_MSM_MIPI_SAMSUNG_OLED_VIDEO_QHD_PT) if (get_lcd_attached() == 0) return ENODEV; #endif mfd = platform_get_drvdata(pdev); fbi = mfd->fbi; var = &fbi->var; pinfo = &mfd->panel_info; esc_byte_ratio = pinfo->mipi.esc_byte_ratio; if (mipi_dsi_pdata && mipi_dsi_pdata->power_common) mipi_dsi_pdata->power_common(); #if defined(CONFIG_SUPPORT_SECOND_POWER) #if defined(CONFIG_FB_MSM_MIPI_RENESAS_TFT_VIDEO_FULL_HD_PT_PANEL) if( is_booting == 1 ) { is_booting = 0; #if defined(CONFIG_MACH_JACTIVE_ATT) || defined(CONFIG_MACH_JACTIVE_EUR) usleep(5000); if (mipi_dsi_pdata && mipi_dsi_pdata->active_reset) mipi_dsi_pdata->active_reset(0); /* low */ usleep(2000); if (mipi_dsi_pdata && mipi_dsi_pdata->panel_power_save) mipi_dsi_pdata->panel_power_save(0); msleep(10); #endif } #endif if (mipi_dsi_pdata && mipi_dsi_pdata->panel_power_save) mipi_dsi_pdata->panel_power_save(1); #endif #if !defined(CONFIG_SEC_PRODUCT_8930) && !defined(CONFIG_SEC_PRODUCT_8960) if (system_rev == 6) mdelay(500); #endif if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_power_save) mipi_dsi_pdata->dsi_power_save(1); cont_splash_clk_ctrl(0); mipi_dsi_prepare_clocks(); mipi_dsi_ahb_ctrl(1); clk_rate = mfd->fbi->var.pixclock; clk_rate = min(clk_rate, mfd->panel_info.clk_max); mipi_dsi_phy_ctrl(1); if (mdp_rev == MDP_REV_42 && mipi_dsi_pdata) target_type = mipi_dsi_pdata->target_type; mipi_dsi_phy_init(0, &(mfd->panel_info), target_type); mipi_dsi_clk_enable(); #if defined(CONFIG_FB_MSM_MIPI_SAMSUNG_OLED_VIDEO_QHD_PT_PANEL) mipi_dsi_configure_dividers(60); #endif MIPI_OUTP(MIPI_DSI_BASE + 0x114, 1); MIPI_OUTP(MIPI_DSI_BASE + 0x114, 0); hbp = var->left_margin; hfp = var->right_margin; vbp = var->upper_margin; vfp = var->lower_margin; hspw = var->hsync_len; vspw = var->vsync_len; width = mfd->panel_info.xres; height = mfd->panel_info.yres; mipi = &mfd->panel_info.mipi; if (mfd->panel_info.type == MIPI_VIDEO_PANEL) { dummy_xres = mfd->panel_info.lcdc.xres_pad; dummy_yres = mfd->panel_info.lcdc.yres_pad; if (mdp_rev >= MDP_REV_41) { MIPI_OUTP(MIPI_DSI_BASE + 0x20, ((hspw + hbp + width + dummy_xres) << 16 | (hspw + hbp))); MIPI_OUTP(MIPI_DSI_BASE + 0x24, ((vspw + vbp + height + dummy_yres) << 16 | (vspw + vbp))); MIPI_OUTP(MIPI_DSI_BASE + 0x28, (vspw + vbp + height + dummy_yres + vfp - 1) << 16 | (hspw + hbp + width + dummy_xres + hfp - 1)); } else { /* DSI_LAN_SWAP_CTRL */ MIPI_OUTP(MIPI_DSI_BASE + 0x00ac, mipi->dlane_swap); MIPI_OUTP(MIPI_DSI_BASE + 0x20, ((hbp + width + dummy_xres) << 16 | (hbp))); MIPI_OUTP(MIPI_DSI_BASE + 0x24, ((vbp + height + dummy_yres) << 16 | (vbp))); MIPI_OUTP(MIPI_DSI_BASE + 0x28, (vbp + height + dummy_yres + vfp) << 16 | (hbp + width + dummy_xres + hfp)); } MIPI_OUTP(MIPI_DSI_BASE + 0x2c, (hspw << 16)); MIPI_OUTP(MIPI_DSI_BASE + 0x30, 0); MIPI_OUTP(MIPI_DSI_BASE + 0x34, (vspw << 16)); } else { /* command mode */ if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB888) bpp = 3; else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB666) bpp = 3; else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB565) bpp = 2; else bpp = 3; /* Default format set to RGB888 */ ystride = width * bpp + 1; /* DSI_COMMAND_MODE_MDP_STREAM_CTRL */ data = (ystride << 16) | (mipi->vc << 8) | DTYPE_DCS_LWRITE; MIPI_OUTP(MIPI_DSI_BASE + 0x5c, data); MIPI_OUTP(MIPI_DSI_BASE + 0x54, data); /* DSI_COMMAND_MODE_MDP_STREAM_TOTAL */ data = height << 16 | width; MIPI_OUTP(MIPI_DSI_BASE + 0x60, data); MIPI_OUTP(MIPI_DSI_BASE + 0x58, data); } mipi_dsi_host_init(mipi); #if defined(CONFIG_FB_MSM_MIPI_SAMSUNG_OLED_VIDEO_HD_PT_PANEL) { u32 tmp_reg0c, tmp_rega8; udelay(200); /* backup register values */ tmp_reg0c = MIPI_INP(MIPI_DSI_BASE + 0x000c); tmp_rega8 = MIPI_INP(MIPI_DSI_BASE + 0xA8); /* Clear HS mode assertion and related flags */ MIPI_OUTP(MIPI_DSI_BASE + 0x0c, 0x8000); MIPI_OUTP(MIPI_DSI_BASE + 0xA8, 0x0); wmb(); mdelay(10); if (mipi_dsi_pdata && mipi_dsi_pdata->lcd_rst_up) mipi_dsi_pdata->lcd_rst_up(); /* restore previous values */ MIPI_OUTP(MIPI_DSI_BASE + 0x0c, tmp_reg0c); MIPI_OUTP(MIPI_DSI_BASE + 0xa8, tmp_rega8); wmb(); } #else msleep(10); #if defined (CONFIG_MIPI_DSI_RESET_LP11) /* LP11 */ tmp = MIPI_INP(MIPI_DSI_BASE + 0xA8); tmp &= ~(1<<28); MIPI_OUTP(MIPI_DSI_BASE + 0xA8, tmp); wmb(); /* LP11 */ usleep(5000); if (mipi_dsi_pdata && mipi_dsi_pdata->active_reset) mipi_dsi_pdata->active_reset(1); /* high */ usleep(10000); #endif #if defined(CONFIG_MACH_LT02_SPR) || defined(CONFIG_MACH_LT02_ATT) || defined(CONFIG_MACH_LT02_TMO) if(system_rev) ret = panel_next_on(pdev); #elif defined(CONFIG_MACH_LT02_CHN_CTC) ret = panel_next_on(pdev); #endif #endif /* always high */ if (mipi->force_clk_lane_hs) { tmp = MIPI_INP(MIPI_DSI_BASE + 0xA8); tmp |= (1<<28); MIPI_OUTP(MIPI_DSI_BASE + 0xA8, tmp); wmb(); } if (mdp_rev >= MDP_REV_41) mutex_lock(&mfd->dma->ov_mutex); else down(&mfd->dma->mutex); #if !defined(CONFIG_MACH_LT02_CHN_CTC) #if defined(CONFIG_MACH_LT02_SPR) || defined(CONFIG_MACH_LT02_ATT) || defined(CONFIG_MACH_LT02_TMO) if(!system_rev) ret = panel_next_on(pdev); #else ret = panel_next_on(pdev); #endif #endif mipi_dsi_op_mode_config(mipi->mode); if (mfd->panel_info.type == MIPI_CMD_PANEL) { if (pinfo->lcd.vsync_enable) { if (pinfo->lcd.hw_vsync_mode && vsync_gpio >= 0) { if (mdp_rev >= MDP_REV_41) { if (gpio_request(vsync_gpio, "MDP_VSYNC") == 0) gpio_direction_input( vsync_gpio); else pr_err("%s: unable to \ request gpio=%d\n", __func__, vsync_gpio); } else if (mdp_rev == MDP_REV_303) { if (!tlmm_settings && gpio_request( vsync_gpio, "MDP_VSYNC") == 0) { ret = gpio_tlmm_config( GPIO_CFG( vsync_gpio, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), GPIO_CFG_ENABLE); if (ret) { pr_err( "%s: unable to config \ tlmm = %d\n", __func__, vsync_gpio); } tlmm_settings = TRUE; gpio_direction_input( vsync_gpio); } else { if (!tlmm_settings) { pr_err( "%s: unable to request \ gpio=%d\n", __func__, vsync_gpio); } } }
static int mdss_dsi_cmd_dma_tx(struct mdss_dsi_ctrl_pdata *ctrl, struct dsi_buf *tp) { int len, ret = 0; int domain = MDSS_IOMMU_DOMAIN_UNSECURE; char *bp; unsigned long size, addr; bp = tp->data; len = ALIGN(tp->len, 4); size = ALIGN(tp->len, SZ_4K); if (is_mdss_iommu_attached()) { int ret = msm_iommu_map_contig_buffer(tp->dmap, mdss_get_iommu_domain(domain), 0, size, SZ_4K, 0, &(addr)); if (IS_ERR_VALUE(ret)) { pr_err("unable to map dma memory to iommu(%d)\n", ret); return -ENOMEM; } } else { addr = tp->dmap; } INIT_COMPLETION(ctrl->dma_comp); if (ctrl->shared_pdata.broadcast_enable) if ((ctrl->ndx == DSI_CTRL_1) && (left_ctrl_pdata != NULL)) { MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x048, addr); MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x04c, len); } MIPI_OUTP((ctrl->ctrl_base) + 0x048, addr); MIPI_OUTP((ctrl->ctrl_base) + 0x04c, len); wmb(); if (ctrl->shared_pdata.broadcast_enable) if ((ctrl->ndx == DSI_CTRL_1) && (left_ctrl_pdata != NULL)) { MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x090, 0x01); } MIPI_OUTP((ctrl->ctrl_base) + 0x090, 0x01); /* trigger */ wmb(); ret = wait_for_completion_timeout(&ctrl->dma_comp, msecs_to_jiffies(DMA_TX_TIMEOUT)); if (ret == 0) ret = -ETIMEDOUT; else ret = tp->len; if (is_mdss_iommu_attached()) msm_iommu_unmap_contig_buffer(addr, mdss_get_iommu_domain(domain), 0, size); return ret; }
/* * This software is contributed or developed by KYOCERA Corporation. * (C) 2012 KYOCERA Corporation * * drivers/video/msm/disp_ext_board.c * * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * */ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/kernel.h> #include "msm_fb.h" #include "mipi_dsi.h" #ifndef CONFIG_FB_MSM_MIPI_DSI_RENESAS_CM #include "mipi_novatek_wxga.h" #include <linux/mipi_novatek_wxga_ext.h> #else #include "mipi_renesas_cm.h" #endif #include "mdp4.h" #include "disp_ext.h" #ifdef CONFIG_DISP_EXT_BLC #include <linux/leds-lm3533.h> #endif /* CONFIG_DISP_EXT_BLC */ #define DETECT_BOARD_NUM 5 #ifndef CONFIG_FB_MSM_MIPI_DSI_RENESAS_CM static char detect_board_cmd1_select[4] = { 0xFF, 0x00, DTYPE_DCS_WRITE1, 0x80 }; static char detect_board_mipi_lane_read[4] = { 0xBA, 0x00, DTYPE_DCS_READ , 0xA0 }; static char maximum_return_seze_set[4] = { 0x01, 0x00, DTYPE_MAX_PKTSIZE , 0x80 }; #else static char detect_board_mipi_lane_read[4] = { 0xA1, 0x00, DTYPE_DCS_READ , 0xA0 }; static char maximum_return_seze_set[4] = { 0x06, 0x00, DTYPE_MAX_PKTSIZE , 0x80 }; #endif extern struct device dsi_dev; static int panel_detection=0; /* -1:not panel 0:Not test 1:panel found */ static int disp_ext_board_cmd_tx( char *cm , int size ,int time ) { char pload[256]; int video_mode; uint32 dsi_ctrl, ctrl; uint32_t off; uint32_t ReadValue; uint32_t count = 0; dma_addr_t dmap; pr_debug("%s:S\n", __func__); DISP_LOCAL_LOG_EMERG("DISP disp_ext_board_cmd_tx S\n"); /* Align pload at 8 byte boundry */ off = (uint32_t)pload; off &= 0x07; if (off) { off = 8 - off; } off += (uint32_t)pload; memcpy((void *)off, cm, size); ctrl = 0; dsi_ctrl = MIPI_INP(MIPI_DSI_BASE + 0x0000); video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */ if (video_mode) { ctrl = dsi_ctrl | 0x04; /* CMD_MODE_EN */ MIPI_OUTP(MIPI_DSI_BASE + 0x0000, ctrl); } dmap = dma_map_single(&dsi_dev, (char *)off, size, DMA_TO_DEVICE); MIPI_OUTP(MIPI_DSI_BASE + 0x0044, dmap); /* DSI1_DMA_CMD_OFFSET */ MIPI_OUTP(MIPI_DSI_BASE + 0x0048, size); /* DSI1_DMA_CMD_LENGTH */ wmb(); MIPI_OUTP(MIPI_DSI_BASE + 0x08c, 0x01); /* trigger */ wmb(); udelay(1); if( time != 0 ) { pr_debug("%s:wait %d ms\n", __func__,time); mdelay(time); } ReadValue = MIPI_INP(MIPI_DSI_BASE + 0x010C) & 0x00000001; pr_debug("%s:S MIPI_INP(MIPI_DSI_BASE + 0x010C)=%x\n", __func__,MIPI_INP(MIPI_DSI_BASE + 0x010C)); if( time != 0 && ReadValue != 0x00000001 ) { pr_err("%s:send command timeout(%d ms)\n", __func__,time); dma_unmap_single(&dsi_dev, dmap, size, DMA_TO_DEVICE); return -1; } while (ReadValue != 0x00000001) { ReadValue = MIPI_INP(MIPI_DSI_BASE + 0x010C) & 0x00000001; count++; if (count > 0xffff) { pr_err("%s:send command timeout__\n", __func__); dma_unmap_single(&dsi_dev, dmap, size, DMA_TO_DEVICE); return -1; } } mdelay(5); MIPI_OUTP(MIPI_DSI_BASE + 0x010C, MIPI_INP(MIPI_DSI_BASE + 0x010C) | 0x01000001); if (video_mode) { MIPI_OUTP(MIPI_DSI_BASE + 0x0000, dsi_ctrl); /* restore */ } dma_unmap_single(&dsi_dev, dmap, size, DMA_TO_DEVICE); pr_debug("%s:E\n", __func__); DISP_LOCAL_LOG_EMERG("DISP disp_ext_board_cmd_tx E\n"); return 0; }
static int mdss_dsi_cmd_dma_tx(struct mdss_dsi_ctrl_pdata *ctrl, struct dsi_buf *tp) { int len, ret = 0; int domain = MDSS_IOMMU_DOMAIN_UNSECURE; char *bp; unsigned long size, addr; struct mdss_dsi_ctrl_pdata *mctrl = NULL; bp = tp->data; len = ALIGN(tp->len, 4); size = ALIGN(tp->len, SZ_4K); if (is_mdss_iommu_attached()) { ret = msm_iommu_map_contig_buffer(tp->dmap, mdss_get_iommu_domain(domain), 0, size, SZ_4K, 0, &(addr)); if (IS_ERR_VALUE(ret)) { pr_err("unable to map dma memory to iommu(%d)\n", ret); return -ENOMEM; } } else { addr = tp->dmap; } INIT_COMPLETION(ctrl->dma_comp); /* Ensure that for slave controller, master is also configured */ if (mdss_dsi_is_slave_ctrl(ctrl)) { mctrl = mdss_dsi_get_master_ctrl(); if (mctrl) { MIPI_OUTP(mctrl->ctrl_base + 0x048, addr); MIPI_OUTP(mctrl->ctrl_base + 0x04c, len); } else { pr_warn("%s: Unable to get master control\n", __func__); } } MIPI_OUTP((ctrl->ctrl_base) + 0x048, addr); MIPI_OUTP((ctrl->ctrl_base) + 0x04c, len); wmb(); /* Trigger on master controller as well */ if (mctrl) MIPI_OUTP(mctrl->ctrl_base + 0x090, 0x01); MIPI_OUTP((ctrl->ctrl_base) + 0x090, 0x01); wmb(); ret = wait_for_completion_timeout(&ctrl->dma_comp, msecs_to_jiffies(DMA_TX_TIMEOUT)); if (ret == 0) ret = -ETIMEDOUT; else ret = tp->len; if (is_mdss_iommu_attached()) msm_iommu_unmap_contig_buffer(addr, mdss_get_iommu_domain(domain), 0, size); return ret; }
void mipi_dsi_phy_init(int panel_ndx, struct msm_panel_info const *panel_info, int target_type) { struct mipi_dsi_phy_ctrl *pd; int i, off; MIPI_OUTP(MIPI_DSI_BASE + 0x128, 0x0001);/* start phy sw reset */ msleep(100); MIPI_OUTP(MIPI_DSI_BASE + 0x128, 0x0000);/* end phy w reset */ MIPI_OUTP(MIPI_DSI_BASE + 0x2cc, 0x0003);/* regulator_ctrl_0 */ MIPI_OUTP(MIPI_DSI_BASE + 0x2d0, 0x0001);/* regulator_ctrl_1 */ MIPI_OUTP(MIPI_DSI_BASE + 0x2d4, 0x0001);/* regulator_ctrl_2 */ MIPI_OUTP(MIPI_DSI_BASE + 0x2d8, 0x0000);/* regulator_ctrl_3 */ #ifdef DSI_POWER MIPI_OUTP(MIPI_DSI_BASE + 0x2dc, 0x0100);/* regulator_ctrl_4 */ #endif pd = (panel_info->mipi).dsi_phy_db; off = 0x02cc; /* regulator ctrl 0 */ for (i = 0; i < 4; i++) { MIPI_OUTP(MIPI_DSI_BASE + off, pd->regulator[i]); wmb(); off += 4; } off = 0x0260; /* phy timig ctrl 0 */ for (i = 0; i < 11; i++) { MIPI_OUTP(MIPI_DSI_BASE + off, pd->timing[i]); wmb(); off += 4; } off = 0x0290; /* ctrl 0 */ for (i = 0; i < 4; i++) { MIPI_OUTP(MIPI_DSI_BASE + off, pd->ctrl[i]); wmb(); off += 4; } off = 0x02a0; /* strength 0 */ for (i = 0; i < 4; i++) { MIPI_OUTP(MIPI_DSI_BASE + off, pd->strength[i]); wmb(); off += 4; } mipi_dsi_calibration(); off = 0x0204; /* pll ctrl 1, skip 0 */ for (i = 1; i < 21; i++) { MIPI_OUTP(MIPI_DSI_BASE + off, pd->pll[i]); wmb(); off += 4; } if (panel_info) mipi_dsi_phy_pll_config(panel_info->clk_rate); /* pll ctrl 0 */ MIPI_OUTP(MIPI_DSI_BASE + 0x200, pd->pll[0]); wmb(); }
void mdss_dsi_host_init(struct mdss_panel_data *pdata) { u32 dsi_ctrl, intr_ctrl; u32 data; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; struct mipi_panel_info *pinfo = NULL; if (pdata == NULL) { pr_err("%s: Invalid input data\n", __func__); return; } ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); pinfo = &pdata->panel_info.mipi; pinfo->rgb_swap = DSI_RGB_SWAP_RGB; if (pinfo->mode == DSI_VIDEO_MODE) { data = 0; if (pinfo->last_line_interleave_en) data |= BIT(31); if (pinfo->pulse_mode_hsa_he) data |= BIT(28); if (pinfo->hfp_power_stop) data |= BIT(24); if (pinfo->hbp_power_stop) data |= BIT(20); if (pinfo->hsa_power_stop) data |= BIT(16); if (pinfo->eof_bllp_power_stop) data |= BIT(15); if (pinfo->bllp_power_stop) data |= BIT(12); data |= ((pinfo->traffic_mode & 0x03) << 8); data |= ((pinfo->dst_format & 0x03) << 4); /* 2 bits */ data |= (pinfo->vc & 0x03); #if defined(CONFIG_FB_MSM_MIPI_LGD_VIDEO_WVGA_PT_INCELL_PANEL) data |= BIT(31); #endif MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0010, data); data = 0; data |= ((pinfo->rgb_swap & 0x07) << 12); if (pinfo->b_sel) data |= BIT(8); if (pinfo->g_sel) data |= BIT(4); if (pinfo->r_sel) data |= BIT(0); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0020, data); } else if (pinfo->mode == DSI_CMD_MODE) { data = 0; data |= ((pinfo->interleave_max & 0x0f) << 20); data |= ((pinfo->rgb_swap & 0x07) << 16); if (pinfo->b_sel) data |= BIT(12); if (pinfo->g_sel) data |= BIT(8); if (pinfo->r_sel) data |= BIT(4); data |= (pinfo->dst_format & 0x0f); /* 4 bits */ MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0040, data); /* DSI_COMMAND_MODE_MDP_DCS_CMD_CTRL */ data = pinfo->wr_mem_continue & 0x0ff; data <<= 8; data |= (pinfo->wr_mem_start & 0x0ff); if (pinfo->insert_dcs_cmd) data |= BIT(16); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0044, data); } else pr_err("%s: Unknown DSI mode=%d\n", __func__, pinfo->mode); dsi_ctrl = BIT(8) | BIT(2); /* clock enable & cmd mode */ intr_ctrl = 0; intr_ctrl = (DSI_INTR_CMD_DMA_DONE_MASK | DSI_INTR_CMD_MDP_DONE_MASK); if (pinfo->crc_check) dsi_ctrl |= BIT(24); if (pinfo->ecc_check) dsi_ctrl |= BIT(20); if (pinfo->data_lane3) dsi_ctrl |= BIT(7); if (pinfo->data_lane2) dsi_ctrl |= BIT(6); if (pinfo->data_lane1) dsi_ctrl |= BIT(5); if (pinfo->data_lane0) dsi_ctrl |= BIT(4); /* from frame buffer, low power mode */ /* DSI_COMMAND_MODE_DMA_CTRL */ if (mdss_dsi_broadcast_mode_enabled()) MIPI_OUTP(ctrl_pdata->ctrl_base + 0x3C, 0x94000000); else #if defined(CONFIG_FB_MSM_MIPI_LGD_LH500WX9_VIDEO_HD_PT_PANEL) MIPI_OUTP(ctrl_pdata->ctrl_base + 0x3C, 0x10000000); #else MIPI_OUTP(ctrl_pdata->ctrl_base + 0x3C, 0x14000000); #endif #if defined(CONFIG_FB_MSM_MIPI_LGD_VIDEO_WVGA_PT_INCELL_PANEL) MIPI_OUTP(ctrl_pdata->ctrl_base + 0xBC, 0xFFFFF); MIPI_OUTP(ctrl_pdata->ctrl_base + 0xC0, 0x111); #endif data = 0; if (pinfo->te_sel) data |= BIT(31); data |= pinfo->mdp_trigger << 4;/* cmd mdp trigger */ data |= pinfo->dma_trigger; /* cmd dma trigger */ data |= (pinfo->stream & 0x01) << 8; MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0084, data); /* DSI_TRIG_CTRL */ /* DSI_LAN_SWAP_CTRL */ MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x00b0, pinfo->dlane_swap); /* clock out ctrl */ data = pinfo->t_clk_post & 0x3f; /* 6 bits */ data <<= 8; data |= pinfo->t_clk_pre & 0x3f; /* 6 bits */ /* DSI_CLKOUT_TIMING_CTRL */ MIPI_OUTP((ctrl_pdata->ctrl_base) + 0xc4, data); data = 0; if (pinfo->rx_eot_ignore) data |= BIT(4); if (pinfo->tx_eot_append) data |= BIT(0); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x00cc, data); /* DSI_EOT_PACKET_CTRL */ /* allow only ack-err-status to generate interrupt */ /* DSI_ERR_INT_MASK0 */ MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x010c, 0x13ff3fe0); intr_ctrl |= DSI_INTR_ERROR_MASK; MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0110, intr_ctrl); /* DSI_INTL_CTRL */ /* turn esc, byte, dsi, pclk, sclk, hclk on */ MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x11c, 0x23f); /* DSI_CLK_CTRL */ dsi_ctrl |= BIT(0); /* enable dsi */ MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004, dsi_ctrl); wmb(); }
int mdss_dsi_on(struct mdss_panel_data *pdata) { int ret = 0; u32 clk_rate; struct mdss_panel_info *pinfo; struct mipi_panel_info *mipi; u32 hbp, hfp, vbp, vfp, hspw, vspw, width, height; u32 ystride, bpp, data, dst_bpp; u32 dummy_xres, dummy_yres; 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 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; ret = mdss_dsi_panel_power_on(pdata, 1); if (ret) { pr_err("%s: Panel power on failed\n", __func__); return ret; } pdata->panel_info.panel_power_on = 1; 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; } mdss_dsi_phy_sw_reset((ctrl_pdata->ctrl_base)); mdss_dsi_phy_init(pdata); mdss_dsi_disable_bus_clocks(ctrl_pdata); mdss_dsi_clk_ctrl(ctrl_pdata, 1); 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); hbp = mult_frac(pdata->panel_info.lcdc.h_back_porch, dst_bpp, pdata->panel_info.bpp); hfp = mult_frac(pdata->panel_info.lcdc.h_front_porch, dst_bpp, pdata->panel_info.bpp); vbp = mult_frac(pdata->panel_info.lcdc.v_back_porch, dst_bpp, pdata->panel_info.bpp); vfp = mult_frac(pdata->panel_info.lcdc.v_front_porch, dst_bpp, pdata->panel_info.bpp); hspw = mult_frac(pdata->panel_info.lcdc.h_pulse_width, dst_bpp, pdata->panel_info.bpp); vspw = pdata->panel_info.lcdc.v_pulse_width; width = mult_frac(pdata->panel_info.xres, dst_bpp, pdata->panel_info.bpp); #ifdef CONFIG_OLED_SUPPORT height = pdata->panel_info.yres + pdata->panel_info.lcdc.yres_margin; #else height = pdata->panel_info.yres; #endif mipi = &pdata->panel_info.mipi; if (pdata->panel_info.type == MIPI_VIDEO_PANEL) { dummy_xres = pdata->panel_info.lcdc.xres_pad; dummy_yres = pdata->panel_info.lcdc.yres_pad; MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x24, ((hspw + hbp + width + dummy_xres) << 16 | (hspw + hbp))); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x28, ((vspw + vbp + height + dummy_yres) << 16 | (vspw + vbp))); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x2C, (vspw + vbp + height + dummy_yres + vfp - 1) << 16 | (hspw + hbp + width + dummy_xres + hfp - 1)); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x30, (hspw << 16)); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x34, 0); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x38, (vspw << 16)); } else { /* command mode */ if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB888) bpp = 3; else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB666) bpp = 3; else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB565) bpp = 2; else bpp = 3; /* Default format set to RGB888 */ ystride = width * bpp + 1; /* DSI_COMMAND_MODE_MDP_STREAM_CTRL */ data = (ystride << 16) | (mipi->vc << 8) | DTYPE_DCS_LWRITE; MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x60, data); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x58, data); /* DSI_COMMAND_MODE_MDP_STREAM_TOTAL */ data = height << 16 | width; MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x64, data); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x5C, data); } mdss_dsi_sw_reset(pdata); mdss_dsi_host_init(mipi, pdata); 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 defined(CONFIG_MACH_LGE) #if defined(CONFIG_OLED_SUPPORT) msleep(10); mdss_dsi_panel_reset(pdata, 1); msleep(20); #else /* LGE_CHANGE_S * power sequence for LGD_FHD panel * 2013-04-05, [email protected] */ #if defined (CONFIG_MACH_MSM8974_VU3_KR) msleep(40); #else msleep(1); #endif mdss_dsi_panel_reset(pdata, 1); #endif #endif if (pdata->panel_info.type == MIPI_CMD_PANEL) mdss_dsi_clk_ctrl(ctrl_pdata, 0); pr_debug("%s-:\n", __func__); return 0; }
void mipi_dsi_lane_cfg(void) { int i, ln_offset; ln_offset = 0x300; for (i = 0; i < 4; i++) { /* DSI1_DSIPHY_LN_CFG0 */ MIPI_OUTP(MIPI_DSI_BASE + ln_offset, 0x80); /* DSI1_DSIPHY_LN_CFG1 */ MIPI_OUTP(MIPI_DSI_BASE + ln_offset + 0x04, 0x45); /* DSI1_DSIPHY_LN_CFG2 */ MIPI_OUTP(MIPI_DSI_BASE + ln_offset + 0x08, 0x0); /* DSI1_DSIPHY_LN_TEST_DATAPATH */ MIPI_OUTP(MIPI_DSI_BASE + ln_offset + 0x0c, 0x0); /* DSI1_DSIPHY_LN_TEST_STR0 */ MIPI_OUTP(MIPI_DSI_BASE + ln_offset + 0x14, 0x1); /* DSI1_DSIPHY_LN_TEST_STR1 */ MIPI_OUTP(MIPI_DSI_BASE + ln_offset + 0x18, 0x66); ln_offset += 0x40; } MIPI_OUTP(MIPI_DSI_BASE + 0x0400, 0x40); /* DSI1_DSIPHY_LNCK_CFG0 */ MIPI_OUTP(MIPI_DSI_BASE + 0x0404, 0x67); /* DSI1_DSIPHY_LNCK_CFG1 */ MIPI_OUTP(MIPI_DSI_BASE + 0x0408, 0x0); /* DSI1_DSIPHY_LNCK_CFG2 */ /* DSI1_DSIPHY_LNCK_TEST_DATAPATH */ MIPI_OUTP(MIPI_DSI_BASE + 0x040c, 0x0); MIPI_OUTP(MIPI_DSI_BASE + 0x0414, 0x1); /* DSI1_DSIPHY_LNCK_TEST_STR0 */ /* DSI1_DSIPHY_LNCK_TEST_STR1 */ MIPI_OUTP(MIPI_DSI_BASE + 0x0418, 0x88); }
void mipi_dsi_lane_cfg(void) { int i, ln_offset; ln_offset = 0x300; for (i = 0; i < 4; i++) { MIPI_OUTP(MIPI_DSI_BASE + ln_offset, 0x80); MIPI_OUTP(MIPI_DSI_BASE + ln_offset + 0x04, 0x45); MIPI_OUTP(MIPI_DSI_BASE + ln_offset + 0x08, 0x0); MIPI_OUTP(MIPI_DSI_BASE + ln_offset + 0x0c, 0x0); MIPI_OUTP(MIPI_DSI_BASE + ln_offset + 0x14, 0x1); MIPI_OUTP(MIPI_DSI_BASE + ln_offset + 0x18, 0x66); ln_offset += 0x40; } MIPI_OUTP(MIPI_DSI_BASE + 0x0400, 0x40); MIPI_OUTP(MIPI_DSI_BASE + 0x0404, 0x67); MIPI_OUTP(MIPI_DSI_BASE + 0x0408, 0x0); MIPI_OUTP(MIPI_DSI_BASE + 0x040c, 0x0); MIPI_OUTP(MIPI_DSI_BASE + 0x0414, 0x1); MIPI_OUTP(MIPI_DSI_BASE + 0x0418, 0x88); }
void mipi_dsi_phy_init(int panel_ndx, struct msm_panel_info const *panel_info, int target_type) { struct mipi_dsi_phy_ctrl *pd; int i, off; MIPI_OUTP(MIPI_DSI_BASE + 0x128, 0x0001);/* start phy sw reset */ wmb(); usleep(1); MIPI_OUTP(MIPI_DSI_BASE + 0x128, 0x0000);/* end phy w reset */ wmb(); usleep(1); MIPI_OUTP(MIPI_DSI_BASE + 0x500, 0x0003);/* regulator_ctrl_0 */ MIPI_OUTP(MIPI_DSI_BASE + 0x504, 0x0001);/* regulator_ctrl_1 */ MIPI_OUTP(MIPI_DSI_BASE + 0x508, 0x0001);/* regulator_ctrl_2 */ MIPI_OUTP(MIPI_DSI_BASE + 0x50c, 0x0000);/* regulator_ctrl_3 */ MIPI_OUTP(MIPI_DSI_BASE + 0x510, 0x0100);/* regulator_ctrl_4 */ MIPI_OUTP(MIPI_DSI_BASE + 0x4b0, 0x04);/* DSIPHY_LDO_CNTRL */ pd = (panel_info->mipi).dsi_phy_db; off = 0x0480; /* strength 0 - 2 */ for (i = 0; i < 3; i++) { MIPI_OUTP(MIPI_DSI_BASE + off, pd->strength[i]); wmb(); off += 4; } off = 0x0470; /* ctrl 0 - 3 */ for (i = 0; i < 4; i++) { MIPI_OUTP(MIPI_DSI_BASE + off, pd->ctrl[i]); wmb(); off += 4; } off = 0x0500; /* regulator ctrl 0 - 4 */ for (i = 0; i < 5; i++) { MIPI_OUTP(MIPI_DSI_BASE + off, pd->regulator[i]); wmb(); off += 4; } mipi_dsi_calibration(); mipi_dsi_lane_cfg(); /* lane cfgs */ mipi_dsi_bist_ctrl(); /* bist ctrl */ off = 0x0204; /* pll ctrl 1 - 19, skip 0 */ for (i = 1; i < 20; i++) { MIPI_OUTP(MIPI_DSI_BASE + off, pd->pll[i]); wmb(); off += 4; } if (panel_info) mipi_dsi_phy_pll_config(panel_info->clk_rate); /* pll ctrl 0 */ MIPI_OUTP(MIPI_DSI_BASE + 0x200, pd->pll[0]); wmb(); off = 0x0440; /* phy timing ctrl 0 - 11 */ for (i = 0; i < 12; i++) { MIPI_OUTP(MIPI_DSI_BASE + off, pd->timing[i]); wmb(); off += 4; } if (target_type == 1) mipi_dsi_configure_serdes(); }
void mipi_dsi_phy_init(int panel_ndx, struct msm_panel_info const *panel_info, int target_type) { struct mipi_dsi_phy_ctrl *pd; int i, off; MIPI_OUTP(MIPI_DSI_BASE + 0x128, 0x0001); wmb(); usleep(1); MIPI_OUTP(MIPI_DSI_BASE + 0x128, 0x0000); wmb(); usleep(1); MIPI_OUTP(MIPI_DSI_BASE + 0x500, 0x0003); MIPI_OUTP(MIPI_DSI_BASE + 0x504, 0x0001); MIPI_OUTP(MIPI_DSI_BASE + 0x508, 0x0001); MIPI_OUTP(MIPI_DSI_BASE + 0x50c, 0x0000); MIPI_OUTP(MIPI_DSI_BASE + 0x510, 0x0100); MIPI_OUTP(MIPI_DSI_BASE + 0x4b0, 0x04); pd = (panel_info->mipi).dsi_phy_db; off = 0x0480; for (i = 0; i < 3; i++) { MIPI_OUTP(MIPI_DSI_BASE + off, pd->strength[i]); wmb(); off += 4; } off = 0x0470; for (i = 0; i < 4; i++) { MIPI_OUTP(MIPI_DSI_BASE + off, pd->ctrl[i]); wmb(); off += 4; } off = 0x0500; for (i = 0; i < 5; i++) { MIPI_OUTP(MIPI_DSI_BASE + off, pd->regulator[i]); wmb(); off += 4; } mipi_dsi_calibration(); mipi_dsi_lane_cfg(); mipi_dsi_bist_ctrl(); off = 0x0204; for (i = 1; i < 20; i++) { MIPI_OUTP(MIPI_DSI_BASE + off, pd->pll[i]); wmb(); off += 4; } if (panel_info) mipi_dsi_phy_pll_config(panel_info->clk_rate); MIPI_OUTP(MIPI_DSI_BASE + 0x200, pd->pll[0]); wmb(); off = 0x0440; for (i = 0; i < 12; i++) { MIPI_OUTP(MIPI_DSI_BASE + off, pd->timing[i]); wmb(); off += 4; } if (target_type == 1) mipi_dsi_configure_serdes(); }
static void __mdss_dsi_ctrl_setup(struct mdss_panel_data *pdata) { struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; struct mdss_panel_info *pinfo; struct mipi_panel_info *mipi; u32 clk_rate; u32 hbp, hfp, vbp, vfp, hspw, vspw, width, height; u32 ystride, bpp, data, dst_bpp; u32 dummy_xres, dummy_yres; u32 hsync_period, vsync_period; ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); pinfo = &pdata->panel_info; 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); hbp = mult_frac(pdata->panel_info.lcdc.h_back_porch, dst_bpp, pdata->panel_info.bpp); hfp = mult_frac(pdata->panel_info.lcdc.h_front_porch, dst_bpp, pdata->panel_info.bpp); vbp = mult_frac(pdata->panel_info.lcdc.v_back_porch, dst_bpp, pdata->panel_info.bpp); vfp = mult_frac(pdata->panel_info.lcdc.v_front_porch, dst_bpp, pdata->panel_info.bpp); hspw = mult_frac(pdata->panel_info.lcdc.h_pulse_width, dst_bpp, pdata->panel_info.bpp); vspw = pdata->panel_info.lcdc.v_pulse_width; width = mult_frac(pdata->panel_info.xres, dst_bpp, pdata->panel_info.bpp); height = pdata->panel_info.yres; if (pdata->panel_info.type == MIPI_VIDEO_PANEL) { dummy_xres = pdata->panel_info.lcdc.xres_pad; dummy_yres = pdata->panel_info.lcdc.yres_pad; } 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) { MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x24, ((hspw + hbp + width + dummy_xres) << 16 | (hspw + hbp))); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x28, ((vspw + vbp + height + dummy_yres) << 16 | (vspw + vbp))); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x2C, ((vsync_period - 1) << 16) | (hsync_period - 1)); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x30, (hspw << 16)); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x34, 0); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x38, (vspw << 16)); } else { /* command mode */ if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB888) bpp = 3; else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB666) bpp = 3; else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB565) bpp = 2; else bpp = 3; /* Default format set to RGB888 */ ystride = width * bpp + 1; /* DSI_COMMAND_MODE_MDP_STREAM_CTRL */ data = (ystride << 16) | (mipi->vc << 8) | DTYPE_DCS_LWRITE; MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x60, data); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x58, data); /* DSI_COMMAND_MODE_MDP_STREAM_TOTAL */ data = height << 16 | width; MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x64, data); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x5C, data); } }
void mdss_dsi_phy_init(struct mdss_panel_data *pdata) { struct mdss_dsi_phy_ctrl *pd; int i, off, ln, offset; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); if (!ctrl_pdata) { pr_err("%s: Invalid input data\n", __func__); return; } pd = &(((ctrl_pdata->panel_data).panel_info.mipi).dsi_phy_db); /* Strength ctrl 0 */ MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0484, pd->strength[0]); /* phy regulator ctrl settings. Both the DSI controller have one regulator */ if ((ctrl_pdata->panel_data).panel_info.pdest == DISPLAY_1) off = 0x0580; else off = 0x0580 - 0x600; /* Regulator ctrl 0 */ MIPI_OUTP((ctrl_pdata->ctrl_base) + off + (4 * 0), 0x0); /* Regulator ctrl - CAL_PWR_CFG */ MIPI_OUTP((ctrl_pdata->ctrl_base) + off + (4 * 6), pd->regulator[6]); /* Regulator ctrl - TEST */ MIPI_OUTP((ctrl_pdata->ctrl_base) + off + (4 * 5), pd->regulator[5]); /* Regulator ctrl 3 */ MIPI_OUTP((ctrl_pdata->ctrl_base) + off + (4 * 3), pd->regulator[3]); /* Regulator ctrl 2 */ MIPI_OUTP((ctrl_pdata->ctrl_base) + off + (4 * 2), pd->regulator[2]); /* Regulator ctrl 1 */ MIPI_OUTP((ctrl_pdata->ctrl_base) + off + (4 * 1), pd->regulator[1]); /* Regulator ctrl 0 */ MIPI_OUTP((ctrl_pdata->ctrl_base) + off + (4 * 0), pd->regulator[0]); /* Regulator ctrl 4 */ MIPI_OUTP((ctrl_pdata->ctrl_base) + off + (4 * 4), pd->regulator[4]); /* LDO ctrl 0 */ if ((ctrl_pdata->panel_data).panel_info.pdest == DISPLAY_1) MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x4dc, 0x00); else MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x4dc, 0x00); off = 0x0440; /* phy timing ctrl 0 - 11 */ for (i = 0; i < 12; i++) { MIPI_OUTP((ctrl_pdata->ctrl_base) + off, pd->timing[i]); wmb(); off += 4; } /* MMSS_DSI_0_PHY_DSIPHY_CTRL_1 */ MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0474, 0x00); /* MMSS_DSI_0_PHY_DSIPHY_CTRL_0 */ MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0470, 0x5f); wmb(); /* Strength ctrl 1 */ MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0488, pd->strength[1]); wmb(); /* 4 lanes + clk lane configuration */ /* lane config n * (0 - 4) & DataPath setup */ for (ln = 0; ln < 5; ln++) { off = 0x0300 + (ln * 0x40); for (i = 0; i < 9; i++) { offset = i + (ln * 9); MIPI_OUTP((ctrl_pdata->ctrl_base) + off, pd->lanecfg[offset]); wmb(); off += 4; } } /* MMSS_DSI_0_PHY_DSIPHY_CTRL_0 */ MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0470, 0x5f); wmb(); /* DSI_0_PHY_DSIPHY_GLBL_TEST_CTRL */ if ((ctrl_pdata->panel_data).panel_info.pdest == DISPLAY_1) MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x04d4, 0x01); else MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x04d4, 0x00); wmb(); off = 0x04b4; /* phy BIST ctrl 0 - 5 */ for (i = 0; i < 6; i++) { MIPI_OUTP((ctrl_pdata->ctrl_base) + off, pd->bistctrl[i]); wmb(); off += 4; } }
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; 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_debug("%s+: ctrl=%p ndx=%d\n", __func__, ctrl_pdata, ctrl_pdata->ndx); pinfo = &pdata->panel_info; mipi = &pdata->panel_info.mipi; 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_debug("%s-:\n", __func__); return 0; }
static int mdss_dsi_cmd_dma_tx(struct mdss_dsi_ctrl_pdata *ctrl, struct dsi_buf *tp) { int len, ret = 0; int domain = MDSS_IOMMU_DOMAIN_UNSECURE; char *bp; unsigned long size, addr; #ifdef DEBUG_CMD int i; bp = tp->data; pr_info("%s: ", __func__); for (i = 0; i < tp->len; i++) printk("%x ", *bp++); pr_info("\n"); #endif bp = tp->data; len = ALIGN(tp->len, 4); size = ALIGN(tp->len, SZ_4K); tp->dmap = dma_map_single(&dsi_dev, tp->data, size, DMA_TO_DEVICE); if (dma_mapping_error(&dsi_dev, tp->dmap)) { pr_err("%s: dmap mapp failed\n", __func__); return -ENOMEM; } if (is_mdss_iommu_attached()) { int ret = msm_iommu_map_contig_buffer(tp->dmap, mdss_get_iommu_domain(domain), 0, size, SZ_4K, 0, &(addr)); if (IS_ERR_VALUE(ret)) { pr_err("unable to map dma memory to iommu(%d)\n", ret); return -ENOMEM; } } else { addr = tp->dmap; } INIT_COMPLETION(ctrl->dma_comp); if (ctrl->shared_pdata.broadcast_enable) if ((ctrl->ndx == DSI_CTRL_1) && (left_ctrl_pdata != NULL)) { MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x048, addr); MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x04c, len); } MIPI_OUTP((ctrl->ctrl_base) + 0x048, addr); MIPI_OUTP((ctrl->ctrl_base) + 0x04c, len); wmb(); if (ctrl->shared_pdata.broadcast_enable) if ((ctrl->ndx == DSI_CTRL_1) && (left_ctrl_pdata != NULL)) { MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x090, 0x01); } MIPI_OUTP((ctrl->ctrl_base) + 0x090, 0x01); /* trigger */ wmb(); ret = wait_for_completion_timeout(&ctrl->dma_comp, msecs_to_jiffies(DMA_TX_TIMEOUT)); if (ret == 0) { #if defined (CONFIG_FB_MSM_MDSS_DSI_DBG) dumpreg(); mdp5_dump_regs(); mdss_dsi_dump_power_clk(&ctrl->panel_data, 0); mdss_mdp_dump_power_clk(); mdss_mdp_debug_bus(); xlog_dump(); #endif pr_err("dma tx timeout!!\n"); ret = -ETIMEDOUT; } else ret = tp->len; if (is_mdss_iommu_attached()) msm_iommu_unmap_contig_buffer(addr, mdss_get_iommu_domain(domain), 0, size); return ret; }