diff options
Diffstat (limited to 'src/soc/rockchip/rk3399')
-rw-r--r-- | src/soc/rockchip/rk3399/include/soc/mipi.h | 31 | ||||
-rw-r--r-- | src/soc/rockchip/rk3399/mipi.c | 69 |
2 files changed, 88 insertions, 12 deletions
diff --git a/src/soc/rockchip/rk3399/include/soc/mipi.h b/src/soc/rockchip/rk3399/include/soc/mipi.h index 2ecd0ee19d..09285cf51c 100644 --- a/src/soc/rockchip/rk3399/include/soc/mipi.h +++ b/src/soc/rockchip/rk3399/include/soc/mipi.h @@ -233,16 +233,27 @@ check_member(rk_mipi_regs, dsi_int_msk1, 0xc8); #define THS_PRE_PROGRAM_EN BIT(7) #define THS_ZERO_PROGRAM_EN BIT(6) -#define PLL_BIAS_CUR_SEL_CAP_VCO_CONTROL 0x10 -#define PLL_CP_CONTROL_PLL_LOCK_BYPASS 0x11 -#define PLL_LPF_AND_CP_CONTROL 0x12 -#define PLL_INPUT_DIVIDER_RATIO 0x17 -#define PLL_LOOP_DIVIDER_RATIO 0x18 -#define PLL_INPUT_AND_LOOP_DIVIDER_RATIOS_CONTROL 0x19 -#define BANDGAP_AND_BIAS_CONTROL 0x20 -#define TERMINATION_RESISTER_CONTROL 0x21 -#define AFE_BIAS_BANDGAP_ANALOG_PROGRAMMABILITY 0x22 -#define HS_RX_CONTROL_OF_LANE_0 0x44 +#define PLL_BIAS_CUR_SEL_CAP_VCO_CONTROL 0x10 +#define PLL_CP_CONTROL_PLL_LOCK_BYPASS 0x11 +#define PLL_LPF_AND_CP_CONTROL 0x12 +#define PLL_INPUT_DIVIDER_RATIO 0x17 +#define PLL_LOOP_DIVIDER_RATIO 0x18 +#define PLL_INPUT_AND_LOOP_DIVIDER_RATIOS_CONTROL 0x19 +#define BANDGAP_AND_BIAS_CONTROL 0x20 +#define TERMINATION_RESISTER_CONTROL 0x21 +#define AFE_BIAS_BANDGAP_ANALOG_PROGRAMMABILITY 0x22 +#define HS_RX_CONTROL_OF_LANE_0 0x44 +#define HS_TX_CLOCK_LANE_REQUEST_STATE_TIME_CONTROL 0x60 +#define HS_TX_CLOCK_LANE_PREPARE_STATE_TIME_CONTROL 0x61 +#define HS_TX_CLOCK_LANE_HS_ZERO_STATE_TIME_CONTROL 0x62 +#define HS_TX_CLOCK_LANE_TRAIL_STATE_TIME_CONTROL 0x63 +#define HS_TX_CLOCK_LANE_EXIT_STATE_TIME_CONTROL 0x64 +#define HS_TX_CLOCK_LANE_POST_TIME_CONTROL 0x65 +#define HS_TX_DATA_LANE_REQUEST_STATE_TIME_CONTROL 0x70 +#define HS_TX_DATA_LANE_PREPARE_STATE_TIME_CONTROL 0x71 +#define HS_TX_DATA_LANE_HS_ZERO_STATE_TIME_CONTROL 0x72 +#define HS_TX_DATA_LANE_TRAIL_STATE_TIME_CONTROL 0x73 +#define HS_TX_DATA_LANE_EXIT_STATE_TIME_CONTROL 0x74 #define GEN_CMD_EMPTY BIT(0) #define GEN_CMD_FULL BIT(1) diff --git a/src/soc/rockchip/rk3399/mipi.c b/src/soc/rockchip/rk3399/mipi.c index 5375c4866b..3f1ddb3664 100644 --- a/src/soc/rockchip/rk3399/mipi.c +++ b/src/soc/rockchip/rk3399/mipi.c @@ -123,10 +123,38 @@ static void rk_mipi_dsi_phy_write(struct rk_mipi_dsi *dsi, write32(&mipi_regs->dsi_phy_tst_ctrl0, PHY_TESTCLK | PHY_UNTESTCLR); } +/* bytes_per_ns - Nanoseconds to byte clock cycles */ +static inline unsigned int bytes_per_ns(struct rk_mipi_dsi *dsi, int ns) +{ + return DIV_ROUND_UP((u64)ns * dsi->lane_bps, (u64)8 * NSECS_PER_SEC); +} + + /* bits_per_ns - Nanoseconds to bit time periods */ +static inline unsigned int bits_per_ns(struct rk_mipi_dsi *dsi, int ns) +{ + return DIV_ROUND_UP((u64)ns * dsi->lane_bps, NSECS_PER_SEC); +} + +static int rk_mipi_dsi_wait_phy_lock(struct rk_mipi_dsi *dsi) +{ + struct stopwatch sw; + int val; + + stopwatch_init_msecs_expire(&sw, 20); + do { + val = read32(&mipi_regs->dsi_phy_status); + if (val & LOCK) + return 0; + } while (!stopwatch_expired(&sw)); + + return -1; +} + static int rk_mipi_dsi_phy_init(struct rk_mipi_dsi *dsi) { - int i, vco; + int i, vco, val; int lane_mbps = div_round_up(dsi->lane_bps, USECS_PER_SEC); + struct stopwatch sw; vco = (lane_mbps < 200) ? 0 : (lane_mbps + 100) / 200; @@ -192,10 +220,47 @@ static int rk_mipi_dsi_phy_init(struct rk_mipi_dsi *dsi) TER_RESISTOR_HIGH | LEVEL_SHIFTERS_ON | SETRD_MAX | POWER_MANAGE | TER_RESISTORS_ON); + rk_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_REQUEST_STATE_TIME_CONTROL, + TLP_PROGRAM_EN | bytes_per_ns(dsi, 500)); + rk_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_PREPARE_STATE_TIME_CONTROL, + THS_PRE_PROGRAM_EN | bits_per_ns(dsi, 40)); + rk_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_HS_ZERO_STATE_TIME_CONTROL, + THS_ZERO_PROGRAM_EN | bytes_per_ns(dsi, 300)); + rk_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_TRAIL_STATE_TIME_CONTROL, + THS_PRE_PROGRAM_EN | bits_per_ns(dsi, 100)); + rk_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_EXIT_STATE_TIME_CONTROL, + BIT(5) | bytes_per_ns(dsi, 100)); + rk_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_POST_TIME_CONTROL, + BIT(5) | (bytes_per_ns(dsi, 60) + 7)); + rk_mipi_dsi_phy_write(dsi, HS_TX_DATA_LANE_REQUEST_STATE_TIME_CONTROL, + TLP_PROGRAM_EN | bytes_per_ns(dsi, 500)); + rk_mipi_dsi_phy_write(dsi, HS_TX_DATA_LANE_PREPARE_STATE_TIME_CONTROL, + THS_PRE_PROGRAM_EN | (bits_per_ns(dsi, 50) + 5)); + rk_mipi_dsi_phy_write(dsi, HS_TX_DATA_LANE_HS_ZERO_STATE_TIME_CONTROL, + THS_ZERO_PROGRAM_EN | + (bytes_per_ns(dsi, 140) + 2)); + rk_mipi_dsi_phy_write(dsi, HS_TX_DATA_LANE_TRAIL_STATE_TIME_CONTROL, + THS_PRE_PROGRAM_EN | (bits_per_ns(dsi, 60) + 8)); + rk_mipi_dsi_phy_write(dsi, HS_TX_DATA_LANE_EXIT_STATE_TIME_CONTROL, + BIT(5) | bytes_per_ns(dsi, 100)); write32(&mipi_regs->dsi_phy_rstz, PHY_ENFORCEPLL | PHY_ENABLECLK | PHY_UNRSTZ | PHY_UNSHUTDOWNZ); - return 0; + + if (rk_mipi_dsi_wait_phy_lock(dsi)) { + printk(BIOS_ERR, "failed to wait for phy lock state\n"); + return -1; + } + + stopwatch_init_msecs_expire(&sw, 20); + do { + val = read32(&mipi_regs->dsi_phy_status); + if (val & STOP_STATE_CLK_LANE) + return 0; + } while (!stopwatch_expired(&sw)); + + printk(BIOS_ERR, "failed to wait for phy clk lane stop state"); + return -1; } static inline int mipi_dsi_pixel_format_to_bpp(enum mipi_dsi_pixel_format fmt) |