aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/s5p-fimc
diff options
context:
space:
mode:
authorSylwester Nawrocki <s.nawrocki@samsung.com>2012-09-21 14:18:41 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-10-05 20:28:04 -0400
commit36fa80927638babe523dce14f3408f9fdefa86d3 (patch)
treefee92facba413f8e31f4dfe2fee3cd2da2a4f97d /drivers/media/platform/s5p-fimc
parentc3010097a79fc741d27b07e068598fd9468ca41f (diff)
[media] s5p-csis: Add support for non-image data packets capture
MIPI-CSI has internal memory mapped buffers for the frame embedded (non-image) data. There are two buffers, for even and odd frames which need to be saved after an interrupt is raised. The packet data buffers size is 4 KiB and there is no status register in the hardware where the actual non-image data size can be read from. Hence the driver copies whole packet data buffer into a buffer provided by the FIMC driver. This will form a separate plane in the user buffer. When FIMC DMA engine is stopped by the driver due the to user space not keeping up with buffer de-queuing the MIPI-CSIS will still run, however it must discard data which is not captured by FIMC. Which frames are actually capture by MIPI-CSIS is determined by means of the s_tx_buffer subdev callback. When it is not called after a single embedded data frame has been captured and copied and before next embedded data frame interrupt occurrs, subsequent embedded data frames will be dropped. Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> Signed-off-by: Andrzej Hajda <a.hajda@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/platform/s5p-fimc')
-rw-r--r--drivers/media/platform/s5p-fimc/mipi-csis.c44
1 files changed, 43 insertions, 1 deletions
diff --git a/drivers/media/platform/s5p-fimc/mipi-csis.c b/drivers/media/platform/s5p-fimc/mipi-csis.c
index 8e4eed8414bd..acf4ce2c4bb9 100644
--- a/drivers/media/platform/s5p-fimc/mipi-csis.c
+++ b/drivers/media/platform/s5p-fimc/mipi-csis.c
@@ -98,6 +98,11 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)");
98#define CSIS_MAX_PIX_WIDTH 0xffff 98#define CSIS_MAX_PIX_WIDTH 0xffff
99#define CSIS_MAX_PIX_HEIGHT 0xffff 99#define CSIS_MAX_PIX_HEIGHT 0xffff
100 100
101/* Non-image packet data buffers */
102#define S5PCSIS_PKTDATA_ODD 0x2000
103#define S5PCSIS_PKTDATA_EVEN 0x3000
104#define S5PCSIS_PKTDATA_SIZE SZ_4K
105
101enum { 106enum {
102 CSIS_CLK_MUX, 107 CSIS_CLK_MUX,
103 CSIS_CLK_GATE, 108 CSIS_CLK_GATE,
@@ -144,6 +149,11 @@ static const struct s5pcsis_event s5pcsis_events[] = {
144}; 149};
145#define S5PCSIS_NUM_EVENTS ARRAY_SIZE(s5pcsis_events) 150#define S5PCSIS_NUM_EVENTS ARRAY_SIZE(s5pcsis_events)
146 151
152struct csis_pktbuf {
153 u32 *data;
154 unsigned int len;
155};
156
147/** 157/**
148 * struct csis_state - the driver's internal state data structure 158 * struct csis_state - the driver's internal state data structure
149 * @lock: mutex serializing the subdev and power management operations, 159 * @lock: mutex serializing the subdev and power management operations,
@@ -159,6 +169,7 @@ static const struct s5pcsis_event s5pcsis_events[] = {
159 * @csis_fmt: current CSIS pixel format 169 * @csis_fmt: current CSIS pixel format
160 * @format: common media bus format for the source and sink pad 170 * @format: common media bus format for the source and sink pad
161 * @slock: spinlock protecting structure members below 171 * @slock: spinlock protecting structure members below
172 * @pkt_buf: the frame embedded (non-image) data buffer
162 * @events: MIPI-CSIS event (error) counters 173 * @events: MIPI-CSIS event (error) counters
163 */ 174 */
164struct csis_state { 175struct csis_state {
@@ -175,6 +186,7 @@ struct csis_state {
175 struct v4l2_mbus_framefmt format; 186 struct v4l2_mbus_framefmt format;
176 187
177 struct spinlock slock; 188 struct spinlock slock;
189 struct csis_pktbuf pkt_buf;
178 struct s5pcsis_event events[S5PCSIS_NUM_EVENTS]; 190 struct s5pcsis_event events[S5PCSIS_NUM_EVENTS];
179}; 191};
180 192
@@ -529,6 +541,22 @@ static int s5pcsis_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
529 return 0; 541 return 0;
530} 542}
531 543
544static int s5pcsis_s_rx_buffer(struct v4l2_subdev *sd, void *buf,
545 unsigned int *size)
546{
547 struct csis_state *state = sd_to_csis_state(sd);
548 unsigned long flags;
549
550 *size = min_t(unsigned int, *size, S5PCSIS_PKTDATA_SIZE);
551
552 spin_lock_irqsave(&state->slock, flags);
553 state->pkt_buf.data = buf;
554 state->pkt_buf.len = *size;
555 spin_unlock_irqrestore(&state->slock, flags);
556
557 return 0;
558}
559
532static int s5pcsis_log_status(struct v4l2_subdev *sd) 560static int s5pcsis_log_status(struct v4l2_subdev *sd)
533{ 561{
534 struct csis_state *state = sd_to_csis_state(sd); 562 struct csis_state *state = sd_to_csis_state(sd);
@@ -566,6 +594,7 @@ static struct v4l2_subdev_pad_ops s5pcsis_pad_ops = {
566}; 594};
567 595
568static struct v4l2_subdev_video_ops s5pcsis_video_ops = { 596static struct v4l2_subdev_video_ops s5pcsis_video_ops = {
597 .s_rx_buffer = s5pcsis_s_rx_buffer,
569 .s_stream = s5pcsis_s_stream, 598 .s_stream = s5pcsis_s_stream,
570}; 599};
571 600
@@ -578,13 +607,26 @@ static struct v4l2_subdev_ops s5pcsis_subdev_ops = {
578static irqreturn_t s5pcsis_irq_handler(int irq, void *dev_id) 607static irqreturn_t s5pcsis_irq_handler(int irq, void *dev_id)
579{ 608{
580 struct csis_state *state = dev_id; 609 struct csis_state *state = dev_id;
610 struct csis_pktbuf *pktbuf = &state->pkt_buf;
581 unsigned long flags; 611 unsigned long flags;
582 u32 status; 612 u32 status;
583 613
584 status = s5pcsis_read(state, S5PCSIS_INTSRC); 614 status = s5pcsis_read(state, S5PCSIS_INTSRC);
585
586 spin_lock_irqsave(&state->slock, flags); 615 spin_lock_irqsave(&state->slock, flags);
587 616
617 if ((status & S5PCSIS_INTSRC_NON_IMAGE_DATA) && pktbuf->data) {
618 u32 offset;
619
620 if (status & S5PCSIS_INTSRC_EVEN)
621 offset = S5PCSIS_PKTDATA_EVEN;
622 else
623 offset = S5PCSIS_PKTDATA_ODD;
624
625 memcpy(pktbuf->data, state->regs + offset, pktbuf->len);
626 pktbuf->data = NULL;
627 rmb();
628 }
629
588 /* Update the event/error counters */ 630 /* Update the event/error counters */
589 if ((status & S5PCSIS_INTSRC_ERRORS) || debug) { 631 if ((status & S5PCSIS_INTSRC_ERRORS) || debug) {
590 int i; 632 int i;