示例#1
0
文件: build.c 项目: AubrCool/barebox
static int get_bad_peb_limit(const struct ubi_device *ubi, int max_beb_per1024)
{
	int limit, device_pebs;
	uint64_t device_size;

	if (!max_beb_per1024)
		return 0;

	/*
	 * Here we are using size of the entire flash chip and
	 * not just the MTD partition size because the maximum
	 * number of bad eraseblocks is a percentage of the
	 * whole device and bad eraseblocks are not fairly
	 * distributed over the flash chip. So the worst case
	 * is that all the bad eraseblocks of the chip are in
	 * the MTD partition we are attaching (ubi->mtd).
	 */
	if (ubi->mtd->master)
		device_size = ubi->mtd->master->size;
	else
		device_size = ubi->mtd->size;

	device_pebs = mtd_div_by_eb(device_size, ubi->mtd);
	limit = mult_frac(device_pebs, max_beb_per1024, 1024);

	/* Round it up */
	if (mult_frac(limit, 1024, max_beb_per1024) < device_pebs)
		limit += 1;

	return limit;
}
static long __div_round_rate(struct div_data *data, unsigned long rate,
	struct clk *parent, unsigned int *best_div, unsigned long *best_prate)
{
	unsigned int div, min_div, max_div, _best_div = 1;
	unsigned long prate, _best_prate = 0, rrate = 0, req_prate, actual_rate;
	unsigned int numer;

	rate = max(rate, 1UL);

	min_div = max(data->min_div, 1U);
	max_div = min(data->max_div, (unsigned int) (ULONG_MAX / rate));

	/*
	 * div values are doubled for half dividers.
	 * Adjust for that by picking a numer of 2.
	 */
	numer = data->is_half_divider ? 2 : 1;

	for (div = min_div; div <= max_div; div++) {
		if (data->skip_odd_div && (div & 1))
				continue;
		req_prate = mult_frac(rate, div, numer);
		prate = clk_round_rate(parent, req_prate);
		if (IS_ERR_VALUE(prate))
			break;

		actual_rate = mult_frac(prate, numer, div);
		if (is_better_rate(rate, rrate, actual_rate)) {
			rrate = actual_rate;
			_best_div = div;
			_best_prate = prate;
		}

		/*
		 * Trying higher dividers is only going to ask the parent for
		 * a higher rate. If it can't even output a rate higher than
		 * the one we request for this divider, the parent is not
		 * going to be able to output an even higher rate required
		 * for a higher divider. So, stop trying higher dividers.
		 */
		if (actual_rate < rate)
			break;

		if (rrate <= rate + data->rate_margin)
			break;
	}

	if (!rrate)
		return -EINVAL;
	if (best_div)
		*best_div = _best_div;
	if (best_prate)
		*best_prate = _best_prate;

	return rrate;
}
示例#3
0
static enum handoff mux_div_clk_handoff(struct clk *c)
{
	struct mux_div_clk *md = to_mux_div_clk(c);
	unsigned long parent_rate;
	unsigned int numer;

	parent_rate = clk_get_rate(c->parent);
	if (!parent_rate)
		return HANDOFF_DISABLED_CLK;
	/*
	 * div values are doubled for half dividers.
	 * Adjust for that by picking a numer of 2.
	 */
	numer = md->data.is_half_divider ? 2 : 1;

	if (md->data.div) {
		c->rate = mult_frac(parent_rate, numer, md->data.div);
	} else {
		c->rate = 0;
		return HANDOFF_DISABLED_CLK;
	}

	if (!md->ops->is_enabled)
		return HANDOFF_DISABLED_CLK;
	if (md->ops->is_enabled(md))
		return HANDOFF_ENABLED_CLK;
	return HANDOFF_DISABLED_CLK;
}
示例#4
0
/**
 * Initialize Hash Filters
 */
int init_hash_filter(struct adapter *adap)
{
	unsigned int n_user_filters;
	unsigned int user_filter_perc;
	int ret;
	u32 params[7], val[7];

#define FW_PARAM_DEV(param) \
	(V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | \
	V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_##param))

#define FW_PARAM_PFVF(param) \
	(V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_PFVF) | \
	V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_PFVF_##param) |  \
	V_FW_PARAMS_PARAM_Y(0) | \
	V_FW_PARAMS_PARAM_Z(0))

	params[0] = FW_PARAM_DEV(NTID);
	ret = t4_query_params(adap, adap->mbox, adap->pf, 0, 1,
			      params, val);
	if (ret < 0)
		return ret;
	adap->tids.ntids = val[0];
	adap->tids.natids = min(adap->tids.ntids / 2, MAX_ATIDS);

	user_filter_perc = 100;
	n_user_filters = mult_frac(adap->tids.nftids,
				   user_filter_perc,
				   100);

	adap->tids.nftids = n_user_filters;
	adap->params.hash_filter = 1;
	return 0;
}
示例#5
0
static int gadc_thermal_adc_to_temp(struct gadc_thermal_info *gti, int val)
{
	int temp, temp_hi, temp_lo, adc_hi, adc_lo;
	int i;

	if (!gti->lookup_table)
		return val;

	for (i = 0; i < gti->nlookup_table; i++) {
		if (val >= gti->lookup_table[2 * i + 1])
			break;
	}

	if (i == 0) {
		temp = gti->lookup_table[0];
	} else if (i >= gti->nlookup_table) {
		temp = gti->lookup_table[2 * (gti->nlookup_table - 1)];
	} else {
		adc_hi = gti->lookup_table[2 * i - 1];
		adc_lo = gti->lookup_table[2 * i + 1];

		temp_hi = gti->lookup_table[2 * i - 2];
		temp_lo = gti->lookup_table[2 * i];

		temp = temp_hi + mult_frac(temp_lo - temp_hi, val - adc_hi,
					   adc_lo - adc_hi);
	}

	return temp;
}
static long __div_round_rate(struct div_data *data, unsigned long rate,
	struct clk *parent, unsigned int *best_div, unsigned long *best_prate)
{
	unsigned int div, min_div, max_div, _best_div = 1;
	unsigned long prate, _best_prate = 0, rrate = 0, req_prate, actual_rate;
	unsigned int numer;

	rate = max(rate, 1UL);

	min_div = max(data->min_div, 1U);
	max_div = min(data->max_div, (unsigned int) (ULONG_MAX / rate));

	numer = data->is_half_divider ? 2 : 1;

	for (div = min_div; div <= max_div; div++) {
		if (data->skip_odd_div && (div & 1))
				continue;
		req_prate = mult_frac(rate, div, numer);
		prate = clk_round_rate(parent, req_prate);
		if (IS_ERR_VALUE(prate))
			break;

		actual_rate = mult_frac(prate, numer, div);
		if (is_better_rate(rate, rrate, actual_rate)) {
			rrate = actual_rate;
			_best_div = div;
			_best_prate = prate;
		}

		if (actual_rate < rate)
			break;

		if (rrate <= rate + data->rate_margin)
			break;
	}

	if (!rrate)
		return -EINVAL;
	if (best_div)
		*best_div = _best_div;
	if (best_prate)
		*best_prate = _best_prate;

	return rrate;
}
/* Returns MBps of read/writes for the sampling window. */
static int mon_get_mbps(int n, u32 start_val, unsigned int us)
{
	u32 overflow, count;
	long long beats;

	count = get_l2_indirect_reg(L2PMnEVCNTR(n));
	overflow = get_l2_indirect_reg(L2PMOVSR);

	if (overflow & BIT(n))
		beats = 0xFFFFFFFF - start_val + count;
	else
		beats = count - start_val;

	beats *= USEC_PER_SEC;
	beats *= bytes_per_beat;
	do_div(beats, us);
	beats = DIV_ROUND_UP_ULL(beats, MBYTE);

	pr_debug("EV%d ov: %x, cnt: %x\n", n, overflow, count);

	return beats;
}

static void do_bw_sample(struct work_struct *work);
static DECLARE_DEFERRED_WORK(bw_sample, do_bw_sample);
static struct workqueue_struct *bw_sample_wq;

static DEFINE_MUTEX(bw_lock);
static ktime_t prev_ts;
static u32 prev_r_start_val;
static u32 prev_w_start_val;

static struct msm_bus_paths bw_levels[] = {
	BW(0), BW(200),
};
static struct msm_bus_scale_pdata bw_data = {
	.usecase = bw_levels,
	.num_usecases = ARRAY_SIZE(bw_levels),
	.name = "cpubw-krait",
	.active_only = 1,
};
static u32 bus_client;
static void compute_bw(int mbps);
static irqreturn_t mon_intr_handler(int irq, void *dev_id);

#define START_LIMIT	100 /* MBps */
static int start_monitoring(void)
{
	int mb_limit;
	int ret;

	bw_sample_wq = alloc_workqueue("cpubw-krait", WQ_HIGHPRI, 0);
	if (!bw_sample_wq) {
		pr_err("Unable to alloc workqueue\n");
		return -ENOMEM;
	}

	ret = request_threaded_irq(MON_INT, NULL, mon_intr_handler,
			  IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_RISING,
			  "cpubw_krait", mon_intr_handler);
	if (ret) {
		pr_err("Unable to register interrupt handler\n");
		return ret;
	}

	bus_client = msm_bus_scale_register_client(&bw_data);
	if (!bus_client) {
		pr_err("Unable to register bus client\n");
		ret = -ENODEV;
		goto bus_reg_fail;
	}

	compute_bw(START_LIMIT);

	mon_init();
	mon_disable(0);
	mon_disable(1);

	mb_limit = mult_frac(START_LIMIT, sample_ms, MSEC_PER_SEC);
	mb_limit /= 2;

	prev_r_start_val = mon_set_limit_mbyte(0, mb_limit);
	prev_w_start_val = mon_set_limit_mbyte(1, mb_limit);

	prev_ts = ktime_get();

	set_l2_indirect_reg(L2PMINTENSET, BIT(0));
	set_l2_indirect_reg(L2PMINTENSET, BIT(1));
	mon_enable(0);
	mon_enable(1);
	global_mon_enable(true);

	queue_delayed_work(bw_sample_wq, &bw_sample,
				msecs_to_jiffies(sample_ms));

	return 0;

bus_reg_fail:
	destroy_workqueue(bw_sample_wq);
	disable_irq(MON_INT);
	free_irq(MON_INT, mon_intr_handler);
	return ret;
}
static u32 mon_set_limit_mbyte(int n, unsigned int mbytes)
{
	u32 regval, beats;

	beats = mult_frac(mbytes, SZ_1M, bytes_per_beat);
	regval = 0xFFFFFFFF - beats;
	set_l2_indirect_reg(L2PMnEVCNTR(n), regval);
	pr_debug("EV%d MB: %d, start val: %x\n", n, mbytes, regval);

	return regval;
}
static unsigned long vco_get_rate(struct clk *c)
{
	u32 sdm0, doubler, sdm_byp_div;
	u64 vco_rate;
	u32 sdm_dc_off, sdm_freq_seed, sdm2, sdm3;
	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
	u64 ref_clk = vco->ref_clk_rate;
	int rc;
	struct mdss_pll_resources *dsi_pll_res = vco->priv;

	rc = mdss_pll_resource_enable(dsi_pll_res, true);
	if (rc) {
		pr_err("Failed to enable mdss dsi pll resources\n");
		return rc;
	}

	/* Check to see if the ref clk doubler is enabled */
	doubler = MDSS_PLL_REG_R(dsi_pll_res->pll_base,
				 DSI_PHY_PLL_UNIPHY_PLL_REFCLK_CFG) & BIT(0);
	ref_clk += (doubler * vco->ref_clk_rate);

	/* see if it is integer mode or sdm mode */
	sdm0 = MDSS_PLL_REG_R(dsi_pll_res->pll_base,
					DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG0);
	if (sdm0 & BIT(6)) {
		/* integer mode */
		sdm_byp_div = (MDSS_PLL_REG_R(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG0) & 0x3f) + 1;
		vco_rate = ref_clk * sdm_byp_div;
	} else {
		/* sdm mode */
		sdm_dc_off = MDSS_PLL_REG_R(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG1) & 0xFF;
		pr_debug("sdm_dc_off = %d\n", sdm_dc_off);
		sdm2 = MDSS_PLL_REG_R(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG2) & 0xFF;
		sdm3 = MDSS_PLL_REG_R(dsi_pll_res->pll_base,
			DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG3) & 0xFF;
		sdm_freq_seed = (sdm3 << 8) | sdm2;
		pr_debug("sdm_freq_seed = %d\n", sdm_freq_seed);

		vco_rate = (ref_clk * (sdm_dc_off + 1)) +
			mult_frac(ref_clk, sdm_freq_seed, BIT(16));
		pr_debug("vco rate = %lld", vco_rate);
	}

	pr_debug("returning vco rate = %lu\n", (unsigned long)vco_rate);

	mdss_pll_resource_enable(dsi_pll_res, false);

	return (unsigned long)vco_rate;
}
static int _find_safe_div(struct clk *c, unsigned long rate)
{
	struct div_clk *d = to_div_clk(c);
	struct div_data *data = &d->data;
	unsigned long fast = max(rate, c->rate);
	unsigned int numer = data->is_half_divider ? 2 : 1;
	int i, safe_div = 0;

	if (!d->safe_freq)
		return 0;

	
	for (i = data->max_div; i >= data->min_div; i--)
		if (mult_frac(d->safe_freq, numer, i) <= fast)
			safe_div = i;

	return safe_div ?: -EINVAL;
}
static int mdss_dsi_phy_initialize_defaults(struct dsi_phy_t_clk_param *t_clk,
		struct dsi_phy_timing *t_param, u32 phy_rev)
{

	if (phy_rev <= DSI_PHY_REV_UNKNOWN || phy_rev >= DSI_PHY_REV_MAX) {
		pr_err("Invalid PHY %d revision\n", phy_rev);
		return -EINVAL;
	}

	t_param->clk_prepare.mipi_min = CLK_PREPARE_SPEC_MIN;
	t_param->clk_prepare.mipi_max = CLK_PREPARE_SPEC_MAX;
	t_param->clk_trail.mipi_min = CLK_TRAIL_SPEC_MIN;
	t_param->hs_exit.mipi_min = HS_EXIT_SPEC_MIN;
	t_param->hs_exit.rec_max = HS_EXIT_RECO_MAX;

	if (phy_rev == DSI_PHY_REV_20) {
		t_param->clk_prepare.rec_min =
			DIV_ROUND_UP((t_param->clk_prepare.mipi_min
						* t_clk->bitclk_mbps),
					(8 * t_clk->tlpx_numer_ns));
		t_param->clk_prepare.rec_max =
			rounddown(mult_frac(t_param->clk_prepare.mipi_max
						* t_clk->bitclk_mbps, 1,
						(8 * t_clk->tlpx_numer_ns)), 1);
		t_param->hs_rqst.mipi_min = HS_RQST_SPEC_MIN;
		t_param->hs_rqst_clk.mipi_min = HS_RQST_SPEC_MIN;
	} else if (phy_rev == DSI_PHY_REV_10) {
		t_param->clk_prepare.rec_min =
			(DIV_ROUND_UP(t_param->clk_prepare.mipi_min *
				      t_clk->bitclk_mbps,
				      t_clk->tlpx_numer_ns)) - 2;
		t_param->clk_prepare.rec_max =
			(DIV_ROUND_UP(t_param->clk_prepare.mipi_max *
				      t_clk->bitclk_mbps,
				      t_clk->tlpx_numer_ns)) - 2;
	}

	pr_debug("clk_prepare: min=%d, max=%d\n", t_param->clk_prepare.rec_min,
			t_param->clk_prepare.rec_max);

	return 0;
}
static unsigned long vco_get_rate(struct clk *c)
{
	u32 sdm0, doubler, sdm_byp_div;
	u64 vco_rate;
	u32 sdm_dc_off, sdm_freq_seed, sdm2, sdm3;
	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
	u64 ref_clk = vco->ref_clk_rate;

	/* Check to see if the ref clk doubler is enabled */
	doubler = DSS_REG_R(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_REFCLK_CFG)
		& BIT(0);
	ref_clk += (doubler * vco->ref_clk_rate);

	/* see if it is integer mode or sdm mode */
	sdm0 = DSS_REG_R(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_SDM_CFG0);
	if (sdm0 & BIT(6)) {
		/* integer mode */
		sdm_byp_div = (DSS_REG_R(mdss_dsi_base,
			DSI_0_PHY_PLL_UNIPHY_PLL_SDM_CFG0) & 0x3f) + 1;
		vco_rate = ref_clk * sdm_byp_div;
	} else {
		/* sdm mode */
		sdm_dc_off = DSS_REG_R(mdss_dsi_base,
			DSI_0_PHY_PLL_UNIPHY_PLL_SDM_CFG1) & 0xFF;
		pr_debug("%s: sdm_dc_off = %d\n", __func__, sdm_dc_off);
		sdm2 = DSS_REG_R(mdss_dsi_base,
			DSI_0_PHY_PLL_UNIPHY_PLL_SDM_CFG2) & 0xFF;
		sdm3 = DSS_REG_R(mdss_dsi_base,
			DSI_0_PHY_PLL_UNIPHY_PLL_SDM_CFG3) & 0xFF;
		sdm_freq_seed = (sdm3 << 8) | sdm2;
		pr_debug("%s: sdm_freq_seed = %d\n", __func__, sdm_freq_seed);

		vco_rate = (ref_clk * (sdm_dc_off + 1)) +
			mult_frac(ref_clk, sdm_freq_seed, BIT(16));
		pr_debug("%s: vco rate = %lld", __func__, vco_rate);
	}

	pr_debug("%s: returning vco rate = %lu\n", __func__,
		(unsigned long)vco_rate);
	return (unsigned long)vco_rate;
}
示例#13
0
static int vt8500_set_baud_rate(struct uart_port *port, unsigned int baud)
{
	struct vt8500_port *vt8500_port =
			container_of(port, struct vt8500_port, uart);
	unsigned long div;
	unsigned int loops = 1000;

	div = ((vt8500_port->clk_predivisor - 1) & 0xf) << 16;
	div |= (uart_get_divisor(port, baud) - 1) & 0x3ff;

	/* Effective baud rate */
	baud = port->uartclk / 16 / ((div & 0x3ff) + 1);

	while ((vt8500_read(port, VT8500_URUSR) & (1 << 5)) && --loops)
		cpu_relax();

	vt8500_write(port, div, VT8500_URDIV);

	/* Break signal timing depends on baud rate, update accordingly */
	vt8500_write(port, mult_frac(baud, 4096, 1000000), VT8500_URBKR);

	return baud;
}
static enum handoff mux_div_clk_handoff(struct clk *c)
{
	struct mux_div_clk *md = to_mux_div_clk(c);
	unsigned long parent_rate;
	unsigned int numer;

	parent_rate = clk_get_rate(c->parent);
	if (!parent_rate)
		return HANDOFF_DISABLED_CLK;
	numer = md->data.is_half_divider ? 2 : 1;

	if (md->data.div) {
		c->rate = mult_frac(parent_rate, numer, md->data.div);
	} else {
		c->rate = 0;
		return HANDOFF_DISABLED_CLK;
	}

	if (!md->ops->is_enabled)
		return HANDOFF_DISABLED_CLK;
	if (md->ops->is_enabled(md))
		return HANDOFF_ENABLED_CLK;
	return HANDOFF_DISABLED_CLK;
}
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_phy_calc_timing_param(struct mdss_panel_info *pinfo, u32 phy_rev,
		u32 frate_hz)
{
	struct dsi_phy_t_clk_param t_clk;
	struct dsi_phy_timing t_param;
	int hsync_period;
	int vsync_period;
	unsigned long inter_num;
	uint32_t lane_config = 0;
	unsigned long x, y;
	int rc = 0;

	if (!pinfo) {
		pr_err("invalid panel info\n");
		return -EINVAL;
	}

	hsync_period = mdss_panel_get_htotal(pinfo, true);
	vsync_period = mdss_panel_get_vtotal(pinfo);

	inter_num = pinfo->bpp * frate_hz;

	if (pinfo->mipi.data_lane0)
		lane_config++;
	if (pinfo->mipi.data_lane1)
		lane_config++;
	if (pinfo->mipi.data_lane2)
		lane_config++;
	if (pinfo->mipi.data_lane3)
		lane_config++;

	x = mult_frac(vsync_period * hsync_period, inter_num, lane_config);
	y = rounddown(x, 1);
	t_clk.bitclk_mbps = rounddown(mult_frac(y, 1, 1000000), 1);
	t_clk.escclk_numer = ESC_CLK_MHZ;
	t_clk.escclk_denom = ESCCLK_MMSS_CC_PREDIV;
	t_clk.tlpx_numer_ns = TLPX_NUMER;
	t_clk.treot_ns = TR_EOT;
	pr_debug("hperiod=%d, vperiod=%d, inter_num=%lu, lane_cfg=%d\n",
			hsync_period, vsync_period, inter_num, lane_config);
	pr_debug("x=%lu, y=%lu, bitrate=%d\n", x, y, t_clk.bitclk_mbps);

	switch (phy_rev) {
	case DSI_PHY_REV_10:
		rc = mdss_dsi_phy_initialize_defaults(&t_clk, &t_param,
				phy_rev);
		if (rc) {
			pr_err("phy%d initialization failed\n", phy_rev);
			goto timing_calc_end;
		}
			mdss_dsi_phy_calc_param_phy_rev_1(&t_clk, &t_param);
		mdss_dsi_phy_update_timing_param(pinfo, &t_param);
		break;
	case DSI_PHY_REV_20:
		rc = mdss_dsi_phy_initialize_defaults(&t_clk, &t_param,
				phy_rev);
		if (rc) {
			pr_err("phy%d initialization failed\n", phy_rev);
			goto timing_calc_end;
		}

		rc = mdss_dsi_phy_calc_param_phy_rev_2(&t_clk, &t_param);
		if (rc) {
			pr_err("Phy timing calculations failed\n");
			goto timing_calc_end;
		}
		mdss_dsi_phy_update_timing_param_rev_2(pinfo, &t_param);
		break;
	default:
		pr_err("phy rev %d not supported\n", phy_rev);
		return -EINVAL;
	}

timing_calc_end:
	return rc;
}
示例#17
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;
}
示例#18
0
static int mdp4_plane_mode_set(struct drm_plane *plane,
		struct drm_crtc *crtc, struct drm_framebuffer *fb,
		int crtc_x, int crtc_y,
		unsigned int crtc_w, unsigned int crtc_h,
		uint32_t src_x, uint32_t src_y,
		uint32_t src_w, uint32_t src_h)
{
	struct drm_device *dev = plane->dev;
	struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);
	struct mdp4_kms *mdp4_kms = get_kms(plane);
	enum mdp4_pipe pipe = mdp4_plane->pipe;
	const struct mdp_format *format;
	uint32_t op_mode = 0;
	uint32_t phasex_step = MDP4_VG_PHASE_STEP_DEFAULT;
	uint32_t phasey_step = MDP4_VG_PHASE_STEP_DEFAULT;
	enum mdp4_frame_format frame_type;

	if (!(crtc && fb)) {
		DBG("%s: disabled!", mdp4_plane->name);
		return 0;
	}

	frame_type = mdp4_get_frame_format(fb);

	/* src values are in Q16 fixed point, convert to integer: */
	src_x = src_x >> 16;
	src_y = src_y >> 16;
	src_w = src_w >> 16;
	src_h = src_h >> 16;

	DBG("%s: FB[%u] %u,%u,%u,%u -> CRTC[%u] %d,%d,%u,%u", mdp4_plane->name,
			fb->base.id, src_x, src_y, src_w, src_h,
			crtc->base.id, crtc_x, crtc_y, crtc_w, crtc_h);

	format = to_mdp_format(msm_framebuffer_format(fb));

	if (src_w > (crtc_w * DOWN_SCALE_MAX)) {
		dev_err(dev->dev, "Width down scaling exceeds limits!\n");
		return -ERANGE;
	}

	if (src_h > (crtc_h * DOWN_SCALE_MAX)) {
		dev_err(dev->dev, "Height down scaling exceeds limits!\n");
		return -ERANGE;
	}

	if (crtc_w > (src_w * UP_SCALE_MAX)) {
		dev_err(dev->dev, "Width up scaling exceeds limits!\n");
		return -ERANGE;
	}

	if (crtc_h > (src_h * UP_SCALE_MAX)) {
		dev_err(dev->dev, "Height up scaling exceeds limits!\n");
		return -ERANGE;
	}

	if (src_w != crtc_w) {
		uint32_t sel_unit = SCALE_FIR;
		op_mode |= MDP4_PIPE_OP_MODE_SCALEX_EN;

		if (MDP_FORMAT_IS_YUV(format)) {
			if (crtc_w > src_w)
				sel_unit = SCALE_PIXEL_RPT;
			else if (crtc_w <= (src_w / 4))
				sel_unit = SCALE_MN_PHASE;

			op_mode |= MDP4_PIPE_OP_MODE_SCALEX_UNIT_SEL(sel_unit);
			phasex_step = mult_frac(MDP4_VG_PHASE_STEP_DEFAULT,
					src_w, crtc_w);
		}
	}

	if (src_h != crtc_h) {
		uint32_t sel_unit = SCALE_FIR;
		op_mode |= MDP4_PIPE_OP_MODE_SCALEY_EN;

		if (MDP_FORMAT_IS_YUV(format)) {

			if (crtc_h > src_h)
				sel_unit = SCALE_PIXEL_RPT;
			else if (crtc_h <= (src_h / 4))
				sel_unit = SCALE_MN_PHASE;

			op_mode |= MDP4_PIPE_OP_MODE_SCALEY_UNIT_SEL(sel_unit);
			phasey_step = mult_frac(MDP4_VG_PHASE_STEP_DEFAULT,
					src_h, crtc_h);
		}
	}

	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_SIZE(pipe),
			MDP4_PIPE_SRC_SIZE_WIDTH(src_w) |
			MDP4_PIPE_SRC_SIZE_HEIGHT(src_h));

	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_XY(pipe),
			MDP4_PIPE_SRC_XY_X(src_x) |
			MDP4_PIPE_SRC_XY_Y(src_y));

	mdp4_write(mdp4_kms, REG_MDP4_PIPE_DST_SIZE(pipe),
			MDP4_PIPE_DST_SIZE_WIDTH(crtc_w) |
			MDP4_PIPE_DST_SIZE_HEIGHT(crtc_h));

	mdp4_write(mdp4_kms, REG_MDP4_PIPE_DST_XY(pipe),
			MDP4_PIPE_DST_XY_X(crtc_x) |
			MDP4_PIPE_DST_XY_Y(crtc_y));

	mdp4_plane_set_scanout(plane, fb);

	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_FORMAT(pipe),
			MDP4_PIPE_SRC_FORMAT_A_BPC(format->bpc_a) |
			MDP4_PIPE_SRC_FORMAT_R_BPC(format->bpc_r) |
			MDP4_PIPE_SRC_FORMAT_G_BPC(format->bpc_g) |
			MDP4_PIPE_SRC_FORMAT_B_BPC(format->bpc_b) |
			COND(format->alpha_enable, MDP4_PIPE_SRC_FORMAT_ALPHA_ENABLE) |
			MDP4_PIPE_SRC_FORMAT_CPP(format->cpp - 1) |
			MDP4_PIPE_SRC_FORMAT_UNPACK_COUNT(format->unpack_count - 1) |
			MDP4_PIPE_SRC_FORMAT_FETCH_PLANES(format->fetch_type) |
			MDP4_PIPE_SRC_FORMAT_CHROMA_SAMP(format->chroma_sample) |
			MDP4_PIPE_SRC_FORMAT_FRAME_FORMAT(frame_type) |
			COND(format->unpack_tight, MDP4_PIPE_SRC_FORMAT_UNPACK_TIGHT));

	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_UNPACK(pipe),
			MDP4_PIPE_SRC_UNPACK_ELEM0(format->unpack[0]) |
			MDP4_PIPE_SRC_UNPACK_ELEM1(format->unpack[1]) |
			MDP4_PIPE_SRC_UNPACK_ELEM2(format->unpack[2]) |
			MDP4_PIPE_SRC_UNPACK_ELEM3(format->unpack[3]));

	if (MDP_FORMAT_IS_YUV(format)) {
		struct csc_cfg *csc = mdp_get_default_csc_cfg(CSC_YUV2RGB);

		op_mode |= MDP4_PIPE_OP_MODE_SRC_YCBCR;
		op_mode |= MDP4_PIPE_OP_MODE_CSC_EN;
		mdp4_write_csc_config(mdp4_kms, pipe, csc);
	}

	mdp4_write(mdp4_kms, REG_MDP4_PIPE_OP_MODE(pipe), op_mode);
	mdp4_write(mdp4_kms, REG_MDP4_PIPE_PHASEX_STEP(pipe), phasex_step);
	mdp4_write(mdp4_kms, REG_MDP4_PIPE_PHASEY_STEP(pipe), phasey_step);

	if (frame_type != FRAME_LINEAR)
		mdp4_write(mdp4_kms, REG_MDP4_PIPE_SSTILE_FRAME_SIZE(pipe),
				MDP4_PIPE_SSTILE_FRAME_SIZE_WIDTH(src_w) |
				MDP4_PIPE_SSTILE_FRAME_SIZE_HEIGHT(src_h));

	return 0;
}
示例#19
0
static long sam9x60_pll_get_best_div_mul(struct sam9x60_pll *pll,
					 unsigned long rate,
					 unsigned long parent_rate,
					 bool update)
{
	const struct clk_pll_characteristics *characteristics =
							pll->characteristics;
	unsigned long bestremainder = ULONG_MAX;
	unsigned long maxdiv, mindiv, tmpdiv;
	long bestrate = -ERANGE;
	unsigned long bestdiv = 0;
	unsigned long bestmul = 0;
	unsigned long bestfrac = 0;

	if (rate < characteristics->output[0].min ||
	    rate > characteristics->output[0].max)
		return -ERANGE;

	if (!pll->characteristics->upll) {
		mindiv = parent_rate / rate;
		if (mindiv < 2)
			mindiv = 2;

		maxdiv = DIV_ROUND_UP(parent_rate * PLL_MUL_MAX, rate);
		if (maxdiv > PLL_DIV_MAX)
			maxdiv = PLL_DIV_MAX;
	} else {
		mindiv = maxdiv = UPLL_DIV;
	}

	for (tmpdiv = mindiv; tmpdiv <= maxdiv; tmpdiv++) {
		unsigned long remainder;
		unsigned long tmprate;
		unsigned long tmpmul;
		unsigned long tmpfrac = 0;

		/*
		 * Calculate the multiplier associated with the current
		 * divider that provide the closest rate to the requested one.
		 */
		tmpmul = mult_frac(rate, tmpdiv, parent_rate);
		tmprate = mult_frac(parent_rate, tmpmul, tmpdiv);
		remainder = rate - tmprate;

		if (remainder) {
			tmpfrac = DIV_ROUND_CLOSEST_ULL((u64)remainder * tmpdiv * (1 << 22),
							parent_rate);

			tmprate += DIV_ROUND_CLOSEST_ULL((u64)tmpfrac * parent_rate,
							 tmpdiv * (1 << 22));

			if (tmprate > rate)
				remainder = tmprate - rate;
			else
				remainder = rate - tmprate;
		}

		/*
		 * Compare the remainder with the best remainder found until
		 * now and elect a new best multiplier/divider pair if the
		 * current remainder is smaller than the best one.
		 */
		if (remainder < bestremainder) {
			bestremainder = remainder;
			bestdiv = tmpdiv;
			bestmul = tmpmul;
			bestrate = tmprate;
			bestfrac = tmpfrac;
		}

		/* We've found a perfect match!  */
		if (!remainder)
			break;
	}

	/* Check if bestrate is a valid output rate  */
	if (bestrate < characteristics->output[0].min &&
	    bestrate > characteristics->output[0].max)
		return -ERANGE;

	if (update) {
		pll->div = bestdiv - 1;
		pll->mul = bestmul - 1;
		pll->frac = bestfrac;
	}

	return bestrate;
}
示例#20
0
static void __mdss_dsi_ctrl_setup(struct mdss_panel_data *pdata)
{
	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
	struct mdss_panel_info *pinfo;
	struct mipi_panel_info *mipi;
	u32 clk_rate;
	u32 hbp, hfp, vbp, vfp, hspw, vspw, width, height;
	u32 ystride, bpp, data, dst_bpp;
	u32 dummy_xres, dummy_yres;
	u32 hsync_period, vsync_period;

	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
				panel_data);

	pinfo = &pdata->panel_info;

	clk_rate = pdata->panel_info.clk_rate;
	clk_rate = min(clk_rate, pdata->panel_info.clk_max);

	dst_bpp = pdata->panel_info.fbc.enabled ?
		(pdata->panel_info.fbc.target_bpp) : (pinfo->bpp);

	hbp = mult_frac(pdata->panel_info.lcdc.h_back_porch, dst_bpp,
			pdata->panel_info.bpp);
	hfp = mult_frac(pdata->panel_info.lcdc.h_front_porch, dst_bpp,
			pdata->panel_info.bpp);
	vbp = mult_frac(pdata->panel_info.lcdc.v_back_porch, dst_bpp,
			pdata->panel_info.bpp);
	vfp = mult_frac(pdata->panel_info.lcdc.v_front_porch, dst_bpp,
			pdata->panel_info.bpp);
	hspw = mult_frac(pdata->panel_info.lcdc.h_pulse_width, dst_bpp,
			pdata->panel_info.bpp);
	vspw = pdata->panel_info.lcdc.v_pulse_width;
	width = mult_frac(pdata->panel_info.xres, dst_bpp,
			pdata->panel_info.bpp);
	height = pdata->panel_info.yres;

	if (pdata->panel_info.type == MIPI_VIDEO_PANEL) {
		dummy_xres = pdata->panel_info.lcdc.xres_pad;
		dummy_yres = pdata->panel_info.lcdc.yres_pad;
	}

	vsync_period = vspw + vbp + height + dummy_yres + vfp;
	hsync_period = hspw + hbp + width + dummy_xres + hfp;

	mipi = &pdata->panel_info.mipi;
	if (pdata->panel_info.type == MIPI_VIDEO_PANEL) {
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x24,
			((hspw + hbp + width + dummy_xres) << 16 |
			(hspw + hbp)));
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x28,
			((vspw + vbp + height + dummy_yres) << 16 |
			(vspw + vbp)));
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x2C,
				((vsync_period - 1) << 16)
				| (hsync_period - 1));

		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x30, (hspw << 16));
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x34, 0);
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x38, (vspw << 16));

	} else {		/* command mode */
		if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB888)
			bpp = 3;
		else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB666)
			bpp = 3;
		else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB565)
			bpp = 2;
		else
			bpp = 3;	/* Default format set to RGB888 */

		ystride = width * bpp + 1;

		/* DSI_COMMAND_MODE_MDP_STREAM_CTRL */
		data = (ystride << 16) | (mipi->vc << 8) | DTYPE_DCS_LWRITE;
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x60, data);
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x58, data);

		/* DSI_COMMAND_MODE_MDP_STREAM_TOTAL */
		data = height << 16 | width;
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x64, data);
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x5C, data);
	}
}
static int mdss_dsi_phy_calc_param_phy_rev_2(struct dsi_phy_t_clk_param *t_clk,
		struct dsi_phy_timing *t_param)
{
	/* recommended fraction for PHY REV 2.0 */
	u32 const min_prepare_frac = 50;
	u32 const hs_exit_min_frac = 10;
	u32 const phy_timing_frac = 30;
	u32 const hs_zero_min_frac = 10;
	u32 const clk_zero_min_frac = 2;
	int tmp;
	int t_hs_prep_actual;
	int teot_clk_lane, teot_data_lane;
	u64 dividend;
	u64 temp, rc = 0;
	u64 multiplier = BIT(20);
	u64 temp_multiple;
	s64 mipi_min, mipi_max, mipi_max_tr, rec_min, rec_prog;
	s64 clk_prep_actual;
	s64 actual_intermediate;
	s32 actual_frac;
	s64 rec_temp1, rec_temp2, rec_temp3;

	/* clk_prepare calculations */
	dividend = ((t_param->clk_prepare.rec_max
			- t_param->clk_prepare.rec_min)
			* min_prepare_frac * multiplier);
	temp = roundup(div_s64(dividend, 100), multiplier);
	temp += (t_param->clk_prepare.rec_min * multiplier);
	t_param->clk_prepare.rec = div_s64(temp, multiplier);

	rc = mdss_dsi_phy_common_validate_and_set(&t_param->clk_prepare,
			"clk prepare");
	if (rc)
		goto error;

	/* clk_ prepare theoretical value*/
	temp_multiple = (8 * t_param->clk_prepare.program_value
			* t_clk->tlpx_numer_ns * multiplier);
	actual_intermediate = div_s64(temp_multiple, t_clk->bitclk_mbps);
	div_s64_rem(temp_multiple, t_clk->bitclk_mbps, &actual_frac);
	clk_prep_actual =
		div_s64((actual_intermediate + actual_frac), multiplier);

	pr_debug("CLK PREPARE: mipi_min=%d, max=%d, rec_min=%d, rec_max=%d",
			t_param->clk_prepare.mipi_min,
			t_param->clk_prepare.mipi_max,
			t_param->clk_prepare.rec_min,
			t_param->clk_prepare.rec_max);
	pr_debug("prog value = %d, actual=%lld\n",
			t_param->clk_prepare.rec, clk_prep_actual);

	/* clk zero calculations */
	/* Mipi spec min*/
	mipi_min = (300 * multiplier) - (actual_intermediate + actual_frac);
	t_param->clk_zero.mipi_min = div_s64(mipi_min, multiplier);

	/* recommended min */
	rec_temp1 = div_s64(mipi_min * t_clk->bitclk_mbps,
			t_clk->tlpx_numer_ns);
	rec_temp2 = rec_temp1 - (11 * multiplier);
	rec_temp3 = roundup(div_s64(rec_temp2, 8),  multiplier);
	rec_min = div_s64(rec_temp3, multiplier) - 3;
	t_param->clk_zero.rec_min = rec_min;

	/* recommended max */
	t_param->clk_zero.rec_max =
			((t_param->clk_zero.rec_min > 255) ? 511 : 255);

	/* Programmed value */
	t_param->clk_zero.rec = DIV_ROUND_UP(
			(t_param->clk_zero.rec_max - t_param->clk_zero.rec_min)
				* clk_zero_min_frac
				+ (t_param->clk_zero.rec_min * 100), 100);

	rc = mdss_dsi_phy_common_validate_and_set(&t_param->clk_zero,
			"clk zero");
	if (rc)
		goto error;

	pr_debug("CLK ZERO: mipi_min=%d, max=%d, rec_min=%d, rec_max=%d, prog value = %d\n",
			t_param->clk_zero.mipi_min, t_param->clk_zero.mipi_max,
			t_param->clk_zero.rec_min, t_param->clk_zero.rec_max,
			t_param->clk_zero.rec);

	/* clk trail calculations */
	temp_multiple = div_s64(12 * multiplier * t_clk->tlpx_numer_ns,
						t_clk->bitclk_mbps);
	div_s64_rem(temp_multiple, multiplier, &actual_frac);

	mipi_max_tr = 105 * multiplier + (temp_multiple + actual_frac);
	teot_clk_lane = div_s64(mipi_max_tr, multiplier);

	mipi_max = mipi_max_tr - (t_clk->treot_ns * multiplier);

	t_param->clk_trail.mipi_max =  div_s64(mipi_max, multiplier);

	/* recommended min*/
	temp_multiple = div_s64(t_param->clk_trail.mipi_min * multiplier *
			t_clk->bitclk_mbps, t_clk->tlpx_numer_ns);
	div_s64_rem(temp_multiple, multiplier, &actual_frac);
	rec_temp1 = temp_multiple + actual_frac + 3 * multiplier;
	rec_temp2 = div_s64(rec_temp1, 8);
	rec_temp3 = roundup(rec_temp2, multiplier);

	t_param->clk_trail.rec_min = div_s64(rec_temp3, multiplier);

	/* recommended max */
	rec_temp1 = div_s64(mipi_max * t_clk->bitclk_mbps,
						t_clk->tlpx_numer_ns);
	rec_temp2 = rec_temp1 + 3 * multiplier;
	rec_temp3 = rec_temp2 / 8;
	t_param->clk_trail.rec_max = div_s64(rec_temp3, multiplier);

	/* Programmed value */
	t_param->clk_trail.rec = DIV_ROUND_UP(
		(t_param->clk_trail.rec_max - t_param->clk_trail.rec_min)
			* phy_timing_frac
			+ (t_param->clk_trail.rec_min * 100), 100);

	rc = mdss_dsi_phy_common_validate_and_set(&t_param->clk_trail,
			"clk trail");
	if (rc)
		goto error;

	pr_debug("CLK TRAIL: mipi_min=%d, max=%d, rec_min=%d, rec_max=%d, prog value = %d\n",
			t_param->clk_trail.mipi_min,
			t_param->clk_trail.mipi_max,
			t_param->clk_trail.rec_min,
			t_param->clk_trail.rec_max,
			t_param->clk_trail.rec);

	/* hs prepare calculations */
	/* mipi min */
	temp_multiple = div_s64(4 * t_clk->tlpx_numer_ns * multiplier,
			t_clk->bitclk_mbps);
	div_s64_rem(temp_multiple, multiplier, &actual_frac);
	mipi_min = 40 * multiplier + (temp_multiple + actual_frac);
	t_param->hs_prepare.mipi_min = div_s64(mipi_min, multiplier);

	/* mipi max */
	temp_multiple = div_s64(6 * t_clk->tlpx_numer_ns * multiplier,
			t_clk->bitclk_mbps);
	div_s64_rem(temp_multiple, multiplier, &actual_frac);
	mipi_max = 85 * multiplier + temp_multiple;
	t_param->hs_prepare.mipi_max = div_s64(mipi_max, multiplier);

	/* recommended min */
	temp_multiple = div_s64(mipi_min * t_clk->bitclk_mbps,
			t_clk->tlpx_numer_ns);
	div_s64_rem(temp_multiple, multiplier, &actual_frac);
	rec_temp1 = roundup((temp_multiple + actual_frac)/8, multiplier);
	t_param->hs_prepare.rec_min = div_s64(rec_temp1, multiplier);

	/* recommended max*/
	temp_multiple = div_s64(mipi_max * t_clk->bitclk_mbps,
			t_clk->tlpx_numer_ns);
	div_s64_rem(temp_multiple, multiplier, &actual_frac);
	rec_temp2 = rounddown((temp_multiple + actual_frac)/8, multiplier);
	t_param->hs_prepare.rec_max = div_s64(rec_temp2, multiplier);

	/* prog value*/
	dividend = (rec_temp2 - rec_temp1) * min_prepare_frac;
	temp = roundup(div_u64(dividend, 100), multiplier);
	rec_prog = temp + rec_temp1;
	t_param->hs_prepare.rec = div_s64(rec_prog, multiplier);

	rc = mdss_dsi_phy_common_validate_and_set(&t_param->hs_prepare,
			"HS prepare");
	if (rc)
		goto error;

	/* theoretical Value */
	temp_multiple = div_s64(8 * rec_prog * t_clk->tlpx_numer_ns,
			t_clk->bitclk_mbps);
	div_s64_rem(temp_multiple, multiplier, &actual_frac);
	t_hs_prep_actual = div_s64(temp_multiple, multiplier);
	pr_debug("HS PREPARE: mipi_min=%d, max=%d, rec_min=%d, rec_max=%d, prog value = %d, actual=%d\n",
			t_param->hs_prepare.mipi_min,
			t_param->hs_prepare.mipi_max,
			t_param->hs_prepare.rec_min,
			t_param->hs_prepare.rec_max,
			t_param->hs_prepare.rec, t_hs_prep_actual);

	/* hs zero calculations */
	/* mipi min*/
	mipi_min = div_s64(10 * t_clk->tlpx_numer_ns * multiplier,
			t_clk->bitclk_mbps);
	rec_temp1 = (145 * multiplier) + mipi_min - temp_multiple;
	t_param->hs_zero.mipi_min = div_s64(rec_temp1, multiplier);

	/* recommended min */
	rec_temp1 = div_s64(rec_temp1 * t_clk->bitclk_mbps,
			t_clk->tlpx_numer_ns);
	rec_temp2 = rec_temp1 - (11 * multiplier);
	rec_temp3 = roundup((rec_temp2/8), multiplier);
	rec_min = rec_temp3 - (3 * multiplier);
	t_param->hs_zero.rec_min = div_s64(rec_min, multiplier);

	t_param->hs_zero.rec_max =
			((t_param->hs_zero.rec_min > 255) ? 511 : 255);

	/* prog value */
	t_param->hs_zero.rec = DIV_ROUND_UP(
		(t_param->hs_zero.rec_max - t_param->hs_zero.rec_min)
		* hs_zero_min_frac + (t_param->hs_zero.rec_min * 100),
		100);

	rc = mdss_dsi_phy_common_validate_and_set(&t_param->hs_zero, "HS zero");
	if (rc)
		goto error;

	pr_debug("HS ZERO: mipi_min=%d, max=%d, rec_min=%d, rec_max=%d, prog value = %d\n",
			t_param->hs_zero.mipi_min, t_param->hs_zero.mipi_max,
			t_param->hs_zero.rec_min, t_param->hs_zero.rec_max,
			t_param->hs_zero.rec);

	/* hs_trail calculations */
	teot_data_lane  = teot_clk_lane;
	t_param->hs_trail.mipi_min =  60 +
		mult_frac(t_clk->tlpx_numer_ns, 4, t_clk->bitclk_mbps);
	t_param->hs_trail.mipi_max =  teot_clk_lane - t_clk->treot_ns;
	t_param->hs_trail.rec_min = DIV_ROUND_UP(
		((t_param->hs_trail.mipi_min * t_clk->bitclk_mbps)
		 + 3 * t_clk->tlpx_numer_ns), (8 * t_clk->tlpx_numer_ns));
	tmp = ((t_param->hs_trail.mipi_max * t_clk->bitclk_mbps)
		 + (3 * t_clk->tlpx_numer_ns));
	t_param->hs_trail.rec_max = tmp/(8 * t_clk->tlpx_numer_ns);
	tmp = DIV_ROUND_UP((t_param->hs_trail.rec_max
			- t_param->hs_trail.rec_min) * phy_timing_frac,
			100);
	t_param->hs_trail.rec = tmp + t_param->hs_trail.rec_min;


	rc = mdss_dsi_phy_common_validate_and_set(&t_param->hs_trail,
			"HS trail");
	if (rc)
		goto error;

	pr_debug("HS TRAIL: mipi_min=%d, max=%d, rec_min=%d, rec_max=%d, prog value = %d\n",
			t_param->hs_trail.mipi_min, t_param->hs_trail.mipi_max,
			t_param->hs_trail.rec_min, t_param->hs_trail.rec_max,
			t_param->hs_trail.rec);

	/* hs rqst calculations for Data lane */
	t_param->hs_rqst.rec = DIV_ROUND_UP(
		(t_param->hs_rqst.mipi_min * t_clk->bitclk_mbps)
		- (8 * t_clk->tlpx_numer_ns), (8 * t_clk->tlpx_numer_ns));

	rc = mdss_dsi_phy_common_validate_and_set(&t_param->hs_rqst, "HS rqst");
	if (rc)
		goto error;

	pr_debug("HS RQST-DATA: mipi_min=%d, max=%d, rec_min=%d, rec_max=%d, prog value = %d\n",
			t_param->hs_rqst.mipi_min, t_param->hs_rqst.mipi_max,
			t_param->hs_rqst.rec_min, t_param->hs_rqst.rec_max,
			t_param->hs_rqst.rec);

	/* hs exit calculations */
	t_param->hs_exit.rec_min = DIV_ROUND_UP(
		(t_param->hs_exit.mipi_min * t_clk->bitclk_mbps),
		(8 * t_clk->tlpx_numer_ns)) - 1;
	t_param->hs_exit.rec = DIV_ROUND_UP(
		(t_param->hs_exit.rec_max - t_param->hs_exit.rec_min)
			* hs_exit_min_frac
			+ (t_param->hs_exit.rec_min * 100), 100);

	rc = mdss_dsi_phy_common_validate_and_set(&t_param->hs_exit, "HS exit");
	if (rc)
		goto error;

	pr_debug("HS EXIT: mipi_min=%d, max=%d, rec_min=%d, rec_max=%d, prog value = %d\n",
			t_param->hs_exit.mipi_min, t_param->hs_exit.mipi_max,
			t_param->hs_exit.rec_min, t_param->hs_exit.rec_max,
			t_param->hs_exit.rec);

	/* hs rqst calculations for Clock lane */
	t_param->hs_rqst_clk.rec = DIV_ROUND_UP(
		(t_param->hs_rqst_clk.mipi_min * t_clk->bitclk_mbps)
		- (8 * t_clk->tlpx_numer_ns), (8 * t_clk->tlpx_numer_ns));

	rc = mdss_dsi_phy_common_validate_and_set(&t_param->hs_rqst_clk,
			"HS rqst clk");
	if (rc)
		goto error;

	pr_debug("HS RQST-CLK: mipi_min=%d, max=%d, rec_min=%d, rec_max=%d, prog value = %d\n",
			t_param->hs_rqst_clk.mipi_min,
			t_param->hs_rqst_clk.mipi_max,
			t_param->hs_rqst_clk.rec_min,
			t_param->hs_rqst_clk.rec_max,
			t_param->hs_rqst_clk.rec);
	pr_debug("teot_clk=%d, data=%d\n", teot_clk_lane, teot_data_lane);
	return 0;

error:
	return -EINVAL;
}