video/drm: inno_mipi_phy: Add support for rk1808

Change-Id: I79d7b33f8458502ed8015d38a4b79a24a7bf7328
Signed-off-by: Nickey Yang <nickey.yang@rock-chips.com>
This commit is contained in:
Nickey Yang 2019-07-07 19:44:07 +08:00 committed by Jianhong Chen
parent f8841d3b05
commit 27d50ce711
2 changed files with 142 additions and 72 deletions

View File

@ -26,63 +26,79 @@
#define UPDATE(v, h, l) (((v) << (l)) & GENMASK((h), (l))) #define UPDATE(v, h, l) (((v) << (l)) & GENMASK((h), (l)))
/* Innosilicon MIPI D-PHY registers */ /* Innosilicon MIPI D-PHY registers */
#define INNO_PHY_LANE_CTRL 0x00000 #define INNO_PHY_LANE_CTRL 0x0000
#define MIPI_BGPD BIT(7) #define MIPI_BGPD BIT(7)
#define CLK_LANE_EN_MASK BIT(6) #define CLK_LANE_EN_MASK BIT(6)
#define DATA_LANE_3_EN_MASK BIT(5) #define DATA_LANE_3_EN_MASK BIT(5)
#define DATA_LANE_2_EN_MASK BIT(4) #define DATA_LANE_2_EN_MASK BIT(4)
#define DATA_LANE_1_EN_MASK BIT(3) #define DATA_LANE_1_EN_MASK BIT(3)
#define DATA_LANE_0_EN_MASK BIT(2) #define DATA_LANE_0_EN_MASK BIT(2)
#define CLK_LANE_EN BIT(6) #define CLK_LANE_EN BIT(6)
#define DATA_LANE_3_EN BIT(5) #define DATA_LANE_3_EN BIT(5)
#define DATA_LANE_2_EN BIT(4) #define DATA_LANE_2_EN BIT(4)
#define DATA_LANE_1_EN BIT(3) #define DATA_LANE_1_EN BIT(3)
#define DATA_LANE_0_EN BIT(2) #define DATA_LANE_0_EN BIT(2)
#define PWROK_BP BIT(1) #define PWROK_BP BIT(1)
#define PWROK BIT(0) #define PWROK BIT(0)
#define INNO_PHY_POWER_CTRL 0x00004 #define INNO_PHY_POWER_CTRL 0x0004
#define ANALOG_RESET_MASK BIT(2) #define ANALOG_RESET_MASK BIT(2)
#define ANALOG_RESET BIT(2) #define ANALOG_RESET BIT(2)
#define ANALOG_NORMAL 0 #define ANALOG_NORMAL 0
#define LDO_POWER_MASK BIT(1) #define LDO_POWER_MASK BIT(1)
#define LDO_POWER_DOWN BIT(1) #define LDO_POWER_DOWN BIT(1)
#define LDO_POWER_ON 0 #define LDO_POWER_ON 0
#define PLL_POWER_MASK BIT(0) #define PLL_POWER_MASK BIT(0)
#define PLL_POWER_DOWN BIT(0) #define PLL_POWER_DOWN BIT(0)
#define PLL_POWER_ON 0 #define PLL_POWER_ON 0
#define INNO_PHY_PLL_CTRL_0 0x0000c #define INNO_PHY_PLL_CTRL_0 0x000c
#define FBDIV_HI_MASK BIT(5) #define FBDIV_HI_MASK BIT(5)
#define FBDIV_HI(x) UPDATE(x, 5, 5) #define FBDIV_HI(x) UPDATE(x, 5, 5)
#define PREDIV_MASK GENMASK(4, 0) #define PREDIV_MASK GENMASK(4, 0)
#define PREDIV(x) UPDATE(x, 4, 0) #define PREDIV(x) UPDATE(x, 4, 0)
#define INNO_PHY_PLL_CTRL_1 0x00010 #define INNO_PHY_PLL_CTRL_1 0x0010
#define FBDIV_LO_MASK GENMASK(7, 0) #define FBDIV_LO_MASK GENMASK(7, 0)
#define FBDIV_LO(x) UPDATE(x, 7, 0) #define FBDIV_LO(x) UPDATE(x, 7, 0)
#define INNO_PHY_DIG_CTRL 0x00080 #define ANALOG_REG_08 0x0020
#define DIGITAL_RESET_MASK BIT(0) #define PRE_EMPHASIS_ENABLE_MASK BIT(7)
#define DIGITAL_NORMAL BIT(0) #define PRE_EMPHASIS_ENABLE BIT(7)
#define DIGITAL_RESET 0 #define PRE_EMPHASIS_DISABLE 0
#define INNO_PHY_LVDS_CTRL 0x003ac #define PLL_POST_DIV_ENABLE_MASK BIT(5)
#define LVDS_BGPD BIT(0) #define PLL_POST_DIV_ENABLE BIT(5)
#define PLL_POST_DIV_DISABLE 0
#define DATA_LANE_VOD_RANGE_SET_MASK GENMASK(3, 0)
#define DATA_LANE_VOD_RANGE_SET(x) UPDATE(x, 3, 0)
#define ANALOG_REG_0B 0x002c
#define CLOCK_LANE_VOD_RANGE_SET_MASK GENMASK(3, 0)
#define CLOCK_LANE_VOD_RANGE_SET(x) UPDATE(x, 3, 0)
#define VOD_MIN_RANGE 0x1
#define VOD_MID_RANGE 0x3
#define VOD_BIG_RANGE 0x7
#define VOD_MAX_RANGE 0xf
#define INNO_PHY_DIG_CTRL 0x0080
#define DIGITAL_RESET_MASK BIT(0)
#define DIGITAL_NORMAL BIT(0)
#define DIGITAL_RESET 0
#define INNO_PHY_LVDS_CTRL 0x03ac
#define LVDS_BGPD BIT(0)
#define INNO_CLOCK_LANE_REG_BASE 0x00100 #define INNO_CLOCK_LANE_REG_BASE 0x0100
#define INNO_DATA_LANE_0_REG_BASE 0x00180 #define INNO_DATA_LANE_0_REG_BASE 0x0180
#define INNO_DATA_LANE_1_REG_BASE 0x00200 #define INNO_DATA_LANE_1_REG_BASE 0x0200
#define INNO_DATA_LANE_2_REG_BASE 0x00280 #define INNO_DATA_LANE_2_REG_BASE 0x0280
#define INNO_DATA_LANE_3_REG_BASE 0x00300 #define INNO_DATA_LANE_3_REG_BASE 0x0300
#define T_LPX_OFFSET 0x00014 #define T_LPX_OFFSET 0x0014
#define T_HS_PREPARE_OFFSET 0x00018 #define T_HS_PREPARE_OFFSET 0x0018
#define T_HS_ZERO_OFFSET 0x0001c #define T_HS_ZERO_OFFSET 0x001c
#define T_HS_TRAIL_OFFSET 0x00020 #define T_HS_TRAIL_OFFSET 0x0020
#define T_HS_EXIT_OFFSET 0x00024 #define T_HS_EXIT_OFFSET 0x0024
#define T_CLK_POST_OFFSET 0x00028 #define T_CLK_POST_OFFSET 0x0028
#define T_WAKUP_H_OFFSET 0x00030 #define T_WAKUP_H_OFFSET 0x0030
#define T_WAKUP_L_OFFSET 0x00034 #define T_WAKUP_L_OFFSET 0x0034
#define T_CLK_PRE_OFFSET 0x00038 #define T_CLK_PRE_OFFSET 0x0038
#define T_TA_GO_OFFSET 0x00040 #define T_TA_GO_OFFSET 0x0040
#define T_TA_SURE_OFFSET 0x00044 #define T_TA_SURE_OFFSET 0x0044
#define T_TA_WAIT_OFFSET 0x00048 #define T_TA_WAIT_OFFSET 0x0048
#define T_LPX_MASK GENMASK(5, 0) #define T_LPX_MASK GENMASK(5, 0)
#define T_LPX(x) UPDATE(x, 5, 0) #define T_LPX(x) UPDATE(x, 5, 0)
@ -109,6 +125,11 @@
#define T_TA_WAIT_MASK GENMASK(5, 0) #define T_TA_WAIT_MASK GENMASK(5, 0)
#define T_TA_WAIT(x) UPDATE(x, 5, 0) #define T_TA_WAIT(x) UPDATE(x, 5, 0)
enum soc_type {
RV1108_MIPI_DPHY,
RK1808_MIPI_DPHY,
};
enum lane_type { enum lane_type {
CLOCK_LANE, CLOCK_LANE,
DATA_LANE_0, DATA_LANE_0,
@ -198,19 +219,37 @@ struct fixed_param {
}; };
static const struct fixed_param fixed_param_table[] = { static const struct fixed_param fixed_param_table[] = {
FIXED_PARAM( 110, 0x20, 0x16, 0x02, 0x22), FIXED_PARAM(110, 0x20, 0x16, 0x02, 0x22),
FIXED_PARAM( 150, 0x06, 0x16, 0x03, 0x45), FIXED_PARAM(150, 0x06, 0x16, 0x03, 0x45),
FIXED_PARAM( 200, 0x18, 0x17, 0x04, 0x0b), FIXED_PARAM(200, 0x18, 0x17, 0x04, 0x0b),
FIXED_PARAM( 250, 0x05, 0x17, 0x05, 0x16), FIXED_PARAM(250, 0x05, 0x17, 0x05, 0x16),
FIXED_PARAM( 300, 0x51, 0x18, 0x06, 0x2c), FIXED_PARAM(300, 0x51, 0x18, 0x06, 0x2c),
FIXED_PARAM( 400, 0x64, 0x19, 0x07, 0x33), FIXED_PARAM(400, 0x64, 0x19, 0x07, 0x33),
FIXED_PARAM( 500, 0x20, 0x1b, 0x07, 0x4e), FIXED_PARAM(500, 0x20, 0x1b, 0x07, 0x4e),
FIXED_PARAM( 600, 0x6a, 0x1d, 0x08, 0x3a), FIXED_PARAM(600, 0x6a, 0x1d, 0x08, 0x3a),
FIXED_PARAM( 700, 0x3e, 0x1e, 0x08, 0x6a), FIXED_PARAM(700, 0x3e, 0x1e, 0x08, 0x6a),
FIXED_PARAM( 800, 0x21, 0x1f, 0x09, 0x29), FIXED_PARAM(800, 0x21, 0x1f, 0x09, 0x29),
FIXED_PARAM(1000, 0x09, 0x20, 0x09, 0x27) FIXED_PARAM(1000, 0x09, 0x20, 0x09, 0x27)
}; };
static const struct fixed_param rk1808_fixed_param_table[] = {
FIXED_PARAM(110, 0x7f, 0x16, 0x02, 0x02),
FIXED_PARAM(150, 0x7f, 0x16, 0x03, 0x02),
FIXED_PARAM(200, 0x7f, 0x17, 0x04, 0x02),
FIXED_PARAM(250, 0x7f, 0x17, 0x05, 0x04),
FIXED_PARAM(300, 0x7f, 0x18, 0x06, 0x04),
FIXED_PARAM(400, 0x7e, 0x19, 0x07, 0x04),
FIXED_PARAM(500, 0x7c, 0x1b, 0x07, 0x08),
FIXED_PARAM(600, 0x70, 0x1d, 0x08, 0x10),
FIXED_PARAM(700, 0x40, 0x1e, 0x08, 0x30),
FIXED_PARAM(800, 0x02, 0x1f, 0x09, 0x30),
FIXED_PARAM(1000, 0x08, 0x20, 0x09, 0x30),
FIXED_PARAM(1400, 0x03, 0x32, 0x14, 0x0f),
FIXED_PARAM(1600, 0x42, 0x36, 0x0e, 0x0f),
FIXED_PARAM(1800, 0x47, 0x7a, 0x0e, 0x0f),
FIXED_PARAM(2000, 0x64, 0x7a, 0x0e, 0x0b),
};
static inline void inno_write(struct inno_mipi_dphy *inno, u32 reg, u32 val) static inline void inno_write(struct inno_mipi_dphy *inno, u32 reg, u32 val)
{ {
writel(val, inno->regs + reg); writel(val, inno->regs + reg);
@ -320,19 +359,28 @@ static void inno_mipi_dphy_timing_update(struct inno_mipi_dphy *inno,
static void inno_mipi_dphy_get_fixed_param(struct inno_mipi_dphy_timing *t, static void inno_mipi_dphy_get_fixed_param(struct inno_mipi_dphy_timing *t,
unsigned int freq, unsigned int freq,
enum soc_type soc_type,
enum lane_type lane_type) enum lane_type lane_type)
{ {
const struct fixed_param *param; const struct fixed_param *param, *param_table;
int i; int i, param_num;
for (i = 0; i < ARRAY_SIZE(fixed_param_table); i++) if (soc_type == RK1808_MIPI_DPHY) {
if (freq <= fixed_param_table[i].max_freq) param_table = rk1808_fixed_param_table;
param_num = ARRAY_SIZE(rk1808_fixed_param_table);
} else {
param_table = fixed_param_table;
param_num = ARRAY_SIZE(fixed_param_table);
}
for (i = 0; i < param_num; i++)
if (freq <= param_table[i].max_freq)
break; break;
if (i == ARRAY_SIZE(fixed_param_table)) if (i == param_num)
--i; --i;
param = &fixed_param_table[i]; param = &param_table[i];
if (lane_type == CLOCK_LANE) if (lane_type == CLOCK_LANE)
t->hs_zero = param->clk_lane.hs_zero; t->hs_zero = param->clk_lane.hs_zero;
@ -346,6 +394,8 @@ static void inno_mipi_dphy_get_fixed_param(struct inno_mipi_dphy_timing *t,
static void inno_mipi_dphy_lane_timing_init(struct inno_mipi_dphy *inno, static void inno_mipi_dphy_lane_timing_init(struct inno_mipi_dphy *inno,
enum lane_type lane_type) enum lane_type lane_type)
{ {
struct rockchip_phy *phy =
(struct rockchip_phy *)dev_get_driver_data(inno->dev);
struct mipi_dphy_timing timing; struct mipi_dphy_timing timing;
struct inno_mipi_dphy_timing data; struct inno_mipi_dphy_timing data;
unsigned long txbyteclk, txclkesc, UI; unsigned long txbyteclk, txclkesc, UI;
@ -363,7 +413,8 @@ static void inno_mipi_dphy_lane_timing_init(struct inno_mipi_dphy *inno,
txbyteclk, txclkesc, esc_clk_div, UI); txbyteclk, txclkesc, esc_clk_div, UI);
mipi_dphy_timing_get_default(&timing, UI); mipi_dphy_timing_get_default(&timing, UI);
inno_mipi_dphy_get_fixed_param(&data, inno->lane_mbps, lane_type); inno_mipi_dphy_get_fixed_param(&data, inno->lane_mbps,
phy->soc_type, lane_type);
/* /*
* Ttxbyteclk * val >= Ths-exit * Ttxbyteclk * val >= Ths-exit
@ -599,6 +650,14 @@ static unsigned long inno_mipi_dphy_set_pll(struct rockchip_phy *phy,
v = FBDIV_LO(fbdiv); v = FBDIV_LO(fbdiv);
inno_update_bits(inno, INNO_PHY_PLL_CTRL_1, m, v); inno_update_bits(inno, INNO_PHY_PLL_CTRL_1, m, v);
if (phy->soc_type == RK1808_MIPI_DPHY) {
inno_update_bits(inno, ANALOG_REG_08,
PLL_POST_DIV_ENABLE_MASK, PLL_POST_DIV_ENABLE);
inno_update_bits(inno, ANALOG_REG_0B,
CLOCK_LANE_VOD_RANGE_SET_MASK,
CLOCK_LANE_VOD_RANGE_SET(VOD_MAX_RANGE));
}
inno->lane_mbps = fout / USEC_PER_SEC; inno->lane_mbps = fout / USEC_PER_SEC;
return fout; return fout;
@ -637,7 +696,13 @@ static const struct rockchip_phy_funcs inno_mipi_dphy_funcs = {
}; };
static struct rockchip_phy inno_mipi_dphy_driver_data = { static struct rockchip_phy inno_mipi_dphy_driver_data = {
.funcs = &inno_mipi_dphy_funcs,
.soc_type = RV1108_MIPI_DPHY,
};
static struct rockchip_phy rk1808_inno_mipi_dphy_driver_data = {
.funcs = &inno_mipi_dphy_funcs, .funcs = &inno_mipi_dphy_funcs,
.soc_type = RK1808_MIPI_DPHY,
}; };
static const struct udevice_id inno_mipi_dphy_ids[] = { static const struct udevice_id inno_mipi_dphy_ids[] = {
@ -645,6 +710,10 @@ static const struct udevice_id inno_mipi_dphy_ids[] = {
.compatible = "rockchip,rv1108-mipi-dphy", .compatible = "rockchip,rv1108-mipi-dphy",
.data = (ulong)&inno_mipi_dphy_driver_data, .data = (ulong)&inno_mipi_dphy_driver_data,
}, },
{
.compatible = "rockchip,rk1808-mipi-dphy",
.data = (ulong)&rk1808_inno_mipi_dphy_driver_data,
},
{} {}
}; };

View File

@ -30,6 +30,7 @@ struct rockchip_phy {
struct udevice *dev; struct udevice *dev;
const struct rockchip_phy_funcs *funcs; const struct rockchip_phy_funcs *funcs;
const void *data; const void *data;
int soc_type;
}; };
int rockchip_phy_init(struct rockchip_phy *phy); int rockchip_phy_init(struct rockchip_phy *phy);