diff options
author | Robert Jarzmik <robert.jarzmik@free.fr> | 2008-08-02 06:10:04 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-08-06 05:57:33 -0400 |
commit | 3f6ac497b036533d1a63ba04fdbe710c55e14cda (patch) | |
tree | e00c267fb51557e97a84520297cded262d1d6898 /drivers/media/video/pxa_camera.c | |
parent | 2e521061db61a35dd64ea85a1642f9a9dfde2872 (diff) |
V4L/DVB (8611): Add suspend/resume to pxa_camera driver
PXA suspend switches off DMA core, which loses all context
of previously assigned descriptors. As pxa_camera driver
relies on DMA transfers, setup the lost descriptors on
resume and retrigger frame acquisition if needed.
Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/pxa_camera.c')
-rw-r--r-- | drivers/media/video/pxa_camera.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index 28d8fd0679b4..ead87ddaf7fb 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c | |||
@@ -128,6 +128,8 @@ struct pxa_camera_dev { | |||
128 | 128 | ||
129 | struct pxa_buffer *active; | 129 | struct pxa_buffer *active; |
130 | struct pxa_dma_desc *sg_tail[3]; | 130 | struct pxa_dma_desc *sg_tail[3]; |
131 | |||
132 | u32 save_cicr[5]; | ||
131 | }; | 133 | }; |
132 | 134 | ||
133 | static const char *pxa_cam_driver_description = "PXA_Camera"; | 135 | static const char *pxa_cam_driver_description = "PXA_Camera"; |
@@ -997,10 +999,64 @@ static int pxa_camera_querycap(struct soc_camera_host *ici, | |||
997 | return 0; | 999 | return 0; |
998 | } | 1000 | } |
999 | 1001 | ||
1002 | static int pxa_camera_suspend(struct soc_camera_device *icd, pm_message_t state) | ||
1003 | { | ||
1004 | struct soc_camera_host *ici = | ||
1005 | to_soc_camera_host(icd->dev.parent); | ||
1006 | struct pxa_camera_dev *pcdev = ici->priv; | ||
1007 | int i = 0, ret = 0; | ||
1008 | |||
1009 | pcdev->save_cicr[i++] = CICR0; | ||
1010 | pcdev->save_cicr[i++] = CICR1; | ||
1011 | pcdev->save_cicr[i++] = CICR2; | ||
1012 | pcdev->save_cicr[i++] = CICR3; | ||
1013 | pcdev->save_cicr[i++] = CICR4; | ||
1014 | |||
1015 | if ((pcdev->icd) && (pcdev->icd->ops->suspend)) | ||
1016 | ret = pcdev->icd->ops->suspend(pcdev->icd, state); | ||
1017 | |||
1018 | return ret; | ||
1019 | } | ||
1020 | |||
1021 | static int pxa_camera_resume(struct soc_camera_device *icd) | ||
1022 | { | ||
1023 | struct soc_camera_host *ici = | ||
1024 | to_soc_camera_host(icd->dev.parent); | ||
1025 | struct pxa_camera_dev *pcdev = ici->priv; | ||
1026 | int i = 0, ret = 0; | ||
1027 | |||
1028 | DRCMR68 = pcdev->dma_chans[0] | DRCMR_MAPVLD; | ||
1029 | DRCMR69 = pcdev->dma_chans[1] | DRCMR_MAPVLD; | ||
1030 | DRCMR70 = pcdev->dma_chans[2] | DRCMR_MAPVLD; | ||
1031 | |||
1032 | CICR0 = pcdev->save_cicr[i++] & ~CICR0_ENB; | ||
1033 | CICR1 = pcdev->save_cicr[i++]; | ||
1034 | CICR2 = pcdev->save_cicr[i++]; | ||
1035 | CICR3 = pcdev->save_cicr[i++]; | ||
1036 | CICR4 = pcdev->save_cicr[i++]; | ||
1037 | |||
1038 | if ((pcdev->icd) && (pcdev->icd->ops->resume)) | ||
1039 | ret = pcdev->icd->ops->resume(pcdev->icd); | ||
1040 | |||
1041 | /* Restart frame capture if active buffer exists */ | ||
1042 | if (!ret && pcdev->active) { | ||
1043 | /* Reset the FIFOs */ | ||
1044 | CIFR |= CIFR_RESET_F; | ||
1045 | /* Enable End-Of-Frame Interrupt */ | ||
1046 | CICR0 &= ~CICR0_EOFM; | ||
1047 | /* Restart the Capture Interface */ | ||
1048 | CICR0 |= CICR0_ENB; | ||
1049 | } | ||
1050 | |||
1051 | return ret; | ||
1052 | } | ||
1053 | |||
1000 | static struct soc_camera_host_ops pxa_soc_camera_host_ops = { | 1054 | static struct soc_camera_host_ops pxa_soc_camera_host_ops = { |
1001 | .owner = THIS_MODULE, | 1055 | .owner = THIS_MODULE, |
1002 | .add = pxa_camera_add_device, | 1056 | .add = pxa_camera_add_device, |
1003 | .remove = pxa_camera_remove_device, | 1057 | .remove = pxa_camera_remove_device, |
1058 | .suspend = pxa_camera_suspend, | ||
1059 | .resume = pxa_camera_resume, | ||
1004 | .set_fmt_cap = pxa_camera_set_fmt_cap, | 1060 | .set_fmt_cap = pxa_camera_set_fmt_cap, |
1005 | .try_fmt_cap = pxa_camera_try_fmt_cap, | 1061 | .try_fmt_cap = pxa_camera_try_fmt_cap, |
1006 | .init_videobuf = pxa_camera_init_videobuf, | 1062 | .init_videobuf = pxa_camera_init_videobuf, |