From f2f204f06bcaeaf1267d7ff9696d18cd1b849f16 Mon Sep 17 00:00:00 2001 From: Jianwei Fan Date: Sat, 16 Aug 2025 11:33:20 +0800 Subject: [PATCH] media: i2c: rk628: fix mipi dphy timing set Signed-off-by: Jianwei Fan Change-Id: I58c77f0f7418651ecf817b225d7dac3e649567db --- drivers/media/i2c/rk628/rk628_csi_v4l2.c | 125 +++++++--------------- drivers/media/i2c/rk628/rk628_dsi.c | 5 - drivers/media/i2c/rk628/rk628_mipi_dphy.c | 94 ++++++++++------ drivers/media/i2c/rk628/rk628_mipi_dphy.h | 1 - 4 files changed, 101 insertions(+), 124 deletions(-) diff --git a/drivers/media/i2c/rk628/rk628_csi_v4l2.c b/drivers/media/i2c/rk628/rk628_csi_v4l2.c index c320465737b0..8428504b4d42 100644 --- a/drivers/media/i2c/rk628/rk628_csi_v4l2.c +++ b/drivers/media/i2c/rk628/rk628_csi_v4l2.c @@ -257,23 +257,6 @@ static const unsigned int rk628_csi_extcon_cable[] = { EXTCON_NONE, }; -static const struct mipi_timing rk628d_csi_mipi = { - 0x0b, 0x53, 0x10, 0x5b, 0x0b, 0x43, 0x2c, 0x50, 0x0f -}; - -static const struct mipi_timing rk628f_csi0_mipi = { - 0x0b, 0x53, 0x10, 0x5b, 0x0b, 0x43, 0x2c, 0x50, 0x0f -}; - -static const struct mipi_timing rk628f_csi1_mipi = { -//data_lp, data-pre, data-zero, data-trail, clk_lp, clk-pre, clk-zero, clk-trail, clk-post - 0x0b, 0x53, 0x10, 0x5b, 0x0b, 0x43, 0x2c, 0x50, 0x0f -}; - -static const struct mipi_timing rk628f_dsi0_mipi = { - 0x10, 0x70, 0x1c, 0x7f, 0x10, 0x70, 0x3f, 0x7f, 0x1f -}; - static struct rkmodule_csi_dphy_param rk3588_dcphy_param = { .vendor = PHY_VENDOR_SAMSUNG, .lp_vol_ref = 0, @@ -1488,17 +1471,6 @@ static void rk628_csi_initial_setup(struct v4l2_subdev *sd) struct rk628_csi *csi = to_csi(sd); rk628_csi_initial(sd); - if (csi->rk628->version >= RK628F_VERSION) { - csi->rk628->mipi_timing[0] = rk628f_csi0_mipi; - csi->rk628->mipi_timing[1] = rk628f_csi1_mipi; - } else { - csi->rk628->mipi_timing[0] = rk628d_csi_mipi; - } - - if (csi->plat_data->tx_mode == DSI_MODE) { - csi->rk628->mipi_timing[0] = rk628f_dsi0_mipi; - csi->rk628->mipi_timing[1] = rk628f_dsi0_mipi; - } csi->rk628->dphy_lane_en = 0x1f; csi->txphy_pwron = true; @@ -2156,11 +2128,37 @@ static int rk628_csi_enum_frame_interval(struct v4l2_subdev *sd, return 0; } +static u32 rk628_csi_get_lane_rate_mbps(struct rk628_csi *csi) +{ + u32 lane_rate; + u32 max_lane_rate = 1300; + u8 bpp, lanes; + u64 pixelclock = csi->timings.bt.pixelclock; + + bpp = 16; + lanes = csi->csi_lanes_in_use; + pixelclock = div_u64(pixelclock, 1000 * 1000); + lane_rate = pixelclock * bpp; + lane_rate = div_u64(lane_rate, lanes); + if (csi->rk628->dual_mipi) + lane_rate /= 2; + + if (lane_rate > 1300) + lane_rate = max_lane_rate; + else if (lane_rate > 700 && lane_rate <= 1300) + lane_rate = 1300; + else + lane_rate = 700; + + return lane_rate; +} + static int rk628_csi_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *format) { struct rk628_csi *csi = to_csi(sd); + u32 rate; if (!tx_5v_power_present(sd) || csi->nosignal) { v4l2_info(sd, "%s hdmirx no signal\n", __func__); @@ -2178,47 +2176,24 @@ static int rk628_csi_get_fmt(struct v4l2_subdev *sd, V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE; if (csi->plat_data->tx_mode == CSI_MODE) { - if (csi->timings.bt.pixelclock > 150000000 || csi->csi_lanes_in_use <= 2) { - v4l2_dbg(1, debug, sd, - "%s res wxh:%dx%d, link freq:%llu, pixrate:%u\n", - __func__, csi->timings.bt.width, csi->timings.bt.height, - link_freq_menu_items[1], RK628_CSI_PIXEL_RATE_HIGH); - __v4l2_ctrl_s_ctrl(csi->link_freq, 1); - __v4l2_ctrl_s_ctrl_int64(csi->pixel_rate, - RK628_CSI_PIXEL_RATE_HIGH); - } else { - v4l2_dbg(1, debug, sd, - "%s res wxh:%dx%d, link freq:%llu, pixrate:%u\n", - __func__, csi->timings.bt.width, csi->timings.bt.height, - link_freq_menu_items[0], RK628_CSI_PIXEL_RATE_LOW); - __v4l2_ctrl_s_ctrl(csi->link_freq, 0); - __v4l2_ctrl_s_ctrl_int64(csi->pixel_rate, - RK628_CSI_PIXEL_RATE_LOW); - } + rate = rk628_csi_get_lane_rate_mbps(csi); } else { - u32 rate; - csi->dsi.rk628 = csi->rk628; csi->dsi.timings = csi->timings; rate = rk628_dsi_get_lane_rate_mbps(&csi->dsi); - v4l2_dbg(1, debug, sd, "%s mipi bitrate:%u mbps\n", __func__, rate); - - if (rate > 1300) { - csi->rk628->mipi_timing[0] = rk628f_dsi0_mipi; - csi->rk628->mipi_timing[1] = rk628f_dsi0_mipi; - __v4l2_ctrl_s_ctrl(csi->link_freq, 2); - } else if (rate <= 1300 && rate > 700) { - csi->rk628->mipi_timing[0] = rk628f_csi0_mipi; - csi->rk628->mipi_timing[1] = rk628f_csi0_mipi; - __v4l2_ctrl_s_ctrl(csi->link_freq, 1); - } else { - csi->rk628->mipi_timing[0] = rk628f_csi0_mipi; - csi->rk628->mipi_timing[1] = rk628f_csi0_mipi; - __v4l2_ctrl_s_ctrl(csi->link_freq, 0); - } - __v4l2_ctrl_s_ctrl_int64(csi->pixel_rate, RK628_CSI_PIXEL_RATE_HIGH); } + v4l2_dbg(1, debug, sd, "%s mipi bitrate:%u mbps\n", __func__, rate); + + if (rate > 1300) + __v4l2_ctrl_s_ctrl(csi->link_freq, 2); + else if (rate <= 1300 && rate > 700) + __v4l2_ctrl_s_ctrl(csi->link_freq, 1); + else + __v4l2_ctrl_s_ctrl(csi->link_freq, 0); + + __v4l2_ctrl_s_ctrl_int64(csi->pixel_rate, RK628_CSI_PIXEL_RATE_HIGH); + mutex_unlock(&csi->confctl_mutex); v4l2_dbg(1, debug, sd, "%s: fmt code:%d, w:%d, h:%d, field code:%d\n", __func__, format->format.code, format->format.width, @@ -2649,19 +2624,13 @@ static int mipi_dphy_power_on(struct rk628_csi *csi) struct v4l2_subdev *sd = &csi->sd; int ret; - if (csi->timings.bt.pixelclock > 150000000 || csi->csi_lanes_in_use <= 2) { - csi->lane_mbps = MIPI_DATARATE_MBPS_HIGH; - } else { - csi->lane_mbps = MIPI_DATARATE_MBPS_LOW; - } - if (csi->rk628->dual_mipi) - csi->lane_mbps = MIPI_DATARATE_MBPS_HIGH; + csi->lane_mbps = rk628_csi_get_lane_rate_mbps(csi); bus_width = csi->lane_mbps << 8; bus_width |= COMBTXPHY_MODULEA_EN; if (csi->rk628->version >= RK628F_VERSION) bus_width |= COMBTXPHY_MODULEB_EN; - v4l2_dbg(1, debug, sd, "%s mipi bitrate:%llu mbps\n", __func__, - csi->lane_mbps); + v4l2_info(sd, "%s mipi bitrate:%llu mbps\n", __func__, csi->lane_mbps); + rk628_mipi_dphy_reset_assert(csi->rk628); rk628_mipi_dphy_reset_deassert(csi->rk628); @@ -2672,18 +2641,6 @@ static int mipi_dphy_power_on(struct rk628_csi *csi) if (csi->rk628->version >= RK628F_VERSION) rk628_mipi_dphy_init_hsfreqrange(csi->rk628, csi->lane_mbps, 1); - if (csi->rk628->dual_mipi) { - rk628_mipi_dphy_init_hsmanual(csi->rk628, true, 0); - rk628_mipi_dphy_init_hsmanual(csi->rk628, true, 1); - } else if (csi->lane_mbps == MIPI_DATARATE_MBPS_HIGH && !csi->rk628->dual_mipi) { - rk628_mipi_dphy_init_hsmanual(csi->rk628, true, 0); - if (csi->rk628->version >= RK628F_VERSION) - rk628_mipi_dphy_init_hsmanual(csi->rk628, false, 1); - } else { - rk628_mipi_dphy_init_hsmanual(csi->rk628, false, 0); - if (csi->rk628->version >= RK628F_VERSION) - rk628_mipi_dphy_init_hsmanual(csi->rk628, false, 1); - } rk628_txphy_power_on(csi->rk628); usleep_range(1500, 2000); diff --git a/drivers/media/i2c/rk628/rk628_dsi.c b/drivers/media/i2c/rk628/rk628_dsi.c index af2ab7e5b50a..4255c57c536a 100644 --- a/drivers/media/i2c/rk628/rk628_dsi.c +++ b/drivers/media/i2c/rk628/rk628_dsi.c @@ -88,11 +88,6 @@ static void mipi_dphy_power_on_dsi(struct rk628_dsi *dsi, uint8_t mipi_id) rk628_testif_testclr_deassert(dsi->rk628, mipi_id); rk628_mipi_dphy_init_hsfreqrange(dsi->rk628, dsi->lane_mbps, mipi_id); - if (dsi->lane_mbps > 1100) - rk628_mipi_dphy_init_hsmanual(dsi->rk628, true, mipi_id); - else - rk628_mipi_dphy_init_hsmanual(dsi->rk628, false, mipi_id); - dsi_update_bits(rk628, mipi_id, DSI_PHY_RSTZ, PHY_ENABLECLK, PHY_ENABLECLK); dsi_update_bits(rk628, mipi_id, DSI_PHY_RSTZ, diff --git a/drivers/media/i2c/rk628/rk628_mipi_dphy.c b/drivers/media/i2c/rk628/rk628_mipi_dphy.c index 22e4d2984610..38809ef50f13 100644 --- a/drivers/media/i2c/rk628/rk628_mipi_dphy.c +++ b/drivers/media/i2c/rk628/rk628_mipi_dphy.c @@ -104,6 +104,15 @@ u8 rk628_testif_write(struct rk628 *rk628, u8 test_code, u8 test_data, uint8_t m } EXPORT_SYMBOL(rk628_testif_write); +static void rk628_testif_set_timing(struct rk628 *rk628, u8 addr, + u8 max, u8 val, uint8_t mipi_id) +{ + if (val > max) + return; + + rk628_testif_write(rk628, addr, (max + 1) | val, mipi_id); +} + u8 rk628_testif_read(struct rk628 *rk628, u8 test_code, uint8_t mipi_id) { u8 test_data; @@ -170,6 +179,56 @@ static inline void mipi_dphy_rstz_deassert(struct rk628 *rk628) udelay(1); } +static void rk628_mipi_dphy_set_timing(struct rk628 *rk628, int lane_mbps, uint8_t mipi_id) +{ + 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}, + {1750, 2050, 0x10, 0x70, 0x3f, 0x7f, 0x1f, 0x10, 0x70, 0x1c, 0x7f}, + }; + unsigned int index; + + // These ranges use the controller's internal automatically calculated timing. + if (lane_mbps < 800 || (lane_mbps >= 900 && lane_mbps < 1100)) + return; + + if (lane_mbps < timing_table[0].min_lane_mbps) + return; + + for (index = 0; index < ARRAY_SIZE(timing_table); index++) + if (lane_mbps >= timing_table[index].min_lane_mbps && + lane_mbps < timing_table[index].max_lane_mbps) + break; + + if (index == ARRAY_SIZE(timing_table)) + --index; + + rk628_testif_set_timing(rk628, 0x60, 0x3f, timing_table[index].clk_lp, mipi_id); + rk628_testif_set_timing(rk628, 0x61, 0x7f, timing_table[index].clk_hs_prepare, mipi_id); + rk628_testif_set_timing(rk628, 0x62, 0x3f, timing_table[index].clk_hs_zero, mipi_id); + rk628_testif_set_timing(rk628, 0x63, 0x7f, timing_table[index].clk_hs_trail, mipi_id); + rk628_testif_set_timing(rk628, 0x65, 0x0f, timing_table[index].clk_post, mipi_id); + rk628_testif_set_timing(rk628, 0x70, 0x3f, timing_table[index].data_lp, mipi_id); + rk628_testif_set_timing(rk628, 0x71, 0x7f, timing_table[index].data_hs_prepare, mipi_id); + rk628_testif_set_timing(rk628, 0x72, 0x3f, timing_table[index].data_hs_zero, mipi_id); + rk628_testif_set_timing(rk628, 0x73, 0x7f, timing_table[index].data_hs_trail, mipi_id); +} + void rk628_mipi_dphy_init_hsfreqrange(struct rk628 *rk628, int lane_mbps, uint8_t mipi_id) { const struct { @@ -199,43 +258,10 @@ void rk628_mipi_dphy_init_hsfreqrange(struct rk628 *rk628, int lane_mbps, uint8_ hsfreqrange = hsfreqrange_table[index].hsfreqrange; rk628_testif_write(rk628, 0x44, HSFREQRANGE(hsfreqrange), mipi_id); + rk628_mipi_dphy_set_timing(rk628, lane_mbps, mipi_id); } EXPORT_SYMBOL(rk628_mipi_dphy_init_hsfreqrange); -void rk628_mipi_dphy_init_hsmanual(struct rk628 *rk628, bool manual, uint8_t mipi_id) -{ - dev_info(rk628->dev, - "mipi dphy%d hs config, manual: %s\n", mipi_id, manual ? "true" : "false"); - //config mipi timing when mipi freq is 1250Mbps - rk628_testif_write(rk628, 0x70, - manual ? (HSZERO(rk628->mipi_timing[mipi_id].data_lp) | BIT(6)) : 0, mipi_id); - usleep_range(1500, 2000); - rk628_testif_write(rk628, 0x71, - manual ? (HSTX(rk628->mipi_timing[mipi_id].data_prepare) | BIT(7)) : 0, mipi_id); - usleep_range(1500, 2000); - rk628_testif_write(rk628, 0x72, - manual ? (HSZERO(rk628->mipi_timing[mipi_id].data_zero) | BIT(6)) : 0, mipi_id); - usleep_range(1500, 2000); - rk628_testif_write(rk628, 0x73, - manual ? (HSTX(rk628->mipi_timing[mipi_id].data_trail) | BIT(7)) : 0, mipi_id); - usleep_range(1500, 2000); - rk628_testif_write(rk628, 0x60, - manual ? (HSZERO(rk628->mipi_timing[mipi_id].clk_lp) | BIT(6)) : 0, mipi_id); - usleep_range(1500, 2000); - rk628_testif_write(rk628, 0x61, - manual ? (HSTX(rk628->mipi_timing[mipi_id].clk_prepare) | BIT(7)) : 0, mipi_id); - usleep_range(1500, 2000); - rk628_testif_write(rk628, 0x62, - manual ? (HSZERO(rk628->mipi_timing[mipi_id].clk_zero) | BIT(6)) : 0, mipi_id); - usleep_range(1500, 2000); - rk628_testif_write(rk628, 0x63, - manual ? (HSTX(rk628->mipi_timing[mipi_id].clk_trail) | BIT(7)) : 0, mipi_id); - usleep_range(1500, 2000); - rk628_testif_write(rk628, 0x65, - manual ? (HSPOST(rk628->mipi_timing[mipi_id].clk_post) | BIT(4)) : 0, mipi_id); -} -EXPORT_SYMBOL(rk628_mipi_dphy_init_hsmanual); - int rk628_mipi_dphy_reset_assert(struct rk628 *rk628) { rk628_i2c_write(rk628, CSITX_SYS_CTRL0_IMD, 0x1); diff --git a/drivers/media/i2c/rk628/rk628_mipi_dphy.h b/drivers/media/i2c/rk628/rk628_mipi_dphy.h index 8410f4d9d7df..72759eb1cea5 100644 --- a/drivers/media/i2c/rk628/rk628_mipi_dphy.h +++ b/drivers/media/i2c/rk628/rk628_mipi_dphy.h @@ -22,7 +22,6 @@ void rk628_testif_testclr_assert(struct rk628 *rk628, uint8_t mipi_id); u8 rk628_testif_write(struct rk628 *rk628, u8 test_code, u8 test_data, uint8_t mipi_id); u8 rk628_testif_read(struct rk628 *rk628, u8 test_code, uint8_t mipi_id); void rk628_mipi_dphy_init_hsfreqrange(struct rk628 *rk628, int lane_mbps, uint8_t mipi_id); -void rk628_mipi_dphy_init_hsmanual(struct rk628 *rk628, bool manual, uint8_t mipi_id); int rk628_mipi_dphy_reset_assert(struct rk628 *rk628); int rk628_mipi_dphy_reset_deassert(struct rk628 *rk628);