media: ccs: Support and default to auto PHY control

CCS supports three variants of PHY timing control, auto, UI based and
manual. The driver previously assumed UI based control that requires
updating the link rate to the sensor. Now default to automatic control
instead, and only write the link rate to the sensor in UI mode.

If neither auto or UI control is supported, return an error in probe.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
This commit is contained in:
Sakari Ailus 2020-10-09 12:57:06 +02:00 committed by Mauro Carvalho Chehab
parent 2f23ecbf40
commit 9c3d7e5549
1 changed files with 43 additions and 11 deletions

View File

@ -383,15 +383,22 @@ static int ccs_pll_configure(struct ccs_sensor *sensor)
if (rval < 0) if (rval < 0)
return rval; return rval;
/* Lane op clock ratio does not apply here. */ if (!(CCS_LIM(sensor, PHY_CTRL_CAPABILITY) &
rval = ccs_write(sensor, REQUESTED_LINK_RATE, CCS_PHY_CTRL_CAPABILITY_AUTO_PHY_CTL)) {
DIV_ROUND_UP(pll->op_bk.sys_clk_freq_hz, /* Lane op clock ratio does not apply here. */
1000000 / 256 / 256) * rval = ccs_write(sensor, REQUESTED_LINK_RATE,
(pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL ? DIV_ROUND_UP(pll->op_bk.sys_clk_freq_hz,
sensor->pll.csi2.lanes : 1) << 1000000 / 256 / 256) *
(pll->flags & CCS_PLL_FLAG_OP_SYS_DDR ? 1 : 0)); (pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL ?
if (rval < 0 || sensor->pll.flags & CCS_PLL_FLAG_NO_OP_CLOCKS) sensor->pll.csi2.lanes : 1) <<
return rval; (pll->flags & CCS_PLL_FLAG_OP_SYS_DDR ?
1 : 0));
if (rval < 0)
return rval;
}
if (sensor->pll.flags & CCS_PLL_FLAG_NO_OP_CLOCKS)
return 0;
rval = ccs_write(sensor, OP_PIX_CLK_DIV, pll->op_bk.pix_clk_div); rval = ccs_write(sensor, OP_PIX_CLK_DIV, pll->op_bk.pix_clk_div);
if (rval < 0) if (rval < 0)
@ -1504,6 +1511,28 @@ static int ccs_write_msr_regs(struct ccs_sensor *sensor)
sensor->mdata.num_module_manufacturer_regs); sensor->mdata.num_module_manufacturer_regs);
} }
static int ccs_update_phy_ctrl(struct ccs_sensor *sensor)
{
struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
u8 val;
if (!sensor->ccs_limits)
return 0;
if (CCS_LIM(sensor, PHY_CTRL_CAPABILITY) &
CCS_PHY_CTRL_CAPABILITY_AUTO_PHY_CTL) {
val = CCS_PHY_CTRL_AUTO;
} else if (CCS_LIM(sensor, PHY_CTRL_CAPABILITY) &
CCS_PHY_CTRL_CAPABILITY_UI_PHY_CTL) {
val = CCS_PHY_CTRL_UI;
} else {
dev_err(&client->dev, "manual PHY control not supported\n");
return -EINVAL;
}
return ccs_write(sensor, PHY_CTRL, val);
}
static int ccs_power_on(struct device *dev) static int ccs_power_on(struct device *dev)
{ {
struct v4l2_subdev *subdev = dev_get_drvdata(dev); struct v4l2_subdev *subdev = dev_get_drvdata(dev);
@ -1620,8 +1649,7 @@ static int ccs_power_on(struct device *dev)
goto out_cci_addr_fail; goto out_cci_addr_fail;
} }
/* DPHY control done by sensor based on requested link rate */ rval = ccs_update_phy_ctrl(sensor);
rval = ccs_write(sensor, PHY_CTRL, CCS_PHY_CTRL_UI);
if (rval < 0) if (rval < 0)
goto out_cci_addr_fail; goto out_cci_addr_fail;
@ -3348,6 +3376,10 @@ static int ccs_probe(struct i2c_client *client)
goto out_free_ccs_limits; goto out_free_ccs_limits;
} }
rval = ccs_update_phy_ctrl(sensor);
if (rval < 0)
goto out_free_ccs_limits;
/* /*
* Handle Sensor Module orientation on the board. * Handle Sensor Module orientation on the board.
* *