phy: rockchip-inno-mipi-dphy: Add fixed timing param table

Change-Id: Ia6a92833f4b597ac5f9af694644714a7b71b3375
Signed-off-by: WeiYong Bi <bivvy.bi@rock-chips.com>
This commit is contained in:
WeiYong Bi 2017-04-11 18:10:46 +08:00 committed by Huang, Tao
parent 758b9ce53b
commit 8e8535815e

View File

@ -66,9 +66,24 @@
#define DATA_LANE_2_EN BIT(4)
#define DATA_LANE_1_EN BIT(3)
#define DATA_LANE_0_EN BIT(2)
#define FBDIV_8_MASK BIT(5)
#define PREDIV_MASK (0x1f << 0)
#define FBDIV_7_0_MASK (0xff << 0)
#define FBDIV_8(x) (((x) & 0x1) << 5)
#define PREDIV(x) (((x) & 0x1f) << 0)
#define FBDIV_7_0(x) (((x) & 0xff) << 0)
#define T_LPX_MASK (0x3f << 0)
#define T_HS_PREPARE_MASK (0x7f << 0)
#define T_HS_ZERO_MASK (0x3f << 0)
#define T_HS_TRAIL_MASK (0x7f << 0)
#define T_HS_EXIT_MASK (0x1f << 0)
#define T_CLK_POST_MASK (0xf << 0)
#define T_WAKUP_H_MASK (0x3 << 0)
#define T_WAKUP_L_MASK (0xff << 0)
#define T_CLK_PRE_MASK (0xf << 0)
#define T_TA_GO_MASK (0x3f << 0)
#define T_TA_SURE_MASK (0x3f << 0)
#define T_TA_WAIT_MASK (0x3f << 0)
#define T_LPX(x) (((x) & 0x3f) << 0)
#define T_HS_PREPARE(x) (((x) & 0x7f) << 0)
#define T_HS_ZERO(x) (((x) & 0x3f) << 0)
@ -90,82 +105,12 @@ enum lane_type {
DATA_LANE_3,
};
static const u32 lane_reg_offset[] = {
[CLOCK_LANE] = INNO_CLOCK_LANE_REG_BASE,
[DATA_LANE_0] = INNO_DATA_LANE_0_REG_BASE,
[DATA_LANE_1] = INNO_DATA_LANE_1_REG_BASE,
[DATA_LANE_2] = INNO_DATA_LANE_2_REG_BASE,
[DATA_LANE_3] = INNO_DATA_LANE_3_REG_BASE,
};
enum hs_clk_range {
HS_CLK_RANGE_80_110_MHZ,
HS_CLK_RANGE_110_150_MHZ,
HS_CLK_RANGE_150_200_MHZ,
HS_CLK_RANGE_200_250_MHZ,
HS_CLK_RANGE_250_300_MHZ,
HS_CLK_RANGE_300_400_MHZ,
HS_CLK_RANGE_400_500_MHZ,
HS_CLK_RANGE_500_600_MHZ,
HS_CLK_RANGE_600_700_MHZ,
HS_CLK_RANGE_700_800_MHZ,
HS_CLK_RANGE_800_1000_MHZ,
};
static const u8 t_hs_prepare_val[] = {
[HS_CLK_RANGE_80_110_MHZ] = 0x20,
[HS_CLK_RANGE_110_150_MHZ] = 0x06,
[HS_CLK_RANGE_150_200_MHZ] = 0x18,
[HS_CLK_RANGE_200_250_MHZ] = 0x05,
[HS_CLK_RANGE_250_300_MHZ] = 0x51,
[HS_CLK_RANGE_300_400_MHZ] = 0x64,
[HS_CLK_RANGE_400_500_MHZ] = 0x20,
[HS_CLK_RANGE_500_600_MHZ] = 0x6a,
[HS_CLK_RANGE_600_700_MHZ] = 0x3e,
[HS_CLK_RANGE_700_800_MHZ] = 0x21,
[HS_CLK_RANGE_800_1000_MHZ] = 0x09,
};
static const u8 clock_lane_t_hs_zero_val[] = {
[HS_CLK_RANGE_80_110_MHZ] = 0x16,
[HS_CLK_RANGE_110_150_MHZ] = 0x16,
[HS_CLK_RANGE_150_200_MHZ] = 0x17,
[HS_CLK_RANGE_200_250_MHZ] = 0x17,
[HS_CLK_RANGE_250_300_MHZ] = 0x18,
[HS_CLK_RANGE_300_400_MHZ] = 0x19,
[HS_CLK_RANGE_400_500_MHZ] = 0x1b,
[HS_CLK_RANGE_500_600_MHZ] = 0x1d,
[HS_CLK_RANGE_600_700_MHZ] = 0x1e,
[HS_CLK_RANGE_700_800_MHZ] = 0x1f,
[HS_CLK_RANGE_800_1000_MHZ] = 0x20,
};
static const u8 data_lane_t_hs_zero_val[] = {
[HS_CLK_RANGE_80_110_MHZ] = 2,
[HS_CLK_RANGE_110_150_MHZ] = 3,
[HS_CLK_RANGE_150_200_MHZ] = 4,
[HS_CLK_RANGE_200_250_MHZ] = 5,
[HS_CLK_RANGE_250_300_MHZ] = 6,
[HS_CLK_RANGE_300_400_MHZ] = 7,
[HS_CLK_RANGE_400_500_MHZ] = 7,
[HS_CLK_RANGE_500_600_MHZ] = 8,
[HS_CLK_RANGE_600_700_MHZ] = 8,
[HS_CLK_RANGE_700_800_MHZ] = 9,
[HS_CLK_RANGE_800_1000_MHZ] = 9,
};
static const u8 t_hs_trail_val[] = {
[HS_CLK_RANGE_80_110_MHZ] = 0x22,
[HS_CLK_RANGE_110_150_MHZ] = 0x45,
[HS_CLK_RANGE_150_200_MHZ] = 0x0b,
[HS_CLK_RANGE_200_250_MHZ] = 0x16,
[HS_CLK_RANGE_250_300_MHZ] = 0x2c,
[HS_CLK_RANGE_300_400_MHZ] = 0x33,
[HS_CLK_RANGE_400_500_MHZ] = 0x4e,
[HS_CLK_RANGE_500_600_MHZ] = 0x3a,
[HS_CLK_RANGE_600_700_MHZ] = 0x6a,
[HS_CLK_RANGE_700_800_MHZ] = 0x29,
[HS_CLK_RANGE_800_1000_MHZ] = 0x27,
struct t_param {
u32 hs_clk_rate;
u8 t_hs_prepare;
u8 clock_lane_t_hs_zero;
u8 data_lane_t_hs_zero;
u8 t_hs_trail;
};
struct mipi_dphy_timing {
@ -226,6 +171,28 @@ struct inno_mipi_dphy {
u32 lane_mbps;
};
static const u32 lane_reg_offset[] = {
[CLOCK_LANE] = INNO_CLOCK_LANE_REG_BASE,
[DATA_LANE_0] = INNO_DATA_LANE_0_REG_BASE,
[DATA_LANE_1] = INNO_DATA_LANE_1_REG_BASE,
[DATA_LANE_2] = INNO_DATA_LANE_2_REG_BASE,
[DATA_LANE_3] = INNO_DATA_LANE_3_REG_BASE,
};
static const struct t_param t_fixed_param_table[] = {
{ 110, 0x20, 0x16, 0x02, 0x22},
{ 150, 0x06, 0x16, 0x03, 0x45},
{ 200, 0x18, 0x17, 0x04, 0x0b},
{ 250, 0x05, 0x17, 0x05, 0x16},
{ 300, 0x51, 0x18, 0x06, 0x2c},
{ 400, 0x64, 0x19, 0x07, 0x33},
{ 500, 0x20, 0x1b, 0x07, 0x4e},
{ 600, 0x6a, 0x1d, 0x08, 0x3a},
{ 700, 0x3e, 0x1e, 0x08, 0x6a},
{ 800, 0x21, 0x1f, 0x09, 0x29},
{1000, 0x09, 0x20, 0x09, 0x27}
};
static inline void inno_write(struct inno_mipi_dphy *inno, u32 reg, u32 val)
{
writel_relaxed(val, inno->regs + reg);
@ -280,46 +247,85 @@ static void inno_mipi_dphy_timing_update(struct inno_mipi_dphy *inno,
struct inno_mipi_dphy_timing *t)
{
u32 base = lane_reg_offset[lane_type];
u32 val, mask;
inno_write(inno, base + T_HS_PREPARE_OFFSET,
T_HS_PREPARE(t->t_hs_prepare));
inno_write(inno, base + T_HS_ZERO_OFFSET, T_HS_ZERO(t->t_hs_zero));
inno_write(inno, base + T_HS_TRAIL_OFFSET, T_HS_TRAIL(t->t_hs_trail));
inno_write(inno, base + T_HS_EXIT_OFFSET, T_HS_EXIT(t->t_hs_exit));
inno_write(inno, base + T_CLK_POST_OFFSET, T_CLK_POST(t->t_clk_post));
inno_write(inno, base + T_CLK_PRE_OFFSET, T_CLK_PRE(t->t_clk_pre));
inno_write(inno, base + T_WAKUP_H_OFFSET, T_WAKUP_H(t->t_wakup_h));
inno_write(inno, base + T_WAKUP_L_OFFSET, T_WAKUP_L(t->t_wakup_l));
inno_write(inno, base + T_LPX_OFFSET, T_LPX(t->t_lpx));
inno_write(inno, base + T_TA_GO_OFFSET, T_TA_GO(t->t_ta_go));
inno_write(inno, base + T_TA_SURE_OFFSET, T_TA_SURE(t->t_ta_sure));
inno_write(inno, base + T_TA_WAIT_OFFSET, T_TA_WAIT(t->t_ta_wait));
mask = T_HS_PREPARE_MASK;
val = T_HS_PREPARE(t->t_hs_prepare);
inno_update_bits(inno, base + T_HS_PREPARE_OFFSET, mask, val);
mask = T_HS_ZERO_MASK;
val = T_HS_ZERO(t->t_hs_zero);
inno_update_bits(inno, base + T_HS_ZERO_OFFSET, mask, val);
mask = T_HS_TRAIL_MASK;
val = T_HS_TRAIL(t->t_hs_trail);
inno_update_bits(inno, base + T_HS_TRAIL_OFFSET, mask, val);
mask = T_HS_EXIT_MASK;
val = T_HS_EXIT(t->t_hs_exit);
inno_update_bits(inno, base + T_HS_EXIT_OFFSET, mask, val);
if (lane_type == CLOCK_LANE) {
mask = T_CLK_POST_MASK;
val = T_CLK_POST(t->t_clk_post);
inno_update_bits(inno, base + T_CLK_POST_OFFSET, mask, val);
mask = T_CLK_PRE_MASK;
val = T_CLK_PRE(t->t_clk_pre);
inno_update_bits(inno, base + T_CLK_PRE_OFFSET, mask, val);
}
mask = T_WAKUP_H_MASK;
val = T_WAKUP_H(t->t_wakup_h);
inno_update_bits(inno, base + T_WAKUP_H_OFFSET, mask, val);
mask = T_WAKUP_L_MASK;
val = T_WAKUP_L(t->t_wakup_l);
inno_update_bits(inno, base + T_WAKUP_L_OFFSET, mask, val);
mask = T_LPX_MASK;
val = T_LPX(t->t_lpx);
inno_update_bits(inno, base + T_LPX_OFFSET, mask, val);
mask = T_TA_GO_MASK;
val = T_TA_GO(t->t_ta_go);
inno_update_bits(inno, base + T_TA_GO_OFFSET, mask, val);
mask = T_TA_SURE_MASK;
val = T_TA_SURE(t->t_ta_sure);
inno_update_bits(inno, base + T_TA_SURE_OFFSET, mask, val);
mask = T_TA_WAIT_MASK;
val = T_TA_WAIT(t->t_ta_wait);
inno_update_bits(inno, base + T_TA_WAIT_OFFSET, mask, val);
}
static enum hs_clk_range inno_mipi_dphy_get_hs_clk_range(u32 lane_mbps)
static int inno_mipi_dphy_get_fixed_param(struct inno_mipi_dphy_timing *t,
u32 hs_clk_rate,
enum lane_type lane_type)
{
if (lane_mbps < 110)
return HS_CLK_RANGE_80_110_MHZ;
else if (lane_mbps < 150)
return HS_CLK_RANGE_110_150_MHZ;
else if (lane_mbps < 200)
return HS_CLK_RANGE_150_200_MHZ;
else if (lane_mbps < 250)
return HS_CLK_RANGE_200_250_MHZ;
else if (lane_mbps < 300)
return HS_CLK_RANGE_250_300_MHZ;
else if (lane_mbps < 400)
return HS_CLK_RANGE_400_500_MHZ;
else if (lane_mbps < 500)
return HS_CLK_RANGE_400_500_MHZ;
else if (lane_mbps < 600)
return HS_CLK_RANGE_500_600_MHZ;
else if (lane_mbps < 700)
return HS_CLK_RANGE_600_700_MHZ;
else if (lane_mbps < 800)
return HS_CLK_RANGE_700_800_MHZ;
const struct t_param *param;
int i;
for (i = 0; i < ARRAY_SIZE(t_fixed_param_table); i++) {
if (hs_clk_rate <= t_fixed_param_table[i].hs_clk_rate)
break;
}
if (i == ARRAY_SIZE(t_fixed_param_table))
return -EINVAL;
param = &t_fixed_param_table[i];
if (lane_type == CLOCK_LANE)
t->t_hs_zero = param->clock_lane_t_hs_zero;
else
return HS_CLK_RANGE_800_1000_MHZ;
t->t_hs_zero = param->data_lane_t_hs_zero;
t->t_hs_prepare = param->t_hs_prepare;
t->t_hs_trail = param->t_hs_trail;
return 0;
}
static void inno_mipi_dphy_lane_timing_init(struct inno_mipi_dphy *inno,
@ -330,22 +336,12 @@ static void inno_mipi_dphy_lane_timing_init(struct inno_mipi_dphy *inno,
u32 txbyteclkhs = inno->lane_mbps / 8; /* MHz */
u32 txclkesc = 20; /* MHz */
u32 UI = DIV_ROUND_CLOSEST(NSEC_PER_USEC, inno->lane_mbps); /* ns */
enum hs_clk_range range;
memset(&timing, 0, sizeof(timing));
memset(&data, 0, sizeof(data));
mipi_dphy_timing_get_default(&timing, UI);
range = inno_mipi_dphy_get_hs_clk_range(inno->lane_mbps);
if (lane_type == CLOCK_LANE)
data.t_hs_zero = clock_lane_t_hs_zero_val[range];
else
data.t_hs_zero = data_lane_t_hs_zero_val[range];
data.t_hs_prepare = t_hs_prepare_val[range];
data.t_hs_trail = t_hs_trail_val[range];
inno_mipi_dphy_get_fixed_param(&data, inno->lane_mbps, lane_type);
/* txbyteclkhs domain */
data.t_hs_exit = DIV_ROUND_UP(txbyteclkhs * timing.hsexit,
@ -374,7 +370,7 @@ static void inno_mipi_dphy_pll_init(struct inno_mipi_dphy *inno)
unsigned int target_mbps = 1000;
unsigned int max_mbps = 1000;
u32 fbdiv = 1, prediv = 1;
u32 val;
u32 val, mask;
mpclk = DIV_ROUND_UP(panel->vm.pixelclock, USEC_PER_SEC);
if (mpclk) {
@ -390,6 +386,8 @@ static void inno_mipi_dphy_pll_init(struct inno_mipi_dphy *inno)
tmp = pllref;
for (i = 1; i < 6; i++) {
if (pllref % i)
continue;
pre = pllref / i;
if ((tmp > (target_mbps % pre)) && (target_mbps / pre < 512)) {
tmp = target_mbps % pre;
@ -400,17 +398,19 @@ static void inno_mipi_dphy_pll_init(struct inno_mipi_dphy *inno)
break;
}
inno->lane_mbps = pllref * fbdiv / prediv;
inno->lane_mbps = pllref / prediv * fbdiv;
phy_set_bus_width(inno->phy, inno->lane_mbps);
mask = FBDIV_8_MASK | PREDIV_MASK;
val = FBDIV_8(fbdiv >> 8) | PREDIV(prediv);
inno_write(inno, INNO_PHY_PLL_CTRL_0, val);
inno_update_bits(inno, INNO_PHY_PLL_CTRL_0, mask, val);
mask = FBDIV_7_0_MASK;
val = FBDIV_7_0(fbdiv);
inno_write(inno, INNO_PHY_PLL_CTRL_1, val);
inno_update_bits(inno, INNO_PHY_PLL_CTRL_1, mask, val);
dev_info(inno->dev, "fin=%d, fout=%d, prediv=%d, fbdiv=%d\n",
pllref, inno->lane_mbps, prediv, fbdiv);
dev_info(inno->dev, "fin=%d, target_mbps=%d, fout=%d, prediv=%d, fbdiv=%d\n",
pllref, target_mbps, inno->lane_mbps, prediv, fbdiv);
}
static void inno_mipi_dphy_reset(struct inno_mipi_dphy *inno)