diff options
Diffstat (limited to 'drivers/media/video/marvell-ccic')
-rw-r--r-- | drivers/media/video/marvell-ccic/mcam-core.c | 35 | ||||
-rw-r--r-- | drivers/media/video/marvell-ccic/mcam-core.h | 1 | ||||
-rw-r--r-- | drivers/media/video/marvell-ccic/mmp-driver.c | 13 |
3 files changed, 32 insertions, 17 deletions
diff --git a/drivers/media/video/marvell-ccic/mcam-core.c b/drivers/media/video/marvell-ccic/mcam-core.c index 37d20e73908a..996ac34d9a89 100644 --- a/drivers/media/video/marvell-ccic/mcam-core.c +++ b/drivers/media/video/marvell-ccic/mcam-core.c @@ -509,11 +509,17 @@ static void mcam_sg_next_buffer(struct mcam_camera *cam) buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer, queue); list_del_init(&buf->queue); + /* + * Very Bad Not Good Things happen if you don't clear + * C1_DESC_ENA before making any descriptor changes. + */ + mcam_reg_clear_bit(cam, REG_CTRL1, C1_DESC_ENA); mcam_reg_write(cam, REG_DMA_DESC_Y, buf->dma_desc_pa); mcam_reg_write(cam, REG_DESC_LEN_Y, buf->dma_desc_nent*sizeof(struct mcam_dma_desc)); mcam_reg_write(cam, REG_DESC_LEN_U, 0); mcam_reg_write(cam, REG_DESC_LEN_V, 0); + mcam_reg_set_bit(cam, REG_CTRL1, C1_DESC_ENA); cam->vb_bufs[0] = buf; } @@ -533,7 +539,6 @@ static void mcam_ctlr_dma_sg(struct mcam_camera *cam) mcam_reg_clear_bit(cam, REG_CTRL1, C1_DESC_3WORD); mcam_sg_next_buffer(cam); - mcam_reg_set_bit(cam, REG_CTRL1, C1_DESC_ENA); cam->nbufs = 3; } @@ -556,17 +561,16 @@ static void mcam_dma_sg_done(struct mcam_camera *cam, int frame) struct mcam_vb_buffer *buf = cam->vb_bufs[0]; /* - * Very Bad Not Good Things happen if you don't clear - * C1_DESC_ENA before making any descriptor changes. + * If we're no longer supposed to be streaming, don't do anything. */ - mcam_reg_clear_bit(cam, REG_CTRL1, C1_DESC_ENA); + if (cam->state != S_STREAMING) + return; /* * If we have another buffer available, put it in and * restart the engine. */ if (!list_empty(&cam->buffers)) { mcam_sg_next_buffer(cam); - mcam_reg_set_bit(cam, REG_CTRL1, C1_DESC_ENA); mcam_ctlr_start(cam); /* * Otherwise set CF_SG_RESTART and the controller will @@ -737,7 +741,14 @@ static void mcam_ctlr_stop_dma(struct mcam_camera *cam) mcam_ctlr_stop(cam); cam->state = S_IDLE; spin_unlock_irqrestore(&cam->dev_lock, flags); - msleep(40); + /* + * This is a brutally long sleep, but experience shows that + * it can take the controller a while to get the message that + * it needs to stop grabbing frames. In particular, we can + * sometimes (on mmp) get a frame at the end WITHOUT the + * start-of-frame indication. + */ + msleep(150); if (test_bit(CF_DMA_ACTIVE, &cam->flags)) cam_err(cam, "Timeout waiting for DMA to end\n"); /* This would be bad news - what now? */ @@ -880,6 +891,7 @@ static int mcam_read_setup(struct mcam_camera *cam) * Turn it loose. */ spin_lock_irqsave(&cam->dev_lock, flags); + clear_bit(CF_DMA_ACTIVE, &cam->flags); mcam_reset_buffers(cam); mcam_ctlr_irq_enable(cam); cam->state = S_STREAMING; @@ -922,7 +934,7 @@ static void mcam_vb_buf_queue(struct vb2_buffer *vb) spin_lock_irqsave(&cam->dev_lock, flags); start = (cam->state == S_BUFWAIT) && !list_empty(&cam->buffers); list_add(&mvb->queue, &cam->buffers); - if (test_bit(CF_SG_RESTART, &cam->flags)) + if (cam->state == S_STREAMING && test_bit(CF_SG_RESTART, &cam->flags)) mcam_sg_restart(cam); spin_unlock_irqrestore(&cam->dev_lock, flags); if (start) @@ -1555,15 +1567,12 @@ static int mcam_v4l_release(struct file *filp) { struct mcam_camera *cam = filp->private_data; - cam_err(cam, "Release, %d frames, %d singles, %d delivered\n", frames, + cam_dbg(cam, "Release, %d frames, %d singles, %d delivered\n", frames, singles, delivered); mutex_lock(&cam->s_mutex); (cam->users)--; - if (filp == cam->owner) { - mcam_ctlr_stop_dma(cam); - cam->owner = NULL; - } if (cam->users == 0) { + mcam_ctlr_stop_dma(cam); mcam_cleanup_vb2(cam); mcam_ctlr_power_down(cam); if (cam->buffer_mode == B_vmalloc && alloc_bufs_at_read) @@ -1688,6 +1697,8 @@ int mccic_irq(struct mcam_camera *cam, unsigned int irqs) if (irqs & (IRQ_EOF0 << frame)) { mcam_frame_complete(cam, frame); handled = 1; + if (cam->buffer_mode == B_DMA_sg) + break; } /* * If a frame starts, note that we have DMA active. This diff --git a/drivers/media/video/marvell-ccic/mcam-core.h b/drivers/media/video/marvell-ccic/mcam-core.h index 917200e63255..bd6acba9fb37 100644 --- a/drivers/media/video/marvell-ccic/mcam-core.h +++ b/drivers/media/video/marvell-ccic/mcam-core.h @@ -107,7 +107,6 @@ struct mcam_camera { enum mcam_state state; unsigned long flags; /* Buffer status, mainly (dev_lock) */ int users; /* How many open FDs */ - struct file *owner; /* Who has data access (v4l2) */ /* * Subsystem structures. diff --git a/drivers/media/video/marvell-ccic/mmp-driver.c b/drivers/media/video/marvell-ccic/mmp-driver.c index 0d64e2d7474a..d23552323f45 100644 --- a/drivers/media/video/marvell-ccic/mmp-driver.c +++ b/drivers/media/video/marvell-ccic/mmp-driver.c @@ -106,6 +106,13 @@ static struct mmp_camera *mmpcam_find_device(struct platform_device *pdev) /* * Power control. */ +static void mmpcam_power_up_ctlr(struct mmp_camera *cam) +{ + iowrite32(0x3f, cam->power_regs + REG_CCIC_DCGCR); + iowrite32(0x3805b, cam->power_regs + REG_CCIC_CRCR); + mdelay(1); +} + static void mmpcam_power_up(struct mcam_camera *mcam) { struct mmp_camera *cam = mcam_to_cam(mcam); @@ -113,9 +120,7 @@ static void mmpcam_power_up(struct mcam_camera *mcam) /* * Turn on power and clocks to the controller. */ - iowrite32(0x3f, cam->power_regs + REG_CCIC_DCGCR); - iowrite32(0x3805b, cam->power_regs + REG_CCIC_CRCR); - mdelay(1); + mmpcam_power_up_ctlr(cam); /* * Provide power to the sensor. */ @@ -335,7 +340,7 @@ static int mmpcam_resume(struct platform_device *pdev) * touch a register even if nothing was active before; trust * me, it's better this way. */ - mmpcam_power_up(&cam->mcam); + mmpcam_power_up_ctlr(cam); return mccic_resume(&cam->mcam); } |