msm: mdss: add support dsi phy v3 timing used on msmcobalt

Add PHY timing calculation support for v3 PHY used on msmcobalt.
This needed to program the DSI PHY to drive the link at a specific
link rate based on the DSI panel configuration.

CRs-Fixed: 1000724
Change-Id: I180af3544c111cb9f491ea9fb77638beece8299c
Signed-off-by: Aravind Venkateswaran <aravindh@codeaurora.org>
This commit is contained in:
Aravind Venkateswaran 2016-03-25 17:06:59 -07:00 committed by Jeevan Shriram
parent af48722765
commit 2df9ce47f6
3 changed files with 114 additions and 36 deletions

View file

@ -293,7 +293,9 @@ void mdss_dsi_read_phy_revision(struct mdss_dsi_ctrl_pdata *ctrl)
reg_val = MIPI_INP(ctrl->phy_io.base);
if (reg_val == DSI_PHY_REV_20)
if (reg_val == DSI_PHY_REV_30)
ctrl->shared_data->phy_rev = DSI_PHY_REV_30;
else if (reg_val == DSI_PHY_REV_20)
ctrl->shared_data->phy_rev = DSI_PHY_REV_20;
else if (reg_val == DSI_PHY_REV_10)
ctrl->shared_data->phy_rev = DSI_PHY_REV_10;

View file

@ -61,6 +61,7 @@ struct dsi_phy_timing {
};
struct dsi_phy_t_clk_param {
u32 phy_rev;
uint32_t bitclk_mbps;
uint32_t escclk_numer;
uint32_t escclk_denom;
@ -117,15 +118,20 @@ static int mdss_dsi_phy_initialize_defaults(struct dsi_phy_t_clk_param *t_clk,
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_clk->phy_rev = phy_rev;
if (phy_rev == DSI_PHY_REV_30) {
t_param->hs_rqst.mipi_min = HS_RQST_SPEC_MIN;
t_param->hs_rqst_clk.mipi_min = HS_RQST_SPEC_MIN;
t_clk->clk_prep_buf = 0;
t_clk->clk_zero_buf = 0;
t_clk->clk_trail_buf = 0;
t_clk->hs_prep_buf = 0;
t_clk->hs_zero_buf = 0;
t_clk->hs_trail_buf = 0;
t_clk->hs_rqst_buf = 0;
t_clk->hs_exit_buf = 0;
} else if (phy_rev == DSI_PHY_REV_20) {
t_param->hs_rqst.mipi_min = HS_RQST_SPEC_MIN;
t_param->hs_rqst_clk.mipi_min = HS_RQST_SPEC_MIN;
@ -175,6 +181,13 @@ static int calc_clk_prepare(struct dsi_phy_t_clk_param *clk_params,
goto error;
}
t->rec_min = DIV_ROUND_UP((t->mipi_min * clk_params->bitclk_mbps),
(8 * clk_params->tlpx_numer_ns));
t->rec_max = rounddown(mult_frac(t->mipi_max * clk_params->bitclk_mbps,
1,
(8 * clk_params->tlpx_numer_ns)),
1);
dividend = ((t->rec_max - t->rec_min) *
clk_params->clk_prep_buf *
multiplier);
@ -228,9 +241,15 @@ static int calc_clk_zero(struct dsi_phy_t_clk_param *clk_params,
rec_temp1 = div_s64((mipi_min * clk_params->bitclk_mbps),
clk_params->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);
if (clk_params->phy_rev == DSI_PHY_REV_30) {
rec_temp2 = (rec_temp1 - multiplier);
rec_temp3 = roundup(div_s64(rec_temp2, 8), multiplier);
rec_min = (div_s64(rec_temp3, multiplier) - 1);
} else {
rec_temp2 = (rec_temp1 - (11 * multiplier));
rec_temp3 = roundup(div_s64(rec_temp2, 8), multiplier);
rec_min = (div_s64(rec_temp3, multiplier) - 3);
}
t->rec_min = rec_min;
t->rec_max = ((t->rec_min > 255) ? 511 : 255);
@ -289,18 +308,30 @@ static int calc_clk_trail(struct dsi_phy_t_clk_param *clk_params,
clk_params->tlpx_numer_ns);
div_s64_rem(temp_multiple, multiplier, &frac);
rec_temp1 = temp_multiple + frac + (3 * multiplier);
rec_temp2 = div_s64(rec_temp1, 8);
rec_temp3 = roundup(rec_temp2, multiplier);
if (clk_params->phy_rev == DSI_PHY_REV_30) {
rec_temp1 = temp_multiple + frac;
rec_temp2 = div_s64(rec_temp1, 8);
rec_temp3 = roundup(rec_temp2, multiplier);
t->rec_min = div_s64(rec_temp3, multiplier) - 1;
} else {
rec_temp1 = temp_multiple + frac + (3 * multiplier);
rec_temp2 = div_s64(rec_temp1, 8);
rec_temp3 = roundup(rec_temp2, multiplier);
t->rec_min = div_s64(rec_temp3, multiplier);
}
t->rec_min = div_s64(rec_temp3, multiplier);
/* recommended max */
rec_temp1 = div_s64((mipi_max * clk_params->bitclk_mbps),
clk_params->tlpx_numer_ns);
rec_temp2 = rec_temp1 + (3 * multiplier);
rec_temp3 = rec_temp2 / 8;
t->rec_max = div_s64(rec_temp3, multiplier);
if (clk_params->phy_rev == DSI_PHY_REV_30) {
rec_temp3 = rec_temp1 / 8;
t->rec_max = div_s64(rec_temp3, multiplier) - 1;
} else {
rec_temp2 = rec_temp1 + (3 * multiplier);
rec_temp3 = rec_temp2 / 8;
t->rec_max = div_s64(rec_temp3, multiplier);
}
t->rec = DIV_ROUND_UP(
(((t->rec_max - t->rec_min) * clk_params->clk_trail_buf) +
@ -421,9 +452,14 @@ static int calc_hs_zero(struct dsi_phy_t_clk_param *clk_params,
/* recommended min */
rec_temp1 = div_s64((rec_temp1 * clk_params->bitclk_mbps),
clk_params->tlpx_numer_ns);
rec_temp2 = rec_temp1 - (11 * multiplier);
rec_temp3 = roundup((rec_temp2 / 8), multiplier);
rec_min = rec_temp3 - (3 * multiplier);
if (clk_params->phy_rev == DSI_PHY_REV_30) {
rec_temp3 = roundup((rec_temp1 / 8), multiplier);
rec_min = rec_temp3 - (1 * multiplier);
} else {
rec_temp2 = rec_temp1 - (11 * multiplier);
rec_temp3 = roundup((rec_temp2 / 8), multiplier);
rec_min = rec_temp3 - (3 * multiplier);
}
t->rec_min = div_s64(rec_min, multiplier);
t->rec_max = ((t->rec_min > 255) ? 511 : 255);
@ -466,14 +502,25 @@ static int calc_hs_trail(struct dsi_phy_t_clk_param *clk_params,
t->mipi_max = teot_clk_lane - clk_params->treot_ns;
t->rec_min = DIV_ROUND_UP(
((t->mipi_min * clk_params->bitclk_mbps) +
(3 * clk_params->tlpx_numer_ns)),
(8 * clk_params->tlpx_numer_ns));
if (clk_params->phy_rev == DSI_PHY_REV_30) {
t->rec_min = DIV_ROUND_UP(
(t->mipi_min * clk_params->bitclk_mbps),
(8 * clk_params->tlpx_numer_ns)) - 1;
rec_temp1 = (t->mipi_max * clk_params->bitclk_mbps);
t->rec_max =
(div_s64(rec_temp1, (8 * clk_params->tlpx_numer_ns))) - 1;
} else {
t->rec_min = DIV_ROUND_UP(
((t->mipi_min * clk_params->bitclk_mbps) +
(3 * clk_params->tlpx_numer_ns)),
(8 * clk_params->tlpx_numer_ns));
rec_temp1 = ((t->mipi_max * clk_params->bitclk_mbps) +
(3 * clk_params->tlpx_numer_ns));
t->rec_max =
div_s64(rec_temp1, (8 * clk_params->tlpx_numer_ns));
}
rec_temp1 = ((t->mipi_max * clk_params->bitclk_mbps) +
(3 * clk_params->tlpx_numer_ns));
t->rec_max = div_s64(rec_temp1, (8 * clk_params->tlpx_numer_ns));
rec_temp1 = DIV_ROUND_UP(
((t->rec_max - t->rec_min) * clk_params->hs_trail_buf),
100);
@ -588,7 +635,7 @@ error:
return rc;
}
static int mdss_dsi_phy_calc_param_phy_rev_2(
static int mdss_dsi_phy_calc_param_phy_cmn(
struct dsi_phy_t_clk_param *clk_params,
struct dsi_phy_timing *desc)
{
@ -932,8 +979,7 @@ static void mdss_dsi_phy_update_timing_param(struct mdss_panel_info *pinfo,
reg->timing[11]);
}
static void mdss_dsi_phy_update_timing_param_rev_2(
struct mdss_panel_info *pinfo,
static void mdss_dsi_phy_update_timing_param_v2(struct mdss_panel_info *pinfo,
struct dsi_phy_timing *t_param)
{
struct mdss_dsi_phy_ctrl *reg;
@ -966,6 +1012,27 @@ static void mdss_dsi_phy_update_timing_param_rev_2(
}
}
static void mdss_dsi_phy_update_timing_param_v3(struct mdss_panel_info *pinfo,
struct dsi_phy_timing *t_param)
{
struct mdss_dsi_phy_ctrl *pd;
pd = &(pinfo->mipi.dsi_phy_db);
pd->timing[0] = 0x00;
pd->timing[1] = t_param->clk_zero.program_value;
pd->timing[2] = t_param->clk_prepare.program_value;
pd->timing[3] = t_param->clk_trail.program_value;
pd->timing[4] = t_param->hs_exit.program_value;
pd->timing[5] = t_param->hs_zero.program_value;
pd->timing[6] = t_param->hs_prepare.program_value;
pd->timing[7] = t_param->hs_trail.program_value;
pd->timing[8] = t_param->hs_rqst.program_value;
pd->timing[9] = 0x03;
pd->timing[10] = 0x04;
pd->timing[11] = 0x00;
}
int mdss_dsi_phy_calc_timing_param(struct mdss_panel_info *pinfo, u32 phy_rev,
u32 frate_hz)
{
@ -1020,12 +1087,20 @@ int mdss_dsi_phy_calc_timing_param(struct mdss_panel_info *pinfo, u32 phy_rev,
mdss_dsi_phy_update_timing_param(pinfo, &t_param);
break;
case DSI_PHY_REV_20:
rc = mdss_dsi_phy_calc_param_phy_rev_2(&t_clk, &t_param);
rc = mdss_dsi_phy_calc_param_phy_cmn(&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);
mdss_dsi_phy_update_timing_param_v2(pinfo, &t_param);
break;
case DSI_PHY_REV_30:
rc = mdss_dsi_phy_calc_param_phy_cmn(&t_clk, &t_param);
if (rc) {
pr_err("Phy timing calculations failed\n");
goto timing_calc_end;
}
mdss_dsi_phy_update_timing_param_v3(pinfo, &t_param);
break;
default:
pr_err("phy rev %d not supported\n", phy_rev);

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -21,6 +21,7 @@ enum phy_rev {
DSI_PHY_REV_UNKNOWN = 0x00,
DSI_PHY_REV_10 = 0x01, /* REV 1.0 - 20nm, 28nm */
DSI_PHY_REV_20 = 0x02, /* REV 2.0 - 14nm */
DSI_PHY_REV_30 = 0x03, /* REV 3.0 */
DSI_PHY_REV_MAX,
};