phy: rockchip: mipi csi2 dphy support set quick stream

Signed-off-by: Zefa Chen <zefa.chen@rock-chips.com>
Change-Id: I1a36a5244cef005daddcd4d80fa8fe051061c7ca
This commit is contained in:
Zefa Chen
2023-11-24 14:26:23 +08:00
committed by 陈泽发
parent b42660e87c
commit e1ecd29fcc
3 changed files with 102 additions and 1 deletions
@@ -130,6 +130,8 @@ struct csi2_dphy_hw {
int (*stream_off)(struct csi2_dphy *dphy, struct v4l2_subdev *sd);
int (*ttl_mode_enable)(struct csi2_dphy_hw *hw);
void (*ttl_mode_disable)(struct csi2_dphy_hw *hw);
int (*quick_stream_on)(struct csi2_dphy *dphy, struct v4l2_subdev *sd);
int (*quick_stream_off)(struct csi2_dphy *dphy, struct v4l2_subdev *sd);
};
int rockchip_csi2_dphy_hw_init(void);
@@ -902,13 +902,90 @@ static int csi2_dphy_hw_stream_off(struct csi2_dphy *dphy,
write_csi2_dphy_reg(hw, CSI2PHY_REG_CTRL_LANE_ENABLE, 0x01);
csi2_dphy_hw_do_reset(hw);
usleep_range(500, 1000);
mutex_unlock(&hw->mutex);
return 0;
}
static int csi2_dphy_hw_quick_stream_on(struct csi2_dphy *dphy,
struct v4l2_subdev *sd)
{
struct v4l2_subdev *sensor_sd = get_remote_sensor(sd);
struct csi2_sensor *sensor;
struct csi2_dphy_hw *hw = dphy->dphy_hw;
u32 val = 0, pre_val = 0;
if (!sensor_sd)
return -ENODEV;
sensor = sd_to_sensor(dphy, sensor_sd);
if (!sensor)
return -ENODEV;
read_csi2_dphy_reg(hw, CSI2PHY_REG_CTRL_LANE_ENABLE, &pre_val);
if (hw->lane_mode == LANE_MODE_FULL) {
val |= (GENMASK(sensor->lanes - 1, 0) <<
CSI2_DPHY_CTRL_DATALANE_ENABLE_OFFSET_BIT) |
(0x1 << CSI2_DPHY_CTRL_CLKLANE_ENABLE_OFFSET_BIT);
} else {
if (!(pre_val & (0x1 << CSI2_DPHY_CTRL_CLKLANE_ENABLE_OFFSET_BIT)))
val |= (0x1 << CSI2_DPHY_CTRL_CLKLANE_ENABLE_OFFSET_BIT);
if (dphy->phy_index % 3 == DPHY1)
val |= (GENMASK(sensor->lanes - 1, 0) <<
CSI2_DPHY_CTRL_DATALANE_ENABLE_OFFSET_BIT);
if (dphy->phy_index % 3 == DPHY2) {
val |= (GENMASK(sensor->lanes - 1, 0) <<
CSI2_DPHY_CTRL_DATALANE_SPLIT_LANE2_3_OFFSET_BIT);
if (hw->drv_data->chip_id >= CHIP_ID_RK3588)
write_csi2_dphy_reg(hw, CSI2PHY_CLK1_LANE_ENABLE, BIT(6));
}
}
pre_val |= val;
write_csi2_dphy_reg(hw, CSI2PHY_REG_CTRL_LANE_ENABLE, pre_val);
return 0;
}
static int csi2_dphy_hw_quick_stream_off(struct csi2_dphy *dphy,
struct v4l2_subdev *sd)
{
struct v4l2_subdev *sensor_sd = get_remote_sensor(sd);
struct csi2_sensor *sensor;
struct csi2_dphy_hw *hw = dphy->dphy_hw;
u32 val = 0, pre_val = 0;
if (!sensor_sd)
return -ENODEV;
sensor = sd_to_sensor(dphy, sensor_sd);
if (!sensor)
return -ENODEV;
read_csi2_dphy_reg(hw, CSI2PHY_REG_CTRL_LANE_ENABLE, &pre_val);
if (hw->lane_mode == LANE_MODE_FULL) {
val |= (GENMASK(sensor->lanes - 1, 0) <<
CSI2_DPHY_CTRL_DATALANE_ENABLE_OFFSET_BIT) |
(0x1 << CSI2_DPHY_CTRL_CLKLANE_ENABLE_OFFSET_BIT);
} else {
if (!(pre_val & (0x1 << CSI2_DPHY_CTRL_CLKLANE_ENABLE_OFFSET_BIT)))
val |= (0x1 << CSI2_DPHY_CTRL_CLKLANE_ENABLE_OFFSET_BIT);
if (dphy->phy_index % 3 == DPHY1)
val |= (GENMASK(sensor->lanes - 1, 0) <<
CSI2_DPHY_CTRL_DATALANE_ENABLE_OFFSET_BIT);
if (dphy->phy_index % 3 == DPHY2) {
val |= (GENMASK(sensor->lanes - 1, 0) <<
CSI2_DPHY_CTRL_DATALANE_SPLIT_LANE2_3_OFFSET_BIT);
if (hw->drv_data->chip_id >= CHIP_ID_RK3588)
write_csi2_dphy_reg(hw, CSI2PHY_CLK1_LANE_ENABLE, BIT(6));
}
}
pre_val &= ~val;
write_csi2_dphy_reg(hw, CSI2PHY_REG_CTRL_LANE_ENABLE, pre_val);
return 0;
}
static int csi2_dphy_hw_ttl_mode_enable(struct csi2_dphy_hw *hw)
{
int ret = 0;
@@ -1091,6 +1168,8 @@ static int rockchip_csi2_dphy_hw_probe(struct platform_device *pdev)
}
dphy_hw->stream_on = drv_data->stream_on;
dphy_hw->stream_off = drv_data->stream_off;
dphy_hw->quick_stream_on = csi2_dphy_hw_quick_stream_on;
dphy_hw->quick_stream_off = csi2_dphy_hw_quick_stream_off;
if (drv_data->chip_id == CHIP_ID_RV1106) {
dphy_hw->ttl_mode_enable = csi2_dphy_hw_ttl_mode_enable;
@@ -689,6 +689,8 @@ static long rkcif_csi2_dphy_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void
{
struct csi2_dphy *dphy = to_csi2_dphy(sd);
long ret = 0;
int i = 0;
int on = 0;
switch (cmd) {
case RKCIF_CMD_SET_CSI_IDX:
@@ -696,6 +698,24 @@ static long rkcif_csi2_dphy_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void
dphy->drv_data->chip_id != CHIP_ID_RV1106)
dphy->csi_info = *((struct rkcif_csi_info *)arg);
break;
case RKMODULE_SET_QUICK_STREAM:
for (i = 0; i < dphy->csi_info.csi_num; i++) {
if (dphy->csi_info.dphy_vendor[i] == PHY_VENDOR_INNO) {
dphy->dphy_hw = (struct csi2_dphy_hw *)dphy->phy_hw[i];
if (!dphy->dphy_hw ||
!dphy->dphy_hw->quick_stream_off ||
!dphy->dphy_hw->quick_stream_on) {
ret = -EINVAL;
break;
}
on = *(int *)arg;
if (on)
dphy->dphy_hw->quick_stream_on(dphy, sd);
else
dphy->dphy_hw->quick_stream_off(dphy, sd);
}
}
break;
default:
ret = -ENOIOCTLCMD;
break;