[PATCH 33/45] media: qcom: camss: sa8775p: add CSID pixel path
From: Gjorgji . Rosikopulos . gjorgji . rosikopulos
Date: Tue Oct 06 2026 - 18:52:44 EST
From: Atanas Filipov <atanas.filipov@xxxxxxxxxxxxxxxx>
Extend the common generation 3 CSID backend with SA8775P streams.
Signed-off-by: Atanas Filipov <atanas.filipov@xxxxxxxxxxxxxxxx>
---
.../platform/qcom/camss/camss-csid-gen3.c | 265 +++++++++++++++++-
.../media/platform/qcom/camss/camss-csid.c | 1 +
.../media/platform/qcom/camss/camss-csid.h | 4 +
drivers/media/platform/qcom/camss/camss-ife.c | 23 ++
drivers/media/platform/qcom/camss/camss-ife.h | 2 +
drivers/media/platform/qcom/camss/camss.c | 1 +
drivers/media/platform/qcom/camss/camss.h | 1 +
7 files changed, 291 insertions(+), 6 deletions(-)
diff --git a/drivers/media/platform/qcom/camss/camss-csid-gen3.c b/drivers/media/platform/qcom/camss/camss-csid-gen3.c
index 0fdbf75fb27d..e44b42215461 100644
--- a/drivers/media/platform/qcom/camss/camss-csid-gen3.c
+++ b/drivers/media/platform/qcom/camss/camss-csid-gen3.c
@@ -4,6 +4,7 @@
*
* Copyright (c) 2024 Qualcomm Technologies, Inc.
*/
+#include <linux/bitfield.h>
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
@@ -19,6 +20,9 @@
#define OUTPUT_IFE_EN 0x100
#define INTERNAL_CSID 1
+#define CSID_GLOBAL_CMD 0x8
+#define GLOBAL_CMD_START BIT(0)
+
#define CSID_RST_CFG 0xC
#define RST_MODE BIT(0)
#define RST_LOCATION BIT(4)
@@ -31,10 +35,12 @@
#define IRQ_CMD_CLEAR BIT(0)
#define CSID_RUP_AUP_CMD 0x18
+#define CSID_RUP_AUP_IPP0 (BIT(0) | BIT(16))
#define CSID_RUP_AUP_RDI(rdi) ((BIT(4) | BIT(20)) << (rdi))
#define CSID_TOP_IRQ_STATUS 0x7C
#define TOP_IRQ_STATUS_RESET_DONE BIT(0)
+#define TOP_IRQ_STATUS_BUF_DONE BIT(14)
#define CSID_TOP_IRQ_MASK 0x80
#define CSID_TOP_IRQ_CLEAR 0x84
@@ -44,6 +50,7 @@
#define CSID_CSI2_RX_IRQ_MASK 0xA0
#define CSID_CSI2_RX_IRQ_CLEAR 0xA4
#define CSID_CSI2_RX_IRQ_SET 0xA8
+#define CSI2_RX_IRQ_ERROR_MASK 0x01bfb800
#define IS_CSID_690(csid) ((csid->camss->res->version == CAMSS_8775P) \
|| (csid->camss->res->version == CAMSS_8300))
@@ -54,6 +61,12 @@
#define CSID_BUF_DONE_IRQ_MASK 0x90
#define CSID_BUF_DONE_IRQ_CLEAR 0x94
#define CSID_BUF_DONE_IRQ_SET 0x98
+#define BUF_DONE_IRQ_STATUS_VID_FULL BIT(0)
+#define BUF_DONE_IRQ_STATUS_DISP_FULL BIT(1)
+#define BUF_DONE_IRQ_STATUS_STATS BIT(5)
+#define BUF_DONE_IRQ_STATUS_PP (BUF_DONE_IRQ_STATUS_VID_FULL | \
+ BUF_DONE_IRQ_STATUS_DISP_FULL | \
+ BUF_DONE_IRQ_STATUS_STATS)
#define CSID_CSI2_RDIN_IRQ_STATUS(rdi) (0xEC + 0x10 * (rdi))
#define RUP_DONE_IRQ_STATUS BIT(23)
@@ -73,6 +86,25 @@
#define CSI2_RX_CFG1_ECC_CORRECTION_EN BIT(0)
#define CSI2_RX_CFG1_VC_MODE BIT(2)
+#define CSID_IPP0_CFG0 0x300
+#define IPP0_CFG0_EN BIT(31)
+#define IPP0_CFG0_VC GENMASK(26, 22)
+#define IPP0_CFG0_DT GENMASK(21, 16)
+#define IPP0_CFG0_DECODE_FMT GENMASK(15, 12)
+
+#define CSID_IPP0_CTRL 0x304
+#define IPP0_CTRL_START_CMD 1
+
+#define CSID_IPP0_CFG1 0x310
+#define IPP0_CFG1_PIX_STORE_EN BIT(14)
+#define IPP0_CFG1_TIMESTAMP_EN BIT(9)
+#define IPP0_CFG1_MIN_HBI GENMASK(7, 4)
+
+#define CSID_IPP0_EPOCH_IRQ_CFG 0x334
+#define CSID_IPP0_EPOCH0_SUBSAMPLE_PATTERN 0x338
+#define CSID_IPP0_EPOCH1_SUBSAMPLE_PATTERN 0x33c
+#define CSID_IPP0_IRQ_SUBSAMPLE_PERIOD 0x380
+
#define CSID_RDI_CFG0(rdi) (csid_is_lite(csid) && IS_CSID_690(csid) ?\
(0x300 + 0x100 * (rdi)) :\
(0x500 + 0x100 * (rdi)))
@@ -97,8 +129,13 @@
#define RDI_CFG1_CROP_H_EN BIT(7)
#define RDI_CFG1_CROP_V_EN BIT(8)
#define RDI_CFG1_PIX_STORE BIT(10)
+#define RDI_CFG1_TIMESTAMP_EN BIT(4)
+#define RDI_CFG1_TIMESTAMP_STB_SEL GENMASK(1, 0)
#define RDI_CFG1_PACKING_FORMAT_MIPI BIT(15)
+#define ERROR_RECOVERY_CFG0_OVERFLOW_CTRL_EN BIT(0)
+#define ERROR_RECOVERY_CFG0_OVERFLOW_CTRL_MODE BIT(3)
+
#define CSID_RDI_IRQ_SUBSAMPLE_PATTERN(rdi) (csid_is_lite(csid) && IS_CSID_690(csid) ?\
(0x348 + 0x100 * (rdi)) :\
(0x548 + 0x100 * (rdi)))
@@ -106,6 +143,39 @@
(0x34C + 0x100 * (rdi)) :\
(0x54C + 0x100 * (rdi)))
#define CSI2_RX_CFG0_PHY_SEL_BASE_IDX 1
+#define CSID_PIX_STREAM_ID 3
+#define EPOCH_IRQ_CFG_EPOCH0_LINE GENMASK(29, 16)
+#define EPOCH_IRQ_CFG_EPOCH1_LINE GENMASK(13, 0)
+
+static bool csid_is_pix_stream(struct csid_device *csid, u32 stream_id)
+{
+ return stream_id == CSID_PIX_STREAM_ID && !csid_is_lite(csid);
+}
+
+static unsigned int csid_num_rdis(struct csid_device *csid)
+{
+ return csid_is_lite(csid) ? 4 : 3;
+}
+
+static u32 csid_rdi_error_recovery_cfg0(struct csid_device *csid, u32 rdi)
+{
+ return (csid_is_lite(csid) ? 0x314 : 0x514) + 0x100 * rdi;
+}
+
+static u32 csid_rdi_epoch_irq_cfg(struct csid_device *csid, u32 rdi)
+{
+ return (csid_is_lite(csid) ? 0x32c : 0x52c) + 0x100 * rdi;
+}
+
+static u32 csid_rdi_epoch0_pattern(struct csid_device *csid, u32 rdi)
+{
+ return (csid_is_lite(csid) ? 0x330 : 0x530) + 0x100 * rdi;
+}
+
+static u32 csid_rdi_epoch1_pattern(struct csid_device *csid, u32 rdi)
+{
+ return (csid_is_lite(csid) ? 0x334 : 0x534) + 0x100 * rdi;
+}
static void __csid_configure_rx(struct csid_device *csid,
struct csid_phy_config *phy, int vc)
@@ -157,6 +227,133 @@ static void __csid_configure_wrapper(struct csid_device *csid)
writel(val, csid->camss->csid_wrapper_base + CSID_IO_PATH_CFG0(csid->id));
}
+static void __csid_configure_ipp(struct csid_device *csid, u8 vc, u8 dt)
+{
+ struct v4l2_mbus_framefmt *input_format =
+ &csid->fmt[MSM_CSID_PAD_FIRST_SRC + CSID_PIX_STREAM_ID];
+ const struct csid_format_info *format =
+ csid_get_fmt_entry(csid->res->formats->formats,
+ csid->res->formats->nformats, input_format->code);
+ u32 val;
+
+ val = IPP0_CFG0_EN;
+ val |= FIELD_PREP(IPP0_CFG0_VC, vc);
+ val |= FIELD_PREP(IPP0_CFG0_DT, dt);
+ val |= FIELD_PREP(IPP0_CFG0_DECODE_FMT, format->decode_format);
+ writel(val, csid->base + CSID_IPP0_CFG0);
+
+ val = IPP0_CFG1_PIX_STORE_EN | IPP0_CFG1_TIMESTAMP_EN;
+ val |= FIELD_PREP(IPP0_CFG1_MIN_HBI, 4);
+ writel(val, csid->base + CSID_IPP0_CFG1);
+
+ val = FIELD_PREP(EPOCH_IRQ_CFG_EPOCH0_LINE, input_format->height / 3);
+ val |= FIELD_PREP(EPOCH_IRQ_CFG_EPOCH1_LINE, input_format->height / 2);
+ writel(val, csid->base + CSID_IPP0_EPOCH_IRQ_CFG);
+ writel(1, csid->base + CSID_IPP0_EPOCH0_SUBSAMPLE_PATTERN);
+ writel(1, csid->base + CSID_IPP0_EPOCH1_SUBSAMPLE_PATTERN);
+ writel(0, csid->base + CSID_IPP0_IRQ_SUBSAMPLE_PERIOD);
+ writel(CSID_RUP_AUP_IPP0, csid->base + CSID_RUP_AUP_CMD);
+}
+
+static void __csid_ctrl_ipp(struct csid_device *csid, bool enable)
+{
+ if (!enable)
+ writel(0, csid->base + CSID_IPP0_CFG0);
+
+ writel(enable ? IPP0_CTRL_START_CMD : 0, csid->base + CSID_IPP0_CTRL);
+}
+
+static void __csid_configure_rdi_streams(struct csid_device *csid, bool enable,
+ u32 port, u8 vc, u8 dt)
+{
+ struct v4l2_mbus_framefmt *input_format =
+ &csid->fmt[MSM_CSID_PAD_FIRST_SRC + port];
+ u32 val;
+
+ if (!enable) {
+ val = readl(csid->base + CSID_RDI_CFG0(port));
+ writel(val & ~RDI_CFG0_EN, csid->base + CSID_RDI_CFG0(port));
+ return;
+ }
+
+ val = DECODE_FORMAT_PAYLOAD_ONLY << RDI_CFG0_DECODE_FORMAT;
+ val |= dt << RDI_CFG0_DT;
+ val |= vc << RDI_CFG0_VC;
+ val |= (port & 0x3) << RDI_CFG0_DT_ID;
+ writel(val, csid->base + CSID_RDI_CFG0(port));
+
+ val = RDI_CFG1_PACKING_FORMAT_MIPI | RDI_CFG1_TIMESTAMP_EN |
+ FIELD_PREP(RDI_CFG1_TIMESTAMP_STB_SEL, 2);
+ writel(val, csid->base + CSID_RDI_CFG1(port));
+
+ val = ERROR_RECOVERY_CFG0_OVERFLOW_CTRL_EN |
+ ERROR_RECOVERY_CFG0_OVERFLOW_CTRL_MODE;
+ writel(val, csid->base + csid_rdi_error_recovery_cfg0(csid, port));
+ writel(0, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PERIOD(port));
+ writel(1, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PATTERN(port));
+
+ val = FIELD_PREP(EPOCH_IRQ_CFG_EPOCH0_LINE, input_format->height / 3);
+ val |= FIELD_PREP(EPOCH_IRQ_CFG_EPOCH1_LINE, input_format->height / 2);
+ writel(val, csid->base + csid_rdi_epoch_irq_cfg(csid, port));
+ writel(1, csid->base + csid_rdi_epoch0_pattern(csid, port));
+ writel(1, csid->base + csid_rdi_epoch1_pattern(csid, port));
+ writel(CSID_RUP_AUP_RDI(port), csid->base + CSID_RUP_AUP_CMD);
+
+ writel(0, csid->base + CSID_RDI_CTRL(port));
+ val = readl(csid->base + CSID_RDI_CFG0(port));
+ writel(val | RDI_CFG0_EN, csid->base + CSID_RDI_CFG0(port));
+}
+
+static void csid_buf_done_irq(struct csid_device *csid, u32 mask, bool enable)
+{
+ unsigned long flags;
+ u32 top_mask;
+ u32 val;
+
+ spin_lock_irqsave(&csid->irq_lock, flags);
+
+ top_mask = readl(csid->base + CSID_TOP_IRQ_MASK);
+ val = readl(csid->base + CSID_BUF_DONE_IRQ_MASK);
+
+ writel(mask, csid->base + CSID_BUF_DONE_IRQ_CLEAR);
+ if (enable) {
+ val |= mask;
+ top_mask |= TOP_IRQ_STATUS_BUF_DONE;
+ } else {
+ val &= ~mask;
+ if (!val)
+ top_mask &= ~TOP_IRQ_STATUS_BUF_DONE;
+ }
+
+ writel(val, csid->base + CSID_BUF_DONE_IRQ_MASK);
+ writel(top_mask, csid->base + CSID_TOP_IRQ_MASK);
+ writel(IRQ_CMD_CLEAR, csid->base + CSID_IRQ_CMD);
+
+ spin_unlock_irqrestore(&csid->irq_lock, flags);
+}
+
+static void csid_buf_done(struct csid_device *csid, u32 status)
+{
+ const struct parent_dev_ops *ops = csid->res->parent_dev_ops;
+ unsigned int i;
+
+ if (!ops->buf_done)
+ return;
+
+ if (!csid_is_lite(csid)) {
+ if (status & BUF_DONE_IRQ_STATUS_VID_FULL)
+ ops->buf_done(csid->camss, csid->id, CAMSS_IFE_OUTPUT_VID_FULL);
+ if (status & BUF_DONE_IRQ_STATUS_DISP_FULL)
+ ops->buf_done(csid->camss, csid->id, CAMSS_IFE_OUTPUT_DISP_FULL);
+ if (status & BUF_DONE_IRQ_STATUS_STATS)
+ ops->buf_done(csid->camss, csid->id, CAMSS_IFE_OUTPUT_STATS);
+ }
+
+ for (i = 0; i < csid_num_rdis(csid); i++)
+ if (status & BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i))
+ ops->buf_done(csid->camss, csid->id, CAMSS_IFE_OUTPUT_RDI0 + i);
+}
+
static void __csid_configure_rdi_stream(struct csid_device *csid, u8 enable, u8 port, u8 vc)
{
u32 val;
@@ -234,6 +431,47 @@ static void csid_configure_stream(struct csid_device *csid, u8 enable)
}
}
+static void csid_configure_rx(struct csid_device *csid)
+{
+ __csid_configure_wrapper(csid);
+ __csid_configure_rx(csid, &csid->phy, 0);
+ writel(CSI2_RX_IRQ_ERROR_MASK, csid->base + CSID_CSI2_RX_IRQ_MASK);
+ writel(GLOBAL_CMD_START, csid->base + CSID_GLOBAL_CMD);
+}
+
+static void csid_enable_stream(struct csid_device *csid, u32 stream_id, u8 vc, u8 dt)
+{
+ u32 mask;
+
+ if (csid_is_pix_stream(csid, stream_id)) {
+ __csid_configure_ipp(csid, vc, dt);
+ mask = BUF_DONE_IRQ_STATUS_PP;
+ csid_buf_done_irq(csid, mask, true);
+ __csid_ctrl_ipp(csid, true);
+ } else if (stream_id < csid_num_rdis(csid)) {
+ mask = BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + stream_id);
+ csid_buf_done_irq(csid, mask, true);
+ __csid_configure_rdi_streams(csid, true, stream_id, vc, dt);
+ __csid_ctrl_rdi(csid, true, stream_id);
+ }
+}
+
+static void csid_disable_stream(struct csid_device *csid, u32 stream_id)
+{
+ u32 mask;
+
+ if (csid_is_pix_stream(csid, stream_id)) {
+ mask = BUF_DONE_IRQ_STATUS_PP;
+ csid_buf_done_irq(csid, mask, false);
+ __csid_ctrl_ipp(csid, false);
+ } else if (stream_id < csid_num_rdis(csid)) {
+ mask = BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + stream_id);
+ csid_buf_done_irq(csid, mask, false);
+ __csid_ctrl_rdi(csid, false, stream_id);
+ __csid_configure_rdi_streams(csid, false, stream_id, 0, 0);
+ }
+}
+
static int csid_configure_testgen_pattern(struct csid_device *csid, s32 val)
{
return 0;
@@ -259,10 +497,14 @@ static void csid_subdev_reg_update(struct csid_device *csid, int port_id, bool c
static irqreturn_t csid_isr(int irq, void *dev)
{
struct csid_device *csid = dev;
- u32 val, buf_done_val;
+ unsigned long flags;
+ u32 buf_done_val;
+ u32 val;
u8 reset_done;
int i;
+ spin_lock_irqsave(&csid->irq_lock, flags);
+
val = readl(csid->base + CSID_TOP_IRQ_STATUS);
writel(val, csid->base + CSID_TOP_IRQ_CLEAR);
reset_done = val & TOP_IRQ_STATUS_RESET_DONE;
@@ -282,8 +524,19 @@ static irqreturn_t csid_isr(int irq, void *dev)
if (val & RUP_DONE_IRQ_STATUS)
/* clear the reg update bit */
csid_subdev_reg_update(csid, i, true);
+ }
+
+ val = IRQ_CMD_CLEAR;
+ writel(val, csid->base + CSID_IRQ_CMD);
+
+ spin_unlock_irqrestore(&csid->irq_lock, flags);
- if (buf_done_val & BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i)) {
+ if (csid->res->streams_enable) {
+ csid_buf_done(csid, buf_done_val);
+ } else {
+ for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++)
+ if (csid->phy.en_vc & BIT(i) &&
+ buf_done_val & BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i)) {
/*
* For Titan Gen3, bus done and RUP IRQ have been moved to
* CSID from VFE. Once CSID received bus done, need notify
@@ -291,10 +544,7 @@ static irqreturn_t csid_isr(int irq, void *dev)
*/
camss_buf_done(csid->camss, csid->id, i);
}
- }
-
- val = IRQ_CMD_CLEAR;
- writel(val, csid->base + CSID_IRQ_CMD);
+ }
if (reset_done)
complete(&csid->reset_complete);
@@ -354,6 +604,9 @@ static void csid_subdev_init(struct csid_device *csid)
const struct csid_hw_ops csid_ops_gen3 = {
.configure_stream = csid_configure_stream,
.configure_testgen_pattern = csid_configure_testgen_pattern,
+ .configure_rx = csid_configure_rx,
+ .enable_stream = csid_enable_stream,
+ .disable_stream = csid_disable_stream,
.hw_version = csid_hw_version,
.isr = csid_isr,
.reset = csid_reset,
diff --git a/drivers/media/platform/qcom/camss/camss-csid.c b/drivers/media/platform/qcom/camss/camss-csid.c
index b7e6bfc58bcf..da13963ef1a0 100644
--- a/drivers/media/platform/qcom/camss/camss-csid.c
+++ b/drivers/media/platform/qcom/camss/camss-csid.c
@@ -1199,6 +1199,7 @@ int msm_csid_subdev_init(struct camss *camss, struct csid_device *csid,
return ret;
init_completion(&csid->reset_complete);
+ spin_lock_init(&csid->irq_lock);
return 0;
}
diff --git a/drivers/media/platform/qcom/camss/camss-csid.h b/drivers/media/platform/qcom/camss/camss-csid.h
index f079956bae8e..2d99b61eb98d 100644
--- a/drivers/media/platform/qcom/camss/camss-csid.h
+++ b/drivers/media/platform/qcom/camss/camss-csid.h
@@ -12,6 +12,8 @@
#include <linux/clk.h>
#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+
#include <media/media-entity.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
@@ -191,6 +193,8 @@ struct csid_device {
struct regulator_bulk_data *supplies;
int num_supplies;
struct completion reset_complete;
+ /* Protects interrupt status, mask, and clear registers. */
+ spinlock_t irq_lock;
struct csid_testgen_config testgen;
bool tpg_linked;
struct csid_phy_config phy;
diff --git a/drivers/media/platform/qcom/camss/camss-ife.c b/drivers/media/platform/qcom/camss/camss-ife.c
index cc5cebfd0862..e2049e00ea96 100644
--- a/drivers/media/platform/qcom/camss/camss-ife.c
+++ b/drivers/media/platform/qcom/camss/camss-ife.c
@@ -1290,6 +1290,29 @@ static const struct v4l2_subdev_ops ife_v4l2_ops = {
.pad = &ife_pad_ops,
};
+void camss_ife_buf_done(struct camss *camss, int id, enum camss_ife_output output)
+{
+ struct ife_device *ife;
+ unsigned long flags;
+ int i;
+
+ if (id >= camss->ife_total_num)
+ return;
+
+ ife = &camss->ife[id];
+ spin_lock_irqsave(&ife->bufs_lock, flags);
+
+ for (i = 0; i < ife->npads; i++) {
+ const struct ife_pad_desc *desc = ife->pads[i].desc;
+ struct ife_video_pad *vpad = ife->pads[i].vid_pad;
+
+ if (vpad && vpad->streaming && desc->output == output)
+ ife_hw_isr_wm_done(ife, vpad);
+ }
+
+ spin_unlock_irqrestore(&ife->bufs_lock, flags);
+}
+
static int ife_video_start_streaming(struct camss_video *vid,
unsigned int count)
{
diff --git a/drivers/media/platform/qcom/camss/camss-ife.h b/drivers/media/platform/qcom/camss/camss-ife.h
index 0ca276203bbb..3d35c17fca7f 100644
--- a/drivers/media/platform/qcom/camss/camss-ife.h
+++ b/drivers/media/platform/qcom/camss/camss-ife.h
@@ -394,6 +394,8 @@ camss_ife_pipe_for_stream_id(int nstreams,
const struct camss_ife_stream *streams,
u32 id);
+void camss_ife_buf_done(struct camss *camss, int id, enum camss_ife_output output);
+
extern const struct ife_pads_descriptors ife_pads_v20x;
extern const struct ife_pads_descriptors ife_pads_v41x;
extern const struct ife_hw_top_ops ife_top_20x_ops;
diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c
index 2dc7864ebe07..7a3e5e6f81e1 100644
--- a/drivers/media/platform/qcom/camss/camss.c
+++ b/drivers/media/platform/qcom/camss/camss.c
@@ -5185,6 +5185,7 @@ static const struct parent_dev_ops ife_parent_dev_ops = {
.get = ife_parent_dev_ops_get,
.put = ife_parent_dev_ops_put,
.get_base_address = ife_parent_dev_ops_get_base_address,
+ .buf_done = camss_ife_buf_done,
};
int camss_attach_host_data(struct camss *camss, struct v4l2_subdev *sd,
diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h
index 65582ff7db23..c19e95df0a54 100644
--- a/drivers/media/platform/qcom/camss/camss.h
+++ b/drivers/media/platform/qcom/camss/camss.h
@@ -201,6 +201,7 @@ struct parent_dev_ops {
int (*get)(struct camss *camss, int id);
int (*put)(struct camss *camss, int id);
void __iomem *(*get_base_address)(struct camss *camss, int id);
+ void (*buf_done)(struct camss *camss, int id, enum camss_ife_output output);
};
void camss_add_clock_margin(u64 *rate);
--
2.34.1