[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250822-camss_tpg-v3-2-c7833a5f10d0@quicinc.com>
Date: Fri, 22 Aug 2025 20:09:20 +0800
From: Wenmeng Liu <quic_wenmliu@...cinc.com>
To: Robert Foss <rfoss@...nel.org>, Todor Tomov <todor.too@...il.com>,
"Bryan
O'Donoghue" <bryan.odonoghue@...aro.org>,
Vladimir Zapolskiy
<vladimir.zapolskiy@...aro.org>,
Mauro Carvalho Chehab <mchehab@...nel.org>
CC: <linux-kernel@...r.kernel.org>, <linux-media@...r.kernel.org>,
<linux-arm-msm@...r.kernel.org>,
Wenmeng Liu <quic_wenmliu@...cinc.com>
Subject: [PATCH v3 2/3] media: qcom: camss: Add link support for TPG common
TPG is connected to the csid as an entity, the link
needs to be adapted.
Signed-off-by: Wenmeng Liu <quic_wenmliu@...cinc.com>
---
drivers/media/platform/qcom/camss/camss-csid.c | 43 +++++++++++++-------
drivers/media/platform/qcom/camss/camss-csiphy.c | 1 +
drivers/media/platform/qcom/camss/camss-csiphy.h | 2 +
drivers/media/platform/qcom/camss/camss.c | 52 ++++++++++++++++++++++++
4 files changed, 84 insertions(+), 14 deletions(-)
diff --git a/drivers/media/platform/qcom/camss/camss-csid.c b/drivers/media/platform/qcom/camss/camss-csid.c
index 5284b5857368c37c202cd89dad6ae8042b637537..196cbc0b60e9bf95a06b053c69c967e345ffcd4b 100644
--- a/drivers/media/platform/qcom/camss/camss-csid.c
+++ b/drivers/media/platform/qcom/camss/camss-csid.c
@@ -35,6 +35,8 @@
#define HW_VERSION_REVISION 16
#define HW_VERSION_GENERATION 28
+#define LANE_CFG_BITWIDTH 4
+
#define MSM_CSID_NAME "msm_csid"
const char * const csid_testgen_modes[] = {
@@ -1227,18 +1229,22 @@ void msm_csid_get_csid_id(struct media_entity *entity, u8 *id)
}
/*
- * csid_get_lane_assign - Calculate CSI2 lane assign configuration parameter
- * @lane_cfg - CSI2 lane configuration
+ * csid_get_lane_assign - Calculate lane assign by csiphy/tpg lane num
+ * @num: lane num
+ * @pos_array: Array of lane positions
*
* Return lane assign
*/
-static u32 csid_get_lane_assign(struct csiphy_lanes_cfg *lane_cfg)
+static u32 csid_get_lane_assign(int num, struct csiphy_lanes_cfg *lane_cfg)
{
u32 lane_assign = 0;
+ int pos;
int i;
- for (i = 0; i < lane_cfg->num_data; i++)
- lane_assign |= lane_cfg->data[i].pos << (i * 4);
+ for (i = 0; i < num; i++) {
+ pos = lane_cfg ? lane_cfg->data[i].pos : i;
+ lane_assign |= pos << (i * LANE_CFG_BITWIDTH);
+ }
return lane_assign;
}
@@ -1266,6 +1272,7 @@ static int csid_link_setup(struct media_entity *entity,
struct csid_device *csid;
struct csiphy_device *csiphy;
struct csiphy_lanes_cfg *lane_cfg;
+ struct tpg_device *tpg;
sd = media_entity_to_v4l2_subdev(entity);
csid = v4l2_get_subdevdata(sd);
@@ -1277,18 +1284,26 @@ static int csid_link_setup(struct media_entity *entity,
return -EBUSY;
sd = media_entity_to_v4l2_subdev(remote->entity);
- csiphy = v4l2_get_subdevdata(sd);
+ if (sd->grp_id == TPG_GUP_ID) {
+ tpg = v4l2_get_subdevdata(sd);
- /* If a sensor is not linked to CSIPHY */
- /* do no allow a link from CSIPHY to CSID */
- if (!csiphy->cfg.csi2)
- return -EPERM;
+ csid->phy.lane_cnt = tpg->res->lane_cnt;
+ csid->phy.csiphy_id = tpg->id;
+ csid->phy.lane_assign = csid_get_lane_assign(csid->phy.lane_cnt, NULL);
+ } else {
+ csiphy = v4l2_get_subdevdata(sd);
- csid->phy.csiphy_id = csiphy->id;
+ /* If a sensor is not linked to CSIPHY */
+ /* do no allow a link from CSIPHY to CSID */
+ if (!csiphy->cfg.csi2)
+ return -EPERM;
- lane_cfg = &csiphy->cfg.csi2->lane_cfg;
- csid->phy.lane_cnt = lane_cfg->num_data;
- csid->phy.lane_assign = csid_get_lane_assign(lane_cfg);
+ csid->phy.csiphy_id = csiphy->id;
+
+ lane_cfg = &csiphy->cfg.csi2->lane_cfg;
+ csid->phy.lane_cnt = lane_cfg->num_data;
+ csid->phy.lane_assign = csid_get_lane_assign(lane_cfg->num_data, lane_cfg);
+ }
}
/* Decide which virtual channels to enable based on which source pads are enabled */
if (local->flags & MEDIA_PAD_FL_SOURCE) {
diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.c b/drivers/media/platform/qcom/camss/camss-csiphy.c
index 2de97f58f9ae4f91e8bba39dcadf92bea8cf6f73..680580d7fe46a215777f3fa1b347f4297deea024 100644
--- a/drivers/media/platform/qcom/camss/camss-csiphy.c
+++ b/drivers/media/platform/qcom/camss/camss-csiphy.c
@@ -799,6 +799,7 @@ int msm_csiphy_register_entity(struct csiphy_device *csiphy,
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d",
MSM_CSIPHY_NAME, csiphy->id);
+ sd->grp_id = CSIPHY_GUP_ID;
v4l2_set_subdevdata(sd, csiphy);
ret = csiphy_init_formats(sd, NULL);
diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.h b/drivers/media/platform/qcom/camss/camss-csiphy.h
index 895f80003c441dcacf98435f91567f90afa29279..b7bcf2bdd2124f77b5354b15b33aa1e0983143e8 100644
--- a/drivers/media/platform/qcom/camss/camss-csiphy.h
+++ b/drivers/media/platform/qcom/camss/camss-csiphy.h
@@ -21,6 +21,8 @@
#define MSM_CSIPHY_PAD_SRC 1
#define MSM_CSIPHY_PADS_NUM 2
+#define CSIPHY_GUP_ID 1
+
struct csiphy_lane {
u8 pos;
u8 pol;
diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c
index ad88356b329af20a577590e0d6bfed685e48f32a..53477a97dcba8385611398dfd07d41653e6ebaf9 100644
--- a/drivers/media/platform/qcom/camss/camss.c
+++ b/drivers/media/platform/qcom/camss/camss.c
@@ -3560,6 +3560,19 @@ static int camss_init_subdevices(struct camss *camss)
}
}
+ if (camss->tpg) {
+ for (i = 0; i < camss->res->tpg_num; i++) {
+ ret = msm_tpg_subdev_init(camss, &camss->tpg[i],
+ &res->tpg_res[i], i);
+ if (ret < 0) {
+ dev_err(camss->dev,
+ "Failed to init tpg%d sub-device: %d\n",
+ i, ret);
+ return ret;
+ }
+ }
+ }
+
/* note: SM8250 requires VFE to be initialized before CSID */
for (i = 0; i < camss->res->vfe_num; i++) {
ret = msm_vfe_subdev_init(camss, &camss->vfe[i],
@@ -3649,6 +3662,23 @@ static int camss_link_entities(struct camss *camss)
}
}
+ for (i = 0; i < camss->res->tpg_num; i++) {
+ for (j = 0; j < camss->res->csid_num; j++) {
+ ret = media_create_pad_link(&camss->tpg[i].subdev.entity,
+ MSM_TPG_PAD_SRC,
+ &camss->csid[j].subdev.entity,
+ MSM_CSID_PAD_SINK,
+ 0);
+ if (ret < 0) {
+ camss_link_err(camss,
+ camss->tpg[i].subdev.entity.name,
+ camss->csid[j].subdev.entity.name,
+ ret);
+ return ret;
+ }
+ }
+ }
+
if (camss->ispif) {
for (i = 0; i < camss->res->csid_num; i++) {
for (j = 0; j < camss->ispif->line_num; j++) {
@@ -3753,6 +3783,19 @@ static int camss_register_entities(struct camss *camss)
}
}
+ if (camss->tpg) {
+ for (i = 0; i < camss->res->tpg_num; i++) {
+ ret = msm_tpg_register_entity(&camss->tpg[i],
+ &camss->v4l2_dev);
+ if (ret < 0) {
+ dev_err(camss->dev,
+ "Failed to register tpg%d entity: %d\n",
+ i, ret);
+ goto err_reg_tpg;
+ }
+ }
+ }
+
for (i = 0; i < camss->res->csid_num; i++) {
ret = msm_csid_register_entity(&camss->csid[i],
&camss->v4l2_dev);
@@ -3796,6 +3839,10 @@ static int camss_register_entities(struct camss *camss)
for (i--; i >= 0; i--)
msm_csid_unregister_entity(&camss->csid[i]);
+ i = camss->res->tpg_num;
+err_reg_tpg:
+ for (i--; i >= 0; i--)
+ msm_tpg_unregister_entity(&camss->tpg[i]);
i = camss->res->csiphy_num;
err_reg_csiphy:
for (i--; i >= 0; i--)
@@ -3817,6 +3864,11 @@ static void camss_unregister_entities(struct camss *camss)
for (i = 0; i < camss->res->csiphy_num; i++)
msm_csiphy_unregister_entity(&camss->csiphy[i]);
+ if (camss->tpg) {
+ for (i = 0; i < camss->res->tpg_num; i++)
+ msm_tpg_unregister_entity(&camss->tpg[i]);
+ }
+
for (i = 0; i < camss->res->csid_num; i++)
msm_csid_unregister_entity(&camss->csid[i]);
--
2.34.1
Powered by blists - more mailing lists