diff options
author | Javier Martin <javier.martin@vista-silicon.com> | 2012-02-22 05:34:36 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-03-08 07:42:31 -0500 |
commit | d84279e6d7266e11bef19de4f624849daa70bc48 (patch) | |
tree | e8ff885e18f680aae3492cbb42bfc482dd2bf123 | |
parent | cdc9d6f191d81aa1b1b34db9d3a33f779f5c5ec7 (diff) |
[media] media i.MX27 camera: handle overflows properly
Signed-off-by: Javier Martin <javier.martin@vista-silicon.com>
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/video/mx2_camera.c | 38 |
1 files changed, 19 insertions, 19 deletions
diff --git a/drivers/media/video/mx2_camera.c b/drivers/media/video/mx2_camera.c index fc5ffe47c558..32a9d76d69c8 100644 --- a/drivers/media/video/mx2_camera.c +++ b/drivers/media/video/mx2_camera.c | |||
@@ -1198,7 +1198,7 @@ static struct soc_camera_host_ops mx2_soc_camera_host_ops = { | |||
1198 | }; | 1198 | }; |
1199 | 1199 | ||
1200 | static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, | 1200 | static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, |
1201 | int bufnum) | 1201 | int bufnum, bool err) |
1202 | { | 1202 | { |
1203 | struct mx2_fmt_cfg *prp = pcdev->emma_prp; | 1203 | struct mx2_fmt_cfg *prp = pcdev->emma_prp; |
1204 | struct mx2_buffer *buf; | 1204 | struct mx2_buffer *buf; |
@@ -1245,7 +1245,10 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, | |||
1245 | list_del_init(&buf->queue); | 1245 | list_del_init(&buf->queue); |
1246 | do_gettimeofday(&vb->v4l2_buf.timestamp); | 1246 | do_gettimeofday(&vb->v4l2_buf.timestamp); |
1247 | vb->v4l2_buf.sequence = pcdev->frame_count; | 1247 | vb->v4l2_buf.sequence = pcdev->frame_count; |
1248 | vb2_buffer_done(vb, VB2_BUF_STATE_DONE); | 1248 | if (err) |
1249 | vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); | ||
1250 | else | ||
1251 | vb2_buffer_done(vb, VB2_BUF_STATE_DONE); | ||
1249 | } | 1252 | } |
1250 | 1253 | ||
1251 | pcdev->frame_count++; | 1254 | pcdev->frame_count++; |
@@ -1296,21 +1299,18 @@ static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data) | |||
1296 | } | 1299 | } |
1297 | 1300 | ||
1298 | if (status & (1 << 7)) { /* overflow */ | 1301 | if (status & (1 << 7)) { /* overflow */ |
1299 | u32 cntl; | 1302 | u32 cntl = readl(pcdev->base_emma + PRP_CNTL); |
1300 | /* | ||
1301 | * We only disable channel 1 here since this is the only | ||
1302 | * enabled channel | ||
1303 | * | ||
1304 | * FIXME: the correct DMA overflow handling should be resetting | ||
1305 | * the buffer, returning an error frame, and continuing with | ||
1306 | * the next one. | ||
1307 | */ | ||
1308 | cntl = readl(pcdev->base_emma + PRP_CNTL); | ||
1309 | writel(cntl & ~(PRP_CNTL_CH1EN | PRP_CNTL_CH2EN), | 1303 | writel(cntl & ~(PRP_CNTL_CH1EN | PRP_CNTL_CH2EN), |
1310 | pcdev->base_emma + PRP_CNTL); | 1304 | pcdev->base_emma + PRP_CNTL); |
1311 | writel(cntl, pcdev->base_emma + PRP_CNTL); | 1305 | writel(cntl, pcdev->base_emma + PRP_CNTL); |
1312 | } | 1306 | |
1313 | if (((status & (3 << 5)) == (3 << 5)) || | 1307 | buf = list_entry(pcdev->active_bufs.next, |
1308 | struct mx2_buffer, queue); | ||
1309 | mx27_camera_frame_done_emma(pcdev, | ||
1310 | buf->bufnum, true); | ||
1311 | |||
1312 | status &= ~(1 << 7); | ||
1313 | } else if (((status & (3 << 5)) == (3 << 5)) || | ||
1314 | ((status & (3 << 3)) == (3 << 3))) { | 1314 | ((status & (3 << 3)) == (3 << 3))) { |
1315 | /* | 1315 | /* |
1316 | * Both buffers have triggered, process the one we're expecting | 1316 | * Both buffers have triggered, process the one we're expecting |
@@ -1318,13 +1318,13 @@ static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data) | |||
1318 | */ | 1318 | */ |
1319 | buf = list_entry(pcdev->active_bufs.next, | 1319 | buf = list_entry(pcdev->active_bufs.next, |
1320 | struct mx2_buffer, queue); | 1320 | struct mx2_buffer, queue); |
1321 | mx27_camera_frame_done_emma(pcdev, buf->bufnum); | 1321 | mx27_camera_frame_done_emma(pcdev, buf->bufnum, false); |
1322 | status &= ~(1 << (6 - buf->bufnum)); /* mark processed */ | 1322 | status &= ~(1 << (6 - buf->bufnum)); /* mark processed */ |
1323 | } else if ((status & (1 << 6)) || (status & (1 << 4))) { | ||
1324 | mx27_camera_frame_done_emma(pcdev, 0, false); | ||
1325 | } else if ((status & (1 << 5)) || (status & (1 << 3))) { | ||
1326 | mx27_camera_frame_done_emma(pcdev, 1, false); | ||
1323 | } | 1327 | } |
1324 | if ((status & (1 << 6)) || (status & (1 << 4))) | ||
1325 | mx27_camera_frame_done_emma(pcdev, 0); | ||
1326 | if ((status & (1 << 5)) || (status & (1 << 3))) | ||
1327 | mx27_camera_frame_done_emma(pcdev, 1); | ||
1328 | 1328 | ||
1329 | irq_ok: | 1329 | irq_ok: |
1330 | spin_unlock_irqrestore(&pcdev->lock, flags); | 1330 | spin_unlock_irqrestore(&pcdev->lock, flags); |