summaryrefslogtreecommitdiff
path: root/drivers/media/platform/qcom/camss/camss.c
diff options
context:
space:
mode:
authorJonathan Marek <jonathan@marek.ca>2021-12-22 03:37:48 +0300
committerMauro Carvalho Chehab <mchehab@kernel.org>2022-01-23 23:18:41 +0300
commitb4436a18eedb8d93e148d009b145b4ae142e6f9d (patch)
treeeea1b0645f0aada1fb878e7d3742a62306b252a8 /drivers/media/platform/qcom/camss/camss.c
parente53d660843de6c98322f2a57eabaf4ce605a83fb (diff)
downloadlinux-b4436a18eedb8d93e148d009b145b4ae142e6f9d.tar.xz
media: camss: add support for SM8250 camss
The Titan 480 camss found on SM8250 has 6 CSIPHY and 4 VFE/CSID. CSID is compatible with the Titan 170 CSID, but the Titan 480 CSID are inside the VFE region (between the "top" and "bus" registers), so a workaround is added to avoid ioremap failure. [bod] Fixed setting camnoc_axi_clk_src instead of camcc_camnoc_axi_clk [jgrahsl, bod] Add slow_ahb_src clock values [jgrahsl, bod] Add cpa_ahb clock values Signed-off-by: Jonathan Marek <jonathan@marek.ca> Tested-by: Julian Grahsl <jgrahsl@snap.com> Co-developed-by: Julian Grahsl <jgrahsl@snap.com> Signed-off-by: Julian Grahsl <jgrahsl@snap.com> Reviewed-by: Robert Foss <robert.foss@linaro.org> Co-developed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
Diffstat (limited to 'drivers/media/platform/qcom/camss/camss.c')
-rw-r--r--drivers/media/platform/qcom/camss/camss.c219
1 files changed, 207 insertions, 12 deletions
diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c
index 71c6109b0526..066639db9f18 100644
--- a/drivers/media/platform/qcom/camss/camss.c
+++ b/drivers/media/platform/qcom/camss/camss.c
@@ -662,6 +662,185 @@ static const struct resources vfe_res_845[] = {
}
};
+static const struct resources csiphy_res_8250[] = {
+ /* CSIPHY0 */
+ {
+ .regulator = { NULL },
+ .clock = { "csiphy0", "csiphy0_timer" },
+ .clock_rate = { { 400000000 },
+ { 300000000 } },
+ .reg = { "csiphy0" },
+ .interrupt = { "csiphy0" }
+ },
+ /* CSIPHY1 */
+ {
+ .regulator = { NULL },
+ .clock = { "csiphy1", "csiphy1_timer" },
+ .clock_rate = { { 400000000 },
+ { 300000000 } },
+ .reg = { "csiphy1" },
+ .interrupt = { "csiphy1" }
+ },
+ /* CSIPHY2 */
+ {
+ .regulator = { NULL },
+ .clock = { "csiphy2", "csiphy2_timer" },
+ .clock_rate = { { 400000000 },
+ { 300000000 } },
+ .reg = { "csiphy2" },
+ .interrupt = { "csiphy2" }
+ },
+ /* CSIPHY3 */
+ {
+ .regulator = { NULL },
+ .clock = { "csiphy3", "csiphy3_timer" },
+ .clock_rate = { { 400000000 },
+ { 300000000 } },
+ .reg = { "csiphy3" },
+ .interrupt = { "csiphy3" }
+ },
+ /* CSIPHY4 */
+ {
+ .regulator = { NULL },
+ .clock = { "csiphy4", "csiphy4_timer" },
+ .clock_rate = { { 400000000 },
+ { 300000000 } },
+ .reg = { "csiphy4" },
+ .interrupt = { "csiphy4" }
+ },
+ /* CSIPHY5 */
+ {
+ .regulator = { NULL },
+ .clock = { "csiphy5", "csiphy5_timer" },
+ .clock_rate = { { 400000000 },
+ { 300000000 } },
+ .reg = { "csiphy5" },
+ .interrupt = { "csiphy5" }
+ }
+};
+
+static const struct resources csid_res_8250[] = {
+ /* CSID0 */
+ {
+ .regulator = { NULL },
+ .clock = { "vfe0_csid", "vfe0_cphy_rx", "vfe0", "vfe0_areg", "vfe0_ahb" },
+ .clock_rate = { { 400000000 },
+ { 400000000 },
+ { 350000000, 475000000, 576000000, 720000000 },
+ { 100000000, 200000000, 300000000, 400000000 },
+ { 0 } },
+ .reg = { "csid0" },
+ .interrupt = { "csid0" }
+ },
+ /* CSID1 */
+ {
+ .regulator = { NULL },
+ .clock = { "vfe1_csid", "vfe1_cphy_rx", "vfe1", "vfe1_areg", "vfe1_ahb" },
+ .clock_rate = { { 400000000 },
+ { 400000000 },
+ { 350000000, 475000000, 576000000, 720000000 },
+ { 100000000, 200000000, 300000000, 400000000 },
+ { 0 } },
+ .reg = { "csid1" },
+ .interrupt = { "csid1" }
+ },
+ /* CSID2 */
+ {
+ .regulator = { NULL },
+ .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "vfe_lite", "vfe_lite_ahb" },
+ .clock_rate = { { 400000000 },
+ { 400000000 },
+ { 400000000, 480000000 },
+ { 0 } },
+ .reg = { "csid2" },
+ .interrupt = { "csid2" }
+ },
+ /* CSID3 */
+ {
+ .regulator = { NULL },
+ .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "vfe_lite", "vfe_lite_ahb" },
+ .clock_rate = { { 400000000 },
+ { 400000000 },
+ { 400000000, 480000000 },
+ { 0 } },
+ .reg = { "csid3" },
+ .interrupt = { "csid3" }
+ }
+};
+
+static const struct resources vfe_res_8250[] = {
+ /* VFE0 */
+ {
+ .regulator = { NULL },
+ .clock = { "camnoc_axi_src", "slow_ahb_src", "cpas_ahb",
+ "camnoc_axi", "vfe0_ahb", "vfe0_areg", "vfe0",
+ "vfe0_axi", "cam_hf_axi" },
+ .clock_rate = { { 19200000, 300000000, 400000000, 480000000 },
+ { 19200000, 80000000 },
+ { 19200000 },
+ { 0 },
+ { 0 },
+ { 100000000, 200000000, 300000000, 400000000 },
+ { 350000000, 475000000, 576000000, 720000000 },
+ { 0 },
+ { 0 } },
+ .reg = { "vfe0" },
+ .interrupt = { "vfe0" }
+ },
+ /* VFE1 */
+ {
+ .regulator = { NULL },
+ .clock = { "camnoc_axi_src", "slow_ahb_src", "cpas_ahb",
+ "camnoc_axi", "vfe1_ahb", "vfe1_areg", "vfe1",
+ "vfe1_axi", "cam_hf_axi" },
+ .clock_rate = { { 19200000, 300000000, 400000000, 480000000 },
+ { 19200000, 80000000 },
+ { 19200000 },
+ { 0 },
+ { 0 },
+ { 100000000, 200000000, 300000000, 400000000 },
+ { 350000000, 475000000, 576000000, 720000000 },
+ { 0 },
+ { 0 } },
+ .reg = { "vfe1" },
+ .interrupt = { "vfe1" }
+ },
+ /* VFE2 (lite) */
+ {
+ .regulator = { NULL },
+ .clock = { "camnoc_axi_src", "slow_ahb_src", "cpas_ahb",
+ "camnoc_axi", "vfe_lite_ahb", "vfe_lite_axi",
+ "vfe_lite", "cam_hf_axi" },
+ .clock_rate = { { 19200000, 300000000, 400000000, 480000000 },
+ { 19200000, 80000000 },
+ { 19200000 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 400000000, 480000000 },
+ { 0 } },
+ .reg = { "vfe_lite0" },
+ .interrupt = { "vfe_lite0" }
+ },
+ /* VFE3 (lite) */
+ {
+ .regulator = { NULL },
+ .clock = { "camnoc_axi_src", "slow_ahb_src", "cpas_ahb",
+ "camnoc_axi", "vfe_lite_ahb", "vfe_lite_axi",
+ "vfe_lite", "cam_hf_axi" },
+ .clock_rate = { { 19200000, 300000000, 400000000, 480000000 },
+ { 19200000, 80000000 },
+ { 19200000 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 400000000, 480000000 },
+ { 0 } },
+ .reg = { "vfe_lite1" },
+ .interrupt = { "vfe_lite1" }
+ },
+};
+
/*
* camss_add_clock_margin - Add margin to clock frequency rate
* @rate: Clock frequency rate
@@ -945,6 +1124,12 @@ static int camss_init_subdevices(struct camss *camss)
/* Titan VFEs don't have an ISPIF */
ispif_res = NULL;
vfe_res = vfe_res_845;
+ } else if (camss->version == CAMSS_8250) {
+ csiphy_res = csiphy_res_8250;
+ csid_res = csid_res_8250;
+ /* Titan VFEs don't have an ISPIF */
+ ispif_res = NULL;
+ vfe_res = vfe_res_8250;
} else {
return -EINVAL;
}
@@ -960,6 +1145,17 @@ static int camss_init_subdevices(struct camss *camss)
}
}
+ /* note: SM8250 requires VFE to be initialized before CSID */
+ for (i = 0; i < camss->vfe_num; i++) {
+ ret = msm_vfe_subdev_init(camss, &camss->vfe[i],
+ &vfe_res[i], i);
+ if (ret < 0) {
+ dev_err(camss->dev,
+ "Fail to init vfe%d sub-device: %d\n", i, ret);
+ return ret;
+ }
+ }
+
for (i = 0; i < camss->csid_num; i++) {
ret = msm_csid_subdev_init(camss, &camss->csid[i],
&csid_res[i], i);
@@ -978,16 +1174,6 @@ static int camss_init_subdevices(struct camss *camss)
return ret;
}
- for (i = 0; i < camss->vfe_num; i++) {
- ret = msm_vfe_subdev_init(camss, &camss->vfe[i],
- &vfe_res[i], i);
- if (ret < 0) {
- dev_err(camss->dev,
- "Fail to init vfe%d sub-device: %d\n", i, ret);
- return ret;
- }
- }
-
return 0;
}
@@ -1250,7 +1436,8 @@ static int camss_configure_pd(struct camss *camss)
if (camss->version == CAMSS_8x96 ||
camss->version == CAMSS_660)
nbr_pm_domains = PM_DOMAIN_GEN1_COUNT;
- else if (camss->version == CAMSS_845)
+ else if (camss->version == CAMSS_845 ||
+ camss->version == CAMSS_8250)
nbr_pm_domains = PM_DOMAIN_GEN2_COUNT;
for (i = 0; i < nbr_pm_domains; i++) {
@@ -1326,6 +1513,12 @@ static int camss_probe(struct platform_device *pdev)
camss->csiphy_num = 4;
camss->csid_num = 3;
camss->vfe_num = 3;
+ } else if (of_device_is_compatible(dev->of_node,
+ "qcom,sm8250-camss")) {
+ camss->version = CAMSS_8250;
+ camss->csiphy_num = 6;
+ camss->csid_num = 4;
+ camss->vfe_num = 4;
} else {
ret = -EINVAL;
goto err_free;
@@ -1457,7 +1650,8 @@ void camss_delete(struct camss *camss)
if (camss->version == CAMSS_8x96 ||
camss->version == CAMSS_660)
nbr_pm_domains = PM_DOMAIN_GEN1_COUNT;
- else if (camss->version == CAMSS_845)
+ else if (camss->version == CAMSS_845 ||
+ camss->version == CAMSS_8250)
nbr_pm_domains = PM_DOMAIN_GEN2_COUNT;
for (i = 0; i < nbr_pm_domains; i++) {
@@ -1493,6 +1687,7 @@ static const struct of_device_id camss_dt_match[] = {
{ .compatible = "qcom,msm8996-camss" },
{ .compatible = "qcom,sdm660-camss" },
{ .compatible = "qcom,sdm845-camss" },
+ { .compatible = "qcom,sm8250-camss" },
{ }
};