int32_t mdss_dsi_auto_pll_config(uint32_t pll_base, uint32_t ctl_base, struct mdss_dsi_pll_config *pd) { int rc = NO_ERROR; struct mdss_dsi_vco_calc vco_calc; rc = mdss_dsi_pll_vco_rate_calc(pd, &vco_calc); if (rc) return rc; mdss_dsi_ssc_param_calc(pd, &vco_calc); mdss_dsi_phy_sw_reset(ctl_base); mdss_dsi_pll_vco_config(pll_base, pd, &vco_calc); return rc; }
int mdss_dsi_on(struct mdss_panel_data *pdata) { int ret = 0; struct mdss_panel_info *pinfo; struct mipi_panel_info *mipi; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; struct mdss_data_type *mdata = mdss_mdp_get_mdata(); if (pdata == NULL) { pr_err("%s: Invalid input data\n", __func__); return -EINVAL; } if (pdata->panel_info.panel_power_on) { pr_warn("%s:%d Panel already on.\n", __func__, __LINE__); return 0; } ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); pr_info("%s+: ctrl=%p ndx=%d\n", __func__, ctrl_pdata, ctrl_pdata->ndx); pinfo = &pdata->panel_info; mipi = &pdata->panel_info.mipi; if (ctrl_pdata->partial_mode_enabled && !pdata->panel_info.panel_dead) { mdss_dsi_ulps_config_sub(ctrl_pdata, 0, 1); mdata->ulps = false; pdata->panel_info.panel_power_on = 1; mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1); } else { if (ctrl_pdata->partial_mode_enabled && pdata->panel_info.panel_dead) pr_warn("%s: Panel is dead, bring up DSI\n", __func__); ret = mdss_dsi_panel_power_on(pdata, 1); if (ret) { pr_err("%s:Panel power on failed. rc=%d\n", __func__, ret); return ret; } mdss_dsi_clk_ctrl(ctrl_pdata, DSI_BUS_CLKS, 1); if (ret) { pr_err("%s: failed to enable bus clocks. rc=%d\n", __func__, ret); ret = mdss_dsi_panel_power_on(pdata, 0); if (ret) { pr_err("%s: Panel reset failed. rc=%d\n", __func__, ret); return ret; } pdata->panel_info.panel_power_on = 0; return ret; } pdata->panel_info.panel_power_on = 1; mdss_dsi_phy_sw_reset((ctrl_pdata->ctrl_base)); mdss_dsi_phy_init(pdata); mdss_dsi_clk_ctrl(ctrl_pdata, DSI_BUS_CLKS, 0); mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1); __mdss_dsi_ctrl_setup(pdata); mdss_dsi_sw_reset(pdata); mdss_dsi_host_init(pdata); } /* * Issue hardware reset line after enabling the DSI clocks and data * data lanes for LP11 init */ if (mipi->lp11_init) mdss_dsi_panel_reset(pdata, 1); if (mipi->init_delay) usleep(mipi->init_delay); if (mipi->force_clk_lane_hs) { u32 tmp; tmp = MIPI_INP((ctrl_pdata->ctrl_base) + 0xac); tmp |= (1<<28); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0xac, tmp); wmb(); } if (pdata->panel_info.type == MIPI_CMD_PANEL) mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 0); pr_info("%s-:\n", __func__); return 0; }
/** * mdss_dsi_core_power_ctrl() - Enable/disable DSI core power * @ctrl: pointer to DSI controller structure * @enable: 1 to enable power, 0 to disable power * * When all DSI bus clocks are disabled, DSI core power module can be turned * off to save any leakage current. This function implements the necessary * programming sequence for the same. For command mode panels, the core power * can be turned off for idle-screen usecases, where additional programming is * needed to clamp DSI phy. */ static int mdss_dsi_core_power_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable) { int rc = 0; struct mdss_panel_data *pdata = NULL; if (!ctrl) { pr_err("%s: invalid input\n", __func__); return -EINVAL; } pdata = &ctrl->panel_data; if (!pdata) { pr_err("%s: Invalid panel data\n", __func__); return -EINVAL; } if (enable) { if (!ctrl->core_power) { /* enable mdss gdsc */ pr_debug("%s: Enable MDP FS\n", __func__); rc = msm_dss_enable_vreg( ctrl->power_data[DSI_CORE_PM].vreg_config, ctrl->power_data[DSI_CORE_PM].num_vreg, 1); if (rc) { pr_err("%s: failed to enable vregs for %s\n", __func__, __mdss_dsi_pm_name(DSI_CORE_PM)); goto error; } ctrl->core_power = true; } rc = mdss_dsi_bus_clk_start(ctrl); if (rc) { pr_err("%s: Failed to start bus clocks. rc=%d\n", __func__, rc); goto error_bus_clk_start; } /* * Phy software reset should not be done for: * 1.) Idle screen power collapse use-case. Issue a phy software * reset only when unblanking the panel in this case. * 2.) When ULPS during suspend is enabled. */ if (pdata->panel_info.blank_state == MDSS_PANEL_BLANK_BLANK && !pdata->panel_info.ulps_suspend_enabled) mdss_dsi_phy_sw_reset(ctrl); /* * Phy and controller setup need not be done during bootup * when continuous splash screen is enabled. */ if (!pdata->panel_info.cont_splash_enabled) { mdss_dsi_phy_init(ctrl); mdss_dsi_ctrl_setup(ctrl); } if (ctrl->ulps) { /* * ULPS Entry Request. This is needed if the lanes were * in ULPS prior to power collapse, since after * power collapse and reset, the DSI controller resets * back to idle state and not ULPS. This ulps entry * request will transition the state of the DSI * controller to ULPS which will match the state of the * DSI phy. This needs to be done prior to disabling * the DSI clamps. * * Also, reset the ulps flag so that ulps_config * function would reconfigure the controller state to * ULPS. */ ctrl->ulps = false; rc = mdss_dsi_ulps_config(ctrl, 1); if (rc) { pr_err("%s: Failed to enter ULPS. rc=%d\n", __func__, rc); goto error_ulps; } } rc = mdss_dsi_clamp_ctrl(ctrl, 0); if (rc) { pr_err("%s: Failed to disable dsi clamps. rc=%d\n", __func__, rc); goto error_ulps; } } else { /* * Enable DSI clamps only if entering idle power collapse or * when ULPS during suspend is enabled. */ if ((pdata->panel_info.blank_state != MDSS_PANEL_BLANK_BLANK) || pdata->panel_info.ulps_suspend_enabled) { rc = mdss_dsi_clamp_ctrl(ctrl, 1); if (rc) pr_err("%s: Failed to enable dsi clamps. rc=%d\n", __func__, rc); } /* * disable bus clocks irrespective of whether dsi phy was * successfully clamped or not */ mdss_dsi_bus_clk_stop(ctrl); /* disable mdss gdsc only if dsi phy was successfully clamped*/ if (rc) { pr_debug("%s: leaving mdss gdsc on\n", __func__); } else { pr_debug("%s: Disable MDP FS\n", __func__); rc = msm_dss_enable_vreg( ctrl->power_data[DSI_CORE_PM].vreg_config, ctrl->power_data[DSI_CORE_PM].num_vreg, 0); if (rc) { pr_warn("%s: failed to disable vregs for %s\n", __func__, __mdss_dsi_pm_name(DSI_CORE_PM)); rc = 0; } else { ctrl->core_power = false; } } } return rc; error_ulps: mdss_dsi_bus_clk_stop(ctrl); error_bus_clk_start: if (msm_dss_enable_vreg(ctrl->power_data[DSI_CORE_PM].vreg_config, ctrl->power_data[DSI_CORE_PM].num_vreg, 0)) pr_warn("%s: failed to disable vregs for %s\n", __func__, __mdss_dsi_pm_name(DSI_CORE_PM)); else ctrl->core_power = false; error: return rc; }
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; 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); 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); 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; }
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; } if (!mipi->lp11_init) { 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) { usleep(mipi->lp11_rst_delay); if (mdss_dsi_pinctrl_set_state(ctrl_pdata, true)) pr_debug("reset enable: pinctrl not enabled\n"); mdss_dsi_panel_reset(pdata, 1); pdata->panel_info.panel_power_on = 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; }
int32_t mdss_dsi_auto_pll_config(uint32_t pll_base, uint32_t ctl_base, struct mdss_dsi_pll_config *pd) { uint32_t rem, divider; uint32_t refclk_cfg = 0, frac_n_mode = 0, ref_doubler_en_b = 0; uint64_t vco_clock, div_fbx; uint32_t ref_clk_to_pll = 0, frac_n_value = 0; uint32_t sdm_cfg0, sdm_cfg1, sdm_cfg2, sdm_cfg3; uint32_t gen_vco_clk, cal_cfg10, cal_cfg11; uint32_t res; uint8_t i, rc = NO_ERROR; /* Configure the Loop filter resistance */ for (i = 0; i < LPFR_LUT_SIZE; i++) if (pd->vco_clock <= lpfr_lut[i].vco_rate) break; if (i == LPFR_LUT_SIZE) { dprintf(INFO, "unable to get loop filter resistance. vco=%d\n" , lpfr_lut[i].vco_rate); rc = ERROR; return rc; } mdss_dsi_phy_sw_reset(ctl_base); /* Loop filter resistance value */ writel(lpfr_lut[i].resistance, pll_base + 0x002c); /* Loop filter capacitance values : c1 and c2 */ writel(0x70, pll_base + 0x0030); writel(0x15, pll_base + 0x0034); writel(0x02, pll_base + 0x0008); /* ChgPump */ /* postDiv1 - calculated in pll config*/ writel(pd->posdiv1, pll_base + 0x0004); /* postDiv2 - fixed devision 4 */ writel(0x03, pll_base + 0x0024); /* postDiv3 - calculated in pll config */ writel(pd->posdiv3, pll_base + 0x0028); /* postDiv3 */ writel(0x2b, pll_base + 0x0078); /* Cal CFG3 */ writel(0x66, pll_base + 0x007c); /* Cal CFG4 */ writel(0x05, pll_base + 0x0064); /* LKDetect CFG2 */ rem = pd->vco_clock % VCO_REF_CLOCK_RATE; if (rem) { refclk_cfg = 0x1; frac_n_mode = 1; ref_doubler_en_b = 0; } else { refclk_cfg = 0x0; frac_n_mode = 0; ref_doubler_en_b = 1; } ref_clk_to_pll = (VCO_REF_CLOCK_RATE * 2 * refclk_cfg) + (ref_doubler_en_b * VCO_REF_CLOCK_RATE); vco_clock = ((uint64_t) pd->vco_clock) * FRAC_DIVIDER; div_fbx = vco_clock / ref_clk_to_pll; rem = (uint32_t) (div_fbx % FRAC_DIVIDER); rem = rem * (1 << 16); frac_n_value = rem / FRAC_DIVIDER; divider = pd->vco_clock / ref_clk_to_pll; div_fbx *= ref_clk_to_pll; gen_vco_clk = div_fbx / FRAC_DIVIDER; if (frac_n_mode) { sdm_cfg0 = 0x0; sdm_cfg1 = (divider & 0x3f) - 1; sdm_cfg3 = frac_n_value / 256; sdm_cfg2 = frac_n_value % 256; } else { sdm_cfg0 = (0x1 << 5); sdm_cfg0 |= (divider & 0x3f) - 1; sdm_cfg1 = 0x0; sdm_cfg2 = 0; sdm_cfg3 = 0; } cal_cfg11 = gen_vco_clk / 256000000; cal_cfg10 = (gen_vco_clk % 256000000) / 1000000; writel(sdm_cfg1 , pll_base + 0x003c); /* SDM CFG1 */ writel(sdm_cfg2 , pll_base + 0x0040); /* SDM CFG2 */ writel(sdm_cfg3 , pll_base + 0x0044); /* SDM CFG3 */ writel(0x00, pll_base + 0x0048); /* SDM CFG4 */ if (pd->vco_delay) udelay(pd->vco_delay); else udelay(10); writel(refclk_cfg, pll_base + 0x0000); /* REFCLK CFG */ writel(0x00, pll_base + 0x0014); /* PWRGEN CFG */ writel(0x71, pll_base + 0x000c); /* VCOLPF CFG */ writel(pd->directpath, pll_base + 0x0010); /* VREG CFG */ writel(sdm_cfg0, pll_base + 0x0038); /* SDM CFG0 */ writel(0x0a, pll_base + 0x006c); /* CAL CFG0 */ writel(0x30, pll_base + 0x0084); /* CAL CFG6 */ writel(0x00, pll_base + 0x0088); /* CAL CFG7 */ writel(0x60, pll_base + 0x008c); /* CAL CFG8 */ writel(0x00, pll_base + 0x0090); /* CAL CFG9 */ writel(cal_cfg10, pll_base + 0x0094); /* CAL CFG10 */ writel(cal_cfg11, pll_base + 0x0098); /* CAL CFG11 */ writel(0x20, pll_base + 0x009c); /* EFUSE CFG */ return 0; }
static 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; u32 dummy_xres, dummy_yres; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); if (!ctrl_pdata) { pr_err("%s: Invalid input data\n", __func__); return -EINVAL; } pinfo = &pdata->panel_info; ret = mdss_dsi_panel_power_on(1); if (ret) { pr_err("%s: Panel power on failed\n", __func__); return ret; } mdss_dsi_phy_sw_reset((ctrl_pdata->ctrl_base)); mdss_dsi_phy_init(pdata); mdss_dsi_prepare_clocks(); mdss_dsi_clk_enable(pdata); clk_rate = pdata->panel_info.clk_rate; clk_rate = min(clk_rate, pdata->panel_info.clk_max); hbp = pdata->panel_info.lcdc.h_back_porch; hfp = pdata->panel_info.lcdc.h_front_porch; vbp = pdata->panel_info.lcdc.v_back_porch; vfp = pdata->panel_info.lcdc.v_front_porch; hspw = pdata->panel_info.lcdc.h_pulse_width; vspw = pdata->panel_info.lcdc.v_pulse_width; width = pdata->panel_info.xres; height = pdata->panel_info.yres; 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(); } ret = ctrl_pdata->on(pdata); if (ret) { pr_err("%s: unable to initialize the panel\n", __func__); return ret; } mdss_dsi_op_mode_config(mipi->mode, pdata); pr_debug("%s-:\n", __func__); return ret; }
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_info("%s+: ctrl=%p ndx=%d\n", __func__, ctrl_pdata, ctrl_pdata->ndx); pinfo = &pdata->panel_info; #ifdef CONFIG_MACH_LGE mdss_dsi_panel_io(pdata, 1); #endif 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; } pdata->panel_info.panel_power_on = 1; if (!pdata->panel_info.mipi.lp11_init) mdss_dsi_panel_reset(pdata, 1); ret = mdss_dsi_bus_clk_start(ctrl_pdata); if (ret) { pr_err("%s: failed to enable bus clocks. rc=%d\n", __func__, ret); mdss_dsi_panel_power_on(pdata, 0); 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_bus_clk_stop(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 { /* */ 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((ctrl_pdata->ctrl_base) + 0x60, data); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x58, data); /* */ 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); /* */ #ifdef CONFIG_MACH_LGE if (pdata->panel_info.mipi.lp11_init){ mdelay(10); if(ctrl_pdata->ndx == 1) mdss_dsi_panel_reset(pdata, 1); } #else if (pdata->panel_info.mipi.lp11_init) mdss_dsi_panel_reset(pdata, 1); #endif if (pdata->panel_info.mipi.init_delay) usleep(pdata->panel_info.mipi.init_delay); #ifndef CONFIG_MACH_LGE 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(); } #endif if (pdata->panel_info.type == MIPI_CMD_PANEL) mdss_dsi_clk_ctrl(ctrl_pdata, 0); pr_info("%s-:\n", __func__); return 0; }