summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/platform/ti/cal/cal-camerarx.c1
-rw-r--r--drivers/media/platform/ti/cal/cal.c57
-rw-r--r--drivers/media/platform/ti/cal/cal.h7
3 files changed, 62 insertions, 3 deletions
diff --git a/drivers/media/platform/ti/cal/cal-camerarx.c b/drivers/media/platform/ti/cal/cal-camerarx.c
index a5d9189ae6e3..16ae52879a79 100644
--- a/drivers/media/platform/ti/cal/cal-camerarx.c
+++ b/drivers/media/platform/ti/cal/cal-camerarx.c
@@ -871,6 +871,7 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
phy->cal = cal;
phy->instance = instance;
+ spin_lock_init(&phy->vc_lock);
mutex_init(&phy->mutex);
phy->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
diff --git a/drivers/media/platform/ti/cal/cal.c b/drivers/media/platform/ti/cal/cal.c
index 425b4f4b7ed7..afba0b72a68c 100644
--- a/drivers/media/platform/ti/cal/cal.c
+++ b/drivers/media/platform/ti/cal/cal.c
@@ -543,7 +543,22 @@ void cal_ctx_unprepare(struct cal_ctx *ctx)
void cal_ctx_start(struct cal_ctx *ctx)
{
- ctx->sequence = 0;
+ struct cal_camerarx *phy = ctx->phy;
+
+ /*
+ * Reset the frame number & sequence number, but only if the
+ * virtual channel is not already in use.
+ */
+
+ spin_lock(&phy->vc_lock);
+
+ if (phy->vc_enable_count[ctx->vc]++ == 0) {
+ phy->vc_frame_number[ctx->vc] = 0;
+ phy->vc_sequence[ctx->vc] = 0;
+ }
+
+ spin_unlock(&phy->vc_lock);
+
ctx->dma.state = CAL_DMA_RUNNING;
/* Configure the CSI-2, pixel processing and write DMA contexts. */
@@ -563,8 +578,15 @@ void cal_ctx_start(struct cal_ctx *ctx)
void cal_ctx_stop(struct cal_ctx *ctx)
{
+ struct cal_camerarx *phy = ctx->phy;
long timeout;
+ WARN_ON(phy->vc_enable_count[ctx->vc] == 0);
+
+ spin_lock(&phy->vc_lock);
+ phy->vc_enable_count[ctx->vc]--;
+ spin_unlock(&phy->vc_lock);
+
/*
* Request DMA stop and wait until it completes. If completion times
* out, forcefully disable the DMA.
@@ -601,6 +623,34 @@ void cal_ctx_stop(struct cal_ctx *ctx)
* ------------------------------------------------------------------
*/
+/*
+ * Track a sequence number for each virtual channel, which is shared by
+ * all contexts using the same virtual channel. This is done using the
+ * CSI-2 frame number as a base.
+ */
+static void cal_update_seq_number(struct cal_ctx *ctx)
+{
+ struct cal_dev *cal = ctx->cal;
+ struct cal_camerarx *phy = ctx->phy;
+ u16 prev_frame_num, frame_num;
+ u8 vc = ctx->vc;
+
+ frame_num =
+ cal_read(cal, CAL_CSI2_STATUS(phy->instance, ctx->csi2_ctx)) &
+ 0xffff;
+
+ if (phy->vc_frame_number[vc] != frame_num) {
+ prev_frame_num = phy->vc_frame_number[vc];
+
+ if (prev_frame_num >= frame_num)
+ phy->vc_sequence[vc] += 1;
+ else
+ phy->vc_sequence[vc] += frame_num - prev_frame_num;
+
+ phy->vc_frame_number[vc] = frame_num;
+ }
+}
+
static inline void cal_irq_wdma_start(struct cal_ctx *ctx)
{
spin_lock(&ctx->dma.lock);
@@ -631,6 +681,8 @@ static inline void cal_irq_wdma_start(struct cal_ctx *ctx)
}
spin_unlock(&ctx->dma.lock);
+
+ cal_update_seq_number(ctx);
}
static inline void cal_irq_wdma_end(struct cal_ctx *ctx)
@@ -657,7 +709,8 @@ static inline void cal_irq_wdma_end(struct cal_ctx *ctx)
if (buf) {
buf->vb.vb2_buf.timestamp = ktime_get_ns();
buf->vb.field = ctx->v_fmt.fmt.pix.field;
- buf->vb.sequence = ctx->sequence++;
+ buf->vb.sequence = ctx->phy->vc_sequence[ctx->vc];
+
vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
}
}
diff --git a/drivers/media/platform/ti/cal/cal.h b/drivers/media/platform/ti/cal/cal.h
index 61409ddced98..80f2c9c73c71 100644
--- a/drivers/media/platform/ti/cal/cal.h
+++ b/drivers/media/platform/ti/cal/cal.h
@@ -180,6 +180,12 @@ struct cal_camerarx {
struct media_pad pads[CAL_CAMERARX_NUM_PADS];
struct v4l2_mbus_framefmt formats[CAL_CAMERARX_NUM_PADS];
+ /* protects the vc_* fields below */
+ spinlock_t vc_lock;
+ u8 vc_enable_count[4];
+ u16 vc_frame_number[4];
+ u32 vc_sequence[4];
+
/*
* Lock for camerarx ops. Protects:
* - formats
@@ -242,7 +248,6 @@ struct cal_ctx {
const struct cal_format_info **active_fmt;
unsigned int num_active_fmt;
- unsigned int sequence;
struct vb2_queue vb_vidq;
u8 dma_ctx;
u8 cport;