* [PATCH RFC 0/6] phy/media: Add generic MIPI C-PHY support to CSI-2 stack
@ 2026-10-17 17:13 ` Nihal Kumar Gupta
2026-10-17 17:13 ` [PATCH RFC 1/6] phy: core: Add MIPI C-PHY configurations Nihal Kumar Gupta
` (6 more replies)
0 siblings, 7 replies; 9+ messages in thread
From: Nihal Kumar Gupta @ 2026-10-17 17:13 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Manivannan Sadhasivam,
Bryan O'Donoghue, Vladimir Zapolskiy, Loic Poulain,
Mauro Carvalho Chehab, Bryan O'Donoghue
Cc: Vikram Sharma, linux-phy, linux-kernel, linux-media,
linux-arm-msm, Nihal Kumar Gupta
George posted a C-PHY series [1] which we are currently reviewing.
As discussed with Bryan, this series shares our independent
implementation so the approaches can be compared.
Two aspects covered here are not in [1]:
- Settle count calculation derived from sensor-reported T_PREPARE and
T_PREAMBLE timing via get_mbus_config(). [1] left this as an open
question.
- Data rate based register sequence selection using effective bit
rate (link_freq * 32 / 7). [1] noted downstream does this but
deferred it; this series implements it.
MIPI CSI-2 operates over two physical layer variants. D-PHY uses a
dedicated differential clock lane with up to four data lanes. C-PHY
encodes the clock within the data stream across up to three wire
trios, eliminating the dedicated clock lane.
Patch 1 extends the generic PHY framework with PHY_MODE_MIPI_CPHY
and struct phy_configure_opts_mipi_cphy.
Patch 2 adds t_prepare_ns and t_preamble_ns fields to the CSI-2
media bus configuration and extends CAMSS to forward them to the PHY
provider for settle count calculation. Sensor drivers must implement
get_mbus_config() and return non-zero values in nanoseconds; stream-on
returns -EINVAL otherwise. The strictness is deliberate: C-PHY settle
timing is symbol-rate-range specific and no safe value can be derived
from link frequency alone. A conservative fallback could be added if
reviewers prefer.
Patches 3-6 extend the Qualcomm CSIPHY driver: refactor D-PHY
register storage to accommodate C-PHY, accept C-PHY mode with
multiple data rate table selection, compute settle count, and add
lane power mask support for C-PHY trios.
C-PHY encodes 16 bits per 7 symbols, so the effective bit rate is:
bit_rate = link_freq * 2 * 16 / 7 = link_freq * 32 / 7
where link_freq is symbol_rate / 2 as reported by the sensor via
get_mbus_config(). The rate-table entry whose bandwidth first meets
or exceeds bit_rate is selected.
The settle count defines how many timer clock cycles the CSIPHY
receiver waits before scanning for C-PHY sync. It is computed from
the sensor's T_PREPARE and T_PREAMBLE timing. The /3 factor reflects
that C-PHY distributes the preamble sequence across three trios:
settle_cnt = (t_prepare_ns + t_preamble_ns / 3) * timer_clk_rate / 1e9
D-PHY settle count is unchanged from before this series.
[1] https://lore.kernel.org/all/20261016-x1e-cphy-rfc-v3-0-40a346a72153@gmail.com/
Signed-off-by: Nihal Kumar Gupta <nihal.gupta@oss.qualcomm.com>
---
Nihal Kumar Gupta (6):
phy: core: Add MIPI C-PHY configurations
media: qcom: camss: Add C-PHY timing fields and get config from sensor
phy: qcom: mipi-csi2: Split D-PHY register settings
phy: qcom: mipi-csi2: Accept C-PHY mode and add register sequence
phy: qcom: mipi-csi2: Add C-PHY settle calculation
phy: qcom: mipi-csi2: Add lane mask calculation for C-PHY
drivers/media/platform/qcom/camss/camss-csiphy.c | 90 +++++++++---
drivers/media/platform/qcom/camss/camss-csiphy.h | 2 +
drivers/media/platform/qcom/camss/camss.c | 8 +-
drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c | 159 +++++++++++++++++----
drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c | 51 +++++--
drivers/phy/qualcomm/phy-qcom-mipi-csi2.h | 25 +++-
include/linux/phy/phy.h | 47 ++++++
include/media/v4l2-mediabus.h | 2 +
8 files changed, 315 insertions(+), 69 deletions(-)
---
base-commit: 2efb7a11f1aa4d2dc285fe2680cca22cb9f72f64
change-id: 20261017-cphy_support-2ce4d656e631
Best regards,
--
Nihal Kumar Gupta <nihal.gupta@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH RFC 1/6] phy: core: Add MIPI C-PHY configurations
2026-10-17 17:13 ` [PATCH RFC 0/6] phy/media: Add generic MIPI C-PHY support to CSI-2 stack Nihal Kumar Gupta
@ 2026-10-17 17:13 ` Nihal Kumar Gupta
2026-10-17 17:13 ` [PATCH RFC 2/6] media: qcom: camss: Add C-PHY timing fields and get config from sensor Nihal Kumar Gupta
` (5 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Nihal Kumar Gupta @ 2026-10-17 17:13 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Manivannan Sadhasivam,
Bryan O'Donoghue, Vladimir Zapolskiy, Loic Poulain,
Mauro Carvalho Chehab, Bryan O'Donoghue
Cc: Vikram Sharma, linux-phy, linux-kernel, linux-media,
linux-arm-msm, Nihal Kumar Gupta
MIPI CSI-2 receivers can be connected through C-PHY as well as D-PHY.
C-PHY uses trios instead of lanes and needs mode-specific timings passed
to the PHY provider.
Add PHY_MODE_MIPI_CPHY and C-PHY configure option carrying the link rate,
trio count and C-PHY prepare/preamble timing.
Signed-off-by: Nihal Kumar Gupta <nihal.gupta@oss.qualcomm.com>
---
include/linux/phy/phy.h | 47 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
index c480d6cb42c500a295eef3bdf42fbc6d36f54bf8..c3784b679f3a26686324286d407cfa9d258579f1 100644
--- a/include/linux/phy/phy.h
+++ b/include/linux/phy/phy.h
@@ -47,6 +47,7 @@ enum phy_mode {
PHY_MODE_DP,
PHY_MODE_HDMI,
PHY_MODE_TBT,
+ PHY_MODE_MIPI_CPHY,
};
enum phy_media {
@@ -64,11 +65,56 @@ union phy_notify {
enum phy_ufs_state ufs_state;
};
+/**
+ * struct phy_configure_opts_mipi_cphy - MIPI C-PHY configuration set
+ *
+ * This structure is used to represent the configuration state of a
+ * MIPI C-PHY phy.
+ */
+struct phy_configure_opts_mipi_cphy {
+ /**
+ * @symbol_rate:
+ *
+ * Symbol rate per trio, in symbols per second.
+ */
+ u64 symbol_rate;
+
+ /**
+ * @trios:
+ *
+ * Number of active C-PHY trios.
+ *
+ * Minimum value: 1
+ * Maximum value: 3
+ */
+ unsigned int trios;
+
+ /**
+ * @t_prepare_ns:
+ *
+ * C-PHY T_PREPARE timing value, in nanoseconds.
+ * Time the transmitter drives the LP-00 state before
+ * starting the HS preamble sequence.
+ */
+ u32 t_prepare_ns;
+
+ /**
+ * @t_preamble_ns:
+ *
+ * C-PHY T_PREAMBLE timing value, in nanoseconds.
+ * Duration of the HS preamble sequence transmitted
+ * before the first payload symbol.
+ */
+ u32 t_preamble_ns;
+};
+
/**
* union phy_configure_opts - Opaque generic phy configuration
*
* @mipi_dphy: Configuration set applicable for phys supporting
* the MIPI_DPHY phy mode.
+ * @mipi_cphy: Configuration set applicable for phys supporting
+ * the MIPI_CPHY phy mode.
* @dp: Configuration set applicable for phys supporting
* the DisplayPort protocol.
* @lvds: Configuration set applicable for phys supporting
@@ -78,6 +124,7 @@ union phy_notify {
*/
union phy_configure_opts {
struct phy_configure_opts_mipi_dphy mipi_dphy;
+ struct phy_configure_opts_mipi_cphy mipi_cphy;
struct phy_configure_opts_dp dp;
struct phy_configure_opts_lvds lvds;
struct phy_configure_opts_hdmi hdmi;
--
2.34.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH RFC 2/6] media: qcom: camss: Add C-PHY timing fields and get config from sensor
2026-10-17 17:13 ` [PATCH RFC 0/6] phy/media: Add generic MIPI C-PHY support to CSI-2 stack Nihal Kumar Gupta
2026-10-17 17:13 ` [PATCH RFC 1/6] phy: core: Add MIPI C-PHY configurations Nihal Kumar Gupta
@ 2026-10-17 17:13 ` Nihal Kumar Gupta
2026-10-17 17:13 ` [PATCH RFC 3/6] phy: qcom: mipi-csi2: Split D-PHY register settings Nihal Kumar Gupta
` (4 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Nihal Kumar Gupta @ 2026-10-17 17:13 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Manivannan Sadhasivam,
Bryan O'Donoghue, Vladimir Zapolskiy, Loic Poulain,
Mauro Carvalho Chehab, Bryan O'Donoghue
Cc: Vikram Sharma, linux-phy, linux-kernel, linux-media,
linux-arm-msm, Nihal Kumar Gupta
C-PHY settle count is derived from the T_PREPARE and T_PREAMBLE link
timing parameters reported by the transmitter. Add C-PHY prepare and
preamble timing fields to the CSI-2 media bus configuration.
The endpoint bus type already describes whether the connected CSI-2 link
uses D-PHY or C-PHY.
Accept C-PHY endpoints, store the parsed CSI-2 PHY type and query the
remote sensor media bus configuration for C-PHY links. Pass the reported
link frequency and timing to the generic PHY while keeping the existing
D-PHY fallback path.
Signed-off-by: Nihal Kumar Gupta <nihal.gupta@oss.qualcomm.com>
---
drivers/media/platform/qcom/camss/camss-csiphy.c | 90 +++++++++++++++++++-----
drivers/media/platform/qcom/camss/camss-csiphy.h | 2 +
drivers/media/platform/qcom/camss/camss.c | 8 +--
include/media/v4l2-mediabus.h | 2 +
4 files changed, 79 insertions(+), 23 deletions(-)
diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.c b/drivers/media/platform/qcom/camss/camss-csiphy.c
index f99eea2ef2289cbee404808348c06968350dc4ac..ed2318d76987d6a9ae7e185d00e258d49d0c79a4 100644
--- a/drivers/media/platform/qcom/camss/camss-csiphy.c
+++ b/drivers/media/platform/qcom/camss/camss-csiphy.c
@@ -313,6 +313,29 @@ static void csiphy_stream_off_legacy(struct csiphy_device *csiphy)
csiphy->res->hw_ops->lanes_disable(csiphy, &csiphy->cfg);
}
+static int csiphy_get_remote_mbus_config(struct csiphy_device *csiphy,
+ struct v4l2_mbus_config *cfg)
+{
+ struct media_pad *remote;
+ struct v4l2_subdev *remote_sd;
+ int ret;
+
+ remote = media_pad_remote_pad_first(&csiphy->pads[MSM_CSIPHY_PAD_SINK]);
+ if (!remote)
+ return -ENOLINK;
+
+ remote_sd = media_entity_to_v4l2_subdev(remote->entity);
+ if (!remote_sd)
+ return -EINVAL;
+
+ memset(cfg, 0, sizeof(*cfg));
+ ret = v4l2_subdev_call(remote_sd, pad, get_mbus_config,
+ remote->index, cfg);
+ if (ret == -ENOIOCTLCMD)
+ return -EOPNOTSUPP;
+
+ return ret;
+}
/*
* csiphy_stream_on - Enable streaming on CSIPHY module
* @csiphy: CSIPHY device
@@ -324,43 +347,74 @@ static void csiphy_stream_off_legacy(struct csiphy_device *csiphy)
*/
static int csiphy_stream_on(struct csiphy_device *csiphy)
{
+ struct v4l2_mbus_config mbus_cfg = { };
u8 bpp = csiphy_get_bpp(csiphy->res->formats->formats, csiphy->res->formats->nformats,
csiphy->fmt[MSM_CSIPHY_PAD_SINK].code);
struct csiphy_lanes_cfg *lncfg = &csiphy->cfg.csi2->lane_cfg;
- struct phy_configure_opts_mipi_dphy *dphy_cfg;
- union phy_configure_opts dphy_opts = { 0 };
+ union phy_configure_opts opts = { 0 };
+ enum phy_mode mode = PHY_MODE_INVALID;
struct device *dev = csiphy->camss->dev;
u8 num_lanes = lncfg->num_data;
s64 link_freq;
int ret;
- dphy_cfg = &dphy_opts.mipi_dphy;
-
- link_freq = camss_get_link_freq(&csiphy->subdev.entity, bpp, num_lanes);
+ ret = csiphy_get_remote_mbus_config(csiphy, &mbus_cfg);
+ if (ret && ret != -EOPNOTSUPP)
+ return ret;
- if (link_freq <= 0) {
- dev_err(dev,
- "Cannot get CSI2 transmitter's link frequency\n");
- return -EINVAL;
+ if (ret == -EOPNOTSUPP && lncfg->phy_type == V4L2_MBUS_CSI2_CPHY) {
+ dev_err(dev, "C-PHY transmitter does not report media bus configuration\n");
+ return ret;
}
- ret = phy_mipi_dphy_get_default_config_for_hsclk(link_freq, num_lanes,
- dphy_cfg);
- if (ret < 0) {
- dev_err(dev, "Invalid config for link frequency %lld\n",
- link_freq);
- return ret;
+ if (!ret && mbus_cfg.type == V4L2_MBUS_CSI2_CPHY) {
+ struct phy_configure_opts_mipi_cphy *cphy = &opts.mipi_cphy;
+
+ link_freq = mbus_cfg.link_freq;
+ if (link_freq <= 0) {
+ dev_err(dev,
+ "Cannot get CSI2 transmitter's link frequency\n");
+ return -EINVAL;
+ }
+
+ cphy->symbol_rate = link_freq * 2;
+ cphy->trios = num_lanes;
+ cphy->t_prepare_ns = mbus_cfg.bus.mipi_csi2.t_prepare_ns;
+ cphy->t_preamble_ns = mbus_cfg.bus.mipi_csi2.t_preamble_ns;
+
+ mode = PHY_MODE_MIPI_CPHY;
+ } else if (ret || mbus_cfg.type == V4L2_MBUS_CSI2_DPHY) {
+ struct phy_configure_opts_mipi_dphy *dphy = &opts.mipi_dphy;
+
+ link_freq = camss_get_link_freq(&csiphy->subdev.entity, bpp, num_lanes);
+ if (link_freq <= 0) {
+ dev_err(dev,
+ "Cannot get CSI2 transmitter's link frequency\n");
+ return -EINVAL;
+ }
+
+ ret = phy_mipi_dphy_get_default_config_for_hsclk(link_freq, num_lanes,
+ dphy);
+ if (ret < 0) {
+ dev_err(dev, "Invalid config for link frequency %lld\n",
+ link_freq);
+ return ret;
+ }
+ mode = PHY_MODE_MIPI_DPHY;
+ } else {
+ dev_err(dev, "Unsupported mbus type %u\n", mbus_cfg.type);
+ return -EINVAL;
}
- ret = phy_set_mode(csiphy->phy, PHY_MODE_MIPI_DPHY);
+ ret = phy_set_mode(csiphy->phy, mode);
if (ret) {
dev_err(dev, "Failed to set phy mode\n");
return ret;
}
- ret = phy_configure(csiphy->phy, &dphy_opts);
+ ret = phy_configure(csiphy->phy, &opts);
if (ret) {
- dev_err(dev, "failed to configure MIPI D-PHY\n");
+ dev_err(dev, "failed to configure MIPI CSI-2 PHY\n");
goto error;
}
diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.h b/drivers/media/platform/qcom/camss/camss-csiphy.h
index 8c3319f2ca1cfdef4c0185deed2805854ac81703..a13cfaf3796106d421c8d711308d3fb3fb9259a8 100644
--- a/drivers/media/platform/qcom/camss/camss-csiphy.h
+++ b/drivers/media/platform/qcom/camss/camss-csiphy.h
@@ -35,11 +35,13 @@ struct csiphy_lane {
* @num_data: number of data lanes
* @data: data lanes configuration
* @clk: clock lane configuration (only for D-PHY)
+ * @phy_type: CSI-2 PHY bus type
*/
struct csiphy_lanes_cfg {
int num_data;
struct csiphy_lane *data;
struct csiphy_lane clk;
+ enum v4l2_mbus_type phy_type;
};
struct csiphy_csi2_cfg {
diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c
index c54185c93a8a98fc6a20fdb8e0f9f8e61bc41058..f61a9c242ef46f968ecc22dddd16a2e96465ca65 100644
--- a/drivers/media/platform/qcom/camss/camss.c
+++ b/drivers/media/platform/qcom/camss/camss.c
@@ -4694,11 +4694,8 @@ 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) {
+ if (vep.bus_type != V4L2_MBUS_CSI2_DPHY &&
+ vep.bus_type != V4L2_MBUS_CSI2_CPHY) {
dev_err(dev, "Unsupported bus type %d\n", vep.bus_type);
return -EINVAL;
}
@@ -4706,6 +4703,7 @@ static int camss_parse_endpoint_node(struct device *dev,
csd->interface.csiphy_id = vep.base.port;
mipi_csi2 = &vep.bus.mipi_csi2;
+ lncfg->phy_type = vep.bus_type;
lncfg->clk.pos = mipi_csi2->clock_lane;
lncfg->clk.pol = mipi_csi2->lane_polarities[0];
lncfg->num_data = mipi_csi2->num_data_lanes;
diff --git a/include/media/v4l2-mediabus.h b/include/media/v4l2-mediabus.h
index 24c738cd78940fa7f6118d78595fe221689a39e7..42543ec98a839567c21485d3e97f875b8a081100 100644
--- a/include/media/v4l2-mediabus.h
+++ b/include/media/v4l2-mediabus.h
@@ -109,6 +109,8 @@ struct v4l2_mbus_config_mipi_csi2 {
unsigned char num_data_lanes;
bool lane_polarities[1 + V4L2_MBUS_CSI2_MAX_DATA_LANES];
enum v4l2_mbus_csi2_cphy_line_orders_type line_orders[V4L2_MBUS_CSI2_MAX_DATA_LANES];
+ u32 t_prepare_ns;
+ u32 t_preamble_ns;
};
/**
--
2.34.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH RFC 3/6] phy: qcom: mipi-csi2: Split D-PHY register settings
2026-10-17 17:13 ` [PATCH RFC 0/6] phy/media: Add generic MIPI C-PHY support to CSI-2 stack Nihal Kumar Gupta
2026-10-17 17:13 ` [PATCH RFC 1/6] phy: core: Add MIPI C-PHY configurations Nihal Kumar Gupta
2026-10-17 17:13 ` [PATCH RFC 2/6] media: qcom: camss: Add C-PHY timing fields and get config from sensor Nihal Kumar Gupta
@ 2026-10-17 17:13 ` Nihal Kumar Gupta
2026-10-17 17:13 ` [PATCH RFC 4/6] phy: qcom: mipi-csi2: Accept C-PHY mode and add register sequence Nihal Kumar Gupta
` (3 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Nihal Kumar Gupta @ 2026-10-17 17:13 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Manivannan Sadhasivam,
Bryan O'Donoghue, Vladimir Zapolskiy, Loic Poulain,
Mauro Carvalho Chehab, Bryan O'Donoghue
Cc: Vikram Sharma, linux-phy, linux-kernel, linux-media,
linux-arm-msm, Nihal Kumar Gupta
The register sequence storage is tied to a single init table. C-PHY
support needs separate D-PHY and C-PHY sequence selection without
changing the existing D-PHY programming.
Wrap the existing D-PHY table in a D-PHY settings structure and route
lane programming through a common register write helper.
Signed-off-by: Nihal Kumar Gupta <nihal.gupta@oss.qualcomm.com>
---
drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c | 28 +++++++++++++++-------
drivers/phy/qualcomm/phy-qcom-mipi-csi2.h | 8 +++++--
2 files changed, 26 insertions(+), 10 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c
index 966d79c98f9b21e1a235b8397c4c84b25d869427..79c7fa57d059b29f2f72a0c1208e07115b3fb049 100644
--- a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c
+++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c
@@ -241,14 +241,12 @@ static u8 phy_qcom_mipi_csi2_settle_cnt_calc(s64 link_freq, u32 timer_clk_rate)
return settle_cnt;
}
-static void
-phy_qcom_mipi_csi2_gen2_config_lanes(struct mipi_csi2phy_device *csi2phy,
- u8 settle_cnt)
+static void phy_qcom_mipi_csi2_write_regs(struct mipi_csi2phy_device *csi2phy,
+ const struct mipi_csi2phy_lane_regs *r,
+ unsigned int array_size, u8 settle_cnt)
{
- const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy);
- const struct mipi_csi2phy_lane_regs *r = regs->init_seq;
- int i, array_size = regs->lane_array_size;
u32 val;
+ int i;
for (i = 0; i < array_size; i++, r++) {
switch (r->param_type) {
@@ -268,6 +266,16 @@ phy_qcom_mipi_csi2_gen2_config_lanes(struct mipi_csi2phy_device *csi2phy,
}
}
+static void
+phy_qcom_mipi_csi2_gen2_config_lanes(struct mipi_csi2phy_device *csi2phy,
+ u8 settle_cnt)
+{
+ const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy);
+
+ phy_qcom_mipi_csi2_write_regs(csi2phy, regs->dphy->dphy_init_seq,
+ regs->dphy->num_regs, settle_cnt);
+}
+
static int phy_qcom_mipi_csi2_lanes_enable(struct mipi_csi2phy_device *csi2phy,
struct mipi_csi2phy_stream_cfg *cfg)
{
@@ -369,11 +377,15 @@ static struct mipi_csi2_genpd x1e_genpds[] = {
{ .name = "mx", .scaled = true },
};
+static const struct mipi_csi2phy_dphy_rate_settings x1e80100_dphy_settings = {
+ .dphy_init_seq = lane_regs_x1e80100,
+ .num_regs = ARRAY_SIZE(lane_regs_x1e80100),
+};
+
const struct mipi_csi2phy_soc_cfg mipi_csi2_dphy_4nm_x1e = {
.ops = &phy_qcom_mipi_csi2_ops_3ph_1_0,
.reg_info = {
- .init_seq = lane_regs_x1e80100,
- .lane_array_size = ARRAY_SIZE(lane_regs_x1e80100),
+ .dphy = &x1e80100_dphy_settings,
.common_regs_offset = 0x1000,
},
.supply_names = (const char **)x1e_supplies,
diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h b/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h
index 7e55ae00737047f2d0384728a9c98780851eec05..528e80109c2f96b8c66d989ac834e30e7b38c732 100644
--- a/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h
+++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h
@@ -47,9 +47,13 @@ struct mipi_csi2phy_lane_regs {
const u32 param_type;
};
+struct mipi_csi2phy_dphy_rate_settings {
+ const struct mipi_csi2phy_lane_regs *dphy_init_seq;
+ unsigned int num_regs;
+};
+
struct mipi_csi2phy_device_regs {
- const struct mipi_csi2phy_lane_regs *init_seq;
- const int lane_array_size;
+ const struct mipi_csi2phy_dphy_rate_settings *dphy;
const u32 common_regs_offset;
};
--
2.34.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH RFC 4/6] phy: qcom: mipi-csi2: Accept C-PHY mode and add register sequence
2026-10-17 17:13 ` [PATCH RFC 0/6] phy/media: Add generic MIPI C-PHY support to CSI-2 stack Nihal Kumar Gupta
` (2 preceding siblings ...)
2026-10-17 17:13 ` [PATCH RFC 3/6] phy: qcom: mipi-csi2: Split D-PHY register settings Nihal Kumar Gupta
@ 2026-10-17 17:13 ` Nihal Kumar Gupta
2026-10-17 17:13 ` [PATCH RFC 5/6] phy: qcom: mipi-csi2: Add C-PHY settle calculation Nihal Kumar Gupta
` (2 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Nihal Kumar Gupta @ 2026-10-17 17:13 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Manivannan Sadhasivam,
Bryan O'Donoghue, Vladimir Zapolskiy, Loic Poulain,
Mauro Carvalho Chehab, Bryan O'Donoghue
Cc: Vikram Sharma, linux-phy, linux-kernel, linux-media,
linux-arm-msm, Nihal Kumar Gupta
The CSI-2 PHY core rejects all modes except D-PHY, so CAMSS cannot pass
C-PHY stream configuration to the PHY provider. Accept PHY_MODE_MIPI_CPHY
in set_mode() and configure(). Validate the trio count and store the C-PHY
link frequency and timing in the stream configuration.
C-PHY programming needs a common base sequence and a data-rate specific
sequence, while D-PHY keeps using its existing sequence. Add
mipi_csi2phy_cphy_rate_settings descriptor and select the register
sequence from the configured PHY mode. Leave SoC-specific C-PHY register
data to separate patches.
Signed-off-by: Nihal Kumar Gupta <nihal.gupta@oss.qualcomm.com>
---
drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c | 51 +++++++++++++++++-----
drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c | 51 ++++++++++++++++------
drivers/phy/qualcomm/phy-qcom-mipi-csi2.h | 17 ++++++++
3 files changed, 96 insertions(+), 23 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c
index 79c7fa57d059b29f2f72a0c1208e07115b3fb049..30f7f39ba855a0a2921189050f0084dead207fbd 100644
--- a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c
+++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c
@@ -266,14 +266,48 @@ static void phy_qcom_mipi_csi2_write_regs(struct mipi_csi2phy_device *csi2phy,
}
}
-static void
+static int
phy_qcom_mipi_csi2_gen2_config_lanes(struct mipi_csi2phy_device *csi2phy,
u8 settle_cnt)
{
const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy);
+ u64 bit_rate;
+ int i;
+
+ switch (csi2phy->phy_mode) {
+ case PHY_MODE_MIPI_CPHY:
+ if (!regs->cphy || !regs->num_cphy)
+ return -EINVAL;
+
+ /*
+ * link_freq = symbol_rate / 2; convert to effective bit rate
+ * (bits/s) for comparison against the bandwidth table:
+ * bit_rate = link_freq * 2 * 16 / 7 = link_freq * 32 / 7
+ */
+ bit_rate = div_u64((u64)csi2phy->stream_cfg.link_freq * 32, 7);
+
+ for (i = 0; i < regs->num_cphy; i++) {
+ if (regs->cphy[i].bandwidth >= bit_rate)
+ break;
+ }
+
+ if (i == regs->num_cphy)
+ i = regs->num_cphy - 1;
+
+ phy_qcom_mipi_csi2_write_regs(csi2phy, regs->cphy[i].cphy_init_seq,
+ regs->cphy[i].num_regs,
+ settle_cnt);
+ break;
+ case PHY_MODE_MIPI_DPHY:
+ phy_qcom_mipi_csi2_write_regs(csi2phy, regs->dphy->dphy_init_seq,
+ regs->dphy->num_regs,
+ settle_cnt);
+ break;
+ default:
+ return -EINVAL;
+ }
- phy_qcom_mipi_csi2_write_regs(csi2phy, regs->dphy->dphy_init_seq,
- regs->dphy->num_regs, settle_cnt);
+ return 0;
}
static int phy_qcom_mipi_csi2_lanes_enable(struct mipi_csi2phy_device *csi2phy,
@@ -283,12 +317,7 @@ static int phy_qcom_mipi_csi2_lanes_enable(struct mipi_csi2phy_device *csi2phy,
struct mipi_csi2phy_lanes_cfg *lane_cfg = &cfg->lane_cfg;
u8 settle_cnt;
u8 val;
- int i;
-
- if (cfg->link_freq <= 0)
- return -EINVAL;
-
- settle_cnt = phy_qcom_mipi_csi2_settle_cnt_calc(cfg->link_freq, csi2phy->timer_clk_rate);
+ int i, ret;
if (!settle_cnt)
return -ENODEV;
@@ -329,7 +358,9 @@ static int phy_qcom_mipi_csi2_lanes_enable(struct mipi_csi2phy_device *csi2phy,
writel(val, csi2phy->base +
CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 0));
- phy_qcom_mipi_csi2_gen2_config_lanes(csi2phy, settle_cnt);
+ ret = phy_qcom_mipi_csi2_gen2_config_lanes(csi2phy, settle_cnt);
+ if (ret)
+ return ret;
/* IRQ_MASK registers - disable all interrupts */
for (i = CSI_COMMON_STATUS_NUM; i < CSI_CTRL_STATUS_INDEX; i++) {
diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c
index c0a4fa20eaf0c87f6c18b35e625f5ba1769c94e7..56b8830d69ee34280119d8b813ede643252e3606 100644
--- a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c
+++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c
@@ -100,23 +100,46 @@ static int phy_qcom_mipi_csi2_configure(struct phy *phy,
union phy_configure_opts *opts)
{
struct mipi_csi2phy_device *csi2phy = phy_get_drvdata(phy);
- struct phy_configure_opts_mipi_dphy *dphy_cfg = &opts->mipi_dphy;
struct mipi_csi2phy_stream_cfg *stream_cfg = &csi2phy->stream_cfg;
- int ret;
+ int ret = 0;
- ret = phy_mipi_dphy_config_validate(dphy_cfg);
- if (ret)
- return ret;
+ if (csi2phy->phy_mode == PHY_MODE_MIPI_DPHY) {
+ struct phy_configure_opts_mipi_dphy *dphy_cfg = &opts->mipi_dphy;
- if (dphy_cfg->lanes < 1 || dphy_cfg->lanes > CSI2_MAX_DATA_LANES)
- return -EINVAL;
+ ret = phy_mipi_dphy_config_validate(dphy_cfg);
+ if (ret)
+ return ret;
- if (dphy_cfg->lanes != stream_cfg->num_data_lanes)
- return -EINVAL;
+ if (dphy_cfg->lanes < 1 || dphy_cfg->lanes > CSI2_MAX_DATA_LANES)
+ return -EINVAL;
- stream_cfg->link_freq = dphy_cfg->hs_clk_rate;
+ if (dphy_cfg->lanes != stream_cfg->num_data_lanes)
+ return -EINVAL;
- return 0;
+ stream_cfg->link_freq = dphy_cfg->hs_clk_rate;
+ stream_cfg->num_data_lanes = dphy_cfg->lanes;
+ } else if (csi2phy->phy_mode == PHY_MODE_MIPI_CPHY) {
+ struct phy_configure_opts_mipi_cphy *cphy_cfg = &opts->mipi_cphy;
+
+ if (cphy_cfg->trios < 1 || cphy_cfg->trios > CSI2_MAX_DATA_TRIOS)
+ return -EINVAL;
+
+ if (!cphy_cfg->t_prepare_ns || !cphy_cfg->t_preamble_ns) {
+ dev_err(csi2phy->dev,
+ "Invalid C-PHY timing: t_prepare_ns=%u t_preamble_ns=%u\n",
+ cphy_cfg->t_prepare_ns, cphy_cfg->t_preamble_ns);
+ return -EINVAL;
+ }
+
+ stream_cfg->link_freq = cphy_cfg->symbol_rate / 2;
+ stream_cfg->num_data_lanes = cphy_cfg->trios;
+ stream_cfg->t_prepare_ns = cphy_cfg->t_prepare_ns;
+ stream_cfg->t_preamble_ns = cphy_cfg->t_preamble_ns;
+ } else {
+ ret = -EINVAL;
+ }
+
+ return ret;
}
static int phy_qcom_mipi_csi2_set_mode(struct phy *phy,
@@ -124,7 +147,8 @@ static int phy_qcom_mipi_csi2_set_mode(struct phy *phy,
{
struct mipi_csi2phy_device *csi2phy = phy_get_drvdata(phy);
- if (mode != PHY_MODE_MIPI_DPHY)
+ if (mode != PHY_MODE_MIPI_DPHY &&
+ mode != PHY_MODE_MIPI_CPHY)
return -EOPNOTSUPP;
csi2phy->phy_mode = mode;
@@ -278,7 +302,8 @@ static int phy_qcom_mipi_csi2_parse_routing(struct mipi_csi2phy_device *csi2phy)
bus_type = MEDIA_BUS_TYPE_CSI2_DPHY;
fwnode_property_read_u32(ep, "bus-type", &bus_type);
- if (bus_type != MEDIA_BUS_TYPE_CSI2_DPHY) {
+ if (bus_type != MEDIA_BUS_TYPE_CSI2_DPHY &&
+ bus_type != MEDIA_BUS_TYPE_CSI2_CPHY) {
ret = -EOPNOTSUPP;
dev_err(dev, "Unsupported bus-type %u\n", bus_type);
goto out_put;
diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h b/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h
index 528e80109c2f96b8c66d989ac834e30e7b38c732..31103546e4874ffd519fe7f386d779f17325cb30 100644
--- a/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h
+++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h
@@ -11,6 +11,7 @@
#include <linux/phy/phy.h>
#define CSI2_MAX_DATA_LANES 4
+#define CSI2_MAX_DATA_TRIOS 3
#define CSI2_DEFAULT_CLK_LANE 7
struct mipi_csi2phy_lane {
@@ -26,6 +27,8 @@ struct mipi_csi2phy_lanes_cfg {
struct mipi_csi2phy_stream_cfg {
s64 link_freq;
u8 num_data_lanes;
+ u32 t_prepare_ns;
+ u32 t_preamble_ns;
struct mipi_csi2phy_lanes_cfg lane_cfg;
};
@@ -52,8 +55,22 @@ struct mipi_csi2phy_dphy_rate_settings {
unsigned int num_regs;
};
+struct mipi_csi2phy_cphy_rate_settings {
+ /**
+ * @bandwidth: Maximum effective data rate for this register sequence,
+ * in bits/s (= symbol_rate * 16 / 7). The first entry whose bandwidth
+ * is >= the configured link bit rate is selected; the last entry is
+ * a fallback.
+ */
+ u64 bandwidth;
+ const struct mipi_csi2phy_lane_regs *cphy_init_seq;
+ unsigned int num_regs;
+};
+
struct mipi_csi2phy_device_regs {
const struct mipi_csi2phy_dphy_rate_settings *dphy;
+ const struct mipi_csi2phy_cphy_rate_settings *cphy;
+ unsigned int num_cphy;
const u32 common_regs_offset;
};
--
2.34.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH RFC 5/6] phy: qcom: mipi-csi2: Add C-PHY settle calculation
2026-10-17 17:13 ` [PATCH RFC 0/6] phy/media: Add generic MIPI C-PHY support to CSI-2 stack Nihal Kumar Gupta
` (3 preceding siblings ...)
2026-10-17 17:13 ` [PATCH RFC 4/6] phy: qcom: mipi-csi2: Accept C-PHY mode and add register sequence Nihal Kumar Gupta
@ 2026-10-17 17:13 ` Nihal Kumar Gupta
2026-10-17 17:13 ` [PATCH RFC 6/6] phy: qcom: mipi-csi2: Add lane mask calculation for C-PHY Nihal Kumar Gupta
2026-10-17 23:39 ` [PATCH RFC 0/6] phy/media: Add generic MIPI C-PHY support to CSI-2 stack Bryan O'Donoghue
6 siblings, 0 replies; 9+ messages in thread
From: Nihal Kumar Gupta @ 2026-10-17 17:13 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Manivannan Sadhasivam,
Bryan O'Donoghue, Vladimir Zapolskiy, Loic Poulain,
Mauro Carvalho Chehab, Bryan O'Donoghue
Cc: Vikram Sharma, linux-phy, linux-kernel, linux-media,
linux-arm-msm, Nihal Kumar Gupta
C-PHY settle timing is provided by the sensor and does not use the D-PHY
T_hs_settle calculation. Add a C-PHY settle count helper and select the
settle calculation from the configured PHY mode.
Use the sensor-provided t_prepare_ns and t_preamble_ns values to derive
the C-PHY settle count:
settle_cnt = (t_prepare_ns + t_preamble_ns / 3) * timer_clk_rate
/ NSEC_PER_SEC
Signed-off-by: Nihal Kumar Gupta <nihal.gupta@oss.qualcomm.com>
---
drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c | 54 ++++++++++++++++++----
1 file changed, 44 insertions(+), 10 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c
index 30f7f39ba855a0a2921189050f0084dead207fbd..d93fd9845b50bd7e5623013aecd6db42dd491dca 100644
--- a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c
+++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c
@@ -210,7 +210,7 @@ static void phy_qcom_mipi_csi2_reset(struct mipi_csi2phy_device *csi2phy)
}
/*
- * phy_qcom_mipi_csi2_settle_cnt_calc - Calculate settle count value
+ * phy_qcom_dphy_settle_cnt - Calculate settle count value
*
* Helper function to calculate settle count value. This is
* based on the CSI2 T_hs_settle parameter which in turn
@@ -218,7 +218,7 @@ static void phy_qcom_mipi_csi2_reset(struct mipi_csi2phy_device *csi2phy)
*
* Return settle count.
*/
-static u8 phy_qcom_mipi_csi2_settle_cnt_calc(s64 link_freq, u32 timer_clk_rate)
+static u8 phy_qcom_dphy_settle_cnt(s64 link_freq, u32 timer_clk_rate)
{
u32 t_hs_prepare_max_ps;
u32 timer_period_ps;
@@ -310,14 +310,44 @@ phy_qcom_mipi_csi2_gen2_config_lanes(struct mipi_csi2phy_device *csi2phy,
return 0;
}
+static u8 phy_qcom_cphy_settle_cnt(struct mipi_csi2phy_stream_cfg *cfg,
+ u32 timer_clk_rate)
+{
+ u64 settle_cnt;
+
+ settle_cnt = ((u64)cfg->t_prepare_ns +
+ DIV_ROUND_CLOSEST(cfg->t_preamble_ns, 3)) * timer_clk_rate;
+ do_div(settle_cnt, NSEC_PER_SEC);
+
+ return settle_cnt;
+}
+
static int phy_qcom_mipi_csi2_lanes_enable(struct mipi_csi2phy_device *csi2phy,
struct mipi_csi2phy_stream_cfg *cfg)
{
+ struct device *dev = csi2phy->dev;
const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy);
struct mipi_csi2phy_lanes_cfg *lane_cfg = &cfg->lane_cfg;
u8 settle_cnt;
u8 val;
int i, ret;
+
+ if (cfg->link_freq <= 0)
+ return -EINVAL;
+
+ switch (csi2phy->phy_mode) {
+ case PHY_MODE_MIPI_CPHY:
+ settle_cnt = phy_qcom_cphy_settle_cnt(cfg,
+ csi2phy->timer_clk_rate);
+ break;
+ case PHY_MODE_MIPI_DPHY:
+ settle_cnt = phy_qcom_dphy_settle_cnt(cfg->link_freq,
+ csi2phy->timer_clk_rate);
+ break;
+ default:
+ dev_err(dev, "Unsupported PHY mode %u\n", csi2phy->phy_mode);
+ return -EINVAL;
+ }
if (!settle_cnt)
return -ENODEV;
@@ -334,17 +364,21 @@ static int phy_qcom_mipi_csi2_lanes_enable(struct mipi_csi2phy_device *csi2phy,
writel(val, csi2phy->base +
CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 5));
- /* Lane configuration for polarity @ CSIPHY-base + CTRL9 */
- for (i = 0; i < cfg->num_data_lanes; i++) {
- if (lane_cfg->data[i].pol) {
- u8 pos = lane_cfg->data[i].pos;
+ if (csi2phy->phy_mode == PHY_MODE_MIPI_DPHY) {
+ /* Lane configuration for polarity @ CSIPHY-base + CTRL9 */
+ for (i = 0; i < cfg->num_data_lanes; i++) {
+ if (lane_cfg->data[i].pol) {
+ u8 pos = lane_cfg->data[i].pos;
- writel(BIT(2), csi2phy->base + CSIPHY_2PH_LN_CSI_2PHASE_CTRL9n(pos * 2));
+ writel(BIT(2), csi2phy->base +
+ CSIPHY_2PH_LN_CSI_2PHASE_CTRL9n(pos * 2));
+ }
}
- }
- if (lane_cfg->clk.pol)
- writel(BIT(2), csi2phy->base + CSIPHY_2PH_LN_CSI_2PHASE_CTRL9n(lane_cfg->clk.pos));
+ if (lane_cfg->clk.pol)
+ writel(BIT(2), csi2phy->base +
+ CSIPHY_2PH_LN_CSI_2PHASE_CTRL9n(lane_cfg->clk.pos));
+ }
val = CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_COMMON_PWRDN_B;
writel(val, csi2phy->base +
--
2.34.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH RFC 6/6] phy: qcom: mipi-csi2: Add lane mask calculation for C-PHY
2026-10-17 17:13 ` [PATCH RFC 0/6] phy/media: Add generic MIPI C-PHY support to CSI-2 stack Nihal Kumar Gupta
` (4 preceding siblings ...)
2026-10-17 17:13 ` [PATCH RFC 5/6] phy: qcom: mipi-csi2: Add C-PHY settle calculation Nihal Kumar Gupta
@ 2026-10-17 17:13 ` Nihal Kumar Gupta
2026-10-17 23:39 ` [PATCH RFC 0/6] phy/media: Add generic MIPI C-PHY support to CSI-2 stack Bryan O'Donoghue
6 siblings, 0 replies; 9+ messages in thread
From: Nihal Kumar Gupta @ 2026-10-17 17:13 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Manivannan Sadhasivam,
Bryan O'Donoghue, Vladimir Zapolskiy, Loic Poulain,
Mauro Carvalho Chehab, Bryan O'Donoghue
Cc: Vikram Sharma, linux-phy, linux-kernel, linux-media,
linux-arm-msm, Nihal Kumar Gupta
C-PHY uses trio lanes instead of D-PHY data+clock lanes. The existing
lane power-up mask hard-codes D-PHY bit positions and cannot represent
C-PHY trios.
Extract csiphy_get_lane_mask() and select the correct bit pattern based
on the configured PHY mode. For C-PHY, data lane bits are shifted by one
to target trio positions [1,3,5]; for D-PHY, the clock lane bit and
even-numbered data bits [0,2,4,6] are set as before.
Signed-off-by: Nihal Kumar Gupta <nihal.gupta@oss.qualcomm.com>
---
drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c | 40 ++++++++++++++++------
1 file changed, 30 insertions(+), 10 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c
index d93fd9845b50bd7e5623013aecd6db42dd491dca..5e7036cb7205d75c988a281eced60658b45c73c3 100644
--- a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c
+++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c
@@ -322,6 +322,35 @@ static u8 phy_qcom_cphy_settle_cnt(struct mipi_csi2phy_stream_cfg *cfg,
return settle_cnt;
}
+static u8 csiphy_get_lane_mask(struct mipi_csi2phy_lanes_cfg *lane_cfg,
+ enum phy_mode mode, u8 num_data)
+{
+ u8 lane_mask = 0;
+ u8 offset = 0;
+
+ switch (mode) {
+ case PHY_MODE_MIPI_CPHY:
+ offset = 1;
+ break;
+ case PHY_MODE_MIPI_DPHY:
+ lane_mask = BIT(lane_cfg->clk.pos);
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * CSI_COMMON_CTRL5 is a physical lane power-up bitmap:
+ * - Bits [0,2,4,6] → D-PHY data lanes(LN0, LN2, LN4, LN6)
+ * - Bits [1,3,5] → C-PHY trio lanes(LN1, LN3, LN5)
+ * - Bit [7] → D-PHY clock lane(LNCK) dedicated clock enable
+ */
+ for (int i = 0; i < num_data; i++)
+ lane_mask |= BIT((lane_cfg->data[i].pos * 2) + offset);
+
+ return lane_mask;
+}
+
static int phy_qcom_mipi_csi2_lanes_enable(struct mipi_csi2phy_device *csi2phy,
struct mipi_csi2phy_stream_cfg *cfg)
{
@@ -351,16 +380,7 @@ static int phy_qcom_mipi_csi2_lanes_enable(struct mipi_csi2phy_device *csi2phy,
if (!settle_cnt)
return -ENODEV;
- /*
- * CSI_COMMON_CTRL5 is a physical lane power-up bitmap:
- * - Bits [0,2,4,6] → D-PHY data lanes(LN0, LN2, LN4, LN6)
- * - Bits [1,3,5] → C-PHY trio lanes(LN1, LN3, LN5)
- * - Bit [7] → D-PHY clock lane(LNCK) dedicated clock enable
- */
- val = BIT(lane_cfg->clk.pos);
- for (i = 0; i < cfg->num_data_lanes; i++)
- val |= BIT(lane_cfg->data[i].pos * 2);
-
+ val = csiphy_get_lane_mask(lane_cfg, csi2phy->phy_mode, cfg->num_data_lanes);
writel(val, csi2phy->base +
CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 5));
--
2.34.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH RFC 0/6] phy/media: Add generic MIPI C-PHY support to CSI-2 stack
2026-10-17 17:13 ` [PATCH RFC 0/6] phy/media: Add generic MIPI C-PHY support to CSI-2 stack Nihal Kumar Gupta
` (5 preceding siblings ...)
2026-10-17 17:13 ` [PATCH RFC 6/6] phy: qcom: mipi-csi2: Add lane mask calculation for C-PHY Nihal Kumar Gupta
@ 2026-10-17 23:39 ` Bryan O'Donoghue
2026-10-19 7:15 ` Nihal Kumar Gupta
6 siblings, 1 reply; 9+ messages in thread
From: Bryan O'Donoghue @ 2026-10-17 23:39 UTC (permalink / raw)
To: Nihal Kumar Gupta, Vinod Koul, Neil Armstrong,
Manivannan Sadhasivam, Bryan O'Donoghue, Vladimir Zapolskiy,
Loic Poulain, Mauro Carvalho Chehab
Cc: Vikram Sharma, linux-phy, linux-kernel, linux-media, linux-arm-msm
On 17/10/2026 18:13, Nihal Kumar Gupta wrote:
> George posted a C-PHY series [1] which we are currently reviewing.
> As discussed with Bryan, this series shares our independent
> implementation so the approaches can be compared.
>
> Two aspects covered here are not in [1]:
>
> - Settle count calculation derived from sensor-reported T_PREPARE and
> T_PREAMBLE timing via get_mbus_config(). [1] left this as an open
> question.
>
> - Data rate based register sequence selection using effective bit
> rate (link_freq * 32 / 7). [1] noted downstream does this but
> deferred it; this series implements it.
>
> MIPI CSI-2 operates over two physical layer variants. D-PHY uses a
> dedicated differential clock lane with up to four data lanes. C-PHY
> encodes the clock within the data stream across up to three wire
> trios, eliminating the dedicated clock lane.
>
> Patch 1 extends the generic PHY framework with PHY_MODE_MIPI_CPHY
> and struct phy_configure_opts_mipi_cphy.
>
> Patch 2 adds t_prepare_ns and t_preamble_ns fields to the CSI-2
> media bus configuration and extends CAMSS to forward them to the PHY
> provider for settle count calculation. Sensor drivers must implement
> get_mbus_config() and return non-zero values in nanoseconds; stream-on
> returns -EINVAL otherwise. The strictness is deliberate: C-PHY settle
> timing is symbol-rate-range specific and no safe value can be derived
> from link frequency alone. A conservative fallback could be added if
> reviewers prefer.
>
> Patches 3-6 extend the Qualcomm CSIPHY driver: refactor D-PHY
> register storage to accommodate C-PHY, accept C-PHY mode with
> multiple data rate table selection, compute settle count, and add
> lane power mask support for C-PHY trios.
>
> C-PHY encodes 16 bits per 7 symbols, so the effective bit rate is:
>
> bit_rate = link_freq * 2 * 16 / 7 = link_freq * 32 / 7
>
> where link_freq is symbol_rate / 2 as reported by the sensor via
> get_mbus_config(). The rate-table entry whose bandwidth first meets
> or exceeds bit_rate is selected.
>
> The settle count defines how many timer clock cycles the CSIPHY
> receiver waits before scanning for C-PHY sync. It is computed from
> the sensor's T_PREPARE and T_PREAMBLE timing. The /3 factor reflects
> that C-PHY distributes the preamble sequence across three trios:
>
> settle_cnt = (t_prepare_ns + t_preamble_ns / 3) * timer_clk_rate / 1e9
>
> D-PHY settle count is unchanged from before this series.
>
> [1] https://lore.kernel.org/all/20261016-x1e-cphy-rfc-v3-0-40a346a72153@gmail.com/
>
> Signed-off-by: Nihal Kumar Gupta <nihal.gupta@oss.qualcomm.com>
> ---
> Nihal Kumar Gupta (6):
> phy: core: Add MIPI C-PHY configurations
> media: qcom: camss: Add C-PHY timing fields and get config from sensor
> phy: qcom: mipi-csi2: Split D-PHY register settings
> phy: qcom: mipi-csi2: Accept C-PHY mode and add register sequence
> phy: qcom: mipi-csi2: Add C-PHY settle calculation
> phy: qcom: mipi-csi2: Add lane mask calculation for C-PHY
>
> drivers/media/platform/qcom/camss/camss-csiphy.c | 90 +++++++++---
> drivers/media/platform/qcom/camss/camss-csiphy.h | 2 +
> drivers/media/platform/qcom/camss/camss.c | 8 +-
> drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c | 159 +++++++++++++++++----
So on thing I notice about this series and like is that there's a small
change to the existing 3ph-dphy.c
- Since it supports 3ph-cphy the file should be renamed
3ph-cphy-dphy.c (or something)
- I like the progressive nature of he changes in this series
as structurally the right way to add stuff in. Small digestable
commits
- I think the missing piece here is data_lanes[] and lane_polarities[]
per the other series from Qcom
- Another thing is the other series from Anusha has
a more advanced mipi_ops data-structure for CPHY.
Basically I like the approach taken in this series for a smaller change
to the phy-qcom-mipi-csi2-3ph-dphy.c file.
I'd like the best of both series - I think there is alot to resolve on
lanes, data-lanes and lane-polarities in the other series and looking at
this series, it seems to me we don't need a separate
phy-qcom-mipi-csi2-3ph-cphy.c, I think Konrad observed in George's
series that really the file deals with 3-phase PHYs and that seems true
enough.
Please work out between yourself and Anusha what's next.
If possible I would prefer to contain 3ph CPHY and DPHY to one file as
is done here - at the same time the definition of CPHY ops and lane
mappings is closer to the spec in the other series.
I think either you should take Anusha's structs and lane definitions or
Anusha should take your approach to minimal change to the
phy-qcom-mipi-csi2-3ph-dphy.c renaming it.
One of you needs to pick up the patches from the other one.
George can land his stuff on top then.
> drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c | 51 +++++--
> drivers/phy/qualcomm/phy-qcom-mipi-csi2.h | 25 +++-
> include/linux/phy/phy.h | 47 ++++++
> include/media/v4l2-mediabus.h | 2 +
> 8 files changed, 315 insertions(+), 69 deletions(-)
> ---
> base-commit: 2efb7a11f1aa4d2dc285fe2680cca22cb9f72f64
> change-id: 20261017-cphy_support-2ce4d656e631
>
> Best regards,
> --
> Nihal Kumar Gupta <nihal.gupta@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH RFC 0/6] phy/media: Add generic MIPI C-PHY support to CSI-2 stack
2026-10-17 23:39 ` [PATCH RFC 0/6] phy/media: Add generic MIPI C-PHY support to CSI-2 stack Bryan O'Donoghue
@ 2026-10-19 7:15 ` Nihal Kumar Gupta
0 siblings, 0 replies; 9+ messages in thread
From: Nihal Kumar Gupta @ 2026-10-19 7:15 UTC (permalink / raw)
To: Bryan O'Donoghue, Vinod Koul, Neil Armstrong,
Manivannan Sadhasivam, Bryan O'Donoghue, Vladimir Zapolskiy,
Loic Poulain, Mauro Carvalho Chehab, Anusha Arun Nandi
Cc: Vikram Sharma, linux-phy, linux-kernel, linux-media, linux-arm-msm
On 18-10-2026 05:09, Bryan O'Donoghue wrote:
>> drivers/media/platform/qcom/camss/camss.c | 8 +-
>> drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c | 159 +++++++++++++++++----
>
> So on thing I notice about this series and like is that there's a small change to the existing 3ph-dphy.c
>
> - Since it supports 3ph-cphy the file should be renamed
> 3ph-cphy-dphy.c (or something)
I agree with the direction here. Keeping the 3-phase CPHY and DPHY support
in a single driver looks like the right model.
> - I like the progressive nature of he changes in this series
> as structurally the right way to add stuff in. Small digestable
> commits
> - I think the missing piece here is data_lanes[] and lane_polarities[]
> per the other series from Qcom
> - Another thing is the other series from Anusha has
> a more advanced mipi_ops data-structure for CPHY.
>
> Basically I like the approach taken in this series for a smaller change to the phy-qcom-mipi-csi2-3ph-dphy.c file.
>
> I'd like the best of both series - I think there is alot to resolve on lanes, data-lanes and lane-polarities in the other series and looking at this series, it seems to me we don't need a separate phy-qcom-mipi-csi2-3ph-cphy.c, I think Konrad observed in George's series that really the file deals with 3-phase PHYs and that seems true enough.
>
> Please work out between yourself and Anusha what's next.
>
> If possible I would prefer to contain 3ph CPHY and DPHY to one file as is done here - at the same time the definition of CPHY ops and lane mappings is closer to the spec in the other series.
>
> I think either you should take Anusha's structs and lane definitions or Anusha should take your approach to minimal change to the phy-qcom-mipi-csi2-3ph-dphy.c renaming it.
> One of you needs to pick up the patches from the other one.
>
I can pick up the CPHY ops/lane mapping pieces from Anusha's series and
post the combined common series. Anusha, if you prefer to carry it instead,
please feel free to take this series and fold in your CPHY ops/lane mapping
changes.
The split I suggest is:
- Combined common series: driver rename + generic 3ph CPHY support + CPHY ops/lane mapping.
- Follow-up from Anusha: Lemans/Monaco-specific lane/register programming.
- Follow-up from George: Hamoa support on top of the common CPHY support.
--
Regards,
Nihal Kumar Gupta
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-10-19 7:15 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <pFAaFSKH8thStYg6_Ew1gWdIvj5lbNBF36QKdamV1cU1Nc73wEZfM_KdQWL2NmB5fvaUpMPen7qMOzjHZ9ROIQ==@protonmail.internalid>
2026-10-17 17:13 ` [PATCH RFC 0/6] phy/media: Add generic MIPI C-PHY support to CSI-2 stack Nihal Kumar Gupta
2026-10-17 17:13 ` [PATCH RFC 1/6] phy: core: Add MIPI C-PHY configurations Nihal Kumar Gupta
2026-10-17 17:13 ` [PATCH RFC 2/6] media: qcom: camss: Add C-PHY timing fields and get config from sensor Nihal Kumar Gupta
2026-10-17 17:13 ` [PATCH RFC 3/6] phy: qcom: mipi-csi2: Split D-PHY register settings Nihal Kumar Gupta
2026-10-17 17:13 ` [PATCH RFC 4/6] phy: qcom: mipi-csi2: Accept C-PHY mode and add register sequence Nihal Kumar Gupta
2026-10-17 17:13 ` [PATCH RFC 5/6] phy: qcom: mipi-csi2: Add C-PHY settle calculation Nihal Kumar Gupta
2026-10-17 17:13 ` [PATCH RFC 6/6] phy: qcom: mipi-csi2: Add lane mask calculation for C-PHY Nihal Kumar Gupta
2026-10-17 23:39 ` [PATCH RFC 0/6] phy/media: Add generic MIPI C-PHY support to CSI-2 stack Bryan O'Donoghue
2026-10-19 7:15 ` Nihal Kumar Gupta
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®