aboutsummaryrefslogtreecommitdiff
path: root/src/soc/rockchip/rk3399/mipi.c
diff options
context:
space:
mode:
authorLin Huang <hl@rock-chips.com>2017-11-02 17:53:30 +0800
committerJulius Werner <jwerner@chromium.org>2017-11-28 19:15:31 +0000
commit45f1b01324ed1712092e80fed7e03fe088452729 (patch)
tree46c995f78dc384dd83bc240db25e3d36795c9371 /src/soc/rockchip/rk3399/mipi.c
parent538b9ef66fc1e24274ae4da2fe9f45531e53a370 (diff)
rockchip/rk3399: mipi: properly configure PHY timing
These values are specified as constant time periods but the PHY configuration is in terms of the current lane byte clock so using constant values guarantees that the timings will be outside the specification with some display configurations. Derive the necessary configuration from the byte clock in order to ensure that the PHY configuration is correct. Change-Id: I396029956730907a33babe39c6a171f2fcea9dcd Signed-off-by: Lin Huang <hl@rock-chips.com> Reviewed-on: https://review.coreboot.org/22470 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Brian Norris <briannorris@chromium.org> Reviewed-by: Matthias Kaehlcke <mka@chromium.org> Reviewed-by: Julius Werner <jwerner@chromium.org>
Diffstat (limited to 'src/soc/rockchip/rk3399/mipi.c')
-rw-r--r--src/soc/rockchip/rk3399/mipi.c69
1 files changed, 67 insertions, 2 deletions
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)