On Sun, May 11, 2025 at 07:47:29PM +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+renesas@xxxxxxxxxxxx> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@xxxxxxxxxxxxxxxx> > --- > 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); > > - /* C-PHY settings */ > - ret = rcsi2_c_phy_setting_v4h(priv, mbps); > - if (ret) > - return ret; > + /* T3: PHY settings */ > + cphy = rcsi2_c_phy_setting_v4h(priv, mbps); > + if (!cphy) > + return -ERANGE; > > + /* 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; > } -- Regards, Laurent Pinchart