diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-16 00:49:56 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-16 00:49:56 +0400 |
commit | 122804ecb59493fbb4d31b3ba9ac59faaf45276f (patch) | |
tree | cff4d8a158c412e4a8d3abc8d91bb0eb52b01c9a /drivers/media/video/marvell-ccic | |
parent | 16008d641670571ff4cd750b416c7caf2d89f467 (diff) | |
parent | 126400033940afb658123517a2e80eb68259fbd7 (diff) | |
download | linux-122804ecb59493fbb4d31b3ba9ac59faaf45276f.tar.xz |
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (655 commits)
[media] revert patch: HDIC HD29L2 DMB-TH USB2.0 reference design driver
mb86a20s: Add a few more register settings at the init seq
mb86a20s: Group registers into the same line
[media] [PATCH] don't reset the delivery system on DTV_CLEAR
[media] [BUG] it913x-fe fix typo error making SNR levels unstable
[media] cx23885: Query the CX25840 during enum_input for status
[media] cx25840: Add support for g_input_status
[media] rc-videomate-m1f.c Rename to match remote controler name
[media] drivers: media: au0828: Fix dependency for VIDEO_AU0828
[media] convert drivers/media/* to use module_platform_driver()
[media] drivers: video: cx231xx: Fix dependency for VIDEO_CX231XX_DVB
[media] Exynos4 JPEG codec v4l2 driver
[media] doc: v4l: selection: choose pixels as units for selection rectangles
[media] v4l: s5p-tv: mixer: fix setup of VP scaling
[media] v4l: s5p-tv: mixer: add support for selection API
[media] v4l: emulate old crop API using extended crop/compose API
[media] doc: v4l: add documentation for selection API
[media] doc: v4l: add binary images for selection API
[media] v4l: add support for selection api
[media] hd29l2: fix review findings
...
Diffstat (limited to 'drivers/media/video/marvell-ccic')
-rw-r--r-- | drivers/media/video/marvell-ccic/mcam-core.c | 36 | ||||
-rw-r--r-- | drivers/media/video/marvell-ccic/mmp-driver.c | 35 |
2 files changed, 64 insertions, 7 deletions
diff --git a/drivers/media/video/marvell-ccic/mcam-core.c b/drivers/media/video/marvell-ccic/mcam-core.c index 2c8fc0f6d690..37d20e73908a 100644 --- a/drivers/media/video/marvell-ccic/mcam-core.c +++ b/drivers/media/video/marvell-ccic/mcam-core.c @@ -522,6 +522,15 @@ static void mcam_sg_next_buffer(struct mcam_camera *cam) */ static void mcam_ctlr_dma_sg(struct mcam_camera *cam) { + /* + * The list-empty condition can hit us at resume time + * if the buffer list was empty when the system was suspended. + */ + if (list_empty(&cam->buffers)) { + set_bit(CF_SG_RESTART, &cam->flags); + return; + } + 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); @@ -566,6 +575,7 @@ static void mcam_dma_sg_done(struct mcam_camera *cam, int frame) } else { set_bit(CF_SG_RESTART, &cam->flags); singles++; + cam->vb_bufs[0] = NULL; } /* * Now we can give the completed frame back to user space. @@ -661,10 +671,10 @@ static int mcam_ctlr_configure(struct mcam_camera *cam) unsigned long flags; spin_lock_irqsave(&cam->dev_lock, flags); + clear_bit(CF_SG_RESTART, &cam->flags); cam->dma_setup(cam); mcam_ctlr_image(cam); mcam_set_config_needed(cam, 0); - clear_bit(CF_SG_RESTART, &cam->flags); spin_unlock_irqrestore(&cam->dev_lock, flags); return 0; } @@ -873,7 +883,8 @@ static int mcam_read_setup(struct mcam_camera *cam) mcam_reset_buffers(cam); mcam_ctlr_irq_enable(cam); cam->state = S_STREAMING; - mcam_ctlr_start(cam); + if (!test_bit(CF_SG_RESTART, &cam->flags)) + mcam_ctlr_start(cam); spin_unlock_irqrestore(&cam->dev_lock, flags); return 0; } @@ -1818,11 +1829,15 @@ void mccic_shutdown(struct mcam_camera *cam) void mccic_suspend(struct mcam_camera *cam) { - enum mcam_state cstate = cam->state; + mutex_lock(&cam->s_mutex); + if (cam->users > 0) { + enum mcam_state cstate = cam->state; - mcam_ctlr_stop_dma(cam); - mcam_ctlr_power_down(cam); - cam->state = cstate; + mcam_ctlr_stop_dma(cam); + mcam_ctlr_power_down(cam); + cam->state = cstate; + } + mutex_unlock(&cam->s_mutex); } int mccic_resume(struct mcam_camera *cam) @@ -1839,8 +1854,15 @@ int mccic_resume(struct mcam_camera *cam) mutex_unlock(&cam->s_mutex); set_bit(CF_CONFIG_NEEDED, &cam->flags); - if (cam->state == S_STREAMING) + if (cam->state == S_STREAMING) { + /* + * If there was a buffer in the DMA engine at suspend + * time, put it back on the queue or we'll forget about it. + */ + if (cam->buffer_mode == B_DMA_sg && cam->vb_bufs[0]) + list_add(&cam->vb_bufs[0]->queue, &cam->buffers); ret = mcam_read_setup(cam); + } return ret; } #endif /* CONFIG_PM */ diff --git a/drivers/media/video/marvell-ccic/mmp-driver.c b/drivers/media/video/marvell-ccic/mmp-driver.c index fb0b124b35f3..0d64e2d7474a 100644 --- a/drivers/media/video/marvell-ccic/mmp-driver.c +++ b/drivers/media/video/marvell-ccic/mmp-driver.c @@ -26,6 +26,7 @@ #include <linux/io.h> #include <linux/delay.h> #include <linux/list.h> +#include <linux/pm.h> #include "mcam-core.h" @@ -310,10 +311,44 @@ static int mmpcam_platform_remove(struct platform_device *pdev) return mmpcam_remove(cam); } +/* + * Suspend/resume support. + */ +#ifdef CONFIG_PM + +static int mmpcam_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct mmp_camera *cam = mmpcam_find_device(pdev); + + if (state.event != PM_EVENT_SUSPEND) + return 0; + mccic_suspend(&cam->mcam); + return 0; +} + +static int mmpcam_resume(struct platform_device *pdev) +{ + struct mmp_camera *cam = mmpcam_find_device(pdev); + + /* + * Power up unconditionally just in case the core tries to + * touch a register even if nothing was active before; trust + * me, it's better this way. + */ + mmpcam_power_up(&cam->mcam); + return mccic_resume(&cam->mcam); +} + +#endif + static struct platform_driver mmpcam_driver = { .probe = mmpcam_probe, .remove = mmpcam_platform_remove, +#ifdef CONFIG_PM + .suspend = mmpcam_suspend, + .resume = mmpcam_resume, +#endif .driver = { .name = "mmp-camera", .owner = THIS_MODULE |