Hej Sakari. On 2023-05-16 16:12:59 +0300, Sakari Ailus wrote: > Hejssan! > > On Mon, Apr 24, 2023 at 08:59:34PM +0200, Niklas Söderlund wrote: > > @@ -645,6 +755,10 @@ static int rcsi2_calc_mbps(struct rcar_csi2 *priv, unsigned int bpp, > > mbps = v4l2_ctrl_g_ctrl_int64(ctrl) * bpp; > > do_div(mbps, lanes * 1000000); > > > > + /* Adjust for C-PHY */ > > + if (priv->cphy) > > + do_div(mbps, 2.8); > > This will divide by 2. I suppose that's not intentional?? Indeed, this looks wrong. I will recheck my work and post a v2. > > > + > > return mbps; > > } > > > > @@ -833,6 +947,170 @@ static int rcsi2_start_receiver_gen3(struct rcar_csi2 *priv) > > return 0; > > } > > > > +static int rcsi2_wait_phy_start_v4h(struct rcar_csi2 *priv, u32 match) > > +{ > > + unsigned int timeout; > > + u32 status; > > + > > + for (timeout = 0; timeout <= 10; timeout++) { > > + status = rcsi2_read(priv, V4H_ST_PHYST_REG); > > + if ((status & match) == match) > > + return 0; > > + > > + usleep_range(1000, 2000); > > + } > > + > > + return -ETIMEDOUT; > > +} > > + > > +static int rcsi2_c_phy_setting_v4h(struct rcar_csi2 *priv, int msps) > > +{ > > + const struct rcsi2_cphy_setting *conf; > > + > > + for (conf = cphy_setting_table_r8a779g0; conf->msps != 0; conf++) { > > + if (conf->msps > msps) > > + break; > > + } > > + > > + if (!conf->msps) { > > + dev_err(priv->dev, "Unsupported PHY speed for msps setting (%u Msps)", msps); > > + return -ERANGE; > > + } > > + > > + /* C-PHY specific */ > > + rcsi2_write16(priv, V4H_CORE_DIG_RW_COMMON_REG(7), 0x0155); > > + rcsi2_write16(priv, V4H_PPI_STARTUP_RW_COMMON_DPHY_REG(7), 0x0068); > > + rcsi2_write16(priv, V4H_PPI_STARTUP_RW_COMMON_DPHY_REG(8), 0x0010); > > + > > + rcsi2_write16(priv, V4H_CORE_DIG_CLANE_0_RW_LP_0_REG, 0x463c); > > + rcsi2_write16(priv, V4H_CORE_DIG_CLANE_1_RW_LP_0_REG, 0x463c); > > + rcsi2_write16(priv, V4H_CORE_DIG_CLANE_2_RW_LP_0_REG, 0x463c); > > + > > + rcsi2_write16(priv, V4H_CORE_DIG_CLANE_0_RW_HS_RX_REG(0), 0x00d5); > > + rcsi2_write16(priv, V4H_CORE_DIG_CLANE_1_RW_HS_RX_REG(0), 0x00d5); > > + rcsi2_write16(priv, V4H_CORE_DIG_CLANE_2_RW_HS_RX_REG(0), 0x00d5); > > + > > + rcsi2_write16(priv, V4H_CORE_DIG_CLANE_0_RW_HS_RX_REG(1), 0x0013); > > + rcsi2_write16(priv, V4H_CORE_DIG_CLANE_1_RW_HS_RX_REG(1), 0x0013); > > + rcsi2_write16(priv, V4H_CORE_DIG_CLANE_2_RW_HS_RX_REG(1), 0x0013); > > + > > + rcsi2_write16(priv, V4H_CORE_DIG_CLANE_0_RW_HS_RX_REG(5), 0x0013); > > + rcsi2_write16(priv, V4H_CORE_DIG_CLANE_1_RW_HS_RX_REG(5), 0x0013); > > + rcsi2_write16(priv, V4H_CORE_DIG_CLANE_2_RW_HS_RX_REG(5), 0x0013); > > + > > + rcsi2_write16(priv, V4H_CORE_DIG_CLANE_0_RW_HS_RX_REG(6), 0x000a); > > + rcsi2_write16(priv, V4H_CORE_DIG_CLANE_1_RW_HS_RX_REG(6), 0x000a); > > + rcsi2_write16(priv, V4H_CORE_DIG_CLANE_2_RW_HS_RX_REG(6), 0x000a); > > + > > + rcsi2_write16(priv, V4H_CORE_DIG_CLANE_0_RW_HS_RX_REG(2), conf->rx2); > > + rcsi2_write16(priv, V4H_CORE_DIG_CLANE_1_RW_HS_RX_REG(2), conf->rx2); > > + rcsi2_write16(priv, V4H_CORE_DIG_CLANE_2_RW_HS_RX_REG(2), conf->rx2); > > + > > + rcsi2_write16(priv, V4H_CORE_DIG_IOCTRL_RW_AFE_LANE0_CTRL_2_REG(2), 0x0001); > > + rcsi2_write16(priv, V4H_CORE_DIG_IOCTRL_RW_AFE_LANE1_CTRL_2_REG(2), 0); > > + rcsi2_write16(priv, V4H_CORE_DIG_IOCTRL_RW_AFE_LANE2_CTRL_2_REG(2), 0x0001); > > + rcsi2_write16(priv, V4H_CORE_DIG_IOCTRL_RW_AFE_LANE3_CTRL_2_REG(2), 0x0001); > > + rcsi2_write16(priv, V4H_CORE_DIG_IOCTRL_RW_AFE_LANE4_CTRL_2_REG(2), 0); > > + > > + rcsi2_write16(priv, V4H_CORE_DIG_RW_TRIO0_REG(0), conf->trio0); > > + rcsi2_write16(priv, V4H_CORE_DIG_RW_TRIO1_REG(0), conf->trio0); > > + rcsi2_write16(priv, V4H_CORE_DIG_RW_TRIO2_REG(0), conf->trio0); > > + > > + rcsi2_write16(priv, V4H_CORE_DIG_RW_TRIO0_REG(2), conf->trio2); > > + rcsi2_write16(priv, V4H_CORE_DIG_RW_TRIO1_REG(2), conf->trio2); > > + rcsi2_write16(priv, V4H_CORE_DIG_RW_TRIO2_REG(2), conf->trio2); > > + > > + rcsi2_write16(priv, V4H_CORE_DIG_RW_TRIO0_REG(1), conf->trio1); > > + rcsi2_write16(priv, V4H_CORE_DIG_RW_TRIO1_REG(1), conf->trio1); > > + rcsi2_write16(priv, V4H_CORE_DIG_RW_TRIO2_REG(1), conf->trio1); > > + > > + /* > > + * Configure pin-swap. > > + * TODO: This registers is not documented yet, the values should depend > > + * on the 'clock-lanes' and 'data-lanes' devicetree properties. > > + */ > > + rcsi2_write16(priv, V4H_CORE_DIG_CLANE_1_RW_CFG_0_REG, 0xf5); > > + 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_LANE0_CTRL_2_REG(9), conf->lane29); > > + rcsi2_write16(priv, V4H_CORE_DIG_IOCTRL_RW_AFE_LANE0_CTRL_2_REG(7), conf->lane27); > > + > > + return 0; > > +} > > + > > +static int rcsi2_start_receiver_v4h(struct rcar_csi2 *priv) > > +{ > > + const struct rcar_csi2_format *format; > > + unsigned int msps, lanes; > > + int ret; > > + > > + /* Calculate parameters */ > > + format = rcsi2_code_to_fmt(priv->mf.code); > > Can this not be NULL? I guess not? Indeed a NULL check should be added here, will fix in a v2. Thanks for spotting this. > > > + > > + ret = rcsi2_get_active_lanes(priv, &lanes); > > + if (ret) > > + return ret; > > + > > + msps = rcsi2_calc_mbps(priv, format->bpp, lanes); > > + if (msps < 0) > > + return msps; > > + > > + /* 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); > > -- > Hälsningar, > > Sakari Ailus -- Kind Regards, Niklas Söderlund