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;
}
Пример #2
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;
	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;
}
Пример #5
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;
}
Пример #7
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;
}
Пример #8
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_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;
}