summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/rockchip/rk3399/include/soc/mipi.h31
-rw-r--r--src/soc/rockchip/rk3399/mipi.c69
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)