int mdss_dsi_cont_splash_on(struct mdss_panel_data *pdata) { int ret = 0; struct mipi_panel_info *mipi; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; pr_info("%s:%d DSI on for continuous splash.\n", __func__, __LINE__); if (pdata == NULL) { pr_err("%s: Invalid input data\n", __func__); return -EINVAL; } #if defined(CONFIG_FB_MSM_MDSS_S6E8AA0A_HD_PANEL) mdss_dsi_reset(pdata); #endif mipi = &pdata->panel_info.mipi; 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); WARN((ctrl_pdata->ctrl_state & CTRL_STATE_PANEL_INIT), "Incorrect Ctrl state=0x%x\n", ctrl_pdata->ctrl_state); #if defined(CONFIG_FB_MSM_MDSS_SDC_WXGA_PANEL) ret = mdss_dsi_panel_power_on(pdata, 0); if (ret) { pr_err("%s: Panel power on with 0 failed\n", __func__); return ret; } mdelay(10); ret = mdss_dsi_panel_power_on(pdata, 1); if (ret) { pr_err("%s: Panel power on with 1 failed\n", __func__); return ret; } #endif mdss_dsi_sw_reset(pdata); mdss_dsi_host_init(mipi, pdata); #if RESET_IN_LP11 // add for LP11 // LP11 { u32 tmp; tmp = MIPI_INP((ctrl_pdata->ctrl_base) + 0xac); tmp &= ~(1<<28); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0xac, tmp); wmb(); } // LP11 (ctrl_pdata->panel_data).panel_reset_fn(pdata, 1); #endif 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(); } mdss_dsi_op_mode_config(mipi->mode, pdata); if (ctrl_pdata->on_cmds.link_state == DSI_LP_MODE) { ret = mdss_dsi_unblank(pdata); if (ret) { pr_err("%s: unblank failed\n", __func__); return ret; } } pr_debug("%s-:End\n", __func__); return ret; }
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; }
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(); }
int disp_ext_board_detect_board(struct msm_fb_data_type *mfd) { int i; int ret = 0; int panel_found; #ifndef CONFIG_FB_MSM_MIPI_DSI_RENESAS_CM uint32_t data; #else uint32_t data[2]; #endif DISP_LOCAL_LOG_EMERG("DISP disp_ext_board_detect_board S\n"); if( panel_detection != 0 ) { pr_debug("%s:panel Checked\n", __func__); DISP_LOCAL_LOG_EMERG("%s:panel Checked\n", __func__); return panel_detection; } mipi_dsi_op_mode_config(DSI_CMD_MODE); #ifndef CONFIG_FB_MSM_MIPI_DSI_RENESAS_CM /* cmd1 select */ ret = disp_ext_board_cmd_tx( detect_board_cmd1_select, sizeof(detect_board_cmd1_select), 0 ); if ( ret != 0 ) { pr_err("%s:command send err1\n", __func__); mipi_dsi_op_mode_config(mfd->panel_info.mipi.mode); light_led_disp_set(LIGHT_MAIN_WLED_LCD_DIS); panel_detection = -1; return panel_detection; } #endif #ifdef CONFIG_FB_MSM_MIPI_DSI_RENESAS_CM mipi_dsi_clk_cfg(1); #endif panel_found = 0; for( i = 0 ; i < DETECT_BOARD_NUM ; i++ ) { /* MIPI_DSI_MRPS, Maximum Return Packet Size */ if (!mfd->panel_info.mipi.no_max_pkt_size) { disp_ext_board_cmd_tx( maximum_return_seze_set , sizeof(maximum_return_seze_set), 0 ); } ret = disp_ext_board_cmd_tx( detect_board_mipi_lane_read , sizeof(detect_board_mipi_lane_read), 5 ); if ( ret != 0 ) { pr_err("%s:ack no receive\n", __func__); mipi_dsi_op_mode_config(mfd->panel_info.mipi.mode); light_led_disp_set(LIGHT_MAIN_WLED_LCD_DIS); panel_detection = -1; return panel_detection; } #ifndef CONFIG_FB_MSM_MIPI_DSI_RENESAS_CM data = (uint32)MIPI_INP(MIPI_DSI_BASE + 0x68); if( ((data >> 16) & 0xFF) == 0x02 ) { panel_found = 1; break; } #else data[0] = (uint32)MIPI_INP(MIPI_DSI_BASE + 0x6C); data[1] = (uint32)MIPI_INP(MIPI_DSI_BASE + 0x68); data[1] &= 0xffff0000; pr_info("%s: device code=%04x %04x\n", __func__, data[0], data[1] ); if ( (data[0] == 0x01010101)&&(data[1] == 0x00ff0000) ) { panel_found = 1; break; } else if ( (data[0] == 0x02020202)&&(data[1] == 0x00ff0000) ) { panel_found = 2; break; } #endif } #ifndef CONFIG_FB_MSM_MIPI_DSI_RENESAS_CM if( panel_found != 1 ) { #else mipi_dsi_clk_cfg(0); if( panel_found != 1 && panel_found != 2) { #endif pr_debug("%s:panel not found\n", __func__); DISP_LOCAL_LOG_EMERG("%s:panel not found 2\n", __func__); mipi_dsi_op_mode_config(mfd->panel_info.mipi.mode); light_led_disp_set(LIGHT_MAIN_WLED_LCD_DIS); panel_detection = -1; return panel_detection; } pr_debug("%s:panel found\n", __func__); DISP_LOCAL_LOG_EMERG("%s:panel found\n", __func__); mipi_dsi_op_mode_config(mfd->panel_info.mipi.mode); light_led_disp_set(LIGHT_MAIN_WLED_LCD_EN); DISP_LOCAL_LOG_EMERG("DISP disp_ext_board_detect_board E\n"); #ifndef CONFIG_FB_MSM_MIPI_DSI_RENESAS_CM panel_detection = 1; #else panel_detection = panel_found; #endif return panel_detection; } int disp_ext_board_get_panel_detect(void) { return panel_detection; }
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; }
/* * 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_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; }
/* * 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); } /*fix qcom bug*/ #ifdef CONFIG_HUAWEI_KERNEL if (rlen <= 2) { #else if (rlen == 0) { #endif 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; } #define DMA_TX_TIMEOUT 200 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 CONFIG_HUAWEI_LCD bool iommu_attached = false; #endif 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; } #ifdef CONFIG_HUAWEI_LCD iommu_attached = true; #endif } else { addr = tp->dmap; #ifdef CONFIG_HUAWEI_LCD iommu_attached = false; #endif } 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; #ifdef CONFIG_HUAWEI_LCD //unmap it when it have been maped at front if (is_mdss_iommu_attached() && iommu_attached) #else if (is_mdss_iommu_attached()) #endif msm_iommu_unmap_contig_buffer(addr, mdss_get_iommu_domain(domain), 0, size); return ret; }
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; pr_debug("%s+:\n", __func__); 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); cont_splash_clk_ctrl(0); mipi_dsi_prepare_ahb_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(); 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 (mipi->force_clk_lane_hs) { u32 tmp; 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); 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); } } }
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; 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); mipi_dsi_mdp_busy_wait(mfd); } else { mdp3_dsi_cmd_dma_busy_wait(mfd); } } else { /* video mode, wait until fifo cleaned */ mipi_dsi_controller_cfg(0); } /* * 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 local_bh_disable(); mipi_dsi_clk_disable(); local_bh_enable(); /* disbale dsi engine */ dsi_ctrl = MIPI_INP(MIPI_DSI_BASE + 0x0000); dsi_ctrl &= ~0x01; MIPI_OUTP(MIPI_DSI_BASE + 0x0000, dsi_ctrl); mipi_dsi_phy_ctrl(0); local_bh_disable(); mipi_dsi_ahb_ctrl(0); local_bh_enable(); if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_power_save) mipi_dsi_pdata->dsi_power_save(0); #if defined(CONFIG_FB_MSM_MIPI_PANEL_POWERON_LP11) if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_client_power_save) mipi_dsi_pdata->dsi_client_power_save(0); #endif /* CONFIG_FB_MSM_MIPI_PANEL_POWERON_LP11 */ if (mdp_rev >= MDP_REV_41) mutex_unlock(&mfd->dma->ov_mutex); else up(&mfd->dma->mutex); 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; uint32 dsi_ctrl; 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 (mipi_dsi_pdata && mipi_dsi_pdata->active_reset) mipi_dsi_pdata->active_reset(0); /* low */ if (mipi_dsi_pdata && mipi_dsi_pdata->panel_power_save) mipi_dsi_pdata->panel_power_save(0); 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; }
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); #if defined(CONFIG_FB_MSM_MIPI_PANEL_POWERON_LP11) /* * Fix for floating state of VDD line in toshiba chip * */ if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_client_power_save) mipi_dsi_pdata->dsi_client_power_save(1); #endif /* CONFIG_FB_MSM_MIPI_PANEL_POWERON_LP11 */ cont_splash_clk_ctrl(); local_bh_disable(); mipi_dsi_ahb_ctrl(1); local_bh_enable(); clk_rate = mfd->fbi->var.pixclock; clk_rate = min(clk_rate, mfd->panel_info.clk_max); 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_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); local_bh_disable(); mipi_dsi_clk_enable(); local_bh_enable(); 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); #if defined(CONFIG_FB_MSM_MIPI_PANEL_POWERON_LP11) /* * For TC358764 D2L IC, one of the requirement for power on * is to maintain an LP11 state in data and clock lanes during * power enabling and reset assertion. This change is to * achieve that. * */ if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_client_power_save) { u32 tmp_reg0c, tmp_rega8; mipi_dsi_pdata->dsi_client_reset(); 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(5); /* restore previous values */ MIPI_OUTP(MIPI_DSI_BASE + 0x0c, tmp_reg0c); MIPI_OUTP(MIPI_DSI_BASE + 0xa8, tmp_rega8); wmb(); } #endif /* CONFIG_FB_MSM_MIPI_PANEL_POWERON_LP11 */ if (mipi->force_clk_lane_hs) { u32 tmp; 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); 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); } } } } mipi_dsi_set_tear_on(mfd); } } #ifdef CONFIG_MSM_BUS_SCALING mdp_bus_scale_update_request(2); #endif mdp4_overlay_dsi_state_set(ST_DSI_RESUME); if (mdp_rev >= MDP_REV_41) mutex_unlock(&mfd->dma->ov_mutex); else up(&mfd->dma->mutex); pr_debug("%s-:\n", __func__); return ret; }
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, *temp_ctrl = 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; } temp_ctrl = ctrl_pdata; pd = &(((ctrl_pdata->panel_data).panel_info.mipi).dsi_phy_db); /* Strength ctrl 0 */ MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x0184, pd->strength[0]); /* * Phy regulator ctrl settings. * In dual dsi configuration, the second controller also uses * the regulators of the first controller, irrespective of whether * broadcast mode is enabled or not. */ if (ctrl_pdata->ndx == DSI_CTRL_1) { temp_ctrl = mdss_dsi_get_ctrl_by_index(DSI_CTRL_0); if (!temp_ctrl) { pr_err("%s: Unable to get master ctrl\n", __func__); return; } } if (pd->reg_ldo_mode) { /* Regulator ctrl 0 */ MIPI_OUTP((temp_ctrl->phy_io.base) + 0x280, 0x0); /* Regulator ctrl - CAL_PWR_CFG */ MIPI_OUTP((temp_ctrl->phy_io.base) + 0x298, pd->regulator[6]); /* Add H/w recommended delay */ udelay(1000); /* Regulator ctrl - TEST */ MIPI_OUTP((temp_ctrl->phy_io.base) + 0x294, pd->regulator[5]); /* Regulator ctrl 3 */ MIPI_OUTP((temp_ctrl->phy_io.base) + 0x28c, pd->regulator[3]); /* Regulator ctrl 2 */ MIPI_OUTP((temp_ctrl->phy_io.base) + 0x288, pd->regulator[2]); /* Regulator ctrl 1 */ MIPI_OUTP((temp_ctrl->phy_io.base) + 0x284, pd->regulator[1]); /* Regulator ctrl 4 */ MIPI_OUTP((temp_ctrl->phy_io.base) + 0x290, pd->regulator[4]); /* LDO ctrl */ if (MIPI_INP(ctrl_pdata->ctrl_base) == MDSS_DSI_HW_REV_103_1) MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x1dc, 0x05); else MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x1dc, 0x0d); } else { /* Regulator ctrl 0 */ MIPI_OUTP((temp_ctrl->phy_io.base) + 0x280, 0x0); /* Regulator ctrl - CAL_PWR_CFG */ MIPI_OUTP((temp_ctrl->phy_io.base) + 0x298, pd->regulator[6]); /* Add H/w recommended delay */ udelay(1000); /* Regulator ctrl 1 */ MIPI_OUTP((temp_ctrl->phy_io.base) + 0x284, pd->regulator[1]); /* Regulator ctrl 2 */ MIPI_OUTP((temp_ctrl->phy_io.base) + 0x288, pd->regulator[2]); /* Regulator ctrl 3 */ MIPI_OUTP((temp_ctrl->phy_io.base) + 0x28c, pd->regulator[3]); /* Regulator ctrl 4 */ MIPI_OUTP((temp_ctrl->phy_io.base) + 0x290, pd->regulator[4]); /* LDO ctrl */ MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x1dc, 0x00); /* Regulator ctrl 0 */ MIPI_OUTP((temp_ctrl->phy_io.base) + 0x280, pd->regulator[0]); } off = 0x0140; /* phy timing ctrl 0 - 11 */ for (i = 0; i < 12; i++) { MIPI_OUTP((ctrl_pdata->phy_io.base) + off, pd->timing[i]); wmb(); off += 4; } /* MMSS_DSI_0_PHY_DSIPHY_CTRL_1 */ MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x0174, 0x00); /* MMSS_DSI_0_PHY_DSIPHY_CTRL_0 */ MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x0170, 0x5f); wmb(); /* Strength ctrl 1 */ MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x0188, pd->strength[1]); wmb(); /* 4 lanes + clk lane configuration */ /* lane config n * (0 - 4) & DataPath setup */ for (ln = 0; ln < 5; ln++) { off = (ln * 0x40); for (i = 0; i < 9; i++) { offset = i + (ln * 9); MIPI_OUTP((ctrl_pdata->phy_io.base) + off, pd->lanecfg[offset]); wmb(); off += 4; } } /* MMSS_DSI_0_PHY_DSIPHY_CTRL_0 */ MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x0170, 0x5f); wmb(); /* DSI_0_PHY_DSIPHY_GLBL_TEST_CTRL */ if ((ctrl_pdata->panel_data).panel_info.pdest == DISPLAY_1) MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x01d4, 0x01); else MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x01d4, 0x00); wmb(); off = 0x01b4; /* phy BIST ctrl 0 - 5 */ for (i = 0; i < 6; i++) { MIPI_OUTP((ctrl_pdata->phy_io.base) + off, pd->bistctrl[i]); wmb(); off += 4; } }
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; printk("%s+:\n", __func__); mfd = platform_get_drvdata(pdev); fbi = mfd->fbi; var = &fbi->var; pinfo = &mfd->panel_info; esc_byte_ratio = pinfo->mipi.esc_byte_ratio; if (mfd->first_init_lcd == 0) { 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(); 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 { MIPI_OUTP(MIPI_DSI_BASE + 0x00ac, mipi_dsi_pdata->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 { 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; ystride = width * bpp + 1; data = (ystride << 16) | (mipi->vc << 8) | DTYPE_DCS_LWRITE; MIPI_OUTP(MIPI_DSI_BASE + 0x5c, data); MIPI_OUTP(MIPI_DSI_BASE + 0x54, data); data = height << 16 | width; MIPI_OUTP(MIPI_DSI_BASE + 0x60, data); MIPI_OUTP(MIPI_DSI_BASE + 0x58, data); } mipi_dsi_host_init(mipi, mipi_dsi_pdata->dlane_swap); if (mipi->force_clk_lane_hs) { u32 tmp; tmp = MIPI_INP(MIPI_DSI_BASE + 0xA8); tmp |= (1<<28); MIPI_OUTP(MIPI_DSI_BASE + 0xA8, tmp); wmb(); } #if defined(CONFIG_MACH_DUMMY) if ((panel_type == PANEL_ID_PROTODCG_SHARP || panel_type == PANEL_ID_PROTODCG_SHARP_C1) && mfd->first_init_lcd != 0) { protodcg_orise_lcd_pre_off(pdev); if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_power_save) mipi_dsi_pdata->dsi_power_save(1); } #elif defined(CONFIG_MACH_PROTOU) if ((panel_type == PANEL_ID_PROTOU_SHARP || panel_type == PANEL_ID_PROTOU_SHARP_C1) && mfd->first_init_lcd != 0) { protou_orise_lcd_pre_off(pdev); if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_power_save) mipi_dsi_pdata->dsi_power_save(1); } #endif if (panel_type == PANEL_ID_URANUS_SONY_ORISE) { if(mfd->first_init_lcd != 0) { if (mipi_dsi_pdata && mipi_dsi_pdata->lcd_pre_off) mipi_dsi_pdata->lcd_pre_off(pdev); if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_power_save) mipi_dsi_pdata->dsi_power_save(1); } } 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_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; }
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; u32 hsync_period, vsync_period; 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; //ASUS_BSP: Louis for display miniporting +++ #if 0 ret = msm_dss_enable_vreg(ctrl_pdata->power_data.vreg_config, ctrl_pdata->power_data.num_vreg, 1); if (ret) { pr_err("%s:Failed to enable vregs. rc=%d\n", __func__, ret); return ret; } #else ret = a90_mdss_dsi_panel_power_on(pdata, 1); if (ret) { pr_err("%s: Panel power on failed\n", __func__); return ret; } #endif //ASUS_BSP: Louis for display miniporting --- pdata->panel_info.panel_power_on = 1; if (!pdata->panel_info.mipi.lp11_init) mdss_dsi_panel_reset(pdata, 1); ret = mdss_dsi_enable_bus_clocks(ctrl_pdata); if (ret) { pr_err("%s: failed to enable bus clocks. rc=%d\n", __func__, ret); //ASUS_BSP: Louis for display porting ++ //mdss_dsi_panel_power_on(pdata, 0); //#ifdef ASUS_A91_PROJECT a90_mdss_dsi_panel_power_on(pdata, 0); //#elif defined ASUS_ME771KL_PROJECT // me771_mdss_dsi_panel_power_on(pdata, 0); //#endif //ASUS_BSP: Louis for display porting -- pdata->panel_info.panel_power_on = 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); 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); } mdss_dsi_sw_reset(pdata); mdss_dsi_host_init(mipi, pdata); /* * Issue hardware reset line after enabling the DSI clocks and data * data lanes for LP11 init */ if (pdata->panel_info.mipi.lp11_init) mdss_dsi_panel_reset(pdata, 1); if (pdata->panel_info.mipi.init_delay) usleep(pdata->panel_info.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, 0); pr_debug("%s-:\n", __func__); return 0; }
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; }
irqreturn_t mdss_dsi_isr(int irq, void *ptr) { u32 isr; struct mdss_dsi_ctrl_pdata *ctrl = (struct mdss_dsi_ctrl_pdata *)ptr; if (!ctrl->ctrl_base) pr_err("%s:%d DSI base adr no Initialized", __func__, __LINE__); 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)) { u32 isr0; isr0 = MIPI_INP(left_ctrl_pdata->ctrl_base + 0x0110);/* DSI_INTR_CTRL */ if (isr0 & DSI_INTR_CMD_DMA_DONE) MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0110, DSI_INTR_CMD_DMA_DONE); } 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; }
void dumpreg(void) { u32 tmp0x0,tmp0x4,tmp0x8,tmp0xc; int i; if (dsi_ctrl_base == NULL) { pr_err("%s : dsi_ctrl_base is null!!..\n",__func__); return; } pr_err("%s: =============DSI Reg DUMP==============\n", __func__); #if defined (CONFIG_FB_MSM_MIPI_SAMSUNG_OCTA_CMD_WQHD_PT_PANEL) if (left_ctrl_pdata) { for (i=0; i< 91; i++) { tmp0x0 = MIPI_INP(left_ctrl_pdata->ctrl_base+(i*16)+0x0); tmp0x4 = MIPI_INP(left_ctrl_pdata->ctrl_base+(i*16)+0x4); tmp0x8 = MIPI_INP(left_ctrl_pdata->ctrl_base+(i*16)+0x8); tmp0xc = MIPI_INP(left_ctrl_pdata->ctrl_base+(i*16)+0xc); pr_err("[DSI0][%04x] : %08x %08x %08x %08x\n",i*16, tmp0x0,tmp0x4,tmp0x8,tmp0xc); } } for (i=0; i< 91; i++) { tmp0x0 = MIPI_INP(dsi_ctrl_base+(i*16)+0x0); tmp0x4 = MIPI_INP(dsi_ctrl_base+(i*16)+0x4); tmp0x8 = MIPI_INP(dsi_ctrl_base+(i*16)+0x8); tmp0xc = MIPI_INP(dsi_ctrl_base+(i*16)+0xc); pr_err("[DSI1][%04x] : %08x %08x %08x %08x\n",i*16, tmp0x0,tmp0x4,tmp0x8,tmp0xc); } #else for(i=0; i< 91; i++){ tmp0x0 = MIPI_INP(dsi_ctrl_base+(i*16)+0x0); tmp0x4 = MIPI_INP(dsi_ctrl_base+(i*16)+0x4); tmp0x8 = MIPI_INP(dsi_ctrl_base+(i*16)+0x8); tmp0xc = MIPI_INP(dsi_ctrl_base+(i*16)+0xc); pr_err("[%04x] : %08x %08x %08x %08x\n",i*16, tmp0x0,tmp0x4,tmp0x8,tmp0xc); } #endif pr_err("%s: ============= END ==============\n", __func__); }
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); } } }
/* * mipi_dsi_cmds_single_tx: * thread context only */ int mdss_dsi_cmds_single_tx(struct mdss_dsi_ctrl_pdata *pdata, struct dsi_cmd_desc *cmds, int cnt) { struct dsi_cmd_desc *cm; unsigned int dsi_ctrl, ctrl; int i, j = 0, k = 0, cmd_len = 0, video_mode; char *cmds_tx; char *bp; struct mdss_dsi_ctrl_pdata *ctrl_pdata = pdata; struct dsi_buf *tp = &ctrl_pdata->tx_buf; pr_debug("%s:++\n",__func__); /*Set Last Bit, only for last packet */ for (i = 0; i < cnt; i++) { if(cmds[i].dchdr.dtype != DTYPE_GEN_LWRITE && cmds[i].dchdr.dtype != DTYPE_DCS_LWRITE ) { pr_err("Single TX expects only Long Packets,"\ "Short packet encountered, return fail\n"); return -1; } cmds[i].dchdr.last = 0; } cmds[cnt-1].dchdr.last = 1; /* turn on cmd mode * for video mode, do not send cmds more than * one pixel line, since it only transmit it * during BLLP. */ if (ctrl_pdata->shared_pdata.broadcast_enable) { if ((ctrl_pdata->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) { int data = dsi_ctrl | 0x04; /* CMD_MODE_EN */ MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004, data); } } } dsi_ctrl = MIPI_INP((ctrl_pdata->ctrl_base) + 0x0004); video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */ if (video_mode) { ctrl = dsi_ctrl | 0x04; /* CMD_MODE_EN */ MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004, ctrl); } cm = cmds; cmds_tx = kmalloc((1024 + DSI_HOST_HDR_SIZE) * cnt, GFP_KERNEL); mdss_dsi_buf_init(tp); mdss_dsi_enable_irq(pdata, DSI_CMD_TERM); for (i = 0; i < cnt; i++) { mdss_dsi_buf_init(tp); mdss_dsi_cmd_dma_add(tp, cm); bp = tp->data; for (j = 0; j < tp->len; j++) { *(cmds_tx + k) = *bp++; k++; } cmd_len = cmd_len + tp->len; cm++; } tp->data = cmds_tx; tp->len = cmd_len; mdss_dsi_cmd_dma_tx(ctrl_pdata, tp); kfree(cmds_tx); if (video_mode) MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004, dsi_ctrl); /* restore */ return cnt; }
/* * 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; }
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; }
/* * 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; }
/* * 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; }
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_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; }
static int mdss_dsi_ulps_config_sub(struct mdss_dsi_ctrl_pdata *ctrl_pdata, int enable, int partial) { 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 (!partial && !__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 (!partial && !pdata->panel_info.panel_power_on) { pr_err("%s: panel off. returning\n", __func__); goto error; } if (!partial && __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; }
/* * 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, len, 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; int no_max_pkt_size = ctrl->panel_data.panel_info.mipi.no_max_pkt_size; 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 (no_max_pkt_size) { /* Only support rlen = 4*n */ rlen = ALIGN(rlen, 4); } tp = &ctrl->tx_buf; rp = &ctrl->rx_buf; len = rlen; diff = 0; end = 0; data_byte = 0; if (len <= 2) { rx_byte = 4; /* short read */ short_response = 1; } else { if (len > MDSS_DSI_LEN) { data_byte = MDSS_DSI_LEN; pkt_size = data_byte + 2;/* 8 bytes +2 padding */ rx_byte = data_byte + 8; /* 4 bytes header + 2 bytes crc + 2 Padding */ } else { len = ALIGN(len, 4); data_byte = len; pkt_size = data_byte; rx_byte = data_byte + 6; /* 4 bytes header + 2 bytes crc*/ } short_response = 0; } mdss_dsi_buf_init(rp); while (!end) { pr_debug("%s: rlen=%d pkt_size=%d rx_byte=%d\n", __func__, len, 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); /* 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 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 (len <= data_byte) { diff = data_byte - len; end = 1; } else { diff = 0; len -= 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; if (rlen <= MDSS_DSI_LEN && !no_max_pkt_size && !short_response) { /* * 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]; pr_debug("%s: Read Response:0x%02X\n", __func__, cmd); switch (cmd) { case DTYPE_ACK_ERR_RESP: pr_info("%s: rx ACK_ERR_PACKAGE\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; }