diff --git a/drivers/media/platform/qcom/camss/camss-csid-gen2.c b/drivers/media/platform/qcom/camss/camss-csid-gen2.c index 2a1746dcc1c5b..fd8d47a310dfb 100644 --- a/drivers/media/platform/qcom/camss/camss-csid-gen2.c +++ b/drivers/media/platform/qcom/camss/camss-csid-gen2.c @@ -183,6 +183,7 @@ static void __csid_configure_rx(struct csid_device *csid, val = (lane_cnt - 1) << CSI2_RX_CFG0_NUM_ACTIVE_LANES; val |= phy->lane_assign << CSI2_RX_CFG0_DL0_INPUT_SEL; val |= phy->csiphy_id << CSI2_RX_CFG0_PHY_NUM_SEL; + val |= csid->phy.phy_sel << CSI2_RX_CFG0_PHY_TYPE_SEL; writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG0); val = 1 << CSI2_RX_CFG1_PACKET_ECC_CORRECTION_EN; diff --git a/drivers/media/platform/qcom/camss/camss-csid-gen3.c b/drivers/media/platform/qcom/camss/camss-csid-gen3.c index 222765fe7914d..10d571127ff6d 100644 --- a/drivers/media/platform/qcom/camss/camss-csid-gen3.c +++ b/drivers/media/platform/qcom/camss/camss-csid-gen3.c @@ -66,6 +66,7 @@ #define CSI2_RX_CFG0_VC_MODE 3 #define CSI2_RX_CFG0_DL0_INPUT_SEL 4 #define CSI2_RX_CFG0_PHY_NUM_SEL 20 +#define CSI2_RX_CFG0_PHY_TYPE_SEL 24 #define CSI2_RX_CFG0_TPG_MUX_EN BIT(27) #define CSI2_RX_CFG0_TPG_MUX_SEL GENMASK(29, 28) @@ -115,6 +116,7 @@ static void __csid_configure_rx(struct csid_device *csid, camss = csid->camss; val = (phy->lane_cnt - 1) << CSI2_RX_CFG0_NUM_ACTIVE_LANES; + val |= phy->phy_sel << CSI2_RX_CFG0_PHY_TYPE_SEL; val |= phy->lane_assign << CSI2_RX_CFG0_DL0_INPUT_SEL; if (camss->tpg && csid->tpg_linked && diff --git a/drivers/media/platform/qcom/camss/camss-csid.c b/drivers/media/platform/qcom/camss/camss-csid.c index 48459b46a981b..c8cb6f1a3d3bc 100644 --- a/drivers/media/platform/qcom/camss/camss-csid.c +++ b/drivers/media/platform/qcom/camss/camss-csid.c @@ -540,14 +540,16 @@ static int csid_set_clock_rates(struct csid_device *csid) { struct device *dev = csid->camss->dev; const struct csid_format_info *fmt; + const bool cphy = (csid->phy.phy_sel == CSID_PHY_SEL_CPHY); + s64 link_freq; int i, j; int ret; fmt = csid_get_fmt_entry(csid->res->formats->formats, csid->res->formats->nformats, csid->fmt[MSM_CSIPHY_PAD_SINK].code); - link_freq = camss_get_link_freq(&csid->subdev.entity, fmt->bpp, - csid->phy.lane_cnt); + + link_freq = camss_get_link_freq(&csid->subdev.entity, fmt->bpp, csid->phy.lane_cnt, cphy); if (link_freq < 0) link_freq = 0; @@ -1291,6 +1293,11 @@ static int csid_link_setup(struct media_entity *entity, lane_cfg = &csiphy->cfg.csi2->lane_cfg; csid->phy.lane_cnt = lane_cfg->num_data; + if (lane_cfg->phy_cfg == V4L2_MBUS_CSI2_CPHY) + csid->phy.phy_sel = CSID_PHY_SEL_CPHY; + else + csid->phy.phy_sel = CSID_PHY_SEL_DPHY; + csid->phy.lane_assign = csid_get_lane_assign(lane_cfg, lane_cfg->num_data); csid->tpg_linked = false; } diff --git a/drivers/media/platform/qcom/camss/camss-csid.h b/drivers/media/platform/qcom/camss/camss-csid.h index 5296b10f6bac8..e65590b0df69f 100644 --- a/drivers/media/platform/qcom/camss/camss-csid.h +++ b/drivers/media/platform/qcom/camss/camss-csid.h @@ -44,6 +44,11 @@ enum csid_testgen_mode { CSID_PAYLOAD_MODE_NUM_SUPPORTED_GEN2 = 9, /* excluding disabled */ }; +enum csid_phy_sel { + CSID_PHY_SEL_DPHY = 0, + CSID_PHY_SEL_CPHY = 1 +}; + struct csid_format_info { u32 code; u8 data_type; @@ -70,6 +75,7 @@ struct csid_phy_config { u32 lane_assign; u32 en_vc; u8 need_vc_update; + enum csid_phy_sel phy_sel; }; struct csid_device; diff --git a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c index babf7e663bdd3..fe88f0db8e104 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c +++ b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c @@ -14,6 +14,7 @@ #include #include #include +#include #define CSIPHY_3PH_LNn_CFG1(n) (0x000 + 0x100 * (n)) #define CSIPHY_3PH_LNn_CFG1_SWI_REC_DLY_PRG (BIT(7) | BIT(6)) @@ -49,6 +50,19 @@ #define CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(offset, common_status_offset, n) \ ((offset) + (common_status_offset) + 0x4 * (n)) +#define CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(n) \ + (0x0100 + ((n) * 0x4)) +#define CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(n) \ + (0x0300 + ((n) * 0x4)) +#define CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(n) \ + (0x0500 + ((n) * 0x4)) +#define CSIPHY_LN9_CSI_3PH_CTRLn_ADDR(n) \ + (0x0900 + ((n) * 0x4)) +#define CSIPHY_LN10_CSI_3PH_CTRLn_ADDR(n) \ + (0x0A00 + ((n) * 0x4)) +#define CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(n) \ + (0x0B00 + ((n) * 0x4)) + #define CSIPHY_DEFAULT_PARAMS 0 #define CSIPHY_LANE_ENABLE 1 #define CSIPHY_SETTLE_CNT_LOWER_BYTE 2 @@ -58,6 +72,8 @@ #define CSIPHY_3PH_REGS 6 #define CSIPHY_SKEW_CAL 7 +#define CSIPHY_CPHY_DATA_RATE_DEFAULT_IDX 0 + struct csiphy_lane_regs { s32 reg_addr; s32 reg_data; @@ -144,7 +160,283 @@ csiphy_lane_regs lane_regs_sa8775p[] = { {0x0664, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, }; +/* GEN3 3PH sa8775p 1.5Gsps */ +/* 3 entries: 3 lanes (C-PHY) */ +static const struct +csiphy_lane_regs lane_regs_sa8775p_3ph[] = { + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(26), 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(23), 0xC8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(3), 0x08, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(34), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(35), 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(36), 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(6), 0x3E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(7), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(9), 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(11), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(17), 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(51), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(25), 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(55), 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(26), 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(23), 0xC8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(1), 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(3), 0x08, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(2), 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(5), 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(20), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(34), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(35), 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(36), 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(6), 0x3E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(7), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(8), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(9), 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(10), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(11), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(17), 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(24), 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(51), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(25), 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(55), 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(26), 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(23), 0xC8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(1), 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(3), 0x08, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(2), 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(5), 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(20), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(34), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(35), 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(36), 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(6), 0x3E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(7), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(8), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(9), 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(10), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(11), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(17), 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(24), 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(51), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(25), 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(55), 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN9_CSI_3PH_CTRLn_ADDR(33), 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN9_CSI_3PH_CTRLn_ADDR(34), 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN9_CSI_3PH_CTRLn_ADDR(32), 0x61, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN9_CSI_3PH_CTRLn_ADDR(44), 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN9_CSI_3PH_CTRLn_ADDR(45), 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN10_CSI_3PH_CTRLn_ADDR(33), 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN10_CSI_3PH_CTRLn_ADDR(34), 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN10_CSI_3PH_CTRLn_ADDR(32), 0x61, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN10_CSI_3PH_CTRLn_ADDR(44), 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN10_CSI_3PH_CTRLn_ADDR(45), 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(33), 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(34), 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(32), 0x61, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(44), 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(45), 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + +struct csiphy_lane_regs datarate_sa8775p_3ph_1p5Gsps[] = { + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(23), 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(26), 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(3), 0x24, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(23), 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(26), 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(3), 0x24, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(23), 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(26), 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(3), 0x24, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN9_CSI_3PH_CTRLn_ADDR(45), 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN10_CSI_3PH_CTRLn_ADDR(45), 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(45), 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + +struct csiphy_lane_regs datarate_sa8775p_3ph_1p7Gsps[] = { + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(23), 0x56, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(26), 0xAE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(27), 0x65, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(3), 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(23), 0x56, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(26), 0xAE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(27), 0x65, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(3), 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(23), 0x56, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(26), 0xAE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(27), 0x65, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(3), 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN9_CSI_3PH_CTRLn_ADDR(45), 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN10_CSI_3PH_CTRLn_ADDR(45), 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(45), 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + +struct csiphy_lane_regs datarate_sa8775p_3ph_2p5Gsps[] = { + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(26), 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(23), 0xC8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(3), 0x08, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(26), 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(23), 0xC8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(3), 0x08, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(26), 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(23), 0xC8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(3), 0x08, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN9_CSI_3PH_CTRLn_ADDR(45), 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN9_CSI_3PH_CTRLn_ADDR(34), 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN10_CSI_3PH_CTRLn_ADDR(45), 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN10_CSI_3PH_CTRLn_ADDR(34), 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(45), 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(34), 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + +struct csiphy_lane_regs datarate_sa8775p_3ph_3p5Gsps[] = { + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(26), 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(23), 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(3), 0x08, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(26), 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(23), 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(3), 0x08, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(26), 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(23), 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(3), 0x08, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN9_CSI_3PH_CTRLn_ADDR(45), 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN9_CSI_3PH_CTRLn_ADDR(34), 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN10_CSI_3PH_CTRLn_ADDR(45), 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN10_CSI_3PH_CTRLn_ADDR(34), 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(45), 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(34), 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + +struct csiphy_lane_regs datarate_sa8775p_3ph_4p5Gsps[] = { + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(26), 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(23), 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(3), 0x08, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(26), 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(23), 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(3), 0x08, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(26), 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(23), 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(3), 0x08, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN9_CSI_3PH_CTRLn_ADDR(45), 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN9_CSI_3PH_CTRLn_ADDR(34), 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN10_CSI_3PH_CTRLn_ADDR(45), 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN10_CSI_3PH_CTRLn_ADDR(34), 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(45), 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(34), 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + +static struct data_rate_reg_info data_rate_settings_sa8775p_3ph[] = { + { + /* 1.5 GSpS */ + .bandwidth = 1500000000, + .data_rate_reg_array_size = ARRAY_SIZE(datarate_sa8775p_3ph_1p5Gsps), + .data_rate_reg_array = datarate_sa8775p_3ph_1p5Gsps, + }, + { + /* 1.7 GSpS */ + .bandwidth = 1700000000, + .data_rate_reg_array_size = ARRAY_SIZE(datarate_sa8775p_3ph_1p7Gsps), + .data_rate_reg_array = datarate_sa8775p_3ph_1p7Gsps, + }, + { + /* 2.5 GSpS */ + .bandwidth = 2500000000, + .data_rate_reg_array_size = ARRAY_SIZE(datarate_sa8775p_3ph_2p5Gsps), + .data_rate_reg_array = datarate_sa8775p_3ph_2p5Gsps, + }, + { + /* 3.5 GSpS */ + .bandwidth = 3500000000, + .data_rate_reg_array_size = ARRAY_SIZE(datarate_sa8775p_3ph_3p5Gsps), + .data_rate_reg_array = datarate_sa8775p_3ph_3p5Gsps, + }, + { + /* 4.5 GSpS */ + .bandwidth = 4500000000, + .data_rate_reg_array_size = ARRAY_SIZE(datarate_sa8775p_3ph_4p5Gsps), + .data_rate_reg_array = datarate_sa8775p_3ph_4p5Gsps, + }, +}; + +struct csiphy_lane_regs datarate_sm8250_3ph_2p5Gsps[] = { + {0x144, 0x32, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x164, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x16C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x344, 0x32, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x364, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x36C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x544, 0x32, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x564, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x56C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + +struct csiphy_lane_regs datarate_sm8250_3ph_3p5Gsps[] = { + {0x144, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x164, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x16C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x9B4, 0x03, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x344, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x364, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x36C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xAB4, 0x03, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x544, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x564, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x56C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x03, 0x01, CSIPHY_DEFAULT_PARAMS}, +}; + +struct csiphy_lane_regs datarate_sm8250_3ph_4p5Gsps[] = { + {0x144, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x164, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x16C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x9B4, 0x02, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x344, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x364, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x36C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xAB4, 0x02, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x544, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x564, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x56C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x02, 0x01, CSIPHY_DEFAULT_PARAMS}, +}; + +static struct data_rate_reg_info data_rate_settings_sm8250_3ph[] = { + { + /* 2.5 GSpS */ + .bandwidth = 2500000000, + .data_rate_reg_array_size = ARRAY_SIZE(datarate_sm8250_3ph_2p5Gsps), + .data_rate_reg_array = datarate_sm8250_3ph_2p5Gsps, + }, + { + /* 3.5 GSpS */ + .bandwidth = 3500000000, + .data_rate_reg_array_size = ARRAY_SIZE(datarate_sm8250_3ph_3p5Gsps), + .data_rate_reg_array = datarate_sm8250_3ph_3p5Gsps, + }, + { + /* 4.5 GSpS */ + .bandwidth = 4500000000, + .data_rate_reg_array_size = ARRAY_SIZE(datarate_sm8250_3ph_4p5Gsps), + .data_rate_reg_array = datarate_sm8250_3ph_4p5Gsps, + }, +}; + /* GEN2 1.0 2PH */ +/* 5 entries: clock + 4 lanes */ static const struct csiphy_lane_regs lane_regs_sdm845[] = { {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -219,6 +511,71 @@ csiphy_lane_regs lane_regs_sdm845[] = { {0x0664, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, }; +/* GEN2 1.0 3PH */ +/* 3 entries: 3 lanes (C-PHY) */ +static const struct +csiphy_lane_regs lane_regs_sdm845_3ph[] = { + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(23), 0x63, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(26), 0xac, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(27), 0xa5, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(1), 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(3), 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(2), 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(5), 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(20), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(6), 0x3e, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(7), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(8), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(9), 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(10), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(11), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(17), 0x12, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(24), 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(51), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(25), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(55), 0x51, 0x00, CSIPHY_DEFAULT_PARAMS}, + + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(23), 0x63, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(26), 0xac, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(27), 0xa5, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(1), 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(3), 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(2), 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(5), 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(20), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(6), 0x3e, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(7), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(8), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(9), 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(10), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(11), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(17), 0x12, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(24), 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(51), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(25), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(55), 0x51, 0x00, CSIPHY_DEFAULT_PARAMS}, + + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(23), 0x63, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(26), 0xac, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(27), 0xa5, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(1), 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(3), 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(2), 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(5), 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(20), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(6), 0x3e, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(7), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(8), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(9), 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(10), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(11), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(17), 0x12, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(24), 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(51), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(25), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(55), 0x51, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + /* GEN2 1.1 2PH */ static const struct csiphy_lane_regs lane_regs_sc8280xp[] = { @@ -837,8 +1194,6 @@ static void csiphy_reset(struct csiphy_device *csiphy) writel_relaxed(0x1, csiphy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->offset, 0)); usleep_range(5000, 8000); - writel_relaxed(0x0, csiphy->base + - CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->offset, 0)); } static irqreturn_t csiphy_isr(int irq, void *dev) @@ -964,6 +1319,60 @@ static void csiphy_gen1_config_lanes(struct csiphy_device *csiphy, writel_relaxed(val, csiphy->base + CSIPHY_3PH_LNn_MISC1(l)); } +/* + * csiphy_cphy_data_rate_config - Apply data-rate specific C-PHY overrides + * + * Applied on top of the base lane_regs. Selects the first table entry whose + * bandwidth >= the data rate derived from @link_freq (highest entry if none + * qualifies, default entry if @link_freq is unknown) and writes its overrides. + */ +static void csiphy_cphy_data_rate_config(struct csiphy_device *csiphy, + struct data_rate_reg_info *settings, + size_t num_settings, + s64 link_freq, u8 settle_cnt) +{ + struct device *dev = csiphy->camss->dev; + const struct csiphy_lane_regs *r; + size_t idx, i; + u32 val; + + if (!settings || !num_settings) + return; + + if (!link_freq) { + /* Link frequency unknown; use the default (lowest) entry. */ + idx = CSIPHY_CPHY_DATA_RATE_DEFAULT_IDX; + } else { + /* First entry that satisfies the rate, else the highest. */ + for (idx = 0; idx < num_settings; idx++) { + if (settings[idx].bandwidth >= link_freq) + break; + } + } + + dev_dbg(dev, + "CSIPHY using specific bandwidth %llu bits/s (entry %zu) for link_freq %lld\n", + settings[idx].bandwidth, idx, link_freq); + + r = settings[idx].data_rate_reg_array; + for (i = 0; i < settings[idx].data_rate_reg_array_size; i++, r++) { + switch (r->csiphy_param_type) { + case CSIPHY_SETTLE_CNT_LOWER_BYTE: + val = settle_cnt & 0xff; + break; + case CSIPHY_SETTLE_CNT_HIGHER_BYTE: + val = (settle_cnt >> 8) & 0xff; + break; + default: + val = r->reg_data; + break; + } + writel_relaxed(val, csiphy->base + r->reg_addr); + if (r->delay_us) + udelay(r->delay_us); + } +} + static void csiphy_gen2_config_lanes(struct csiphy_device *csiphy, u8 settle_cnt) { @@ -993,13 +1402,22 @@ static void csiphy_gen2_config_lanes(struct csiphy_device *csiphy, static u8 csiphy_get_lane_mask(struct csiphy_lanes_cfg *lane_cfg) { - u8 lane_mask; - int i; + u8 lane_mask = 0; + u8 offset = 0; - lane_mask = CSIPHY_3PH_CMN_CSI_COMMON_CTRL5_CLK_ENABLE; + switch (lane_cfg->phy_cfg) { + case V4L2_MBUS_CSI2_CPHY: + offset = 1; + break; + case V4L2_MBUS_CSI2_DPHY: + lane_mask = CSIPHY_3PH_CMN_CSI_COMMON_CTRL5_CLK_ENABLE; + break; + default: + break; + } - for (i = 0; i < lane_cfg->num_data; i++) - lane_mask |= 1 << lane_cfg->data[i].pos; + for (int i = 0; i < lane_cfg->num_data; i++) + lane_mask |= BIT((lane_cfg->data[i].pos * 2) + offset); return lane_mask; } @@ -1035,16 +1453,103 @@ static void csiphy_lanes_enable(struct csiphy_device *csiphy, { struct csiphy_lanes_cfg *c = &cfg->csi2->lane_cfg; struct csiphy_device_regs *regs = csiphy->regs; + struct data_rate_reg_info *data_rate_settings = NULL; + size_t num_data_rate_settings = 0; u8 settle_cnt; u8 val; int i; - settle_cnt = csiphy_settle_cnt_calc(link_freq, csiphy->timer_clk_rate); + switch (csiphy->camss->res->version) { + case CAMSS_845: + if (c->phy_cfg == V4L2_MBUS_CSI2_DPHY) { + regs->lane_regs = &lane_regs_sdm845[0]; + regs->lane_array_size = ARRAY_SIZE(lane_regs_sdm845); + } else if (c->phy_cfg == V4L2_MBUS_CSI2_CPHY) { + regs->lane_regs = &lane_regs_sdm845_3ph[0]; + regs->lane_array_size = ARRAY_SIZE(lane_regs_sdm845_3ph); + } + break; + case CAMSS_2290: + case CAMSS_2390: + case CAMSS_6150: + if (c->phy_cfg == V4L2_MBUS_CSI2_DPHY) { + regs->lane_regs = &lane_regs_qcm2290[0]; + regs->lane_array_size = ARRAY_SIZE(lane_regs_qcm2290); + } else if (c->phy_cfg == V4L2_MBUS_CSI2_CPHY) { + regs->lane_regs = NULL; + regs->lane_array_size = 0; + } + break; + case CAMSS_7280: + case CAMSS_8250: + if (c->phy_cfg == V4L2_MBUS_CSI2_DPHY) { + regs->lane_regs = &lane_regs_sm8250[0]; + regs->lane_array_size = ARRAY_SIZE(lane_regs_sm8250); + } else if (c->phy_cfg == V4L2_MBUS_CSI2_CPHY) { + regs->lane_regs = NULL; + regs->lane_array_size = 0; + } + break; + case CAMSS_8280XP: + if (c->phy_cfg == V4L2_MBUS_CSI2_DPHY) { + regs->lane_regs = &lane_regs_sc8280xp[0]; + regs->lane_array_size = ARRAY_SIZE(lane_regs_sc8280xp); + } else if (c->phy_cfg == V4L2_MBUS_CSI2_CPHY) { + regs->lane_regs = NULL; + regs->lane_array_size = 0; + } + break; + case CAMSS_X1E80100: + case CAMSS_X1P42100: + if (c->phy_cfg == V4L2_MBUS_CSI2_DPHY) { + regs->lane_regs = &lane_regs_x1e80100[0]; + regs->lane_array_size = ARRAY_SIZE(lane_regs_x1e80100); + } else if (c->phy_cfg == V4L2_MBUS_CSI2_CPHY) { + regs->lane_regs = NULL; + regs->lane_array_size = 0; + } + break; + case CAMSS_8550: + if (c->phy_cfg == V4L2_MBUS_CSI2_DPHY) { + regs->lane_regs = &lane_regs_sm8550[0]; + regs->lane_array_size = ARRAY_SIZE(lane_regs_sm8550); + } else if (c->phy_cfg == V4L2_MBUS_CSI2_CPHY) { + regs->lane_regs = NULL; + regs->lane_array_size = 0; + } + break; + case CAMSS_8650: + if (c->phy_cfg == V4L2_MBUS_CSI2_DPHY) { + regs->lane_regs = &lane_regs_sm8650[0]; + regs->lane_array_size = ARRAY_SIZE(lane_regs_sm8650); + } else if (c->phy_cfg == V4L2_MBUS_CSI2_CPHY) { + regs->lane_regs = NULL; + regs->lane_array_size = 0; + } + break; + break; + case CAMSS_8300: + case CAMSS_8775P: + if (c->phy_cfg == V4L2_MBUS_CSI2_CPHY) { + regs->lane_regs = &lane_regs_sa8775p_3ph[0]; + regs->lane_array_size = ARRAY_SIZE(lane_regs_sa8775p_3ph); + data_rate_settings = data_rate_settings_sa8775p_3ph; + num_data_rate_settings = ARRAY_SIZE(data_rate_settings_sa8775p_3ph); + } else { + regs->lane_regs = &lane_regs_sa8775p[0]; + regs->lane_array_size = ARRAY_SIZE(lane_regs_sa8775p); + } + break; + default: + break; + } + + if (!regs->lane_regs) + WARN_ONCE(1, "Missing lane_regs definition!\n"); - val = CSIPHY_3PH_CMN_CSI_COMMON_CTRL5_CLK_ENABLE; - for (i = 0; i < c->num_data; i++) - val |= BIT(c->data[i].pos * 2); + settle_cnt = csiphy_settle_cnt_calc(link_freq, csiphy->timer_clk_rate); + val = csiphy_get_lane_mask(c); writel_relaxed(val, csiphy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->offset, 5)); @@ -1052,9 +1557,37 @@ static void csiphy_lanes_enable(struct csiphy_device *csiphy, writel_relaxed(val, csiphy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->offset, 6)); - val = 0x02; - writel_relaxed(val, csiphy->base + - CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->offset, 7)); + switch (csiphy->camss->res->version) { + case CAMSS_8300: + case CAMSS_8775P: + if (c->phy_cfg == V4L2_MBUS_CSI2_CPHY) { + val = 0x5A; + writel_relaxed(val, csiphy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->offset, 7)); + val = 0xE; + writel_relaxed(val, csiphy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->offset, 0)); + } else { + val = 0x02; + writel_relaxed(val, csiphy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->offset, 7)); + writel_relaxed(val, csiphy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->offset, 0)); + } + break; + case CAMSS_7280: + case CAMSS_8250: + case CAMSS_8280XP: + case CAMSS_845: + default: + val = 0x02; + writel_relaxed(val, csiphy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->offset, 7)); + val = 0x0; + writel_relaxed(val, csiphy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->offset, 0)); + break; + } val = 0x00; writel_relaxed(val, csiphy->base + @@ -1065,6 +1598,15 @@ static void csiphy_lanes_enable(struct csiphy_device *csiphy, else csiphy_gen1_config_lanes(csiphy, cfg, settle_cnt); + /* + * For C-PHY platforms with a data-rate settings table, apply the + * data-rate specific overrides on top of the base lane_regs config. + */ + if (c->phy_cfg == V4L2_MBUS_CSI2_CPHY && data_rate_settings) + csiphy_cphy_data_rate_config(csiphy, data_rate_settings, + num_data_rate_settings, + link_freq, settle_cnt); + /* IRQ_MASK registers - disable all interrupts */ for (i = 11; i < 22; i++) { writel_relaxed(0, csiphy->base + @@ -1094,51 +1636,17 @@ static int csiphy_init(struct csiphy_device *csiphy) return -ENOMEM; csiphy->regs = regs; - regs->offset = 0x800; regs->common_status_offset = 0xb0; switch (csiphy->camss->res->version) { - case CAMSS_845: - regs->lane_regs = &lane_regs_sdm845[0]; - regs->lane_array_size = ARRAY_SIZE(lane_regs_sdm845); - break; - case CAMSS_2290: - case CAMSS_2390: - case CAMSS_6150: - regs->lane_regs = &lane_regs_qcm2290[0]; - regs->lane_array_size = ARRAY_SIZE(lane_regs_qcm2290); - break; - case CAMSS_7280: - case CAMSS_8250: - regs->lane_regs = &lane_regs_sm8250[0]; - regs->lane_array_size = ARRAY_SIZE(lane_regs_sm8250); - break; - case CAMSS_8280XP: - regs->lane_regs = &lane_regs_sc8280xp[0]; - regs->lane_array_size = ARRAY_SIZE(lane_regs_sc8280xp); - break; case CAMSS_X1E80100: case CAMSS_X1P42100: - regs->lane_regs = &lane_regs_x1e80100[0]; - regs->lane_array_size = ARRAY_SIZE(lane_regs_x1e80100); - regs->offset = 0x1000; - break; case CAMSS_8550: - regs->lane_regs = &lane_regs_sm8550[0]; - regs->lane_array_size = ARRAY_SIZE(lane_regs_sm8550); - regs->offset = 0x1000; - break; case CAMSS_8650: - regs->lane_regs = &lane_regs_sm8650[0]; - regs->lane_array_size = ARRAY_SIZE(lane_regs_sm8650); regs->offset = 0x1000; break; - case CAMSS_8300: - case CAMSS_8775P: - regs->lane_regs = &lane_regs_sa8775p[0]; - regs->lane_array_size = ARRAY_SIZE(lane_regs_sa8775p); - break; default: + regs->offset = 0x800; break; } diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.c b/drivers/media/platform/qcom/camss/camss-csiphy.c index b9f7d6573a0f0..66ae6d9610661 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy.c +++ b/drivers/media/platform/qcom/camss/camss-csiphy.c @@ -146,8 +146,9 @@ static int csiphy_set_clock_rates_legacy(struct csiphy_device *csiphy) u8 bpp = csiphy_get_bpp(csiphy->res->formats->formats, csiphy->res->formats->nformats, csiphy->fmt[MSM_CSIPHY_PAD_SINK].code); u8 num_lanes = csiphy->cfg.csi2->lane_cfg.num_data; + const bool cphy = (csiphy->cfg.csi2->lane_cfg.phy_cfg == V4L2_MBUS_CSI2_CPHY); - link_freq = camss_get_link_freq(&csiphy->subdev.entity, bpp, num_lanes); + link_freq = camss_get_link_freq(&csiphy->subdev.entity, bpp, num_lanes, cphy); if (link_freq < 0) link_freq = 0; @@ -272,9 +273,10 @@ static int csiphy_stream_on_legacy(struct csiphy_device *csiphy) u8 bpp = csiphy_get_bpp(csiphy->res->formats->formats, csiphy->res->formats->nformats, csiphy->fmt[MSM_CSIPHY_PAD_SINK].code); u8 num_lanes = csiphy->cfg.csi2->lane_cfg.num_data; + const bool cphy = (csiphy->cfg.csi2->lane_cfg.phy_cfg == V4L2_MBUS_CSI2_CPHY); u8 val; - link_freq = camss_get_link_freq(&csiphy->subdev.entity, bpp, num_lanes); + link_freq = camss_get_link_freq(&csiphy->subdev.entity, bpp, num_lanes, cphy); if (link_freq < 0) { dev_err(csiphy->camss->dev, @@ -331,13 +333,14 @@ static int csiphy_stream_on(struct csiphy_device *csiphy) union phy_configure_opts dphy_opts = { 0 }; struct device *dev = csiphy->camss->dev; u8 num_lanes = lncfg->num_data; + const bool cphy = (lncfg->phy_cfg == V4L2_MBUS_CSI2_CPHY); s64 link_freq; int i; int ret; dphy_cfg = &dphy_opts.mipi_dphy; - link_freq = camss_get_link_freq(&csiphy->subdev.entity, bpp, num_lanes); + link_freq = camss_get_link_freq(&csiphy->subdev.entity, bpp, num_lanes, cphy); if (link_freq < 0) { dev_err(dev, diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.h b/drivers/media/platform/qcom/camss/camss-csiphy.h index 1879826034aac..805f040290f62 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy.h +++ b/drivers/media/platform/qcom/camss/camss-csiphy.h @@ -31,11 +31,13 @@ struct csiphy_lane { /** * struct csiphy_lanes_cfg - CSIPHY lanes configuration + * @phy_cfg: interface selection (C-PHY or D-PHY) * @num_data: number of data lanes * @data: data lanes configuration * @clk: clock lane configuration (only for D-PHY) */ struct csiphy_lanes_cfg { + enum v4l2_mbus_type phy_cfg; int num_data; struct csiphy_lane *data; struct csiphy_lane clk; @@ -61,6 +63,12 @@ struct csiphy_formats { const struct csiphy_format_info *formats; }; +struct data_rate_reg_info { + u64 bandwidth; + ssize_t data_rate_reg_array_size; + struct csiphy_lane_regs *data_rate_reg_array; +}; + struct csiphy_device; struct csiphy_hw_ops { diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 3a45271c33a62..ee592a1633552 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -33,6 +33,14 @@ #define CAMSS_CLOCK_MARGIN_NUMERATOR 105 #define CAMSS_CLOCK_MARGIN_DENOMINATOR 100 +/* + * C-PHY encodes data by 16/7 ~ 2.28 bits/symbol + * D-PHY doesn't encode data, thus 16/16 = 1 b/s + */ +#define CAMSS_COMMON_PHY_DIVIDENT 16 +#define CAMSS_CPHY_DIVISOR 7 +#define CAMSS_DPHY_DIVISOR 16 + static const struct parent_dev_ops vfe_parent_dev_ops; static const struct camss_subdev_resources csiphy_res_8x16[] = { @@ -4434,19 +4442,22 @@ struct media_pad *camss_find_sensor_pad(struct media_entity *entity) * @entity: Media entity in the current pipeline * @bpp: Number of bits per pixel for the current format * @lanes: Number of lanes in the link to the sensor + * @cphy: If C-PHY encoding is used. * * Return link frequency on success or a negative error code otherwise */ s64 camss_get_link_freq(struct media_entity *entity, unsigned int bpp, - unsigned int lanes) + unsigned int lanes, const bool cphy) { struct media_pad *sensor_pad; + unsigned int div = lanes * 2 * (cphy ? CAMSS_CPHY_DIVISOR : + CAMSS_DPHY_DIVISOR); sensor_pad = camss_find_sensor_pad(entity); if (!sensor_pad) return -ENODEV; - return v4l2_get_link_freq(sensor_pad, bpp, 2 * lanes); + return v4l2_get_link_freq(sensor_pad, CAMSS_COMMON_PHY_DIVIDENT * bpp, div); } /* @@ -4556,7 +4567,9 @@ static int camss_parse_endpoint_node(struct device *dev, { struct csiphy_lanes_cfg *lncfg = &csd->interface.csi2.lane_cfg; struct v4l2_mbus_config_mipi_csi2 *mipi_csi2; - struct v4l2_fwnode_endpoint vep = { { 0 } }; + struct v4l2_fwnode_endpoint vep = { .bus_type = V4L2_MBUS_UNKNOWN }; + struct v4l2_fwnode_endpoint remote_vep = { .bus_type = V4L2_MBUS_UNKNOWN }; + struct fwnode_handle *remote_ep; unsigned int i; int ret; @@ -4564,21 +4577,49 @@ static int camss_parse_endpoint_node(struct device *dev, if (ret) return ret; - /* - * Most SoCs support both D-PHY and C-PHY standards, but currently only - * D-PHY is supported in the driver. - */ - if (vep.bus_type != V4L2_MBUS_CSI2_DPHY) { + switch (vep.bus_type) { + case V4L2_MBUS_CSI2_CPHY: + case V4L2_MBUS_CSI2_DPHY: + break; + default: dev_err(dev, "Unsupported bus type %d\n", vep.bus_type); return -EINVAL; } + /* Get the remote (sensor) endpoint handle, e.g. imx686_ep1 */ + remote_ep = fwnode_graph_get_remote_endpoint(ep); + if (!remote_ep) { + dev_dbg(dev, "No remote endpoint found for %pfw\n", ep); + return -ENODEV; + } + + /* Parse the remote bus type and release the handle */ + ret = v4l2_fwnode_endpoint_parse(remote_ep, &remote_vep); + fwnode_handle_put(remote_ep); + if (ret) { + dev_dbg(dev, "Failed to parse remote endpoint\n"); + return ret; + } + + /* The local (CSIPHY) and remote (sensor) ends must agree */ + if (vep.bus_type != remote_vep.bus_type) { + dev_dbg(dev, "Bus type mismatch! Local (CSI-PHY): %u, Remote (Sensor): %u\n", + vep.bus_type, remote_vep.bus_type); + return -EINVAL; + } + + dev_dbg(dev, "Verified link: both ends use bus-type %u\n", vep.bus_type); + csd->interface.csiphy_id = vep.base.port; mipi_csi2 = &vep.bus.mipi_csi2; - lncfg->clk.pos = mipi_csi2->clock_lane; - lncfg->clk.pol = mipi_csi2->lane_polarities[0]; lncfg->num_data = mipi_csi2->num_data_lanes; + lncfg->phy_cfg = vep.bus_type; + + if (lncfg->phy_cfg != V4L2_MBUS_CSI2_CPHY) { + lncfg->clk.pos = mipi_csi2->clock_lane; + lncfg->clk.pol = mipi_csi2->lane_polarities[0]; + } lncfg->data = devm_kcalloc(dev, lncfg->num_data, sizeof(*lncfg->data), diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h index 0e49aaba3438e..fc79e24f98f9e 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -171,7 +171,7 @@ int camss_enable_clocks(int nclocks, struct camss_clock *clock, void camss_disable_clocks(int nclocks, struct camss_clock *clock); struct media_pad *camss_find_sensor_pad(struct media_entity *entity); s64 camss_get_link_freq(struct media_entity *entity, unsigned int bpp, - unsigned int lanes); + unsigned int lanes, const bool cphy); int camss_get_pixel_clock(struct media_entity *entity, u64 *pixel_clock); int camss_pm_domain_on(struct camss *camss, int id); void camss_pm_domain_off(struct camss *camss, int id);