On Thu Jun 12 19:59:03 2025 +0200, Niklas Söderlund wrote: > Prepare for adding D-PHY support to the driver by first updating the > generic startup procedure that covers both C-PHY and D-PHY operations. > The starting procedure where updated in later versions of the datasheet. > > Most of the configuration is only documented as tables of magic values > in the documentation. Each step is however marked with a T<n> marker, > inject these markers in the comments to make it easier to map driver to > documentation. > > Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se> > Tested-by: Tomi Valkeinen <tomi.valkeinen+rene...@ideasonboard.com> > Reviewed-by: Laurent Pinchart <laurent.pinchart+rene...@ideasonboard.com> > Link: > https://lore.kernel.org/r/20250612175904.1126717-4-niklas.soderlund+rene...@ragnatech.se > Signed-off-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com> > Signed-off-by: Hans Verkuil <hverk...@xs4all.nl>
Patch committed. Thanks, Hans Verkuil drivers/media/platform/renesas/rcar-csi2.c | 84 +++++++++++++++++++++--------- 1 file changed, 58 insertions(+), 26 deletions(-) --- diff --git a/drivers/media/platform/renesas/rcar-csi2.c b/drivers/media/platform/renesas/rcar-csi2.c index cdd358b4a973..7ba637d8683b 100644 --- a/drivers/media/platform/renesas/rcar-csi2.c +++ b/drivers/media/platform/renesas/rcar-csi2.c @@ -1199,7 +1199,8 @@ static int rcsi2_wait_phy_start_v4h(struct rcar_csi2 *priv, u32 match) return -ETIMEDOUT; } -static int rcsi2_c_phy_setting_v4h(struct rcar_csi2 *priv, int mbps) +static const struct rcsi2_cphy_setting * +rcsi2_c_phy_setting_v4h(struct rcar_csi2 *priv, int mbps) { const struct rcsi2_cphy_setting *conf; int msps; @@ -1214,7 +1215,7 @@ static int rcsi2_c_phy_setting_v4h(struct rcar_csi2 *priv, int mbps) if (!conf->msps) { dev_err(priv->dev, "Unsupported PHY speed for msps setting (%u Msps)", msps); - return -ERANGE; + return NULL; } /* C-PHY specific */ @@ -1278,27 +1279,14 @@ static int rcsi2_c_phy_setting_v4h(struct rcar_csi2 *priv, int mbps) /* TODO: This registers is not documented. */ rcsi2_write16(priv, V4H_CORE_DIG_CLANE_1_RW_HS_TX_6_REG, 0x5000); - /* Leave Shutdown mode */ - rcsi2_write(priv, V4H_DPHY_RSTZ_REG, BIT(0)); - rcsi2_write(priv, V4H_PHY_SHUTDOWNZ_REG, BIT(0)); - - /* Wait for calibration */ - if (rcsi2_wait_phy_start_v4h(priv, V4H_ST_PHYST_ST_PHY_READY)) { - dev_err(priv->dev, "PHY calibration failed\n"); - return -ETIMEDOUT; - } - - /* C-PHY setting - analog programing*/ - rcsi2_write16(priv, V4H_CORE_DIG_IOCTRL_RW_AFE_LANEl_CTRL_2_REG(0, 9), conf->lane29); - rcsi2_write16(priv, V4H_CORE_DIG_IOCTRL_RW_AFE_LANEl_CTRL_2_REG(0, 7), conf->lane27); - - return 0; + return conf; } static int rcsi2_start_receiver_v4h(struct rcar_csi2 *priv, struct v4l2_subdev_state *state) { const struct rcar_csi2_format *format; + const struct rcsi2_cphy_setting *cphy; const struct v4l2_mbus_framefmt *fmt; unsigned int lanes; int mbps; @@ -1318,24 +1306,35 @@ static int rcsi2_start_receiver_v4h(struct rcar_csi2 *priv, if (mbps < 0) return mbps; - /* Reset LINK and PHY*/ + /* T0: Reset LINK and PHY*/ rcsi2_write(priv, V4H_CSI2_RESETN_REG, 0); rcsi2_write(priv, V4H_DPHY_RSTZ_REG, 0); rcsi2_write(priv, V4H_PHY_SHUTDOWNZ_REG, 0); - /* PHY static setting */ - rcsi2_write(priv, V4H_PHY_EN_REG, V4H_PHY_EN_ENABLE_CLK); + /* T1: PHY static setting */ + rcsi2_write(priv, V4H_PHY_EN_REG, V4H_PHY_EN_ENABLE_CLK | + V4H_PHY_EN_ENABLE_0 | V4H_PHY_EN_ENABLE_1 | + V4H_PHY_EN_ENABLE_2 | V4H_PHY_EN_ENABLE_3); rcsi2_write(priv, V4H_FLDC_REG, 0); rcsi2_write(priv, V4H_FLDD_REG, 0); rcsi2_write(priv, V4H_IDIC_REG, 0); rcsi2_write(priv, V4H_PHY_MODE_REG, V4H_PHY_MODE_CPHY); rcsi2_write(priv, V4H_N_LANES_REG, lanes - 1); - /* Reset CSI2 */ + rcsi2_write(priv, V4M_FRXM_REG, + V4M_FRXM_FORCERXMODE_0 | V4M_FRXM_FORCERXMODE_1 | + V4M_FRXM_FORCERXMODE_2 | V4M_FRXM_FORCERXMODE_3); + rcsi2_write(priv, V4M_OVR1_REG, + V4M_OVR1_FORCERXMODE_0 | V4M_OVR1_FORCERXMODE_1 | + V4M_OVR1_FORCERXMODE_2 | V4M_OVR1_FORCERXMODE_3); + + /* T2: Reset CSI2 */ rcsi2_write(priv, V4H_CSI2_RESETN_REG, BIT(0)); /* Registers static setting through APB */ /* Common setting */ + rcsi2_write16(priv, V4H_PPI_STARTUP_RW_COMMON_DPHY_REG(10), 0x0030); + rcsi2_write16(priv, V4H_CORE_DIG_ANACTRL_RW_COMMON_ANACTRL_REG(2), 0x1444); rcsi2_write16(priv, V4H_CORE_DIG_ANACTRL_RW_COMMON_ANACTRL_REG(0), 0x1bfd); rcsi2_write16(priv, V4H_PPI_STARTUP_RW_COMMON_STARTUP_1_1_REG, 0x0233); rcsi2_write16(priv, V4H_PPI_STARTUP_RW_COMMON_DPHY_REG(6), 0x0027); @@ -1350,15 +1349,48 @@ static int rcsi2_start_receiver_v4h(struct rcar_csi2 *priv, rcsi2_write16(priv, V4H_PPI_RW_LPDCOCAL_COARSE_CFG_REG, 0x0105); rcsi2_write16(priv, V4H_CORE_DIG_IOCTRL_RW_AFE_CB_CTRL_2_REG(6), 0x1000); rcsi2_write16(priv, V4H_PPI_RW_COMMON_CFG_REG, 0x0003); + rcsi2_write16(priv, V4H_CORE_DIG_IOCTRL_RW_AFE_CB_CTRL_2_REG(0), 0x0000); + rcsi2_write16(priv, V4H_CORE_DIG_IOCTRL_RW_AFE_CB_CTRL_2_REG(1), 0x0400); + rcsi2_write16(priv, V4H_CORE_DIG_IOCTRL_RW_AFE_CB_CTRL_2_REG(3), 0x41f6); + rcsi2_write16(priv, V4H_CORE_DIG_IOCTRL_RW_AFE_CB_CTRL_2_REG(0), 0x0000); + rcsi2_write16(priv, V4H_CORE_DIG_IOCTRL_RW_AFE_CB_CTRL_2_REG(3), 0x43f6); + rcsi2_write16(priv, V4H_CORE_DIG_IOCTRL_RW_AFE_CB_CTRL_2_REG(6), 0x3000); + rcsi2_write16(priv, V4H_CORE_DIG_IOCTRL_RW_AFE_CB_CTRL_2_REG(7), 0x0000); + rcsi2_write16(priv, V4H_CORE_DIG_IOCTRL_RW_AFE_CB_CTRL_2_REG(6), 0x7000); + rcsi2_write16(priv, V4H_CORE_DIG_IOCTRL_RW_AFE_CB_CTRL_2_REG(7), 0x0000); + rcsi2_write16(priv, V4H_CORE_DIG_IOCTRL_RW_AFE_CB_CTRL_2_REG(5), 0x4000); + + /* T3: PHY settings */ + cphy = rcsi2_c_phy_setting_v4h(priv, mbps); + if (!cphy) + return -ERANGE; - /* C-PHY settings */ - ret = rcsi2_c_phy_setting_v4h(priv, mbps); - if (ret) - return ret; + /* T4: Leave Shutdown mode */ + rcsi2_write(priv, V4H_DPHY_RSTZ_REG, BIT(0)); + rcsi2_write(priv, V4H_PHY_SHUTDOWNZ_REG, BIT(0)); + + /* T5: Wait for calibration */ + if (rcsi2_wait_phy_start_v4h(priv, V4H_ST_PHYST_ST_PHY_READY)) { + dev_err(priv->dev, "PHY calibration failed\n"); + return -ETIMEDOUT; + } + + /* T6: Analog programming */ + for (unsigned int l = 0; l < 3; l++) { + rcsi2_write16(priv, V4H_CORE_DIG_IOCTRL_RW_AFE_LANEl_CTRL_2_REG(l, 9), + cphy->lane29); + rcsi2_write16(priv, V4H_CORE_DIG_IOCTRL_RW_AFE_LANEl_CTRL_2_REG(l, 7), + cphy->lane27); + } + /* T7: Wait for stop state */ rcsi2_wait_phy_start_v4h(priv, V4H_ST_PHYST_ST_STOPSTATE_0 | V4H_ST_PHYST_ST_STOPSTATE_1 | - V4H_ST_PHYST_ST_STOPSTATE_2); + V4H_ST_PHYST_ST_STOPSTATE_2 | + V4H_ST_PHYST_ST_STOPSTATE_3); + + /* T8: De-assert FRXM */ + rcsi2_write(priv, V4M_FRXM_REG, 0); return 0; }