diff mbox series

[4/6] media: camss: Add support for SDM630/636/660 camera subsystem

Message ID 20201018125237.16717-5-kholk11@gmail.com
State Superseded
Headers show
Series None | expand

Commit Message

AngeloGioacchino Del Regno Oct. 18, 2020, 12:52 p.m. UTC
From: AngeloGioacchino Del Regno <kholk11@gmail.com>

Add support for the Qualcomm SDM630/636/660 and SDA variants' camera
subsystem. These SoCs are equipped with:
- 3x CSI PHY 3-Phase v1.0 (downstream csiphy-v3.5)
- 4x CSID v5.0
- 2x ISPIF v3.0
- 2x VFE 4.8
As a note, this camera subsystem is very similar to the one that
is found in the MSM8998/APQ8098 SoCs.

Signed-off-by: AngeloGioacchino Del Regno <kholk11@gmail.com>
---
 .../media/platform/qcom/camss/camss-csid.c    |   9 +-
 .../media/platform/qcom/camss/camss-csiphy.c  |   3 +-
 .../media/platform/qcom/camss/camss-ispif.c   |  17 +-
 drivers/media/platform/qcom/camss/camss-vfe.c |  19 +-
 .../media/platform/qcom/camss/camss-video.c   |   3 +-
 drivers/media/platform/qcom/camss/camss.c     | 206 +++++++++++++++++-
 drivers/media/platform/qcom/camss/camss.h     |   1 +
 7 files changed, 238 insertions(+), 20 deletions(-)

Comments

Robert Foss Oct. 20, 2020, 10:26 a.m. UTC | #1
Looks good to me.

Signed-off-by: Robert Foss <robert.foss@linaro.org>

On Sun, 18 Oct 2020 at 14:53, <kholk11@gmail.com> wrote:
>
> From: AngeloGioacchino Del Regno <kholk11@gmail.com>
>
> Add support for the Qualcomm SDM630/636/660 and SDA variants' camera
> subsystem. These SoCs are equipped with:
> - 3x CSI PHY 3-Phase v1.0 (downstream csiphy-v3.5)
> - 4x CSID v5.0
> - 2x ISPIF v3.0
> - 2x VFE 4.8
> As a note, this camera subsystem is very similar to the one that
> is found in the MSM8998/APQ8098 SoCs.
>
> Signed-off-by: AngeloGioacchino Del Regno <kholk11@gmail.com>
> ---
>  .../media/platform/qcom/camss/camss-csid.c    |   9 +-
>  .../media/platform/qcom/camss/camss-csiphy.c  |   3 +-
>  .../media/platform/qcom/camss/camss-ispif.c   |  17 +-
>  drivers/media/platform/qcom/camss/camss-vfe.c |  19 +-
>  .../media/platform/qcom/camss/camss-video.c   |   3 +-
>  drivers/media/platform/qcom/camss/camss.c     | 206 +++++++++++++++++-
>  drivers/media/platform/qcom/camss/camss.h     |   1 +
>  7 files changed, 238 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/media/platform/qcom/camss/camss-csid.c b/drivers/media/platform/qcom/camss/camss-csid.c
> index 2ffcda06706b..be3fe76f3dc3 100644
> --- a/drivers/media/platform/qcom/camss/camss-csid.c
> +++ b/drivers/media/platform/qcom/camss/camss-csid.c
> @@ -383,7 +383,8 @@ static u32 csid_src_pad_code(struct csid_device *csid, u32 sink_code,
>                         return 0;
>
>                 return sink_code;
> -       } else if (csid->camss->version == CAMSS_8x96) {
> +       } else if (csid->camss->version == CAMSS_8x96 ||
> +                  csid->camss->version == CAMSS_660) {
>                 switch (sink_code) {
>                 case MEDIA_BUS_FMT_SBGGR10_1X10:
>                 {
> @@ -718,7 +719,8 @@ static int csid_set_stream(struct v4l2_subdev *sd, int enable)
>                 val |= df << CAMSS_CSID_CID_n_CFG_DECODE_FORMAT_SHIFT;
>                 val |= CAMSS_CSID_CID_n_CFG_RDI_MODE_RAW_DUMP;
>
> -               if (csid->camss->version == CAMSS_8x96) {
> +               if (csid->camss->version == CAMSS_8x96 ||
> +                   csid->camss->version == CAMSS_660) {
>                         u32 sink_code = csid->fmt[MSM_CSID_PAD_SINK].code;
>                         u32 src_code = csid->fmt[MSM_CSID_PAD_SRC].code;
>
> @@ -1098,7 +1100,8 @@ int msm_csid_subdev_init(struct camss *camss, struct csid_device *csid,
>                 csid->formats = csid_formats_8x16;
>                 csid->nformats =
>                                 ARRAY_SIZE(csid_formats_8x16);
> -       } else if (camss->version == CAMSS_8x96) {
> +       } else if (camss->version == CAMSS_8x96 ||
> +                  camss->version == CAMSS_660) {
>                 csid->formats = csid_formats_8x96;
>                 csid->nformats =
>                                 ARRAY_SIZE(csid_formats_8x96);
> diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.c b/drivers/media/platform/qcom/camss/camss-csiphy.c
> index 03ef9c5f4774..c00f25aac21b 100644
> --- a/drivers/media/platform/qcom/camss/camss-csiphy.c
> +++ b/drivers/media/platform/qcom/camss/camss-csiphy.c
> @@ -552,7 +552,8 @@ int msm_csiphy_subdev_init(struct camss *camss,
>                 csiphy->ops = &csiphy_ops_2ph_1_0;
>                 csiphy->formats = csiphy_formats_8x16;
>                 csiphy->nformats = ARRAY_SIZE(csiphy_formats_8x16);
> -       } else if (camss->version == CAMSS_8x96) {
> +       } else if (camss->version == CAMSS_8x96 ||
> +                  camss->version == CAMSS_660) {
>                 csiphy->ops = &csiphy_ops_3ph_1_0;
>                 csiphy->formats = csiphy_formats_8x96;
>                 csiphy->nformats = ARRAY_SIZE(csiphy_formats_8x96);
> diff --git a/drivers/media/platform/qcom/camss/camss-ispif.c b/drivers/media/platform/qcom/camss/camss-ispif.c
> index 252db6b33dab..adeb92808998 100644
> --- a/drivers/media/platform/qcom/camss/camss-ispif.c
> +++ b/drivers/media/platform/qcom/camss/camss-ispif.c
> @@ -263,6 +263,7 @@ static irqreturn_t ispif_isr_8x16(int irq, void *dev)
>
>  static int ispif_vfe_reset(struct ispif_device *ispif, u8 vfe_id)
>  {
> +       unsigned long time;
>         u32 val;
>
>         if (vfe_id > (to_camss(ispif)->vfe_num - 1)) {
> @@ -315,7 +316,6 @@ static int ispif_vfe_reset(struct ispif_device *ispif, u8 vfe_id)
>   */
>  static int ispif_reset(struct ispif_device *ispif, u8 vfe_id)
>  {
> -       unsigned long time;
>         int ret;
>
>         ret = camss_pm_domain_on(to_camss(ispif), PM_DOMAIN_VFE0);
> @@ -825,7 +825,8 @@ static int ispif_set_stream(struct v4l2_subdev *sd, int enable)
>                 ispif_select_csid(ispif, intf, csid, vfe, 1);
>                 ispif_select_cid(ispif, intf, cid, vfe, 1);
>                 ispif_config_irq(ispif, intf, vfe, 1);
> -               if (to_camss(ispif)->version == CAMSS_8x96)
> +               if (to_camss(ispif)->version == CAMSS_8x96 ||
> +                   to_camss(ispif)->version == CAMSS_660)
>                         ispif_config_pack(ispif,
>                                           line->fmt[MSM_ISPIF_PAD_SINK].code,
>                                           intf, cid, vfe, 1);
> @@ -842,7 +843,8 @@ static int ispif_set_stream(struct v4l2_subdev *sd, int enable)
>                         return ret;
>
>                 mutex_lock(&ispif->config_lock);
> -               if (to_camss(ispif)->version == CAMSS_8x96)
> +               if (to_camss(ispif)->version == CAMSS_8x96 ||
> +                   to_camss(ispif)->version == CAMSS_660)
>                         ispif_config_pack(ispif,
>                                           line->fmt[MSM_ISPIF_PAD_SINK].code,
>                                           intf, cid, vfe, 0);
> @@ -1098,7 +1100,8 @@ int msm_ispif_subdev_init(struct ispif_device *ispif,
>         /* Number of ISPIF lines - same as number of CSID hardware modules */
>         if (to_camss(ispif)->version == CAMSS_8x16)
>                 ispif->line_num = 2;
> -       else if (to_camss(ispif)->version == CAMSS_8x96)
> +       else if (to_camss(ispif)->version == CAMSS_8x96 ||
> +                to_camss(ispif)->version == CAMSS_660)
>                 ispif->line_num = 4;
>         else
>                 return -EINVAL;
> @@ -1116,7 +1119,8 @@ int msm_ispif_subdev_init(struct ispif_device *ispif,
>                         ispif->line[i].formats = ispif_formats_8x16;
>                         ispif->line[i].nformats =
>                                         ARRAY_SIZE(ispif_formats_8x16);
> -               } else if (to_camss(ispif)->version == CAMSS_8x96) {
> +               } else if (to_camss(ispif)->version == CAMSS_8x96 ||
> +                          to_camss(ispif)->version == CAMSS_660) {
>                         ispif->line[i].formats = ispif_formats_8x96;
>                         ispif->line[i].nformats =
>                                         ARRAY_SIZE(ispif_formats_8x96);
> @@ -1156,7 +1160,8 @@ int msm_ispif_subdev_init(struct ispif_device *ispif,
>         if (to_camss(ispif)->version == CAMSS_8x16)
>                 ret = devm_request_irq(dev, ispif->irq, ispif_isr_8x16,
>                                IRQF_TRIGGER_RISING, ispif->irq_name, ispif);
> -       else if (to_camss(ispif)->version == CAMSS_8x96)
> +       else if (to_camss(ispif)->version == CAMSS_8x96 ||
> +                to_camss(ispif)->version == CAMSS_660)
>                 ret = devm_request_irq(dev, ispif->irq, ispif_isr_8x96,
>                                IRQF_TRIGGER_RISING, ispif->irq_name, ispif);
>         else
> diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c
> index b7d2293a5004..fae2b513b2f9 100644
> --- a/drivers/media/platform/qcom/camss/camss-vfe.c
> +++ b/drivers/media/platform/qcom/camss/camss-vfe.c
> @@ -205,7 +205,8 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code,
>
>                         return sink_code;
>                 }
> -       else if (vfe->camss->version == CAMSS_8x96)
> +       else if (vfe->camss->version == CAMSS_8x96 ||
> +                vfe->camss->version == CAMSS_660)
>                 switch (sink_code) {
>                 case MEDIA_BUS_FMT_YUYV8_2X8:
>                 {
> @@ -1991,12 +1992,19 @@ int msm_vfe_subdev_init(struct camss *camss, struct vfe_device *vfe,
>         vfe->isr_ops.comp_done = vfe_isr_comp_done;
>         vfe->isr_ops.wm_done = vfe_isr_wm_done;
>
> -       if (camss->version == CAMSS_8x16)
> +       switch (camss->version) {
> +       case CAMSS_8x16:
>                 vfe->ops = &vfe_ops_4_1;
> -       else if (camss->version == CAMSS_8x96)
> +               break;
> +       case CAMSS_8x96:
>                 vfe->ops = &vfe_ops_4_7;
> -       else
> +               break;
> +       case CAMSS_660:
> +               vfe->ops = &vfe_ops_4_8;
> +               break;
> +       default:
>                 return -EINVAL;
> +       }
>
>         /* Memory */
>
> @@ -2095,7 +2103,8 @@ int msm_vfe_subdev_init(struct camss *camss, struct vfe_device *vfe,
>                                 l->formats = formats_rdi_8x16;
>                                 l->nformats = ARRAY_SIZE(formats_rdi_8x16);
>                         }
> -               } else if (camss->version == CAMSS_8x96) {
> +               } else if (camss->version == CAMSS_8x96 ||
> +                          camss->version == CAMSS_660) {
>                         if (i == VFE_LINE_PIX) {
>                                 l->formats = formats_pix_8x96;
>                                 l->nformats = ARRAY_SIZE(formats_pix_8x96);
> diff --git a/drivers/media/platform/qcom/camss/camss-video.c b/drivers/media/platform/qcom/camss/camss-video.c
> index 114c3ae4a4ab..fbba9e45d732 100644
> --- a/drivers/media/platform/qcom/camss/camss-video.c
> +++ b/drivers/media/platform/qcom/camss/camss-video.c
> @@ -970,7 +970,8 @@ int msm_video_register(struct camss_video *video, struct v4l2_device *v4l2_dev,
>                         video->formats = formats_rdi_8x16;
>                         video->nformats = ARRAY_SIZE(formats_rdi_8x16);
>                 }
> -       } else if (video->camss->version == CAMSS_8x96) {
> +       } else if (video->camss->version == CAMSS_8x96 ||
> +                  video->camss->version == CAMSS_660) {
>                 if (is_pix) {
>                         video->formats = formats_pix_8x96;
>                         video->nformats = ARRAY_SIZE(formats_pix_8x96);
> diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c
> index 9186881afc98..8fefce57bc49 100644
> --- a/drivers/media/platform/qcom/camss/camss.c
> +++ b/drivers/media/platform/qcom/camss/camss.c
> @@ -283,6 +283,188 @@ static const struct resources vfe_res_8x96[] = {
>         }
>  };
>
> +static const struct resources csiphy_res_660[] = {
> +       /* CSIPHY0 */
> +       {
> +               .regulator = { NULL },
> +               .clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy0_timer",
> +                          "csi0_phy", "csiphy_ahb2crif" },
> +               .clock_rate = { { 0 },
> +                               { 0 },
> +                               { 0 },
> +                               { 100000000, 200000000, 269333333 },
> +                               { 0 } },
> +               .reg = { "csiphy0", "csiphy0_clk_mux" },
> +               .interrupt = { "csiphy0" }
> +       },
> +
> +       /* CSIPHY1 */
> +       {
> +               .regulator = { NULL },
> +               .clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy1_timer",
> +                          "csi1_phy", "csiphy_ahb2crif" },
> +               .clock_rate = { { 0 },
> +                               { 0 },
> +                               { 0 },
> +                               { 100000000, 200000000, 269333333 },
> +                               { 0 } },
> +               .reg = { "csiphy1", "csiphy1_clk_mux" },
> +               .interrupt = { "csiphy1" }
> +       },
> +
> +       /* CSIPHY2 */
> +       {
> +               .regulator = { NULL },
> +               .clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy2_timer",
> +                          "csi2_phy", "csiphy_ahb2crif" },
> +               .clock_rate = { { 0 },
> +                               { 0 },
> +                               { 0 },
> +                               { 100000000, 200000000, 269333333 },
> +                               { 0 } },
> +               .reg = { "csiphy2", "csiphy2_clk_mux" },
> +               .interrupt = { "csiphy2" }
> +       }
> +};
> +
> +static const struct resources csid_res_660[] = {
> +       /* CSID0 */
> +       {
> +               .regulator = { "vdda", "vdd_sec" },
> +               .clock = { "top_ahb", "ispif_ahb", "csi0_ahb", "ahb",
> +                          "csi0", "csi0_phy", "csi0_pix", "csi0_rdi",
> +                          "cphy_csid0" },
> +               .clock_rate = { { 0 },
> +                               { 0 },
> +                               { 0 },
> +                               { 0 },
> +                               { 100000000, 200000000, 310000000,
> +                                 404000000, 465000000 },
> +                               { 0 },
> +                               { 0 },
> +                               { 0 },
> +                               { 0 } },
> +               .reg = { "csid0" },
> +               .interrupt = { "csid0" }
> +       },
> +
> +       /* CSID1 */
> +       {
> +               .regulator = { "vdda", "vdd_sec" },
> +               .clock = { "top_ahb", "ispif_ahb", "csi1_ahb", "ahb",
> +                          "csi1", "csi1_phy", "csi1_pix", "csi1_rdi",
> +                          "cphy_csid1" },
> +               .clock_rate = { { 0 },
> +                               { 0 },
> +                               { 0 },
> +                               { 0 },
> +                               { 100000000, 200000000, 310000000,
> +                                 404000000, 465000000 },
> +                               { 0 },
> +                               { 0 },
> +                               { 0 },
> +                               { 0 } },
> +               .reg = { "csid1" },
> +               .interrupt = { "csid1" }
> +       },
> +
> +       /* CSID2 */
> +       {
> +               .regulator = { "vdda", "vdd_sec" },
> +               .clock = { "top_ahb", "ispif_ahb", "csi2_ahb", "ahb",
> +                          "csi2", "csi2_phy", "csi2_pix", "csi2_rdi",
> +                          "cphy_csid2" },
> +               .clock_rate = { { 0 },
> +                               { 0 },
> +                               { 0 },
> +                               { 0 },
> +                               { 100000000, 200000000, 310000000,
> +                                 404000000, 465000000 },
> +                               { 0 },
> +                               { 0 },
> +                               { 0 },
> +                               { 0 } },
> +               .reg = { "csid2" },
> +               .interrupt = { "csid2" }
> +       },
> +
> +       /* CSID3 */
> +       {
> +               .regulator = { "vdda", "vdd_sec" },
> +               .clock = { "top_ahb", "ispif_ahb", "csi3_ahb", "ahb",
> +                          "csi3", "csi3_phy", "csi3_pix", "csi3_rdi",
> +                          "cphy_csid3" },
> +               .clock_rate = { { 0 },
> +                               { 0 },
> +                               { 0 },
> +                               { 0 },
> +                               { 100000000, 200000000, 310000000,
> +                                 404000000, 465000000 },
> +                               { 0 },
> +                               { 0 },
> +                               { 0 },
> +                               { 0 } },
> +               .reg = { "csid3" },
> +               .interrupt = { "csid3" }
> +       }
> +};
> +
> +static const struct resources_ispif ispif_res_660 = {
> +       /* ISPIF */
> +       .clock = { "top_ahb", "ahb", "ispif_ahb",
> +                  "csi0", "csi0_pix", "csi0_rdi",
> +                  "csi1", "csi1_pix", "csi1_rdi",
> +                  "csi2", "csi2_pix", "csi2_rdi",
> +                  "csi3", "csi3_pix", "csi3_rdi" },
> +       .clock_for_reset = { "vfe0", "csi_vfe0", "vfe1", "csi_vfe1" },
> +       .reg = { "ispif", "csi_clk_mux" },
> +       .interrupt = "ispif"
> +};
> +
> +static const struct resources vfe_res_660[] = {
> +       /* VFE0 */
> +       {
> +               .regulator = { NULL },
> +               .clock = { "throttle_axi", "top_ahb", "ahb", "vfe0",
> +                          "csi_vfe0", "vfe_ahb", "vfe0_ahb", "vfe_axi",
> +                          "vfe0_stream"},
> +               .clock_rate = { { 0 },
> +                               { 0 },
> +                               { 0 },
> +                               { 120000000, 200000000, 256000000,
> +                                 300000000, 404000000, 480000000,
> +                                 540000000, 576000000 },
> +                               { 0 },
> +                               { 0 },
> +                               { 0 },
> +                               { 0 },
> +                               { 0 } },
> +               .reg = { "vfe0" },
> +               .interrupt = { "vfe0" }
> +       },
> +
> +       /* VFE1 */
> +       {
> +               .regulator = { NULL },
> +               .clock = { "throttle_axi", "top_ahb", "ahb", "vfe1",
> +                          "csi_vfe1", "vfe_ahb", "vfe1_ahb", "vfe_axi",
> +                          "vfe1_stream"},
> +               .clock_rate = { { 0 },
> +                               { 0 },
> +                               { 0 },
> +                               { 120000000, 200000000, 256000000,
> +                                 300000000, 404000000, 480000000,
> +                                 540000000, 576000000 },
> +                               { 0 },
> +                               { 0 },
> +                               { 0 },
> +                               { 0 },
> +                               { 0 } },
> +               .reg = { "vfe1" },
> +               .interrupt = { "vfe1" }
> +       }
> +};
> +
>  /*
>   * camss_add_clock_margin - Add margin to clock frequency rate
>   * @rate: Clock frequency rate
> @@ -397,7 +579,8 @@ int camss_get_pixel_clock(struct media_entity *entity, u32 *pixel_clock)
>
>  int camss_pm_domain_on(struct camss *camss, int id)
>  {
> -       if (camss->version == CAMSS_8x96) {
> +       if (camss->version == CAMSS_8x96 ||
> +           camss->version == CAMSS_660) {
>                 camss->genpd_link[id] = device_link_add(camss->dev,
>                                 camss->genpd[id], DL_FLAG_STATELESS |
>                                 DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE);
> @@ -411,7 +594,8 @@ int camss_pm_domain_on(struct camss *camss, int id)
>
>  void camss_pm_domain_off(struct camss *camss, int id)
>  {
> -       if (camss->version == CAMSS_8x96)
> +       if (camss->version == CAMSS_8x96 ||
> +           camss->version == CAMSS_660)
>                 device_link_del(camss->genpd_link[id]);
>  }
>
> @@ -533,6 +717,11 @@ static int camss_init_subdevices(struct camss *camss)
>                 csid_res = csid_res_8x96;
>                 ispif_res = &ispif_res_8x96;
>                 vfe_res = vfe_res_8x96;
> +       } else if (camss->version == CAMSS_660) {
> +               csiphy_res = csiphy_res_660;
> +               csid_res = csid_res_660;
> +               ispif_res = &ispif_res_660;
> +               vfe_res = vfe_res_660;
>         } else {
>                 return -EINVAL;
>         }
> @@ -833,6 +1022,12 @@ static int camss_probe(struct platform_device *pdev)
>                 camss->csiphy_num = 3;
>                 camss->csid_num = 4;
>                 camss->vfe_num = 2;
> +       } else if (of_device_is_compatible(dev->of_node,
> +                                          "qcom,sdm660-camss")) {
> +               camss->version = CAMSS_660;
> +               camss->csiphy_num = 3;
> +               camss->csid_num = 4;
> +               camss->vfe_num = 2;
>         } else {
>                 ret = -EINVAL;
>                 goto err_free;
> @@ -919,7 +1114,8 @@ static int camss_probe(struct platform_device *pdev)
>                 }
>         }
>
> -       if (camss->version == CAMSS_8x96) {
> +       if (camss->version == CAMSS_8x96 ||
> +           camss->version == CAMSS_660) {
>                 camss->genpd[PM_DOMAIN_VFE0] = dev_pm_domain_attach_by_id(
>                                                 camss->dev, PM_DOMAIN_VFE0);
>                 if (IS_ERR(camss->genpd[PM_DOMAIN_VFE0]))
> @@ -958,7 +1154,8 @@ void camss_delete(struct camss *camss)
>
>         pm_runtime_disable(camss->dev);
>
> -       if (camss->version == CAMSS_8x96) {
> +       if (camss->version == CAMSS_8x96 ||
> +           camss->version == CAMSS_660) {
>                 dev_pm_domain_detach(camss->genpd[PM_DOMAIN_VFE0], true);
>                 dev_pm_domain_detach(camss->genpd[PM_DOMAIN_VFE1], true);
>         }
> @@ -989,6 +1186,7 @@ static int camss_remove(struct platform_device *pdev)
>  static const struct of_device_id camss_dt_match[] = {
>         { .compatible = "qcom,msm8916-camss" },
>         { .compatible = "qcom,msm8996-camss" },
> +       { .compatible = "qcom,sdm660-camss" },
>         { }
>  };
>
> diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h
> index 1376b07889bf..3a0484683cd6 100644
> --- a/drivers/media/platform/qcom/camss/camss.h
> +++ b/drivers/media/platform/qcom/camss/camss.h
> @@ -65,6 +65,7 @@ enum pm_domain {
>  enum camss_version {
>         CAMSS_8x16,
>         CAMSS_8x96,
> +       CAMSS_660,
>  };
>
>  struct camss {
> --
> 2.28.0
>
diff mbox series

Patch

diff --git a/drivers/media/platform/qcom/camss/camss-csid.c b/drivers/media/platform/qcom/camss/camss-csid.c
index 2ffcda06706b..be3fe76f3dc3 100644
--- a/drivers/media/platform/qcom/camss/camss-csid.c
+++ b/drivers/media/platform/qcom/camss/camss-csid.c
@@ -383,7 +383,8 @@  static u32 csid_src_pad_code(struct csid_device *csid, u32 sink_code,
 			return 0;
 
 		return sink_code;
-	} else if (csid->camss->version == CAMSS_8x96) {
+	} else if (csid->camss->version == CAMSS_8x96 ||
+		   csid->camss->version == CAMSS_660) {
 		switch (sink_code) {
 		case MEDIA_BUS_FMT_SBGGR10_1X10:
 		{
@@ -718,7 +719,8 @@  static int csid_set_stream(struct v4l2_subdev *sd, int enable)
 		val |= df << CAMSS_CSID_CID_n_CFG_DECODE_FORMAT_SHIFT;
 		val |= CAMSS_CSID_CID_n_CFG_RDI_MODE_RAW_DUMP;
 
-		if (csid->camss->version == CAMSS_8x96) {
+		if (csid->camss->version == CAMSS_8x96 ||
+		    csid->camss->version == CAMSS_660) {
 			u32 sink_code = csid->fmt[MSM_CSID_PAD_SINK].code;
 			u32 src_code = csid->fmt[MSM_CSID_PAD_SRC].code;
 
@@ -1098,7 +1100,8 @@  int msm_csid_subdev_init(struct camss *camss, struct csid_device *csid,
 		csid->formats = csid_formats_8x16;
 		csid->nformats =
 				ARRAY_SIZE(csid_formats_8x16);
-	} else if (camss->version == CAMSS_8x96) {
+	} else if (camss->version == CAMSS_8x96 ||
+		   camss->version == CAMSS_660) {
 		csid->formats = csid_formats_8x96;
 		csid->nformats =
 				ARRAY_SIZE(csid_formats_8x96);
diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.c b/drivers/media/platform/qcom/camss/camss-csiphy.c
index 03ef9c5f4774..c00f25aac21b 100644
--- a/drivers/media/platform/qcom/camss/camss-csiphy.c
+++ b/drivers/media/platform/qcom/camss/camss-csiphy.c
@@ -552,7 +552,8 @@  int msm_csiphy_subdev_init(struct camss *camss,
 		csiphy->ops = &csiphy_ops_2ph_1_0;
 		csiphy->formats = csiphy_formats_8x16;
 		csiphy->nformats = ARRAY_SIZE(csiphy_formats_8x16);
-	} else if (camss->version == CAMSS_8x96) {
+	} else if (camss->version == CAMSS_8x96 ||
+		   camss->version == CAMSS_660) {
 		csiphy->ops = &csiphy_ops_3ph_1_0;
 		csiphy->formats = csiphy_formats_8x96;
 		csiphy->nformats = ARRAY_SIZE(csiphy_formats_8x96);
diff --git a/drivers/media/platform/qcom/camss/camss-ispif.c b/drivers/media/platform/qcom/camss/camss-ispif.c
index 252db6b33dab..adeb92808998 100644
--- a/drivers/media/platform/qcom/camss/camss-ispif.c
+++ b/drivers/media/platform/qcom/camss/camss-ispif.c
@@ -263,6 +263,7 @@  static irqreturn_t ispif_isr_8x16(int irq, void *dev)
 
 static int ispif_vfe_reset(struct ispif_device *ispif, u8 vfe_id)
 {
+	unsigned long time;
 	u32 val;
 
 	if (vfe_id > (to_camss(ispif)->vfe_num - 1)) {
@@ -315,7 +316,6 @@  static int ispif_vfe_reset(struct ispif_device *ispif, u8 vfe_id)
  */
 static int ispif_reset(struct ispif_device *ispif, u8 vfe_id)
 {
-	unsigned long time;
 	int ret;
 
 	ret = camss_pm_domain_on(to_camss(ispif), PM_DOMAIN_VFE0);
@@ -825,7 +825,8 @@  static int ispif_set_stream(struct v4l2_subdev *sd, int enable)
 		ispif_select_csid(ispif, intf, csid, vfe, 1);
 		ispif_select_cid(ispif, intf, cid, vfe, 1);
 		ispif_config_irq(ispif, intf, vfe, 1);
-		if (to_camss(ispif)->version == CAMSS_8x96)
+		if (to_camss(ispif)->version == CAMSS_8x96 ||
+		    to_camss(ispif)->version == CAMSS_660)
 			ispif_config_pack(ispif,
 					  line->fmt[MSM_ISPIF_PAD_SINK].code,
 					  intf, cid, vfe, 1);
@@ -842,7 +843,8 @@  static int ispif_set_stream(struct v4l2_subdev *sd, int enable)
 			return ret;
 
 		mutex_lock(&ispif->config_lock);
-		if (to_camss(ispif)->version == CAMSS_8x96)
+		if (to_camss(ispif)->version == CAMSS_8x96 ||
+		    to_camss(ispif)->version == CAMSS_660)
 			ispif_config_pack(ispif,
 					  line->fmt[MSM_ISPIF_PAD_SINK].code,
 					  intf, cid, vfe, 0);
@@ -1098,7 +1100,8 @@  int msm_ispif_subdev_init(struct ispif_device *ispif,
 	/* Number of ISPIF lines - same as number of CSID hardware modules */
 	if (to_camss(ispif)->version == CAMSS_8x16)
 		ispif->line_num = 2;
-	else if (to_camss(ispif)->version == CAMSS_8x96)
+	else if (to_camss(ispif)->version == CAMSS_8x96 ||
+		 to_camss(ispif)->version == CAMSS_660)
 		ispif->line_num = 4;
 	else
 		return -EINVAL;
@@ -1116,7 +1119,8 @@  int msm_ispif_subdev_init(struct ispif_device *ispif,
 			ispif->line[i].formats = ispif_formats_8x16;
 			ispif->line[i].nformats =
 					ARRAY_SIZE(ispif_formats_8x16);
-		} else if (to_camss(ispif)->version == CAMSS_8x96) {
+		} else if (to_camss(ispif)->version == CAMSS_8x96 ||
+			   to_camss(ispif)->version == CAMSS_660) {
 			ispif->line[i].formats = ispif_formats_8x96;
 			ispif->line[i].nformats =
 					ARRAY_SIZE(ispif_formats_8x96);
@@ -1156,7 +1160,8 @@  int msm_ispif_subdev_init(struct ispif_device *ispif,
 	if (to_camss(ispif)->version == CAMSS_8x16)
 		ret = devm_request_irq(dev, ispif->irq, ispif_isr_8x16,
 			       IRQF_TRIGGER_RISING, ispif->irq_name, ispif);
-	else if (to_camss(ispif)->version == CAMSS_8x96)
+	else if (to_camss(ispif)->version == CAMSS_8x96 ||
+		 to_camss(ispif)->version == CAMSS_660)
 		ret = devm_request_irq(dev, ispif->irq, ispif_isr_8x96,
 			       IRQF_TRIGGER_RISING, ispif->irq_name, ispif);
 	else
diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c
index b7d2293a5004..fae2b513b2f9 100644
--- a/drivers/media/platform/qcom/camss/camss-vfe.c
+++ b/drivers/media/platform/qcom/camss/camss-vfe.c
@@ -205,7 +205,8 @@  static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code,
 
 			return sink_code;
 		}
-	else if (vfe->camss->version == CAMSS_8x96)
+	else if (vfe->camss->version == CAMSS_8x96 ||
+		 vfe->camss->version == CAMSS_660)
 		switch (sink_code) {
 		case MEDIA_BUS_FMT_YUYV8_2X8:
 		{
@@ -1991,12 +1992,19 @@  int msm_vfe_subdev_init(struct camss *camss, struct vfe_device *vfe,
 	vfe->isr_ops.comp_done = vfe_isr_comp_done;
 	vfe->isr_ops.wm_done = vfe_isr_wm_done;
 
-	if (camss->version == CAMSS_8x16)
+	switch (camss->version) {
+	case CAMSS_8x16:
 		vfe->ops = &vfe_ops_4_1;
-	else if (camss->version == CAMSS_8x96)
+		break;
+	case CAMSS_8x96:
 		vfe->ops = &vfe_ops_4_7;
-	else
+		break;
+	case CAMSS_660:
+		vfe->ops = &vfe_ops_4_8;
+		break;
+	default:
 		return -EINVAL;
+	}
 
 	/* Memory */
 
@@ -2095,7 +2103,8 @@  int msm_vfe_subdev_init(struct camss *camss, struct vfe_device *vfe,
 				l->formats = formats_rdi_8x16;
 				l->nformats = ARRAY_SIZE(formats_rdi_8x16);
 			}
-		} else if (camss->version == CAMSS_8x96) {
+		} else if (camss->version == CAMSS_8x96 ||
+			   camss->version == CAMSS_660) {
 			if (i == VFE_LINE_PIX) {
 				l->formats = formats_pix_8x96;
 				l->nformats = ARRAY_SIZE(formats_pix_8x96);
diff --git a/drivers/media/platform/qcom/camss/camss-video.c b/drivers/media/platform/qcom/camss/camss-video.c
index 114c3ae4a4ab..fbba9e45d732 100644
--- a/drivers/media/platform/qcom/camss/camss-video.c
+++ b/drivers/media/platform/qcom/camss/camss-video.c
@@ -970,7 +970,8 @@  int msm_video_register(struct camss_video *video, struct v4l2_device *v4l2_dev,
 			video->formats = formats_rdi_8x16;
 			video->nformats = ARRAY_SIZE(formats_rdi_8x16);
 		}
-	} else if (video->camss->version == CAMSS_8x96) {
+	} else if (video->camss->version == CAMSS_8x96 ||
+		   video->camss->version == CAMSS_660) {
 		if (is_pix) {
 			video->formats = formats_pix_8x96;
 			video->nformats = ARRAY_SIZE(formats_pix_8x96);
diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c
index 9186881afc98..8fefce57bc49 100644
--- a/drivers/media/platform/qcom/camss/camss.c
+++ b/drivers/media/platform/qcom/camss/camss.c
@@ -283,6 +283,188 @@  static const struct resources vfe_res_8x96[] = {
 	}
 };
 
+static const struct resources csiphy_res_660[] = {
+	/* CSIPHY0 */
+	{
+		.regulator = { NULL },
+		.clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy0_timer",
+			   "csi0_phy", "csiphy_ahb2crif" },
+		.clock_rate = { { 0 },
+				{ 0 },
+				{ 0 },
+				{ 100000000, 200000000, 269333333 },
+				{ 0 } },
+		.reg = { "csiphy0", "csiphy0_clk_mux" },
+		.interrupt = { "csiphy0" }
+	},
+
+	/* CSIPHY1 */
+	{
+		.regulator = { NULL },
+		.clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy1_timer",
+			   "csi1_phy", "csiphy_ahb2crif" },
+		.clock_rate = { { 0 },
+				{ 0 },
+				{ 0 },
+				{ 100000000, 200000000, 269333333 },
+				{ 0 } },
+		.reg = { "csiphy1", "csiphy1_clk_mux" },
+		.interrupt = { "csiphy1" }
+	},
+
+	/* CSIPHY2 */
+	{
+		.regulator = { NULL },
+		.clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy2_timer",
+			   "csi2_phy", "csiphy_ahb2crif" },
+		.clock_rate = { { 0 },
+				{ 0 },
+				{ 0 },
+				{ 100000000, 200000000, 269333333 },
+				{ 0 } },
+		.reg = { "csiphy2", "csiphy2_clk_mux" },
+		.interrupt = { "csiphy2" }
+	}
+};
+
+static const struct resources csid_res_660[] = {
+	/* CSID0 */
+	{
+		.regulator = { "vdda", "vdd_sec" },
+		.clock = { "top_ahb", "ispif_ahb", "csi0_ahb", "ahb",
+			   "csi0", "csi0_phy", "csi0_pix", "csi0_rdi",
+			   "cphy_csid0" },
+		.clock_rate = { { 0 },
+				{ 0 },
+				{ 0 },
+				{ 0 },
+				{ 100000000, 200000000, 310000000,
+				  404000000, 465000000 },
+				{ 0 },
+				{ 0 },
+				{ 0 },
+				{ 0 } },
+		.reg = { "csid0" },
+		.interrupt = { "csid0" }
+	},
+
+	/* CSID1 */
+	{
+		.regulator = { "vdda", "vdd_sec" },
+		.clock = { "top_ahb", "ispif_ahb", "csi1_ahb", "ahb",
+			   "csi1", "csi1_phy", "csi1_pix", "csi1_rdi",
+			   "cphy_csid1" },
+		.clock_rate = { { 0 },
+				{ 0 },
+				{ 0 },
+				{ 0 },
+				{ 100000000, 200000000, 310000000,
+				  404000000, 465000000 },
+				{ 0 },
+				{ 0 },
+				{ 0 },
+				{ 0 } },
+		.reg = { "csid1" },
+		.interrupt = { "csid1" }
+	},
+
+	/* CSID2 */
+	{
+		.regulator = { "vdda", "vdd_sec" },
+		.clock = { "top_ahb", "ispif_ahb", "csi2_ahb", "ahb",
+			   "csi2", "csi2_phy", "csi2_pix", "csi2_rdi",
+			   "cphy_csid2" },
+		.clock_rate = { { 0 },
+				{ 0 },
+				{ 0 },
+				{ 0 },
+				{ 100000000, 200000000, 310000000,
+				  404000000, 465000000 },
+				{ 0 },
+				{ 0 },
+				{ 0 },
+				{ 0 } },
+		.reg = { "csid2" },
+		.interrupt = { "csid2" }
+	},
+
+	/* CSID3 */
+	{
+		.regulator = { "vdda", "vdd_sec" },
+		.clock = { "top_ahb", "ispif_ahb", "csi3_ahb", "ahb",
+			   "csi3", "csi3_phy", "csi3_pix", "csi3_rdi",
+			   "cphy_csid3" },
+		.clock_rate = { { 0 },
+				{ 0 },
+				{ 0 },
+				{ 0 },
+				{ 100000000, 200000000, 310000000,
+				  404000000, 465000000 },
+				{ 0 },
+				{ 0 },
+				{ 0 },
+				{ 0 } },
+		.reg = { "csid3" },
+		.interrupt = { "csid3" }
+	}
+};
+
+static const struct resources_ispif ispif_res_660 = {
+	/* ISPIF */
+	.clock = { "top_ahb", "ahb", "ispif_ahb",
+		   "csi0", "csi0_pix", "csi0_rdi",
+		   "csi1", "csi1_pix", "csi1_rdi",
+		   "csi2", "csi2_pix", "csi2_rdi",
+		   "csi3", "csi3_pix", "csi3_rdi" },
+	.clock_for_reset = { "vfe0", "csi_vfe0", "vfe1", "csi_vfe1" },
+	.reg = { "ispif", "csi_clk_mux" },
+	.interrupt = "ispif"
+};
+
+static const struct resources vfe_res_660[] = {
+	/* VFE0 */
+	{
+		.regulator = { NULL },
+		.clock = { "throttle_axi", "top_ahb", "ahb", "vfe0",
+			   "csi_vfe0", "vfe_ahb", "vfe0_ahb", "vfe_axi",
+			   "vfe0_stream"},
+		.clock_rate = { { 0 },
+				{ 0 },
+				{ 0 },
+				{ 120000000, 200000000, 256000000,
+				  300000000, 404000000, 480000000,
+				  540000000, 576000000 },
+				{ 0 },
+				{ 0 },
+				{ 0 },
+				{ 0 },
+				{ 0 } },
+		.reg = { "vfe0" },
+		.interrupt = { "vfe0" }
+	},
+
+	/* VFE1 */
+	{
+		.regulator = { NULL },
+		.clock = { "throttle_axi", "top_ahb", "ahb", "vfe1",
+			   "csi_vfe1", "vfe_ahb", "vfe1_ahb", "vfe_axi",
+			   "vfe1_stream"},
+		.clock_rate = { { 0 },
+				{ 0 },
+				{ 0 },
+				{ 120000000, 200000000, 256000000,
+				  300000000, 404000000, 480000000,
+				  540000000, 576000000 },
+				{ 0 },
+				{ 0 },
+				{ 0 },
+				{ 0 },
+				{ 0 } },
+		.reg = { "vfe1" },
+		.interrupt = { "vfe1" }
+	}
+};
+
 /*
  * camss_add_clock_margin - Add margin to clock frequency rate
  * @rate: Clock frequency rate
@@ -397,7 +579,8 @@  int camss_get_pixel_clock(struct media_entity *entity, u32 *pixel_clock)
 
 int camss_pm_domain_on(struct camss *camss, int id)
 {
-	if (camss->version == CAMSS_8x96) {
+	if (camss->version == CAMSS_8x96 ||
+	    camss->version == CAMSS_660) {
 		camss->genpd_link[id] = device_link_add(camss->dev,
 				camss->genpd[id], DL_FLAG_STATELESS |
 				DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE);
@@ -411,7 +594,8 @@  int camss_pm_domain_on(struct camss *camss, int id)
 
 void camss_pm_domain_off(struct camss *camss, int id)
 {
-	if (camss->version == CAMSS_8x96)
+	if (camss->version == CAMSS_8x96 ||
+	    camss->version == CAMSS_660)
 		device_link_del(camss->genpd_link[id]);
 }
 
@@ -533,6 +717,11 @@  static int camss_init_subdevices(struct camss *camss)
 		csid_res = csid_res_8x96;
 		ispif_res = &ispif_res_8x96;
 		vfe_res = vfe_res_8x96;
+	} else if (camss->version == CAMSS_660) {
+		csiphy_res = csiphy_res_660;
+		csid_res = csid_res_660;
+		ispif_res = &ispif_res_660;
+		vfe_res = vfe_res_660;
 	} else {
 		return -EINVAL;
 	}
@@ -833,6 +1022,12 @@  static int camss_probe(struct platform_device *pdev)
 		camss->csiphy_num = 3;
 		camss->csid_num = 4;
 		camss->vfe_num = 2;
+	} else if (of_device_is_compatible(dev->of_node,
+					   "qcom,sdm660-camss")) {
+		camss->version = CAMSS_660;
+		camss->csiphy_num = 3;
+		camss->csid_num = 4;
+		camss->vfe_num = 2;
 	} else {
 		ret = -EINVAL;
 		goto err_free;
@@ -919,7 +1114,8 @@  static int camss_probe(struct platform_device *pdev)
 		}
 	}
 
-	if (camss->version == CAMSS_8x96) {
+	if (camss->version == CAMSS_8x96 ||
+	    camss->version == CAMSS_660) {
 		camss->genpd[PM_DOMAIN_VFE0] = dev_pm_domain_attach_by_id(
 						camss->dev, PM_DOMAIN_VFE0);
 		if (IS_ERR(camss->genpd[PM_DOMAIN_VFE0]))
@@ -958,7 +1154,8 @@  void camss_delete(struct camss *camss)
 
 	pm_runtime_disable(camss->dev);
 
-	if (camss->version == CAMSS_8x96) {
+	if (camss->version == CAMSS_8x96 ||
+	    camss->version == CAMSS_660) {
 		dev_pm_domain_detach(camss->genpd[PM_DOMAIN_VFE0], true);
 		dev_pm_domain_detach(camss->genpd[PM_DOMAIN_VFE1], true);
 	}
@@ -989,6 +1186,7 @@  static int camss_remove(struct platform_device *pdev)
 static const struct of_device_id camss_dt_match[] = {
 	{ .compatible = "qcom,msm8916-camss" },
 	{ .compatible = "qcom,msm8996-camss" },
+	{ .compatible = "qcom,sdm660-camss" },
 	{ }
 };
 
diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h
index 1376b07889bf..3a0484683cd6 100644
--- a/drivers/media/platform/qcom/camss/camss.h
+++ b/drivers/media/platform/qcom/camss/camss.h
@@ -65,6 +65,7 @@  enum pm_domain {
 enum camss_version {
 	CAMSS_8x16,
 	CAMSS_8x96,
+	CAMSS_660,
 };
 
 struct camss {