mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 02:50:49 +09:00
phy: rockchip: mipi csi2 dphy support rv1126b
Change-Id: I45365edfa4ffb7363bec13387e9b2b3d2a6a0a0b Signed-off-by: Zefa Chen <zefa.chen@rock-chips.com>
This commit is contained in:
@@ -26,6 +26,7 @@ enum csi2_dphy_chip_id {
|
||||
CHIP_ID_RV1106 = 0x3,
|
||||
CHIP_ID_RK3562 = 0x4,
|
||||
CHIP_ID_RK3576 = 0x5,
|
||||
CHIP_ID_RV1126B = 0x6,
|
||||
};
|
||||
|
||||
enum csi2_dphy_rx_pads {
|
||||
|
||||
@@ -44,6 +44,11 @@
|
||||
/*RK3576 DPHY GRF REG OFFSET */
|
||||
#define GRF_SOC_CON5_RK3576 (0x14)
|
||||
|
||||
/*RV1126B DPHY GRF REG OFFSET */
|
||||
#define CSIPHY0_GRF_CON_RV1126B (0x50010)
|
||||
#define CSIPHY1_GRF_CON_RV1126B (0x50014)
|
||||
#define MISC_GRF_CON_RV1126B (0x50020)
|
||||
|
||||
/*GRF REG BIT DEFINE */
|
||||
#define GRF_CSI2PHY_LANE_SEL_SPLIT (0x1)
|
||||
#define GRF_CSI2PHY_SEL_SPLIT_0_1 (0x0)
|
||||
@@ -78,6 +83,12 @@
|
||||
#define CSI2_DPHY_PATH1_MODE_SEL (0x84C)
|
||||
#define CSI2_DPHY_PATH1_LVDS_MODE_SEL (0x880)
|
||||
|
||||
/* rv1126b path mode */
|
||||
#define RV1126B_CSI2_DPHY_PATH0_MODE_SEL (0x66C)
|
||||
#define RV1126B_CSI2_DPHY_PATH0_LVDS_MODE_SEL (0x700)
|
||||
#define RV1126B_CSI2_DPHY_PATH1_MODE_SEL (0xACC)
|
||||
#define RV1126B_CSI2_DPHY_PATH1_LVDS_MODE_SEL (0xB00)
|
||||
|
||||
/* PHY REG BIT DEFINE */
|
||||
#define CSI2_DPHY_LANE_MODE_FULL (0x4)
|
||||
#define CSI2_DPHY_LANE_MODE_SPLIT (0x2)
|
||||
@@ -525,6 +536,49 @@ static const struct grf_reg rk3576_grf_dphy_regs[] = {
|
||||
[GRF_DPHY_CSI2PHY1_LANE_SEL] = GRF_REG(GRF_SOC_CON5_RK3576, 1, 2),
|
||||
};
|
||||
|
||||
static const struct grf_reg rv1126b_grf_dphy_regs[] = {
|
||||
[GRF_DPHY_CSI2PHY_FORCERXMODE] = GRF_REG(CSIPHY0_GRF_CON_RV1126B, 4, 0),
|
||||
[GRF_DPHY_CSI2PHY_CLKLANE_EN] = GRF_REG(CSIPHY0_GRF_CON_RV1126B, 1, 8),
|
||||
[GRF_DPHY_CSI2PHY_DATALANE_EN] = GRF_REG(CSIPHY0_GRF_CON_RV1126B, 4, 4),
|
||||
[GRF_DPHY_CSI2PHY_DATALANE_EN0] = GRF_REG(CSIPHY0_GRF_CON_RV1126B, 2, 4),
|
||||
[GRF_DPHY_CSI2PHY_DATALANE_EN1] = GRF_REG(CSIPHY0_GRF_CON_RV1126B, 2, 6),
|
||||
[GRF_DPHY_CLK_INV_SEL] = GRF_REG(CSIPHY0_GRF_CON_RV1126B, 1, 9),
|
||||
[GRF_DPHY_CSI2PHY_CLKLANE1_EN] = GRF_REG(CSIPHY0_GRF_CON_RV1126B, 1, 10),
|
||||
[GRF_DPHY_CLK1_INV_SEL] = GRF_REG(CSIPHY0_GRF_CON_RV1126B, 1, 11),
|
||||
[GRF_DPHY1_CSI2PHY_FORCERXMODE] = GRF_REG(CSIPHY1_GRF_CON_RV1126B, 4, 0),
|
||||
[GRF_DPHY1_CSI2PHY_CLKLANE_EN] = GRF_REG(CSIPHY1_GRF_CON_RV1126B, 1, 8),
|
||||
[GRF_DPHY1_CSI2PHY_DATALANE_EN] = GRF_REG(CSIPHY1_GRF_CON_RV1126B, 4, 4),
|
||||
[GRF_DPHY1_CSI2PHY_DATALANE_EN0] = GRF_REG(CSIPHY1_GRF_CON_RV1126B, 2, 4),
|
||||
[GRF_DPHY1_CSI2PHY_DATALANE_EN1] = GRF_REG(CSIPHY1_GRF_CON_RV1126B, 2, 6),
|
||||
[GRF_DPHY1_CLK_INV_SEL] = GRF_REG(CSIPHY1_GRF_CON_RV1126B, 1, 9),
|
||||
[GRF_DPHY1_CSI2PHY_CLKLANE1_EN] = GRF_REG(CSIPHY1_GRF_CON_RV1126B, 1, 10),
|
||||
[GRF_DPHY1_CLK1_INV_SEL] = GRF_REG(CSIPHY1_GRF_CON_RV1126B, 1, 11),
|
||||
[GRF_DPHY_CSI2PHY_LANE_SEL] = GRF_REG(MISC_GRF_CON_RV1126B, 1, 0),
|
||||
[GRF_DPHY_CSI2PHY1_LANE_SEL] = GRF_REG(MISC_GRF_CON_RV1126B, 1, 1),
|
||||
};
|
||||
|
||||
static const struct csi2dphy_reg rv1126b_csi2dphy_regs[] = {
|
||||
[CSI2PHY_REG_CTRL_LANE_ENABLE] = CSI2PHY_REG(CSI2_DPHY_CTRL_LANE_ENABLE),
|
||||
[CSI2PHY_DUAL_CLK_EN] = CSI2PHY_REG(CSI2_DPHY_DUAL_CAL_EN),
|
||||
[CSI2PHY_CLK_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_CLK_WR_THS_SETTLE),
|
||||
[CSI2PHY_CLK_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_CLK_CALIB_EN),
|
||||
[CSI2PHY_LANE0_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_LANE0_WR_THS_SETTLE),
|
||||
[CSI2PHY_LANE0_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_LANE0_CALIB_EN),
|
||||
[CSI2PHY_LANE1_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_LANE1_WR_THS_SETTLE),
|
||||
[CSI2PHY_LANE1_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_LANE1_CALIB_EN),
|
||||
[CSI2PHY_LANE2_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_LANE2_WR_THS_SETTLE),
|
||||
[CSI2PHY_LANE2_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_LANE2_CALIB_EN),
|
||||
[CSI2PHY_LANE3_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_LANE3_WR_THS_SETTLE),
|
||||
[CSI2PHY_LANE3_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_LANE3_CALIB_EN),
|
||||
[CSI2PHY_CLK1_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_CLK1_WR_THS_SETTLE),
|
||||
[CSI2PHY_CLK1_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_CLK1_CALIB_EN),
|
||||
[CSI2PHY_CLK1_LANE_ENABLE] = CSI2PHY_REG(CSI2_DPHY_CLK1_LANE_EN),
|
||||
[CSI2PHY_PATH0_MODEL] = CSI2PHY_REG(RV1126B_CSI2_DPHY_PATH0_MODE_SEL),
|
||||
[CSI2PHY_PATH0_LVDS_MODEL] = CSI2PHY_REG(RV1126B_CSI2_DPHY_PATH0_LVDS_MODE_SEL),
|
||||
[CSI2PHY_PATH1_MODEL] = CSI2PHY_REG(RV1126B_CSI2_DPHY_PATH1_MODE_SEL),
|
||||
[CSI2PHY_PATH1_LVDS_MODEL] = CSI2PHY_REG(RV1126B_CSI2_DPHY_PATH1_LVDS_MODE_SEL),
|
||||
};
|
||||
|
||||
/* These tables must be sorted by .range_h ascending. */
|
||||
static const struct hsfreq_range rk3568_csi2_dphy_hw_hsfreq_ranges[] = {
|
||||
{ 109, 0x02}, { 149, 0x03}, { 199, 0x06}, { 249, 0x06},
|
||||
@@ -683,6 +737,8 @@ static void csi2_dphy_config_dual_mode(struct csi2_dphy *dphy,
|
||||
write_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val);
|
||||
} else if (hw->drv_data->chip_id == CHIP_ID_RK3576) {
|
||||
write_sys_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val);
|
||||
} else if (hw->drv_data->chip_id == CHIP_ID_RV1126B) {
|
||||
write_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
@@ -709,6 +765,8 @@ static void csi2_dphy_config_dual_mode(struct csi2_dphy *dphy,
|
||||
write_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val);
|
||||
} else if (hw->drv_data->chip_id == CHIP_ID_RK3576) {
|
||||
write_sys_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val);
|
||||
} else if (hw->drv_data->chip_id == CHIP_ID_RV1126B) {
|
||||
write_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
@@ -728,6 +786,11 @@ static void csi2_dphy_config_dual_mode(struct csi2_dphy *dphy,
|
||||
write_grf_reg(hw, GRF_DPHY_CSI2PHY_DATALANE_EN0,
|
||||
GENMASK(sensor->lanes - 1, 0));
|
||||
write_grf_reg(hw, GRF_DPHY_CSI2PHY_CLKLANE_EN, 0x1);
|
||||
} else if (hw->drv_data->chip_id == CHIP_ID_RV1126B) {
|
||||
write_grf_reg(hw, GRF_DPHY_CSI2PHY1_LANE_SEL, val);
|
||||
write_grf_reg(hw, GRF_DPHY1_CSI2PHY_DATALANE_EN0,
|
||||
GENMASK(sensor->lanes - 1, 0));
|
||||
write_grf_reg(hw, GRF_DPHY1_CSI2PHY_CLKLANE_EN, 0x1);
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
@@ -747,6 +810,11 @@ static void csi2_dphy_config_dual_mode(struct csi2_dphy *dphy,
|
||||
write_grf_reg(hw, GRF_DPHY_CSI2PHY_DATALANE_EN1,
|
||||
GENMASK(sensor->lanes - 1, 0));
|
||||
write_grf_reg(hw, GRF_DPHY_CSI2PHY_CLKLANE1_EN, 0x1);
|
||||
} else if (hw->drv_data->chip_id == CHIP_ID_RV1126B) {
|
||||
write_grf_reg(hw, GRF_DPHY_CSI2PHY1_LANE_SEL, val);
|
||||
write_grf_reg(hw, GRF_DPHY1_CSI2PHY_DATALANE_EN1,
|
||||
GENMASK(sensor->lanes - 1, 0));
|
||||
write_grf_reg(hw, GRF_DPHY1_CSI2PHY_CLKLANE1_EN, 0x1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -788,6 +856,13 @@ static int csi2_dphy_hw_stream_on(struct csi2_dphy *dphy,
|
||||
}
|
||||
}
|
||||
|
||||
if (hw->drv_data->chip_id == CHIP_ID_RV1126B &&
|
||||
dphy->phy_index % 3 == DPHY2) {
|
||||
read_csi2_dphy_reg(hw, CSI2PHY_DUAL_CLK_EN, &val);
|
||||
val |= BIT(7);//split mode lane2_3 reset
|
||||
write_csi2_dphy_reg(hw, CSI2PHY_DUAL_CLK_EN, val);
|
||||
}
|
||||
|
||||
/* set data lane num and enable clock lane */
|
||||
/*
|
||||
* for rk356x: dphy0 is used just for full mode,
|
||||
@@ -905,7 +980,8 @@ static int csi2_dphy_hw_stream_on(struct csi2_dphy *dphy,
|
||||
}
|
||||
}
|
||||
|
||||
if (hw->drv_data->chip_id == CHIP_ID_RV1106) {
|
||||
if (hw->drv_data->chip_id == CHIP_ID_RV1106 ||
|
||||
hw->drv_data->chip_id == CHIP_ID_RV1126B) {
|
||||
if (dphy->phy_index % 3 == DPHY0 ||
|
||||
dphy->phy_index % 3 == DPHY1) {
|
||||
if (sensor->mbus.type == V4L2_MBUS_CSI2_DPHY) {
|
||||
@@ -924,7 +1000,8 @@ static int csi2_dphy_hw_stream_on(struct csi2_dphy *dphy,
|
||||
write_csi2_dphy_reg(hw, CSI2PHY_PATH1_LVDS_MODEL, (lvds_width << 4) | 0X0f);
|
||||
}
|
||||
}
|
||||
if (sensor->mbus.type == V4L2_MBUS_CSI2_DPHY) {
|
||||
if (hw->drv_data->chip_id == CHIP_ID_RV1106 &&
|
||||
sensor->mbus.type == V4L2_MBUS_CSI2_DPHY) {
|
||||
if (hw->lane_mode == LANE_MODE_FULL)
|
||||
write_csi2_dphy_reg(hw, CSI2PHY_CLK_INV, 0x04);
|
||||
else
|
||||
@@ -1083,6 +1160,11 @@ static void rk3576_csi2_dphy_hw_individual_init(struct csi2_dphy_hw *hw)
|
||||
hw->grf_regs = rk3576_grf_dphy_regs;
|
||||
}
|
||||
|
||||
static void rv1126b_csi2_dphy_hw_individual_init(struct csi2_dphy_hw *hw)
|
||||
{
|
||||
hw->grf_regs = rv1126b_grf_dphy_regs;
|
||||
}
|
||||
|
||||
static const struct dphy_hw_drv_data rk3568_csi2_dphy_hw_drv_data = {
|
||||
.hsfreq_ranges = rk3568_csi2_dphy_hw_hsfreq_ranges,
|
||||
.num_hsfreq_ranges = ARRAY_SIZE(rk3568_csi2_dphy_hw_hsfreq_ranges),
|
||||
@@ -1148,6 +1230,19 @@ static const struct dphy_hw_drv_data rk3576_csi2_dphy_hw_drv_data = {
|
||||
.stream_off = csi2_dphy_hw_stream_off,
|
||||
};
|
||||
|
||||
static const struct dphy_hw_drv_data rv1126b_csi2_dphy_hw_drv_data = {
|
||||
.hsfreq_ranges = rk3568_csi2_dphy_hw_hsfreq_ranges,
|
||||
.num_hsfreq_ranges = ARRAY_SIZE(rk3568_csi2_dphy_hw_hsfreq_ranges),
|
||||
.csi2dphy_regs = rv1126b_csi2dphy_regs,
|
||||
.num_csi2dphy_regs = ARRAY_SIZE(rv1126b_csi2dphy_regs),
|
||||
.grf_regs = rv1126b_grf_dphy_regs,
|
||||
.num_grf_regs = ARRAY_SIZE(rv1126b_grf_dphy_regs),
|
||||
.individual_init = rv1126b_csi2_dphy_hw_individual_init,
|
||||
.chip_id = CHIP_ID_RV1126B,
|
||||
.stream_on = csi2_dphy_hw_stream_on,
|
||||
.stream_off = csi2_dphy_hw_stream_off,
|
||||
};
|
||||
|
||||
static const struct of_device_id rockchip_csi2_dphy_hw_match_id[] = {
|
||||
{
|
||||
.compatible = "rockchip,rk3568-csi2-dphy-hw",
|
||||
@@ -1169,6 +1264,10 @@ static const struct of_device_id rockchip_csi2_dphy_hw_match_id[] = {
|
||||
.compatible = "rockchip,rk3576-csi2-dphy-hw",
|
||||
.data = &rk3576_csi2_dphy_hw_drv_data,
|
||||
},
|
||||
{
|
||||
.compatible = "rockchip,rv1126b-csi2-dphy-hw",
|
||||
.data = &rv1126b_csi2_dphy_hw_drv_data,
|
||||
},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rockchip_csi2_dphy_hw_match_id);
|
||||
|
||||
@@ -208,7 +208,8 @@ static int rockchip_csi2_dphy_attach_hw(struct csi2_dphy *dphy, int csi_idx, int
|
||||
dphy->csi_info.dphy_vendor[index] = PHY_VENDOR_INNO;
|
||||
mutex_unlock(&dphy_hw->mutex);
|
||||
}
|
||||
} else if (dphy->drv_data->chip_id == CHIP_ID_RK3562) {
|
||||
} else if (dphy->drv_data->chip_id == CHIP_ID_RK3562 ||
|
||||
dphy->drv_data->chip_id == CHIP_ID_RV1126B) {
|
||||
dphy_hw = dphy->dphy_hw_group[csi_idx / 2];
|
||||
mutex_lock(&dphy_hw->mutex);
|
||||
if (csi_idx == 0 || csi_idx == 2) {
|
||||
@@ -393,7 +394,8 @@ static int rockchip_csi2_dphy_detach_hw(struct csi2_dphy *dphy, int csi_idx, int
|
||||
rockchip_csi2_inno_phy_remove_dphy_dev(dphy, dphy_hw);
|
||||
mutex_unlock(&dphy_hw->mutex);
|
||||
}
|
||||
} else if (dphy->drv_data->chip_id == CHIP_ID_RK3562) {
|
||||
} else if (dphy->drv_data->chip_id == CHIP_ID_RK3562 ||
|
||||
dphy->drv_data->chip_id == CHIP_ID_RV1126B) {
|
||||
dphy_hw = (struct csi2_dphy_hw *)dphy->phy_hw[index];
|
||||
if (!dphy_hw) {
|
||||
dev_err(dphy->dev, "%s csi_idx %d detach hw failed\n",
|
||||
@@ -1070,6 +1072,13 @@ static struct dphy_drv_data rk3576_dphy_drv_data = {
|
||||
.num_samsung_phy = 1,
|
||||
};
|
||||
|
||||
static struct dphy_drv_data rv1126b_dphy_drv_data = {
|
||||
.dev_name = "csi2dphy",
|
||||
.chip_id = CHIP_ID_RV1126B,
|
||||
.num_inno_phy = 2,
|
||||
.num_samsung_phy = 0,
|
||||
};
|
||||
|
||||
static const struct of_device_id rockchip_csi2_dphy_match_id[] = {
|
||||
{
|
||||
.compatible = "rockchip,rk3568-csi2-dphy",
|
||||
@@ -1091,6 +1100,10 @@ static const struct of_device_id rockchip_csi2_dphy_match_id[] = {
|
||||
.compatible = "rockchip,rk3576-csi2-dphy",
|
||||
.data = &rk3576_dphy_drv_data,
|
||||
},
|
||||
{
|
||||
.compatible = "rockchip,rv1126b-csi2-dphy",
|
||||
.data = &rv1126b_dphy_drv_data,
|
||||
},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rockchip_csi2_dphy_match_id);
|
||||
|
||||
Reference in New Issue
Block a user