[PATCH v23 04/15] media: qcom: camss: Add addr_update hooks and guard CSID reg_update

Loic Poulain loic.poulain at oss.qualcomm.com
Wed Oct 28 09:36:15 PDT 2026


On Wed, Oct 28, 2026 at 4:21 PM Hangxiang Ma
<hangxiang.ma at oss.qualcomm.com> wrote:
>
> From CSID 680 on, CAMIF was moved into the CSID and the CSID became
> responsible for issuing RUP commands. Starting with CSID 980, RUP and
> AUP are issued separately, and each command must have its corresponding
> SET bit asserted in RUP_AUP_CMD; otherwise, the hardware ignores it.
>
> CSID 980 and newer require a specific stream-on sequence. After the RX
> is configured and before the RDI path is enabled, the CSID must first
> issue an AUP and then a RUP. A RUP issued before that point would leave
> the VFE without a BUF_DONE event. Therefore, once addr_update is set,
> the VFE must skip the initial RUP during stream-on.
>
> Add addr_update hooks and camss_addr_update, and make camss_reg_update
> handle a missing callback safely. The VFE keeps issuing its initial RUP
> during stream-on and behavior is unchanged if nullify addr_update. The
> skip takes effect once a generation that sets addr_update is enabled.
>
> Signed-off-by: Hangxiang Ma <hangxiang.ma at oss.qualcomm.com>

Reviewed-by: Loic Poulain <loic.poulain at oss.qualcomm.com>

> ---
>  drivers/media/platform/qcom/camss/camss-csid.h |  8 ++++++++
>  drivers/media/platform/qcom/camss/camss-vfe.c  |  9 ++++++++-
>  drivers/media/platform/qcom/camss/camss-vfe.h  |  3 +++
>  drivers/media/platform/qcom/camss/camss.c      | 15 ++++++++++++++-
>  drivers/media/platform/qcom/camss/camss.h      |  2 ++
>  5 files changed, 35 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/media/platform/qcom/camss/camss-csid.h b/drivers/media/platform/qcom/camss/camss-csid.h
> index 5296b10f6bac..2f7e593defed 100644
> --- a/drivers/media/platform/qcom/camss/camss-csid.h
> +++ b/drivers/media/platform/qcom/camss/camss-csid.h
> @@ -137,6 +137,14 @@ struct csid_hw_ops {
>          * @is_clear: Indicate if it is clearing reg update or setting reg update
>          */
>         void (*reg_update)(struct csid_device *csid, int port_id, bool is_clear);
> +
> +       /*
> +        * addr_update - latch buffer address update through AUP
> +        * @csid: CSID device
> +        * @port_id: Port id
> +        * @is_clear: Indicate if it is clearing addr update or setting addr update
> +        */
> +       void (*addr_update)(struct csid_device *csid, int port_id, bool is_clear);
>  };
>
>  struct csid_subdev_resources {
> diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c
> index 2680a9914765..4f8867daea4c 100644
> --- a/drivers/media/platform/qcom/camss/camss-vfe.c
> +++ b/drivers/media/platform/qcom/camss/camss-vfe.c
> @@ -487,6 +487,8 @@ void vfe_buf_done(struct vfe_device *vfe, int wm)
>                 ops->vfe_wm_update(vfe, output->wm_idx[0],
>                                    output->buf[index]->addr[0],
>                                    line);
> +               if (ops->addr_update)
> +                       ops->addr_update(vfe, line->id);
>                 ops->reg_update(vfe, line->id);
>         } else {
>                 output->gen2.active_num--;
> @@ -525,6 +527,8 @@ int vfe_enable_output_v2(struct vfe_line *line)
>
>         spin_lock_irqsave(&vfe->output_lock, flags);
>
> +       if (ops->addr_update_clear)
> +               ops->addr_update_clear(vfe, line->id);
>         ops->reg_update_clear(vfe, line->id);
>
>         if (output->state > VFE_OUTPUT_RESERVED) {
> @@ -552,7 +556,8 @@ int vfe_enable_output_v2(struct vfe_line *line)
>                 output->gen2.active_num++;
>                 ops->vfe_wm_update(vfe, output->wm_idx[0],
>                                    output->buf[i]->addr[0], line);
> -               ops->reg_update(vfe, line->id);
> +               if (!ops->addr_update)
> +                       ops->reg_update(vfe, line->id);
>         }
>
>         spin_unlock_irqrestore(&vfe->output_lock, flags);
> @@ -588,6 +593,8 @@ int vfe_queue_buffer_v2(struct camss_video *vid,
>                 output->buf[output->gen2.active_num++] = buf;
>                 ops->vfe_wm_update(vfe, output->wm_idx[0],
>                                    buf->addr[0], line);
> +               if (ops->addr_update)
> +                       ops->addr_update(vfe, line->id);
>                 ops->reg_update(vfe, line->id);
>         } else {
>                 vfe_buf_add_pending(output, buf);
> diff --git a/drivers/media/platform/qcom/camss/camss-vfe.h b/drivers/media/platform/qcom/camss/camss-vfe.h
> index ae9dad353a37..8312e4c91e98 100644
> --- a/drivers/media/platform/qcom/camss/camss-vfe.h
> +++ b/drivers/media/platform/qcom/camss/camss-vfe.h
> @@ -99,6 +99,9 @@ struct vfe_line {
>  struct vfe_device;
>
>  struct vfe_hw_ops {
> +       void (*addr_update)(struct vfe_device *vfe, enum vfe_line_id line_id);
> +       void (*addr_update_clear)(struct vfe_device *vfe,
> +                                 enum vfe_line_id line_id);
>         void (*enable_irq)(struct vfe_device *vfe);
>         void (*global_reset)(struct vfe_device *vfe);
>         u32 (*hw_version)(struct vfe_device *vfe);
> diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c
> index c54185c93a8a..be58a39f4a8b 100644
> --- a/drivers/media/platform/qcom/camss/camss.c
> +++ b/drivers/media/platform/qcom/camss/camss.c
> @@ -5049,7 +5049,20 @@ void camss_reg_update(struct camss *camss, int hw_id, int port_id, bool is_clear
>         if (hw_id < camss->res->csid_num) {
>                 csid = &camss->csid[hw_id];
>
> -               csid->res->hw_ops->reg_update(csid, port_id, is_clear);
> +               if (csid->res->hw_ops->reg_update)
> +                       csid->res->hw_ops->reg_update(csid, port_id, is_clear);
> +       }
> +}
> +
> +void camss_addr_update(struct camss *camss, int hw_id, int port_id, bool is_clear)
> +{
> +       struct csid_device *csid;
> +
> +       if (hw_id < camss->res->csid_num) {
> +               csid = &camss->csid[hw_id];
> +
> +               if (csid->res->hw_ops->addr_update)
> +                       csid->res->hw_ops->addr_update(csid, port_id, is_clear);
>         }
>  }
>
> diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h
> index 7dc2fd9f03e0..431afeb381aa 100644
> --- a/drivers/media/platform/qcom/camss/camss.h
> +++ b/drivers/media/platform/qcom/camss/camss.h
> @@ -182,5 +182,7 @@ void camss_delete(struct camss *camss);
>  void camss_buf_done(struct camss *camss, int hw_id, int port_id);
>  void camss_reg_update(struct camss *camss, int hw_id,
>                       int port_id, bool is_clear);
> +void camss_addr_update(struct camss *camss, int hw_id,
> +                      int port_id, bool is_clear);
>
>  #endif /* QC_MSM_CAMSS_H */
>
> --
> 2.34.1
>



More information about the linux-phy mailing list