summaryrefslogtreecommitdiff
path: root/drivers/media/video/marvell-ccic
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-01-15 12:49:56 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2012-01-15 12:49:56 -0800
commit122804ecb59493fbb4d31b3ba9ac59faaf45276f (patch)
treecff4d8a158c412e4a8d3abc8d91bb0eb52b01c9a /drivers/media/video/marvell-ccic
parent16008d641670571ff4cd750b416c7caf2d89f467 (diff)
parent126400033940afb658123517a2e80eb68259fbd7 (diff)
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.c36
-rw-r--r--drivers/media/video/marvell-ccic/mmp-driver.c35
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