diff --git a/drivers/misc/rk628/rk628_combtxphy.c b/drivers/misc/rk628/rk628_combtxphy.c index 43a75838605e..721e58b9c6f1 100644 --- a/drivers/misc/rk628/rk628_combtxphy.c +++ b/drivers/misc/rk628/rk628_combtxphy.c @@ -41,10 +41,24 @@ static void rk628_combtxphy_dsi_power_on(struct rk628 *rk628) if (ret < 0) dev_err(rk628->dev, "phy is not lock\n"); - - rk628_i2c_update_bits(rk628, COMBTXPHY_CON9, - SW_DSI_FSET_EN_MASK | SW_DSI_RCAL_EN_MASK, - SW_DSI_FSET_EN | SW_DSI_RCAL_EN); + if (rk628->version == RK628F_VERSION) { + rk628_i2c_update_bits(rk628, COMBTXPHY_CON6, + SW_PLL_CTL_CON0_MASK, + SW_PLL_CTL_CON0(1)); + rk628_i2c_update_bits(rk628, COMBTXPHY_CON9, + SW_DSI_FSET_EN_MASK | + SW_DSI_RCAL_EN_MASK | + SW_DSI_RCAL_TRIM_MASK | + SW_DSI_HSTX_AMP_TRIM_MASK, + SW_DSI_FSET_EN | + SW_DSI_RCAL_EN(1) | + SW_DSI_RCAL_TRIM(8) | + SW_DSI_HSTX_AMP_TRIM(7)); + } else { + rk628_i2c_update_bits(rk628, COMBTXPHY_CON9, + SW_DSI_FSET_EN_MASK | SW_DSI_RCAL_EN_MASK, + SW_DSI_FSET_EN | SW_DSI_RCAL_EN(0)); + } usleep_range(200, 400); } diff --git a/drivers/misc/rk628/rk628_combtxphy.h b/drivers/misc/rk628/rk628_combtxphy.h index b59594df8700..dd155f8ecf47 100644 --- a/drivers/misc/rk628/rk628_combtxphy.h +++ b/drivers/misc/rk628/rk628_combtxphy.h @@ -41,6 +41,8 @@ #define SW_PLL_FB_DIV(x) UPDATE(x, 14, 10) #define SW_PLL_FRAC_DIV(x) UPDATE(x, 9, 0) #define COMBTXPHY_CON6 REG(0x0018) +#define SW_PLL_CTL_CON0_MASK GENMASK(2, 0) +#define SW_PLL_CTL_CON0(x) UPDATE(x, 2, 0) #define COMBTXPHY_CON7 REG(0x001c) #define SW_TX_RTERM_MASK GENMASK(22, 20) #define SW_TX_RTERM(x) UPDATE(x, 22, 20) @@ -60,7 +62,11 @@ #define SW_DSI_FSET_EN_MASK BIT(29) #define SW_DSI_FSET_EN BIT(29) #define SW_DSI_RCAL_EN_MASK BIT(28) -#define SW_DSI_RCAL_EN BIT(28) +#define SW_DSI_RCAL_EN(x) UPDATE((~(x)) & 0xf, 28, 28) +#define SW_DSI_RCAL_TRIM_MASK GENMASK(27, 24) +#define SW_DSI_RCAL_TRIM(x) UPDATE(x, 27, 24) +#define SW_DSI_HSTX_AMP_TRIM_MASK GENMASK(2, 0) +#define SW_DSI_HSTX_AMP_TRIM(x) UPDATE(x, 2, 0) #define COMBTXPHY_CON10 REG(0x0028) #define TX9_CKDRV_EN BIT(9) #define TX8_CKDRV_EN BIT(8) diff --git a/drivers/misc/rk628/rk628_dsi.c b/drivers/misc/rk628/rk628_dsi.c index 7ea67468b9b5..05ecf7147a75 100644 --- a/drivers/misc/rk628/rk628_dsi.c +++ b/drivers/misc/rk628/rk628_dsi.c @@ -946,6 +946,59 @@ static void testif_write(struct rk628 *rk628, const struct rk628_dsi *dsi, dev_info(rk628->dev, "monitor_data: 0x%x\n", monitor_data); } +static void testif_set_timing(const struct rk628_dsi *dsi, u8 addr, + u8 max, u8 val) +{ + struct rk628 *rk628 = dsi->rk628; + + if (val > max) + return; + + testif_write(rk628, dsi, addr, (max + 1) | val); +} + +static void mipi_dphy_set_timing(const struct rk628_dsi *dsi) +{ + const struct { + unsigned int min_lane_mbps; + unsigned int max_lane_mbps; + u8 clk_lp; + u8 clk_hs_prepare; + u8 clk_hs_zero; + u8 clk_hs_trail; + u8 clk_post; + u8 data_lp; + u8 data_hs_prepare; + u8 data_hs_zero; + u8 data_hs_trail; + } timing_table[] = { + {800, 899, 0x07, 0x30, 0x25, 0x3c, 0x0f, 0x07, 0x40, 0x09, 0x40}, + {1100, 1249, 0x0a, 0x43, 0x2c, 0x50, 0x0f, 0x0a, 0x43, 0x10, 0x55}, + {1250, 1349, 0x0b, 0x43, 0x2c, 0x50, 0x0f, 0x0b, 0x53, 0x10, 0x5b}, + {1350, 1449, 0x0c, 0x43, 0x36, 0x60, 0x0f, 0x0c, 0x53, 0x10, 0x65}, + {1450, 1500, 0x0f, 0x60, 0x31, 0x60, 0x0f, 0x0e, 0x60, 0x11, 0x6a} + }; + unsigned int index; + + for (index = 0; index < ARRAY_SIZE(timing_table); index++) + if (dsi->lane_mbps >= timing_table[index].min_lane_mbps && + dsi->lane_mbps < timing_table[index].max_lane_mbps) + break; + + if (index == ARRAY_SIZE(timing_table)) + --index; + + testif_set_timing(dsi, 0x60, 0x3f, timing_table[index].clk_lp); + testif_set_timing(dsi, 0x61, 0x7f, timing_table[index].clk_hs_prepare); + testif_set_timing(dsi, 0x62, 0x3f, timing_table[index].clk_hs_zero); + testif_set_timing(dsi, 0x63, 0x7f, timing_table[index].clk_hs_trail); + testif_set_timing(dsi, 0x65, 0x0f, timing_table[index].clk_post); + testif_set_timing(dsi, 0x70, 0x3f, timing_table[index].data_lp); + testif_set_timing(dsi, 0x71, 0x7f, timing_table[index].data_hs_prepare); + testif_set_timing(dsi, 0x72, 0x3f, timing_table[index].data_hs_zero); + testif_set_timing(dsi, 0x73, 0x7f, timing_table[index].data_hs_trail); +} + static void mipi_dphy_init(struct rk628 *rk628, const struct rk628_dsi *dsi) { const struct { @@ -975,6 +1028,9 @@ static void mipi_dphy_init(struct rk628 *rk628, const struct rk628_dsi *dsi) hsfreqrange = hsfreqrange_table[index].hsfreqrange; testif_write(rk628, dsi, 0x44, HSFREQRANGE(hsfreqrange)); + + if (rk628->version == RK628F_VERSION) + mipi_dphy_set_timing(dsi); } static void mipi_dphy_power_on(struct rk628 *rk628, const struct rk628_dsi *dsi)