[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